Apply line coverage comments
[platform/core/system/libstorage.git] / src / storage.c
index 480ef05..69dd87f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <vconf.h>
 
 #include "common.h"
 #include "list.h"
 #include "log.h"
+#include "storage-external.h"
 
 const char *dir_path[STORAGE_DIRECTORY_MAX] = {
        [STORAGE_DIRECTORY_IMAGES] = "Images",
        [STORAGE_DIRECTORY_SOUNDS] = "Sounds",
        [STORAGE_DIRECTORY_VIDEOS] = "Videos",
-       [STORAGE_DIRECTORY_CAMERA] = "DCIM",
+       [STORAGE_DIRECTORY_CAMERA] = "Camera",
        [STORAGE_DIRECTORY_DOWNLOADS] = "Downloads",
        [STORAGE_DIRECTORY_MUSIC] = "Music",
        [STORAGE_DIRECTORY_DOCUMENTS] = "Documents",
        [STORAGE_DIRECTORY_OTHERS] = "Others",
-       [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "/opt/usr/share/settings/Ringtones",
+       [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "",
 };
 
-static dd_list *st_head;
+static dd_list *st_int_head; /* Internal storage list */
+
+static dd_list *compat_cb_list;
+struct compat_cb_info {
+       storage_state_changed_cb user_cb;
+       void *user_data;
+};
 
 void add_device(const struct storage_ops *st)
 {
-       DD_LIST_APPEND(st_head, st);
+       DD_LIST_APPEND(st_int_head, st);
 }
 
 void remove_device(const struct storage_ops *st)
 {
-       DD_LIST_REMOVE(st_head, st);
+       DD_LIST_REMOVE(st_int_head, st);
 }
 
 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
 {
        const struct storage_ops *st;
        dd_list *elem;
-       int storage_id = 0, ret;
+       int ret;
 
        if (!callback) {
                _E("Invalid parameter");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       DD_LIST_FOREACH(st_head, elem, st) {
-               ret = callback(storage_id, st->type, st->get_state(),
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               ret = callback(st->storage_id, st->type, st->get_state(),
                                st->root(), user_data);
                /* if the return value is false, will be stop to iterate */
                if (!ret)
                        break;
-               storage_id++;
+       }
+
+       ret = storage_ext_foreach_device_list(callback, user_data);
+       if (ret < 0) {
+               _E("Failed to iterate external devices (%d)", ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_OPERATION_FAILED;
        }
 
        return STORAGE_ERROR_NONE;
@@ -74,21 +87,42 @@ API int storage_foreach_device_supported(storage_device_supported_cb callback, v
 API int storage_get_root_directory(int storage_id, char **path)
 {
        const struct storage_ops *st;
+       dd_list *elem;
+       char root[PATH_MAX];
+       int ret;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!path) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               if (st->storage_id != storage_id)
+                       continue;
+               *path = strdup(st->root());
+               if (!*path) {
+//LCOV_EXCL_START System Error
+                       _E("Failed to copy the root string : %d", errno);
+                       return STORAGE_ERROR_OUT_OF_MEMORY;
+//LCOV_EXCL_STOP
+               }
+               return STORAGE_ERROR_NONE;
+       }
+
+       /* external storage */
+       ret = storage_ext_get_root(storage_id, root, sizeof(root));
+       if (ret < 0) {
+               _E("Failed to get root path of external storage(%d, %d", storage_id, ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       *path = strdup(st->root());
+       *path = strdup(root);
        if (!*path) {
-               _E("Failed to copy the root string : %s", strerror(errno));
+               _E("Failed to copy the root string : %d", errno); //LCOV_EXCL_LINE System Error
                return STORAGE_ERROR_OUT_OF_MEMORY;
        }
 
@@ -98,8 +132,15 @@ API int storage_get_root_directory(int storage_id, char **path)
 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
 {
        const struct storage_ops *st;
-       const char *root;
+       char root[PATH_MAX];
        char temp[PATH_MAX];
+       char *temp2, *end;
+       int ret;
+       dd_list *elem;
+       bool found;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!path) {
                _E("Invalid parameger");
@@ -111,27 +152,50 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       found = false;
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               if (st->storage_id != storage_id)
+                       continue;
+               found = true;
+               break;
        }
 
-       if (st->type != STORAGE_TYPE_INTERNAL
-           && type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
-               _E("Not support directory : id(%d) type(%d)", storage_id, type);
+       if (found && st) {
+               snprintf(root, sizeof(root), "%s", st->root());
+               if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
+                       temp2 = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR);
+                       if (temp2 == NULL)
+                               return STORAGE_ERROR_OPERATION_FAILED;
+                       end = strrchr(temp2, '/');
+                       if (end)
+                               *end = '\0';
+                       snprintf(temp, PATH_MAX, "%s", temp2);
+                       free(temp2);
+               } else
+                       snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
+
+               goto out;
+       }
+
+       /* external storage */
+       if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
+               _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
                return STORAGE_ERROR_NOT_SUPPORTED;
        }
 
-       root = st->root();
-       if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES)
-               snprintf(temp, PATH_MAX, "%s", dir_path[type]);
-       else
-               snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
+       ret = storage_ext_get_root(storage_id, root, sizeof(root));
+       if (ret < 0) {
+               _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_OPERATION_FAILED;
+       }
 
+       snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
+
+out:
        *path = strdup(temp);
        if (!*path) {
-               _E("Failed to copy the directory(%d) string : %s", type, strerror(errno));
+               _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
                return STORAGE_ERROR_OUT_OF_MEMORY;
        }
 
@@ -141,71 +205,130 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p
 API int storage_get_type(int storage_id, storage_type_e *type)
 {
        const struct storage_ops *st;
+       dd_list *elem;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!type) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               if (st->storage_id != storage_id)
+                       continue;
+               *type = st->type;
+               return STORAGE_ERROR_NONE;
        }
 
-       *type = st->type;
+       /* external storage */
+       *type = STORAGE_TYPE_EXTERNAL;
 
        return STORAGE_ERROR_NONE;
 }
 
 API int storage_get_state(int storage_id, storage_state_e *state)
 {
-       const struct storage_ops *st;
+       const struct storage_ops *ops;
+       storage_state_e st;
+       dd_list *elem;
+       int ret;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!state) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       DD_LIST_FOREACH(st_int_head, elem, ops) {
+               if (ops->storage_id != storage_id)
+                       continue;
+               *state = ops->get_state();
+               return STORAGE_ERROR_NONE;
        }
 
-       *state = st->get_state();
+       /* external storage */
+       ret = storage_ext_get_state(storage_id, &st);
+       if (ret < 0) {
+               _E("Failed to get state (storage id(%d), ret(%d))", storage_id, ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_OPERATION_FAILED;
+       }
 
+       *state = st;
        return STORAGE_ERROR_NONE;
 }
 
+//LCOV_EXCL_START Not called Callback
+static void compat_cb(int storage_id,
+               storage_dev_e dev, storage_state_e state,
+               const char *fstype, const char *fsuuid, const char *mountpath,
+               bool primary, int flags, void *user_data)
+{
+       struct compat_cb_info* ccb_info;
+       dd_list *elem;
+
+       if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
+               DD_LIST_FOREACH(compat_cb_list, elem, ccb_info)
+                       ccb_info->user_cb(storage_id, state, ccb_info->user_data);
+}
+//LCOV_EXCL_STOP
+
 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
 {
        const struct storage_ops *st;
        struct storage_cb_info info;
        int ret;
+       dd_list *elem;
+
+       struct compat_cb_info* ccb_info;
+       static int compat_cb_init = 0;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!callback) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
-       }
+       /* For backward compatability */
+       if (storage_id == STORAGE_TYPE_EXTERNAL) {
+               if (!compat_cb_init) {
+                       ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
+                       if (ret == STORAGE_ERROR_NONE)
+                               compat_cb_init = 1;
+                       else
+                               return ret;
+               }
+
+               ccb_info = malloc(sizeof(struct compat_cb_info));
+               if (ccb_info == NULL)
+                       return STORAGE_ERROR_OPERATION_FAILED;
+               ccb_info->user_cb = callback;
+               ccb_info->user_data = user_data;
+               DD_LIST_APPEND(compat_cb_list, ccb_info);
 
-       /* do not register changed callback in case of internal memory */
-       if (st->type == STORAGE_TYPE_INTERNAL)
                return STORAGE_ERROR_NONE;
+       }
+
+       /* Internal storage does not support registering changed callback */
+       DD_LIST_FOREACH(st_int_head, elem, st)
+               if (st->storage_id == storage_id)
+                       return STORAGE_ERROR_NONE;
 
+       /* external storage */
        info.id = storage_id;
        info.state_cb = callback;
        info.user_data = user_data;
 
-       ret = st->register_cb(STORAGE_CALLBACK_STATE, &info);
+       ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
        if (ret < 0) {
-               _E("Failed to register callback : id(%d)", storage_id);
+               _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
                return STORAGE_ERROR_OPERATION_FAILED;
        }
 
@@ -217,28 +340,43 @@ API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb
        const struct storage_ops *st;
        struct storage_cb_info info;
        int ret;
+       dd_list *elem;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!callback) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* For backward compatability */
+       if (storage_id == STORAGE_TYPE_EXTERNAL) {
+               dd_list *elem_n;
+               struct compat_cb_info* ccb_info;
+
+               DD_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
+                       if (ccb_info->user_cb == callback) {
+                               DD_LIST_REMOVE(compat_cb_list, ccb_info);
+                               free(ccb_info);
+                               return STORAGE_ERROR_NONE;
+                       }
+               }
+               return STORAGE_ERROR_OPERATION_FAILED;
        }
 
