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>
32 #include "storage-external-dbus.h"
34 #define CHECK_STR(a) (a ? a : "")
36 #define STORAGE_EXT_GET_LIST "GetDeviceList"
37 #define STORAGE_EXT_GET_STATVFS "GetStatvfs"
39 #define STORAGE_EXT_DEVICE_CHANGED "DeviceChanged"
40 #define STORAGE_EXT_DEVICE_ADDED "DeviceAdded"
41 #define STORAGE_EXT_DEVICE_REMOVED "DeviceRemoved"
42 #define STORAGE_EXT_DEVICE_BLOCKED "DeviceBlocked"
44 #define DBUS_REPLY_TIMEOUT (-1)
46 struct storage_ext_callback {
47 storage_ext_changed_cb func;
52 static dd_list *changed_list;
54 static void storage_ext_release_internal(storage_ext_device *dev)
62 free(dev->fs_version);
64 free(dev->mount_point);
67 void storage_ext_release_device(storage_ext_device **dev)
71 storage_ext_release_internal(*dev);
76 void storage_ext_release_list(dd_list **list)
78 storage_ext_device *dev;
84 DD_LIST_FOREACH(*list, elem, dev) {
85 storage_ext_release_internal(dev);
93 static GDBusConnection *get_dbus_connection(void)
96 static GDBusConnection *conn;
101 #if !GLIB_CHECK_VERSION(2, 35, 0)
105 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
107 //LCOV_EXCL_START System Error
109 _E("fail to get dbus connection : %s", err->message);
112 _E("fail to get dbus connection");
119 GVariant *dbus_method_call_sync(const gchar *dest, const gchar *path,
120 const gchar *iface, const gchar *method, GVariant *param)
122 GDBusConnection *conn;
126 if (!dest || !path || !iface || !method)
129 conn = get_dbus_connection();
131 _E("fail to get dbus connection"); //LCOV_EXCL_LINE
135 ret = g_dbus_connection_call_sync(conn,
136 dest, path, iface, method,
137 param, NULL, G_DBUS_CALL_FLAGS_NONE,
140 //LCOV_EXCL_START System Error
142 _E("dbus method sync call failed(%s)", err->message);
145 _E("g_dbus_connection_call_sync() failed");
153 int storage_ext_get_list(dd_list **list)
157 storage_ext_device *elem, info;
163 result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
164 STORAGE_EXT_PATH_MANAGER,
165 STORAGE_EXT_IFACE_MANAGER,
166 STORAGE_EXT_GET_LIST,
167 g_variant_new("(s)", "all"));
169 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
173 g_variant_get(result, "(a(issssssisibii))", &iter);
175 while (g_variant_iter_loop(iter, "(issssssisibii)",
176 &info.type, &info.devnode, &info.syspath,
177 &info.fs_usage, &info.fs_type,
178 &info.fs_version, &info.fs_uuid,
179 &info.readonly, &info.mount_point,
180 &info.state, &info.primary,
181 &info.flags, &info.storage_id)) {
183 elem = (storage_ext_device *)malloc(sizeof(storage_ext_device));
185 _E("malloc() failed"); //LCOV_EXCL_LINE
190 elem->type = info.type;
191 elem->readonly = info.readonly;
192 elem->state = info.state;
193 elem->primary = info.primary;
194 elem->devnode = strdup(CHECK_STR(info.devnode));
195 elem->syspath = strdup(CHECK_STR(info.syspath));
196 elem->fs_usage = strdup(CHECK_STR(info.fs_usage));
197 elem->fs_type = strdup(CHECK_STR(info.fs_type));
198 elem->fs_version = strdup(CHECK_STR(info.fs_version));
199 elem->fs_uuid = strdup(CHECK_STR(info.fs_uuid));
200 elem->mount_point = strdup(CHECK_STR(info.mount_point));
201 elem->flags = info.flags;
202 elem->storage_id = info.storage_id;
204 DD_LIST_APPEND(*list, elem);
207 ret = g_list_length(*list);
211 storage_ext_release_list(list); //LCOV_EXCL_LINE System Error
212 g_variant_iter_free(iter);
213 g_variant_unref(result);
217 int storage_ext_get_statvfs(char *path, struct statvfs_32 *buf)
220 guint64 bsize, frsize, blocks, bfree, bavail, files, ffree, favail, fsid, flag, namemax;
224 memset(buf, 0, sizeof(struct statvfs_32));
226 result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
227 STORAGE_EXT_PATH_STORAGE,
228 STORAGE_EXT_IFACE_STORAGE,
229 STORAGE_EXT_GET_STATVFS,
230 g_variant_new("(s)", path));
232 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
236 g_variant_get(result, "(ttttttttttt)",
237 &bsize, &frsize, &blocks,
238 &bfree, &bavail, &files,
239 &ffree, &favail, &fsid,
241 // %llu bsize, frsize, blocks, bfree, bavail, files, ffree, favail, fsid, flag, namemax
243 buf->f_bsize = (unsigned long)bsize;
244 buf->f_frsize = (unsigned long)frsize;
245 buf->f_blocks = (unsigned long)blocks;
246 buf->f_bfree = (unsigned long)bfree;
247 buf->f_bavail = (unsigned long)bavail;
248 buf->f_files = (unsigned long)files;
249 buf->f_ffree = (unsigned long)ffree;
250 buf->f_favail = (unsigned long)favail;
251 buf->f_fsid = (unsigned long)fsid;
252 buf->f_flag = (unsigned long)flag;
253 buf->f_namemax = (unsigned long)namemax;
255 // %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
259 int storage_ext_get_statvfs_size64(char *path, struct statvfs *buf)
265 memset(buf, 0, sizeof(struct statvfs));
267 result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
268 STORAGE_EXT_PATH_STORAGE,
269 STORAGE_EXT_IFACE_STORAGE,
270 STORAGE_EXT_GET_STATVFS,
271 g_variant_new("(s)", path));
273 _E("Failed to get storage_ext device info"); //LCOV_EXCL_LINE
277 g_variant_get(result, "(ttttttttttt)",
278 &(buf->f_bsize), &(buf->f_frsize), &(buf->f_blocks),
279 &(buf->f_bfree), &(buf->f_bavail), &(buf->f_files),
280 &(buf->f_ffree), &(buf->f_favail), &(buf->f_fsid),
281 &(buf->f_flag), &(buf->f_namemax));
283 // %lu buf->f_bsize, buf->f_frsize, buf->f_fsid, buf->f_flag, buf->f_namemax
284 // %llu buf->f_blocks, buf->f_bfree, buf->f_bavail, buf->f_files, buf->f_ffree, buf->f_favail
289 //LCOV_EXCL_START Not called Callback
290 static void storage_ext_device_changed(GVariant *params, enum storage_ext_state state, gpointer user_data)
292 storage_ext_device *dev;
294 struct storage_ext_callback *callback;
300 dev = calloc(1, sizeof(storage_ext_device));
304 g_variant_get(params, "(issssssisibii)",
319 /* Callback is called when unmount is started(DeviceBlocked signal) */
320 if (state == STORAGE_EXT_CHANGED && dev->state == STORAGE_EXT_UNMOUNTED) {
321 storage_ext_release_device(&dev);
325 DD_LIST_FOREACH(changed_list, elem, callback) {
328 ret = callback->func(dev, state, callback->data);
330 _E("Failed to call callback for devnode(%s, %d)", dev->devnode, ret);
333 storage_ext_release_device(&dev);
337 //LCOV_EXCL_START Not called Callback
338 static void storage_ext_changed(GDBusConnection *conn,
346 size_t iface_len, signal_len;
347 enum storage_ext_state state;
349 if (!params || !sender || !path || !iface || !signal)
352 iface_len = strlen(iface) + 1;
353 signal_len = strlen(signal) + 1;
355 if (strncmp(iface, STORAGE_EXT_IFACE_MANAGER, iface_len))
358 if (!strncmp(signal, STORAGE_EXT_DEVICE_CHANGED, signal_len))
359 state = STORAGE_EXT_CHANGED;
361 else if (!strncmp(signal, STORAGE_EXT_DEVICE_ADDED, signal_len))
362 state = STORAGE_EXT_ADDED;
364 else if (!strncmp(signal, STORAGE_EXT_DEVICE_REMOVED, signal_len))
365 state = STORAGE_EXT_REMOVED;
367 else if (!strncmp(signal, STORAGE_EXT_DEVICE_BLOCKED, signal_len))
368 state = STORAGE_EXT_BLOCKED;
373 storage_ext_device_changed(params, state, user_data);
377 int storage_ext_register_device_change(storage_ext_changed_cb func, void *data)
379 GDBusConnection *conn;
381 struct storage_ext_callback *callback;
387 DD_LIST_FOREACH(changed_list, elem, callback) {
388 if (callback->func != func)
390 if (callback->block_id == 0)
396 callback = (struct storage_ext_callback *)malloc(sizeof(struct storage_ext_callback));
398 //LCOV_EXCL_START System Error
399 _E("malloc() failed");
404 conn = get_dbus_connection();
406 //LCOV_EXCL_START System Error
408 _E("Failed to get dbus connection");
413 block_id = g_dbus_connection_signal_subscribe(conn,
415 STORAGE_EXT_IFACE_MANAGER,
419 G_DBUS_SIGNAL_FLAGS_NONE,
424 //LCOV_EXCL_START System Error
426 _E("Failed to subscrive bus signal");
431 callback->func = func;
432 callback->data = data;
433 callback->block_id = block_id;
435 DD_LIST_APPEND(changed_list, callback);
440 void storage_ext_unregister_device_change(storage_ext_changed_cb func)
442 GDBusConnection *conn;
443 struct storage_ext_callback *callback;
450 conn = get_dbus_connection();
452 //LCOV_EXCL_START System Error
453 _E("fail to get dbus connection");
458 DD_LIST_FOREACH_SAFE(changed_list, elem, elem_n, callback) {
459 if (callback->func != func)
461 if (callback->block_id > 0)
462 g_dbus_connection_signal_unsubscribe(conn, callback->block_id);
464 DD_LIST_REMOVE(changed_list, callback);
469 int storage_ext_get_device_info(int storage_id, storage_ext_device *info)
473 result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
474 STORAGE_EXT_PATH_MANAGER,
475 STORAGE_EXT_IFACE_MANAGER,
477 g_variant_new("(i)", storage_id));
479 _E("There is no storage with the storage id (%d)", storage_id); //LCOV_EXCL_LINE
483 if (g_variant_check_format_string(result, "(issssssisibii)", true)) {
484 g_variant_get(result, "(issssssisibii)",
485 &info->type, &info->devnode, &info->syspath,
486 &info->fs_usage, &info->fs_type,
487 &info->fs_version, &info->fs_uuid,
488 &info->readonly, &info->mount_point,
489 &info->state, &info->primary,
490 &info->flags, &info->storage_id);
492 _E("No storage with the storage id (%d)", storage_id); //LCOV_EXCL_LINE
496 g_variant_unref(result);