2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/statfs.h>
24 #include <sys/types.h>
27 #include <sys/syscall.h> /*__NR_gettid*/
31 #include "mf-fo-internal.h"
32 #include "mf-fo-common.h"
33 #include "mf-fo-debug.h"
35 GSList *dir_list = NULL;
37 #define SAFE_FREE(x) do { \
50 #define FILENAME_MAX 4096
53 static inline long __mf_fo_get_name_max(void)
58 max = pathconf("/", _PC_NAME_MAX);
68 static inline long __mf_fo_get_path_max(void)
73 max = pathconf("/", _PC_PATH_MAX);
83 static const char *__mf_fo_get_base_name(const char *path)
85 const char *base = NULL;
88 if (path && (path[0] != '\0')) {
90 tmp = strrchr(path, '/');
93 mf_fo_loge("path is ROOT - %s", path);
95 mf_fo_loge("invaild arg - %s", path);
104 static int __get_directory_hierarchies( const char *pathname, const struct stat *statptr, int type)
106 mf_fo_dir_list_info *info = NULL;
107 mf_debug("pathname is [%s]\t type is [%d]\t size is [%ld]",
108 pathname, type, statptr->st_size);
113 info = calloc(sizeof(mf_fo_dir_list_info), 1);
114 info->ftw_path = g_strdup(pathname);
115 info->size = statptr->st_size;
117 dir_list = g_slist_append(dir_list, info);
118 mf_debug("File pathname is [%s]", pathname);
121 info = calloc(sizeof(mf_fo_dir_list_info), 1);
122 info->ftw_path = g_strdup(pathname);
123 info->size = statptr->st_size;
125 dir_list = g_slist_append(dir_list, info);
126 mf_debug("Directory pathname is [%s]", pathname);
130 mf_debug("Default pathname is [%s]", pathname);
136 static int __mf_fo_get_total_dir_size(const char *dir, unsigned long long *size)
142 ret = ftw(dir, __get_directory_hierarchies, 16);
145 mf_fo_dir_list_info *ent = NULL;
149 ent = (mf_fo_dir_list_info *)list->data;
150 if (ent->type == FTW_D) {
151 *size += MF_VISUAL_FOLDER_SIZE;
152 } else if (ent->type == FTW_F) {
155 list = g_slist_next(list);
158 _mf_fo_free_directory_hierarchies(&dir_list);
161 _mf_fo_free_directory_hierarchies(&dir_list);
168 static char *_get_unique_dirname(const char *name)
170 char *new_name = NULL;
173 char *num_area = NULL;
174 gboolean has_num = FALSE;
177 if ((num_area = strrchr(name, NEW_NAME_SEPARATOR)) != NULL) {
180 for (i = (num_area - name); name[i] != '\0'; i++) {
181 if (!isdigit(name[i])) {
187 max = __mf_fo_get_path_max();
188 new_name = malloc(sizeof(char) * max);
191 int prefix_len = (int)(num_area - name - 1);
193 next_num = atoi(num_area) + 1;
194 write_len = snprintf(new_name, max, "%.*s_%d", (int)(num_area - name - 1), name, next_num);
195 if (write_len > max) {
196 snprintf(new_name, max, "%.*s_%d", (int)(num_area - name - 1), name, next_num);
198 while (_mf_fo_check_exist(new_name)) {
200 snprintf(new_name, max, "%.*s_%d", (int)(num_area - name - 1), name, next_num);
203 snprintf(new_name, max, "%s_%d", name, next_num);
204 while (_mf_fo_check_exist(new_name)) {
206 snprintf(new_name, max, "%s_%d", name, next_num);
213 char *_mf_fo_get_next_unique_dirname(const char *name, int *errcode)
215 char *new_name = NULL;
216 char *tmp_name = NULL;
225 name_len = strlen(name);
231 p_max = __mf_fo_get_path_max();
233 if (name[name_len - 1] == '/') {
234 tmp_name = strndup(name, name_len - 1);
241 new_name = malloc(sizeof(char) * p_max);
247 n_max = __mf_fo_get_name_max();
252 write_len = snprintf(new_name, p_max, "%s_%d", tmp_name ? tmp_name : name, next_num);
253 if (write_len > p_max) {
254 mf_fo_loge("write_len[%u] is greater than max[%ld]", write_len, p_max);
255 *errcode = ENAMETOOLONG;
256 goto ERROR_FREE_RETURN;
258 const char *b_name = 0;
259 b_name = __mf_fo_get_base_name(new_name);
260 if (b_name && (mf_util_character_count_get(b_name) > n_max)) {
261 mf_fo_loge("b_name length[%u] is greater than name max[%ld]", strlen(b_name), n_max);
262 *errcode = ENAMETOOLONG;
263 goto ERROR_FREE_RETURN;
266 } while (_mf_fo_check_exist(new_name));
282 char *_mf_fo_get_next_unique_filename(const char *name, int *errcode)
284 char *new_name = NULL;
287 const char *base = NULL;
294 name_len = strlen(name);
300 base = __mf_fo_get_base_name(name);
306 p_max = __mf_fo_get_path_max();
308 new_name = malloc(sizeof(char) * p_max);
315 const char *ext = NULL;
317 n_max = __mf_fo_get_name_max();
318 dir_len = (int)(base - name);
320 if ((ext = strrchr(name, '.')) != NULL) {
321 base_len = (int)(ext - base);
323 base_len = strlen(base);
330 write_len = snprintf(new_name, p_max, "%.*s%.*s_%d%s", dir_len, name, base_len, base, next_num, ext);
332 write_len = snprintf(new_name, p_max, "%.*s%.*s_%d", dir_len, name, base_len, base, next_num);
335 if (write_len > p_max) {
336 mf_fo_loge("write_len[%u] is greater than max[%ld]", write_len, p_max);
337 *errcode = ENAMETOOLONG;
338 goto ERROR_FREE_RETURN;
340 const char *b_name = NULL;
341 b_name = __mf_fo_get_base_name(new_name);
342 if (b_name && (strlen(b_name) > n_max)) {
343 mf_fo_loge("b_name length[%u] is greater than name max[%ld]", strlen(b_name), n_max);
344 *errcode = ENAMETOOLONG;
345 goto ERROR_FREE_RETURN;
348 } while (_mf_fo_check_exist(new_name));
361 int _mf_fo_get_total_item_size(const char *item, unsigned long long *size)
364 if (!item || !size) {
367 if (stat(item, &info)) {
368 mf_fo_loge("Fail to stat item : %s", item);
372 if (S_ISREG(info.st_mode)) {
373 *size = (unsigned long long)info.st_size;
374 } else if (S_ISDIR(info.st_mode)) {
375 int ret = __mf_fo_get_total_dir_size(item, size);
377 mf_fo_loge("Fail to get size of directory(%s)", item);
382 mf_fo_loge("item(%s) is not file or directory", item);
383 *size = (unsigned long long)info.st_size;
389 int _mf_fo_get_remain_space(const char *path, unsigned long long *size)
392 struct statfs dst_fs;
394 if (!path || !size) {
399 if (statfs(path, &dst_fs) == 0) {
400 *size = ((unsigned long long)(dst_fs.f_bsize) * (unsigned long long)(dst_fs.f_bavail));
410 inline bool _mf_fo_check_exist(const char *path)
412 if (path && (access(path, F_OK) == 0)) {
418 int _mf_fo_errno_to_mferr(int err_no)
420 int err = MF_FO_ERR_SET(MF_FO_ERR_UNKNOWN);
424 err = MF_FO_ERR_SET(MF_FO_ERR_ARGUMENT);
427 #ifdef EACCES /*The requested access to the file is not allowed*/
428 case EACCES: /*report*/
429 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_PERMISSION);
432 #ifdef EFAULT /* pathname points outside your accessible address space*/
434 err = MF_FO_ERR_SET(MF_FO_ERR_FAULT);
437 #ifdef EISDIR /*pathname refers to a directory and the access requested involved writing*/
438 case EISDIR: /*report*/
439 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_TYPE);
442 #ifdef EMFILE /*The process already has the maximum number of files open.*/
444 err = MF_FO_ERR_SET(MF_FO_ERR_MAX_OPEN);
447 #ifdef ENOSPC /*pathname was to be created but the device containing pathname has no room for the new file*/
448 case ENOSPC: /*report*/
449 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_SPACE);
452 #ifdef ENOTDIR /* A component used as a directory in pathname is not*/
453 case ENOTDIR: /*report*/
454 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_TYPE);
457 #ifdef EROFS /*pathname refers to a file on a read-only filesystem and write access was requested*/
458 case EROFS: /*report*/
459 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_RO);
462 #ifdef ELOOP /* Too many symbolic links were encountered in resolving pathname */
464 err = MF_FO_ERR_SET(MF_FO_ERR_LOOP);
467 #ifdef ENOMEM /* Insufficient kernel memory was available */
468 case ENOMEM: /*report*/
469 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_MEM);
472 #ifdef ENOENT /* O_CREAT is not set and the named file does not exist*/
473 case ENOENT: /*report*/
474 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_NOT_EXIST);
477 #ifdef ENAMETOOLONG /*pathname was too long.*/
478 case ENAMETOOLONG: /*report*/
479 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_LONG_NAME);
482 #ifdef EFBIG /* An attempt was made to write a file that exceeds the implementation-defined maximum
483 file size or the process file size limit*/
484 case EFBIG: /*report*/
485 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_BIG_SIZE);
488 #ifdef EIO /* I/O error */
490 err = MF_FO_ERR_SET(MF_FO_ERR_REPORT_CLASS | MF_FO_ERR_IO);
500 void _mf_fo_free_directory_hierarchies(GSList **glist)
504 GSList *list = *glist;
506 mf_fo_dir_list_info *info = NULL;
507 info = (mf_fo_dir_list_info *)list->data;
508 g_free(info->ftw_path);
510 list = g_slist_next(list);
512 g_slist_free(*glist);