1f3936220b930f5e77ed86ea0e830b6df590e8dc
[platform/core/system/libstorage.git] / src / storage-external-dbus.c
1 /*
2  * libstorage
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <vconf.h>
23 #include <stdbool.h>
24 #include <errno.h>
25 #include <gio/gio.h>
26 #include <glib.h>
27 #include <limits.h>
28
29 #include "log.h"
30 #include "storage-external-dbus.h"
31
32 #define CHECK_STR(a) (a ? a : "")
33
34 #define STORAGE_EXT_GET_LIST       "GetDeviceList"
35
36 #define DBUS_REPLY_TIMEOUT (-1)
37
38 static void storage_ext_release_internal(storage_ext_device *dev)
39 {
40         if (!dev)
41                 return;
42         free(dev->devnode);
43         free(dev->syspath);
44         free(dev->fs_usage);
45         free(dev->fs_type);
46         free(dev->fs_version);
47         free(dev->fs_uuid);
48         free(dev->mount_point);
49 }
50
51 void storage_ext_release_device(storage_ext_device **dev)
52 {
53         if (!dev || !*dev)
54                 return;
55         storage_ext_release_internal(*dev);
56         free(*dev);
57         *dev = NULL;
58 }
59
60 void storage_ext_release_list(dd_list **list)
61 {
62         storage_ext_device *dev;
63         dd_list *elem;
64
65         if (*list == NULL)
66                 return;
67
68         DD_LIST_FOREACH(*list, elem, dev) {
69                 storage_ext_release_internal(dev);
70                 free(dev);
71         }
72
73         g_list_free(*list);
74         *list = NULL;
75 }
76
77 static GDBusConnection *get_dbus_connection(void)
78 {
79         GError *err = NULL;
80         static GDBusConnection *conn;
81
82         if (conn)
83                 return conn;
84
85 #if !GLIB_CHECK_VERSION(2, 35, 0)
86         g_type_init();
87 #endif
88
89         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
90         if (!conn) {
91                 if (err) {
92                         _E("fail to get dbus connection : %s", err->message);
93                         g_clear_error(&err);
94                 } else
95                         _E("fail to get dbus connection");
96                 return NULL;
97         }
98         return conn;
99 }
100
101 static GVariant *dbus_method_call_sync(const gchar *dest, const gchar *path,
102                                 const gchar *iface, const gchar *method, GVariant *param)
103 {
104         GDBusConnection *conn;
105         GError *err = NULL;
106         GVariant *ret;
107
108         if (!dest || !path || !iface || !method || !param)
109                 return NULL;
110
111         conn = get_dbus_connection();
112         if (!conn) {
113                 _E("fail to get dbus connection");
114                 return NULL;
115         }
116
117         ret = g_dbus_connection_call_sync(conn,
118                         dest, path, iface, method,
119                         param, NULL, G_DBUS_CALL_FLAGS_NONE,
120                         -1, NULL, &err);
121         if (!ret) {
122                 if (err) {
123                         _E("dbus method sync call failed(%s)", err->message);
124                         g_clear_error(&err);
125                 } else
126                         _E("g_dbus_connection_call_sync() failed");
127                 return NULL;
128         }
129
130         return ret;
131 }
132
133 int storage_ext_get_list(dd_list **list)
134 {
135         GVariant *result;
136         GVariantIter *iter;
137         storage_ext_device *elem, info;
138         int ret;
139
140         if (!list)
141                 return -EINVAL;
142
143         result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
144                         STORAGE_EXT_PATH_MANAGER,
145                         STORAGE_EXT_IFACE_MANAGER,
146                         STORAGE_EXT_GET_LIST,
147                         g_variant_new("(s)", "all"));
148         if (!result) {
149                 _E("Failed to get storage_ext device info");
150                 return -EIO;
151         }
152
153         g_variant_get(result, "(a(issssssisibii))", &iter);
154
155         while (g_variant_iter_loop(iter, "(issssssisibii)",
156                                 &info.type, &info.devnode, &info.syspath,
157                                 &info.fs_usage, &info.fs_type,
158                                 &info.fs_version, &info.fs_uuid,
159                                 &info.readonly, &info.mount_point,
160                                 &info.state, &info.primary,
161                                 &info.flags, &info.storage_id)) {
162
163                 elem = (storage_ext_device *)malloc(sizeof(storage_ext_device));
164                 if (!elem) {
165                         _E("malloc() failed");
166                         ret = -ENOMEM;
167                         goto out;
168                 }
169
170                 elem->type = info.type;
171                 elem->readonly = info.readonly;
172                 elem->state = info.state;
173                 elem->primary = info.primary;
174                 elem->devnode = strdup(CHECK_STR(info.devnode));
175                 elem->syspath = strdup(CHECK_STR(info.syspath));
176                 elem->fs_usage = strdup(CHECK_STR(info.fs_usage));
177                 elem->fs_type = strdup(CHECK_STR(info.fs_type));
178                 elem->fs_version = strdup(CHECK_STR(info.fs_version));
179                 elem->fs_uuid = strdup(CHECK_STR(info.fs_uuid));
180                 elem->mount_point = strdup(CHECK_STR(info.mount_point));
181                 elem->flags = info.flags;
182                 elem->storage_id = info.storage_id;
183
184                 DD_LIST_APPEND(*list, elem);
185         }
186
187         ret = g_list_length(*list);
188
189 out:
190         if (ret < 0)
191                 storage_ext_release_list(list);
192         g_variant_iter_free(iter);
193         g_variant_unref(result);
194         return ret;
195 }