external: add function to get root path
[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);
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 (!path || storage_id < 0) {
89                 _E("Invalid parameger");
90                 return STORAGE_ERROR_INVALID_PARAMETER;
91         }
92
93         /* internal storage */
94         DD_LIST_FOREACH(st_int_head, elem, st) {
95                 if (st->storage_id != storage_id)
96                         continue;
97                 *path = strdup(st->root());
98                 if (!*path) {
99                         _E("Failed to copy the root string : %d", errno);
100                         return STORAGE_ERROR_OUT_OF_MEMORY;
101                 }
102                 return STORAGE_ERROR_NONE;
103         }
104
105         /* external storage */
106         ret = storage_ext_get_root(storage_id, root, sizeof(root));
107         if (ret < 0) {
108                 _E("Failed to get root path of external storage(%d, %d", storage_id, ret);
109                 return STORAGE_ERROR_INVALID_PARAMETER;
110         }
111
112         *path = strdup(root);
113         if (!*path) {
114                 _E("Failed to copy the root string : %d", errno);
115                 return STORAGE_ERROR_OUT_OF_MEMORY;
116         }
117
118         return STORAGE_ERROR_NONE;
119 }
120
121 API int storage_get_directory(int storage_id, storage_directory_e type, char **path)
122 {
123         const struct storage_ops *st;
124         char root[PATH_MAX];
125         char temp[PATH_MAX];
126         char *temp2, *end;
127         int ret;
128         dd_list *elem;
129         bool found;
130
131         if (!path || storage_id < 0) {
132                 _E("Invalid parameger");
133                 return STORAGE_ERROR_INVALID_PARAMETER;
134         }
135
136         if (type < 0 || type >= STORAGE_DIRECTORY_MAX) {
137                 _E("Invalid parameter");
138                 return STORAGE_ERROR_INVALID_PARAMETER;
139         }
140
141         /* internal storage */
142         found = false;
143         DD_LIST_FOREACH(st_int_head, elem, st) {
144                 if (st->storage_id != storage_id)
145                         continue;
146                 found = true;
147                 break;
148         }
149
150         if (found && st) {
151                 snprintf(root, sizeof(root), "%s", st->root());
152                 if (type == STORAGE_DIRECTORY_SYSTEM_RINGTONES) {
153                         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &temp2);
154                         if (ret < 0) {
155                                 _E("Failed to get ringtone path : %d", ret);
156                                 return STORAGE_ERROR_OPERATION_FAILED;
157                         }
158                         end = strrchr(temp2, '/');
159                         if (end)
160                                 *end = '\0';
161                         snprintf(temp, PATH_MAX, "%s", temp2);
162                         free(temp2);
163                 } else
164                         snprintf(temp, PATH_MAX, "%s/%s", root, dir_path[type]);
165
166                 goto out;
167         }
168
169         /* external storage */
170         return STORAGE_ERROR_NONE;
171
172 out:
173         *path = strdup(temp);
174         if (!*path) {
175                 _E("Failed to copy the directory(%d) string : %d", type, errno);
176                 return STORAGE_ERROR_OUT_OF_MEMORY;
177         }
178
179         return STORAGE_ERROR_NONE;
180 }
181
182 API int storage_get_type(int storage_id, storage_type_e *type)
183 {
184         const struct storage_ops *st;
185         dd_list *elem;
186
187         if (!type || storage_id < 0) {
188                 _E("Invalid parameger");
189                 return STORAGE_ERROR_INVALID_PARAMETER;
190         }
191
192         /* internal storage */
193         DD_LIST_FOREACH(st_int_head, elem, st) {
194                 if (st->storage_id != storage_id)
195                         continue;
196                 *type = st->type;
197                 return STORAGE_ERROR_NONE;
198         }
199
200         /* external storage */
201
202         return STORAGE_ERROR_NONE;
203 }
204
205 API int storage_get_state(int storage_id, storage_state_e *state)
206 {
207         const struct storage_ops *ops;
208         dd_list *elem;
209
210         if (!state) {
211                 _E("Invalid parameger");
212                 return STORAGE_ERROR_INVALID_PARAMETER;
213         }
214
215         /* internal storage */
216         DD_LIST_FOREACH(st_int_head, elem, ops) {
217                 if (ops->storage_id != storage_id)
218                         continue;
219                 *state = ops->get_state();
220                 return STORAGE_ERROR_NONE;
221         }
222
223         /* external storage */
224
225         return STORAGE_ERROR_NONE;
226 }
227
228 API int storage_set_state_changed_cb(int storage_id, storage_state_changed_cb callback, void *user_data)
229 {
230         const struct storage_ops *st;
231         struct storage_cb_info info;
232         int ret;
233         dd_list *elem;
234
235         if (!callback) {
236                 _E("Invalid parameger");
237                 return STORAGE_ERROR_INVALID_PARAMETER;
238         }
239
240         /* Internal storage does not support registering changed callback */
241         DD_LIST_FOREACH(st_int_head, elem, st)
242                 if (st->storage_id == storage_id)
243                         return STORAGE_ERROR_NONE;
244
245         /* external storage */
246         info.id = storage_id;
247         info.state_cb = callback;
248         info.user_data = user_data;
249
250         ret = storage_ext_register_cb(STORAGE_CALLBACK_STATE, &info);
251         if (ret < 0) {
252                 _E("Failed to register callback : id(%d)", storage_id);
253                 return STORAGE_ERROR_OPERATION_FAILED;
254         }
255
256         return STORAGE_ERROR_NONE;
257 }
258
259 API int storage_unset_state_changed_cb(int storage_id, storage_state_changed_cb callback)
260 {
261         const struct storage_ops *st;
262         struct storage_cb_info info;
263         int ret;
264         dd_list *elem;
265
266         if (!callback) {
267                 _E("Invalid parameger");
268                 return STORAGE_ERROR_INVALID_PARAMETER;
269         }
270
271         /* Internal storage does not support registering changed callback */
272         DD_LIST_FOREACH(st_int_head, elem, st)
273                 if (st->storage_id == storage_id)
274                         return STORAGE_ERROR_NONE;
275
276         /* external storage */
277         info.id = storage_id;
278         info.state_cb = callback;
279
280         ret = storage_ext_unregister_cb(STORAGE_CALLBACK_STATE, &info);
281         if (ret < 0) {
282                 _E("Failed to unregister callback : id(%d)", storage_id);
283                 return STORAGE_ERROR_OPERATION_FAILED;
284         }
285
286         return STORAGE_ERROR_NONE;
287 }
288
289 API int storage_get_total_space(int storage_id, unsigned long long *bytes)
290 {
291         const struct storage_ops *st;
292         unsigned long long total;
293         int ret;
294         dd_list *elem;
295
296         if (!bytes || storage_id < 0) {
297                 _E("Invalid parameger");
298                 return STORAGE_ERROR_INVALID_PARAMETER;
299         }
300
301         /* internal storage */
302         DD_LIST_FOREACH(st_int_head, elem, st) {
303                 if (st->storage_id != storage_id)
304                         continue;
305                 ret = st->get_space(&total, NULL);
306                 goto out;
307         }
308
309         /* external storage */
310         ret = 0;
311
312 out:
313         if (ret < 0) {
314                 _E("Failed to get total memory : id(%d)", storage_id);
315                 return STORAGE_ERROR_OPERATION_FAILED;
316         }
317
318         *bytes = total;
319         return STORAGE_ERROR_NONE;
320 }
321
322 API int storage_get_available_space(int storage_id, unsigned long long *bytes)
323 {
324         const struct storage_ops *st;
325         unsigned long long avail;
326         int ret;
327         dd_list *elem;
328
329         if (!bytes) {
330                 _E("Invalid parameger");
331                 return STORAGE_ERROR_INVALID_PARAMETER;
332         }
333
334         /* internal storage */
335         DD_LIST_FOREACH(st_int_head, elem, st) {
336                 if (st->storage_id != storage_id)
337                         continue;
338                 ret = st->get_space(NULL, &avail);
339                 goto out;
340         }
341
342         /* external storage */
343         ret = 0;
344
345 out:
346         if (ret < 0) {
347                 _E("Failed to get available memory : id(%d)", storage_id);
348                 return STORAGE_ERROR_OPERATION_FAILED;
349         }
350
351         *bytes = avail;
352         return STORAGE_ERROR_NONE;
353 }