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