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 #define USER_UID_START 5000
32 const char *dir_path[STORAGE_DIRECTORY_MAX];
34 const int tz_id[STORAGE_DIRECTORY_MAX] = {
35 [STORAGE_DIRECTORY_IMAGES] = TZ_USER_IMAGES,
36 [STORAGE_DIRECTORY_SOUNDS] = TZ_USER_SOUNDS,
37 [STORAGE_DIRECTORY_VIDEOS] = TZ_USER_VIDEOS,
38 [STORAGE_DIRECTORY_CAMERA] = TZ_USER_CAMERA,
39 [STORAGE_DIRECTORY_DOWNLOADS] = TZ_USER_DOWNLOADS,
40 [STORAGE_DIRECTORY_MUSIC] = TZ_USER_MUSIC,
41 [STORAGE_DIRECTORY_DOCUMENTS] = TZ_USER_DOCUMENTS,
42 [STORAGE_DIRECTORY_OTHERS] = TZ_USER_OTHERS,
45 static dd_list *st_int_head; /* Internal storage list */
47 static dd_list *compat_cb_list;
48 struct compat_cb_info {
49 storage_state_changed_cb user_cb;
53 void add_device(const struct storage_ops *st)
55 DD_LIST_APPEND(st_int_head, st);
58 void remove_device(const struct storage_ops *st)
60 DD_LIST_REMOVE(st_int_head, st);
63 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
65 const struct storage_ops *st;
71 _E("Invalid parameter");
72 return STORAGE_ERROR_INVALID_PARAMETER;
75 if (getuid() < USER_UID_START)
78 DD_LIST_FOREACH(st_int_head, elem, st) {
80 ret = callback(st->storage_id, st->type, st->get_state(),
81 st->root(), user_data);
82 /* if the return value is false, will be stop to iterate */
88 if (!storage_ext_is_supported()) {
89 _D("Block module is not enabled");
90 return STORAGE_ERROR_NONE;
93 ret = storage_ext_foreach_device_list(callback, user_data);
95 _E("Failed to iterate external devices (%d)", ret); //LCOV_EXCL_LINE
96 return STORAGE_ERROR_OPERATION_FAILED;
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_NOT_SUPPORTED;
115 _E("Invalid parameger");
116 return STORAGE_ERROR_INVALID_PARAMETER;
119 if (getuid() < USER_UID_START)
122 /* internal storage */
123 DD_LIST_FOREACH(st_int_head, elem, st) {
124 if (st->storage_id != storage_id)
127 _E("Only Tizen applications and user session daemons can use \
128 storage_get_root_directory(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 ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
145 _E("Failed to get root path of external storage(%d, %d", storage_id, ret); //LCOV_EXCL_LINE
146 return STORAGE_ERROR_INVALID_PARAMETER;
149 *path = strdup(root);
151 _E("Failed to copy the root string : %d", errno); //LCOV_EXCL_LINE System Error
152 return STORAGE_ERROR_OUT_OF_MEMORY;
155 return STORAGE_ERROR_NONE;
158 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
160 const struct storage_ops *st;
171 return STORAGE_ERROR_NOT_SUPPORTED;
174 _E("Invalid parameger");
175 return STORAGE_ERROR_INVALID_PARAMETER;
178 if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
179 _E("Invalid parameter");
180 return STORAGE_ERROR_INVALID_PARAMETER;
183 /* internal storage */
185 DD_LIST_FOREACH(st_int_head, elem, st) {
186 if (st->storage_id != storage_id)
192 if (getuid() < USER_UID_START)
197 _E("Only Tizen applications and user session daemons can use \
198 storage_get_directory(id, ...)");
199 return STORAGE_ERROR_INVALID_PARAMETER;
202 snprintf(root, sizeof(root), "%s", st->root());
203 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
204 temp2 = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR);
206 return STORAGE_ERROR_OPERATION_FAILED;
207 end = strrchr(temp2, '/');
210 snprintf(temp, PATH_MAX, "%s", temp2);
213 snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
218 /* external storage */
219 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
220 _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
221 return STORAGE_ERROR_NOT_SUPPORTED;
224 ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
226 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
227 return STORAGE_ERROR_NOT_SUPPORTED;
229 /* The operation is not decided */
231 return STORAGE_ERROR_NOT_SUPPORTED;
233 snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
236 *path = strdup(temp);
238 _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
239 return STORAGE_ERROR_OUT_OF_MEMORY;
242 return STORAGE_ERROR_NONE;
245 API int storage_get_type(int storage_id, storage_type_e *type)
247 const struct storage_ops *st;
254 return STORAGE_ERROR_NOT_SUPPORTED;
257 _E("Invalid parameger");
258 return STORAGE_ERROR_INVALID_PARAMETER;
261 /* internal storage */
262 DD_LIST_FOREACH(st_int_head, elem, st) {
263 if (st->storage_id != storage_id)
266 return STORAGE_ERROR_NONE;
269 /* external storage */
270 ret = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
272 _E("Failed to get type of external storage");
273 return STORAGE_ERROR_NOT_SUPPORTED;
276 *type = STORAGE_TYPE_EXTENDED_INTERNAL;
278 *type = STORAGE_TYPE_EXTERNAL;
280 return STORAGE_ERROR_NONE;
283 API int storage_get_state(int storage_id, storage_state_e *state)
285 const struct storage_ops *ops;
291 return STORAGE_ERROR_NOT_SUPPORTED;
294 _E("Invalid parameger");
295 return STORAGE_ERROR_INVALID_PARAMETER;
298 /* internal storage */
299 DD_LIST_FOREACH(st_int_head, elem, ops) {
300 if (ops->storage_id != storage_id)
302 *state = ops->get_state();
303 return STORAGE_ERROR_NONE;
306 /* external storage */
307 ret = storage_ext_get_state(storage_id, &st);
309 _E("Failed to get state (storage id(%d), ret(%d))", storage_id, ret); //LCOV_EXCL_LINE
310 return STORAGE_ERROR_OPERATION_FAILED;
314 return STORAGE_ERROR_NONE;
317 //LCOV_EXCL_START Not called Callback
318 static void compat_cb(int storage_id,
319 storage_dev_e dev, storage_state_e state,
320 const char *fstype, const char *fsuuid, const char *mountpath,
321 bool primary, int flags, void *user_data)
323 struct compat_cb_info* ccb_info;
326 if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
327 DD_LIST_FOREACH(compat_cb_list, elem, ccb_info)
328 ccb_info->user_cb(storage_id, state, ccb_info->user_data);
332 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
334 const struct storage_ops *st;
335 struct storage_cb_info info;
339 struct compat_cb_info* ccb_info;
340 static int compat_cb_init = 0;
343 return STORAGE_ERROR_NOT_SUPPORTED;
346 _E("Invalid parameger");
347 return STORAGE_ERROR_INVALID_PARAMETER;
350 /* For backward compatability */
351 if (storage_id == STORAGE_TYPE_EXTERNAL) {
352 if (!compat_cb_init) {
353 ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
354 if (ret == STORAGE_ERROR_NONE)
360 ccb_info = malloc(sizeof(struct compat_cb_info));
361 if (ccb_info == NULL)
362 return STORAGE_ERROR_OPERATION_FAILED;
363 ccb_info->user_cb = callback;
364 ccb_info->user_data = user_data;
365 DD_LIST_APPEND(compat_cb_list, ccb_info);
367 return STORAGE_ERROR_NONE;
370 /* Internal storage does not support registering changed callback */
371 DD_LIST_FOREACH(st_int_head, elem, st)
372 if (st->storage_id == storage_id)
373 return STORAGE_ERROR_NONE;
375 /* external storage */
376 info.id = storage_id;
377 info.state_cb = callback;
378 info.user_data = user_data;
380 ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
382 _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
383 return STORAGE_ERROR_OPERATION_FAILED;
386 return STORAGE_ERROR_NONE;
389 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
391 const struct storage_ops *st;
392 struct storage_cb_info info;
397 return STORAGE_ERROR_NOT_SUPPORTED;
400 _E("Invalid parameger");
401 return STORAGE_ERROR_INVALID_PARAMETER;
404 /* For backward compatability */
405 if (storage_id == STORAGE_TYPE_EXTERNAL) {
407 struct compat_cb_info* ccb_info;
409 DD_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
410 if (ccb_info->user_cb == callback) {
411 DD_LIST_REMOVE(compat_cb_list, ccb_info);
413 return STORAGE_ERROR_NONE;
416 return STORAGE_ERROR_OPERATION_FAILED;
419 /* Internal storage does not support registering changed callback */
420 DD_LIST_FOREACH(st_int_head, elem, st)
421 if (st->storage_id == storage_id)
422 return STORAGE_ERROR_NONE;
424 /* external storage */
425 info.id = storage_id;
426 info.state_cb = callback;
428 ret = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
430 _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
431 return STORAGE_ERROR_OPERATION_FAILED;
434 return STORAGE_ERROR_NONE;
437 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
439 const struct storage_ops *st;
440 unsigned long long total;
445 return STORAGE_ERROR_NOT_SUPPORTED;
448 _E("Invalid parameger");
449 return STORAGE_ERROR_INVALID_PARAMETER;
452 /* internal storage */
453 DD_LIST_FOREACH(st_int_head, elem, st) {
454 if (st->storage_id != storage_id)
456 ret = st->get_space(&total, NULL);
460 /* external storage */
461 ret = storage_ext_get_space(storage_id, &total, NULL);
465 _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
467 return STORAGE_ERROR_NOT_SUPPORTED;
468 return STORAGE_ERROR_OPERATION_FAILED;
472 return STORAGE_ERROR_NONE;
475 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
477 const struct storage_ops *st;
478 unsigned long long avail;
483 return STORAGE_ERROR_NOT_SUPPORTED;
486 _E("Invalid parameger");
487 return STORAGE_ERROR_INVALID_PARAMETER;
490 /* internal storage */
491 DD_LIST_FOREACH(st_int_head, elem, st) {
492 if (st->storage_id != storage_id)
494 ret = st->get_space(NULL, &avail);
498 /* external storage */
499 ret = storage_ext_get_space(storage_id, NULL, &avail);
503 _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
505 return STORAGE_ERROR_NOT_SUPPORTED;
506 return STORAGE_ERROR_OPERATION_FAILED;
510 return STORAGE_ERROR_NONE;
513 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
516 struct storage_cb_info info;
518 if (type == STORAGE_TYPE_INTERNAL) {
519 _E("Internal storage is not supported");
520 return STORAGE_ERROR_NOT_SUPPORTED;
523 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
524 _E("Invalid type (%d)", type);
525 return STORAGE_ERROR_INVALID_PARAMETER;
529 _E("Callback is NULL");
530 return STORAGE_ERROR_INVALID_PARAMETER;
533 if (!storage_ext_is_supported()) {
534 _E("Block module is not enabled");
535 return STORAGE_ERROR_NOT_SUPPORTED;
538 /* external storage */
540 info.type_cb = callback;
541 info.user_data = user_data;
543 ret = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
545 _E("Failed to register storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
546 return STORAGE_ERROR_OPERATION_FAILED;
549 return STORAGE_ERROR_NONE;
552 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
554 struct storage_cb_info info;
557 if (type == STORAGE_TYPE_INTERNAL) {
558 _E("Internal storage is not supported");
559 return STORAGE_ERROR_NOT_SUPPORTED;
562 if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
563 _E("Invalid type (%d)", type);
564 return STORAGE_ERROR_INVALID_PARAMETER;
568 _E("Callback is NULL");
569 return STORAGE_ERROR_INVALID_PARAMETER;
572 if (!storage_ext_is_supported()) {
573 _E("Block module is not enabled");
574 return STORAGE_ERROR_NOT_SUPPORTED;
577 /* external storage */
579 info.type_cb = callback;
581 ret = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
583 _E("Failed to unregister storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
584 return STORAGE_ERROR_OPERATION_FAILED;
587 return STORAGE_ERROR_NONE;
590 API int storage_get_type_dev(int storage_id, storage_type_e *type, storage_dev_e *dev)
592 storage_ext_device *ext_dev;
595 if (storage_id < 0 || !type || !dev) {
596 _E("Invalid parameter");
597 return STORAGE_ERROR_INVALID_PARAMETER;
600 ret = storage_get_type(storage_id, type);
601 if (ret != STORAGE_ERROR_NONE) {
602 _E("Failed to get storage type: %d", ret);
605 if (*type == STORAGE_TYPE_INTERNAL || *type == STORAGE_TYPE_EXTENDED_INTERNAL)
606 return STORAGE_ERROR_INVALID_PARAMETER;
608 ext_dev = calloc(1, sizeof(storage_ext_device));
610 //LCOV_EXCL_START System Error
612 return STORAGE_ERROR_OUT_OF_MEMORY;
616 ret = storage_ext_get_device_info(storage_id, ext_dev);
618 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
619 ret = STORAGE_ERROR_OPERATION_FAILED;
623 if (ext_dev->type == STORAGE_EXT_SCSI)
624 *dev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
625 else if (ext_dev->type == STORAGE_EXT_MMC)
626 *dev = STORAGE_DEV_EXT_SDCARD;
627 ret = STORAGE_ERROR_NONE;
628 _I("type: %d(internal:0, external:1) dev: %d(sdcard: 1001, usb: 1002)", *type, *dev);
631 storage_ext_release_device(&ext_dev);
635 static void __CONSTRUCTOR__ init(void)
641 for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
642 tmp = tzplatform_getenv(tz_id[i]);
644 token = rindex(tmp, '/');
647 dir_path[i] = strdup(token);