Check block module enabled before sending GetMmcPrimary dbus method
[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         if (!storage_ext_is_supported())
153                 return STORAGE_ERROR_NO_DEVICE;
154
155         result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
156                         STORAGE_EXT_PATH_MANAGER,
157                         STORAGE_EXT_IFACE_MANAGER,
158                         "GetMmcPrimary",
159                         NULL);
160         if (!result) {
161                 //LCOV_EXCL_START System Error
162                 _E("Failed to get primary sdcard partition"); //LCOV_EXCL_LINE
163                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
164                 //LCOV_EXCL_STOP
165         }
166
167         g_variant_get(result, "(issssssisibii)",
168                         &info.type, &info.devnode, &info.syspath,
169                         &info.fs_usage, &info.fs_type,
170                         &info.fs_version, &info.fs_uuid,
171                         &info.readonly, &info.mount_point,
172                         &info.state, &info.primary,
173                         &info.flags, &info.storage_id);
174
175         g_variant_unref(result);
176
177         if (info.storage_id < 0)
178                 return STORAGE_ERROR_NO_DEVICE;
179
180         *path = strdup(info.mount_point);
181         if (*path == NULL)
182                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
183
184         *storage_id = info.storage_id;
185
186         return STORAGE_ERROR_NONE;
187 }
188
189 API int storage_get_storage_level(const char *path, char **level)
190 {
191         int ret;
192
193         if (!level || !path)
194                 return STORAGE_ERROR_INVALID_PARAMETER;
195
196         ret = storage_ext_get_storage_level(path, level);
197         if (ret == -ENOMEM)
198                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
199         else if (ret == -EINVAL)
200                 return STORAGE_ERROR_INVALID_PARAMETER;
201         else if (ret < 0)
202                 return STORAGE_ERROR_OPERATION_FAILED;
203
204         return STORAGE_ERROR_NONE;
205 }
206
207 static void mount_mmc_cb(GVariant *var, void *user_data, GError *err)
208 {
209         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
210         int mmc_ret = -1;
211
212         _D("mount_mmc_cb called");
213
214         if (!var) {
215                 _E("no message [%s]", err->message);
216                 mmc_ret = -EBADMSG;
217                 goto exit;
218         }
219
220         g_variant_get(var, "(i)", &mmc_ret);
221
222         _I("Mount State : %d", mmc_ret);
223
224 exit:
225         if (var)
226                 g_variant_unref(var);
227         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
228 }
229
230 API int storage_request_mount_mmc(struct mmc_contents *mmc_data)
231 {
232         void (*mount_cb)(GVariant *, void *, GError *) = NULL;
233         void *data = NULL;
234         char *path;
235         int ret;
236         int id;
237
238         if (mmc_data && mmc_data->mmc_cb) {
239                 _I("Mount callback exists");
240                 mount_cb = mount_mmc_cb;
241                 data = mmc_data;
242         }
243
244         ret = storage_get_primary_sdcard(&id, &path);
245         if (ret != STORAGE_ERROR_NONE)
246                 return ret;
247
248         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
249                         STORAGE_EXT_PATH_MANAGER,
250                         STORAGE_EXT_IFACE_MANAGER,
251                         "Mount",
252                         g_variant_new("(is)", id, ""),
253                         mount_cb,
254                         -1,
255                         data);
256
257         _I("Mount Request %s", ret == 0 ? "Success" : "Failed");
258
259         if (ret == -ENOMEM)
260                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
261         if (ret < 0)
262                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
263
264         return STORAGE_ERROR_NONE;
265 }
266
267 static void unmount_mmc_cb(GVariant *var, void *user_data, GError *err)
268 {
269         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
270         int mmc_ret;
271
272         _D("unmount_mmc_cb called");
273
274         if (!var) {
275                 _E("no message [%s]", err->message);
276                 mmc_ret = -EBADMSG;
277                 goto exit;
278         }
279
280         g_variant_get(var, "(i)", &mmc_ret);
281
282         _I("Unmount State : %d", mmc_ret);
283
284 exit:
285         if (var)
286                 g_variant_unref(var);
287         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
288 }
289
290 API int storage_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
291 {
292         void (*unmount_cb)(GVariant *, void *, GError *) = NULL;
293         void *data = NULL;
294         char *path;
295         int ret;
296         int id;
297
298         if (option < 0 || option > 1)
299                 return STORAGE_ERROR_INVALID_PARAMETER;
300
301         if (mmc_data && mmc_data->mmc_cb) {
302                 _I("Unmount callback exists");
303                 unmount_cb = unmount_mmc_cb;
304                 data = mmc_data;
305         }
306
307         ret = storage_get_primary_sdcard(&id, &path);
308         if (ret != STORAGE_ERROR_NONE)
309                 return ret;
310
311         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
312                         STORAGE_EXT_PATH_MANAGER,
313                         STORAGE_EXT_IFACE_MANAGER,
314                         "Unmount",
315                         g_variant_new("(ii)", id, option),
316                         unmount_cb,
317                         -1,
318                         data);
319
320         _I("Unmount Request %s", ret == 0 ? "Success" : "Failed");
321
322         if (ret == -ENOMEM)
323                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
324         if (ret < 0)
325                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
326
327         return STORAGE_ERROR_NONE;
328 }
329
330 static void format_mmc_cb(GVariant *var, void *user_data, GError *err)
331 {
332         struct mmc_contents *mmc_data = (struct mmc_contents*)user_data;
333         int mmc_ret;
334
335         _D("format_mmc_cb called");
336
337         if (!var) {
338                 _E("no message [%s]", err->message);
339                 mmc_ret = -EBADMSG;
340                 goto exit;
341         }
342
343         g_variant_get(var, "(i)", &mmc_ret);
344
345         _I("Format State : %d", mmc_ret);
346
347 exit:
348         if (var)
349                 g_variant_unref(var);
350         (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data);
351 }
352
353 API int storage_request_format_mmc(struct mmc_contents *mmc_data)
354 {
355         return storage_format_mmc(mmc_data, 1);
356 }
357
358 API int storage_format_mmc(struct mmc_contents *mmc_data, int option)
359 {
360         void (*format_cb)(GVariant *, void *, GError *) = NULL;
361         void *data = NULL;
362         char *path;
363         int ret;
364         int id;
365
366         if (option < 0 || option > 1)
367                 return STORAGE_ERROR_INVALID_PARAMETER;
368
369         if (mmc_data && mmc_data->mmc_cb) {
370                 _I("Format callback exists");
371                 format_cb = format_mmc_cb;
372                 data = mmc_data;
373         }
374
375         ret = storage_get_primary_sdcard(&id, &path);
376         if (ret != STORAGE_ERROR_NONE)
377                 return ret;
378
379         ret = dbus_method_async_with_reply_var(STORAGE_EXT_BUS_NAME,
380                         STORAGE_EXT_PATH_MANAGER,
381                         STORAGE_EXT_IFACE_MANAGER,
382                         "Format",
383                         g_variant_new("(ii)", id, option),
384                         format_cb,
385                         FORMAT_TIMEOUT,
386                         data);
387
388         _I("Format Request %s", ret == 0 ? "Success" : "Failed");
389
390         if (ret == -ENOMEM)
391                 return STORAGE_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE System Error
392         if (ret < 0)
393                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
394
395         return STORAGE_ERROR_NONE;
396 }