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()) {
87 _D("Block module is not enabled");
88 return STORAGE_ERROR_NONE;
91 ret_val = storage_ext_foreach_device_list(callback, user_data);
93 _E("Failed to iterate external devices (%d)", ret_val); //LCOV_EXCL_LINE
94 return STORAGE_ERROR_OPERATION_FAILED;
97 return STORAGE_ERROR_NONE;
100 API int storage_get_root_directory(int storage_id, char **path)
102 const struct storage_ops *st;
110 return STORAGE_ERROR_INVALID_PARAMETER;
113 _E("Invalid parameger");
114 return STORAGE_ERROR_INVALID_PARAMETER;
117 if (getuid() <= USER_UID_START)
120 /* internal storage */
121 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
122 if (st->storage_id != storage_id)
125 _E("Only apps and user session daemons are allowed "
126 "to use storage_get_root_directory(INTERNAL_STORAGE_ID, ...)");
127 return STORAGE_ERROR_INVALID_PARAMETER;
130 *path = strdup(st->root());
132 //LCOV_EXCL_START System Error
133 _E("Failed to copy the root string : %d", errno);
134 return STORAGE_ERROR_OUT_OF_MEMORY;
137 return STORAGE_ERROR_NONE;
140 /* external storage */
141 if (!storage_ext_is_supported()) {
142 _D("Block module is not enabled");
143 return STORAGE_ERROR_NOT_SUPPORTED;
146 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
148 _E("Failed to get root path of external storage(%d, %d", storage_id, ret_val); //LCOV_EXCL_LINE
149 if (ret_val == -ENODEV || ret_val == -EINVAL)
150 return STORAGE_ERROR_INVALID_PARAMETER;
151 else if (ret_val == -ENOMEM)
152 return STORAGE_ERROR_OUT_OF_MEMORY;
154 return STORAGE_ERROR_OPERATION_FAILED;
157 *path = strdup(root);
159 _E("Failed to copy the root string : %d", errno); //LCOV_EXCL_LINE System Error
160 return STORAGE_ERROR_OUT_OF_MEMORY;
163 return STORAGE_ERROR_NONE;
166 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
168 const struct storage_ops *st;
179 return STORAGE_ERROR_INVALID_PARAMETER;
182 _E("Invalid parameger");
183 return STORAGE_ERROR_INVALID_PARAMETER;
186 if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
187 _E("Invalid parameter");
188 return STORAGE_ERROR_INVALID_PARAMETER;
191 /* internal storage */
193 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
194 if (st->storage_id != storage_id)
200 if (getuid() <= USER_UID_START)
205 _E("Only apps and user session daemons are allowed "
206 "to use storage_get_root_directory(INTERNAL_STORAGE_ID, ...)");
208 return STORAGE_ERROR_INVALID_PARAMETER;
211 snprintf(root, sizeof(root), "%s", st->root());
212 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
213 temp2 = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR);
215 return STORAGE_ERROR_OPERATION_FAILED;
216 end = strrchr(temp2, '/');
219 snprintf(temp, PATH_MAX, "%s", temp2);
222 if ((ret_val = snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type])) > PATH_MAX - 1) {
223 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
224 return STORAGE_ERROR_OUT_OF_MEMORY;
231 /* external storage */
232 if (!storage_ext_is_supported()) {
233 _D("Block module is not enabled");
234 return STORAGE_ERROR_NOT_SUPPORTED;
237 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
238 _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
239 return STORAGE_ERROR_INVALID_PARAMETER;
242 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
244 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret_val); //LCOV_EXCL_LINE
245 if (ret_val == -ENODEV || ret_val == -EINVAL)
246 return STORAGE_ERROR_INVALID_PARAMETER;
247 else if (ret_val == -ENOMEM)
248 return STORAGE_ERROR_OUT_OF_MEMORY;
250 return STORAGE_ERROR_OPERATION_FAILED;
252 /* The operation is not decided */
254 return STORAGE_ERROR_INVALID_PARAMETER;
256 if ((ret_val = snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type])) > sizeof(temp) - 1) {
257 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
258 return STORAGE_ERROR_OUT_OF_MEMORY;
262 *path = strdup(temp);
264 _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
265 return STORAGE_ERROR_OUT_OF_MEMORY;
268 return STORAGE_ERROR_NONE;
271 API int storage_get_type(int storage_id, storage_type_e *type)
273 const struct storage_ops *st;
280 return STORAGE_ERROR_INVALID_PARAMETER;
283 _E("Invalid parameger");
284 return STORAGE_ERROR_INVALID_PARAMETER;
287 /* internal storage */
288 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
289 if (st->storage_id != storage_id)
292 return STORAGE_ERROR_NONE;
295 /* external storage */
296 if (!storage_ext_is_supported()) {
297 _D("Block module is not enabled");
298 return STORAGE_ERROR_NOT_SUPPORTED;
301 ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
303 _E("Failed to get type of external storage");
304 if (ret_val == -ENODEV || ret_val == -EINVAL)
305 return STORAGE_ERROR_INVALID_PARAMETER;
306 else if (ret_val == -ENOMEM)
307 return STORAGE_ERROR_OUT_OF_MEMORY;
309 return STORAGE_ERROR_OPERATION_FAILED;
312 *type = STORAGE_TYPE_EXTENDED_INTERNAL;
314 *type = STORAGE_TYPE_EXTERNAL;
316 return STORAGE_ERROR_NONE;
319 API int storage_get_state(int storage_id, storage_state_e *state)
321 const struct storage_ops *ops;
327 return STORAGE_ERROR_INVALID_PARAMETER;
330 _E("Invalid parameger");
331 return STORAGE_ERROR_INVALID_PARAMETER;
334 /* internal storage */
335 SYS_G_LIST_FOREACH(st_int_head, elem, ops) {
336 if (ops->storage_id != storage_id)
338 *state = ops->get_state();
339 return STORAGE_ERROR_NONE;
342 /* external storage */
343 if (!storage_ext_is_supported()) {
344 _D("Block module is not enabled");
345 return STORAGE_ERROR_NOT_SUPPORTED;
348 ret_val = storage_ext_get_state(storage_id, &st);
350 _E("Failed to get state (storage id(%d), ret_val(%d))", storage_id, ret_val); //LCOV_EXCL_LINE
351 if (ret_val == -ENODEV || ret_val == -EINVAL)
352 return STORAGE_ERROR_INVALID_PARAMETER;
353 else if (ret_val == -ENOMEM)
354 return STORAGE_ERROR_OUT_OF_MEMORY;
356 return STORAGE_ERROR_OPERATION_FAILED;
360 return STORAGE_ERROR_NONE;
363 //LCOV_EXCL_START Not called Callback
364 static void compat_cb(int storage_id,
365 storage_dev_e dev, storage_state_e state,
366 const char *fstype, const char *fsuuid, const char *mountpath,
367 bool primary, int flags, void *user_data)
369 struct compat_cb_info* ccb_info;
372 if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
373 SYS_G_LIST_FOREACH(compat_cb_list, elem, ccb_info)
374 ccb_info->user_cb(storage_id, state, ccb_info->user_data);
378 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
380 const struct storage_ops *st;
381 struct storage_cb_info info;
385 struct compat_cb_info* ccb_info;
386 static int compat_cb_init = 0;
389 return STORAGE_ERROR_INVALID_PARAMETER;
392 _E("Invalid parameger");
393 return STORAGE_ERROR_INVALID_PARAMETER;
396 /* For backward compatability */
397 if (storage_id == STORAGE_TYPE_EXTERNAL) {
398 if (!storage_ext_is_supported()) {
399 _D("Block module is not enabled");
400 return STORAGE_ERROR_NOT_SUPPORTED;
403 if (!compat_cb_init) {
404 ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
405 if (ret == STORAGE_ERROR_NONE)
411 ccb_info = malloc(sizeof(struct compat_cb_info));
412 if (ccb_info == NULL)
413 return STORAGE_ERROR_OPERATION_FAILED;
414 ccb_info->user_cb = callback;
415 ccb_info->user_data = user_data;
416 SYS_G_LIST_APPEND(compat_cb_list, ccb_info);
418 return STORAGE_ERROR_NONE;
421 /* Internal storage does not support registering changed callback */
422 SYS_G_LIST_FOREACH(st_int_head, elem, st)
423 if (st->storage_id == storage_id)
424 return STORAGE_ERROR_NONE;
426 /* external storage */
427 if (!storage_ext_is_supported()) {
428 _D("Block module is not enabled");
429 return STORAGE_ERROR_NOT_SUPPORTED;
432 info.id = storage_id;
433 info.state_cb = callback;
434 info.user_data = user_data;
436 ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
438 _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
439 return STORAGE_ERROR_OPERATION_FAILED;
442 return STORAGE_ERROR_NONE;
445 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
447 const struct storage_ops *st;
448 struct storage_cb_info info;
453 return STORAGE_ERROR_INVALID_PARAMETER;
456 _E("Invalid parameger");
457 return STORAGE_ERROR_INVALID_PARAMETER;
460 /* For backward compatability */
461 if (storage_id == STORAGE_TYPE_EXTERNAL) {
462 if (!storage_ext_is_supported()) {
463 _D("Block module is not enabled");
464 return STORAGE_ERROR_NOT_SUPPORTED;
468 struct compat_cb_info* ccb_info;
470 SYS_G_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
471 if (ccb_info->user_cb == callback) {
472 SYS_G_LIST_REMOVE(compat_cb_list, ccb_info);
474 return STORAGE_ERROR_NONE;
477 return STORAGE_ERROR_OPERATION_FAILED;
480 /* Internal storage does not support registering changed callback */
481 SYS_G_LIST_FOREACH(st_int_head, elem, st)
482 if (st->storage_id == storage_id)
483 return STORAGE_ERROR_NONE;
485 /* external storage */
486 if (!storage_ext_is_supported()) {
487 _D("Block module is not enabled");
488 return STORAGE_ERROR_NOT_SUPPORTED;
491 info.id = storage_id;
492 info.state_cb = callback;
494 ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
496 _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
497 return STORAGE_ERROR_OPERATION_FAILED;
500 return STORAGE_ERROR_NONE;
503 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
505 const struct storage_ops *st;
506 unsigned long long total;
511 return STORAGE_ERROR_INVALID_PARAMETER;
514 _E("Invalid parameger");
515 return STORAGE_ERROR_INVALID_PARAMETER;
518 /* internal storage */
519 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
520 if (st->storage_id != storage_id)
522 ret_val = st->get_space(&total, NULL);
526 /* external storage */
527 if (!storage_ext_is_supported()) {
528 _D("Block module is not enabled");
529 return STORAGE_ERROR_NOT_SUPPORTED;
532 ret_val = storage_ext_get_space(storage_id, &total, NULL);
536 _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
537 if (ret_val == -ENODEV || ret_val == -EINVAL)
538 return STORAGE_ERROR_INVALID_PARAMETER;
539 else if (ret_val == -ENOMEM)
540 return STORAGE_ERROR_OUT_OF_MEMORY;
542 return STORAGE_ERROR_OPERATION_FAILED;
546 return STORAGE_ERROR_NONE;
549 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
551 const struct storage_ops *st;
552 unsigned long long avail;
557 return STORAGE_ERROR_INVALID_PARAMETER;
560 _E("Invalid parameger");
561 return STORAGE_ERROR_INVALID_PARAMETER;
564 /* internal storage */
565 SYS_G_LIST_FOREACH(st_int_head, elem, st) {
566 if (st->storage_id != storage_id)
568 ret_val = st->get_space(NULL, &avail);
572 /* external storage */
573 if (!storage_ext_is_supported()) {
574 _D("Block module is not enabled");
575 return STORAGE_ERROR_NOT_SUPPORTED;
578 ret_val = storage_ext_get_space(storage_id, NULL, &avail);
582 _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
583 if (ret_val == -ENODEV || ret_val == -EINVAL)
584 return STORAGE_ERROR_INVALID_PARAMETER;
585 else if (ret_val == -ENOMEM)
586 return STORAGE_ERROR_OUT_OF_MEMORY;
588 return STORAGE_ERROR_OPERATION_FAILED;
592 return STORAGE_ERROR_NONE;
595 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
598 struct storage_cb_info info;
600 if (type == STORAGE_TYPE_INTERNAL) {
601 _E("Internal storage is not supported");
602 return STORAGE_ERROR_INVALID_PARAMETER;
605 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
606 _E("Invalid type (%d)", type);
607 return STORAGE_ERROR_INVALID_PARAMETER;
611 _E("Callback is NULL");
612 return STORAGE_ERROR_INVALID_PARAMETER;
615 if (!storage_ext_is_supported()) {
616 _E("Block module is not enabled");
617 return STORAGE_ERROR_NOT_SUPPORTED;
620 /* external storage */
622 info.type_cb = callback;
623 info.user_data = user_data;
625 ret_val = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
627 _E("Failed to register storage callback(ret:%d)", ret_val); //LCOV_EXCL_LINE
628 return STORAGE_ERROR_OPERATION_FAILED;
631 return STORAGE_ERROR_NONE;
634 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
636 struct storage_cb_info info;
639 if (type == STORAGE_TYPE_INTERNAL) {
640 _E("Internal storage is not supported");
641 return STORAGE_ERROR_INVALID_PARAMETER;
644 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
645 _E("Invalid type (%d)", type);
646 return STORAGE_ERROR_INVALID_PARAMETER;
650 _E("Callback is NULL");
651 return STORAGE_ERROR_INVALID_PARAMETER;
654 if (!storage_ext_is_supported()) {
655 _E("Block module is not enabled");
656 return STORAGE_ERROR_NOT_SUPPORTED;
659 /* external storage */
661 info.type_cb = callback;
663 ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
665 _E("Failed to unregister storage callback(ret:%d)", ret_val); //LCOV_EXCL_LINE
666 return STORAGE_ERROR_OPERATION_FAILED;
669 return STORAGE_ERROR_NONE;
672 API int storage_get_type_dev(int storage_id, storage_type_e *type, storage_dev_e *dev)
674 storage_ext_device *ext_dev;
677 if (storage_id < 0 || !type || !dev) {
678 _E("Invalid parameter");
679 return STORAGE_ERROR_INVALID_PARAMETER;
682 ret = storage_get_type(storage_id, type);
683 if (ret != STORAGE_ERROR_NONE) {
684 _E("Failed to get storage type: %d", ret);
687 if (*type == STORAGE_TYPE_INTERNAL || *type == STORAGE_TYPE_EXTENDED_INTERNAL)
688 return STORAGE_ERROR_INVALID_PARAMETER;
690 if (!storage_ext_is_supported()) {
691 _D("Block module is not enabled");
692 return STORAGE_ERROR_NOT_SUPPORTED;
695 ext_dev = calloc(1, sizeof(storage_ext_device));
697 //LCOV_EXCL_START System Error
699 return STORAGE_ERROR_OUT_OF_MEMORY;
703 ret = storage_ext_get_device_info(storage_id, ext_dev);
705 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
706 if (ret == -ENODEV) {
707 ret = STORAGE_ERROR_INVALID_PARAMETER;
710 ret = STORAGE_ERROR_OPERATION_FAILED;
714 if (ext_dev->type == STORAGE_EXT_SCSI)
715 *dev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
716 else if (ext_dev->type == STORAGE_EXT_MMC)
717 *dev = STORAGE_DEV_EXT_SDCARD;
718 ret = STORAGE_ERROR_NONE;
719 _I("type: %d(internal:0, external:1) dev: %d(sdcard: 1001, usb: 1002)", *type, *dev);
722 storage_ext_release_device(&ext_dev);
726 static void __CONSTRUCTOR__ init(void)
732 for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
733 tmp = tzplatform_getenv(tz_id[i]);
735 token = rindex(tmp, '/');
738 dir_path[i] = strdup(token);