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