2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <tzplatform_config.h>
24 #include <libsyscommon/list.h>
28 #include "storage-external.h"
30 const char *dir_path[STORAGE_DIRECTORY_MAX];
32 const int tz_id[STORAGE_DIRECTORY_MAX] = {
33 [STORAGE_DIRECTORY_IMAGES] = TZ_USER_IMAGES,
34 [STORAGE_DIRECTORY_SOUNDS] = TZ_USER_SOUNDS,
35 [STORAGE_DIRECTORY_VIDEOS] = TZ_USER_VIDEOS,
36 [STORAGE_DIRECTORY_CAMERA] = TZ_USER_CAMERA,
37 [STORAGE_DIRECTORY_DOWNLOADS] = TZ_USER_DOWNLOADS,
38 [STORAGE_DIRECTORY_MUSIC] = TZ_USER_MUSIC,
39 [STORAGE_DIRECTORY_DOCUMENTS] = TZ_USER_DOCUMENTS,
40 [STORAGE_DIRECTORY_OTHERS] = TZ_USER_OTHERS,
43 static GList *st_int_head; /* Internal storage list */
45 static GList *compat_cb_list;
46 struct compat_cb_info {
47 storage_state_changed_cb user_cb;
51 void add_device(const struct storage_ops *st)
53 SYS_G_LIST_APPEND(st_int_head, st);
56 void remove_device(const struct storage_ops *st)
58 SYS_G_LIST_REMOVE(st_int_head, st);
61 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
63 const struct storage_ops *st;
69 _E("Invalid parameter");
70 return STORAGE_ERROR_INVALID_PARAMETER;
73 if (getuid() <= USER_UID_START)
76 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
78 ret_val = callback(st->storage_id, st->type, st->get_state(),
79 st->root(), user_data);
80 /* if the return value is false, will be stop to iterate */
86 if (!storage_ext_is_supported()) {
88 _D("Block module is not enabled");
89 return STORAGE_ERROR_NONE;
93 ret_val = storage_ext_foreach_device_list(callback, user_data);
95 _E("Failed to iterate external devices (%d)", ret_val); //LCOV_EXCL_LINE
96 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
99 return STORAGE_ERROR_NONE;
102 API int storage_get_root_directory(int storage_id, char **path)
104 const struct storage_ops *st;
112 return STORAGE_ERROR_INVALID_PARAMETER;
115 _E("Invalid parameger");
116 return STORAGE_ERROR_INVALID_PARAMETER;
119 if (getuid() <= USER_UID_START)
122 /* internal storage */
123 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
124 if (st->storage_id != storage_id)
127 _E("Only apps and user session daemons are allowed "
128 "to use storage_get_root_directory(INTERNAL_STORAGE_ID, ...)");
129 return STORAGE_ERROR_INVALID_PARAMETER;
132 *path = strdup(st->root());
134 //LCOV_EXCL_START System Error
135 _E("Failed to copy the root string : %d", errno);
136 return STORAGE_ERROR_OUT_OF_MEMORY;
139 return STORAGE_ERROR_NONE;
142 /* external storage */
143 if (!storage_ext_is_supported()) {
145 _D("Block module is not enabled");
146 return STORAGE_ERROR_NOT_SUPPORTED;
150 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
152 _E("Failed to get root path of external storage(%d, %d", storage_id, ret_val);
153 if (ret_val == -ENODEV || ret_val == -EINVAL)
154 return STORAGE_ERROR_INVALID_PARAMETER;
156 else if (ret_val == -ENOMEM)
157 return STORAGE_ERROR_OUT_OF_MEMORY;
159 return STORAGE_ERROR_OPERATION_FAILED;
163 *path = strdup(root);
165 //LCOV_EXCL_START System error
166 _E("Failed to copy the root string : %d", errno);
167 return STORAGE_ERROR_OUT_OF_MEMORY;
171 return STORAGE_ERROR_NONE;
174 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
176 const struct storage_ops *st;
187 return STORAGE_ERROR_INVALID_PARAMETER;
190 _E("Invalid parameger");
191 return STORAGE_ERROR_INVALID_PARAMETER;
194 if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
195 _E("Invalid parameter");
196 return STORAGE_ERROR_INVALID_PARAMETER;
199 /* internal storage */
201 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
202 if (st->storage_id != storage_id)
208 if (getuid() <= USER_UID_START)
213 _E("Only apps and user session daemons are allowed "
214 "to use storage_get_root_directory(INTERNAL_STORAGE_ID, ...)");
216 return STORAGE_ERROR_INVALID_PARAMETER;
219 snprintf(root, sizeof(root), "%s", st->root());
220 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
221 temp2 = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR);
223 return STORAGE_ERROR_OPERATION_FAILED;
224 end = strrchr(temp2, '/');
227 snprintf(temp, PATH_MAX, "%s", temp2);
230 if ((ret_val = snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type])) > PATH_MAX - 1) {
232 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
233 return STORAGE_ERROR_OUT_OF_MEMORY;
241 /* external storage */
242 if (!storage_ext_is_supported()) {
244 _D("Block module is not enabled");
245 return STORAGE_ERROR_NOT_SUPPORTED;
249 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
250 _E("Not support directory : id(%d) type(%d)", storage_id, type);
251 return STORAGE_ERROR_INVALID_PARAMETER;
254 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
256 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret_val);
257 if (ret_val == -ENODEV || ret_val == -EINVAL)
258 return STORAGE_ERROR_INVALID_PARAMETER;
260 else if (ret_val == -ENOMEM)
261 return STORAGE_ERROR_OUT_OF_MEMORY;
263 return STORAGE_ERROR_OPERATION_FAILED;
266 /* The operation is not decided */
268 return STORAGE_ERROR_INVALID_PARAMETER;
270 if ((ret_val = snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type])) > sizeof(temp) - 1) {
272 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
273 return STORAGE_ERROR_OUT_OF_MEMORY;
278 *path = strdup(temp);
280 //LCOV_EXCL_START System error
281 _E("Failed to copy the directory(%d) string : %d", type, errno);
282 return STORAGE_ERROR_OUT_OF_MEMORY;
286 return STORAGE_ERROR_NONE;
289 API int storage_get_type(int storage_id, storage_type_e *type)
291 const struct storage_ops *st;
298 return STORAGE_ERROR_INVALID_PARAMETER;
301 _E("Invalid parameger");
302 return STORAGE_ERROR_INVALID_PARAMETER;
305 /* internal storage */
306 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
307 if (st->storage_id != storage_id)
310 return STORAGE_ERROR_NONE;
313 /* external storage */
314 if (!storage_ext_is_supported()) {
316 _D("Block module is not enabled");
317 return STORAGE_ERROR_NOT_SUPPORTED;
321 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
323 _E("Failed to get type of external storage");
324 if (ret_val == -ENODEV || ret_val == -EINVAL)
325 return STORAGE_ERROR_INVALID_PARAMETER;
327 else if (ret_val == -ENOMEM)
328 return STORAGE_ERROR_OUT_OF_MEMORY;
330 return STORAGE_ERROR_OPERATION_FAILED;
334 *type = STORAGE_TYPE_EXTENDED_INTERNAL;
336 *type = STORAGE_TYPE_EXTERNAL;
338 return STORAGE_ERROR_NONE;
341 API int storage_get_state(int storage_id, storage_state_e *state)
343 const struct storage_ops *ops;
349 return STORAGE_ERROR_INVALID_PARAMETER;
352 _E("Invalid parameger");
353 return STORAGE_ERROR_INVALID_PARAMETER;
356 /* internal storage */
357 SYS_G_LIST_FOREACH(st_int_head, elem, ops) {
358 if (ops->storage_id != storage_id)
360 *state = ops->get_state();
361 return STORAGE_ERROR_NONE;
364 /* external storage */
365 if (!storage_ext_is_supported()) {
367 _D("Block module is not enabled");
368 return STORAGE_ERROR_NOT_SUPPORTED;
372 ret_val = storage_ext_get_state(storage_id, &st);
374 _E("Failed to get state (storage id(%d), ret_val(%d))", storage_id, ret_val);
375 if (ret_val == -ENODEV || ret_val == -EINVAL)
376 return STORAGE_ERROR_INVALID_PARAMETER;
378 else if (ret_val == -ENOMEM)
379 return STORAGE_ERROR_OUT_OF_MEMORY;
381 return STORAGE_ERROR_OPERATION_FAILED;
386 return STORAGE_ERROR_NONE;
389 //LCOV_EXCL_START Not called Callback
390 static void compat_cb(int storage_id,
391 storage_dev_e dev, storage_state_e state,
392 const char *fstype, const char *fsuuid, const char *mountpath,
393 bool primary, int flags, void *user_data)
395 struct compat_cb_info* ccb_info;
398 if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
399 SYS_G_LIST_FOREACH(compat_cb_list, elem, ccb_info)
400 ccb_info->user_cb(storage_id, state, ccb_info->user_data);
404 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
406 const struct storage_ops *st;
407 struct storage_cb_info info;
411 struct compat_cb_info* ccb_info;
412 static int compat_cb_init = 0;
415 return STORAGE_ERROR_INVALID_PARAMETER;
418 _E("Invalid parameger");
419 return STORAGE_ERROR_INVALID_PARAMETER;
423 * storage_id is different from storage type, but this code handles
424 * incorrect storage_id usage (pass storage type instead of storage id)
425 * For backward compatability.
427 if (storage_id == STORAGE_TYPE_EXTERNAL) {
428 if (!storage_ext_is_supported()) {
430 _D("Block module is not enabled");
431 return STORAGE_ERROR_NOT_SUPPORTED;
435 if (!compat_cb_init) {
436 ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
437 if (ret == STORAGE_ERROR_NONE)
443 ccb_info = malloc(sizeof(struct compat_cb_info));
444 if (ccb_info == NULL)
445 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
446 ccb_info->user_cb = callback;
447 ccb_info->user_data = user_data;
448 SYS_G_LIST_APPEND(compat_cb_list, ccb_info);
450 return STORAGE_ERROR_NONE;
453 /* Internal storage does not support registering changed callback */
454 SYS_G_LIST_FOREACH(st_int_head, elem, st)
455 if (st->storage_id == storage_id)
456 return STORAGE_ERROR_NONE;
458 /* external storage */
459 if (!storage_ext_is_supported()) {
461 _D("Block module is not enabled");
462 return STORAGE_ERROR_NOT_SUPPORTED;
466 info.id = storage_id;
467 info.state_cb = callback;
468 info.user_data = user_data;
470 ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
473 _E("Failed to register callback : id(%d)", storage_id);
474 return STORAGE_ERROR_OPERATION_FAILED;
478 return STORAGE_ERROR_NONE;
481 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
483 const struct storage_ops *st;
484 struct storage_cb_info info;
489 return STORAGE_ERROR_INVALID_PARAMETER;
492 _E("Invalid parameger");
493 return STORAGE_ERROR_INVALID_PARAMETER;
497 * storage_id is different from storage type, but this code handles
498 * incorrect storage_id usage (pass storage type instead of storage id)
499 * For backward compatability.
501 if (storage_id == STORAGE_TYPE_EXTERNAL) {
502 if (!storage_ext_is_supported()) {
504 _D("Block module is not enabled");
505 return STORAGE_ERROR_NOT_SUPPORTED;
510 struct compat_cb_info* ccb_info;
512 SYS_G_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
513 if (ccb_info->user_cb == callback) {
514 SYS_G_LIST_REMOVE(compat_cb_list, ccb_info);
516 return STORAGE_ERROR_NONE;
520 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
523 /* Internal storage does not support registering changed callback */
524 SYS_G_LIST_FOREACH(st_int_head, elem, st)
525 if (st->storage_id == storage_id)
526 return STORAGE_ERROR_NONE;
528 /* external storage */
529 if (!storage_ext_is_supported()) {
531 _D("Block module is not enabled");
532 return STORAGE_ERROR_NOT_SUPPORTED;
536 info.id = storage_id;
537 info.state_cb = callback;
539 ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
542 _E("Failed to unregister callback : id(%d)", storage_id);
543 return STORAGE_ERROR_OPERATION_FAILED;
547 return STORAGE_ERROR_NONE;
550 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
552 const struct storage_ops *st;
553 unsigned long long total;
558 return STORAGE_ERROR_INVALID_PARAMETER;
561 _E("Invalid parameger");
562 return STORAGE_ERROR_INVALID_PARAMETER;
565 /* internal storage */
566 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
567 if (st->storage_id != storage_id)
569 ret_val = st->get_space(&total, NULL);
573 /* external storage */
574 if (!storage_ext_is_supported()) {
576 _D("Block module is not enabled");
577 return STORAGE_ERROR_NOT_SUPPORTED;
581 ret_val = storage_ext_get_space(storage_id, &total, NULL);
585 _E("Failed to get total memory : id(%d)", storage_id);
586 if (ret_val == -ENODEV || ret_val == -EINVAL)
587 return STORAGE_ERROR_INVALID_PARAMETER;
589 else if (ret_val == -ENOMEM)
590 return STORAGE_ERROR_OUT_OF_MEMORY;
592 return STORAGE_ERROR_OPERATION_FAILED;
597 return STORAGE_ERROR_NONE;
600 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
602 const struct storage_ops *st;
603 unsigned long long avail;
608 return STORAGE_ERROR_INVALID_PARAMETER;
611 _E("Invalid parameger");
612 return STORAGE_ERROR_INVALID_PARAMETER;
615 /* internal storage */
616 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
617 if (st->storage_id != storage_id)
619 ret_val = st->get_space(NULL, &avail);
623 /* external storage */
624 if (!storage_ext_is_supported()) {
626 _D("Block module is not enabled");
627 return STORAGE_ERROR_NOT_SUPPORTED;
631 ret_val = storage_ext_get_space(storage_id, NULL, &avail);
635 _E("Failed to get available memory : id(%d)", storage_id);
636 if (ret_val == -ENODEV || ret_val == -EINVAL)
637 return STORAGE_ERROR_INVALID_PARAMETER;
639 else if (ret_val == -ENOMEM)
640 return STORAGE_ERROR_OUT_OF_MEMORY;
642 return STORAGE_ERROR_OPERATION_FAILED;
647 return STORAGE_ERROR_NONE;
650 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
653 struct storage_cb_info info;
655 if (type == STORAGE_TYPE_INTERNAL) {
656 _E("Internal storage is not supported");
657 return STORAGE_ERROR_INVALID_PARAMETER;
660 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
661 _E("Invalid type (%d)", type);
662 return STORAGE_ERROR_INVALID_PARAMETER;
666 _E("Callback is NULL");
667 return STORAGE_ERROR_INVALID_PARAMETER;
670 if (!storage_ext_is_supported()) {
672 _E("Block module is not enabled");
673 return STORAGE_ERROR_NOT_SUPPORTED;
677 /* external storage */
679 info.type_cb = callback;
680 info.user_data = user_data;
682 ret_val = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
685 _E("Failed to register storage callback(ret:%d)", ret_val);
686 return STORAGE_ERROR_OPERATION_FAILED;
690 return STORAGE_ERROR_NONE;
693 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
695 struct storage_cb_info info;
698 if (type == STORAGE_TYPE_INTERNAL) {
699 _E("Internal storage is not supported");
700 return STORAGE_ERROR_INVALID_PARAMETER;
703 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
704 _E("Invalid type (%d)", type);
705 return STORAGE_ERROR_INVALID_PARAMETER;
709 _E("Callback is NULL");
710 return STORAGE_ERROR_INVALID_PARAMETER;
713 if (!storage_ext_is_supported()) {
715 _E("Block module is not enabled");
716 return STORAGE_ERROR_NOT_SUPPORTED;
720 /* external storage */
722 info.type_cb = callback;
724 ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
727 _E("Failed to unregister storage callback(ret:%d)", ret_val);
728 return STORAGE_ERROR_OPERATION_FAILED;
732 return STORAGE_ERROR_NONE;
735 API int storage_get_type_dev(int storage_id, storage_type_e *type, storage_dev_e *dev)
737 storage_ext_device *ext_dev;
740 if (storage_id < 0 || !type || !dev) {
741 _E("Invalid parameter");
742 return STORAGE_ERROR_INVALID_PARAMETER;
745 ret = storage_get_type(storage_id, type);
746 if (ret != STORAGE_ERROR_NONE) {
748 _E("Failed to get storage type: %d", ret);
752 if (*type == STORAGE_TYPE_INTERNAL || *type == STORAGE_TYPE_EXTENDED_INTERNAL)
753 return STORAGE_ERROR_INVALID_PARAMETER;
755 if (!storage_ext_is_supported()) {
757 _D("Block module is not enabled");
758 return STORAGE_ERROR_NOT_SUPPORTED;
762 ext_dev = calloc(1, sizeof(storage_ext_device));
764 //LCOV_EXCL_START System Error
766 return STORAGE_ERROR_OUT_OF_MEMORY;
770 ret = storage_ext_get_device_info(storage_id, ext_dev);
772 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
773 if (ret == -ENODEV) {
774 ret = STORAGE_ERROR_INVALID_PARAMETER;
778 ret = STORAGE_ERROR_OPERATION_FAILED;
783 if (ext_dev->type == STORAGE_EXT_SCSI)
784 *dev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
785 else if (ext_dev->type == STORAGE_EXT_MMC)
786 *dev = STORAGE_DEV_EXT_SDCARD;
787 ret = STORAGE_ERROR_NONE;
788 _I("type: %d(internal:0, external:1) dev: %d(sdcard: 1001, usb: 1002)", *type, *dev);
791 storage_ext_release_device(&ext_dev);
795 static void __CONSTRUCTOR__ init(void)
801 for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
802 tmp = tzplatform_getenv(tz_id[i]);
804 token = rindex(tmp, '/');
807 dir_path[i] = strdup(token);