vconf cb debugging info add
[framework/appfw/vconf.git] / vconftool.c
1 /*
2  * libslp-setting
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hakjoo Ko <hakjoo.ko@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26 #include <vconf.h>
27 #include <glib-object.h>
28 #include "vconf-log.h"
29
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <fcntl.h>
34 #include <errno.h>
35
36 #include <wordexp.h>
37
38 enum {
39         VCONFTOOL_TYPE_NO = 0x00,
40         VCONFTOOL_TYPE_STRING,
41         VCONFTOOL_TYPE_INT,
42         VCONFTOOL_TYPE_DOUBLE,
43         VCONFTOOL_TYPE_BOOL
44 };
45
46 #define BUFSIZE         1024
47
48 const char *BACKEND_DB_PREFIX = "db/";
49 const char *BACKEND_FILE_PREFIX = "file/";
50 const char *BACKEND_MEMORY_PREFIX = "memory/";
51
52 const char *DB_PREFIX = "/opt/var/kdb";
53 const char *FILE_PREFIX = "/opt/var/kdb";
54 const char *MEMORY_PREFIX = "/var/run";
55 const char *MEMORY_INIT = "/opt/var/kdb/memory_init";
56
57 static char *guid = NULL;
58 static char *uid = NULL;
59 static char *vconf_type = NULL;
60 static int is_recursive = FALSE;
61 static int is_initialization = FALSE;
62 static int is_forced = FALSE;
63 static int get_num = 0;
64
65 static GOptionEntry entries[] = {
66         {"type", 't', 0, G_OPTION_ARG_STRING, &vconf_type, "type of value",
67          "int|bool|double|string"},
68         {"recursive", 'r', 0, G_OPTION_ARG_NONE, &is_recursive,
69          "retrieve keys recursively", NULL},
70         {"guid", 'g', 0, G_OPTION_ARG_STRING, &guid, "group permission", NULL},
71         {"uid", 'u', 0, G_OPTION_ARG_STRING, &uid, "user permission", NULL},
72         {"initialization", 'i', 0, G_OPTION_ARG_NONE, &is_initialization,
73          "memory backend initialization", NULL},
74         {"force", 'f', 0, G_OPTION_ARG_NONE, &is_forced,
75          "overwrite vconf values by force", NULL},
76         {NULL}
77 };
78
79 static void get_operation(char *input);
80 static void recursive_get(char *subDIR, int level);
81 static void print_keylist(keylist_t *keylist, keynode_t *temp_node, int level);
82
83 static void print_help(const char *cmd)
84 {
85         fprintf(stderr, "Usage:\n");
86         fprintf(stderr, "\n");
87         fprintf(stderr, "[Set vconf value]\n");
88         fprintf(stderr,
89                 "       %s set -t <TYPE> <KEY NAME> <VALUE> <OPTIONS>\n", cmd);
90         fprintf(stderr, "                 <TYPE>=int|bool|double|string\n");
91         fprintf(stderr, "\n");
92         fprintf(stderr,
93                 "       Ex) %s set -t string db/testapp/key1 \"This is test\" \n",
94                 cmd);
95         fprintf(stderr, "\n");
96         fprintf(stderr, "       <OPTIONS>\n");
97         fprintf(stderr,
98                 "          -g <GUID> : Set Effective group id. The key's permission will be set to 0664.\n");
99         fprintf(stderr,
100                 "           Ex) %s set -t string db/testapp/key1 \"This is test\" -g 425\n",
101                 cmd);
102         fprintf(stderr,
103                 "           NOTE: -g and -u cannot be userd together. -u ignores -g option.\n");
104         fprintf(stderr, "\n");
105         fprintf(stderr,
106                 "          -u <UID> : Set Effective user id. The key's permission will be set to 0644.\n");
107         fprintf(stderr,
108                 "           Ex) %s set -t string db/testapp/key1 \"This is test\" -u 5000\n",
109                 cmd);
110         fprintf(stderr,
111                 "           NOTE: -g and -u cannot be userd together. -u ignores -g option.\n");
112         fprintf(stderr, "\n");
113         fprintf(stderr,
114                 "          -i : Install memory backend key into flash space for backup.\n");
115         fprintf(stderr,
116                 "           Ex) %s set -t string db/testapp/key1 \"This is test\" -i\n",
117                 cmd);
118         fprintf(stderr, "\n");
119         fprintf(stderr,
120                 "          -f : Overwrite values by force, even when vconf values are already exist.\n");
121         fprintf(stderr, "\n");
122         fprintf(stderr, "[Get vconf value]\n");
123         fprintf(stderr, "       %s get <OPTIONS> <KEY NAME>\n", cmd);
124         fprintf(stderr, "\n");
125         fprintf(stderr, "       <OPTIONS>\n");
126         fprintf(stderr,
127                 "          -r : retrieve all keys included in sub-directorys \n");
128         fprintf(stderr, "       Ex) %s get db/testapp/key1\n", cmd);
129         fprintf(stderr, "           %s get db/testapp/\n", cmd);
130         fprintf(stderr, "\n");
131         fprintf(stderr, "[Unset vconf value]\n");
132         fprintf(stderr, "       %s unset <KEY NAME>\n", cmd);
133         fprintf(stderr, "\n");
134         fprintf(stderr, "       Ex) %s unset db/testapp/key1\n", cmd);
135         fprintf(stderr, "\n");
136 }
137
138 static int check_type(void)
139 {
140         if (vconf_type) {
141                 if (!strncasecmp(vconf_type, "int", 3))
142                         return VCONFTOOL_TYPE_INT;
143                 else if (!strncasecmp(vconf_type, "string", 6))
144                         return VCONFTOOL_TYPE_STRING;
145                 else if (!strncasecmp(vconf_type, "double", 6))
146                         return VCONFTOOL_TYPE_DOUBLE;
147                 else if (!strncasecmp(vconf_type, "bool", 4))
148                         return VCONFTOOL_TYPE_BOOL;
149         }
150         return VCONFTOOL_TYPE_NO;
151 }
152
153 static int __system(char * cmd)
154 {
155         int status;
156         pid_t cpid;
157
158         if((cpid = fork()) < 0) {
159                 perror("fork");
160                 return -1;
161         }
162
163         if (cpid == 0) {
164                 /* child */
165                 wordexp_t p;
166                 char **w;
167
168                 wordexp(cmd, &p, 0);
169                 w = p.we_wordv;
170
171                 execv(w[0], (char *const *)w);
172
173                 wordfree(&p);
174
175                 _exit(-1);
176         } else {
177                 /* parent */
178                 if (waitpid(cpid, &status, 0) == -1) {
179                         perror("waitpid failed");
180                         return -1;
181                 }
182                 if (WIFSIGNALED(status)) {
183                         printf("signal(%d)\n", WTERMSIG(status));
184                         perror("exit by signal");
185                         return -1;
186                 }
187                 if (!WIFEXITED(status)) {
188                         perror("exit abnormally");
189                         return -1;
190                 }
191                 if (WIFEXITED(status) && WEXITSTATUS(status)) {
192                         perror("child return error");
193                         return -1;
194                 }
195         }
196
197         return 0;
198 }
199
200 static void disable_invalid_char(char* src)
201 {
202         char* tmp;
203
204         for(tmp = src; *tmp; ++tmp)
205         {
206                 if( (*tmp == ';') || (*tmp == '|') )
207                 {
208                         fprintf(stderr,"invalid char is found\n");
209                         *tmp = '_';
210                 }
211         }
212 }
213
214 static int check_file_path_mode(char* file_path)
215 {
216         char szCmd[BUFSIZE] = {0,};
217         int create_file = 0;
218         int set_id = 0;
219         int fd;
220
221         if (guid || uid) {
222                 if (getuid() != 0) {
223                         fprintf(stderr,
224                                 "Error!\t Only root user can use '-g or -u' option\n");
225                         return -1;
226                 }
227
228                 set_id = 1;
229         }
230
231         /* Check file path */
232         if (access(file_path, F_OK) != 0) {
233                 /* fprintf(stderr,"key does not exist\n"); */
234
235                 char szPath[BUFSIZE] = { 0, };
236                 char *pCh = strrchr(file_path, '/');
237                 strncat(szPath, file_path, pCh - file_path);
238                 /* fprintf(stderr, "szPath : %s\n", szPath); */
239
240                 /* Check directory & create it */
241                 if (access(szPath, F_OK) != 0) {
242                         /* fprintf(stderr,"parent dir does not exist\n"); */
243
244                         snprintf(szCmd, BUFSIZE, "/bin/mkdir %s -p --mode=755", szPath);
245                         disable_invalid_char(szCmd);
246                         if (__system(szCmd)) {
247                                 fprintf(stderr,"Fail mkdir() szCmd=%s\n", __FILE__, __LINE__, szCmd);
248                                 return -1;
249                         }
250
251                 }
252
253                 create_file = 1;
254         } else if (!is_forced) {
255                 fprintf(stderr, "Key already exist. Use -f option to force update\n");
256                 return -1;
257         }
258
259         if(create_file) {
260                 /* Create file */
261                 mode_t temp;
262                 temp = umask(0000);
263                 fd = open(file_path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
264                 umask(temp);
265                 if(fd == -1) {
266                         fprintf(stderr, "open(rdwr,create) error\n");
267                         return -1;
268                 }
269                 close(fd);
270         }
271
272         if(set_id) {
273                 if((fd = open(file_path, O_RDONLY)) == -1) {
274                         fprintf(stderr, "open(rdonly) error\n");
275                         return -1;
276                 }
277
278                 if(uid) {
279                         if (fchown(fd, atoi(uid), atoi(uid)) == -1) {
280                                 fprintf(stderr, "Error!\t Fail to fchown(%d)\n", errno);
281                                 close(fd);
282                                 return -1;
283                         }
284                 } else if (guid) {
285                         if (-1 == fchown(fd, 0, atoi(guid))) {
286                                 fprintf(stderr, "Error!\t Fail to fchown()\n");
287                                 close(fd);
288                                 return -1;
289                         }
290                 }
291
292                 close(fd);
293         }
294
295         return 0;
296 }
297
298 static int copy_memory_key(char *pszKey, char *pszOrigin)
299 {
300         char szCmd[BUFSIZE] = { 0, };
301         char szPath[BUFSIZE] = { 0, };
302         char szFileName[BUFSIZE] = { 0, };
303         char *pCh = strrchr(pszKey, '/');
304         int nLen = strlen(pszKey);
305
306         /* Get directory path and file name */
307         snprintf(szPath, BUFSIZE, "%s/", MEMORY_INIT);
308         strncat(szPath, pszKey, pCh - pszKey);
309         strncpy(szFileName, pszKey + (pCh - pszKey) + 1, nLen - (pCh - pszKey));
310
311         /* Check directory & create it */
312         if (0 != access(szPath, F_OK)) {
313                 snprintf(szCmd, BUFSIZE, "mkdir %s -p --mode=755", szPath);
314                 if (system(szCmd)) {
315                         printf("[%s:%d]Fail mkdir() szCmd=%s\n", __FILE__,
316                                __LINE__, szCmd);
317                         return -1;
318                 }
319         }
320         /* copy */
321         strncat(szPath, "/", 1);
322         strncat(szPath, szFileName, strlen(szFileName));
323         memset(szCmd, 0x00, BUFSIZE);
324         snprintf(szCmd, BUFSIZE, "cp %s %s -r -p", pszOrigin, szPath);
325         if (system(szCmd)) {
326                 printf("[%s:%d]Fail copy\n", __FILE__, __LINE__);
327                 return -1;
328         }
329         return 0;
330 }
331
332 static int make_file_path(char *pszKey, char *pszBuf)
333 {
334         if (0 ==
335             strncmp(pszKey, BACKEND_DB_PREFIX, sizeof(BACKEND_DB_PREFIX) - 1)) {
336                 snprintf(pszBuf, BUFSIZE, "%s/%s", DB_PREFIX, pszKey);
337                 return 0;
338         } else if (0 ==
339                    strncmp(pszKey, BACKEND_FILE_PREFIX,
340                            sizeof(BACKEND_FILE_PREFIX) - 1)) {
341                 snprintf(pszBuf, BUFSIZE, "%s/%s", FILE_PREFIX, pszKey);
342                 return 0;
343         } else if (0 ==
344                    strncmp(pszKey, BACKEND_MEMORY_PREFIX,
345                            sizeof(BACKEND_MEMORY_PREFIX) - 1)) {
346                 snprintf(pszBuf, BUFSIZE, "%s/%s", MEMORY_PREFIX, pszKey);
347                 return 0;
348         }
349         return -1;
350 }
351
352 int main(int argc, char **argv)
353 {
354         int set_type;
355         char szFilePath[BUFSIZE] = { 0, };
356         int fd;
357         int group_id;
358         int user_id;
359
360         GError *error = NULL;
361         GOptionContext *context;
362
363         g_type_init();
364         context = g_option_context_new("- vconf library tool");
365         g_option_context_add_main_entries(context, entries, NULL);
366         g_option_context_set_help_enabled(context, FALSE);
367         g_option_context_set_ignore_unknown_options(context, TRUE);
368
369         if (!g_option_context_parse(context, &argc, &argv, &error)) {
370                 g_print("option parsing failed: %s\n", error->message);
371                 exit(1);
372         }
373
374         if (argc < 2) {
375                 print_help(argv[0]);
376                 return 1;
377         }
378
379         if (!strncmp(argv[1], "set", 3)) {
380                 set_type = check_type();
381                 if (argc < 4 || !set_type) {
382                         print_help(argv[0]);
383                         return 1;
384                 }
385
386                 if (make_file_path(argv[2], szFilePath)) {
387                         fprintf(stderr, "Error!\t Bad prefix\n");
388                         return -1;
389                 }
390
391                 if (check_file_path_mode(szFilePath)) {
392                         fprintf(stderr, "Error!\t create key %s\n", argv[2]);
393                         return -1;
394                 }
395
396                 switch (set_type) {
397                         case VCONFTOOL_TYPE_STRING:
398                                 vconf_set_str(argv[2], argv[3]);
399                                 break;
400                         case VCONFTOOL_TYPE_INT:
401                                 vconf_set_int(argv[2], atoi(argv[3]));
402                                 break;
403                         case VCONFTOOL_TYPE_DOUBLE:
404                                 vconf_set_dbl(argv[2], atof(argv[3]));
405                                 break;
406                         case VCONFTOOL_TYPE_BOOL:
407                                 vconf_set_bool(argv[2], !!atoi(argv[3]));
408                                 break;
409                         default:
410                                 fprintf(stderr, "never reach");
411                                 exit(1);
412                 }
413
414                 /* Install memory backend key into flash space *******/
415                 if (is_initialization) {
416                         copy_memory_key(argv[2], szFilePath);
417                 }
418                 /* End memory backend key into flash space ***********/
419
420         } else if (!strncmp(argv[1], "get", 3)) {
421                 if (argv[2])
422                         get_operation(argv[2]);
423                 else
424                         print_help(argv[0]);
425         } else if (!strncmp(argv[1], "unset", 5)) {
426                 if (argv[2])
427                         vconf_unset(argv[2]);
428                 else
429                         print_help(argv[0]);
430         } else
431                 fprintf(stderr, "%s is a invalid command\n", argv[1]);
432         return 0;
433 }
434
435 static void get_operation(char *input)
436 {
437         keylist_t *get_keylist;
438         keynode_t *temp_node;
439         char *test;
440
441         get_keylist = vconf_keylist_new();
442         /* ParentDIR parameter of gconf_client_all_entries
443         can not include the last slash. */
444         if ('/' == input[strlen(input) - 1] && strlen(input) > 8)
445                 input[strlen(input) - 1] = '\0';
446
447         vconf_get(get_keylist, input, VCONF_GET_ALL);
448         if (!(temp_node = vconf_keylist_nextnode(get_keylist))) {
449                 test = strrchr(input, '/');
450                 if (NULL != test) {
451                         vconf_keylist_add_null(get_keylist, input);
452                         if (test - input < 7)
453                                 *(test + 1) = '\0';
454                         else
455                                 *test = '\0';
456                         vconf_get(get_keylist, input, VCONF_GET_KEY);
457                         temp_node = vconf_keylist_nextnode(get_keylist);
458                 } else {
459                         fprintf(stderr, "Include at least one slash\"/\"\n");
460                         vconf_keylist_free(get_keylist);
461                         return;
462                 }
463         }
464         get_num = 0;
465         print_keylist(get_keylist, temp_node, 0);
466
467         if (!get_num)
468                 printf("No data\n");
469         vconf_keylist_free(get_keylist);
470 }
471
472 static void recursive_get(char *subDIR, int level)
473 {
474         printf("%s", subDIR);
475
476         keylist_t *get_keylist;
477         keynode_t *first_node;
478
479         get_keylist = vconf_keylist_new();
480         vconf_get(get_keylist, subDIR, VCONF_GET_ALL);
481
482         if ((first_node = vconf_keylist_nextnode(get_keylist))) {
483                 print_keylist(get_keylist, first_node, level);
484         }
485         vconf_keylist_free(get_keylist);
486 }
487
488 static void print_keylist(keylist_t *keylist, keynode_t *temp_node, int level)
489 {
490         do {
491                 switch (vconf_keynode_get_type(temp_node))
492                 {
493                         case VCONF_TYPE_INT:
494                                 printf("%s, value = %d (int)\n",
495                                        vconf_keynode_get_name(temp_node),
496                                        vconf_keynode_get_int(temp_node));
497                                 get_num++;
498                                 break;
499                         case VCONF_TYPE_BOOL:
500                                 printf("%s, value = %d (bool)\n",
501                                        vconf_keynode_get_name(temp_node),
502                                        vconf_keynode_get_bool(temp_node));
503                                 get_num++;
504                                 break;
505                         case VCONF_TYPE_DOUBLE:
506                                 printf("%s, value = %f (double)\n",
507                                        vconf_keynode_get_name(temp_node),
508                                        vconf_keynode_get_dbl(temp_node));
509                                 get_num++;
510                                 break;
511                         case VCONF_TYPE_STRING:
512                                 printf("%s, value = %s (string)\n",
513                                        vconf_keynode_get_name(temp_node),
514                                        vconf_keynode_get_str(temp_node));
515                                 get_num++;
516                                 break;
517                         case VCONF_TYPE_DIR:
518                                 printf("%s(Directory)\n",
519                                         vconf_keynode_get_name(temp_node));
520                                 if (is_recursive)
521                                         recursive_get(vconf_keynode_get_name(temp_node),
522                                                       level + 1);
523                                 break;
524                         default:
525                                 /* fprintf(stderr, "Unknown Type(%d)\n", vconf_keynode_get_type(temp_node)); */
526                                 break;
527                 }
528         } while ((temp_node = vconf_keylist_nextnode(keylist)));
529 }