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