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