Remove resource leak
[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 //LCOV_EXCL_START System Error
270         if (path)
271                 free(path);
272 //LCOV_EXCL_STOP
273
274         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
275                         STORAGE_EXT_PATH_MANAGER,
276                         STORAGE_EXT_IFACE_MANAGER,
277                         "Mount",
278                         g_variant_new("(is)", id, ""),
279                         mount_cb,
280                         -1,
281                         data);
282
283         _I("Mount Request %s", ret == 0 ? "Success" : "Failed");
284
285         if (ret == -ENOMEM)
286                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
287         if (ret < 0)
288                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
289
290         return STORAGE_ERROR_NONE;
291 }
292
293 //LCOV_EXCL_START Not called callback
294 static void unmount_mmc_cb(GVariant *var, void *user_data, GError *err)
295 {
296         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
297         int mmc_ret;
298
299         _D("unmount_mmc_cb called");
300
301         if (!var) {
302                 _E("no message [%s]", err->message);
303                 mmc_ret = -EBADMSG;
304                 goto exit;
305         }
306
307         g_variant_get(var, "(i)", &mmc_ret);
308
309         _I("Unmount State : %d", mmc_ret);
310
311 exit:
312         if (var)
313                 g_variant_unref(var);
314         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
315 }
316 //LCOV_EXCL_STOP
317
318 API int storage_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
319 {
320         void (*unmount_cb)(GVariant *, void *, GError *) = NULL;
321         void *data = NULL;
322         char *path;
323         int ret;
324         int id;
325
326         if (option < 0 || option > 1)
327                 return STORAGE_ERROR_INVALID_PARAMETER;
328
329         if (mmc_data && mmc_data->mmc_cb) {
330                 _I("Unmount callback exists");
331                 unmount_cb = unmount_mmc_cb;
332                 data = mmc_data;
333         }
334
335         ret = storage_get_primary_sdcard(&id, &path);
336         if (ret != STORAGE_ERROR_NONE)
337                 return ret;
338 //LCOV_EXCL_START System Error
339         if (path)
340                 free(path);
341 //LCOV_EXCL_STOP
342
343         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
344                         STORAGE_EXT_PATH_MANAGER,
345                         STORAGE_EXT_IFACE_MANAGER,
346                         "Unmount",
347                         g_variant_new("(ii)", id, option),
348                         unmount_cb,
349                         -1,
350                         data);
351
352         _I("Unmount Request %s", ret == 0 ? "Success" : "Failed");
353
354         if (ret == -ENOMEM)
355                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
356         if (ret < 0)
357                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
358
359         return STORAGE_ERROR_NONE;
360 }
361
362 //LCOV_EXCL_START Not called callback
363 static void format_mmc_cb(GVariant *var, void *user_data, GError *err)
364 {
365         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
366         int mmc_ret;
367
368         _D("format_mmc_cb called");
369
370         if (!var) {
371                 _E("no message [%s]", err->message);
372                 mmc_ret = -EBADMSG;
373                 goto exit;
374         }
375
376         g_variant_get(var, "(i)", &mmc_ret);
377
378         _I("Format State : %d", mmc_ret);
379
380 exit:
381         if (var)
382                 g_variant_unref(var);
383         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
384 }
385 //LCOV_EXCL_STOP
386
387 API int storage_request_format_mmc(struct mmc_contents *mmc_data)
388 {
389         return storage_format_mmc(mmc_data, 1);
390 }
391
392 API int storage_format_mmc(struct mmc_contents *mmc_data, int option)
393 {
394         void (*format_cb)(GVariant *, void *, GError *) = NULL;
395         void *data = NULL;
396         char *path;
397         int ret;
398         int id;
399
400         if (option < 0 || option > 1)
401                 return STORAGE_ERROR_INVALID_PARAMETER;
402
403         if (mmc_data && mmc_data->mmc_cb) {
404                 _I("Format callback exists");
405                 format_cb = format_mmc_cb;
406                 data = mmc_data;
407         }
408
409         ret = storage_get_primary_sdcard(&id, &path);
410         if (ret != STORAGE_ERROR_NONE)
411                 return ret;
412 //LCOV_EXCL_START System Error
413         if (path)
414                 free(path);
415 //LCOV_EXCL_STOP
416
417         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
418                         STORAGE_EXT_PATH_MANAGER,
419                         STORAGE_EXT_IFACE_MANAGER,
420                         "Format",
421                         g_variant_new("(ii)", id, option),
422                         format_cb,
423                         FORMAT_TIMEOUT,
424                         data);
425
426         _I("Format Request %s", ret == 0 ? "Success" : "Failed");
427
428         if (ret == -ENOMEM)
429                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
430         if (ret < 0)
431                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
432
433         return STORAGE_ERROR_NONE;
434 }
435
436 API int storage_is_mounted_opt_usr(storage_part_mount_e *mounted)
437 {
438         blkid_cache cache = NULL;
439         blkid_dev_iterate iter;
440         blkid_dev dev;
441         int ret;
442         bool found = false;
443
444         if (!mounted)
445                 return STORAGE_ERROR_INVALID_PARAMETER;
446
447         ret = blkid_get_cache(&cache, NULL);
448         if (ret < 0) {
449                 _E("Failed to get cache"); //LCOV_EXCL_LINE
450                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
451                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
452         }
453
454         ret = blkid_probe_all(cache);
455         if (ret < 0) {
456                 _E("Failed to probe all block devices"); //LCOV_EXCL_LINE
457                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
458                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
459         }
460
461         iter = blkid_dev_iterate_begin(cache);
462         if (!iter) {
463                 _E("Failed to get iterate"); //LCOV_EXCL_LINE
464                 *mounted = STORAGE_PART_ERROR; //LCOV_EXCL_LINE
465                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
466         }
467
468         ret = blkid_dev_set_search(iter, "LABEL", USER_PARTITION);
469         if (blkid_dev_next(iter, &dev) == 0) {
470                 dev = blkid_verify(cache, dev);
471                 if (dev) {
472                         found = true;
473                         _D("Partition for user data is found(LABEL=user)");
474                 }
475         }
476         blkid_dev_iterate_end(iter);
477
478         if (!found) {
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 = blkid_dev_set_search(iter, "PARTLABEL", USER_PARTITION);
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(PARTLABEL=user)");
492                         }
493                 }
494                 blkid_dev_iterate_end(iter);
495         }
496
497         blkid_put_cache(cache);
498
499         if (found) {
500                 ret = mount_check(tzplatform_getenv(TZ_SYS_USER));
501                 if (ret)
502                         *mounted = STORAGE_PART_MOUNTED;
503                 else
504                         *mounted = STORAGE_PART_NOT_MOUNTED;
505         } else
506                 *mounted = STORAGE_PART_NOT_SUPPORTED;
507
508         return STORAGE_ERROR_NONE;
509 }