Apply line coverage comments
[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
24 #include "common.h"
25 #include "list.h"
26 #include "log.h"
27 #include "storage-external.h"
28
29 const char *dir_path[STORAGE_DIRECTORY_MAX] = {
30         [STORAGE_DIRECTORY_IMAGES] = "Images",
31         [STORAGE_DIRECTORY_SOUNDS] = "Sounds",
32         [STORAGE_DIRECTORY_VIDEOS] = "Videos",
33         [STORAGE_DIRECTORY_CAMERA] = "Camera",
34         [STORAGE_DIRECTORY_DOWNLOADS] = "Downloads",
35         [STORAGE_DIRECTORY_MUSIC] = "Music",
36         [STORAGE_DIRECTORY_DOCUMENTS] = "Documents",
37         [STORAGE_DIRECTORY_OTHERS] = "Others",
38         [STORAGE_DIRECTORY_SYSTEM_RINGTONES] = "",
39 };
40
41 static dd_list *st_int_head; /* Internal storage list */
42
43 static dd_list *compat_cb_list;
44 struct compat_cb_info {
45         storage_state_changed_cb user_cb;
46         void *user_data;
47 };
48
49 void add_device(const struct storage_ops *st)
50 {
51         DD_LIST_APPEND(st_int_head, st);
52 }
53
54 void remove_device(const struct storage_ops *st)
55 {
56         DD_LIST_REMOVE(st_int_head, st);
57 }
58
59 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
60 {
61         const struct storage_ops *st;
62         dd_list *elem;
63         int ret;
64
65         if (!callback) {
66                 _E("Invalid parameter");
67                 return STORAGE_ERROR_INVALID_PARAMETER;
68         }
69
70         DD_LIST_FOREACH(st_int_head, elem, st) {
71                 ret = callback(st->storage_id, st->type, st->get_state(),
72                                 st->root(), user_data);
73                 /* if the return value is false, will be stop to iterate */
74                 if (!ret)
75                         break;
76         }
77
78         ret = storage_ext_foreach_device_list(callback, user_data);
79         if (ret < 0) {
80                 _E("Failed to iterate external devices (%d)", ret); //LCOV_EXCL_LINE
81                 return STORAGE_ERROR_OPERATION_FAILED;
82         }
83
84         return STORAGE_ERROR_NONE;
85 }
86
87 API int storage_get_root_directory(int storage_id, char **path)
88 {
89         const struct storage_ops *st;
90         dd_list *elem;
91         char root[PATH_MAX];
92         int ret;
93
94         if (storage_id < 0)
95                 return STORAGE_ERROR_NOT_SUPPORTED;
96
97         if (!path) {
98                 _E("Invalid parameger");
99                 return STORAGE_ERROR_INVALID_PARAMETER;
100         }
101
102         /* internal storage */
103         DD_LIST_FOREACH(st_int_head, elem, st) {
104                 if (st->storage_id != storage_id)
105                         continue;
106                 *path = strdup(st->root());
107                 if (!*path) {
108 //LCOV_EXCL_START System Error
109                         _E("Failed to copy the root string : %d", errno);
110                         return STORAGE_ERROR_OUT_OF_MEMORY;
111 //LCOV_EXCL_STOP
112                 }
113                 return STORAGE_ERROR_NONE;
114         }
115
116         /* external storage */
117         ret = storage_ext_get_root(storage_id, root, sizeof(root));
118         if (ret < 0) {
119                 _E("Failed to get root path of external storage(%d, %d", storage_id, ret); //LCOV_EXCL_LINE
120                 return STORAGE_ERROR_INVALID_PARAMETER;
121         }
122
123         *path = strdup(root);
124         if (!*path) {
125                 _E("Failed to copy the root string : %d", errno); //LCOV_EXCL_LINE System Error
126                 return STORAGE_ERROR_OUT_OF_MEMORY;
127         }
128
129         return STORAGE_ERROR_NONE;
130 }
131
132 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
133 {
134         const struct storage_ops *st;
135         char root[PATH_MAX];
136         char temp[PATH_MAX];
137         char *temp2, *end;
138         int ret;
139         dd_list *elem;
140         bool found;
141
142         if (storage_id < 0)
143                 return STORAGE_ERROR_NOT_SUPPORTED;
144
145         if (!path) {
146                 _E("Invalid parameger");
147                 return STORAGE_ERROR_INVALID_PARAMETER;
148         }
149
150         if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
151                 _E("Invalid parameter");
152                 return STORAGE_ERROR_INVALID_PARAMETER;
153         }
154
155         /* internal storage */
156         found = false;
157         DD_LIST_FOREACH(st_int_head, elem, st) {
158                 if (st->storage_id != storage_id)
159                         continue;
160                 found = true;
161                 break;
162         }
163
164         if (found && st) {
165                 snprintf(root, sizeof(root), "%s", st->root());
166                 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
167                         temp2 = vconf_get_str(VCONFKEY_SETAPPL_CALL_RINGTONE_PATH_STR);
168                         if (temp2 == NULL)
169                                 return STORAGE_ERROR_OPERATION_FAILED;
170                         end = strrchr(temp2, '/');
171                         if (end)
172                                 *end = '\0';
173                         snprintf(temp, PATH_MAX, "%s", temp2);
174                         free(temp2);
175                 } else
176                         snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
177
178                 goto out;
179         }
180
181         /* external storage */
182         if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
183                 _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
184                 return STORAGE_ERROR_NOT_SUPPORTED;
185         }
186
187         ret = storage_ext_get_root(storage_id, root, sizeof(root));
188         if (ret < 0) {
189                 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
190                 return STORAGE_ERROR_OPERATION_FAILED;
191         }
192
193         snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
194
195 out:
196         *path = strdup(temp);
197         if (!*path) {
198                 _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
199                 return STORAGE_ERROR_OUT_OF_MEMORY;
200         }
201
202         return STORAGE_ERROR_NONE;
203 }
204
205 API int storage_get_type(int storage_id, storage_type_e *type)
206 {
207         const struct storage_ops *st;
208         dd_list *elem;
209
210         if (storage_id < 0)
211                 return STORAGE_ERROR_NOT_SUPPORTED;
212
213         if (!type) {
214                 _E("Invalid parameger");
215                 return STORAGE_ERROR_INVALID_PARAMETER;
216         }
217
218         /* internal storage */
219         DD_LIST_FOREACH(st_int_head, elem, st) {
220                 if (st->storage_id != storage_id)
221                         continue;
222                 *type = st->type;
223                 return STORAGE_ERROR_NONE;
224         }
225
226         /* external storage */
227         *type = STORAGE_TYPE_EXTERNAL;
228
229         return STORAGE_ERROR_NONE;
230 }
231
232 API int storage_get_state(int storage_id, storage_state_e *state)
233 {
234         const struct storage_ops *ops;
235         storage_state_e st;
236         dd_list *elem;
237         int ret;
238
239         if (storage_id < 0)
240                 return STORAGE_ERROR_NOT_SUPPORTED;
241
242         if (!state) {
243                 _E("Invalid parameger");
244                 return STORAGE_ERROR_INVALID_PARAMETER;
245         }
246
247         /* internal storage */
248         DD_LIST_FOREACH(st_int_head, elem, ops) {
249                 if (ops->storage_id != storage_id)
250                         continue;
251                 *state = ops->get_state();
252                 return STORAGE_ERROR_NONE;
253         }
254
255         /* external storage */
256         ret = storage_ext_get_state(storage_id, &st);
257         if (ret < 0) {
258                 _E("Failed to get state (storage id(%d), ret(%d))", storage_id, ret); //LCOV_EXCL_LINE
259                 return STORAGE_ERROR_OPERATION_FAILED;
260         }
261
262         *state = st;
263         return STORAGE_ERROR_NONE;
264 }
265
266 //LCOV_EXCL_START Not called Callback
267 static void compat_cb(int storage_id,
268                 storage_dev_e dev, storage_state_e state,
269                 const char *fstype, const char *fsuuid, const char *mountpath,
270                 bool primary, int flags, void *user_data)
271 {
272         struct compat_cb_info* ccb_info;
273         dd_list *elem;
274
275         if (storage_id == STORAGE_TYPE_EXTERNAL && dev == STORAGE_DEV_EXT_SDCARD)
276                 DD_LIST_FOREACH(compat_cb_list, elem, ccb_info)
277                         ccb_info->user_cb(storage_id, state, ccb_info->user_data);
278 }
279 //LCOV_EXCL_STOP
280
281 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
282 {
283         const struct storage_ops *st;
284         struct storage_cb_info info;
285         int ret;
286         dd_list *elem;
287
288         struct compat_cb_info* ccb_info;
289         static int compat_cb_init = 0;
290
291         if (storage_id < 0)
292                 return STORAGE_ERROR_NOT_SUPPORTED;
293
294         if (!callback) {
295                 _E("Invalid parameger");
296                 return STORAGE_ERROR_INVALID_PARAMETER;
297         }
298
299         /* For backward compatability */
300         if (storage_id == STORAGE_TYPE_EXTERNAL) {
301                 if (!compat_cb_init) {
302                         ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, compat_cb, NULL);
303                         if (ret == STORAGE_ERROR_NONE)
304                                 compat_cb_init = 1;
305                         else
306                                 return ret;
307                 }
308
309                 ccb_info = malloc(sizeof(struct compat_cb_info));
310                 if (ccb_info == NULL)
311                         return STORAGE_ERROR_OPERATION_FAILED;
312                 ccb_info->user_cb = callback;
313                 ccb_info->user_data = user_data;
314                 DD_LIST_APPEND(compat_cb_list, ccb_info);
315
316                 return STORAGE_ERROR_NONE;
317         }
318
319         /* Internal storage does not support registering changed callback */
320         DD_LIST_FOREACH(st_int_head, elem, st)
321                 if (st->storage_id == storage_id)
322                         return STORAGE_ERROR_NONE;
323
324         /* external storage */
325         info.id = storage_id;
326         info.state_cb = callback;
327         info.user_data = user_data;
328
329         ret = storage_ext_register_cb(STORAGE_CALLBACK_ID, &info);
330         if (ret < 0) {
331                 _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
332                 return STORAGE_ERROR_OPERATION_FAILED;
333         }
334
335         return STORAGE_ERROR_NONE;
336 }
337
338 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
339 {
340         const struct storage_ops *st;
341         struct storage_cb_info info;
342         int ret;
343         dd_list *elem;
344
345         if (storage_id < 0)
346                 return STORAGE_ERROR_NOT_SUPPORTED;
347
348         if (!callback) {
349                 _E("Invalid parameger");
350                 return STORAGE_ERROR_INVALID_PARAMETER;
351         }
352
353         /* For backward compatability */
354         if (storage_id == STORAGE_TYPE_EXTERNAL) {
355                 dd_list *elem_n;
356                 struct compat_cb_info* ccb_info;
357
358                 DD_LIST_FOREACH_SAFE(compat_cb_list, elem, elem_n, ccb_info) {
359                         if (ccb_info->user_cb == callback) {
360                                 DD_LIST_REMOVE(compat_cb_list, ccb_info);
361                                 free(ccb_info);
362                                 return STORAGE_ERROR_NONE;
363                         }
364                 }
365                 return STORAGE_ERROR_OPERATION_FAILED;
366         }
367
368         /* Internal storage does not support registering changed callback */
369         DD_LIST_FOREACH(st_int_head, elem, st)
370                 if (st->storage_id == storage_id)
371                         return STORAGE_ERROR_NONE;
372
373         /* external storage */
374         info.id = storage_id;
375         info.state_cb = callback;
376
377         ret = storage_ext_unregister_cb(STORAGE_CALLBACK_ID, &info);
378         if (ret < 0) {
379                 _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
380                 return STORAGE_ERROR_OPERATION_FAILED;
381         }
382
383         return STORAGE_ERROR_NONE;
384 }
385
386 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
387 {
388         const struct storage_ops *st;
389         unsigned long long total;
390         int ret;
391         dd_list *elem;
392
393         if (storage_id < 0)
394                 return STORAGE_ERROR_NOT_SUPPORTED;
395
396         if (!bytes) {
397                 _E("Invalid parameger");
398                 return STORAGE_ERROR_INVALID_PARAMETER;
399         }
400
401         /* internal storage */
402         DD_LIST_FOREACH(st_int_head, elem, st) {
403                 if (st->storage_id != storage_id)
404                         continue;
405                 ret = st->get_space(&total, NULL);
406                 goto out;
407         }
408
409         /* external storage */
410         ret = storage_ext_get_space(storage_id, &total, NULL);
411
412 out:
413         if (ret < 0) {
414                 _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
415                 if (ret == -ENOTSUP)
416                         return STORAGE_ERROR_NOT_SUPPORTED;
417                 return STORAGE_ERROR_OPERATION_FAILED;
418         }
419
420         *bytes = total;
421         return STORAGE_ERROR_NONE;
422 }
423
424 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
425 {
426         const struct storage_ops *st;
427         unsigned long long avail;
428         int ret;
429         dd_list *elem;
430
431         if (storage_id < 0)
432                 return STORAGE_ERROR_NOT_SUPPORTED;
433
434         if (!bytes) {
435                 _E("Invalid parameger");
436                 return STORAGE_ERROR_INVALID_PARAMETER;
437         }
438
439         /* internal storage */
440         DD_LIST_FOREACH(st_int_head, elem, st) {
441                 if (st->storage_id != storage_id)
442                         continue;
443                 ret = st->get_space(NULL, &avail);
444                 goto out;
445         }
446
447         /* external storage */
448         ret = storage_ext_get_space(storage_id, NULL, &avail);
449
450 out:
451         if (ret < 0) {
452                 _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
453                 if (ret == -ENOTSUP)
454                         return STORAGE_ERROR_NOT_SUPPORTED;
455                 return STORAGE_ERROR_OPERATION_FAILED;
456         }
457
458         *bytes = avail;
459         return STORAGE_ERROR_NONE;
460 }
461
462 API int storage_set_changed_cb(storage_type_e type, storage_changed_cb callback, void *user_data)
463 {
464         int ret;
465         struct storage_cb_info info;
466
467         if (type == STORAGE_TYPE_INTERNAL) {
468                 _E("Internal storage is not supported");
469                 return STORAGE_ERROR_NOT_SUPPORTED;
470         }
471
472         if (type != STORAGE_TYPE_EXTERNAL) {
473                 _E("Invalid type (%d)", type);
474                 return STORAGE_ERROR_INVALID_PARAMETER;
475         }
476
477         if (!callback) {
478                 _E("Callback is NULL");
479                 return STORAGE_ERROR_INVALID_PARAMETER;
480         }
481
482         /* external storage */
483         info.type = type;
484         info.type_cb = callback;
485         info.user_data = user_data;
486
487         ret = storage_ext_register_cb(STORAGE_CALLBACK_TYPE, &info);
488         if (ret < 0) {
489                 _E("Failed to register storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
490                 return STORAGE_ERROR_OPERATION_FAILED;
491         }
492
493         return STORAGE_ERROR_NONE;
494 }
495
496 API int storage_unset_changed_cb(storage_type_e type, storage_changed_cb callback)
497 {
498         struct storage_cb_info info;
499         int ret;
500
501         if (type == STORAGE_TYPE_INTERNAL) {
502                 _E("Internal storage is not supported");
503                 return STORAGE_ERROR_NOT_SUPPORTED;
504         }
505
506         if (type != STORAGE_TYPE_EXTERNAL) {
507                 _E("Invalid type (%d)", type);
508                 return STORAGE_ERROR_INVALID_PARAMETER;
509         }
510
511         if (!callback) {
512                 _E("Callback is NULL");
513                 return STORAGE_ERROR_INVALID_PARAMETER;
514         }
515
516         /* external storage */
517         info.type = type;
518         info.type_cb = callback;
519
520         ret = storage_ext_unregister_cb(STORAGE_CALLBACK_TYPE, &info);
521         if (ret < 0) {
522                 _E("Failed to unregister storage callback(ret:%d)", ret); //LCOV_EXCL_LINE
523                 return STORAGE_ERROR_OPERATION_FAILED;
524         }
525
526         return STORAGE_ERROR_NONE;
527 }