4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include <sys/statvfs.h>
30 #include <tzplatform_config.h>
31 #include <libsyscommon/libgdbus.h>
32 #include <libsyscommon/list.h>
35 #include "storage-external-dbus.h"
37 #define CHECK_STR(a) (a ? a : "")
39 #define STORAGE_EXT_GET_LIST "GetDeviceList"
40 #define STORAGE_EXT_GET_STATVFS "GetStatvfs"
41 #define STORAGE_EXT_GET_STORAGE_LEVEL "GetStorageLevel"
43 #define STORAGE_EXT_DEVICE_CHANGED "DeviceChanged"
44 #define STORAGE_EXT_DEVICE_ADDED "DeviceAdded"
45 #define STORAGE_EXT_DEVICE_REMOVED "DeviceRemoved"
46 #define STORAGE_EXT_DEVICE_BLOCKED "DeviceBlocked"
48 #define DBUS_REPLY_TIMEOUT (-1)
50 #define GET_DBUS_CONN_OR_EXIT() \
52 dbus_handle_h dbus_handle = gdbus_get_connection(G_BUS_TYPE_SYSTEM, true); \
53 if (dbus_handle == NULL) { \
54 _E("Failed to get dbus connection"); \
61 struct storage_ext_callback {
62 storage_ext_changed_cb func;
67 static GList *changed_list;
69 static void storage_ext_release_internal(storage_ext_device *dev)
77 free(dev->fs_version);
79 free(dev->mount_point);
82 void storage_ext_release_device(storage_ext_device **dev)
86 storage_ext_release_internal(*dev);
91 void storage_ext_release_list(GList **list)
93 storage_ext_device *dev;
99 SYS_G_LIST_FOREACH(*list, elem, dev) {
100 storage_ext_release_internal(dev);
108 int storage_ext_get_list(GList **list)
112 storage_ext_device *elem, info;
118 dbus_handle_h dbus_handle = GET_DBUS_CONN_OR_EXIT();
120 ret_dbus = gdbus_priv_call_sync_with_reply(dbus_handle,
121 STORAGE_EXT_BUS_NAME,
122 STORAGE_EXT_PATH_MANAGER,
123 STORAGE_EXT_IFACE_MANAGER,
124 STORAGE_EXT_GET_LIST,
125 g_variant_new("(s)", "all"),
128 gdbus_free_connection(dbus_handle);
131 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
132 return -EIO; //LCOV_EXCL_LINE
135 if (!g_variant_get_safe(reply, "(a(issssssisibii))", &iter)) {
136 //LCOV_EXCL_START Dbus type error
137 _E("Failed to get params from gvariant.");
138 g_variant_unref(reply);
143 while (g_variant_iter_loop(iter, "(issssssisibii)",
144 &info.type, &info.devnode, &info.syspath,
145 &info.fs_usage, &info.fs_type,
146 &info.fs_version, &info.fs_uuid,
147 &info.readonly, &info.mount_point,
148 &info.state, &info.primary,
149 &info.flags, &info.storage_id)) {
151 elem = (storage_ext_device *)malloc(sizeof(storage_ext_device));
153 //LCOV_EXCL_START System error
154 _E("malloc() failed");
160 elem->type = info.type;
161 elem->readonly = info.readonly;
162 elem->state = info.state;
163 elem->primary = info.primary;
164 elem->devnode = strdup(CHECK_STR(info.devnode));
165 elem->syspath = strdup(CHECK_STR(info.syspath));
166 elem->fs_usage = strdup(CHECK_STR(info.fs_usage));
167 elem->fs_type = strdup(CHECK_STR(info.fs_type));
168 elem->fs_version = strdup(CHECK_STR(info.fs_version));
169 elem->fs_uuid = strdup(CHECK_STR(info.fs_uuid));
170 elem->mount_point = strdup(CHECK_STR(info.mount_point));
171 elem->flags = info.flags;
172 elem->storage_id = info.storage_id;
174 SYS_G_LIST_APPEND(*list, elem);
177 ret = SYS_G_LIST_LENGTH(*list);
181 storage_ext_release_list(list); //LCOV_EXCL_LINE System Error
182 g_variant_iter_free(iter);
183 g_variant_unref(reply);
187 int storage_ext_get_statvfs(char *path, struct statvfs_32 *buf)
191 guint64 bsize, frsize, blocks, bfree, bavail, files, ffree, favail, fsid, flag, namemax;
195 memset(buf, 0, sizeof(struct statvfs_32));
197 dbus_handle_h dbus_handle = GET_DBUS_CONN_OR_EXIT();
199 ret_dbus = gdbus_priv_call_sync_with_reply(dbus_handle,
200 STORAGE_EXT_BUS_NAME,
201 STORAGE_EXT_PATH_STORAGE,
202 STORAGE_EXT_IFACE_STORAGE,
203 STORAGE_EXT_GET_STATVFS,
204 g_variant_new("(s)", path),
207 gdbus_free_connection(dbus_handle);
210 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
211 return -EIO; //LCOV_EXCL_LINE
214 if (!g_variant_get_safe(reply, "(ttttttttttt)",
215 &bsize, &frsize, &blocks,
216 &bfree, &bavail, &files,
217 &ffree, &favail, &fsid,
219 _E("Failed to get params from gvariant.");
220 g_variant_unref(reply);
223 // %llu bsize, frsize, blocks, bfree, bavail, files, ffree, favail, fsid, flag, namemax
225 buf->f_bsize = (unsigned long)bsize;
226 buf->f_frsize = (unsigned long)frsize;
227 buf->f_blocks = (unsigned long)blocks;
228 buf->f_bfree = (unsigned long)bfree;
229 buf->f_bavail = (unsigned long)bavail;
230 buf->f_files = (unsigned long)files;
231 buf->f_ffree = (unsigned long)ffree;
232 buf->f_favail = (unsigned long)favail;
233 buf->f_fsid = (unsigned long)fsid;
234 buf->f_flag = (unsigned long)flag;
235 buf->f_namemax = (unsigned long)namemax;
237 // %lu buf->f_bsize, buf->f_frsize, buf->f_blocks, buf->f_bfree, buf->f_bavail, buf->f_files, buf->f_ffree, buf->f_favail, buf->f_fsid, buf->f_flag, buf->f_namemax
241 int storage_ext_get_statvfs_size64(char *path, struct statvfs *buf)
248 memset(buf, 0, sizeof(struct statvfs));
250 dbus_handle_h dbus_handle = GET_DBUS_CONN_OR_EXIT();
252 ret_dbus = gdbus_priv_call_sync_with_reply(dbus_handle,
253 STORAGE_EXT_BUS_NAME,
254 STORAGE_EXT_PATH_STORAGE,
255 STORAGE_EXT_IFACE_STORAGE,
256 STORAGE_EXT_GET_STATVFS,
257 g_variant_new("(s)", path),
260 gdbus_free_connection(dbus_handle);
263 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
264 return -EIO; //LCOV_EXCL_LINE
267 if (!g_variant_get_safe(reply, "(ttttttttttt)",
268 &(buf->f_bsize), &(buf->f_frsize), &(buf->f_blocks),
269 &(buf->f_bfree), &(buf->f_bavail), &(buf->f_files),
270 &(buf->f_ffree), &(buf->f_favail), &(buf->f_fsid),
271 &(buf->f_flag), &(buf->f_namemax))) {
272 //LCOV_EXCL_START Dbus type error
273 _E("Failed to get params from gvariant.");
274 g_variant_unref(reply);
279 // %lu buf->f_bsize, buf->f_frsize, buf->f_fsid, buf->f_flag, buf->f_namemax
280 // %llu buf->f_blocks, buf->f_bfree, buf->f_bavail, buf->f_files, buf->f_ffree, buf->f_favail
285 int storage_ext_get_storage_level(const char *path, char **level)
290 enum tzplatform_variable id;
292 if (!strcmp(path, tzplatform_getenv(TZ_SYS_USER)))
294 else if (!strcmp(path, tzplatform_getenv(TZ_SYS_TMP)))
296 else if (!strcmp(path, tzplatform_getenv(TZ_SYS_OPT)))
303 dbus_handle_h dbus_handle = GET_DBUS_CONN_OR_EXIT();
305 ret_dbus = gdbus_priv_call_sync_with_reply(
307 STORAGE_EXT_BUS_NAME,
308 STORAGE_EXT_PATH_STORAGE,
309 STORAGE_EXT_IFACE_STORAGE,
310 STORAGE_EXT_GET_STORAGE_LEVEL,
311 g_variant_new("(i)", id),
314 gdbus_free_connection(dbus_handle);
317 //LCOV_EXCL_START Dbus error
318 _E("Failed to get %d level", id);
323 if (!g_variant_get_safe(reply, "(s)", &reply_val)) {
324 //LCOV_EXCL_START Dbus type error
325 _E("Failed to get params from gvariant.");
326 g_variant_unref(reply);
331 *level = strdup(reply_val);
333 g_variant_unref(reply);
336 return -ENOMEM; //LCOV_EXCL_LINE
341 //LCOV_EXCL_START Not called Callback
342 static void storage_ext_device_changed(GVariant *params, enum storage_ext_state state, gpointer user_data)
344 storage_ext_device *dev;
346 struct storage_ext_callback *callback;
352 dev = calloc(1, sizeof(storage_ext_device));
356 if (!g_variant_get_safe(params, "(issssssisibii)",
372 /* Callback is called when unmount is started(DeviceBlocked signal) */
373 if (state == STORAGE_EXT_CHANGED && dev->state == STORAGE_EXT_UNMOUNTED) {
374 storage_ext_release_device(&dev);
378 SYS_G_LIST_FOREACH(changed_list, elem, callback) {
381 ret_val = callback->func(dev, state, callback->data);
383 _E("Failed to call callback for devnode(%s, %d)", dev->devnode, ret_val);
386 storage_ext_release_device(&dev);
390 //LCOV_EXCL_START Not called Callback
391 static void storage_ext_changed(GDBusConnection *conn,
399 size_t iface_len, signal_len;
400 enum storage_ext_state state;
402 if (!params || !sender || !path || !iface || !signal)
405 iface_len = strlen(iface) + 1;
406 signal_len = strlen(signal) + 1;
408 if (strncmp(iface, STORAGE_EXT_IFACE_MANAGER, iface_len))
411 if (!strncmp(signal, STORAGE_EXT_DEVICE_CHANGED, signal_len))
412 state = STORAGE_EXT_CHANGED;
414 else if (!strncmp(signal, STORAGE_EXT_DEVICE_ADDED, signal_len))
415 state = STORAGE_EXT_ADDED;
417 else if (!strncmp(signal, STORAGE_EXT_DEVICE_REMOVED, signal_len))
418 state = STORAGE_EXT_REMOVED;
420 else if (!strncmp(signal, STORAGE_EXT_DEVICE_BLOCKED, signal_len))
421 state = STORAGE_EXT_BLOCKED;
426 storage_ext_device_changed(params, state, user_data);
430 int storage_ext_register_device_change(storage_ext_changed_cb func, void *data)
433 struct storage_ext_callback *callback;
439 SYS_G_LIST_FOREACH(changed_list, elem, callback) {
440 if (callback->func != func)
442 if (callback->block_id == 0)
448 callback = (struct storage_ext_callback *)malloc(sizeof(struct storage_ext_callback));
450 //LCOV_EXCL_START System Error
451 _E("malloc() failed");
456 block_id = gdbus_signal_subscribe(NULL, NULL,
457 STORAGE_EXT_IFACE_MANAGER,
463 //LCOV_EXCL_START System Error
465 _E("Failed to subscrive bus signal");
470 callback->func = func;
471 callback->data = data;
472 callback->block_id = block_id;
474 SYS_G_LIST_APPEND(changed_list, callback);
479 void storage_ext_unregister_device_change(storage_ext_changed_cb func)
481 struct storage_ext_callback *callback;
488 SYS_G_LIST_FOREACH_SAFE(changed_list, elem, elem_n, callback) {
489 if (callback->func != func)
491 if (callback->block_id > 0)
492 gdbus_signal_unsubscribe(NULL, callback->block_id);
494 SYS_G_LIST_REMOVE(changed_list, callback);
499 int storage_ext_get_device_info(int storage_id, storage_ext_device *info)
504 dbus_handle_h dbus_handle = GET_DBUS_CONN_OR_EXIT();
506 ret_dbus = gdbus_priv_call_sync_with_reply(dbus_handle,
507 STORAGE_EXT_BUS_NAME,
508 STORAGE_EXT_PATH_MANAGER,
509 STORAGE_EXT_IFACE_MANAGER,
511 g_variant_new("(i)", storage_id),
514 gdbus_free_connection(dbus_handle);
517 _E("There is no storage with the storage id (%d)", storage_id); //LCOV_EXCL_LINE
518 return -ENODEV; //LCOV_EXCL_LINE
521 if (!g_variant_get_safe(reply, "(issssssisibii)",
522 &info->type, &info->devnode, &info->syspath,
523 &info->fs_usage, &info->fs_type,
524 &info->fs_version, &info->fs_uuid,
525 &info->readonly, &info->mount_point,
526 &info->state, &info->primary,
527 &info->flags, &info->storage_id)) {
528 //LCOV_EXCL_START Dbus error
529 _E("No storage with the storage id (%d)", storage_id);
535 if (info->storage_id < 0) {
536 //LCOV_EXCL_START Dbus error
537 _E("No storage with the storage id (%d)", storage_id);
544 g_variant_unref(reply);