From bc401352acecfd4d112cac8d59acbbf9792db170 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Fri, 11 Sep 2015 16:26:20 +0900 Subject: [PATCH 01/16] ringtones: change the path for the ringtones files Change-Id: I3b4d9d40bcf1fb86dd9db64c7b62034ad44293dd Signed-off-by: taeyoung --- src/storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage.c b/src/storage.c index 4ea9171..dcf301d 100644 --- a/src/storage.c +++ b/src/storage.c @@ -33,7 +33,7 @@ const char *dir_path[STORAGE_DIRECTORY_MAX] = { [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] = "/usr/apps/org.tizen.setting/shared/res/settings/Ringtones", }; static dd_list *st_head; -- 2.7.4 From 41465ce5e41bb421b5178c62f7a99d886f40798a Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Mon, 3 Aug 2015 19:15:21 +0900 Subject: [PATCH 02/16] license: update license name Signed-off-by: Taeyoung Kim Change-Id: I18feb1e2e05f22c1142419998307ae09b9812eff --- packaging/libstorage.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libstorage.spec b/packaging/libstorage.spec index 501ed0d..f9eef1f 100644 --- a/packaging/libstorage.spec +++ b/packaging/libstorage.spec @@ -3,7 +3,7 @@ Summary: Library to get storage information Version: 0.1.0 Release: 0 Group: System/Libraries -License: Apache License, Version 2.0 +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1: %{name}.manifest BuildRequires: cmake -- 2.7.4 From 600669d7db4b7866e420f668b462093dfd4c5e47 Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Wed, 17 Feb 2016 14:17:47 +0900 Subject: [PATCH 03/16] paths: change mount path to TZ_SYS_MEDIA - Tizen Directory policy is changed. The block device mount paths are located under the TZ_SYS_MEDIA (/opt/media) Change-Id: I5376ff66d94db8b3bfde19db304d8566985b8c1e Signed-off-by: Taeyoung Kim --- src/statvfs.c | 2 +- src/storage-sdcard.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/statvfs.c b/src/statvfs.c index 859f43d..5d04821 100644 --- a/src/statvfs.c +++ b/src/statvfs.c @@ -328,7 +328,7 @@ static int mount_check(const char *path) static const char *get_external_path(void) { - return tzplatform_mkpath(TZ_SYS_STORAGE, + return tzplatform_mkpath(TZ_SYS_MEDIA, EXTERNAL_MEMORY_NODE); } diff --git a/src/storage-sdcard.c b/src/storage-sdcard.c index 8d6dcbd..742586e 100755 --- a/src/storage-sdcard.c +++ b/src/storage-sdcard.c @@ -89,7 +89,7 @@ static int sdcard_get_space(unsigned long long *total, unsigned long long *avail static const char *sdcard_get_root(void) { - return tzplatform_mkpath(TZ_SYS_STORAGE, SDCARD_NODE); + return tzplatform_mkpath(TZ_SYS_MEDIA, SDCARD_NODE); } static void sdcard_state_cb(keynode_t *key, void *data) -- 2.7.4 From 3ef0599a84171afe7a6235003288843475a2bf0d Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 24 Mar 2016 22:01:41 +0900 Subject: [PATCH 04/16] paths: change paths to Macros - The paths of storages can be changed according to the dir policy. Thus the paths are changed to macros which define the policy Change-Id: I6eb483abefc8f8583bd439c37f886ab6b80880bd Signed-off-by: Taeyoung Kim --- src/statvfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/statvfs.c b/src/statvfs.c index 5d04821..c6c187b 100644 --- a/src/statvfs.c +++ b/src/statvfs.c @@ -33,7 +33,6 @@ #define MEMORY_GIGABYTE_VALUE 1073741824 #define MEMORY_MEGABYTE_VALUE 1048576 -#define MEMORY_STATUS_USR_PATH "/opt/usr" #define EXTERNAL_MEMORY_NODE "sdcard" #define STORAGE_CONF_FILE "/etc/storage/libstorage.conf" @@ -252,7 +251,7 @@ API int storage_get_internal_memory_size(struct statvfs *buf) return -EINVAL; } - ret = get_memory_size(MEMORY_STATUS_USR_PATH, &temp); + ret = get_memory_size(tzplatform_getenv(TZ_SYS_HOME), &temp); if (ret || temp.f_bsize == 0) { _E("fail to get memory size"); return -errno; @@ -285,7 +284,7 @@ API int storage_get_internal_memory_size64(struct statvfs *buf) return -EINVAL; } - ret = statvfs(MEMORY_STATUS_USR_PATH, buf); + ret = statvfs(tzplatform_getenv(TZ_SYS_HOME), buf); if (ret) { _E("fail to get memory size"); return -errno; -- 2.7.4 From a032c6f8d23115fdfc7337dc07775e7b7979d858 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Wed, 30 Mar 2016 11:01:49 +0900 Subject: [PATCH 05/16] Get Ringtone path from system setting api Change-Id: I4a837028d9e6b49c6d57b2d3c62da36a108e3784 Signed-off-by: pr.jung --- CMakeLists.txt | 2 +- packaging/libstorage.spec | 1 + src/storage.c | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f621ade..a846ba6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(VERSION 0.1) SET(INC_DIR include) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/${INC_DIR}) -SET(dependents "dlog capi-base-common vconf glib-2.0 libtzplatform-config") +SET(dependents "dlog capi-base-common vconf glib-2.0 libtzplatform-config capi-system-system-settings") SET(pc_dependents "capi-base-common") INCLUDE(FindPkgConfig) diff --git a/packaging/libstorage.spec b/packaging/libstorage.spec index f9eef1f..9f1087a 100644 --- a/packaging/libstorage.spec +++ b/packaging/libstorage.spec @@ -12,6 +12,7 @@ BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(capi-system-system-settings) %description development package of library to get storage diff --git a/src/storage.c b/src/storage.c index dcf301d..e21b0cd 100644 --- a/src/storage.c +++ b/src/storage.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "common.h" #include "list.h" @@ -33,7 +34,7 @@ const char *dir_path[STORAGE_DIRECTORY_MAX] = { [STORAGE_DIRECTORY_MUSIC] = "Music", [STORAGE_DIRECTORY_DOCUMENTS] = "Documents", [STORAGE_DIRECTORY_OTHERS] = "Others", - [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "/usr/apps/org.tizen.setting/shared/res/settings/Ringtones", + [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "", }; static dd_list *st_head; @@ -100,6 +101,8 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p const struct storage_ops *st; const char *root; char temp[PATH_MAX]; + char *temp2, *end; + int ret; if (!path) { _E("Invalid parameger"); @@ -124,9 +127,18 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p } root = st->root(); - if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) - snprintf(temp, PATH_MAX, "%s", dir_path[type]); - else + if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) { + ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &temp2); + if (ret < 0) { + _E("Failed to get ringtone path : %d", ret); + 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]); *path = strdup(temp); -- 2.7.4 From 19353c73307d748daa811508f25ae3f353813bef Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Fri, 1 Apr 2016 09:03:03 +0900 Subject: [PATCH 06/16] common: apply Tizen Coding Rule - Space policy is applied. - Brace position policy is applied. Change-Id: I06e6e17e37018b0285c3eaf929a92640f7775f6c Signed-off-by: Taeyoung Kim --- include/log.h | 16 ++++++++-------- include/storage-expand.h | 12 ++++-------- include/storage.h | 4 ++-- src/statvfs.c | 2 +- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/include/log.h b/include/log.h index dfa287e..0c35119 100644 --- a/include/log.h +++ b/include/log.h @@ -28,21 +28,21 @@ #ifdef ENABLE_DLOG #include #define _D(fmt, arg...) \ - do { SLOGD(fmt, ##arg); } while(0) + do { SLOGD(fmt, ##arg); } while (0) #define _I(fmt, arg...) \ - do { SLOGI(fmt, ##arg); } while(0) + do { SLOGI(fmt, ##arg); } while (0) #define _W(fmt, arg...) \ - do { SLOGW(fmt, ##arg); } while(0) + do { SLOGW(fmt, ##arg); } while (0) #define _E(fmt, arg...) \ - do { SLOGE(fmt, ##arg); } while(0) + do { SLOGE(fmt, ##arg); } while (0) #define _SD(fmt, arg...) \ - do { SECURE_SLOGD(fmt, ##arg); } while(0) + do { SECURE_SLOGD(fmt, ##arg); } while (0) #define _SI(fmt, arg...) \ - do { SECURE_SLOGI(fmt, ##arg); } while(0) + do { SECURE_SLOGI(fmt, ##arg); } while (0) #define _SW(fmt, arg...) \ - do { SECURE_SLOGW(fmt, ##arg); } while(0) + do { SECURE_SLOGW(fmt, ##arg); } while (0) #define _SE(fmt, arg...) \ - do { SECURE_SLOGE(fmt, ##arg); } while(0) + do { SECURE_SLOGE(fmt, ##arg); } while (0) #else #define _D(...) do { } while (0) #define _I(...) do { } while (0) diff --git a/include/storage-expand.h b/include/storage-expand.h index 83f3491..c7b67a1 100644 --- a/include/storage-expand.h +++ b/include/storage-expand.h @@ -35,8 +35,7 @@ extern "C" { * @brief Enumeration of error codes for Storage. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ -typedef enum -{ +typedef enum { STORAGE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ STORAGE_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ STORAGE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ @@ -49,8 +48,7 @@ typedef enum * @brief Enumeration of the storage types. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ -typedef enum -{ +typedef enum { STORAGE_TYPE_INTERNAL, /**< Internal device storage (built-in storage in a device, non-removable) */ STORAGE_TYPE_EXTERNAL, /**< External storage */ } storage_type_e; @@ -60,8 +58,7 @@ typedef enum * @brief Enumeration of the state of storage devices. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ -typedef enum -{ +typedef enum { STORAGE_STATE_UNMOUNTABLE = -2, /**< Storage is present but cannot be mounted. Typically it happens if the file system of the storage is corrupted */ STORAGE_STATE_REMOVED = -1, /**< Storage is not present */ STORAGE_STATE_MOUNTED = 0, /**< Storage is present and mounted with read/write access */ @@ -139,8 +136,7 @@ int storage_get_root_directory(int storage_id, char **path); * @brief Enumeration of the storage directory types * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ -typedef enum -{ +typedef enum { STORAGE_DIRECTORY_IMAGES, /**< Image directory */ STORAGE_DIRECTORY_SOUNDS, /**< Sounds directory */ STORAGE_DIRECTORY_VIDEOS, /**< Videos directory */ diff --git a/include/storage.h b/include/storage.h index 7370582..5df9a26 100644 --- a/include/storage.h +++ b/include/storage.h @@ -98,9 +98,9 @@ extern int storage_get_internal_memory_size64(struct statvfs *buf); extern int storage_get_external_memory_size(struct statvfs *buf); #else # ifdef __REDIRECT_NTH -extern int __REDIRECT_NTH (storage_get_external_memory_size, +extern int __REDIRECT_NTH(storage_get_external_memory_size, (struct statvfs *buf), storage_get_external_memory_size64) - __nonnull ((1)); + __nonnull((1)); # else # define storage_get_external_memory_size storage_get_external_memory_size64 # endif diff --git a/src/statvfs.c b/src/statvfs.c index c6c187b..52e030c 100644 --- a/src/statvfs.c +++ b/src/statvfs.c @@ -93,7 +93,7 @@ static inline char *trim_str(char *s) } static int config_parse(const char *file_name, int cb(struct parse_result *result, - void *user_data), void *user_data) + void *user_data), void *user_data) { FILE *f = NULL; struct parse_result result; -- 2.7.4 From a9890064eb43db2f37d8f7c7137c418e8db85f7a Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:10:16 +0900 Subject: [PATCH 07/16] internal: storage list is used just for internal storage - External storages are changeable and can be added/removed frequently. Thus storage list maintains just internal storage. Change-Id: Ia4da6c41b29156fdd8f783cadc371acbf8699be2 Signed-off-by: Taeyoung Kim --- include/common.h | 1 + src/storage-internal.c | 1 + src/storage.c | 210 ++++++++++++++++++++++++------------------------- 3 files changed, 106 insertions(+), 106 deletions(-) diff --git a/include/common.h b/include/common.h index 1a9d987..7ff5ce9 100644 --- a/include/common.h +++ b/include/common.h @@ -59,6 +59,7 @@ struct storage_ops { int (*get_space) (unsigned long long *total, unsigned long long *available); int (*register_cb) (enum storage_cb_type type, struct storage_cb_info *info); int (*unregister_cb) (enum storage_cb_type type, struct storage_cb_info *info); + int storage_id; }; #define STORAGE_OPS_REGISTER(st) \ diff --git a/src/storage-internal.c b/src/storage-internal.c index ca8b182..1867def 100755 --- a/src/storage-internal.c +++ b/src/storage-internal.c @@ -68,6 +68,7 @@ const struct storage_ops internal = { .root = internal_get_root, .get_state = internal_get_state, .get_space = internal_get_space, + .storage_id = 0, }; STORAGE_OPS_REGISTER(&internal) diff --git a/src/storage.c b/src/storage.c index e21b0cd..cb4409a 100644 --- a/src/storage.c +++ b/src/storage.c @@ -37,61 +37,65 @@ const char *dir_path[STORAGE_DIRECTORY_MAX] = { [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "", }; -static dd_list *st_head; +static dd_list *st_int_head; /* Internal storage list */ 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++; } + /* TODO external storage */ + return STORAGE_ERROR_NONE; } API int storage_get_root_directory(int storage_id, char **path) { const struct storage_ops *st; + dd_list *elem; - if (!path) { + if (!path || storage_id < 0) { _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) { + _E("Failed to copy the root string : %d", errno); + return STORAGE_ERROR_OUT_OF_MEMORY; + } + return STORAGE_ERROR_NONE; } - *path = strdup(st->root()); - if (!*path) { - _E("Failed to copy the root string : %d", errno); - return STORAGE_ERROR_OUT_OF_MEMORY; - } + /* TODO external storage */ return STORAGE_ERROR_NONE; } @@ -99,12 +103,14 @@ 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 (!path) { + if (!path || storage_id < 0) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -114,33 +120,38 @@ 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); - return STORAGE_ERROR_NOT_SUPPORTED; + if (found && st) { + snprintf(root, sizeof(root), "%s", st->root()); + if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) { + ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &temp2); + if (ret < 0) { + _E("Failed to get ringtone path : %d", ret); + 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; } - root = st->root(); - if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) { - ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &temp2); - if (ret < 0) { - _E("Failed to get ringtone path : %d", ret); - 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]); + /* external storage */ + return STORAGE_ERROR_NONE; +out: *path = strdup(temp); if (!*path) { _E("Failed to copy the directory(%d) string : %d", type, errno); @@ -153,39 +164,45 @@ 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 (!type) { + if (!type || storage_id < 0) { _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 */ 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; + dd_list *elem; 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 */ return STORAGE_ERROR_NONE; } @@ -193,33 +210,19 @@ API int storage_get_state(int storage_id, storage_state_e *state) 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; 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; - } - - /* do not register changed callback in case of internal memory */ - if (st->type == STORAGE_TYPE_INTERNAL) - return STORAGE_ERROR_NONE; - - info.id = storage_id; - info.state_cb = callback; - info.user_data = user_data; + /* 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; - ret = st->register_cb(STORAGE_CALLBACK_STATE, &info); - if (ret < 0) { - _E("Failed to register callback : id(%d)", storage_id); - return STORAGE_ERROR_OPERATION_FAILED; - } + /* external storage */ return STORAGE_ERROR_NONE; } @@ -227,32 +230,17 @@ API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb ca API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback) { const struct storage_ops *st; - struct storage_cb_info info; - int ret; + dd_list *elem; 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; - } - - /* in case of internal memory, it does not register changed callback */ - if (st->type == STORAGE_TYPE_INTERNAL) - return STORAGE_ERROR_NONE; - - info.id = storage_id; - info.state_cb = callback; - - ret = st->unregister_cb(STORAGE_CALLBACK_STATE, &info); - if (ret < 0) { - _E("Failed to unregister callback : id(%d)", storage_id); - return STORAGE_ERROR_OPERATION_FAILED; - } + /* 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; return STORAGE_ERROR_NONE; } @@ -262,26 +250,31 @@ 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 (!bytes) { + if (!bytes || storage_id < 0) { _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 = 0; + +out: if (ret < 0) { _E("Failed to get total memory : id(%d)", storage_id); return STORAGE_ERROR_OPERATION_FAILED; } *bytes = total; - return STORAGE_ERROR_NONE; } @@ -290,25 +283,30 @@ 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 (!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 = 0; + +out: if (ret < 0) { _E("Failed to get available memory : id(%d)", storage_id); return STORAGE_ERROR_OPERATION_FAILED; } *bytes = avail; - return STORAGE_ERROR_NONE; } -- 2.7.4 From 9f1b2e6440f504363b46b80116e6ae55e7544e99 Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:25:59 +0900 Subject: [PATCH 08/16] external: support foreach function for external storages - External storage information can be get from deviced. Thus the dbus method call from deviced is used to get the information. Change-Id: Iac56c26ed766b8a72a78ba970152c7105b0672a1 Signed-off-by: Taeyoung Kim --- CMakeLists.txt | 13 ++- packaging/libstorage.spec | 1 + src/storage-external-dbus.c | 195 +++++++++++++++++++++++++++++++++++++++ src/storage-external-dbus.h | 80 ++++++++++++++++ src/storage-external.c | 94 +++++++++++++++++++ src/storage-external.h | 26 ++++++ src/storage-sdcard.c | 217 -------------------------------------------- src/storage.c | 7 +- 8 files changed, 413 insertions(+), 220 deletions(-) create mode 100755 src/storage-external-dbus.c create mode 100644 src/storage-external-dbus.h create mode 100755 src/storage-external.c create mode 100755 src/storage-external.h delete mode 100755 src/storage-sdcard.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a846ba6..56482b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,15 @@ SET(VERSION 0.1) SET(INC_DIR include) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/${INC_DIR}) -SET(dependents "dlog capi-base-common vconf glib-2.0 libtzplatform-config capi-system-system-settings") +SET(dependents + dlog + capi-base-common + vconf + glib-2.0 + gio-2.0 + libtzplatform-config + capi-system-system-settings +) SET(pc_dependents "capi-base-common") INCLUDE(FindPkgConfig) @@ -36,7 +44,8 @@ SET(SRCS src/statvfs.c src/storage.c src/storage-internal.c - src/storage-sdcard.c) + src/storage-external.c + src/storage-external-dbus.c) ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${TARGET_SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${rpkgs_LDFLAGS}) diff --git a/packaging/libstorage.spec b/packaging/libstorage.spec index 9f1087a..0204e53 100644 --- a/packaging/libstorage.spec +++ b/packaging/libstorage.spec @@ -11,6 +11,7 @@ BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(capi-system-system-settings) diff --git a/src/storage-external-dbus.c b/src/storage-external-dbus.c new file mode 100755 index 0000000..1f39362 --- /dev/null +++ b/src/storage-external-dbus.c @@ -0,0 +1,195 @@ +/* + * libstorage + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "storage-external-dbus.h" + +#define CHECK_STR(a) (a ? a : "") + +#define STORAGE_EXT_GET_LIST "GetDeviceList" + +#define DBUS_REPLY_TIMEOUT (-1) + +static void storage_ext_release_internal(storage_ext_device *dev) +{ + if (!dev) + return; + free(dev->devnode); + free(dev->syspath); + free(dev->fs_usage); + free(dev->fs_type); + free(dev->fs_version); + free(dev->fs_uuid); + free(dev->mount_point); +} + +void storage_ext_release_device(storage_ext_device **dev) +{ + if (!dev || !*dev) + return; + storage_ext_release_internal(*dev); + free(*dev); + *dev = NULL; +} + +void storage_ext_release_list(dd_list **list) +{ + storage_ext_device *dev; + dd_list *elem; + + if (*list == NULL) + return; + + DD_LIST_FOREACH(*list, elem, dev) { + storage_ext_release_internal(dev); + free(dev); + } + + g_list_free(*list); + *list = NULL; +} + +static GDBusConnection *get_dbus_connection(void) +{ + GError *err = NULL; + static GDBusConnection *conn; + + if (conn) + return conn; + +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn) { + if (err) { + _E("fail to get dbus connection : %s", err->message); + g_clear_error(&err); + } else + _E("fail to get dbus connection"); + return NULL; + } + return conn; +} + +static GVariant *dbus_method_call_sync(const gchar *dest, const gchar *path, + const gchar *iface, const gchar *method, GVariant *param) +{ + GDBusConnection *conn; + GError *err = NULL; + GVariant *ret; + + if (!dest || !path || !iface || !method || !param) + return NULL; + + conn = get_dbus_connection(); + if (!conn) { + _E("fail to get dbus connection"); + return NULL; + } + + ret = g_dbus_connection_call_sync(conn, + dest, path, iface, method, + param, NULL, G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &err); + if (!ret) { + if (err) { + _E("dbus method sync call failed(%s)", err->message); + g_clear_error(&err); + } else + _E("g_dbus_connection_call_sync() failed"); + return NULL; + } + + return ret; +} + +int storage_ext_get_list(dd_list **list) +{ + GVariant *result; + GVariantIter *iter; + storage_ext_device *elem, info; + int ret; + + if (!list) + return -EINVAL; + + result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME, + STORAGE_EXT_PATH_MANAGER, + STORAGE_EXT_IFACE_MANAGER, + STORAGE_EXT_GET_LIST, + g_variant_new("(s)", "all")); + if (!result) { + _E("Failed to get storage_ext device info"); + return -EIO; + } + + g_variant_get(result, "(a(issssssisibii))", &iter); + + while (g_variant_iter_loop(iter, "(issssssisibii)", + &info.type, &info.devnode, &info.syspath, + &info.fs_usage, &info.fs_type, + &info.fs_version, &info.fs_uuid, + &info.readonly, &info.mount_point, + &info.state, &info.primary, + &info.flags, &info.storage_id)) { + + elem = (storage_ext_device *)malloc(sizeof(storage_ext_device)); + if (!elem) { + _E("malloc() failed"); + ret = -ENOMEM; + goto out; + } + + elem->type = info.type; + elem->readonly = info.readonly; + elem->state = info.state; + elem->primary = info.primary; + elem->devnode = strdup(CHECK_STR(info.devnode)); + elem->syspath = strdup(CHECK_STR(info.syspath)); + elem->fs_usage = strdup(CHECK_STR(info.fs_usage)); + elem->fs_type = strdup(CHECK_STR(info.fs_type)); + elem->fs_version = strdup(CHECK_STR(info.fs_version)); + elem->fs_uuid = strdup(CHECK_STR(info.fs_uuid)); + elem->mount_point = strdup(CHECK_STR(info.mount_point)); + elem->flags = info.flags; + elem->storage_id = info.storage_id; + + DD_LIST_APPEND(*list, elem); + } + + ret = g_list_length(*list); + +out: + if (ret < 0) + storage_ext_release_list(list); + g_variant_iter_free(iter); + g_variant_unref(result); + return ret; +} diff --git a/src/storage-external-dbus.h b/src/storage-external-dbus.h new file mode 100644 index 0000000..7a0867a --- /dev/null +++ b/src/storage-external-dbus.h @@ -0,0 +1,80 @@ +/* + * libstorage + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * 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. + */ + + +#ifndef __STORAGE_EXTERNAL_DBUS_H__ +#define __STORAGE_EXTERNAL_DBUS_H__ + +#include +#include +#include +#include "list.h" + +#define STORAGE_EXT_BUS_NAME "org.tizen.system.deviced" +#define STORAGE_EXT_PATH "/Org/Tizen/System/DeviceD/Block" +#define STORAGE_EXT_PATH_DEVICES STORAGE_EXT_PATH"/Devices" +#define STORAGE_EXT_PATH_MANAGER STORAGE_EXT_PATH"/Manager" +#define STORAGE_EXT_IFACE STORAGE_EXT_BUS_NAME".Block" +#define STORAGE_EXT_IFACE_MANAGER STORAGE_EXT_BUS_NAME".BlockManager" + +enum mount_state { + STORAGE_EXT_UNMOUNTED, + STORAGE_EXT_MOUNTED, +}; + +enum storage_ext_state { + STORAGE_EXT_REMOVED, + STORAGE_EXT_ADDED, + STORAGE_EXT_CHANGED, +}; + +enum storage_ext_type { + STORAGE_EXT_SCSI, + STORAGE_EXT_MMC, +}; + +enum storage_ext_flags { + FLAG_NONE = 0, + UNMOUNT_UNSAFE = 1 << 0, + FS_BROKEN = 1 << 1, + FS_EMPTY = 1 << 2, + FS_NOT_SUPPORTED = 1 << 3, + MOUNT_READONLY = 1 << 4, +}; + +typedef struct _storage_ext_device { + enum storage_ext_type type; + char *devnode; + char *syspath; + char *fs_usage; + char *fs_type; + char *fs_version; + char *fs_uuid; + bool readonly; + char *mount_point; + enum mount_state state; + bool primary; /* the first partition */ + int flags; + int storage_id; +} storage_ext_device; + +void storage_ext_release_device(storage_ext_device **dev); +void storage_ext_release_list(dd_list **list); +int storage_ext_get_list(dd_list **list); + +#endif /* __STORAGE_EXTERNAL_DBUS_H__ */ diff --git a/src/storage-external.c b/src/storage-external.c new file mode 100755 index 0000000..c671645 --- /dev/null +++ b/src/storage-external.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 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 +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "list.h" +#include "log.h" +#include "storage-external-dbus.h" + +static int storage_ext_get_dev_state(storage_ext_device *dev, + enum storage_ext_state blk_state, + storage_state_e *state) +{ + if (!dev || !state) + return -EINVAL; + + switch (blk_state) { + case STORAGE_EXT_REMOVED: + *state = STORAGE_STATE_REMOVED; + return 0; + case STORAGE_EXT_CHANGED: + switch (dev->state) { + case STORAGE_EXT_UNMOUNTED: + *state = STORAGE_STATE_UNMOUNTABLE; + return 0; + case STORAGE_EXT_MOUNTED: + if (dev->flags & MOUNT_READONLY) + *state = STORAGE_STATE_MOUNTED_READ_ONLY; + else + *state = STORAGE_STATE_MOUNTED; + return 0; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data) +{ + int ret; + bool ret_cb; + dd_list *list = NULL, *elem; + storage_ext_device *dev; + storage_state_e state; + + if (!callback) + return -EINVAL; + + ret = storage_ext_get_list(&list); + if (ret < 0) { + _E("Failed to get external storage list from deviced (%d)", errno); + return ret; + } + + DD_LIST_FOREACH(list, elem, dev) { + ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state); + if (ret < 0) { + _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret); + continue; + } + + ret_cb = callback(dev->storage_id, STORAGE_TYPE_EXTERNAL, + state, dev->mount_point, user_data); + if (!ret_cb) + break; + } + + if (list) + storage_ext_release_list(&list); + return 0; +} \ No newline at end of file diff --git a/src/storage-external.h b/src/storage-external.h new file mode 100755 index 0000000..45c4167 --- /dev/null +++ b/src/storage-external.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016 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. + */ + +#ifndef __STORAGE_EXTERNAL_H__ +#define __STORAGE_EXTERNAL_H__ + +#include +#include "common.h" +#include "storage-external-dbus.h" + +int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data); + +#endif /* __STORAGE_EXTERNAL_H__ */ diff --git a/src/storage-sdcard.c b/src/storage-sdcard.c deleted file mode 100755 index 742586e..0000000 --- a/src/storage-sdcard.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2011 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 -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "list.h" -#include "log.h" - -#define SDCARD_NODE "sdcard" - -#ifndef __USE_FILE_OFFSET64 -int __WEAK__ storage_get_external_memory_size(struct statvfs *buf); -#else -int __WEAK__ storage_get_external_memory_size64(struct statvfs *buf); -#endif - -static dd_list *cb_list[STORAGE_CALLBACK_MAX]; - -static int sdcard_get_state(void) -{ - int val, ret; - - ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &val); - if (ret < 0) - return -EPERM; - - switch (val) { - case VCONFKEY_SYSMAN_MMC_MOUNTED: - return STORAGE_STATE_MOUNTED; - case VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED: - return STORAGE_STATE_UNMOUNTABLE; - case VCONFKEY_SYSMAN_MMC_REMOVED: - default: - break; - } - - return STORAGE_STATE_REMOVED; -} - -static int sdcard_get_space(unsigned long long *total, unsigned long long *available) -{ - storage_state_e state; - struct statvfs s; - int ret; - unsigned long long t = 0, a = 0; - - state = sdcard_get_state(); - if (state >= STORAGE_STATE_MOUNTED) { -#ifndef __USE_FILE_OFFSET64 - ret = storage_get_external_memory_size(&s); -#else - ret = storage_get_external_memory_size64(&s); -#endif - if (ret < 0) - return -EPERM; - - t = (unsigned long long)s.f_frsize*s.f_blocks; - a = (unsigned long long)s.f_bsize*s.f_bavail; - } - - if (total) - *total = t; - if (available) - *available = a; - - return 0; -} - -static const char *sdcard_get_root(void) -{ - return tzplatform_mkpath(TZ_SYS_MEDIA, SDCARD_NODE); -} - -static void sdcard_state_cb(keynode_t *key, void *data) -{ - struct storage_cb_info *cb_info; - dd_list *elem; - storage_state_e state; - - state = sdcard_get_state(); - - DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_STATE], elem, cb_info) - cb_info->state_cb(cb_info->id, state, cb_info->user_data); -} - -static int register_request(enum storage_cb_type type) -{ - switch (type) { - case STORAGE_CALLBACK_STATE: - return vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, - sdcard_state_cb, NULL); - default: - break; - } - - return -EINVAL; -} - -static int release_request(enum storage_cb_type type) -{ - switch (type) { - case STORAGE_CALLBACK_STATE: - return vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, - sdcard_state_cb); - default: - break; - } - - return -EINVAL; -} - -static int sdcard_register_cb(enum storage_cb_type type, struct storage_cb_info *info) -{ - struct storage_cb_info *cb_info; - dd_list *elem; - int ret, n; - - if (type < 0 || type >= STORAGE_CALLBACK_MAX) - return -EINVAL; - - if (!info) - return -EINVAL; - - /* check if it is the first request */ - n = DD_LIST_LENGTH(cb_list[type]); - if (n == 0) { - ret = register_request(type); - if (ret < 0) - return -EPERM; - } - - /* check for the same request */ - DD_LIST_FOREACH(cb_list[type], elem, cb_info) { - if (cb_info->id == info->id && - cb_info->state_cb == info->state_cb) - return -EEXIST; - } - - /* add device changed callback to list (local) */ - cb_info = malloc(sizeof(struct storage_cb_info)); - if (!cb_info) - return -errno; - - memcpy(cb_info, info, sizeof(struct storage_cb_info)); - DD_LIST_APPEND(cb_list[type], cb_info); - - return 0; -} - -static int sdcard_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info) -{ - struct storage_cb_info *cb_info; - dd_list *elem; - int ret, n; - - if (type < 0 || type >= STORAGE_CALLBACK_MAX) - return -EINVAL; - - if (!info) - return -EINVAL; - - /* search for the same element with callback */ - DD_LIST_FOREACH(cb_list[type], elem, cb_info) { - if (cb_info->id == info->id && - cb_info->state_cb == info->state_cb) - break; - } - - if (!cb_info) - return -EINVAL; - - /* remove device callback from list (local) */ - DD_LIST_REMOVE(cb_list[type], cb_info); - free(cb_info); - - /* check if this callback is last element */ - n = DD_LIST_LENGTH(cb_list[type]); - if (n == 0) { - ret = release_request(type); - if (ret < 0) - return -EPERM; - } - - return 0; -} - -const struct storage_ops sdcard = { - .type = STORAGE_TYPE_EXTERNAL, - .root = sdcard_get_root, - .get_state = sdcard_get_state, - .get_space = sdcard_get_space, - .register_cb = sdcard_register_cb, - .unregister_cb = sdcard_unregister_cb, -}; - -STORAGE_OPS_REGISTER(&sdcard) diff --git a/src/storage.c b/src/storage.c index cb4409a..cc04ab5 100644 --- a/src/storage.c +++ b/src/storage.c @@ -24,6 +24,7 @@ #include "common.h" #include "list.h" #include "log.h" +#include "storage-external.h" const char *dir_path[STORAGE_DIRECTORY_MAX] = { [STORAGE_DIRECTORY_IMAGES] = "Images", @@ -68,7 +69,11 @@ API int storage_foreach_device_supported(storage_device_supported_cb callback, v break; } - /* TODO external storage */ + ret = storage_ext_foreach_device_list(callback, user_data); + if (ret < 0) { + _E("Failed to iterate external devices (%d)", ret); + return STORAGE_ERROR_OPERATION_FAILED; + } return STORAGE_ERROR_NONE; } -- 2.7.4 From ebc865a7f34020f47d65aac30aa97782b88d05f4 Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:40:48 +0900 Subject: [PATCH 09/16] external: add storage change handler - Storage change handler functions are added. They trace dbus signal from deviced. If storages are added/removed/changed, dbus signal is broadcasted. Thus the callbacks can be called according to the storage state change. Change-Id: Ib60f9f5b3bc316bb1c276dc0a7d30b881ca9da3a Signed-off-by: Taeyoung Kim --- src/storage-external-dbus.c | 251 ++++++++++++++++++++++++++++++++++++++++++++ src/storage-external-dbus.h | 5 + src/storage-external.c | 100 ++++++++++++++++++ src/storage-external.h | 2 + src/storage.c | 23 ++++ 5 files changed, 381 insertions(+) diff --git a/src/storage-external-dbus.c b/src/storage-external-dbus.c index 1f39362..2c63d76 100755 --- a/src/storage-external-dbus.c +++ b/src/storage-external-dbus.c @@ -33,8 +33,23 @@ #define STORAGE_EXT_GET_LIST "GetDeviceList" +#define STORAGE_EXT_OBJECT_ADDED "ObjectAdded" +#define STORAGE_EXT_OBJECT_REMOVED "ObjectRemoved" +#define STORAGE_EXT_DEVICE_CHANGED "DeviceChanged" + #define DBUS_REPLY_TIMEOUT (-1) +#define DEV_PREFIX "/dev/" + +struct storage_ext_callback { + storage_ext_changed_cb func; + void *data; + guint block_id; + guint blockmanager_id; +}; + +static dd_list *changed_list; + static void storage_ext_release_internal(storage_ext_device *dev) { if (!dev) @@ -193,3 +208,239 @@ out: g_variant_unref(result); return ret; } + +static char *get_devnode_from_path(char *path) +{ + if (!path) + return NULL; + /* 1 means '/' */ + return path + strlen(STORAGE_EXT_PATH_DEVICES) + 1; +} + +static void storage_ext_object_path_changed(enum storage_ext_state state, + GVariant *params, gpointer user_data) +{ + storage_ext_device *dev = NULL; + dd_list *elem; + struct storage_ext_callback *callback; + char *path = NULL; + char *devnode; + int ret; + + if (!params) + return; + + g_variant_get(params, "(s)", &path); + + devnode = get_devnode_from_path(path); + if (!devnode) + goto out; + + dev = calloc(1, sizeof(storage_ext_device *)); + if (!dev) + goto out; + + dev->devnode = strdup(devnode); + if (dev->devnode == NULL) { + _E("strdup() failed"); + goto out; + } + + DD_LIST_FOREACH(changed_list, elem, callback) { + if (!callback->func) + continue; + ret = callback->func(dev, state, callback->data); + if (ret < 0) + _E("Failed to call callback for devnode(%s, %d)", devnode, ret); + } + +out: + if (dev) { + free(dev->devnode); + free(dev); + } + free(path); +} + +static void storage_ext_device_added(GVariant *params, gpointer user_data) +{ + storage_ext_object_path_changed(STORAGE_EXT_ADDED, params, user_data); +} + +static void storage_ext_device_removed(GVariant *params, gpointer user_data) +{ + storage_ext_object_path_changed(STORAGE_EXT_REMOVED, params, user_data); +} + +static void storage_ext_device_changed(GVariant *params, gpointer user_data) +{ + storage_ext_device *dev; + dd_list *elem; + struct storage_ext_callback *callback; + int ret; + + if (!params) + return; + + dev = calloc(1, sizeof(storage_ext_device)); + if (!dev) + return; + + g_variant_get(params, "(issssssisibii)", + &dev->type, + &dev->devnode, + &dev->syspath, + &dev->fs_usage, + &dev->fs_type, + &dev->fs_version, + &dev->fs_uuid, + &dev->readonly, + &dev->mount_point, + &dev->state, + &dev->primary, + &dev->flags, + &dev->storage_id); + + DD_LIST_FOREACH(changed_list, elem, callback) { + if (!callback->func) + continue; + ret = callback->func(dev, STORAGE_EXT_CHANGED, callback->data); + if (ret < 0) + _E("Failed to call callback for devnode(%s, %d)", dev->devnode, ret); + } + + storage_ext_release_device(&dev); +} + +static void storage_ext_changed(GDBusConnection *conn, + const gchar *sender, + const gchar *path, + const gchar *iface, + const gchar *signal, + GVariant *params, + gpointer user_data) +{ + size_t iface_len, signal_len; + + if (!params || !sender || !path || !iface || !signal) + return; + + iface_len = strlen(iface) + 1; + signal_len = strlen(signal) + 1; + + if (!strncmp(iface, STORAGE_EXT_IFACE_MANAGER, iface_len)) { + if (!strncmp(signal, STORAGE_EXT_OBJECT_ADDED, signal_len)) + storage_ext_device_added(params, user_data); + else if (!strncmp(signal, STORAGE_EXT_OBJECT_REMOVED, signal_len)) + storage_ext_device_removed(params, user_data); + return; + } + + if (!strncmp(iface, STORAGE_EXT_IFACE, iface_len) && + !strncmp(signal, STORAGE_EXT_DEVICE_CHANGED, signal_len)) { + storage_ext_device_changed(params, user_data); + return; + } +} + +int storage_ext_register_device_change(storage_ext_changed_cb func, void *data) +{ + GDBusConnection *conn; + guint block_id = NULL, blockmanager_id = NULL; + struct storage_ext_callback *callback; + dd_list *elem; + + if (!func) + return -EINVAL; + + DD_LIST_FOREACH(changed_list, elem, callback) { + if (callback->func != func) + continue; + if (callback->block_id == 0 || callback->blockmanager_id == 0) + continue; + + return -EEXIST; + } + + callback = (struct storage_ext_callback *)malloc(sizeof(struct storage_ext_callback)); + if (!callback) { + _E("malloc() failed"); + return -ENOMEM; + } + + conn = get_dbus_connection(); + if (!conn) { + free(callback); + _E("Failed to get dbus connection"); + return -EPERM; + } + + block_id = g_dbus_connection_signal_subscribe(conn, + STORAGE_EXT_BUS_NAME, + STORAGE_EXT_IFACE, + STORAGE_EXT_DEVICE_CHANGED, + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + storage_ext_changed, + NULL, + NULL); + if (block_id == 0) { + free(callback); + _E("Failed to subscrive bus signal"); + return -EPERM; + } + + blockmanager_id = g_dbus_connection_signal_subscribe(conn, + STORAGE_EXT_BUS_NAME, + STORAGE_EXT_IFACE_MANAGER, + NULL, + STORAGE_EXT_PATH_MANAGER, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + storage_ext_changed, + NULL, + NULL); + if (blockmanager_id == 0) { + free(callback); + _E("Failed to subscrive bus signal"); + return -EPERM; + } + + callback->func = func; + callback->data = data; + callback->block_id = block_id; + callback->blockmanager_id = blockmanager_id; + + DD_LIST_APPEND(changed_list, callback); + + return 0; +} + +void storage_ext_unregister_device_change(storage_ext_changed_cb func) +{ + GDBusConnection *conn; + struct storage_ext_callback *callback; + dd_list *elem; + + if (!func) + return; + + conn = get_dbus_connection(); + if (!conn) { + _E("fail to get dbus connection"); + return; + } + + DD_LIST_FOREACH(changed_list, elem, callback) { + if (callback->func != func) + continue; + if (callback->block_id > 0) + g_dbus_connection_signal_unsubscribe(conn, callback->block_id); + if (callback->blockmanager_id > 0) + g_dbus_connection_signal_unsubscribe(conn, callback->blockmanager_id); + + DD_LIST_REMOVE(changed_list, callback); + free(callback); + } +} diff --git a/src/storage-external-dbus.h b/src/storage-external-dbus.h index 7a0867a..98522d5 100644 --- a/src/storage-external-dbus.h +++ b/src/storage-external-dbus.h @@ -73,8 +73,13 @@ typedef struct _storage_ext_device { int storage_id; } storage_ext_device; +typedef int (*storage_ext_changed_cb)(storage_ext_device *dev, enum storage_ext_state state, void *data); + void storage_ext_release_device(storage_ext_device **dev); void storage_ext_release_list(dd_list **list); int storage_ext_get_list(dd_list **list); +int storage_ext_register_device_change(storage_ext_changed_cb func, void *data); +void storage_ext_unregister_device_change(storage_ext_changed_cb func); + #endif /* __STORAGE_EXTERNAL_DBUS_H__ */ diff --git a/src/storage-external.c b/src/storage-external.c index c671645..6308c3b 100755 --- a/src/storage-external.c +++ b/src/storage-external.c @@ -28,6 +28,8 @@ #include "log.h" #include "storage-external-dbus.h" +static dd_list *cb_list[STORAGE_CALLBACK_MAX]; + static int storage_ext_get_dev_state(storage_ext_device *dev, enum storage_ext_state blk_state, storage_state_e *state) @@ -91,4 +93,102 @@ int storage_ext_foreach_device_list(storage_device_supported_cb callback, void * if (list) storage_ext_release_list(&list); return 0; +} + +static int storage_ext_state_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data) +{ + enum storage_cb_type type = (enum storage_cb_type)data; + struct storage_cb_info *cb_info; + dd_list *elem; + storage_state_e state; + int ret; + + if (!dev) + return -EINVAL; + + if (type != STORAGE_CALLBACK_STATE) + return 0; + + ret = storage_ext_get_dev_state(dev, blk_state, &state); + if (ret < 0) { + _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret); + return ret; + } + + DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_STATE], elem, cb_info) + cb_info->state_cb(cb_info->id, state, cb_info->user_data); + + return 0; +} + +int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info) +{ + struct storage_cb_info *cb_info; + dd_list *elem; + int ret, n; + + if (type < 0 || type >= STORAGE_CALLBACK_MAX) + return -EINVAL; + + if (!info) + return -EINVAL; + + /* check if it is the first request */ + n = DD_LIST_LENGTH(cb_list[type]); + if (n == 0) { + ret = storage_ext_register_device_change(storage_ext_state_changed, (void *)type); + if (ret < 0) + return -EPERM; + } + + /* check for the same request */ + DD_LIST_FOREACH(cb_list[type], elem, cb_info) { + if (cb_info->id == info->id && + cb_info->state_cb == info->state_cb) + return -EEXIST; + } + + /* add device changed callback to list (local) */ + cb_info = malloc(sizeof(struct storage_cb_info)); + if (!cb_info) + return -errno; + + memcpy(cb_info, info, sizeof(struct storage_cb_info)); + DD_LIST_APPEND(cb_list[type], cb_info); + + return 0; +} + +int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info) +{ + struct storage_cb_info *cb_info; + dd_list *elem; + int n; + + if (type < 0 || type >= STORAGE_CALLBACK_MAX) + return -EINVAL; + + if (!info) + return -EINVAL; + + /* search for the same element with callback */ + DD_LIST_FOREACH(cb_list[type], elem, cb_info) { + if (cb_info->id == info->id && + cb_info->state_cb == info->state_cb) + break; + } + + if (!cb_info) + return -EINVAL; + + /* remove device callback from list (local) */ + DD_LIST_REMOVE(cb_list[type], cb_info); + free(cb_info); + + /* check if this callback is last element */ + n = DD_LIST_LENGTH(cb_list[type]); + if (n == 0) + storage_ext_unregister_device_change(storage_ext_state_changed); + + return 0; } \ No newline at end of file diff --git a/src/storage-external.h b/src/storage-external.h index 45c4167..cf5217b 100755 --- a/src/storage-external.h +++ b/src/storage-external.h @@ -22,5 +22,7 @@ #include "storage-external-dbus.h" int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data); +int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info); +int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info); #endif /* __STORAGE_EXTERNAL_H__ */ diff --git a/src/storage.c b/src/storage.c index cc04ab5..e6a54f7 100644 --- a/src/storage.c +++ b/src/storage.c @@ -215,6 +215,8 @@ API int storage_get_state(int storage_id, storage_state_e *state) 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; if (!callback) { @@ -228,6 +230,15 @@ API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb ca return STORAGE_ERROR_NONE; /* external storage */ + info.id = storage_id; + info.state_cb = callback; + info.user_data = user_data; + + ret = storage_ext_register_cb(STORAGE_CALLBACK_STATE, &info); + if (ret < 0) { + _E("Failed to register callback : id(%d)", storage_id); + return STORAGE_ERROR_OPERATION_FAILED; + } return STORAGE_ERROR_NONE; } @@ -235,6 +246,8 @@ API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb ca API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback) { const struct storage_ops *st; + struct storage_cb_info info; + int ret; dd_list *elem; if (!callback) { @@ -247,6 +260,16 @@ API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb if (st->storage_id == storage_id) return STORAGE_ERROR_NONE; + /* external storage */ + info.id = storage_id; + info.state_cb = callback; + + ret = storage_ext_unregister_cb(STORAGE_CALLBACK_STATE, &info); + if (ret < 0) { + _E("Failed to unregister callback : id(%d)", storage_id); + return STORAGE_ERROR_OPERATION_FAILED; + } + return STORAGE_ERROR_NONE; } -- 2.7.4 From f417cc7beddef2029c733c1a524eb823134fc28c Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:46:24 +0900 Subject: [PATCH 10/16] external: add function to get root path - External storages are handled by deviced, and deviced knows the information about root paths of storages. Thus dbus method from deviced is used to get root path information. Change-Id: I5ca86c1c9280bacc78d7f07fc55617ac9c397bb4 Signed-off-by: Taeyoung Kim --- src/storage-external-dbus.c | 27 +++++++++++++++++++++++++++ src/storage-external-dbus.h | 2 ++ src/storage-external.c | 30 +++++++++++++++++++++++++++++- src/storage-external.h | 1 + src/storage.c | 15 ++++++++++++++- 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/storage-external-dbus.c b/src/storage-external-dbus.c index 2c63d76..e4f4c49 100755 --- a/src/storage-external-dbus.c +++ b/src/storage-external-dbus.c @@ -444,3 +444,30 @@ void storage_ext_unregister_device_change(storage_ext_changed_cb func) free(callback); } } + +int storage_ext_get_device_info(int storage_id, storage_ext_device *info) +{ + GVariant *result; + + result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME, + STORAGE_EXT_PATH_MANAGER, + STORAGE_EXT_IFACE_MANAGER, + "GetDeviceInfoByID", + g_variant_new("(i)", storage_id)); + if (!result) { + _E("There is no storage with the storage id (%d)", storage_id); + return -ENODEV; + } + + g_variant_get(result, "(issssssisibii)", + &info->type, &info->devnode, &info->syspath, + &info->fs_usage, &info->fs_type, + &info->fs_version, &info->fs_uuid, + &info->readonly, &info->mount_point, + &info->state, &info->primary, + &info->flags, &info->storage_id); + + g_variant_unref(result); + + return 0; +} diff --git a/src/storage-external-dbus.h b/src/storage-external-dbus.h index 98522d5..e9db898 100644 --- a/src/storage-external-dbus.h +++ b/src/storage-external-dbus.h @@ -82,4 +82,6 @@ int storage_ext_get_list(dd_list **list); int storage_ext_register_device_change(storage_ext_changed_cb func, void *data); void storage_ext_unregister_device_change(storage_ext_changed_cb func); +int storage_ext_get_device_info(int storage_id, storage_ext_device *info); + #endif /* __STORAGE_EXTERNAL_DBUS_H__ */ diff --git a/src/storage-external.c b/src/storage-external.c index 6308c3b..63d564a 100755 --- a/src/storage-external.c +++ b/src/storage-external.c @@ -191,4 +191,32 @@ int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info storage_ext_unregister_device_change(storage_ext_state_changed); return 0; -} \ No newline at end of file +} + +int storage_ext_get_root(int storage_id, char *path, size_t len) +{ + storage_ext_device *dev; + int ret; + + if (storage_id < 0 || !path) + return -EINVAL; + + dev = calloc(1, sizeof(storage_ext_device)); + if (!dev) { + _E("calloc failed"); + return -ENOMEM; + } + + ret = storage_ext_get_device_info(storage_id, dev); + if (ret < 0) { + _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); + goto out; + } + + snprintf(path, len, "%s", dev->mount_point); + ret = 0; + +out: + storage_ext_release_device(&dev); + return ret; +} diff --git a/src/storage-external.h b/src/storage-external.h index cf5217b..a002c0b 100755 --- a/src/storage-external.h +++ b/src/storage-external.h @@ -24,5 +24,6 @@ int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data); int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info); int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info); +int storage_ext_get_root(int storage_id, char *path, size_t len); #endif /* __STORAGE_EXTERNAL_H__ */ diff --git a/src/storage.c b/src/storage.c index e6a54f7..275b8a9 100644 --- a/src/storage.c +++ b/src/storage.c @@ -82,6 +82,8 @@ 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 (!path || storage_id < 0) { _E("Invalid parameger"); @@ -100,7 +102,18 @@ API int storage_get_root_directory(int storage_id, char **path) return STORAGE_ERROR_NONE; } - /* TODO external storage */ + /* 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); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + *path = strdup(root); + if (!*path) { + _E("Failed to copy the root string : %d", errno); + return STORAGE_ERROR_OUT_OF_MEMORY; + } return STORAGE_ERROR_NONE; } -- 2.7.4 From dd4cb30512c937ca15e6899edadb4f5d1b672d0b Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:51:26 +0900 Subject: [PATCH 11/16] external: add function to get state of storages - Storage states are delivered from deviced. To get the information, dbus method is used. Change-Id: Ib6c03dae93e428cadd6f484cc5b84e2e12bf1050 Signed-off-by: Taeyoung Kim --- src/storage-external.c | 29 +++++++++++++++++++++++++++++ src/storage-external.h | 1 + src/storage.c | 10 +++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/storage-external.c b/src/storage-external.c index 63d564a..8fdde8c 100755 --- a/src/storage-external.c +++ b/src/storage-external.c @@ -220,3 +220,32 @@ out: storage_ext_release_device(&dev); return ret; } + +int storage_ext_get_state(int storage_id, storage_state_e *state) +{ + storage_ext_device *dev; + int ret; + + if (storage_id < 0 || !state) + return -EINVAL; + + dev = calloc(1, sizeof(storage_ext_device)); + if (!dev) { + _E("calloc failed"); + return -ENOMEM; + } + + ret = storage_ext_get_device_info(storage_id, dev); + if (ret < 0) { + _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); + goto out; + } + + ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, state); + if (ret < 0) + _E("Failed to get state of storage id (%d, ret:%d)", storage_id, ret); + +out: + storage_ext_release_device(&dev); + return ret; +} diff --git a/src/storage-external.h b/src/storage-external.h index a002c0b..a9046af 100755 --- a/src/storage-external.h +++ b/src/storage-external.h @@ -25,5 +25,6 @@ int storage_ext_foreach_device_list(storage_device_supported_cb callback, void * int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info); int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info); int storage_ext_get_root(int storage_id, char *path, size_t len); +int storage_ext_get_state(int storage_id, storage_state_e *state); #endif /* __STORAGE_EXTERNAL_H__ */ diff --git a/src/storage.c b/src/storage.c index 275b8a9..3e372a8 100644 --- a/src/storage.c +++ b/src/storage.c @@ -205,9 +205,11 @@ API int storage_get_type(int storage_id, storage_type_e *type) API int storage_get_state(int storage_id, storage_state_e *state) { const struct storage_ops *ops; + storage_state_e st; dd_list *elem; + int ret; - if (!state) { + if (!state || storage_id < 0) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -221,7 +223,13 @@ API int storage_get_state(int storage_id, storage_state_e *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); + return STORAGE_ERROR_OPERATION_FAILED; + } + *state = st; return STORAGE_ERROR_NONE; } -- 2.7.4 From 35f081ba2bbe21fb2423dcd85605332f91b82d56 Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:54:36 +0900 Subject: [PATCH 12/16] external: add function to get type - If a storage is not the one of internal storages, it is external storage. Change-Id: Idd2e4bac3c398c91ccb0f3b2891a143c9fa95100 Signed-off-by: Taeyoung Kim --- src/storage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/storage.c b/src/storage.c index 3e372a8..7f56f52 100644 --- a/src/storage.c +++ b/src/storage.c @@ -198,6 +198,7 @@ API int storage_get_type(int storage_id, storage_type_e *type) } /* external storage */ + *type = STORAGE_TYPE_EXTERNAL; return STORAGE_ERROR_NONE; } -- 2.7.4 From eebcfd39a817a7e2cb89ae2a1deb9f7beedd414b Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 15:57:17 +0900 Subject: [PATCH 13/16] external: add function to get specific directories - The specific directories are under the root path of external storage. - Ringtone path is not supported on external storages. Change-Id: Ie7e13d19a30dbe8e6b874eba98f498c81c5da0a0 Signed-off-by: Taeyoung Kim --- src/storage.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/storage.c b/src/storage.c index 7f56f52..41a3b3b 100644 --- a/src/storage.c +++ b/src/storage.c @@ -167,7 +167,18 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p } /* external storage */ - return STORAGE_ERROR_NONE; + if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) { + _E("Not support directory : id(%d) type(%d)", storage_id, type); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + 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); + return STORAGE_ERROR_OPERATION_FAILED; + } + + snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]); out: *path = strdup(temp); -- 2.7.4 From fe84aaecd0ea19e055dbfc1b6f7d671e0da07920 Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Thu, 28 Apr 2016 17:54:52 +0900 Subject: [PATCH 14/16] external: add functions to get storage size - The functions to get storage size of given path are added. - For the following apis, default path is set to primary sdcard. int storage_get_external_memory_size(struct statvfs *buf) int storage_get_external_memory_size64(struct statvfs *buf) Change-Id: I0cfdcf2496849520cf0ef00a3ee2c3a70ec3c06c Signed-off-by: Taeyoung Kim --- include/common.h | 4 +++ src/statvfs.c | 52 +++++++++++++++++++++++++------ src/storage-external.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/storage-external.h | 3 ++ src/storage.c | 4 +-- 5 files changed, 135 insertions(+), 12 deletions(-) diff --git a/include/common.h b/include/common.h index 7ff5ce9..ec9ca67 100644 --- a/include/common.h +++ b/include/common.h @@ -24,6 +24,7 @@ extern "C" { #endif #include "storage-expand.h" +#include #ifndef API #define API __attribute__ ((visibility("default"))) @@ -75,6 +76,9 @@ static void __DESTRUCTOR__ module_exit(void) \ void add_device(const struct storage_ops *st); void remove_device(const struct storage_ops *st); +int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf); +int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf); + #ifdef __cplusplus } #endif diff --git a/src/statvfs.c b/src/statvfs.c index 52e030c..6ccdb5e 100644 --- a/src/statvfs.c +++ b/src/statvfs.c @@ -29,6 +29,7 @@ #include "log.h" #include "common.h" +#include "storage-external.h" #define MEMORY_GIGABYTE_VALUE 1073741824 #define MEMORY_MEGABYTE_VALUE 1048576 @@ -305,7 +306,7 @@ API int storage_get_internal_memory_size64(struct statvfs *buf) return 0; } -static int mount_check(const char *path) +static int mount_check(char *path) { int ret = false; struct mntent *mnt; @@ -325,16 +326,16 @@ static int mount_check(const char *path) return ret; } -static const char *get_external_path(void) +static int get_external_path(char *path, size_t len) { - return tzplatform_mkpath(TZ_SYS_MEDIA, - EXTERNAL_MEMORY_NODE); + return storage_ext_get_primary_mmc_path(path, len); } -API int storage_get_external_memory_size(struct statvfs *buf) +int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf) { struct statvfs_32 temp; int ret; + char ext_path[32]; _D("storage_get_external_memory_size"); if (!buf) { @@ -342,12 +343,22 @@ API int storage_get_external_memory_size(struct statvfs *buf) return -EINVAL; } - if (!mount_check(get_external_path())) { + if (path) + snprintf(ext_path, sizeof(ext_path), "%s", path); + else { + ret = get_external_path(ext_path, sizeof(ext_path)); + if (ret < 0) { + _E("Failed to get external path(%d)", ret); + return ret; + } + } + + if (!mount_check(ext_path)) { memset(buf, 0, sizeof(struct statvfs_32)); return 0; } - ret = get_memory_size(get_external_path(), &temp); + ret = get_memory_size(ext_path, &temp); if (ret) { _E("fail to get memory size"); return -errno; @@ -357,9 +368,10 @@ API int storage_get_external_memory_size(struct statvfs *buf) return 0; } -API int storage_get_external_memory_size64(struct statvfs *buf) +int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf) { int ret; + char ext_path[32]; _D("storage_get_external_memory_size64"); if (!buf) { @@ -367,12 +379,22 @@ API int storage_get_external_memory_size64(struct statvfs *buf) return -EINVAL; } - if (!mount_check(get_external_path())) { + if (path) + snprintf(ext_path, sizeof(ext_path), "%s", path); + else { + ret = get_external_path(ext_path, sizeof(ext_path)); + if (ret < 0) { + _E("Failed to get external path(%d)", ret); + return ret; + } + } + + if (!mount_check(ext_path)) { memset(buf, 0, sizeof(struct statvfs)); return 0; } - ret = statvfs(get_external_path(), buf); + ret = statvfs(ext_path, buf); if (ret) { _E("fail to get memory size"); return -errno; @@ -380,3 +402,13 @@ API int storage_get_external_memory_size64(struct statvfs *buf) return 0; } + +API int storage_get_external_memory_size(struct statvfs *buf) +{ + return storage_get_external_memory_size_with_path(NULL, buf); +} + +API int storage_get_external_memory_size64(struct statvfs *buf) +{ + return storage_get_external_memory_size64_with_path(NULL, buf); +} diff --git a/src/storage-external.c b/src/storage-external.c index 8fdde8c..d6d6bca 100755 --- a/src/storage-external.c +++ b/src/storage-external.c @@ -60,6 +60,62 @@ static int storage_ext_get_dev_state(storage_ext_device *dev, } } +int storage_ext_get_space(int storage_id, + unsigned long long *total, unsigned long long *available) +{ + storage_state_e state; + struct statvfs s; + int ret; + unsigned long long t = 0, a = 0; + storage_ext_device *dev; + + if (storage_id < 0) + return -EINVAL; + + dev = calloc(1, sizeof(storage_ext_device)); + if (!dev) { + _E("calloc failed"); + return -ENOMEM; + } + + ret = storage_ext_get_device_info(storage_id, dev); + if (ret < 0) { + _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); + goto out; + } + + ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state); + if (ret < 0) { + _E("Failed to get state of storage (id:%d, ret:%d)", storage_id, ret); + goto out; + } + + if (state >= STORAGE_STATE_MOUNTED) { +#ifndef __USE_FILE_OFFSET64 + ret = storage_get_external_memory_size_with_path(dev->mount_point, &s); +#else + ret = storage_get_external_memory_size64_with_path(dev->mount_point, &s); +#endif + if (ret < 0) { + _E("Failed to get external memory size of (%s)(ret:%d)", dev->mount_point, ret); + goto out; + } + + t = (unsigned long long)s.f_frsize*s.f_blocks; + a = (unsigned long long)s.f_bsize*s.f_bavail; + } + + if (total) + *total = t; + if (available) + *available = a; + + ret = 0; +out: + storage_ext_release_device(&dev); + return ret; +} + int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data) { int ret; @@ -249,3 +305,31 @@ out: storage_ext_release_device(&dev); return ret; } + +int storage_ext_get_primary_mmc_path(char *path, size_t len) +{ + dd_list *list = NULL, *elem; + storage_ext_device *dev; + int ret; + + ret = storage_ext_get_list(&list); + if (ret < 0) { + _E("Failed to get external storage list from deviced (%d)", errno); + return ret; + } + + DD_LIST_FOREACH(list, elem, dev) { + if (dev->primary) { + snprintf(path, len, "%s", dev->mount_point); + ret = 0; + goto out; + } + } + + ret = -ENODEV; + +out: + if (list) + storage_ext_release_list(&list); + return ret; +} diff --git a/src/storage-external.h b/src/storage-external.h index a9046af..c7bd9fd 100755 --- a/src/storage-external.h +++ b/src/storage-external.h @@ -21,10 +21,13 @@ #include "common.h" #include "storage-external-dbus.h" +int storage_ext_get_space(int storage_id, + unsigned long long *total, unsigned long long *available); int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data); int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info); int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info); int storage_ext_get_root(int storage_id, char *path, size_t len); int storage_ext_get_state(int storage_id, storage_state_e *state); +int storage_ext_get_primary_mmc_path(char *path, size_t len); #endif /* __STORAGE_EXTERNAL_H__ */ diff --git a/src/storage.c b/src/storage.c index 41a3b3b..c71af5c 100644 --- a/src/storage.c +++ b/src/storage.c @@ -327,7 +327,7 @@ API int storage_get_total_space(int storage_id, unsigned long long *bytes) } /* external storage */ - ret = 0; + ret = storage_ext_get_space(storage_id, &total, NULL); out: if (ret < 0) { @@ -360,7 +360,7 @@ API int storage_get_available_space(int storage_id, unsigned long long *bytes) } /* external storage */ - ret = 0; + ret = storage_ext_get_space(storage_id,NULL, &avail); out: if (ret < 0) { -- 2.7.4 From 04377774d7c6e597fb572bf78a11746c882f419b Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Tue, 10 May 2016 19:36:12 +0900 Subject: [PATCH 15/16] storage id: return NOT_SUPPORTED if storage id is invalid - When storage id is invalid, the apis should return NOT_SUPPORTED. This is for backward compatibility. Change-Id: I5c54f0675072979dfc42242e5ce9b8efc438190d Signed-off-by: Taeyoung Kim --- src/storage-external.c | 12 +++++++++--- src/storage.c | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/storage-external.c b/src/storage-external.c index d6d6bca..bd9a8e1 100755 --- a/src/storage-external.c +++ b/src/storage-external.c @@ -70,7 +70,7 @@ int storage_ext_get_space(int storage_id, storage_ext_device *dev; if (storage_id < 0) - return -EINVAL; + return -ENOTSUP; dev = calloc(1, sizeof(storage_ext_device)); if (!dev) { @@ -254,7 +254,10 @@ int storage_ext_get_root(int storage_id, char *path, size_t len) storage_ext_device *dev; int ret; - if (storage_id < 0 || !path) + if (storage_id < 0) + return -ENOTSUP; + + if (!path) return -EINVAL; dev = calloc(1, sizeof(storage_ext_device)); @@ -282,7 +285,10 @@ int storage_ext_get_state(int storage_id, storage_state_e *state) storage_ext_device *dev; int ret; - if (storage_id < 0 || !state) + if (storage_id < 0) + return -ENOTSUP; + + if (!state) return -EINVAL; dev = calloc(1, sizeof(storage_ext_device)); diff --git a/src/storage.c b/src/storage.c index c71af5c..b98fded 100644 --- a/src/storage.c +++ b/src/storage.c @@ -85,7 +85,10 @@ API int storage_get_root_directory(int storage_id, char **path) char root[PATH_MAX]; int ret; - if (!path || storage_id < 0) { + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + + if (!path) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -128,7 +131,10 @@ API int storage_get_directory(int storage_id, storage_directory_e type, char **p dd_list *elem; bool found; - if (!path || storage_id < 0) { + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + + if (!path) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -195,7 +201,10 @@ API int storage_get_type(int storage_id, storage_type_e *type) const struct storage_ops *st; dd_list *elem; - if (!type || storage_id < 0) { + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + + if (!type) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -221,7 +230,10 @@ API int storage_get_state(int storage_id, storage_state_e *state) dd_list *elem; int ret; - if (!state || storage_id < 0) { + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + + if (!state) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -252,6 +264,9 @@ API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb ca int ret; dd_list *elem; + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + if (!callback) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; @@ -283,6 +298,9 @@ API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb int ret; dd_list *elem; + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + if (!callback) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; @@ -313,7 +331,10 @@ API int storage_get_total_space(int storage_id, unsigned long long *bytes) int ret; dd_list *elem; - if (!bytes || storage_id < 0) { + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + + if (!bytes) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; } @@ -332,6 +353,8 @@ API int storage_get_total_space(int storage_id, unsigned long long *bytes) out: if (ret < 0) { _E("Failed to get total memory : id(%d)", storage_id); + if (ret == -ENOTSUP) + return STORAGE_ERROR_NOT_SUPPORTED; return STORAGE_ERROR_OPERATION_FAILED; } @@ -346,6 +369,9 @@ API int storage_get_available_space(int storage_id, unsigned long long *bytes) int ret; dd_list *elem; + if (storage_id < 0) + return STORAGE_ERROR_NOT_SUPPORTED; + if (!bytes) { _E("Invalid parameger"); return STORAGE_ERROR_INVALID_PARAMETER; @@ -365,6 +391,8 @@ API int storage_get_available_space(int storage_id, unsigned long long *bytes) out: if (ret < 0) { _E("Failed to get available memory : id(%d)", storage_id); + if (ret == -ENOTSUP) + return STORAGE_ERROR_NOT_SUPPORTED; return STORAGE_ERROR_OPERATION_FAILED; } -- 2.7.4 From c075e0569c9f8059dbda2a7d8111143a35e7569d Mon Sep 17 00:00:00 2001 From: Taeyoung Kim Date: Tue, 10 May 2016 20:46:15 +0900 Subject: [PATCH 16/16] external: return storage size 0 if external storage does not exist - Previously, error was returned if external storage does not exist when getting storage size. But it is fixed to return size 0 for the backward compatibility. Change-Id: I84eca101a740729cc038f7e02b6db97536913ca9 Signed-off-by: Taeyoung Kim --- src/statvfs.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/statvfs.c b/src/statvfs.c index 6ccdb5e..dd038af 100644 --- a/src/statvfs.c +++ b/src/statvfs.c @@ -347,16 +347,16 @@ int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf) snprintf(ext_path, sizeof(ext_path), "%s", path); else { ret = get_external_path(ext_path, sizeof(ext_path)); + if (ret == -ENODEV) + goto out_nodev; if (ret < 0) { _E("Failed to get external path(%d)", ret); return ret; } } - if (!mount_check(ext_path)) { - memset(buf, 0, sizeof(struct statvfs_32)); - return 0; - } + if (!mount_check(ext_path)) + goto out_nodev; ret = get_memory_size(ext_path, &temp); if (ret) { @@ -366,6 +366,10 @@ int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf) memcpy(buf, &temp, sizeof(temp)); return 0; + +out_nodev: + memset(buf, 0, sizeof(struct statvfs_32)); + return 0; } int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf) @@ -383,16 +387,16 @@ int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf snprintf(ext_path, sizeof(ext_path), "%s", path); else { ret = get_external_path(ext_path, sizeof(ext_path)); + if (ret == -ENODEV) + goto out_nodev; if (ret < 0) { _E("Failed to get external path(%d)", ret); return ret; } } - if (!mount_check(ext_path)) { - memset(buf, 0, sizeof(struct statvfs)); - return 0; - } + if (!mount_check(ext_path)) + goto out_nodev; ret = statvfs(ext_path, buf); if (ret) { @@ -401,6 +405,10 @@ int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf } return 0; + +out_nodev: + memset(buf, 0, sizeof(struct statvfs)); + return 0; } API int storage_get_external_memory_size(struct statvfs *buf) -- 2.7.4