File Manager / src / model /
fs-manager.c
- /*
- * Copyright 2014 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- #include "model/fs-manager.h"
- #include "model/fs-operation.h"
- #include "utils/config.h"
- #include "utils/model-utils.h"
- #include "utils/logger.h"
- #include <storage.h>
- #include <stdbool.h>
- enum {
- FM_CHECK_ARG_VALID = 0x0001,
- FM_CHECK_EXIST = 0x0002,
- FM_CHECK_PATH_VALID = 0x0004,
- FM_CHECK_PARENT_DIR_EXIST = 0x0008,
- FM_CHECK_DUPLICATED = 0x0010
- };
- #define FM_COMP_RES_D1_LESS_D2 -1
- #define FM_COMP_RES_D1_GREATER_D2 1
- #define FM_COMP_RES_D1_EQUAL_D2 0
- struct _fs_manager {
- Eina_Bool is_locked;
- fs_operation *operation;
- fs_manager_complete_cb_func user_cb_func;
- void *user_cb_data;
- };
- static void _fs_manager_clear_data(fs_manager *manager);
- static Eina_Bool _fs_manager_check_path_valid(const char *path, int *ret);
- static Eina_Bool _fs_manager_check_parent_exists(const char *path, int *ret);
- static int _fs_manager_check_error(const char *fullpath, int check_option);
- static int _fs_manager_sort_by_name_cb(const void *d1, const void *d2);
- static int _fs_manager_is_mmc_supported(bool *supported);
- static int _fs_manager_generate_operation(fs_manager *manager,
- Eina_List *source_list,
- const char *dest_path,
- operation_type oper_type,
- fs_manager_complete_cb_func func,
- void *data);
- static void _on_operation_completed(void *data);
- fs_manager *fs_manager_create()
- {
- fs_manager *manager = calloc(1, sizeof(fs_manager));
- if (manager) {
- manager->is_locked = EINA_FALSE;
- }
- return manager;
- }
- void fs_manager_destroy(fs_manager *manager)
- {
- if (manager) {
- _fs_manager_clear_data(manager);
- free(manager);
- }
- }
- int fs_manager_get_storage_list(fs_manager *manager, Eina_List **storage_list)
- {
- RETVM_IF(!manager, RESULT_TYPE_INVALID_ARG, "File manager is NULL");
- char *buf = model_utils_get_phone_path();
- if (!buf) {
- dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] buf == NULL", __FILE__, __LINE__);
- return RESULT_TYPE_INVALID_PATH;
- }
- if (manager->is_locked) {
- ERR("File manager is busy");
- free(buf);
- return RESULT_TYPE_BUSY;
- }
- bool is_supported = false;
- int res = _fs_manager_is_mmc_supported(&is_supported);
- if (res != RESULT_TYPE_OK) {
- free(buf);
- return res;
- }
- if (is_supported) {
- storage_info *const pNode_internal = calloc(1, sizeof(node_info));
- pNode_internal->root_name = strdup(FM_MEMORY_LABEL);
- pNode_internal->root_path = strdup(FM_MEMORY_FOLDER);
- pNode_internal->type = STORAGE_TYPE_MMC;
- *storage_list = eina_list_append(*storage_list, pNode_internal);
- }
- storage_info *const pNode_device = calloc(1, sizeof(node_info));
- pNode_device->root_name = strdup(FM_PHONE_LABEL);
- pNode_device->root_path = strdup(buf);
- pNode_device->type = STORAGE_TYPE_PHONE;
- *storage_list = eina_list_append(*storage_list, pNode_device);
- *storage_list = eina_list_sort(*storage_list, eina_list_count(*storage_list), _fs_manager_sort_by_name_cb);
- free(buf);
- return RESULT_TYPE_OK;
- }
- int fs_manager_get_file_list(fs_manager *manager, const char *dir_path, Eina_List **file_list)
- {
- RETVM_IF(!manager, RESULT_TYPE_INVALID_ARG, "File manager is NULL");
- RETVM_IF(!dir_path, RESULT_TYPE_INVALID_ARG, "Path is NULL");
- RETVM_IF(!file_list, RESULT_TYPE_INVALID_ARG, "File list is NULL");
- if (manager->is_locked) {
- ERR("File manager is busy");
- return RESULT_TYPE_BUSY;
- }
- int option = FM_CHECK_EXIST;
- int ret = _fs_manager_check_error(dir_path, option);
- if (ret != RESULT_TYPE_OK) {
- return ret;
- }
- Eina_List *dirs = NULL;
- Eina_List *files = NULL;
- ret = model_utils_read_dir(dir_path, &dirs, &files);
- if (ret != RESULT_TYPE_OK) {
- ERR("Failed to read dir '%s'", dir_path);
- return ret;
- }
- dirs = eina_list_sort(dirs, eina_list_count(dirs), _fs_manager_sort_by_name_cb);
- files = eina_list_sort(files, eina_list_count(files), _fs_manager_sort_by_name_cb);
- *file_list = eina_list_merge(dirs, files);
- return RESULT_TYPE_OK;
- }
- int fs_manager_copy_files(fs_manager *manager,
- Eina_List *source_list,
- const char *dest_path,
- fs_manager_complete_cb_func cb_func,
- void *cb_data)
- {
- return _fs_manager_generate_operation(manager,
- source_list,
- dest_path,
- OPERATION_TYPE_COPY,
- cb_func,
- cb_data);
- }
- int fs_manager_move_files(fs_manager *manager,
- Eina_List *source_list,
- const char *dest_path,
- fs_manager_complete_cb_func cb_func,
- void *cb_data)
- {
- return _fs_manager_generate_operation(manager,
- source_list,
- dest_path,
- OPERATION_TYPE_MOVE,
- cb_func,
- cb_data);
- }
- int fs_manager_delete_files(fs_manager *manager,
- Eina_List *source_list,
- fs_manager_complete_cb_func cb_func,
- void *cb_data)
- {
- return _fs_manager_generate_operation(manager,
- source_list,
- NULL,
- OPERATION_TYPE_DELETE,
- cb_func,
- cb_data);
- }
- int fs_manager_create_folder(fs_manager *manager, const char *dir)
- {
- RETVM_IF(!manager, RESULT_TYPE_INVALID_ARG, "File manager is NULL");
- RETVM_IF(!dir, RESULT_TYPE_INVALID_ARG, "Directory path is NULL");
- if (manager->is_locked) {
- ERR("File manager is busy");
- return RESULT_TYPE_BUSY;
- }
- int option = FM_CHECK_DUPLICATED | FM_CHECK_PATH_VALID;
- int ret = _fs_manager_check_error(dir, option);
- if (ret != RESULT_TYPE_OK) {
- return ret;
- }
- if (mkdir(dir, DIR_MODE) < 0) {
- ERR("Failed to create folder '%s'", dir);
- return RESULT_TYPE_FAIL;
- }
- return RESULT_TYPE_OK;
- }
- static Eina_Bool _fs_manager_check_path_valid(const char *path, int *ret)
- {
- *ret = model_utils_is_path_valid(path, model_utils_is_file_exists(path));
- return (*ret == RESULT_TYPE_OK);
- }
- static Eina_Bool _fs_manager_check_parent_exists(const char *path, int *ret)
- {
- *ret = RESULT_TYPE_FAIL;
- char *const parent_path = model_utils_get_dir_name(path);
- if (parent_path) {
- *ret = model_utils_is_file_exists(parent_path) ?
- RESULT_TYPE_OK :
- RESULT_TYPE_DIR_NOT_FOUND;
- free(parent_path);
- } else {
- *ret = RESULT_TYPE_FAIL_ALLOCATE_MEMORY;
- }
- return (*ret == RESULT_TYPE_OK);
- }
- static int _fs_manager_sort_by_name_cb(const void *d1, const void *d2)
- {
- node_info *txt1 = (node_info *)d1;
- node_info *txt2 = (node_info *)d2;
- char *name1 = NULL;
- char *name2 = NULL;
- int comp_res = FM_COMP_RES_D1_EQUAL_D2;
- if (!txt1 || !txt1->name) {
- return FM_COMP_RES_D1_GREATER_D2;
- }
- if (!txt2 || !txt2->name) {
- return FM_COMP_RES_D1_LESS_D2;
- }
- name1 = strdup(txt1->name);
- if (!name1) {
- return FM_COMP_RES_D1_LESS_D2;
- }
- eina_str_tolower(&name1);
- name2 = strdup(txt2->name);
- if (!name2) {
- free(name1);
- name1 = NULL;
- return FM_COMP_RES_D1_LESS_D2;
- }
- eina_str_tolower(&name2);
- comp_res = strcmp(name1, name2);
- free(name1);
- free(name2);
- return comp_res;
- }
- static int _fs_manager_check_error(const char *fullpath, int check_option)
- {
- int ret = RESULT_TYPE_OK;
- int ret2 = RESULT_TYPE_OK;
- if ((check_option & FM_CHECK_ARG_VALID) && !fullpath) {
- ERR("Input argument is NULL");
- ret = RESULT_TYPE_INVALID_ARG;
- } else if ((check_option & FM_CHECK_EXIST) && (!model_utils_is_file_exists(fullpath))) {
- ERR("'%s' doesn't exist", fullpath);
- ret = RESULT_TYPE_NOT_EXIST;
- } else if ((check_option & FM_CHECK_PATH_VALID) && (!_fs_manager_check_path_valid(fullpath, &ret2))) {
- ERR("Path '%s' is invalid", fullpath);
- ret = ret2;
- } else if ((check_option & FM_CHECK_PARENT_DIR_EXIST) && (!_fs_manager_check_parent_exists(fullpath, &ret2))) {
- ERR("Parent directory for '%s' doesn't exist", fullpath);
- ret = ret2;
- } else if ((check_option & FM_CHECK_DUPLICATED) && (model_utils_is_file_exists(fullpath))) {
- ERR("Duplicated name. '%s' already exists", fullpath);
- ret = RESULT_TYPE_DUPLICATED_NAME;
- }
- return ret;
- }
- static int _fs_manager_is_mmc_supported(bool *supported)
- {
- RETVM_IF(!supported, RESULT_TYPE_INVALID_ARG, "Input argument is NULL");
- *supported = false;
- struct statvfs st;
- RETVM_IF(storage_get_external_memory_size(&st) < 0,
- RESULT_TYPE_FAIL,
- "Failed to get external memory size");
- double total_size = (double)st.f_frsize * st.f_blocks;
- if (total_size > 0) {
- *supported = true;
- }
- return RESULT_TYPE_OK;
- }
- static int _fs_manager_generate_operation(fs_manager *manager,
- Eina_List *source_list,
- const char *dest_path,
- operation_type oper_type,
- fs_manager_complete_cb_func func,
- void *data)
- {
- RETVM_IF(!manager, RESULT_TYPE_INVALID_ARG, "File manager is NULL");
- RETVM_IF(!source_list, RESULT_TYPE_INVALID_ARG, "Source list is NULL");
- RETVM_IF(oper_type == OPERATION_TYPE_NONE, RESULT_TYPE_INVALID_ARG, "No appropriate operation type");
- RETVM_IF(!dest_path && (oper_type != OPERATION_TYPE_DELETE), RESULT_TYPE_INVALID_ARG, "Destination path is NULL");
- if (manager->is_locked) {
- ERR("File manager is busy");
- return RESULT_TYPE_BUSY;
- }
- manager->user_cb_func = func;
- manager->user_cb_data = data;
- manager->operation = fs_operation_create();
- if (!manager->operation) {
- _fs_manager_clear_data(manager);
- ERR("Failed to allocate memory for file operation");
- return RESULT_TYPE_FAIL_ALLOCATE_MEMORY;
- }
- int result = fs_operation_set_data(manager->operation, source_list, dest_path, oper_type);
- if (result != RESULT_TYPE_OK) {
- _fs_manager_clear_data(manager);
- ERR("Failed to set operation data");
- return result;
- }
- fs_operation_cb_data *cb_data = calloc(1, sizeof(fs_operation_cb_data));
- if (!cb_data) {
- _fs_manager_clear_data(manager);
- ERR("Failed to allocate memory for callback operation data");
- return RESULT_TYPE_FAIL_ALLOCATE_MEMORY;
- }
- cb_data->manager = manager;
- cb_data->result = RESULT_TYPE_FAIL;
- /* Lock file system manager */
- manager->is_locked = EINA_TRUE;
- result = fs_operation_execute(manager->operation, _on_operation_completed, cb_data);
- if (result != RESULT_TYPE_OK) {
- free(cb_data);
- _fs_manager_clear_data(manager);
- manager->is_locked = EINA_FALSE;
- ERR("Failed to execute operation");
- }
- return result;
- }
- static void _on_operation_completed(void *data)
- {
- RETM_IF(!data, "Callback data is NULL");
- fs_operation_cb_data *operation_data = data;
- fs_manager *manager = operation_data->manager;
- RETM_IF(!manager, "File manager in callback data is NULL");
- fs_operation_destroy(manager->operation);
- manager->operation = NULL;
- /* Unlock file system manager */
- manager->is_locked = EINA_FALSE;
- /* User callback calling */
- if (manager->user_cb_func) {
- manager->user_cb_func(manager->user_cb_data, operation_data->result);
- manager->user_cb_func = NULL;
- manager->user_cb_data = NULL;
- }
- free(operation_data);
- }
- static void _fs_manager_clear_data(fs_manager *manager)
- {
- manager->user_cb_func = NULL;
- manager->user_cb_data = NULL;
- fs_operation_destroy(manager->operation);
- manager->operation = NULL;
- }