Change tzplatform_getenv to tzplatform_uid_getenv
[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
26 #include "common.h"
27 #include "list.h"
28 #include "log.h"
29 #include "storage-internal.h"
30 #include "storage-external-dbus.h"
31
32 #define FORMAT_TIMEOUT  (120*1000)
33
34 /*
35         Get compat path from origin Multi-user path
36         from TZ_USER_CONTENT/.. to /opt/usr/media/..
37         Input should be normalized path like /opt/usr/home/owner/media (TODO: internal normalization)
38
39         Why this API should be provided?
40         In multi-user environment, each user has own compat content direcotry.(/opt/usr/media)
41         However, although system daemon operates real path,
42                 system daemon needs to provide compat path to App if the real path is converted.
43
44         Usage:
45                 #include <storage-internal.h>
46
47                 char dest[100];
48                 if(storage_get_compat_internal_path(src, sizeof(dest), dest) < 0)
49                         // cannot convert. use src path
50                 else
51                         // can convert. use dest path
52  */
53 //LCOV_EXCL_START Untested function
54 API int storage_get_compat_internal_path(const char* origin, int len, char* compat)
55 {
56         int r = -1;
57         int str_len;
58         const char* str;
59
60         if (!compat || !origin) {
61                 _E("Invalid parameter");
62                 return -1;
63         }
64
65         if (getuid() <= USER_UID_START) {
66                 //LCOV_EXCL_START System Error
67                 _E("Only apps and user session daemons are allowed "
68                                 "to use storage_get_compat_internal_path()");
69                 return -1;
70                 //LCOV_EXCL_STOP
71         }
72
73         // this API works on place where compat path is bind-mounted
74         if (!is_compat_bind_mount()) {
75                 //LCOV_EXCL_START System Error
76                 _E("No compat bind mount");
77                 return -1;
78                 //LCOV_EXCL_STOP
79         }
80
81         str = tzplatform_uid_getenv(getuid(), TZ_USER_CONTENT);
82         str_len = strlen(str);
83         if (strncmp(origin, str, str_len) != 0) {
84                 _E("Failed to match TZ_USER_CONTENT");
85                 return -1;
86         }
87
88         r = snprintf(compat, len, "%s%s", COMPAT_DIR, origin + str_len);
89         if (r < 0) {
90                 //LCOV_EXCL_START System Error
91                 _E("Failed to create new path");
92                 return -1;
93                 //LCOV_EXCL_STOP
94         }
95
96         return 0;
97 }
98 //LCOV_EXCL_STOP
99
100 /*
101         Get Multi-user path from compat path
102         from /opt/usr/media/.. to TZ_USER_CONTENT/..
103         Input should be normalized path like /opt/usr/media (TODO: internal normalization)
104
105         Why this API should be provided?
106         In multi-user environment, each user has own compat content direcotry.(/opt/usr/media)
107         However, although some APIs send the compat path to system daemon,
108                 system daemon should access real path.
109
110         Usage:
111                 #include <storage-internal.h>
112
113                 char dest[100];
114                 if(storage_get_origin_internal_path(src, sizeof(dest), dest) < 0)
115                         // cannot convert. use src path
116                 else
117                         // can convert. use dest path
118 */
119 API int storage_get_origin_internal_path(const char* compat, int len, char* origin)
120 {
121         int r;
122         int compat_len;
123
124         if (!compat || !origin) {
125                 _E("Invalid parameter");
126                 return -1;
127         }
128
129         if (getuid() <= USER_UID_START) {
130                 //LCOV_EXCL_START System Error
131                 _E("Only apps and user session daemons are allowed "
132                                 "to use storage_get_origin_internal_path()");
133                 return -1;
134                 //LCOV_EXCL_STOP
135         }
136
137         // this API works on place where compat path is bind-mounted
138         if (!is_compat_bind_mount()) {
139                 //LCOV_EXCL_START System Error
140                 _E("no compat bind mount");
141                 return -1;
142                 //LCOV_EXCL_STOP
143         }
144
145         compat_len = strlen(COMPAT_DIR);
146         if (strncmp(compat, COMPAT_DIR, compat_len) != 0) {
147                 _E("failed to match COMPAT_DIR");
148                 return -1;
149         }
150
151         r = snprintf(origin, len, "%s%s", tzplatform_uid_getenv(getuid(), TZ_USER_CONTENT), compat + compat_len);
152         if (r < 0) {
153                 //LCOV_EXCL_START System Error
154                 _E("failed to create new path");
155                 return -1;
156                 //LCOV_EXCL_STOP
157         }
158
159         return 0;
160 }
161
162 API int storage_get_primary_sdcard(int *storage_id, char **path)
163 {
164         GVariant *result;
165         storage_ext_device info;
166
167         if (!storage_id || !path)
168                 return STORAGE_ERROR_INVALID_PARAMETER;
169
170         if (!storage_ext_is_supported())
171                 return STORAGE_ERROR_NO_DEVICE;
172
173         result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
174                         STORAGE_EXT_PATH_MANAGER,
175                         STORAGE_EXT_IFACE_MANAGER,
176                         "GetMmcPrimary",
177                         NULL);
178         if (!result) {
179                 //LCOV_EXCL_START System Error
180                 _E("Failed to get primary sdcard partition"); //LCOV_EXCL_LINE
181                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
182                 //LCOV_EXCL_STOP
183         }
184
185         g_variant_get(result, "(issssssisibii)",
186                         &info.type, &info.devnode, &info.syspath,
187                         &info.fs_usage, &info.fs_type,
188                         &info.fs_version, &info.fs_uuid,
189                         &info.readonly, &info.mount_point,
190                         &info.state, &info.primary,
191                         &info.flags, &info.storage_id);
192
193         g_variant_unref(result);
194
195         if (info.storage_id < 0)
196                 return STORAGE_ERROR_NO_DEVICE;
197
198         *path = strdup(info.mount_point);
199         if (*path == NULL)
200                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
201
202         *storage_id = info.storage_id;
203
204         return STORAGE_ERROR_NONE;
205 }
206
207 API int storage_get_storage_level(const char *path, char **level)
208 {
209         int ret;
210
211         if (!level || !path)
212                 return STORAGE_ERROR_INVALID_PARAMETER;
213
214         ret = storage_ext_get_storage_level(path, level);
215         if (ret == -ENOMEM)
216                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
217         else if (ret == -EINVAL)
218                 return STORAGE_ERROR_INVALID_PARAMETER;
219         else if (ret < 0)
220                 return STORAGE_ERROR_OPERATION_FAILED;
221
222         return STORAGE_ERROR_NONE;
223 }
224
225 static void mount_mmc_cb(GVariant *var, void *user_data, GError *err)
226 {
227         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
228         int mmc_ret = -1;
229
230         _D("mount_mmc_cb called");
231
232         if (!var) {
233                 _E("no message [%s]", err->message);
234                 mmc_ret = -EBADMSG;
235                 goto exit;
236         }
237
238         g_variant_get(var, "(i)", &mmc_ret);
239
240         _I("Mount State : %d", mmc_ret);
241
242 exit:
243         if (var)
244                 g_variant_unref(var);
245         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
246 }
247
248 API int storage_request_mount_mmc(struct mmc_contents *mmc_data)
249 {
250         void (*mount_cb)(GVariant *, void *, GError *) = NULL;
251         void *data = NULL;
252         char *path;
253         int ret;
254         int id;
255
256         if (mmc_data && mmc_data->mmc_cb) {
257                 _I("Mount callback exists");
258                 mount_cb = mount_mmc_cb;
259                 data = mmc_data;
260         }
261
262         ret = storage_get_primary_sdcard(&id, &path);
263         if (ret != STORAGE_ERROR_NONE)
264                 return ret;
265
266         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
267                         STORAGE_EXT_PATH_MANAGER,
268                         STORAGE_EXT_IFACE_MANAGER,
269                         "Mount",
270                         g_variant_new("(is)", id, ""),
271                         mount_cb,
272                         -1,
273                         data);
274
275         _I("Mount Request %s", ret == 0 ? "Success" : "Failed");
276
277         if (ret == -ENOMEM)
278                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
279         if (ret < 0)
280                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
281
282         return STORAGE_ERROR_NONE;
283 }
284
285 static void unmount_mmc_cb(GVariant *var, void *user_data, GError *err)
286 {
287         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
288         int mmc_ret;
289
290         _D("unmount_mmc_cb called");
291
292         if (!var) {
293                 _E("no message [%s]", err->message);
294                 mmc_ret = -EBADMSG;
295                 goto exit;
296         }
297
298         g_variant_get(var, "(i)", &mmc_ret);
299
300         _I("Unmount State : %d", mmc_ret);
301
302 exit:
303         if (var)
304                 g_variant_unref(var);
305         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
306 }
307
308 API int storage_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
309 {
310         void (*unmount_cb)(GVariant *, void *, GError *) = NULL;
311         void *data = NULL;
312         char *path;
313         int ret;
314         int id;
315
316         if (option < 0 || option > 1)
317                 return STORAGE_ERROR_INVALID_PARAMETER;
318
319         if (mmc_data && mmc_data->mmc_cb) {
320                 _I("Unmount callback exists");
321                 unmount_cb = unmount_mmc_cb;
322                 data = mmc_data;
323         }
324
325         ret = storage_get_primary_sdcard(&id, &path);
326         if (ret != STORAGE_ERROR_NONE)
327                 return ret;
328
329         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
330                         STORAGE_EXT_PATH_MANAGER,
331                         STORAGE_EXT_IFACE_MANAGER,
332                         "Unmount",
333                         g_variant_new("(ii)", id, option),
334                         unmount_cb,
335                         -1,
336                         data);
337
338         _I("Unmount Request %s", ret == 0 ? "Success" : "Failed");
339
340         if (ret == -ENOMEM)
341                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
342         if (ret < 0)
343                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
344
345         return STORAGE_ERROR_NONE;
346 }
347
348 static void format_mmc_cb(GVariant *var, void *user_data, GError *err)
349 {
350         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
351         int mmc_ret;
352
353         _D("format_mmc_cb called");
354
355         if (!var) {
356                 _E("no message [%s]", err->message);
357                 mmc_ret = -EBADMSG;
358                 goto exit;
359         }
360
361         g_variant_get(var, "(i)", &mmc_ret);
362
363         _I("Format State : %d", mmc_ret);
364
365 exit:
366         if (var)
367                 g_variant_unref(var);
368         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
369 }
370
371 API int storage_request_format_mmc(struct mmc_contents *mmc_data)
372 {
373         return storage_format_mmc(mmc_data, 1);
374 }
375
376 API int storage_format_mmc(struct mmc_contents *mmc_data, int option)
377 {
378         void (*format_cb)(GVariant *, void *, GError *) = NULL;
379         void *data = NULL;
380         char *path;
381         int ret;
382         int id;
383
384         if (option < 0 || option > 1)
385                 return STORAGE_ERROR_INVALID_PARAMETER;
386
387         if (mmc_data && mmc_data->mmc_cb) {
388                 _I("Format callback exists");
389                 format_cb = format_mmc_cb;
390                 data = mmc_data;
391         }
392
393         ret = storage_get_primary_sdcard(&id, &path);
394         if (ret != STORAGE_ERROR_NONE)
395                 return ret;
396
397         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
398                         STORAGE_EXT_PATH_MANAGER,
399                         STORAGE_EXT_IFACE_MANAGER,
400                         "Format",
401                         g_variant_new("(ii)", id, option),
402                         format_cb,
403                         FORMAT_TIMEOUT,
404                         data);
405
406         _I("Format Request %s", ret == 0 ? "Success" : "Failed");
407
408         if (ret == -ENOMEM)
409                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
410         if (ret < 0)
411                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
412
413         return STORAGE_ERROR_NONE;
414 }