Increase line coverage using LCOV_EXCL
[platform/core/system/libstorage.git] / src / storage.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <vconf.h>
23 #include <tzplatform_config.h>
24 #include <libsyscommon/list.h>
25
26 #include "common.h"
27 #include "log.h"
28 #include "storage-external.h"
29
30 const char *dir_path[STORAGE_DIRECTORY_MAX];
31
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,
41 };
42
43 static GList *st_int_head; /* Internal storage list */
44
45 static GList *compat_cb_list;
46 struct compat_cb_info {
47         storage_state_changed_cb user_cb;
48         void *user_data;
49 };
50
51 void add_device(const struct storage_ops *st)
52 {
53         SYS_G_LIST_APPEND(st_int_head, st);
54 }
55
56 void remove_device(const struct storage_ops *st)
57 {
58         SYS_G_LIST_REMOVE(st_int_head, st);
59 }
60
61 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
62 {
63         const struct storage_ops *st;
64         GList *elem;
65         int ret_val;
66         bool user = true;
67
68         if (!callback) {
69                 _E("Invalid parameter");
70                 return STORAGE_ERROR_INVALID_PARAMETER;
71         }
72
73         if (getuid() <= USER_UID_START)
74                 user = false;
75
76         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
77                 if (user) {
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 */
81                         if (!ret_val)
82                                 break;
83                 }
84         }
85
86         if (!storage_ext_is_supported()) {
87                 //LCOV_EXCL_START
88                 _D("Block module is not enabled");
89                 return STORAGE_ERROR_NONE;
90                 //LCOV_EXCL_STOP
91         }
92
93         ret_val = storage_ext_foreach_device_list(callback, user_data);
94         if (ret_val < 0) {
95                 _E("Failed to iterate external devices (%d)", ret_val); //LCOV_EXCL_LINE
96                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
97         }
98
99         return STORAGE_ERROR_NONE;
100 }
101
102 API int storage_get_root_directory(int storage_id, char **path)
103 {
104         const struct storage_ops *st;
105         GList *elem;
106         char root[PATH_MAX];
107         int ret_val;
108         bool extendedint;
109         bool user = true;
110
111         if (storage_id < 0)
112                 return STORAGE_ERROR_INVALID_PARAMETER;
113
114         if (!path) {
115                 _E("Invalid parameger");
116                 return STORAGE_ERROR_INVALID_PARAMETER;
117         }
118
119         if (getuid() <= USER_UID_START)
120                 user = false;
121
122         /* internal storage */
123         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
124                 if (st->storage_id != storage_id)
125                         continue;
126                 if (!user) {
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;
130                 }
131
132                 *path = strdup(st->root());
133                 if (!*path) {
134 //LCOV_EXCL_START System Error
135                         _E("Failed to copy the root string : %d", errno);
136                         return STORAGE_ERROR_OUT_OF_MEMORY;
137 //LCOV_EXCL_STOP
138                 }
139                 return STORAGE_ERROR_NONE;
140         }
141
142         /* external storage */
143         if (!storage_ext_is_supported()) {
144                 //LCOV_EXCL_START
145                 _D("Block module is not enabled");
146                 return STORAGE_ERROR_NOT_SUPPORTED;
147                 //LCOV_EXCL_STOP
148         }
149
150         ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
151         if (ret_val < 0) {
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;
155                 //LCOV_EXCL_START
156                 else if (ret_val == -ENOMEM)
157                         return STORAGE_ERROR_OUT_OF_MEMORY;
158                 else
159                         return STORAGE_ERROR_OPERATION_FAILED;
160                 //LCOV_EXCL_STOP
161         }
162
163         *path = strdup(root);
164         if (!*path) {
165                 //LCOV_EXCL_START System error
166                 _E("Failed to copy the root string : %d", errno);
167                 return STORAGE_ERROR_OUT_OF_MEMORY;
168                 //LCOV_EXCL_STOP
169         }
170
171         return STORAGE_ERROR_NONE;
172 }
173
174 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
175 {
176         const struct storage_ops *st;
177         char root[PATH_MAX];
178         char temp[PATH_MAX];
179         char *temp2, *end;
180         int ret_val;
181         GList *elem;
182         bool found;
183         bool extendedint;
184         bool user = true;
185
186         if (storage_id < 0)
187                 return STORAGE_ERROR_INVALID_PARAMETER;
188
189         if (!path) {
190                 _E("Invalid parameger");
191                 return STORAGE_ERROR_INVALID_PARAMETER;
192         }
193
194         if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
195                 _E("Invalid parameter");
196                 return STORAGE_ERROR_INVALID_PARAMETER;
197         }
198
199         /* internal storage */
200         found = false;
201         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
202                 if (st->storage_id != storage_id)
203                         continue;
204                 found = true;
205                 break;
206         }
207
208         if (getuid() <= USER_UID_START)
209                 user = false;
210
211         if (found && st) {
212                 if (!user) {
213                         _E("Only apps and user session daemons are allowed "
214                                         "to use storage_get_root_directory(INTERNAL_STORAGE_ID, ...)");
215
216                         return STORAGE_ERROR_INVALID_PARAMETER;
217                 }
218
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);
222                         if (temp2 == NULL)
223                                 return STORAGE_ERROR_OPERATION_FAILED;
224                         end = strrchr(temp2, '/');
225                         if (end)
226                                 *end = '\0';
227                         snprintf(temp, PATH_MAX, "%s", temp2);
228                         free(temp2);
229                 } else {
230                         if ((ret_val = snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type])) > PATH_MAX - 1) {
231                                 //LCOV_EXCL_START
232                                 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
233                                 return STORAGE_ERROR_OUT_OF_MEMORY;
234                                 //LCOV_EXCL_STOP
235                         }
236                 }
237
238                 goto out;
239         }
240
241         /* external storage */
242         if (!storage_ext_is_supported()) {
243                 //LCOV_EXCL_START
244                 _D("Block module is not enabled");
245                 return STORAGE_ERROR_NOT_SUPPORTED;
246                 //LCOV_EXCL_STOP
247         }
248
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;
252         }
253
254         ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
255         if (ret_val < 0) {
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;
259                 //LCOV_EXCL_START
260                 else if (ret_val == -ENOMEM)
261                         return STORAGE_ERROR_OUT_OF_MEMORY;
262                 else
263                         return STORAGE_ERROR_OPERATION_FAILED;
264                 //LCOV_EXCL_STOP
265         }
266         /* The operation is not decided */
267         if (extendedint)
268                 return STORAGE_ERROR_INVALID_PARAMETER;
269
270         if ((ret_val = snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type])) > sizeof(temp) - 1) {
271                 //LCOV_EXCL_START
272                 _E("Path is longer than buffer. Need %d size of buffer.", ret_val + 1);
273                 return STORAGE_ERROR_OUT_OF_MEMORY;
274                 //LCOV_EXCL_STOP
275         }
276
277 out:
278         *path = strdup(temp);
279         if (!*path) {
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;
283                 //LCOV_EXCL_STOP
284         }
285
286         return STORAGE_ERROR_NONE;
287 }
288
289 API int storage_get_type(int storage_id, storage_type_e *type)
290 {
291         const struct storage_ops *st;
292         GList *elem;
293         char root[PATH_MAX];
294         int ret_val;
295         bool extendedint;
296
297         if (storage_id < 0)
298                 return STORAGE_ERROR_INVALID_PARAMETER;
299
300         if (!type) {
301                 _E("Invalid parameger");
302                 return STORAGE_ERROR_INVALID_PARAMETER;
303         }
304
305         /* internal storage */
306         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
307                 if (st->storage_id != storage_id)
308                         continue;
309                 *type = st->type;
310                 return STORAGE_ERROR_NONE;
311         }
312
313         /* external storage */
314         if (!storage_ext_is_supported()) {
315                 //LCOV_EXCL_START
316                 _D("Block module is not enabled");
317                 return STORAGE_ERROR_NOT_SUPPORTED;
318                 //LCOV_EXCL_STOP
319         }
320
321         ret_val = storage_ext_get_root(storage_id, root, sizeof(root), &extendedint);
322         if (ret_val < 0) {
323                 _E("Failed to get type of external storage");
324                 if (ret_val == -ENODEV || ret_val == -EINVAL)
325                         return STORAGE_ERROR_INVALID_PARAMETER;
326                 //LCOV_EXCL_START
327                 else if (ret_val == -ENOMEM)
328                         return STORAGE_ERROR_OUT_OF_MEMORY;
329                 else
330                         return STORAGE_ERROR_OPERATION_FAILED;
331                 //LCOV_EXCL_STOP
332         }
333         if (extendedint)
334                 *type = STORAGE_TYPE_EXTENDED_INTERNAL;
335         else
336                 *type = STORAGE_TYPE_EXTERNAL;
337
338         return STORAGE_ERROR_NONE;
339 }
340
341 API int storage_get_state(int storage_id, storage_state_e *state)
342 {
343         const struct storage_ops *ops;
344         storage_state_e st;
345         GList *elem;
346         int ret_val;
347
348         if (storage_id < 0)
349                 return STORAGE_ERROR_INVALID_PARAMETER;
350
351         if (!state) {
352                 _E("Invalid parameger");
353                 return STORAGE_ERROR_INVALID_PARAMETER;
354         }
355
356         /* internal storage */
357         SYS_G_LIST_FOREACH(st_int_head, elem, ops) {
358                 if (ops->storage_id != storage_id)
359                         continue;
360                 *state = ops->get_state();
361                 return STORAGE_ERROR_NONE;
362         }
363
364         /* external storage */
365         if (!storage_ext_is_supported()) {
366                 //LCOV_EXCL_START
367                 _D("Block module is not enabled");
368                 return STORAGE_ERROR_NOT_SUPPORTED;
369                 //LCOV_EXCL_STOP
370         }
371
372         ret_val = storage_ext_get_state(storage_id, &st);
373         if (ret_val < 0) {
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;
377                 //LCOV_EXCL_START
378                 else if (ret_val == -ENOMEM)
379                         return STORAGE_ERROR_OUT_OF_MEMORY;
380                 else
381                         return STORAGE_ERROR_OPERATION_FAILED;
382                 //LCOV_EXCL_STOP
383         }
384
385         *state = st;
386         return STORAGE_ERROR_NONE;
387 }
388
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)
394 {
395         struct compat_cb_info* ccb_info;
396         GList *elem;
397
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);
401 }
402 //LCOV_EXCL_STOP
403
404 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
405 {
406         const struct storage_ops *st;
407         struct storage_cb_info info;
408         int ret;
409         GList *elem;
410
411         struct compat_cb_info* ccb_info;
412         static int compat_cb_init = 0;
413
414         if (storage_id < 0)
415                 return STORAGE_ERROR_INVALID_PARAMETER;
416
417         if (!callback) {
418                 _E("Invalid parameger");
419                 return STORAGE_ERROR_INVALID_PARAMETER;
420         }
421
422         /**
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.
426          */
427         if (storage_id == STORAGE_TYPE_EXTERNAL) {
428                 if (!storage_ext_is_supported()) {
429                         //LCOV_EXCL_START
430                         _D("Block module is not enabled");
431                         return STORAGE_ERROR_NOT_SUPPORTED;
432                         //LCOV_EXCL_STOP
433                 }
434
435                 if (!compat_cb_init) {
436                         ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
437                         if (ret == STORAGE_ERROR_NONE)
438                                 compat_cb_init = 1;
439                         else
440                                 return ret;
441                 }
442
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);
449
450                 return STORAGE_ERROR_NONE;
451         }
452
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;
457
458         /* external storage */
459         if (!storage_ext_is_supported()) {
460                 //LCOV_EXCL_START
461                 _D("Block module is not enabled");
462                 return STORAGE_ERROR_NOT_SUPPORTED;
463                 //LCOV_EXCL_STOP
464         }
465
466         info.id = storage_id;
467         info.state_cb = callback;
468         info.user_data = user_data;
469
470         ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
471         if (ret < 0) {
472                 //LCOV_EXCL_START
473                 _E("Failed to register callback : id(%d)", storage_id);
474                 return STORAGE_ERROR_OPERATION_FAILED;
475                 //LCOV_EXCL_STOP
476         }
477
478         return STORAGE_ERROR_NONE;
479 }
480
481 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
482 {
483         const struct storage_ops *st;
484         struct storage_cb_info info;
485         int ret_val;
486         GList *elem;
487
488         if (storage_id < 0)
489                 return STORAGE_ERROR_INVALID_PARAMETER;
490
491         if (!callback) {
492                 _E("Invalid parameger");
493                 return STORAGE_ERROR_INVALID_PARAMETER;
494         }
495
496         /**
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.
500          */
501         if (storage_id == STORAGE_TYPE_EXTERNAL) {
502                 if (!storage_ext_is_supported()) {
503                         //LCOV_EXCL_START
504                         _D("Block module is not enabled");
505                         return STORAGE_ERROR_NOT_SUPPORTED;
506                         //LCOV_EXCL_STOP
507                 }
508
509                 GList *elem_n;
510                 struct compat_cb_info* ccb_info;
511
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);
515                                 free(ccb_info);
516                                 return STORAGE_ERROR_NONE;
517                         }
518                 }
519
520                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
521         }
522
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;
527
528         /* external storage */
529         if (!storage_ext_is_supported()) {
530                 //LCOV_EXCL_START
531                 _D("Block module is not enabled");
532                 return STORAGE_ERROR_NOT_SUPPORTED;
533                 //LCOV_EXCL_STOP
534         }
535
536         info.id = storage_id;
537         info.state_cb = callback;
538
539         ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
540         if (ret_val < 0) {
541                 //LCOV_EXCL_START
542                 _E("Failed to unregister callback : id(%d)", storage_id);
543                 return STORAGE_ERROR_OPERATION_FAILED;
544                 //LCOV_EXCL_STOP
545         }
546
547         return STORAGE_ERROR_NONE;
548 }
549
550 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
551 {
552         const struct storage_ops *st;
553         unsigned long long total;
554         int ret_val;
555         GList *elem;
556
557         if (storage_id < 0)
558                 return STORAGE_ERROR_INVALID_PARAMETER;
559
560         if (!bytes) {
561                 _E("Invalid parameger");
562                 return STORAGE_ERROR_INVALID_PARAMETER;
563         }
564
565         /* internal storage */
566         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
567                 if (st->storage_id != storage_id)
568                         continue;
569                 ret_val = st->get_space(&total, NULL);
570                 goto out;
571         }
572
573         /* external storage */
574         if (!storage_ext_is_supported()) {
575                 //LCOV_EXCL_START
576                 _D("Block module is not enabled");
577                 return STORAGE_ERROR_NOT_SUPPORTED;
578                 //LCOV_EXCL_STOP
579         }
580
581         ret_val = storage_ext_get_space(storage_id, &total, NULL);
582
583 out:
584         if (ret_val < 0) {
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;
588                 //LCOV_EXCL_START
589                 else if (ret_val == -ENOMEM)
590                         return STORAGE_ERROR_OUT_OF_MEMORY;
591                 else
592                         return STORAGE_ERROR_OPERATION_FAILED;
593                 //LCOV_EXCL_STOP
594         }
595
596         *bytes = total;
597         return STORAGE_ERROR_NONE;
598 }
599
600 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
601 {
602         const struct storage_ops *st;
603         unsigned long long avail;
604         int ret_val;
605         GList *elem;
606
607         if (storage_id < 0)
608                 return STORAGE_ERROR_INVALID_PARAMETER;
609
610         if (!bytes) {
611                 _E("Invalid parameger");
612                 return STORAGE_ERROR_INVALID_PARAMETER;
613         }
614
615         /* internal storage */
616         SYS_G_LIST_FOREACH(st_int_head, elem, st) {
617                 if (st->storage_id != storage_id)
618                         continue;
619                 ret_val = st->get_space(NULL, &avail);
620                 goto out;
621         }
622
623         /* external storage */
624         if (!storage_ext_is_supported()) {
625                 //LCOV_EXCL_START
626                 _D("Block module is not enabled");
627                 return STORAGE_ERROR_NOT_SUPPORTED;
628                 //LCOV_EXCL_STOP
629         }
630
631         ret_val = storage_ext_get_space(storage_id, NULL, &avail);
632
633 out:
634         if (ret_val < 0) {
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;
638                 //LCOV_EXCL_START
639                 else if (ret_val == -ENOMEM)
640                         return STORAGE_ERROR_OUT_OF_MEMORY;
641                 else
642                         return STORAGE_ERROR_OPERATION_FAILED;
643                 //LCOV_EXCL_STOP
644         }
645
646         *bytes = avail;
647         return STORAGE_ERROR_NONE;
648 }
649
650 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
651 {
652         int ret_val;
653         struct storage_cb_info info;
654
655         if (type == STORAGE_TYPE_INTERNAL) {
656                 _E("Internal storage is not supported");
657                 return STORAGE_ERROR_INVALID_PARAMETER;
658         }
659
660         if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
661                 _E("Invalid type (%d)", type);
662                 return STORAGE_ERROR_INVALID_PARAMETER;
663         }
664
665         if (!callback) {
666                 _E("Callback is NULL");
667                 return STORAGE_ERROR_INVALID_PARAMETER;
668         }
669
670         if (!storage_ext_is_supported()) {
671                 //LCOV_EXCL_START
672                 _E("Block module is not enabled");
673                 return STORAGE_ERROR_NOT_SUPPORTED;
674                 //LCOV_EXCL_STOP
675         }
676
677         /* external storage */
678         info.type = type;
679         info.type_cb = callback;
680         info.user_data = user_data;
681
682         ret_val = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
683         if (ret_val < 0) {
684                 //LCOV_EXCL_START
685                 _E("Failed to register storage callback(ret:%d)", ret_val);
686                 return STORAGE_ERROR_OPERATION_FAILED;
687                 //LCOV_EXCL_STOP
688         }
689
690         return STORAGE_ERROR_NONE;
691 }
692
693 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
694 {
695         struct storage_cb_info info;
696         int ret_val;
697
698         if (type == STORAGE_TYPE_INTERNAL) {
699                 _E("Internal storage is not supported");
700                 return STORAGE_ERROR_INVALID_PARAMETER;
701         }
702
703         if (type != STORAGE_TYPE_EXTERNAL && type != STORAGE_TYPE_EXTENDED_INTERNAL) {
704                 _E("Invalid type (%d)", type);
705                 return STORAGE_ERROR_INVALID_PARAMETER;
706         }
707
708         if (!callback) {
709                 _E("Callback is NULL");
710                 return STORAGE_ERROR_INVALID_PARAMETER;
711         }
712
713         if (!storage_ext_is_supported()) {
714                 //LCOV_EXCL_START
715                 _E("Block module is not enabled");
716                 return STORAGE_ERROR_NOT_SUPPORTED;
717                 //LCOV_EXCL_STOP
718         }
719
720         /* external storage */
721         info.type = type;
722         info.type_cb = callback;
723
724         ret_val = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
725         if (ret_val < 0) {
726                 //LCOV_EXCL_START
727                 _E("Failed to unregister storage callback(ret:%d)", ret_val);
728                 return STORAGE_ERROR_OPERATION_FAILED;
729                 //LCOV_EXCL_STOP
730         }
731
732         return STORAGE_ERROR_NONE;
733 }
734
735 API int storage_get_type_dev(int storage_id, storage_type_e *type, storage_dev_e *dev)
736 {
737         storage_ext_device *ext_dev;
738         int ret;
739
740         if (storage_id < 0 || !type || !dev) {
741                 _E("Invalid parameter");
742                 return STORAGE_ERROR_INVALID_PARAMETER;
743         }
744
745         ret = storage_get_type(storage_id, type);
746         if (ret != STORAGE_ERROR_NONE) {
747                 //LCOV_EXCL_START
748                 _E("Failed to get storage type: %d", ret);
749                 return ret;
750                 //LCOV_EXCL_STOP
751         }
752         if (*type == STORAGE_TYPE_INTERNAL || *type == STORAGE_TYPE_EXTENDED_INTERNAL)
753                 return STORAGE_ERROR_INVALID_PARAMETER;
754
755         if (!storage_ext_is_supported()) {
756                 //LCOV_EXCL_START
757                 _D("Block module is not enabled");
758                 return STORAGE_ERROR_NOT_SUPPORTED;
759                 //LCOV_EXCL_STOP
760         }
761
762         ext_dev = calloc(1, sizeof(storage_ext_device));
763         if (!ext_dev) {
764                 //LCOV_EXCL_START System Error
765                 _E("calloc failed");
766                 return STORAGE_ERROR_OUT_OF_MEMORY;
767                 //LCOV_EXCL_STOP
768         }
769
770         ret = storage_ext_get_device_info(storage_id, ext_dev);
771         if (ret < 0) {
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;
775                         goto out;
776                 }
777                 //LCOV_EXCL_START
778                 ret = STORAGE_ERROR_OPERATION_FAILED;
779                 goto out;
780                 //LCOV_EXCL_STOP
781         }
782
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);
789
790 out:
791         storage_ext_release_device(&ext_dev);
792         return ret;
793 }
794
795 static void __CONSTRUCTOR__ init(void)
796 {
797         const char *tmp;
798         char *token;
799         int i;
800
801         for (i = 0 ; i <= STORAGE_DIRECTORY_OTHERS ; i++) {
802                 tmp = tzplatform_getenv(tz_id[i]);
803                 if (tmp != NULL) {
804                         token = rindex(tmp, '/');
805                         if (token != NULL) {
806                                 token++;
807                                 dir_path[i] = strdup(token);
808                         }
809                 }
810         }
811 }