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