#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <vconf.h>
+#include <tzplatform_config.h>
#include "common.h"
#include "list.h"
#include "log.h"
-
-const char *dir_path[STORAGE_DIRECTORY_MAX] = {
- [STORAGE_DIRECTORY_IMAGES] = "Images",
- [STORAGE_DIRECTORY_SOUNDS] = "Sounds",
- [STORAGE_DIRECTORY_VIDEOS] = "Videos",
- [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",
+#include "storage-external.h"
+
+#define BLOCK_CONF_FILE "/etc/storaged/block.conf"
+#define USER_UID_START 5000
+
+const char *dir_path[STORAGE_DIRECTORY_MAX];
+
+const int tz_id[STORAGE_DIRECTORY_MAX] = {
+ [STORAGE_DIRECTORY_IMAGES] = TZ_USER_IMAGES,
+ [STORAGE_DIRECTORY_SOUNDS] = TZ_USER_SOUNDS,
+ [STORAGE_DIRECTORY_VIDEOS] = TZ_USER_VIDEOS,
+ [STORAGE_DIRECTORY_CAMERA] = TZ_USER_CAMERA,
+ [STORAGE_DIRECTORY_DOWNLOADS] = TZ_USER_DOWNLOADS,
+ [STORAGE_DIRECTORY_MUSIC] = TZ_USER_MUSIC,
+ [STORAGE_DIRECTORY_DOCUMENTS] = TZ_USER_DOCUMENTS,
+ [STORAGE_DIRECTORY_OTHERS] = TZ_USER_OTHERS,
};
-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);
+}
+
+int storage_ext_is_supported(void)
+{
+ static int support = -1;
+
+ if (support >= 0)
+ return support;
+
+ if (access(BLOCK_CONF_FILE, R_OK) == 0)
+ support = 1;
+ else
+ support = 0;
+
+ return support;
}
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;
+ bool user = true;
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(),
- st->root(), user_data);
- /* if the return value is false, will be stop to iterate */
- if (!ret)
- break;
- storage_id++;
+ if (getuid() < USER_UID_START)
+ user = false;
+
+ DD_LIST_FOREACH(st_int_head, elem, st) {
+ if (user) {
+ 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;
+ }
+ }
+
+ if (!storage_ext_is_supported()) {
+ _D("Block module is not enabled");
+ return STORAGE_ERROR_NONE;
+ }
+
+ 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;
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;
+ bool extendedint;
+ bool user = true;
+
+ 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;
+ if (getuid() < USER_UID_START)
+ user = false;
+
+ /* internal storage */
+ DD_LIST_FOREACH(st_int_head, elem, st) {
+ if (st->storage_id != storage_id)
+ continue;
+ if (!user) {
+ _E("Only Tizen applications and user session daemons can use \
+ storage_get_root_directory(id , ...)");
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ *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), &extendedint);
+ 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 : %d", errno);
+ _E("Failed to copy the root string : %d", errno); //LCOV_EXCL_LINE System Error
return STORAGE_ERROR_OUT_OF_MEMORY;
}
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;
+ bool extendedint;
+ bool user = true;
+
+ 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);
+ /* internal storage */
+ found = false;
+ DD_LIST_FOREACH(st_int_head, elem, st) {
+ if (st->storage_id != storage_id)
+ continue;
+ found = true;
+ break;
+ }
+
+ if (getuid() < USER_UID_START)
+ user = false;
+
+ if (found && st) {
+ if (!user) {
+ _E("Only Tizen applications and user session daemons can use \
+ storage_get_directory(id, ...)");
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ 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;
}
- if (st->type != STORAGE_TYPE_INTERNAL
- && type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
- _E("Not support directory : id(%d) type(%d)", storage_id, type);
+ ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
+ 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_NOT_SUPPORTED;
}
+ /* The operation is not decided */
+ if (extendedint)
+ 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]);
+ snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
+out:
*path = strdup(temp);
if (!*path) {
- _E("Failed to copy the directory(%d) string : %d", type, errno);
+ _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
return STORAGE_ERROR_OUT_OF_MEMORY;
}
API int storage_get_type(int storage_id, storage_type_e *type)
{
const struct storage_ops *st;
+ dd_list *elem;
+ char root[PATH_MAX];
+ int ret;
+ bool extendedint;
+
+ 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 */
+ ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
+ if (ret < 0) {
+ _E("Failed to get type of external storage");
+ return STORAGE_ERROR_NOT_SUPPORTED;
+ }
+ if (extendedint)
+ *type = STORAGE_TYPE_EXTENDED_INTERNAL;
+ else
+ *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;
}
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;
}
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;
}
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 && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
+ _E("Invalid type (%d)", type);
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!callback) {
+ _E("Callback is NULL");
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!storage_ext_is_supported()) {
+ _E("Block module is not enabled");
+ return STORAGE_ERROR_NOT_SUPPORTED;
+ }
+
+ /* 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 && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
+ _E("Invalid type (%d)", type);
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!callback) {
+ _E("Callback is NULL");
+ return STORAGE_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!storage_ext_is_supported()) {
+ _E("Block module is not enabled");
+ return STORAGE_ERROR_NOT_SUPPORTED;
+ }
+
+ /* 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;
+}
+
+static void __CONSTRUCTOR__ init(void)
+{
+ const char *tmp;
+ char *token;
+ int i;
+
+ for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
+ tmp = tzplatform_getenv(tz_id[i]);
+ if (tmp != NULL) {
+ token = rindex(tmp, '/');
+ if (token != NULL) {
+ token++;
+ dir_path[i] = strdup(token);
+ }
+ }
+ }
+}