Apply libsyscommon gdbus api improvement on error handling
[platform/core/system/libstorage.git] / src / storage-inhouse.c
1 /*
2  * Copyright (c) 2016 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 <unistd.h>
19 #include <sys/types.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <tzplatform_config.h>
25 #include <blkid.h>
26 #include <libsyscommon/dbus-system.h>
27
28 #include "common.h"
29 #include "log.h"
30 #include "storage-internal.h"
31 #include "storage-external-dbus.h"
32
33 #define FORMAT_TIMEOUT  (120*1000)
34 #define USER_PARTITION "user"
35
36 /*
37         Get compat path from origin Multi-user path
38         from TZ_USER_CONTENT/.. to /opt/usr/media/..
39         Input should be normalized path like /opt/usr/home/owner/media (TODO: internal normalization)
40
41         Why this API should be provided?
42         In multi-user environment, each user has own compat content direcotry.(/opt/usr/media)
43         However, although system daemon operates real path,
44                 system daemon needs to provide compat path to App if the real path is converted.
45
46         Usage:
47                 #include <storage-internal.h>
48
49                 char dest[100];
50                 if(storage_get_compat_internal_path(src, sizeof(dest), dest) < 0)
51                         // cannot convert. use src path
52                 else
53                         // can convert. use dest path
54  */
55 //LCOV_EXCL_START Untested function
56 API int storage_get_compat_internal_path(const char* origin, int len, char* compat)
57 {
58         int r = -1;
59         int str_len;
60         const char* str;
61
62         if (!compat || !origin) {
63                 _E("Invalid parameter");
64                 return -1;
65         }
66
67         if (getuid() <= USER_UID_START) {
68                 //LCOV_EXCL_START System Error
69                 _E("Only apps and user session daemons are allowed "
70                                 "to use storage_get_compat_internal_path()");
71                 return -1;
72                 //LCOV_EXCL_STOP
73         }
74
75         // this API works on place where compat path is bind-mounted
76         if (!is_compat_bind_mount()) {
77                 //LCOV_EXCL_START System Error
78                 _E("No compat bind mount");
79                 return -1;
80                 //LCOV_EXCL_STOP
81         }
82
83         str = tzplatform_uid_getenv(getuid(), TZ_USER_CONTENT);
84         str_len = strlen(str);
85         if (strncmp(origin, str, str_len) != 0) {
86                 _E("Failed to match TZ_USER_CONTENT");
87                 return -1;
88         }
89
90         r = snprintf(compat, len, "%s%s", COMPAT_DIR, origin + str_len);
91         if (r < 0) {
92                 //LCOV_EXCL_START System Error
93                 _E("Failed to create new path");
94                 return -1;
95                 //LCOV_EXCL_STOP
96         }
97
98         return 0;
99 }
100 //LCOV_EXCL_STOP
101
102 /*
103         Get Multi-user path from compat path
104         from /opt/usr/media/.. to TZ_USER_CONTENT/..
105         Input should be normalized path like /opt/usr/media (TODO: internal normalization)
106
107         Why this API should be provided?
108         In multi-user environment, each user has own compat content direcotry.(/opt/usr/media)
109         However, although some APIs send the compat path to system daemon,
110                 system daemon should access real path.
111
112         Usage:
113                 #include <storage-internal.h>
114
115                 char dest[100];
116                 if(storage_get_origin_internal_path(src, sizeof(dest), dest) < 0)
117                         // cannot convert. use src path
118                 else
119                         // can convert. use dest path
120 */
121 API int storage_get_origin_internal_path(const char* compat, int len, char* origin)
122 {
123         int r;
124         int compat_len;
125
126         if (!compat || !origin) {
127                 _E("Invalid parameter");
128                 return -1;
129         }
130
131         if (getuid() <= USER_UID_START) {
132                 //LCOV_EXCL_START System Error
133                 _E("Only apps and user session daemons are allowed "
134                                 "to use storage_get_origin_internal_path()");
135                 return -1;
136                 //LCOV_EXCL_STOP
137         }
138
139         // this API works on place where compat path is bind-mounted
140         if (!is_compat_bind_mount()) {
141                 //LCOV_EXCL_START System Error
142                 _E("no compat bind mount");
143                 return -1;
144                 //LCOV_EXCL_STOP
145         }
146
147         compat_len = strlen(COMPAT_DIR);
148         if (strncmp(compat, COMPAT_DIR, compat_len) != 0) {
149                 _E("failed to match COMPAT_DIR");
150                 return -1;
151         }
152
153         r = snprintf(origin, len, "%s%s", tzplatform_uid_getenv(getuid(), TZ_USER_CONTENT), compat + compat_len);
154         if (r < 0) {
155                 //LCOV_EXCL_START System Error
156                 _E("failed to create new path");
157                 return -1;
158                 //LCOV_EXCL_STOP
159         }
160
161         return 0;
162 }
163
164 API int storage_get_primary_sdcard(int *storage_id, char **path)
165 {
166         GVariant *result;
167         int ret;
168         char *mount_point = NULL;
169         int id;
170
171         if (!storage_id || !path)
172                 return STORAGE_ERROR_INVALID_PARAMETER;
173
174         if (!storage_ext_is_supported())
175                 return STORAGE_ERROR_NOT_SUPPORTED;
176
177         ret = dbus_handle_method_sync_with_reply_var(STORAGE_EXT_BUS_NAME,
178                         STORAGE_EXT_PATH_MANAGER,
179                         STORAGE_EXT_IFACE_MANAGER,
180                         "GetMmcPrimary",
181                         NULL,
182                         &result);
183         if (ret < 0) {
184                 //LCOV_EXCL_START System Error
185                 _E("Failed to get primary sdcard partition"); //LCOV_EXCL_LINE
186                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
187                 //LCOV_EXCL_STOP
188         }
189
190         if (!g_variant_get_safe(result, "(issssssisibii)",
191                         NULL, NULL, NULL,
192                         NULL, NULL,
193                         NULL, NULL,
194                         NULL, &mount_point,
195                         NULL, NULL,
196                         NULL, &id)) {
197                 g_variant_unref(result);
198                 return STORAGE_ERROR_OPERATION_FAILED;
199         }
200
201         g_variant_unref(result);
202
203         if (id < 0) {
204                 ret = STORAGE_ERROR_NO_DEVICE;
205                 goto out;
206         }
207
208         *path = strdup(mount_point);
209         if (*path == NULL) {
210                 ret = STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
211                 goto out;
212         }
213
214         *storage_id = id;
215
216         ret = STORAGE_ERROR_NONE;
217 out:
218         g_free(mount_point);
219
220         return ret;
221 }
222
223 API int storage_get_storage_level(const char *path, char **level)
224 {
225         int ret;
226
227         if (!level || !path)
228                 return STORAGE_ERROR_INVALID_PARAMETER;
229
230         ret = storage_ext_get_storage_level(path, level);
231         if (ret == -ENOMEM)
232                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
233         else if (ret == -EINVAL)
234                 return STORAGE_ERROR_INVALID_PARAMETER;
235         else if (ret < 0)
236                 return STORAGE_ERROR_OPERATION_FAILED;
237
238         return STORAGE_ERROR_NONE;
239 }
240
241 //LCOV_EXCL_START Not called callback
242 static void mount_mmc_cb(GVariant *var, void *user_data, GError *err)
243 {
244         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
245         int mmc_ret = -1;
246
247         _D("mount_mmc_cb called");
248
249         if (!var) {
250                 _E("no message [%s]", err->message);
251                 mmc_ret = -EBADMSG;
252                 goto exit;
253         }
254
255         g_variant_get(var, "(i)", &mmc_ret);
256
257         _I("Mount State : %d", mmc_ret);
258
259 exit:
260         if (var)
261                 g_variant_unref(var);
262         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
263 }
264 //LCOV_EXCL_STOP
265
266 API int storage_request_mount_mmc(struct mmc_contents *mmc_data)
267 {
268         void (*mount_cb)(GVariant *, void *, GError *) = NULL;
269         void *data = NULL;
270         char *path;
271         int ret;
272         int id;
273
274         if (mmc_data && mmc_data->mmc_cb) {
275                 _I("Mount callback exists");
276                 mount_cb = mount_mmc_cb;
277                 data = mmc_data;
278         }
279
280         ret = storage_get_primary_sdcard(&id, &path);
281         if (ret != STORAGE_ERROR_NONE)
282                 return ret;
283 //LCOV_EXCL_START System Error
284         if (path)
285                 free(path);
286 //LCOV_EXCL_STOP
287
288         ret = dbus_handle_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
289                         STORAGE_EXT_PATH_MANAGER,
290                         STORAGE_EXT_IFACE_MANAGER,
291                         "Mount",
292                         g_variant_new("(is)", id, ""),
293                         mount_cb,
294                         -1,
295                         data);
296
297         _I("Mount Request %s", ret == 0 ? "Success" : "Failed");
298
299         if (ret == -ENOMEM)
300                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
301         if (ret < 0)
302                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
303
304         return STORAGE_ERROR_NONE;
305 }
306
307 //LCOV_EXCL_START Not called callback
308 static void unmount_mmc_cb(GVariant *var, void *user_data, GError *err)
309 {
310         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
311         int mmc_ret;
312
313         _D("unmount_mmc_cb called");
314
315         if (!var) {
316                 _E("no message [%s]", err->message);
317                 mmc_ret = -EBADMSG;
318                 goto exit;
319         }
320
321         g_variant_get(var, "(i)", &mmc_ret);
322
323         _I("Unmount State : %d", mmc_ret);
324
325 exit:
326         if (var)
327                 g_variant_unref(var);
328         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
329 }
330 //LCOV_EXCL_STOP
331
332 API int storage_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
333 {
334         void (*unmount_cb)(GVariant *, void *, GError *) = NULL;
335         void *data = NULL;
336         char *path;
337         int ret;
338         int id;
339
340         if (option < 0 || option > 1)
341                 return STORAGE_ERROR_INVALID_PARAMETER;
342
343         if (mmc_data && mmc_data->mmc_cb) {
344                 _I("Unmount callback exists");
345                 unmount_cb = unmount_mmc_cb;
346                 data = mmc_data;
347         }
348
349         ret = storage_get_primary_sdcard(&id, &path);
350         if (ret != STORAGE_ERROR_NONE)
351                 return ret;
352 //LCOV_EXCL_START System Error
353         if (path)
354                 free(path);
355 //LCOV_EXCL_STOP
356
357         ret = dbus_handle_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
358                         STORAGE_EXT_PATH_MANAGER,
359                         STORAGE_EXT_IFACE_MANAGER,
360                         "Unmount",
361                         g_variant_new("(ii)", id, option),
362                         unmount_cb,
363                         -1,
364                         data);
365
366         _I("Unmount Request %s", ret == 0 ? "Success" : "Failed");
367
368         if (ret == -ENOMEM)
369                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
370         if (ret < 0)
371                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
372
373         return STORAGE_ERROR_NONE;
374 }
375
376 //LCOV_EXCL_START Not called callback
377 static void format_mmc_cb(GVariant *var, void *user_data, GError *err)
378 {
379         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
380         int mmc_ret;
381
382         _D("format_mmc_cb called");
383
384         if (!var) {
385                 _E("no message [%s]", err->message);
386                 mmc_ret = -EBADMSG;
387                 goto exit;
388         }
389
390         g_variant_get(var, "(i)", &mmc_ret);
391
392         _I("Format State : %d", mmc_ret);
393
394 exit:
395         if (var)
396                 g_variant_unref(var);
397         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
398 }
399 //LCOV_EXCL_STOP
400
401 API int storage_request_format_mmc(struct mmc_contents *mmc_data)
402 {
403         return storage_format_mmc(mmc_data, 1);
404 }
405
406 API int storage_format_mmc(struct mmc_contents *mmc_data, int option)
407 {
408         void (*format_cb)(GVariant *, void *, GError *) = NULL;
409         void *data = NULL;
410         char *path;
411         int ret;
412         int id;
413
414         if (option < 0 || option > 1)
415                 return STORAGE_ERROR_INVALID_PARAMETER;
416
417         if (mmc_data && mmc_data->mmc_cb) {
418                 _I("Format callback exists");
419                 format_cb = format_mmc_cb;
420                 data = mmc_data;
421         }
422
423         ret = storage_get_primary_sdcard(&id, &path);
424         if (ret != STORAGE_ERROR_NONE)
425                 return ret;
426 //LCOV_EXCL_START System Error
427         if (path)
428                 free(path);
429 //LCOV_EXCL_STOP
430
431         ret = dbus_handle_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
432                         STORAGE_EXT_PATH_MANAGER,
433                         STORAGE_EXT_IFACE_MANAGER,
434                         "Format",
435                         g_variant_new("(ii)", id, option),
436                         format_cb,
437                         FORMAT_TIMEOUT,
438                         data);
439
440         _I("Format Request %s", ret == 0 ? "Success" : "Failed");
441
442         if (ret == -ENOMEM)
443                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
444         if (ret < 0)
445                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
446
447         return STORAGE_ERROR_NONE;
448 }
449
450 API int storage_is_mounted_opt_usr(storage_part_mount_e *mounted)
451 {
452         blkid_cache cache = NULL;
453         blkid_dev_iterate iter;
454         blkid_dev dev;
455         int ret;
456         bool found = false;
457
458         if (!mounted)
459                 return STORAGE_ERROR_INVALID_PARAMETER;
460
461         ret = blkid_get_cache(&cache, NULL);
462         if (ret < 0) {
463                 _E("Failed to get cache"); //LCOV_EXCL_LINE
464                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
465                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
466         }
467
468         ret = blkid_probe_all(cache);
469         if (ret < 0) {
470                 _E("Failed to probe all block devices"); //LCOV_EXCL_LINE
471                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
472                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
473         }
474
475         iter = blkid_dev_iterate_begin(cache);
476         if (!iter) {
477                 _E("Failed to get iterate"); //LCOV_EXCL_LINE
478                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
479                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
480         }
481
482         ret = blkid_dev_set_search(iter, "LABEL", USER_PARTITION);
483         if (blkid_dev_next(iter, &dev) == 0) {
484                 dev = blkid_verify(cache, dev);
485                 if (dev) {
486                         found = true;
487                         _D("Partition for user data is found(LABEL=user)");
488                 }
489         }
490         blkid_dev_iterate_end(iter);
491
492         if (!found) {
493                 iter = blkid_dev_iterate_begin(cache);
494                 if (!iter) {
495                         _E("Failed to get iterate"); //LCOV_EXCL_LINE
496                         *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
497                         return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
498                 }
499
500                 ret = blkid_dev_set_search(iter, "PARTLABEL", USER_PARTITION);
501                 if (blkid_dev_next(iter, &dev) == 0) {
502                         dev = blkid_verify(cache, dev);
503                         if (dev) {
504                                 found = true;
505                                 _D("Partition for user data is found(PARTLABEL=user)");
506                         }
507                 }
508                 blkid_dev_iterate_end(iter);
509         }
510
511         blkid_put_cache(cache);
512
513         if (found) {
514                 ret = mount_check(tzplatform_getenv(TZ_SYS_USER));
515                 if (ret)
516                         *mounted = STORAGE_PART_MOUNTED;
517                 else
518                         *mounted = STORAGE_PART_NOT_MOUNTED;
519         } else
520                 *mounted = STORAGE_PART_NOT_SUPPORTED;
521
522         return STORAGE_ERROR_NONE;
523 }