-       /* in case of internal memory, it does not register changed callback */
-       if (st->type == STORAGE_TYPE_INTERNAL)
-               return STORAGE_ERROR_NONE;
+       /* Internal storage does not support registering changed callback */
+       DD_LIST_FOREACH(st_int_head, elem, st)
+               if (st->storage_id == storage_id)
+                       return STORAGE_ERROR_NONE;
 
+       /* external storage */
        info.id = storage_id;
        info.state_cb = callback;
 
-       ret = st->unregister_cb(STORAGE_CALLBACK_STATE, &info);
+       ret = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
        if (ret < 0) {
-               _E("Failed to unregister callback : id(%d)", storage_id);
+               _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
                return STORAGE_ERROR_OPERATION_FAILED;
        }
 
@@ -250,26 +388,36 @@ API int storage_get_total_space(int storage_id, unsigned long long *bytes)
        const struct storage_ops *st;
        unsigned long long total;
        int ret;
+       dd_list *elem;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!bytes) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               if (st->storage_id != storage_id)
+                       continue;
+               ret = st->get_space(&total, NULL);
+               goto out;
        }
 
-       ret = st->get_space(&total, NULL);
+       /* external storage */
+       ret = storage_ext_get_space(storage_id, &total, NULL);
+
+out:
        if (ret < 0) {
-               _E("Failed to get total memory : id(%d)", storage_id);
+               _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
+               if (ret == -ENOTSUP)
+                       return STORAGE_ERROR_NOT_SUPPORTED;
                return STORAGE_ERROR_OPERATION_FAILED;
        }
 
        *bytes = total;
