Check parameter and return error
[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
27 #include "common.h"
28 #include "list.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         storage_ext_device info;
168
169         if (!storage_id || !path)
170                 return STORAGE_ERROR_INVALID_PARAMETER;
171
172         if (!storage_ext_is_supported())
173                 return STORAGE_ERROR_NOT_SUPPORTED;
174
175         result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
176                         STORAGE_EXT_PATH_MANAGER,
177                         STORAGE_EXT_IFACE_MANAGER,
178                         "GetMmcPrimary",
179                         NULL);
180         if (!result) {
181                 //LCOV_EXCL_START System Error
182                 _E("Failed to get primary sdcard partition"); //LCOV_EXCL_LINE
183                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
184                 //LCOV_EXCL_STOP
185         }
186
187         g_variant_get(result, "(issssssisibii)",
188                         &info.type, &info.devnode, &info.syspath,
189                         &info.fs_usage, &info.fs_type,
190                         &info.fs_version, &info.fs_uuid,
191                         &info.readonly, &info.mount_point,
192                         &info.state, &info.primary,
193                         &info.flags, &info.storage_id);
194
195         g_variant_unref(result);
196
197         if (info.storage_id < 0)
198                 return STORAGE_ERROR_NO_DEVICE;
199
200         *path = strdup(info.mount_point);
201         if (*path == NULL)
202                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
203
204         *storage_id = info.storage_id;
205
206         return STORAGE_ERROR_NONE;
207 }
208
209 API int storage_get_storage_level(const char *path, char **level)
210 {
211         int ret;
212
213         if (!level || !path)
214                 return STORAGE_ERROR_INVALID_PARAMETER;
215
216         ret = storage_ext_get_storage_level(path, level);
217         if (ret == -ENOMEM)
218                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
219         else if (ret == -EINVAL)
220                 return STORAGE_ERROR_INVALID_PARAMETER;
221         else if (ret < 0)
222                 return STORAGE_ERROR_OPERATION_FAILED;
223
224         return STORAGE_ERROR_NONE;
225 }
226
227 //LCOV_EXCL_START Not called callback
228 static void mount_mmc_cb(GVariant *var, void *user_data, GError *err)
229 {
230         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
231         int mmc_ret = -1;
232
233         _D("mount_mmc_cb called");
234
235         if (!var) {
236                 _E("no message [%s]", err->message);
237                 mmc_ret = -EBADMSG;
238                 goto exit;
239         }
240
241         g_variant_get(var, "(i)", &mmc_ret);
242
243         _I("Mount State : %d", mmc_ret);
244
245 exit:
246         if (var)
247                 g_variant_unref(var);
248         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
249 }
250 //LCOV_EXCL_STOP
251
252 API int storage_request_mount_mmc(struct mmc_contents *mmc_data)
253 {
254         void (*mount_cb)(GVariant *, void *, GError *) = NULL;
255         void *data = NULL;
256         char *path;
257         int ret;
258         int id;
259
260         if (mmc_data && mmc_data->mmc_cb) {
261                 _I("Mount callback exists");
262                 mount_cb = mount_mmc_cb;
263                 data = mmc_data;
264         }
265
266         ret = storage_get_primary_sdcard(&id, &path);
267         if (ret != STORAGE_ERROR_NONE)
268                 return ret;
269
270         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
271                         STORAGE_EXT_PATH_MANAGER,
272                         STORAGE_EXT_IFACE_MANAGER,
273                         "Mount",
274                         g_variant_new("(is)", id, ""),
275                         mount_cb,
276                         -1,
277                         data);
278
279         _I("Mount Request %s", ret == 0 ? "Success" : "Failed");
280
281         if (ret == -ENOMEM)
282                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
283         if (ret < 0)
284                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
285
286         return STORAGE_ERROR_NONE;
287 }
288
289 //LCOV_EXCL_START Not called callback
290 static void unmount_mmc_cb(GVariant *var, void *user_data, GError *err)
291 {
292         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
293         int mmc_ret;
294
295         _D("unmount_mmc_cb called");
296
297         if (!var) {
298                 _E("no message [%s]", err->message);
299                 mmc_ret = -EBADMSG;
300                 goto exit;
301         }
302
303         g_variant_get(var, "(i)", &mmc_ret);
304
305         _I("Unmount State : %d", mmc_ret);
306
307 exit:
308         if (var)
309                 g_variant_unref(var);
310         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
311 }
312 //LCOV_EXCL_STOP
313
314 API int storage_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
315 {
316         void (*unmount_cb)(GVariant *, void *, GError *) = NULL;
317         void *data = NULL;
318         char *path;
319         int ret;
320         int id;
321
322         if (option < 0 || option > 1)
323                 return STORAGE_ERROR_INVALID_PARAMETER;
324
325         if (mmc_data && mmc_data->mmc_cb) {
326                 _I("Unmount callback exists");
327                 unmount_cb = unmount_mmc_cb;
328                 data = mmc_data;
329         }
330
331         ret = storage_get_primary_sdcard(&id, &path);
332         if (ret != STORAGE_ERROR_NONE)
333                 return ret;
334
335         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
336                         STORAGE_EXT_PATH_MANAGER,
337                         STORAGE_EXT_IFACE_MANAGER,
338                         "Unmount",
339                         g_variant_new("(ii)", id, option),
340                         unmount_cb,
341                         -1,
342                         data);
343
344         _I("Unmount Request %s", ret == 0 ? "Success" : "Failed");
345
346         if (ret == -ENOMEM)
347                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
348         if (ret < 0)
349                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
350
351         return STORAGE_ERROR_NONE;
352 }
353
354 //LCOV_EXCL_START Not called callback
355 static void format_mmc_cb(GVariant *var, void *user_data, GError *err)
356 {
357         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
358         int mmc_ret;
359
360         _D("format_mmc_cb called");
361
362         if (!var) {
363                 _E("no message [%s]", err->message);
364                 mmc_ret = -EBADMSG;
365                 goto exit;
366         }
367
368         g_variant_get(var, "(i)", &mmc_ret);
369
370         _I("Format State : %d", mmc_ret);
371
372 exit:
373         if (var)
374                 g_variant_unref(var);
375         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
376 }
377 //LCOV_EXCL_STOP
378
379 API int storage_request_format_mmc(struct mmc_contents *mmc_data)
380 {
381         return storage_format_mmc(mmc_data, 1);
382 }
383
384 API int storage_format_mmc(struct mmc_contents *mmc_data, int option)
385 {
386         void (*format_cb)(GVariant *, void *, GError *) = NULL;
387         void *data = NULL;
388         char *path;
389         int ret;
390         int id;
391
392         if (option < 0 || option > 1)
393                 return STORAGE_ERROR_INVALID_PARAMETER;
394
395         if (mmc_data && mmc_data->mmc_cb) {
396                 _I("Format callback exists");
397                 format_cb = format_mmc_cb;
398                 data = mmc_data;
399         }
400
401         ret = storage_get_primary_sdcard(&id, &path);
402         if (ret != STORAGE_ERROR_NONE)
403                 return ret;
404
405         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
406                         STORAGE_EXT_PATH_MANAGER,
407                         STORAGE_EXT_IFACE_MANAGER,
408                         "Format",
409                         g_variant_new("(ii)", id, option),
410                         format_cb,
411                         FORMAT_TIMEOUT,
412                         data);
413
414         _I("Format Request %s", ret == 0 ? "Success" : "Failed");
415
416         if (ret == -ENOMEM)
417                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
418         if (ret < 0)
419                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
420
421         return STORAGE_ERROR_NONE;
422 }
423
424 API int storage_is_mounted_opt_usr(storage_part_mount_e *mounted)
425 {
426         blkid_cache cache = NULL;
427         blkid_dev_iterate iter;
428         blkid_dev dev;
429         int ret;
430         bool found = false;
431
432         if (!mounted)
433                 return STORAGE_ERROR_INVALID_PARAMETER;
434
435         ret = blkid_get_cache(&cache, NULL);
436         if (ret < 0) {
437                 _E("Failed to get cache"); //LCOV_EXCL_LINE
438                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
439                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
440         }
441
442         ret = blkid_probe_all(cache);
443         if (ret < 0) {
444                 _E("Failed to probe all block devices"); //LCOV_EXCL_LINE
445                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
446                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
447         }
448
449         iter = blkid_dev_iterate_begin(cache);
450         if (!iter) {
451                 _E("Failed to get iterate"); //LCOV_EXCL_LINE
452                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
453                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
454         }
455
456         ret = blkid_dev_set_search(iter, "LABEL", USER_PARTITION);
457         if (blkid_dev_next(iter, &dev) == 0) {
458                 dev = blkid_verify(cache, dev);
459                 if (dev) {
460                         found = true;
461                         _D("Partition for user data is found(LABEL=user)");
462                 }
463         }
464         blkid_dev_iterate_end(iter);
465
466         if (!found) {
467                 iter = blkid_dev_iterate_begin(cache);
468                 if (!iter) {
469                         _E("Failed to get iterate"); //LCOV_EXCL_LINE
470                         *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
471                         return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
472                 }
473
474                 ret = blkid_dev_set_search(iter, "PARTLABEL", USER_PARTITION);
475                 if (blkid_dev_next(iter, &dev) == 0) {
476                         dev = blkid_verify(cache, dev);
477                         if (dev) {
478                                 found = true;
479                                 _D("Partition for user data is found(PARTLABEL=user)");
480                         }
481                 }
482                 blkid_dev_iterate_end(iter);
483         }
484
485         blkid_put_cache(cache);
486
487         if (found) {
488                 ret = mount_check(tzplatform_getenv(TZ_SYS_USER));
489                 if (ret)
490                         *mounted = STORAGE_PART_MOUNTED;
491                 else
492                         *mounted = STORAGE_PART_NOT_MOUNTED;
493         } else
494                 *mounted = STORAGE_PART_NOT_SUPPORTED;
495
496         return STORAGE_ERROR_NONE;
497 }