277e5f532db215a727605daff00ec59ef520b1e3
[platform/upstream/connman.git] / src / storage.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  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 <errno.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <dirent.h>
30 #include <stdio.h>
31
32 #include <connman/storage.h>
33
34 #include "connman.h"
35
36 #define SETTINGS        "settings"
37 #define DEFAULT         "default.profile"
38 #if defined TIZEN_EXT
39 #define INS_SETTINGS    "settings.ins"
40 #endif
41
42 #define MODE            (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | \
43                         S_IXGRP | S_IROTH | S_IXOTH)
44
45 static GKeyFile *storage_load(const char *pathname)
46 {
47         GKeyFile *keyfile = NULL;
48         GError *error = NULL;
49
50         keyfile = g_key_file_new();
51
52         if (!g_key_file_load_from_file(keyfile, pathname, 0, &error)) {
53                 DBG("Unable to load %s: %s", pathname, error->message);
54                 g_clear_error(&error);
55
56                 g_key_file_free(keyfile);
57                 keyfile = NULL;
58         }
59
60         return keyfile;
61 }
62
63 static int storage_save(GKeyFile *keyfile, char *pathname)
64 {
65         gchar *data = NULL;
66         gsize length = 0;
67         GError *error = NULL;
68         int ret = 0;
69
70         data = g_key_file_to_data(keyfile, &length, NULL);
71
72         if (!g_file_set_contents(pathname, data, length, &error)) {
73                 DBG("Failed to store information: %s", error->message);
74                 g_error_free(error);
75                 ret = -EIO;
76         }
77
78 #if defined TIZEN_EXT
79         {
80                 FILE *fp = NULL;
81                 fp = fopen(pathname, "a+");
82                 if(fp){
83                         fflush(fp);
84                         fsync(fp->_fileno);
85                         fclose(fp);
86                         DBG("sync the file to disk");
87                 }
88         }
89 #endif
90
91         g_free(data);
92
93         return ret;
94 }
95
96 static void storage_delete(const char *pathname)
97 {
98         DBG("file path %s", pathname);
99
100         if (unlink(pathname) < 0)
101                 connman_error("Failed to remove %s", pathname);
102 }
103
104 GKeyFile *__connman_storage_load_global(void)
105 {
106         gchar *pathname;
107         GKeyFile *keyfile = NULL;
108
109         pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS);
110         if (!pathname)
111                 return NULL;
112
113         keyfile = storage_load(pathname);
114
115         g_free(pathname);
116
117         return keyfile;
118 }
119
120 int __connman_storage_save_global(GKeyFile *keyfile)
121 {
122         gchar *pathname;
123         int ret;
124
125         pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS);
126         if (!pathname)
127                 return -ENOMEM;
128
129         ret = storage_save(keyfile, pathname);
130
131         g_free(pathname);
132
133         return ret;
134 }
135
136 #if defined TIZEN_EXT
137 GKeyFile *__connman_storage_load_ins(void)
138 {
139         gchar *pathname;
140         GKeyFile *keyfile = NULL;
141
142         pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
143         if (!pathname)
144                 return NULL;
145
146         keyfile = storage_load(pathname);
147
148         g_free(pathname);
149
150         return keyfile;
151 }
152
153 int __connman_storage_save_ins(GKeyFile *keyfile)
154 {
155         gchar *pathname;
156         int ret;
157
158         pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
159         if (!pathname)
160                 return -ENOMEM;
161
162         ret = storage_save(keyfile, pathname);
163
164         g_free(pathname);
165
166         return ret;
167 }
168 #endif
169
170 void __connman_storage_delete_global(void)
171 {
172         gchar *pathname;
173
174         pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS);
175         if (!pathname)
176                 return;
177
178         storage_delete(pathname);
179
180         g_free(pathname);
181 }
182
183 GKeyFile *__connman_storage_load_config(const char *ident)
184 {
185         gchar *pathname;
186         GKeyFile *keyfile = NULL;
187
188         pathname = g_strdup_printf("%s/%s.config", STORAGEDIR, ident);
189         if (!pathname)
190                 return NULL;
191
192         keyfile = storage_load(pathname);
193
194         g_free(pathname);
195
196         return keyfile;
197 }
198
199 GKeyFile *__connman_storage_load_provider_config(const char *ident)
200 {
201         gchar *pathname;
202         GKeyFile *keyfile = NULL;
203
204         pathname = g_strdup_printf("%s/%s.config", VPN_STORAGEDIR, ident);
205         if (!pathname)
206                 return NULL;
207
208         keyfile = storage_load(pathname);
209
210         g_free(pathname);
211
212         return keyfile;
213 }
214
215 GKeyFile *__connman_storage_open_service(const char *service_id)
216 {
217         gchar *pathname;
218         GKeyFile *keyfile = NULL;
219
220         pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, SETTINGS);
221         if (!pathname)
222                 return NULL;
223
224         keyfile =  storage_load(pathname);
225         if (keyfile) {
226                 g_free(pathname);
227                 return keyfile;
228         }
229
230         g_free(pathname);
231
232         keyfile = g_key_file_new();
233
234         return keyfile;
235 }
236
237 gchar **connman_storage_get_services(void)
238 {
239         struct dirent *d;
240         gchar *str;
241         DIR *dir;
242         GString *result;
243         gchar **services = NULL;
244         struct stat buf;
245         int ret;
246
247         dir = opendir(STORAGEDIR);
248         if (!dir)
249                 return NULL;
250
251         result = g_string_new(NULL);
252
253         while ((d = readdir(dir))) {
254                 if (strcmp(d->d_name, ".") == 0 ||
255                                 strcmp(d->d_name, "..") == 0 ||
256                                 strncmp(d->d_name, "provider_", 9) == 0)
257                         continue;
258
259                 switch (d->d_type) {
260                 case DT_DIR:
261                 case DT_UNKNOWN:
262                         /*
263                          * If the settings file is not found, then
264                          * assume this directory is not a services dir.
265                          */
266                         str = g_strdup_printf("%s/%s/settings", STORAGEDIR,
267                                                                 d->d_name);
268                         ret = stat(str, &buf);
269                         g_free(str);
270                         if (ret < 0)
271                                 continue;
272
273                         g_string_append_printf(result, "%s/", d->d_name);
274                         break;
275                 }
276         }
277
278         closedir(dir);
279
280         str = g_string_free(result, FALSE);
281         if (str && str[0] != '\0') {
282                 /*
283                  * Remove the trailing separator so that services doesn't end up
284                  * with an empty element.
285                  */
286                 str[strlen(str) - 1] = '\0';
287                 services = g_strsplit(str, "/", -1);
288         }
289         g_free(str);
290
291         return services;
292 }
293
294 GKeyFile *connman_storage_load_service(const char *service_id)
295 {
296         gchar *pathname;
297         GKeyFile *keyfile = NULL;
298
299         pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, SETTINGS);
300         if (!pathname)
301                 return NULL;
302
303         keyfile =  storage_load(pathname);
304         g_free(pathname);
305
306         return keyfile;
307 }
308
309 int __connman_storage_save_service(GKeyFile *keyfile, const char *service_id)
310 {
311         int ret = 0;
312         gchar *pathname, *dirname;
313
314         dirname = g_strdup_printf("%s/%s", STORAGEDIR, service_id);
315         if (!dirname)
316                 return -ENOMEM;
317
318         /* If the dir doesn't exist, create it */
319         if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
320                 if (mkdir(dirname, MODE) < 0) {
321                         if (errno != EEXIST) {
322                                 g_free(dirname);
323                                 return -errno;
324                         }
325                 }
326         }
327
328         pathname = g_strdup_printf("%s/%s", dirname, SETTINGS);
329
330         g_free(dirname);
331
332         ret = storage_save(keyfile, pathname);
333
334         g_free(pathname);
335
336         return ret;
337 }
338
339 static bool remove_file(const char *service_id, const char *file)
340 {
341         gchar *pathname;
342         bool ret = false;
343
344         pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, file);
345         if (!pathname)
346                 return false;
347
348         if (!g_file_test(pathname, G_FILE_TEST_EXISTS)) {
349                 ret = true;
350         } else if (g_file_test(pathname, G_FILE_TEST_IS_REGULAR)) {
351                 unlink(pathname);
352                 ret = true;
353         }
354
355         g_free(pathname);
356         return ret;
357 }
358
359 static bool remove_dir(const char *service_id)
360 {
361         gchar *pathname;
362         bool ret = false;
363
364         pathname = g_strdup_printf("%s/%s", STORAGEDIR, service_id);
365         if (!pathname)
366                 return false;
367
368         if (!g_file_test(pathname, G_FILE_TEST_EXISTS)) {
369                 ret = true;
370         } else if (g_file_test(pathname, G_FILE_TEST_IS_DIR)) {
371                 rmdir(pathname);
372                 ret = true;
373         }
374
375         g_free(pathname);
376         return ret;
377 }
378
379 bool __connman_storage_remove_service(const char *service_id)
380 {
381         bool removed;
382
383         /* Remove service configuration file */
384         removed = remove_file(service_id, SETTINGS);
385         if (!removed)
386                 return false;
387
388         /* Remove the statistics file also */
389         removed = remove_file(service_id, "data");
390         if (!removed)
391                 return false;
392
393         removed = remove_dir(service_id);
394         if (!removed)
395                 return false;
396
397         DBG("Removed service dir %s/%s", STORAGEDIR, service_id);
398
399         return true;
400 }
401
402 GKeyFile *__connman_storage_load_provider(const char *identifier)
403 {
404         gchar *pathname;
405         GKeyFile *keyfile;
406
407         pathname = g_strdup_printf("%s/%s_%s/%s", STORAGEDIR, "provider",
408                         identifier, SETTINGS);
409         if (!pathname)
410                 return NULL;
411
412         keyfile = storage_load(pathname);
413         g_free(pathname);
414
415         return keyfile;
416 }
417
418 void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier)
419 {
420         gchar *pathname, *dirname;
421
422         dirname = g_strdup_printf("%s/%s_%s", STORAGEDIR,
423                         "provider", identifier);
424         if (!dirname)
425                 return;
426
427         if (!g_file_test(dirname, G_FILE_TEST_IS_DIR) &&
428                         mkdir(dirname, MODE) < 0) {
429                 g_free(dirname);
430                 return;
431         }
432
433         pathname = g_strdup_printf("%s/%s", dirname, SETTINGS);
434         g_free(dirname);
435
436         storage_save(keyfile, pathname);
437         g_free(pathname);
438 }
439
440 static bool remove_all(const char *id)
441 {
442         bool removed;
443
444         remove_file(id, SETTINGS);
445         remove_file(id, "data");
446
447         removed = remove_dir(id);
448         if (!removed)
449                 return false;
450
451         return true;
452 }
453
454 bool __connman_storage_remove_provider(const char *identifier)
455 {
456         bool removed;
457         gchar *id;
458
459         id = g_strdup_printf("%s_%s", "provider", identifier);
460         if (!id)
461                 return false;
462
463         if (remove_all(id))
464                 DBG("Removed provider dir %s/%s", STORAGEDIR, id);
465
466         g_free(id);
467
468         id = g_strdup_printf("%s_%s", "vpn", identifier);
469         if (!id)
470                 return false;
471
472         if ((removed = remove_all(id)))
473                 DBG("Removed vpn dir %s/%s", STORAGEDIR, id);
474
475         g_free(id);
476
477         return removed;
478 }
479
480 gchar **__connman_storage_get_providers(void)
481 {
482         GSList *list = NULL;
483         int num = 0, i = 0;
484         struct dirent *d;
485         gchar *str;
486         DIR *dir;
487         struct stat buf;
488         int ret;
489         char **providers;
490         GSList *iter;
491
492         dir = opendir(STORAGEDIR);
493         if (!dir)
494                 return NULL;
495
496         while ((d = readdir(dir))) {
497                 if (strcmp(d->d_name, ".") == 0 ||
498                                 strcmp(d->d_name, "..") == 0 ||
499                                 strncmp(d->d_name, "provider_", 9) != 0)
500                         continue;
501
502                 if (d->d_type == DT_DIR) {
503                         str = g_strdup_printf("%s/%s/settings", STORAGEDIR,
504                                         d->d_name);
505                         ret = stat(str, &buf);
506                         g_free(str);
507                         if (ret < 0)
508                                 continue;
509                         list = g_slist_prepend(list, g_strdup(d->d_name));
510                         num += 1;
511                 }
512         }
513
514         closedir(dir);
515
516         providers = g_try_new0(char *, num + 1);
517         for (iter = list; iter; iter = g_slist_next(iter)) {
518                 if (providers)
519                         providers[i] = iter->data;
520                 else
521                         g_free(iter->data);
522                 i += 1;
523         }
524         g_slist_free(list);
525
526         return providers;
527 }