-
        return STORAGE_ERROR_NONE;
 }
 
@@ -278,25 +426,102 @@ API int storage_get_available_space(int storage_id, unsigned long long *bytes)
        const struct storage_ops *st;
        unsigned long long avail;
        int ret;
+       dd_list *elem;
+
+       if (storage_id < 0)
+               return STORAGE_ERROR_NOT_SUPPORTED;
 
        if (!bytes) {
                _E("Invalid parameger");
                return STORAGE_ERROR_INVALID_PARAMETER;
        }
 
-       st = DD_LIST_NTH(st_head, storage_id);
-       if (!st) {
-               _E("Not supported storage : id(%d)", storage_id);
-               return STORAGE_ERROR_NOT_SUPPORTED;
+       /* internal storage */
+       DD_LIST_FOREACH(st_int_head, elem, st) {
+               if (st->storage_id != storage_id)
+                       continue;
+               ret = st->get_space(NULL, &avail);
+               goto out;
        }
 
-       ret = st->get_space(NULL, &avail);
+       /* external storage */
+       ret = storage_ext_get_space(storage_id, NULL, &avail);
+
+out:
        if (ret < 0) {
-               _E("Failed to get available memory : id(%d)", storage_id);
+               _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
+               if (ret == -ENOTSUP)
+                       return STORAGE_ERROR_NOT_SUPPORTED;
                return STORAGE_ERROR_OPERATION_FAILED;
        }
 
        *bytes = avail;
+       return STORAGE_ERROR_NONE;
+}
+
+API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
+{
+       int ret;
+       struct storage_cb_info info;
+
+       if (type == STORAGE_TYPE_INTERNAL) {
+               _E("Internal storage is not supported");
+               return STORAGE_ERROR_NOT_SUPPORTED;
+       }
+
+       if (type != STORAGE_TYPE_EXTERNAL) {
+               _E("Invalid type (%d)", type);
+               return STORAGE_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!callback) {
+               _E("Callback is NULL");
+               return STORAGE_ERROR_INVALID_PARAMETER;
+       }
+
+       /* external storage */
+       info.type = type;
+       info.type_cb = callback;
+       info.user_data = user_data;
+
+       ret = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
+       if (ret < 0) {
+               _E("Failed to register storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_OPERATION_FAILED;
+       }
+
+       return STORAGE_ERROR_NONE;
+}
+
+API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
+{
+       struct storage_cb_info info;
+       int ret;
+
+       if (type == STORAGE_TYPE_INTERNAL) {
+               _E("Internal storage is not supported");
+               return STORAGE_ERROR_NOT_SUPPORTED;
+       }
+
+       if (type != STORAGE_TYPE_EXTERNAL) {
+               _E("Invalid type (%d)", type);
+               return STORAGE_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!callback) {
+               _E("Callback is NULL");
+               return STORAGE_ERROR_INVALID_PARAMETER;
+       }
+
+       /* external storage */
+       info.type = type;
+       info.type_cb = callback;
+
+       ret = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
+       if (ret < 0) {
+               _E("Failed to unregister storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
+               return STORAGE_ERROR_OPERATION_FAILED;
+       }
 
        return STORAGE_ERROR_NONE;
 }