Add comments for line/function coverage analysis
[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 <system_settings.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 void add_device(const struct storage_ops *st)
44 {
45         DD_LIST_APPEND(st_int_head, st);
46 }
47
48 void remove_device(const struct storage_ops *st)
49 {
50         DD_LIST_REMOVE(st_int_head, st);
51 }
52
53 API int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data)
54 {
55         const struct storage_ops *st;
56         dd_list *elem;
57         int ret;
58
59         if (!callback) {
60                 _E("Invalid parameter");
61                 return STORAGE_ERROR_INVALID_PARAMETER;
62         }
63
64         DD_LIST_FOREACH(st_int_head, elem, st) {
65                 ret = callback(st->storage_id, st->type, st->get_state(),
66                                 st->root(), user_data);
67                 /* if the return value is false, will be stop to iterate */
68                 if (!ret)
69                         break;
70         }
71
72         ret = storage_ext_foreach_device_list(callback, user_data);
73         if (ret < 0) {
74                 _E("Failed to iterate external devices (%d)", ret); //LCOV_EXCL_LINE
75                 return STORAGE_ERROR_OPERATION_FAILED;
76         }
77
78         return STORAGE_ERROR_NONE;
79 }
80
81 API int storage_get_root_directory(int storage_id, char **path)
82 {
83         const struct storage_ops *st;
84         dd_list *elem;
85         char root[PATH_MAX];
86         int ret;
87
88         if (storage_id < 0)
89                 return STORAGE_ERROR_NOT_SUPPORTED;
90
91         if (!path) {
92                 _E("Invalid parameger");
93                 return STORAGE_ERROR_INVALID_PARAMETER;
94         }
95
96         /* internal storage */
97         DD_LIST_FOREACH(st_int_head, elem, st) {
98                 if (st->storage_id != storage_id)
99                         continue;
100                 *path = strdup(st->root());
101                 if (!*path) {
102 //LCOV_EXCL_START System Error
103                         _E("Failed to copy the root string : %d", errno);
104                         return STORAGE_ERROR_OUT_OF_MEMORY;
105 //LCOV_EXCL_STOP
106                 }
107                 return STORAGE_ERROR_NONE;
108         }
109
110         /* external storage */
111         ret = storage_ext_get_root(storage_id, root, sizeof(root));
112         if (ret < 0) {
113                 _E("Failed to get root path of external storage(%d, %d", storage_id, ret); //LCOV_EXCL_LINE
114                 return STORAGE_ERROR_INVALID_PARAMETER;
115         }
116
117         *path = strdup(root);
118         if (!*path) {
119                 _E("Failed to copy the root string : %d", errno);
120                 return STORAGE_ERROR_OUT_OF_MEMORY;
121         }
122
123         return STORAGE_ERROR_NONE;
124 }
125
126 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
127 {
128         const struct storage_ops *st;
129         char root[PATH_MAX];
130         char temp[PATH_MAX];
131         char *temp2, *end;
132         int ret;
133         dd_list *elem;
134         bool found;
135
136         if (storage_id < 0)
137                 return STORAGE_ERROR_NOT_SUPPORTED;
138
139         if (!path) {
140                 _E("Invalid parameger");
141                 return STORAGE_ERROR_INVALID_PARAMETER;
142         }
143
144         if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
145                 _E("Invalid parameter");
146                 return STORAGE_ERROR_INVALID_PARAMETER;
147         }
148
149         /* internal storage */
150         found = false;
151         DD_LIST_FOREACH(st_int_head, elem, st) {
152                 if (st->storage_id != storage_id)
153                         continue;
154                 found = true;
155                 break;
156         }
157
158         if (found && st) {
159                 snprintf(root, sizeof(root), "%s", st->root());
160                 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
161                         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &temp2);
162                         if (ret < 0) {
163                                 _E("Failed to get ringtone path : %d", ret); //LCOV_EXCL_LINE
164                                 return STORAGE_ERROR_OPERATION_FAILED;
165                         }
166                         end = strrchr(temp2, '/');
167                         if (end)
168                                 *end = '\0';
169                         snprintf(temp, PATH_MAX, "%s", temp2);
170                         free(temp2);
171                 } else
172                         snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
173
174                 goto out;
175         }
176
177         /* external storage */
178         if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
179                 _E("Not support directory : id(%d) type(%d)", storage_id, type); //LCOV_EXCL_LINE
180                 return STORAGE_ERROR_NOT_SUPPORTED;
181         }
182
183         ret = storage_ext_get_root(storage_id, root, sizeof(root));
184         if (ret < 0) {
185                 _E("Failed to get root dir for external storage(id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
186                 return STORAGE_ERROR_OPERATION_FAILED;
187         }
188
189         snprintf(temp, sizeof(temp), "%s/%s", root, dir_path[type]);
190
191 out:
192         *path = strdup(temp);
193         if (!*path) {
194                 _E("Failed to copy the directory(%d) string : %d", type, errno); //LCOV_EXCL_LINE
195                 return STORAGE_ERROR_OUT_OF_MEMORY;
196         }
197
198         return STORAGE_ERROR_NONE;
199 }
200
201 API int storage_get_type(int storage_id, storage_type_e *type)
202 {
203         const struct storage_ops *st;
204         dd_list *elem;
205
206         if (storage_id < 0)
207                 return STORAGE_ERROR_NOT_SUPPORTED;
208
209         if (!type) {
210                 _E("Invalid parameger");
211                 return STORAGE_ERROR_INVALID_PARAMETER;
212         }
213
214         /* internal storage */
215         DD_LIST_FOREACH(st_int_head, elem, st) {
216                 if (st->storage_id != storage_id)
217                         continue;
218                 *type = st->type;
219                 return STORAGE_ERROR_NONE;
220         }
221
222         /* external storage */
223         *type = STORAGE_TYPE_EXTERNAL;
224
225         return STORAGE_ERROR_NONE;
226 }
227
228 API int storage_get_state(int storage_id, storage_state_e *state)
229 {
230         const struct storage_ops *ops;
231         storage_state_e st;
232         dd_list *elem;
233         int ret;
234
235         if (storage_id < 0)
236                 return STORAGE_ERROR_NOT_SUPPORTED;
237
238         if (!state) {
239                 _E("Invalid parameger");
240                 return STORAGE_ERROR_INVALID_PARAMETER;
241         }
242
243         /* internal storage */
244         DD_LIST_FOREACH(st_int_head, elem, ops) {
245                 if (ops->storage_id != storage_id)
246                         continue;
247                 *state = ops->get_state();
248                 return STORAGE_ERROR_NONE;
249         }
250
251         /* external storage */
252         ret = storage_ext_get_state(storage_id, &st);
253         if (ret < 0) {
254                 _E("Failed to get state (storage id(%d), ret(%d))", storage_id, ret); //LCOV_EXCL_LINE
255                 return STORAGE_ERROR_OPERATION_FAILED;
256         }
257
258         *state = st;
259         return STORAGE_ERROR_NONE;
260 }
261
262 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
263 {
264         const struct storage_ops *st;
265         struct storage_cb_info info;
266         int ret;
267         dd_list *elem;
268
269         if (storage_id < 0)
270                 return STORAGE_ERROR_NOT_SUPPORTED;
271
272         if (!callback) {
273                 _E("Invalid parameger");
274                 return STORAGE_ERROR_INVALID_PARAMETER;
275         }
276
277         /* Internal storage does not support registering changed callback */
278         DD_LIST_FOREACH(st_int_head, elem, st)
279                 if (st->storage_id == storage_id)
280                         return STORAGE_ERROR_NONE;
281
282         /* external storage */
283         info.id = storage_id;
284         info.state_cb = callback;
285         info.user_data = user_data;
286
287         ret = storage_ext_register_cb(STORAGE_CALLBACK_STATE, &info);
288         if (ret < 0) {
289                 _E("Failed to register callback : id(%d)", storage_id); //LCOV_EXCL_LINE
290                 return STORAGE_ERROR_OPERATION_FAILED;
291         }
292
293         return STORAGE_ERROR_NONE;
294 }
295
296 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
297 {
298         const struct storage_ops *st;
299         struct storage_cb_info info;
300         int ret;
301         dd_list *elem;
302
303         if (storage_id < 0)
304                 return STORAGE_ERROR_NOT_SUPPORTED;
305
306         if (!callback) {
307                 _E("Invalid parameger");
308                 return STORAGE_ERROR_INVALID_PARAMETER;
309         }
310
311         /* Internal storage does not support registering changed callback */
312         DD_LIST_FOREACH(st_int_head, elem, st)
313                 if (st->storage_id == storage_id)
314                         return STORAGE_ERROR_NONE;
315
316         /* external storage */
317         info.id = storage_id;
318         info.state_cb = callback;
319
320         ret = storage_ext_unregister_cb(STORAGE_CALLBACK_STATE, &info);
321         if (ret < 0) {
322                 _E("Failed to unregister callback : id(%d)", storage_id); //LCOV_EXCL_LINE
323                 return STORAGE_ERROR_OPERATION_FAILED;
324         }
325
326         return STORAGE_ERROR_NONE;
327 }
328
329 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
330 {
331         const struct storage_ops *st;
332         unsigned long long total;
333         int ret;
334         dd_list *elem;
335
336         if (storage_id < 0)
337                 return STORAGE_ERROR_NOT_SUPPORTED;
338
339         if (!bytes) {
340                 _E("Invalid parameger");
341                 return STORAGE_ERROR_INVALID_PARAMETER;
342         }
343
344         /* internal storage */
345         DD_LIST_FOREACH(st_int_head, elem, st) {
346                 if (st->storage_id != storage_id)
347                         continue;
348                 ret = st->get_space(&total, NULL);
349                 goto out;
350         }
351
352         /* external storage */
353         ret = storage_ext_get_space(storage_id, &total, NULL);
354
355 out:
356         if (ret < 0) {
357                 _E("Failed to get total memory : id(%d)", storage_id); //LCOV_EXCL_LINE
358                 if (ret == -ENOTSUP)
359                         return STORAGE_ERROR_NOT_SUPPORTED;
360                 return STORAGE_ERROR_OPERATION_FAILED;
361         }
362
363         *bytes = total;
364         return STORAGE_ERROR_NONE;
365 }
366
367 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
368 {
369         const struct storage_ops *st;
370         unsigned long long avail;
371         int ret;
372         dd_list *elem;
373
374         if (storage_id < 0)
375                 return STORAGE_ERROR_NOT_SUPPORTED;
376
377         if (!bytes) {
378                 _E("Invalid parameger");
379                 return STORAGE_ERROR_INVALID_PARAMETER;
380         }
381
382         /* internal storage */
383         DD_LIST_FOREACH(st_int_head, elem, st) {
384                 if (st->storage_id != storage_id)
385                         continue;
386                 ret = st->get_space(NULL, &avail);
387                 goto out;
388         }
389
390         /* external storage */
391         ret = storage_ext_get_space(storage_id,NULL, &avail);
392
393 out:
394         if (ret < 0) {
395                 _E("Failed to get available memory : id(%d)", storage_id); //LCOV_EXCL_LINE
396                 if (ret == -ENOTSUP)
397                         return STORAGE_ERROR_NOT_SUPPORTED;
398                 return STORAGE_ERROR_OPERATION_FAILED;
399         }
400
401         *bytes = avail;
402         return STORAGE_ERROR_NONE;
403 }