Add functions for loading and saving information
[connman] / src / storage.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "connman.h"
27
28 static GSList *storage_list = NULL;
29
30 static gint compare_priority(gconstpointer a, gconstpointer b)
31 {
32         const struct connman_storage *storage1 = a;
33         const struct connman_storage *storage2 = b;
34
35         return storage2->priority - storage1->priority;
36 }
37
38 /**
39  * connman_storage_register:
40  * @storage: storage module
41  *
42  * Register a new storage module
43  *
44  * Returns: %0 on success
45  */
46 int connman_storage_register(struct connman_storage *storage)
47 {
48         DBG("storage %p name %s", storage, storage->name);
49
50         storage_list = g_slist_insert_sorted(storage_list, storage,
51                                                         compare_priority);
52
53         return 0;
54 }
55
56 /**
57  * connman_storage_unregister:
58  * @storage: storage module
59  *
60  * Remove a previously registered storage module
61  */
62 void connman_storage_unregister(struct connman_storage *storage)
63 {
64         DBG("storage %p name %s", storage, storage->name);
65
66         storage_list = g_slist_remove(storage_list, storage);
67 }
68
69 int __connman_storage_load_device(struct connman_device *device)
70 {
71         GSList *list;
72
73         DBG("device %p", device);
74
75         for (list = storage_list; list; list = list->next) {
76                 struct connman_storage *storage = list->data;
77
78                 if (storage->device_load) {
79                         DBG("%s", storage->name);
80
81                         if (storage->device_load(device) == 0)
82                                 return 0;
83                 }
84         }
85
86         return -ENOENT;
87 }
88
89 int __connman_storage_save_device(struct connman_device *device)
90 {
91         GSList *list;
92
93         DBG("device %p", device);
94
95         for (list = storage_list; list; list = list->next) {
96                 struct connman_storage *storage = list->data;
97
98                 if (storage->device_save) {
99                         DBG("%s", storage->name);
100
101                         if (storage->device_save(device) == 0)
102                                 return 0;
103                 }
104         }
105
106         return -ENOENT;
107 }
108
109 int __connman_storage_load_network(struct connman_network *network)
110 {
111         GSList *list;
112
113         DBG("network %p", network);
114
115         for (list = storage_list; list; list = list->next) {
116                 struct connman_storage *storage = list->data;
117
118                 if (storage->network_load) {
119                         DBG("%s", storage->name);
120
121                         if (storage->network_load(network) == 0)
122                                 return 0;
123                 }
124         }
125
126         return -ENOENT;
127 }
128
129 int __connman_storage_save_network(struct connman_network *network)
130 {
131         GSList *list;
132
133         DBG("network %p", network);
134
135         for (list = storage_list; list; list = list->next) {
136                 struct connman_storage *storage = list->data;
137
138                 if (storage->network_save) {
139                         DBG("%s", storage->name);
140
141                         if (storage->network_save(network) == 0)
142                                 return 0;
143                 }
144         }
145
146         return -ENOENT;
147 }
148
149 int __connman_storage_init(void)
150 {
151         DBG("");
152
153         return 0;
154 }
155
156 void __connman_storage_cleanup(void)
157 {
158         DBG("");
159 }
160
161 static int do_load(GKeyFile *keyfile, struct connman_element *element)
162 {
163         const gchar *value;
164
165         DBG("element %p name %s", element, element->name);
166
167         value = g_key_file_get_string(keyfile, element->path,
168                                                 "Policy", NULL);
169         if (value != NULL)
170                 element->policy = __connman_element_string2policy(value);
171
172         if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
173                 element->remember = g_key_file_get_boolean(keyfile,
174                                         element->path, "Remember", NULL);
175
176         value = g_key_file_get_string(keyfile, element->path,
177                                                 "WiFi.Security", NULL);
178         if (value != NULL)
179                 connman_element_set_property(element,
180                                 CONNMAN_PROPERTY_ID_WIFI_SECURITY, &value);
181
182         value = g_key_file_get_string(keyfile, element->path,
183                                                 "WiFi.Passphrase", NULL);
184         if (value != NULL)
185                 connman_element_set_property(element,
186                                 CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE, &value);
187
188         return 0;
189 }
190
191 int __connman_element_load(struct connman_element *element)
192 {
193         GKeyFile *keyfile;
194         gchar *pathname, *data = NULL;
195         gsize length;
196
197         DBG("element %p name %s", element, element->name);
198
199         pathname = g_strdup_printf("%s/elements.conf", STORAGEDIR);
200         if (pathname == NULL)
201                 return -ENOMEM;
202
203         keyfile = g_key_file_new();
204
205         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
206                 g_free(pathname);
207                 return -ENOENT;
208         }
209
210         g_free(pathname);
211
212         if (g_key_file_load_from_data(keyfile, data, length,
213                                                         0, NULL) == FALSE) {
214                 g_free(data);
215                 return -EILSEQ;
216         }
217
218         g_free(data);
219
220         do_load(keyfile, element);
221
222         g_key_file_free(keyfile);
223
224         return 0;
225 }
226
227 static void do_update(GKeyFile *keyfile, struct connman_element *element)
228 {
229         GSList *list;
230         char *value;
231         const char *str;
232
233         DBG("element %p name %s", element, element->name);
234
235         g_key_file_set_string(keyfile, element->path, "Name", element->name);
236
237         str = __connman_element_policy2string(element->policy);
238         if (str != NULL)
239                 g_key_file_set_string(keyfile, element->path, "Policy", str);
240
241         //g_key_file_set_boolean(keyfile, element->path, "Enabled",
242         //                                              element->enabled);
243
244         if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
245                 g_key_file_set_boolean(keyfile, element->path, "Remember",
246                                                         element->remember);
247
248         __connman_element_lock(element);
249
250         for (list = element->properties; list; list = list->next) {
251                 struct connman_property *property = list->data;
252
253                 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
254                         continue;
255
256                 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
257                         continue;
258
259                 if (property->type == DBUS_TYPE_STRING)
260                         g_key_file_set_string(keyfile, element->path,
261                                         property->name, property->value);
262         }
263
264         __connman_element_unlock(element);
265
266         if (connman_element_get_value(element,
267                         CONNMAN_PROPERTY_ID_WIFI_SECURITY, &value) == 0)
268                 g_key_file_set_string(keyfile, element->path,
269                                                 "WiFi.Security", value);
270
271         if (connman_element_get_value(element,
272                         CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE, &value) == 0)
273                 g_key_file_set_string(keyfile, element->path,
274                                                 "WiFi.Passphrase", value);
275 }
276
277 int __connman_element_store(struct connman_element *element)
278 {
279         GKeyFile *keyfile;
280         gchar *pathname, *data = NULL;
281         gsize length;
282
283         DBG("element %p name %s", element, element->name);
284
285         if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE &&
286                                 element->type != CONNMAN_ELEMENT_TYPE_NETWORK)
287                 return -EINVAL;
288
289         if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_FAKE)
290                 return -EINVAL;
291
292         pathname = g_strdup_printf("%s/elements.conf", STORAGEDIR);
293         if (pathname == NULL)
294                 return -ENOMEM;
295
296         keyfile = g_key_file_new();
297
298         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
299                 goto update;
300
301         if (length > 0) {
302                 if (g_key_file_load_from_data(keyfile, data, length,
303                                                         0, NULL) == FALSE)
304                         goto done;
305         }
306
307         g_free(data);
308
309 update:
310         do_update(keyfile, element);
311
312         data = g_key_file_to_data(keyfile, &length, NULL);
313
314         g_file_set_contents(pathname, data, length, NULL);
315
316 done:
317         g_free(data);
318
319         g_key_file_free(keyfile);
320
321         g_free(pathname);
322
323         return 0;
324 }