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>
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 dd_list *st_int_head; /* Internal storage list */
45 static dd_list *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 DD_LIST_APPEND(st_int_head, st);
56 void remove_device(const struct storage_ops *st)
58 DD_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 DD_LIST_FOREACH(st_int_head, elem, st) {
78 ret = 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 = storage_ext_foreach_device_list(callback, user_data);
93 _E("Failed to iterate external devices (%d)", ret); //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 DD_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 = 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); //LCOV_EXCL_LINE
149 if (ret == -ENODEV || ret == -EINVAL)
150 return STORAGE_ERROR_INVALID_PARAMETER;
151 else if (ret == -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 DD_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 snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
227 /* external storage */
228 if (!storage_ext_is_supported()) {
229 _D("Block module is not enabled");
230 return STORAGE_ERROR_NOT_SUPPORTED;
233 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
234 _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
235 return STORAGE_ERROR_INVALID_PARAMETER;
238 ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
240 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
241 if (ret == -ENODEV || ret == -EINVAL)
242 return STORAGE_ERROR_INVALID_PARAMETER;
243 else if (ret == -ENOMEM)
244 return STORAGE_ERROR_OUT_OF_MEMORY;
246 return STORAGE_ERROR_OPERATION_FAILED;
248 /* The operation is not decided */
250 return STORAGE_ERROR_INVALID_PARAMETER;
252 snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
255 *path = strdup(temp);
257 _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
258 return STORAGE_ERROR_OUT_OF_MEMORY;
261 return STORAGE_ERROR_NONE;
264 API int storage_get_type(int storage_id, storage_type_e *type)
266 const struct storage_ops *st;
273 return STORAGE_ERROR_INVALID_PARAMETER;
276 _E("Invalid parameger");
277 return STORAGE_ERROR_INVALID_PARAMETER;
280 /* internal storage */
281 DD_LIST_FOREACH(st_int_head, elem, st) {
282 if (st->storage_id != storage_id)
285 return STORAGE_ERROR_NONE;
288 /* external storage */
289 if (!storage_ext_is_supported()) {
290 _D("Block module is not enabled");
291 return STORAGE_ERROR_NOT_SUPPORTED;
294 ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
296 _E("Failed to get type of external storage");
297 if (ret == -ENODEV || ret == -EINVAL)
298 return STORAGE_ERROR_INVALID_PARAMETER;
299 else if (ret == -ENOMEM)
300 return STORAGE_ERROR_OUT_OF_MEMORY;
302 return STORAGE_ERROR_OPERATION_FAILED;
305 *type = STORAGE_TYPE_EXTENDED_INTERNAL;
307 *type = STORAGE_TYPE_EXTERNAL;
309 return STORAGE_ERROR_NONE;
312 API int storage_get_state(int storage_id, storage_state_e *state)
314 const struct storage_ops *ops;
320 return STORAGE_ERROR_INVALID_PARAMETER;
323 _E("Invalid parameger");
324 return STORAGE_ERROR_INVALID_PARAMETER;
327 /* internal storage */
328 DD_LIST_FOREACH(st_int_head, elem, ops) {
329 if (ops->storage_id != storage_id)
331 *state = ops->get_state();
332 return STORAGE_ERROR_NONE;
335 /* external storage */
336 if (!storage_ext_is_supported()) {
337 _D("Block module is not enabled");
338 return STORAGE_ERROR_NOT_SUPPORTED;
341 ret = storage_ext_get_state(storage_id, &st);
343 _E("Failed to get state (storage id(%d), ret(%d))", storage_id, ret); //LCOV_EXCL_LINE
344 if (ret == -ENODEV || ret == -EINVAL)
345 return STORAGE_ERROR_INVALID_PARAMETER;
346 else if (ret == -ENOMEM)
347 return STORAGE_ERROR_OUT_OF_MEMORY;
349 return STORAGE_ERROR_OPERATION_FAILED;
353 return STORAGE_ERROR_NONE;
356 //LCOV_EXCL_START Not called Callback
357 static void compat_cb(int storage_id,
358 storage_dev_e dev, storage_state_e state,
359 const char *fstype, const char *fsuuid, const char *mountpath,
360 bool primary, int flags, void *user_data)
362 struct compat_cb_info* ccb_info;
365 if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
366 DD_LIST_FOREACH(compat_cb_list, elem, ccb_info)
367 ccb_info->user_cb(storage_id, state, ccb_info->user_data);
371 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
373 const struct storage_ops *st;
374 struct storage_cb_info info;
378 struct compat_cb_info* ccb_info;
379 static int compat_cb_init = 0;
382 return STORAGE_ERROR_INVALID_PARAMETER;
385 _E("Invalid parameger");
386 return STORAGE_ERROR_INVALID_PARAMETER;
389 /* For backward compatability */
390 if (storage_id == STORAGE_TYPE_EXTERNAL) {
391 if (!storage_ext_is_supported()) {
392 _D("Block module is not enabled");
393 return STORAGE_ERROR_NOT_SUPPORTED;
396 if (!compat_cb_init) {
397 ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
398 if (ret == STORAGE_ERROR_NONE)
404 ccb_info = malloc(sizeof(struct compat_cb_info));
405 if (ccb_info == NULL)
406 return STORAGE_ERROR_OPERATION_FAILED;
407 ccb_info->user_cb = callback;
408 ccb_info->user_data = user_data;
409 DD_LIST_APPEND(compat_cb_list, ccb_info);
411 return STORAGE_ERROR_NONE;
414 /* Internal storage does not support registering changed callback */
415 DD_LIST_FOREACH(st_int_head, elem, st)
416 if (st->storage_id == storage_id)
417 return STORAGE_ERROR_NONE;
419 /* external storage */
420 if (!storage_ext_is_supported()) {
421 _D("Block module is not enabled");
422 return STORAGE_ERROR_NOT_SUPPORTED;
425 info.id = storage_id;
426 info.state_cb = callback;
427 info.user_data = user_data;
429 ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
431 _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
432 return STORAGE_ERROR_OPERATION_FAILED;
435 return STORAGE_ERROR_NONE;
438 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
440 const struct storage_ops *st;
441 struct storage_cb_info info;
446 return STORAGE_ERROR_INVALID_PARAMETER;
449 _E("Invalid parameger");
450 return STORAGE_ERROR_INVALID_PARAMETER;
453 /* For backward compatability */
454 if (storage_id == STORAGE_TYPE_EXTERNAL) {
455 if (!storage_ext_is_supported()) {
456 _D("Block module is not enabled");
457 return STORAGE_ERROR_NOT_SUPPORTED;
461 struct compat_cb_info* ccb_info;
463 DD_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
464 if (ccb_info->user_cb == callback) {
465 DD_LIST_REMOVE(compat_cb_list, ccb_info);
467 return STORAGE_ERROR_NONE;
470 return STORAGE_ERROR_OPERATION_FAILED;
473 /* Internal storage does not support registering changed callback */
474 DD_LIST_FOREACH(st_int_head, elem, st)
475 if (st->storage_id == storage_id)
476 return STORAGE_ERROR_NONE;
478 /* external storage */
479 if (!storage_ext_is_supported()) {
480 _D("Block module is not enabled");
481 return STORAGE_ERROR_NOT_SUPPORTED;
484 info.id = storage_id;
485 info.state_cb = callback;
487 ret = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
489 _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
490 return STORAGE_ERROR_OPERATION_FAILED;
493 return STORAGE_ERROR_NONE;
496 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
498 const struct storage_ops *st;
499 unsigned long long total;
504 return STORAGE_ERROR_INVALID_PARAMETER;
507 _E("Invalid parameger");
508 return STORAGE_ERROR_INVALID_PARAMETER;
511 /* internal storage */
512 DD_LIST_FOREACH(st_int_head, elem, st) {
513 if (st->storage_id != storage_id)
515 ret = st->get_space(&total, NULL);
519 /* external storage */
520 if (!storage_ext_is_supported()) {
521 _D("Block module is not enabled");
522 return STORAGE_ERROR_NOT_SUPPORTED;
525 ret = storage_ext_get_space(storage_id, &total, NULL);
529 _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
530 if (ret == -ENODEV || ret == -EINVAL)
531 return STORAGE_ERROR_INVALID_PARAMETER;
532 else if (ret == -ENOMEM)
533 return STORAGE_ERROR_OUT_OF_MEMORY;
535 return STORAGE_ERROR_OPERATION_FAILED;
539 return STORAGE_ERROR_NONE;
542 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
544 const struct storage_ops *st;
545 unsigned long long avail;
550 return STORAGE_ERROR_INVALID_PARAMETER;
553 _E("Invalid parameger");
554 return STORAGE_ERROR_INVALID_PARAMETER;
557 /* internal storage */
558 DD_LIST_FOREACH(st_int_head, elem, st) {
559 if (st->storage_id != storage_id)
561 ret = st->get_space(NULL, &avail);
565 /* external storage */
566 if (!storage_ext_is_supported()) {
567 _D("Block module is not enabled");
568 return STORAGE_ERROR_NOT_SUPPORTED;
571 ret = storage_ext_get_space(storage_id, NULL, &avail);
575 _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
576 if (ret == -ENODEV || ret == -EINVAL)
577 return STORAGE_ERROR_INVALID_PARAMETER;
578 else if (ret == -ENOMEM)
579 return STORAGE_ERROR_OUT_OF_MEMORY;
581 return STORAGE_ERROR_OPERATION_FAILED;
585 return STORAGE_ERROR_NONE;
588 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
591 struct storage_cb_info info;
593 if (type == STORAGE_TYPE_INTERNAL) {
594 _E("Internal storage is not supported");
595 return STORAGE_ERROR_INVALID_PARAMETER;
598 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
599 _E("Invalid type (%d)", type);
600 return STORAGE_ERROR_INVALID_PARAMETER;
604 _E("Callback is NULL");
605 return STORAGE_ERROR_INVALID_PARAMETER;
608 if (!storage_ext_is_supported()) {
609 _E("Block module is not enabled");
610 return STORAGE_ERROR_NOT_SUPPORTED;
613 /* external storage */
615 info.type_cb = callback;
616 info.user_data = user_data;
618 ret = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
620 _E("Failed to register storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
621 return STORAGE_ERROR_OPERATION_FAILED;
624 return STORAGE_ERROR_NONE;
627 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
629 struct storage_cb_info info;
632 if (type == STORAGE_TYPE_INTERNAL) {
633 _E("Internal storage is not supported");
634 return STORAGE_ERROR_INVALID_PARAMETER;
637 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
638 _E("Invalid type (%d)", type);
639 return STORAGE_ERROR_INVALID_PARAMETER;
643 _E("Callback is NULL");
644 return STORAGE_ERROR_INVALID_PARAMETER;
647 if (!storage_ext_is_supported()) {
648 _E("Block module is not enabled");
649 return STORAGE_ERROR_NOT_SUPPORTED;
652 /* external storage */
654 info.type_cb = callback;
656 ret = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
658 _E("Failed to unregister storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
659 return STORAGE_ERROR_OPERATION_FAILED;
662 return STORAGE_ERROR_NONE;
665 API int storage_get_type_dev(int storage_id, storage_type_e *type, storage_dev_e *dev)
667 storage_ext_device *ext_dev;
670 if (storage_id < 0 || !type || !dev) {
671 _E("Invalid parameter");
672 return STORAGE_ERROR_INVALID_PARAMETER;
675 ret = storage_get_type(storage_id, type);
676 if (ret != STORAGE_ERROR_NONE) {
677 _E("Failed to get storage type: %d", ret);
680 if (*type == STORAGE_TYPE_INTERNAL || *type == STORAGE_TYPE_EXTENDED_INTERNAL)
681 return STORAGE_ERROR_INVALID_PARAMETER;
683 if (!storage_ext_is_supported()) {
684 _D("Block module is not enabled");
685 return STORAGE_ERROR_NOT_SUPPORTED;
688 ext_dev = calloc(1, sizeof(storage_ext_device));
690 //LCOV_EXCL_START System Error
692 return STORAGE_ERROR_OUT_OF_MEMORY;
696 ret = storage_ext_get_device_info(storage_id, ext_dev);
698 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
699 if (ret == -ENODEV) {
700 ret = STORAGE_ERROR_INVALID_PARAMETER;
703 ret = STORAGE_ERROR_OPERATION_FAILED;
707 if (ext_dev->type == STORAGE_EXT_SCSI)
708 *dev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
709 else if (ext_dev->type == STORAGE_EXT_MMC)
710 *dev = STORAGE_DEV_EXT_SDCARD;
711 ret = STORAGE_ERROR_NONE;
712 _I("type: %d(internal:0, external:1) dev: %d(sdcard: 1001, usb: 1002)", *type, *dev);
715 storage_ext_release_device(&ext_dev);
719 static void __CONSTRUCTOR__ init(void)
725 for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
726 tmp = tzplatform_getenv(tz_id[i]);
728 token = rindex(tmp, '/');
731 dir_path[i] = strdup(token);