fix changelog
[platform/core/appfw/vconf.git] / vconf.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 <stdlib.h>
23 #include <limits.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include "vconf-internals.h"
28 #include <dirent.h>
29 #include <sys/stat.h>
30 #include <sys/xattr.h>
31 #include <ctype.h>
32
33 #ifndef API
34 #define API __attribute__ ((visibility("default")))
35 #endif
36
37 #define VCONF_ERROR_RETRY_CNT 20
38 #define VCONF_ERROR_RETRY_SLEEP_UTIME 10000
39
40 #define VCONF_NOT_INITIALIZED (access("/tmp/vconf-initialized", F_OK) == -1)
41
42 #ifdef VCONF_USE_SQLFS_TRANSACTION
43 int IN_SBOX=0;
44
45 #define VCONF_MOUNT_PATH "/opt/var/kdb/db"
46 #define VCONF_MOUNT_PATH_CHECK \
47 do{\
48         if(!IN_SBOX) \
49       IN_SBOX = access("/opt/var/kdb/kdb_first_boot", F_OK) + 2; \
50         if(2==IN_SBOX) return 0;\
51 }while(0)
52
53 __thread int is_transaction;
54 #endif
55
56 #ifdef VCONF_TIMECHECK
57 double correction, startT;
58
59 double set_start_time(void)
60 {
61         struct timeval tv;
62         double curtime;
63
64         gettimeofday(&tv, NULL);
65         curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
66         return curtime;
67 }
68
69 double exec_time(double start)
70 {
71         double end = set_start_time();
72         return (end - start - correction);
73 }
74
75 int init_time(void)
76 {
77         double temp_t;
78         temp_t = set_start_time();
79         correction = exec_time(temp_t);
80
81         return 0;
82 }
83 #endif
84
85 int _vconf_keynode_set_keyname(keynode_t *keynode, const char *keyname)
86 {
87         if (keynode->keyname) free(keynode->keyname);
88         keynode->keyname = strndup(keyname, VCONF_KEY_PATH_LEN);
89         retvm_if(keynode->keyname == NULL, VCONF_ERROR, "strndup Fails");
90         return VCONF_OK;
91 }
92
93 static inline void _vconf_keynode_set_dir(keynode_t *keynode)
94 {
95         keynode->type = VCONF_TYPE_DIR;
96 }
97
98 static inline void _vconf_keynode_set_value_int(keynode_t *keynode, const int value)
99 {
100         keynode->type = VCONF_TYPE_INT;
101         keynode->value.i = value;
102 }
103
104 static inline void _vconf_keynode_set_value_bool(keynode_t *keynode, const int value)
105 {
106         keynode->type = VCONF_TYPE_BOOL;
107         keynode->value.b = !!value;
108 }
109
110 static inline void _vconf_keynode_set_value_dbl(keynode_t *keynode, const double value)
111 {
112         keynode->type = VCONF_TYPE_DOUBLE;
113         keynode->value.d = value;
114 }
115
116 static inline void _vconf_keynode_set_value_str(keynode_t *keynode, const char *value)
117 {
118         keynode->type = VCONF_TYPE_STRING;
119         keynode->value.s = strdup(value);
120 }
121
122 inline void _vconf_keynode_set_null(keynode_t *keynode)
123 {
124         keynode->type = VCONF_TYPE_NONE;
125         //keynode->value.d = NULL;
126 }
127
128 static inline keynode_t *_vconf_keynode_next(keynode_t *keynode)
129 {
130         return keynode->next;
131 }
132
133 inline keynode_t *_vconf_keynode_new(void)
134 {
135         keynode_t *keynode;
136         keynode = calloc(1, sizeof(keynode_t));
137
138         return keynode;
139 }
140
141 inline void _vconf_keynode_free(keynode_t *keynode)
142 {
143         if(keynode) {
144                 if (keynode->keyname)
145                         free(keynode->keyname);
146                 if (keynode->type == VCONF_TYPE_STRING && keynode->value.s)
147                         free(keynode->value.s);
148                 free(keynode);
149         }
150 }
151
152 static inline keynode_t *_vconf_keylist_headnode(keylist_t *keylist)
153 {
154         return keylist->head;
155 }
156
157 static keynode_t *_vconf_keylist_lookup(keylist_t *keylist, const char *keyname,
158                                  keynode_t **before_keynode)
159 {
160         keynode_t *found_node, *temp_node = NULL;
161
162         found_node = _vconf_keylist_headnode(keylist);
163
164         while (found_node) {
165                 if(found_node->keyname == NULL) {
166                         ERR("key node has null keyname");
167                         return NULL;
168                 }
169
170                 if (!strncmp(keyname, found_node->keyname, strlen(keyname))) {
171                         if (before_keynode) {
172                                         *before_keynode = temp_node;
173                         }
174                         return found_node;
175                 }
176
177                 temp_node = found_node;
178                 found_node = _vconf_keynode_next(found_node);
179         }
180         return NULL;
181 }
182
183 /*
184  * This function get Key name of the keynode.
185  * @param[in] keynode The Key
186  * @return Key Name of the keynode
187  */
188 API char *vconf_keynode_get_name(keynode_t *keynode)
189 {
190         retvm_if(keynode == NULL, NULL, "Invalid argument: keynode is NULL");
191         retvm_if(keynode->keyname == NULL, NULL, "The name of keynode is NULL");
192
193         return keynode->keyname;
194 }
195
196 /*
197  * This function get value type of the keynode.
198  * @param[in] keynode The Key
199  * @return Type of the keynode
200  */
201 API int vconf_keynode_get_type(keynode_t *keynode)
202 {
203         retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
204
205         return keynode->type;
206 }
207
208 API int vconf_keynode_get_int(keynode_t *keynode)
209 {
210         retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
211         retvm_if(keynode->type != VCONF_TYPE_INT, VCONF_ERROR,
212                  "The type(%d) of keynode(%s) is not INT", keynode->type, keynode->keyname);
213
214         return keynode->value.i;
215 }
216
217 API double vconf_keynode_get_dbl(keynode_t *keynode)
218 {
219         retvm_if(keynode == NULL, -1.0, "Invalid argument: keynode is NULL");
220         retvm_if(keynode->type != VCONF_TYPE_DOUBLE, -1.0,
221                  "The type(%d) of keynode(%s) is not DBL", keynode->type, keynode->keyname);
222
223         return keynode->value.d;
224 }
225
226 /*
227  * This function get Boolean value of the keynode.
228  * @param[in] keynode The Key
229  * @return Boolean value, -1 on error
230  */
231 API int vconf_keynode_get_bool(keynode_t *keynode)
232 {
233         retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
234         retvm_if(keynode->type != VCONF_TYPE_BOOL, VCONF_ERROR,
235                  "The type(%d) of keynode(%s) is not BOOL", keynode->type, keynode->keyname);
236
237         return !!(keynode->value.b);
238 }
239
240 /*
241  * This function get String value of the keynode.
242  * @param[in] keynode The Key
243  * @return String value, NULL on error
244  */
245 API char *vconf_keynode_get_str(keynode_t *keynode)
246 {
247         retvm_if(keynode == NULL, NULL, "Invalid argument: keynode is NULL");
248         retvm_if(keynode->type != VCONF_TYPE_STRING, NULL,
249                 "The type(%d) of keynode(%s) is not STR", keynode->type, keynode->keyname);
250
251         return keynode->value.s;
252 }
253
254 /*
255  * Allocate, initialize and return a new Keylist object.
256  * @return The pointer of New keylist, NULL on error
257  */
258 API keylist_t *vconf_keylist_new(void)
259 {
260         keylist_t *keylist;
261         keylist = calloc(1, sizeof(keylist_t));
262
263         return keylist;
264 }
265
266 /*
267  * This function rewinds the KeyList internal cursor.
268  * @param[in] keylist Key List
269  * @return 0 on success, -1 on error
270  */
271 API int vconf_keylist_rewind(keylist_t *keylist)
272 {
273         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
274
275         keylist->cursor = NULL;
276
277         return 0;
278 }
279
280 /*
281  * A destructor for Keylist objects.
282  * @param[in] keylist Key List
283  * @return 0 on success, -1 on error
284  */
285 API int vconf_keylist_free(keylist_t *keylist)
286 {
287         keynode_t *keynode, *temp;
288
289         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
290
291         if (keylist->num) {
292                 keynode = _vconf_keylist_headnode(keylist);
293                 while (keynode) {
294                         temp = _vconf_keynode_next(keynode);
295                         _vconf_keynode_free(keynode);
296                         keynode = temp;
297                 }
298         }
299         free(keylist);
300         return 0;
301 }
302
303 /*
304  * This function look for a Keynode contained in keylist that matches keyname.
305  * @param[in] keylist Key List
306  * @param[in] keyname Key to find
307  * @param[out] return_node pointer of keynode to set
308  * @return Type of the found key
309  */
310 API int
311 vconf_keylist_lookup(keylist_t *keylist,
312                      const char *keyname, keynode_t **return_node)
313 {
314         keynode_t *found_node;
315
316         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
317         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
318         retvm_if(return_node == NULL, VCONF_ERROR, "Invalid argument: return_node is NULL");
319
320         found_node = _vconf_keylist_lookup(keylist, keyname, NULL);
321         if (NULL == found_node)
322                 return 0;
323
324         if (return_node)
325                 *return_node = found_node;
326         return found_node->type;
327 }
328
329 /*
330  * This function returns the next Key in a Keylist.
331  * Next key is known by the keylist internal cursor.
332  * @param[in] keylist Key List
333  * @return The next Keynode, NULL on error
334  */
335 API keynode_t *vconf_keylist_nextnode(keylist_t *keylist)
336 {
337         retvm_if(keylist == NULL, NULL, "Invalid argument: keylist is NULL");
338
339         if (keylist->cursor)
340                 keylist->cursor = _vconf_keynode_next(keylist->cursor);
341         else
342                 keylist->cursor = keylist->head;
343
344         return keylist->cursor;
345 }
346
347 /*
348  * This function appends a new Keynode included integer value to the keylist.
349  * If same keyname exist, the keynode will change.
350  * @param[in] keylist Key List
351  * @param[in] keyname Key
352  * @param[in] value The integer value
353  * @return Number of keynode included in the keylist, -1 on error
354  */
355 API int
356 vconf_keylist_add_int(keylist_t *keylist, const char *keyname, const int value)
357 {
358         keynode_t *keynode = NULL, *addition = NULL;
359
360         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
361         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
362
363         if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
364                 _vconf_keynode_set_value_int(keynode, value);
365                 return keylist->num;
366         }
367         if ((keynode = _vconf_keylist_headnode(keylist)))
368                 while (_vconf_keynode_next(keynode))
369                         keynode = _vconf_keynode_next(keynode);
370
371         addition = calloc(1, sizeof(keynode_t));
372         retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
373         if (!_vconf_keynode_set_keyname(addition, keyname)) {
374                 _vconf_keynode_set_value_int(addition, value);
375                 if (keylist->head && NULL != keynode)
376                         keynode->next = addition;
377                 else
378                         keylist->head = addition;
379                 keylist->num += 1;
380         } else {
381                 ERR("(maybe)not enought memory");
382                 free(addition), addition = NULL;
383                 return VCONF_ERROR;
384         }
385
386         return keylist->num;
387 }
388
389 /*
390  * This function appends a new Keynode included boolean value to the keylist.
391  * If same keyname exist, the keynode will change.
392  * @param[in] keylist Key List
393  * @param[in] keyname Key
394  * @param[in] value The boolean value
395  * @return Number of keynode included in the keylist, -1 on error
396  */
397 API int
398 vconf_keylist_add_bool(keylist_t *keylist, const char *keyname, const int value)
399 {
400         keynode_t *keynode = NULL, *addition = NULL;
401
402         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
403         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
404
405         if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
406                 _vconf_keynode_set_value_bool(keynode, value);
407                 return keylist->num;
408         }
409         if ((keynode = _vconf_keylist_headnode(keylist)))
410                 while (_vconf_keynode_next(keynode))
411                         keynode = _vconf_keynode_next(keynode);
412
413         addition = calloc(1, sizeof(keynode_t));
414         retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
415         if (!_vconf_keynode_set_keyname(addition, keyname)) {
416                 _vconf_keynode_set_value_bool(addition, value);
417                 if (keylist->head && NULL != keynode)
418                         keynode->next = addition;
419                 else
420                         keylist->head = addition;
421                 keylist->num += 1;
422         } else {
423                 ERR("(maybe)not enought memory");
424                 free(addition), addition = NULL;
425                 return VCONF_ERROR;
426         }
427
428         return keylist->num;
429 }
430
431 /*
432  * This function appends a new Keynode included double value to the keylist.
433  * If same keyname exist, the keynode will change.
434  * @param[in] keylist Key List
435  * @param[in] keyname Key
436  * @param[in] value The double value
437  * @return Number of keynode included in the keylist, -1 on error
438  */
439 API int
440 vconf_keylist_add_dbl(keylist_t *keylist,
441                       const char *keyname, const double value)
442 {
443         keynode_t *keynode = NULL, *addition = NULL;
444
445         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
446         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
447
448         if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
449                 _vconf_keynode_set_value_dbl(keynode, value);
450                 return keylist->num;
451         }
452         if ((keynode = _vconf_keylist_headnode(keylist)))
453                 while (_vconf_keynode_next(keynode))
454                         keynode = _vconf_keynode_next(keynode);
455
456         addition = calloc(1, sizeof(keynode_t));
457         retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
458         if (!_vconf_keynode_set_keyname(addition, keyname)) {
459                 _vconf_keynode_set_value_dbl(addition, value);
460                 if (keylist->head && NULL != keynode)
461                         keynode->next = addition;
462                 else
463                         keylist->head = addition;
464                 keylist->num += 1;
465         } else {
466                 ERR("(maybe)not enought memory");
467                 free(addition), addition = NULL;
468                 return VCONF_ERROR;
469         }
470
471         return keylist->num;
472 }
473
474 /*
475  * This function appends a new Keynode included string value to the keylist.
476  * If same keyname exist, the keynode will change.
477  * @param[in] keylist Key List
478  * @param[in] keyname Key
479  * @param[in] value The pointer of string value
480  * @return Number of keynode included in the keylist, -1 on error
481  */
482 API int
483 vconf_keylist_add_str(keylist_t *keylist,
484                       const char *keyname, const char *value)
485 {
486         keynode_t *keynode = NULL, *addition = NULL;
487
488         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
489         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
490
491         if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
492                 if (VCONF_TYPE_STRING == keynode->type && keynode->value.s)
493                         free(keynode->value.s);
494                 _vconf_keynode_set_value_str(keynode, value);
495                 return keylist->num;
496         }
497         if (NULL != (keynode = _vconf_keylist_headnode(keylist)))
498                 while (_vconf_keynode_next(keynode))
499                         keynode = _vconf_keynode_next(keynode);
500
501         addition = calloc(1, sizeof(keynode_t));
502         retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
503         if (!_vconf_keynode_set_keyname(addition, keyname)) {
504                 _vconf_keynode_set_value_str(addition, value);
505                 if (keylist->head && NULL != keynode)
506                         keynode->next = addition;
507                 else
508                         keylist->head = addition;
509                 keylist->num += 1;
510         } else {
511                 ERR("(maybe)not enought memory");
512                 free(addition), addition = NULL;
513                 return VCONF_ERROR;
514         }
515
516         return keylist->num;
517 }
518
519 /*
520  * This function Appends a new Keynode to the keylist without value.
521  * Use on vconf_get()
522  * @param[in] keylist Key List
523  * @param[in] keyname Key
524  * @return Number of keynode included in the keylist, -1 on error
525  */
526 API int vconf_keylist_add_null(keylist_t *keylist, const char *keyname)
527 {
528         keynode_t *keynode = NULL, *addition = NULL;
529
530         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
531         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
532
533         if (NULL != (keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
534                 keynode->type = 0;
535                 keynode->value.d = 0;
536                 return keylist->num;
537         }
538         if ((keynode = _vconf_keylist_headnode(keylist)))
539                 while (_vconf_keynode_next(keynode))
540                         keynode = _vconf_keynode_next(keynode);
541
542         addition = calloc(1, sizeof(keynode_t));
543         retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
544         if (!_vconf_keynode_set_keyname(addition, keyname)) {
545                 if (keylist->head && keynode)
546                         keynode->next = addition;
547                 else
548                         keylist->head = addition;
549                 keylist->num += 1;
550         } else {
551                 ERR("(maybe)not enought memory");
552                 free(addition), addition = NULL;
553                 return VCONF_ERROR;
554         }
555
556         return keylist->num;
557 }
558
559 /*
560  * This function remove the keynode that matches keyname.
561  * @param[in] keylist the keylist included the keyname
562  * @param[in] keyname key
563  * @return 0 on success, -1(Invalid parameter), -2(Not exist keyname in keylist) on error
564  */
565 API int vconf_keylist_del(keylist_t *keylist, const char *keyname)
566 {
567         keynode_t *found_node, *before_node = NULL;
568
569         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
570         retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
571
572         if ((found_node = _vconf_keylist_lookup(keylist, keyname, &before_node))) {
573                 if(before_node) {
574                         before_node->next = found_node->next;
575                 } else {
576                         /* requested key is headnode of keylist */
577                         keylist->head = found_node->next;
578                 }
579
580                 _vconf_keynode_free(found_node);
581         } else
582                 return VCONF_ERROR;
583
584         return VCONF_OK;
585 }
586
587
588 int _vconf_get_key_prefix(const char *keyname, int *prefix)
589 {
590         if (strncmp(keyname, BACKEND_DB_PREFIX, strlen(BACKEND_DB_PREFIX)) == 0) {
591                 *prefix = VCONF_BACKEND_DB;
592         } else if (0 == strncmp(keyname, BACKEND_FILE_PREFIX, strlen(BACKEND_FILE_PREFIX))) {
593                 *prefix = VCONF_BACKEND_FILE;
594         } else if (0 == strncmp(keyname, BACKEND_MEMORY_PREFIX, strlen(BACKEND_MEMORY_PREFIX))) {
595                 *prefix = VCONF_BACKEND_MEMORY;
596         } else {
597                 ERR("Invalid argument: wrong prefix of key(%s)", keyname);
598                 *prefix = VCONF_BACKEND_NULL;
599                 return VCONF_ERROR_WRONG_PREFIX;
600         }
601
602         return VCONF_OK;
603 }
604
605 int _vconf_get_key_path(const char *keyname, char *path)
606 {
607         if (strncmp(keyname, BACKEND_DB_PREFIX, strlen(BACKEND_DB_PREFIX)) == 0) {
608                 snprintf(path, VCONF_KEY_PATH_LEN, "%s%s", BACKEND_SYSTEM_DIR, keyname);
609         } else if (0 == strncmp(keyname, BACKEND_FILE_PREFIX, strlen(BACKEND_FILE_PREFIX))) {
610                 snprintf(path, VCONF_KEY_PATH_LEN, "%s%s", BACKEND_SYSTEM_DIR, keyname);
611         } else if (0 == strncmp(keyname, BACKEND_MEMORY_PREFIX, strlen(BACKEND_MEMORY_PREFIX))) {
612                 snprintf(path, VCONF_KEY_PATH_LEN, "%s%s", BACKEND_MEMORY_DIR, keyname);
613         } else {
614                 ERR("Invalid argument: wrong prefix of key(%s)", keyname);
615                 return VCONF_ERROR_WRONG_PREFIX;
616         }
617
618         return VCONF_OK;
619 }
620
621 #ifdef VCONF_USE_BACKUP_TRANSACTION
622 int _vconf_get_backup_path(const char *keyname, char *path)
623 {
624         char key_buf[VCONF_KEY_PATH_LEN] = {0, };
625         int i;
626
627         for(i = 0; i<VCONF_KEY_PATH_LEN-1 && keyname[i] != '\0' ; i++) {
628                 if (keyname[i] == '/')
629                         key_buf[i] = '$';
630                 else
631                         key_buf[i] = keyname[i];
632         }
633
634         snprintf(path, VCONF_KEY_PATH_LEN, "%s%s%s%s", BACKEND_SYSTEM_DIR, BACKEND_DB_PREFIX, ".backup/", key_buf);
635
636         return VCONF_OK;
637 }
638 #endif
639
640 #ifndef DISABLE_RUNTIME_KEY_CREATION
641 static int _vconf_set_key_check_parent_dir(const char* path)
642 {
643         int exists = 0;
644         struct stat stat_info;
645         char* parent;
646         char path_buf[VCONF_KEY_PATH_LEN] = {0,};
647         int ret = 0;
648
649         mode_t dir_mode =  0664 | 0111;
650
651         parent = strrchr(path, '/');
652         strncpy(path_buf, path, parent-path);
653         path_buf[parent-path]=0;
654
655         exists = stat(path_buf,&stat_info);
656         if(exists){
657                 if(mkdir(path_buf, dir_mode) != 0) {
658                         if(errno == ENOENT) {
659                                 ret = _vconf_set_key_check_parent_dir((const char*)path_buf);
660                                 if(ret != VCONF_OK) return ret;
661                                 if(mkdir(path_buf, dir_mode) != 0) {
662                                         ERR("mkdir error(%d)", errno);
663                                         return VCONF_ERROR;
664                                 }
665                         }
666                 }
667         }
668
669         return VCONF_OK;
670 }
671
672 static int _vconf_set_key_creation(const char* path)
673 {
674         int fd;
675         mode_t temp;
676         temp = umask(0000);
677         fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
678         umask(temp);
679         if(fd == -1) {
680                 ERR("open(rdwr,create) error\n");
681                 return VCONF_ERROR;
682         }
683         close(fd);
684
685         return VCONF_OK;
686 }
687 #endif
688
689 static int _vconf_set_file_lock(int fd, short type)
690 {
691         struct flock l;
692
693         l.l_type = type; /*Do read Lock*/
694         l.l_start= 0;       /*Start at begin*/
695         l.l_whence = SEEK_SET;
696         l.l_len = 0;        /*Do it with whole file*/
697
698         return fcntl(fd, F_SETLKW, &l);
699 }
700
701 static int _vconf_set_read_lock(int fd)
702 {
703         return _vconf_set_file_lock(fd, F_RDLCK);
704 }
705
706 static int _vconf_set_write_lock(int fd)
707 {
708         return _vconf_set_file_lock(fd, F_WRLCK);
709 }
710
711 static int _vconf_set_unlock(int fd)
712 {
713         return _vconf_set_file_lock(fd, F_UNLCK);
714 }
715
716 #ifdef VCONF_USE_SQLFS_TRANSACTION
717 static void _vconf_acquire_transaction_delay(int ms)
718 {
719     struct timeval timeout;
720     timeout.tv_sec = ms / 1000 ;
721     timeout.tv_usec = 1000 * ( ms % 1000 );
722
723     select(0, 0, 0, 0, &timeout);
724 }
725
726 static int _vconf_db_begin_transaction()
727 {
728         pid_t value;
729         VCONF_MOUNT_PATH_CHECK;
730
731         if(is_transaction == 0) {
732                 value = getpid();
733 transaction_retry:
734                 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_start", &value, sizeof(value), 0) == -1)
735                 {
736                         //ERR("someone access vconf. retrying...(%d)", errno);
737                         _vconf_acquire_transaction_delay(50);
738                         goto transaction_retry;
739                 } else {
740                         is_transaction++;
741                 }
742         } else {
743                 is_transaction++;
744         }
745
746         return VCONF_OK;
747 }
748
749 static int _vconf_db_commit_transaction()
750 {
751         pid_t value;
752         VCONF_MOUNT_PATH_CHECK;
753
754         retv_if(is_transaction <= 0, VCONF_ERROR);
755
756         if(is_transaction == 1) {
757                 value = getpid();
758 transaction_retry:
759                 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_stop", &value, sizeof(value), 0) == -1)
760                 {
761                         //ERR("setxattr failed. retrying...(%d)", errno);
762                         _vconf_acquire_transaction_delay(50);
763                         goto transaction_retry;
764                 } else {
765                         is_transaction = 0;
766                 }
767         } else {
768                 is_transaction--;
769         }
770
771         return 0;
772 }
773
774 static int _vconf_db_rollback_transaction()
775 {
776         pid_t value;
777         VCONF_MOUNT_PATH_CHECK;
778
779         retv_if(is_transaction <= 0, VCONF_ERROR);
780
781         if(is_transaction == 1) {
782                 value = getpid();
783 transaction_retry:
784                 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_rb", &value, sizeof(value), 0) == -1)
785                 {
786                         //ERR("setxattr failed. retrying...(%d)", errno);
787                         _vconf_acquire_transaction_delay(50);
788                         goto transaction_retry;
789                 } else {
790                         is_transaction = 0;
791                 }
792         } else {
793                 is_transaction --;
794         }
795
796         return 0;
797 }
798 #endif //VCONF_USE_SQLFS_TRANSACTION
799
800 #ifdef VCONF_USE_BACKUP_TRANSACTION
801
802 static int _vconf_backup_check(char* vconf_path, char* backup_path)
803 {
804         int ret = VCONF_OK;
805         int vconf_fd = -1;
806         int backup_fd = -1;
807         char file_buf[BUF_LEN] = { 0, };
808         char err_buf[100] = { 0, };
809         int complete_mark = 0;
810         int read_len;
811         int err_no = 0;
812         int is_recovered = 0;
813         int file_size;
814
815         if (access(vconf_path, F_OK) == -1 || access(backup_path, F_OK) == -1)
816                 return ret;
817
818         vconf_fd = open(vconf_path, O_WRONLY);
819         if (vconf_fd == -1) {
820                 ERR("open %s failed", vconf_path);
821                 ret = VCONF_ERROR_FILE_OPEN;
822                 err_no = errno;
823                 goto out_close;
824         }
825
826         if(_vconf_set_write_lock(vconf_fd) == -1) {
827                 ERR("set write lock %s failed", vconf_path);
828                 ret = VCONF_ERROR_FILE_LOCK;
829                 err_no = errno;
830                 goto out_close;
831         }
832
833         backup_fd = open(backup_path, O_RDONLY);
834         if (backup_fd == -1) {
835                 ERR("open %s failed", backup_path);
836                 ret = VCONF_ERROR_FILE_OPEN;
837                 err_no = errno;
838                 goto out_unlock;
839         }
840
841         file_size = lseek(backup_fd, 0, SEEK_END);
842         if (file_size == -1) {
843                 ERR("seek end %s failed", backup_path);
844                 ret = VCONF_ERROR_FILE_SEEK;
845                 err_no = errno;
846                 goto out_unlock;
847         } else if (file_size < FILE_ATOMIC_GUARANTEE_SIZE + VCONF_BACKUP_COMP_MARK_SIZE) {
848                 goto out_unlock;
849         }
850
851         if (lseek(backup_fd, 0, SEEK_SET) != 0) {
852                 ERR("seek %s failed", backup_path);
853                 ret = VCONF_ERROR_FILE_SEEK;
854                 err_no = errno;
855                 goto out_unlock;
856         }
857
858         read_len = read(backup_fd, &complete_mark, sizeof(int));
859         if (read_len < sizeof(int))
860                 goto out_unlock;
861
862         if (complete_mark != VCONF_BACKUP_COMPLETE_MARK)
863                 goto out_unlock;
864
865         if (ftruncate(vconf_fd, 0) == -1) {
866                 ERR("truncate %s failed", vconf_path);
867                 ret = VCONF_ERROR_FILE_TRUNCATE;
868                 err_no = errno;
869                 goto out_unlock;
870         }
871
872         while ( (read_len = read(backup_fd, file_buf, BUF_LEN )) >0) {
873                 if(write(vconf_fd, file_buf, read_len) != read_len) {
874                         ERR("write %s failed", backup_path);
875                         ret = VCONF_ERROR_FILE_WRITE;
876                         err_no = errno;
877                         goto out_unlock;
878                 }
879         }
880
881         is_recovered = 1;
882
883 out_unlock :
884         if(_vconf_set_unlock(vconf_fd)==-1) {
885                 ERR("unset write lock %s failed", vconf_path);
886                 ret = VCONF_ERROR_FILE_LOCK;
887                 err_no = errno;
888                 goto out_close;
889         }
890
891 out_close:
892         if (vconf_fd != -1)
893                 close(vconf_fd);
894         if(backup_fd != -1)
895                 close(backup_fd);
896
897         if(ret == VCONF_OK) {
898                 if(remove(backup_path) == -1) {
899                         ret = VCONF_ERROR_FILE_REMOVE;
900                         err_no = errno;
901                 }
902         }
903
904         if(ret != VCONF_OK) {
905                 strerror_r(err_no, err_buf, 100);
906                 ERR("_vconf_backup_check failed %d (%d / %s)\n", ret, err_no, err_buf);
907         } else if (is_recovered)
908                 WARN("vconf(%s) successfully recovered and backup file is removed", vconf_path, backup_path);
909         else
910                 WARN("vconf(%s)'s non-complete backup file is removed", vconf_path, backup_path);
911
912         return ret;
913 }
914
915 static int _vconf_backup_write_str(char* backup_path, char* value)
916 {
917         int ret = VCONF_OK;
918         char err_buf[100] = { 0, };
919         int err_no = 0;
920         int backup_fd = -1;
921         int write_len = 0;
922         int complete_mark = VCONF_BACKUP_COMPLETE_MARK;
923         int empty_mark = 0;
924         int vconf_type_str = VCONF_TYPE_STRING;
925         int result;
926
927         if( (backup_fd = open(backup_path, O_CREAT|O_EXCL|O_WRONLY, 0666)) == -1 ) {
928                 ERR("open %s failed", backup_path);
929                 ret = VCONF_ERROR_FILE_OPEN;
930                 err_no = errno;
931                 goto out_close;
932         }
933
934         if ((result = write(backup_fd, (void *)&empty_mark, sizeof(int))) != sizeof(int)) {
935                 ERR("write empty mark of %s failed %d", backup_path, result);
936                 ret = VCONF_ERROR_FILE_WRITE;
937                 err_no = errno;
938                 goto out_close;
939         }
940
941         if ((result = write(backup_fd, (void *)&vconf_type_str, sizeof(int))) != sizeof(int)) {
942                 ERR("write type of %s failed %d", backup_path, result);
943                 ret = VCONF_ERROR_FILE_WRITE;
944                 err_no = errno;
945                 goto out_close;
946         }
947
948         write_len = strlen(value);
949         if((result = write(backup_fd, value, write_len)) != write_len) {
950                 ERR("write %s failed %d", backup_path, result);
951                 ret = VCONF_ERROR_FILE_WRITE;
952                 err_no = errno;
953                 goto out_close;
954
955         }
956
957         if (fdatasync(backup_fd) == -1) {
958                 ERR("sync %s failed", backup_path);
959                 ret = VCONF_ERROR_FILE_SYNC;
960                 err_no = errno;
961                 goto out_close;
962         }
963
964         if (lseek(backup_fd, 0, SEEK_SET) != 0) {
965                 ERR("seek %s failed", backup_path);
966                 ret = VCONF_ERROR_FILE_SEEK;
967                 err_no = errno;
968                 goto out_close;
969         }
970
971         if((result = write(backup_fd, (void *)&complete_mark, sizeof(int))) != sizeof(int)) {
972                 ERR("write complete mark of %s failed %d", backup_path, result);
973                 ret = VCONF_ERROR_FILE_WRITE;
974                 err_no = errno;
975                 goto out_close;
976         }
977
978         if (fdatasync(backup_fd) == -1) {
979                 ERR("sync %s failed", backup_path);
980                 ret = VCONF_ERROR_FILE_SYNC;
981                 err_no = errno;
982                 goto out_close;
983         }
984
985 out_close:
986         if(backup_fd != -1)
987                 close(backup_fd);
988
989         if(ret != VCONF_OK) {
990                 strerror_r(err_no, err_buf, 100);
991                 ERR("_vconf_backup_write_str failed %d (%d / %s)\n", ret, err_no, err_buf);
992         }
993
994         return ret;
995
996 }
997
998 static int _vconf_backup_commit(char* backup_path)
999 {
1000         int ret = VCONF_OK;
1001         char err_buf[100] = { 0, };
1002         int err_no = 0;
1003
1004         if(remove(backup_path) == -1) {
1005                 ERR("remove %s failed", backup_path);
1006                 ret = VCONF_ERROR_FILE_REMOVE;
1007                 err_no = errno;
1008         }
1009
1010         if(ret != VCONF_OK) {
1011                 strerror_r(err_no, err_buf, 100);
1012                 ERR("_vconf_backup_commit failed %d (%d / %s)\n", ret, err_no, err_buf);
1013         }
1014
1015         return ret;
1016
1017 }
1018 #endif // VCONF_USE_BACKUP_TRANSACTION
1019
1020 static int _vconf_set_key_filesys(keynode_t *keynode, int prefix)
1021 {
1022         char path[VCONF_KEY_PATH_LEN] = {0,};
1023         FILE *fp = NULL;
1024         int ret = -1;
1025         int func_ret = VCONF_OK;
1026         int err_no = 0;
1027         char err_buf[100] = { 0, };
1028         int is_write_error = 0;
1029 #ifdef VCONF_USE_BACKUP_TRANSACTION
1030         char backup_path[VCONF_KEY_PATH_LEN] = {0,};
1031         int is_backup_need = 0;
1032         int file_size = 0;
1033 #endif
1034
1035         errno = 0;
1036
1037         ret = _vconf_get_key_path(keynode->keyname, path);
1038         retv_if(ret != VCONF_OK, ret);
1039
1040         if(prefix == VCONF_BACKEND_MEMORY && VCONF_NOT_INITIALIZED) {
1041                 func_ret = VCONF_ERROR_NOT_INITIALIZED;
1042                 goto out_return;
1043         }
1044
1045 #ifdef VCONF_USE_BACKUP_TRANSACTION
1046         if(prefix == VCONF_BACKEND_DB && keynode->type == VCONF_TYPE_STRING) {
1047                 _vconf_get_backup_path(keynode->keyname, backup_path);
1048                 ret = _vconf_backup_check(path, backup_path);
1049                 if(ret != VCONF_OK) {
1050                         func_ret = ret;
1051                         err_no = errno;
1052                         goto out_return;
1053                 }
1054         }
1055 #endif
1056
1057         if( (fp = fopen(path, "r+")) == NULL ) {
1058                 func_ret = VCONF_ERROR_FILE_OPEN;
1059                 err_no = errno;
1060                 goto out_return;
1061         }
1062
1063 #ifdef VCONF_USE_SQLFS_TRANSACTION
1064         if (prefix != VCONF_BACKEND_DB)
1065 #endif
1066         {
1067                 ret = _vconf_set_write_lock(fileno(fp));
1068                 if(ret == -1) {
1069                         func_ret = VCONF_ERROR_FILE_LOCK;
1070                         err_no = errno;
1071                         goto out_close;
1072                 }
1073         }
1074
1075 #ifdef VCONF_USE_BACKUP_TRANSACTION
1076         if(prefix == VCONF_BACKEND_DB && keynode->type == VCONF_TYPE_STRING) {
1077                 file_size = VCONF_TYPE_SIZE + strlen(keynode->value.s);
1078                 if (file_size > FILE_ATOMIC_GUARANTEE_SIZE) {
1079                         is_backup_need = 1;
1080
1081                         ret = _vconf_backup_write_str(backup_path, keynode->value.s);
1082                         if(ret != VCONF_OK) {
1083                                 func_ret = ret;
1084                                 err_no = errno;
1085                                 goto out_unlock;
1086                         } else
1087                                 WARN("vconf backup file for(%s) is created. file size(%d)", path, file_size);
1088                 }
1089         }
1090 #endif
1091
1092         if (ftruncate(fileno(fp), 0) == -1) {
1093                 func_ret = VCONF_ERROR_FILE_TRUNCATE;
1094                 err_no = errno;
1095                 goto out_unlock;
1096         }
1097
1098         /* write key type */
1099         ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
1100         if(ret <= 0)
1101         {
1102                 if(errno) {
1103                         err_no = errno;
1104                 } else {
1105                         errno = EAGAIN;
1106                 }
1107                 func_ret = VCONF_ERROR_FILE_WRITE;
1108                 goto out_unlock;
1109         }
1110
1111         /* write key value */
1112         switch(keynode->type)
1113         {
1114                 case VCONF_TYPE_INT:
1115                         ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
1116                         if(ret <= 0) is_write_error = 1;
1117                         break;
1118                 case VCONF_TYPE_DOUBLE:
1119                         ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
1120                         if(ret <= 0) is_write_error = 1;
1121                         break;
1122                 case VCONF_TYPE_BOOL:
1123                         ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
1124                         if(ret <= 0) is_write_error = 1;
1125                         break;
1126                 case VCONF_TYPE_STRING:
1127                         ret = fprintf(fp,"%s",keynode->value.s);
1128                         if(ret < strlen(keynode->value.s)) is_write_error = 1;
1129                         //ret = fwrite((void *)keynode->value.s, sizeof(char), strlen(keynode->value.s), fp);
1130                         break;
1131                 default :
1132                         func_ret = VCONF_ERROR_WRONG_TYPE;
1133                         goto out_unlock;
1134         }
1135         if(is_write_error)
1136         {
1137                 if(errno) {
1138                         err_no = errno;
1139                 } else {
1140                         errno = EAGAIN;
1141                 }
1142                 func_ret = VCONF_ERROR_FILE_WRITE;
1143                 goto out_unlock;
1144         }
1145
1146 #ifdef VCONF_USE_SQLFS_TRANSACTION
1147         if(prefix == VCONF_BACKEND_FILE)
1148 #else
1149         if(prefix == VCONF_BACKEND_FILE || prefix == VCONF_BACKEND_DB)
1150 #endif
1151         {
1152                 fflush(fp);
1153
1154                 ret = fdatasync(fileno(fp));
1155                 if(ret == -1) {
1156                         err_no = errno;
1157                         func_ret = VCONF_ERROR_FILE_SYNC;
1158                 }
1159         }
1160
1161 #ifdef VCONF_USE_BACKUP_TRANSACTION
1162         if (is_backup_need) {
1163                 ret = _vconf_backup_commit(backup_path);
1164                 if(ret != VCONF_OK) {
1165                         func_ret = ret;
1166                         err_no = errno;
1167                         goto out_unlock;
1168                 }
1169         }
1170 #endif
1171
1172 out_unlock :
1173 #ifdef VCONF_USE_SQLFS_TRANSACTION
1174         if (prefix != VCONF_BACKEND_DB)
1175 #endif
1176         {
1177                 ret = _vconf_set_unlock(fileno(fp));
1178                 if(ret == -1) {
1179                         func_ret = VCONF_ERROR_FILE_LOCK;
1180                         err_no = errno;
1181                         goto out_close;
1182                 }
1183         }
1184 out_close :
1185         fclose(fp);
1186
1187 out_return :
1188         if(err_no != 0) {
1189                 strerror_r(err_no, err_buf, 100);
1190                 ERR("_vconf_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
1191         }
1192
1193         return func_ret;
1194 }
1195
1196 static int _vconf_set_key(keynode_t *keynode)
1197 {
1198         int func_ret = VCONF_OK;
1199         int ret = 0;
1200         int is_busy_err = 0;
1201         int retry = -1;
1202         int prefix = 0;
1203         int rc = 0;
1204
1205         ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
1206         retv_if(ret != VCONF_OK, ret);
1207
1208 #ifdef VCONF_USE_SQLFS_TRANSACTION
1209         if(prefix == VCONF_BACKEND_DB) {
1210                 _vconf_db_begin_transaction();
1211         }
1212 #endif
1213
1214         while((ret = _vconf_set_key_filesys(keynode, prefix)) != VCONF_OK)
1215         {
1216                 is_busy_err = 0;
1217                 retry++;
1218
1219                 if(VCONF_NOT_INITIALIZED)
1220                 {
1221                         ERR("%s : vconf is not initialized\n", keynode->keyname);
1222                         is_busy_err = 1;
1223                 }
1224                 else if(ret == VCONF_ERROR_FILE_OPEN)
1225                 {
1226                         switch (errno)
1227                         {
1228                                 /* file is not exist, make path */
1229 #ifndef DISABLE_RUNTIME_KEY_CREATION
1230                                 case EFAULT :
1231                                 case ENOENT :
1232                                 {
1233                                         char path[VCONF_KEY_PATH_LEN] = {0,};
1234                                         rc = _vconf_get_key_path(keynode->keyname, path);
1235                                         if(rc != VCONF_OK) {
1236                                                 ERR("_vconf_get_key_path error");
1237                                                 break;
1238                                         }
1239
1240                                         rc = _vconf_set_key_check_parent_dir(path);
1241                                         if(rc != VCONF_OK) {
1242                                                 ERR("_vconf_set_key_check_parent_dir error : %s", path);
1243                                                 break;
1244                                         }
1245
1246                                         rc = _vconf_set_key_creation(path);
1247                                         if(rc != VCONF_OK) {
1248                                                 ERR("_vconf_set_key_creation error : %s", path);
1249                                                 break;
1250                                         }
1251                                         INFO("%s key is created", keynode->keyname);
1252                                 }
1253 #endif
1254                                 case EAGAIN :
1255                                 case EMFILE :
1256                                 case ENFILE :
1257                                 case ETXTBSY :
1258                                 {
1259                                         is_busy_err = 1;
1260                                 }
1261                         }
1262                 }
1263                 else if (ret == VCONF_ERROR_FILE_CHMOD)
1264                 {
1265                         switch (errno)
1266                         {
1267                                 case EINTR :
1268                                 case EBADF :
1269                                 {
1270                                         is_busy_err = 1;
1271                                 }
1272                         }
1273                 }
1274                 else if (ret == VCONF_ERROR_FILE_LOCK)
1275                 {
1276                         switch (errno)
1277                         {
1278                                 case EBADF :
1279                                 case EACCES :
1280                                 case EAGAIN :
1281                                 case ENOLCK :
1282                                 {
1283                                         is_busy_err = 1;
1284                                 }
1285                         }
1286                 }
1287                 else if (ret == VCONF_ERROR_FILE_WRITE)
1288                 {
1289                         switch (errno)
1290                         {
1291                                 case 0 :
1292                                 case EAGAIN :
1293                                 case EINTR :
1294                                 case EIO :
1295                                 case ENOMEM :
1296                                 {
1297                                         is_busy_err = 1;
1298                                 }
1299                         }
1300                 }
1301                 else
1302                 {
1303                         is_busy_err = 0;
1304                 }
1305
1306                 if ((is_busy_err == 1) && (retry < VCONF_ERROR_RETRY_CNT)) {
1307                         ERR("%s : write buf error(%d). write will be retried(%d) , usleep time : %d\n", keynode->keyname, ret, retry, (retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
1308                         usleep((retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
1309                         continue;
1310                 } else {
1311                         ERR("%s : write buf error(%d). break. (%d)\n", keynode->keyname, ret, retry);
1312                         func_ret = VCONF_ERROR;
1313                         break;
1314                 }
1315         }
1316
1317 #ifdef VCONF_USE_SQLFS_TRANSACTION
1318         if(prefix == VCONF_BACKEND_DB) {
1319                 if(func_ret == VCONF_ERROR) {
1320                         _vconf_db_rollback_transaction();
1321                 } else {
1322                         _vconf_db_commit_transaction();
1323                 }
1324         }
1325 #endif
1326
1327         return func_ret;
1328 }
1329
1330 /*
1331  * This function set the value of given keys
1332  * @param[in] keylist the keylist which should contain changed keys
1333  * @return 0 on success, -1 on error
1334  */
1335 API int vconf_set(keylist_t *keylist)
1336 {
1337         START_TIME_CHECK
1338
1339         keynode_t *got_node;
1340
1341         int func_ret = VCONF_OK;
1342         int ret = 0;
1343         int prefix = 0;
1344
1345         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
1346
1347         INFO("vconf_set (%d)START", keylist->num);
1348
1349         got_node = _vconf_keylist_headnode(keylist);
1350
1351         retvm_if(got_node == NULL, VCONF_ERROR, "Invalid argument: headnode is NULL");
1352
1353         ret = _vconf_get_key_prefix(got_node->keyname, &prefix);
1354         retv_if(ret != VCONF_OK, ret);
1355
1356 #ifdef VCONF_USE_SQLFS_TRANSACTION
1357         if(prefix == VCONF_BACKEND_DB) {
1358                 _vconf_db_begin_transaction();
1359         }
1360 #endif
1361
1362         while (got_node != NULL) {
1363                 ret = _vconf_set_key(got_node);
1364                 if(ret != VCONF_OK) {
1365                         func_ret = VCONF_ERROR;
1366                 }
1367
1368                 got_node = _vconf_keynode_next(got_node);
1369         }
1370
1371 #ifdef VCONF_USE_SQLFS_TRANSACTION
1372         if(prefix == VCONF_BACKEND_DB) {
1373                 if(func_ret == VCONF_ERROR) {
1374                         _vconf_db_rollback_transaction();
1375                 } else {
1376                         _vconf_db_commit_transaction();
1377                 }
1378         }
1379 #endif
1380
1381         END_TIME_CHECK
1382
1383         return func_ret;
1384 }
1385
1386 API int vconf_sync_key(const char *in_key)
1387 {
1388         START_TIME_CHECK
1389
1390         int fd;
1391         char path[VCONF_KEY_PATH_LEN] = {0,};
1392         int ret = -1;
1393
1394         ret = _vconf_get_key_path(in_key, path);
1395         if(ret != VCONF_OK) return VCONF_ERROR;
1396
1397         fd = open(path, O_RDWR);
1398         if(fd == -1) return VCONF_ERROR;
1399
1400         fsync(fd);
1401         close(fd);
1402
1403         END_TIME_CHECK
1404
1405         return 0;
1406 }
1407
1408 /*
1409  * This function set the integer value of given key
1410  * @param[in]   in_key  key
1411  * @param[in]   intval integer value to set
1412  * @return 0 on success, -1 on error
1413  */
1414 API int vconf_set_int(const char *in_key, const int intval)
1415 {
1416         START_TIME_CHECK
1417
1418         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1419
1420         int func_ret = VCONF_OK;
1421
1422         keynode_t* pKeyNode = _vconf_keynode_new();
1423         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
1424
1425         func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
1426         if(func_ret != VCONF_OK) {
1427                 _vconf_keynode_free(pKeyNode);
1428                 ERR("set key name error");
1429                 return VCONF_ERROR;
1430         }
1431         _vconf_keynode_set_value_int(pKeyNode, intval);
1432
1433         if (_vconf_set_key(pKeyNode) != VCONF_OK) {
1434                 ERR("vconf_set_int(%d) : %s(%d) error", getpid(), in_key, intval);
1435                 func_ret = VCONF_ERROR;
1436         } else{
1437                 INFO("vconf_set_int(%d) : %s(%d) success", getpid(), in_key, intval);
1438         }
1439
1440         _vconf_keynode_free(pKeyNode);
1441
1442         END_TIME_CHECK
1443
1444         return func_ret;
1445 }
1446
1447 /*
1448 * This function set the boolean value of given key
1449 * @param[in]    in_key  key
1450 * @param[in]    boolval boolean value to set
1451                 (Integer value 1 is 'True', and 0 is 'False')
1452 * @return 0 on success, -1 on error
1453 */
1454 API int vconf_set_bool(const char *in_key, const int boolval)
1455 {
1456         START_TIME_CHECK
1457
1458         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1459
1460         int func_ret = VCONF_OK;
1461         keynode_t* pKeyNode = _vconf_keynode_new();
1462         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
1463
1464         func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
1465         if(func_ret != VCONF_OK) {
1466                 _vconf_keynode_free(pKeyNode);
1467                 ERR("set key name error");
1468                 return VCONF_ERROR;
1469         }
1470         _vconf_keynode_set_value_bool(pKeyNode, boolval);
1471
1472         if (_vconf_set_key(pKeyNode) != VCONF_OK) {
1473                 ERR("vconf_set_bool(%d) : %s(%d) error", getpid(), in_key, boolval);
1474                 func_ret = VCONF_ERROR;
1475         } else {
1476                 INFO("vconf_set_bool(%d) : %s(%d) success", getpid(), in_key, boolval);
1477         }
1478
1479         _vconf_keynode_free(pKeyNode);
1480
1481         END_TIME_CHECK
1482
1483         return func_ret;
1484 }
1485
1486 /*
1487  * This function set the double value of given key
1488  * @param[in]   in_key  key
1489  * @param[in]   dblval double value to set
1490  * @return 0 on success, -1 on error
1491  */
1492 API int vconf_set_dbl(const char *in_key, const double dblval)
1493 {
1494         START_TIME_CHECK
1495
1496         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1497
1498         int func_ret = VCONF_OK;
1499         keynode_t* pKeyNode = _vconf_keynode_new();
1500         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
1501
1502         func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
1503         if(func_ret != VCONF_OK) {
1504                 _vconf_keynode_free(pKeyNode);
1505                 ERR("set key name error");
1506                 return VCONF_ERROR;
1507         }
1508         _vconf_keynode_set_value_dbl(pKeyNode, dblval);
1509
1510         if (_vconf_set_key(pKeyNode) != VCONF_OK) {
1511                 ERR("vconf_set_dbl(%d) : %s(%f) error", getpid(), in_key, dblval);
1512                 func_ret = VCONF_ERROR;
1513         } else {
1514                 INFO("vconf_set_dbl(%d) : %s(%f) success", getpid(), in_key, dblval);
1515         }
1516
1517         _vconf_keynode_free(pKeyNode);
1518
1519         END_TIME_CHECK
1520
1521         return func_ret;
1522 }
1523
1524 /*
1525  * This function set the string value of given key
1526  * @param[in]   in_key  key
1527  * @param[in]   strval string value to set
1528  * @return 0 on success, -1 on error
1529  */
1530 API int vconf_set_str(const char *in_key, const char *strval)
1531 {
1532         START_TIME_CHECK
1533
1534         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1535         retvm_if(strval == NULL, VCONF_ERROR, "Invalid argument: value is NULL");
1536
1537         int func_ret = VCONF_OK;
1538         keynode_t* pKeyNode = _vconf_keynode_new();
1539         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
1540
1541         func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
1542         if(func_ret != VCONF_OK) {
1543                 _vconf_keynode_free(pKeyNode);
1544                 ERR("set key name error");
1545                 return VCONF_ERROR;
1546         }
1547         _vconf_keynode_set_value_str(pKeyNode, strval);
1548
1549         if (_vconf_set_key(pKeyNode) != VCONF_OK) {
1550                 ERR("vconf_set_str(%d) : %s(%s) error", getpid(), in_key, strval);
1551                 func_ret = VCONF_ERROR;
1552         } else {
1553                 INFO("vconf_set_str(%d) : %s(%s) success", getpid(), in_key, strval);
1554         }
1555
1556         _vconf_keynode_free(pKeyNode);
1557
1558         END_TIME_CHECK
1559
1560         return func_ret;
1561 }
1562
1563
1564 #ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
1565 /* keyFileUnserialize function of ELEKTRA */
1566 static int _vconf_get_key_elektra_format(keynode_t *keynode, FILE *fp)
1567 {
1568         char version[10] = {0,};
1569         char type[5] = {0,};
1570         char comment[8] = {0,};
1571         char file_buf[BUF_LEN] = {0,};
1572         char *value = NULL;
1573         int value_size = 0;
1574         int err_no = 0;
1575         char err_buf[100] = { 0, };
1576         int func_ret = VCONF_OK;
1577         char tmp;
1578
1579         INFO("_vconf_get_key_elektra_format start");
1580
1581         rewind(fp);
1582
1583         if (!fgets(version, sizeof(version), fp))
1584         {
1585                 if(ferror(fp)) {
1586                         err_no = errno;
1587                 } else {
1588                         err_no = EAGAIN;
1589                 }
1590                 func_ret = VCONF_ERROR_FILE_FGETS;
1591                 goto out_return;
1592         }
1593         if (strncmp(version,"RG",2)) {
1594                 func_ret = VCONF_ERROR_WRONG_TYPE;
1595                 goto out_return;
1596         }
1597
1598         if (!fgets(type, sizeof(type), fp))
1599         {
1600                 if(ferror(fp)) {
1601                         err_no = errno;
1602                 } else {
1603                         err_no = EAGAIN;
1604                 }
1605                 func_ret = VCONF_ERROR_FILE_FGETS;
1606                 goto out_return;
1607         }
1608
1609         if (!fgets(comment, sizeof(comment), fp))
1610         {
1611                 if(ferror(fp)) {
1612                         err_no = errno;
1613                 } else {
1614                         err_no = EAGAIN;
1615                 }
1616                 func_ret = VCONF_ERROR_FILE_FGETS;
1617                 goto out_return;
1618         }
1619
1620         while(fgets(file_buf, sizeof(file_buf), fp))
1621         {
1622                 if(value) {
1623                         value_size = value_size + strlen(file_buf);
1624                         tmp = (char *) realloc(value, value_size);
1625                         if(!tmp) {
1626                                 free(value);
1627                                 func_ret = VCONF_ERROR_NO_MEM;
1628                                 break;
1629                         }
1630                         value = tmp;
1631                         strncat(value, file_buf, strlen(file_buf));
1632                 } else {
1633                         value_size = strlen(file_buf) + 1;
1634                         value = (char *)malloc(value_size);
1635                         if(value == NULL) {
1636                                 func_ret = VCONF_ERROR_NO_MEM;
1637                                 break;
1638                         }
1639                         memset(value, 0x00, value_size);
1640                         strncpy(value, file_buf, strlen(file_buf));
1641                 }
1642         }
1643
1644         if(ferror(fp)) {
1645                 err_no = errno;
1646                 func_ret = VCONF_ERROR_FILE_FGETS;
1647         } else {
1648                 if(value) {
1649                         switch(atoi(type))
1650                         {
1651                                 case VCONF_TYPE_INT:
1652                                 {
1653                                         _vconf_keynode_set_value_int(keynode, atoi(value));
1654                                         break;
1655                                 }
1656                                 case VCONF_TYPE_DOUBLE:
1657                                 {
1658                                         _vconf_keynode_set_value_dbl(keynode, atof(value));
1659                                         break;
1660                                 }
1661                                 case VCONF_TYPE_BOOL:
1662                                 {
1663                                         _vconf_keynode_set_value_bool(keynode, atoi(value));
1664                                         break;
1665                                 }
1666                                 case VCONF_TYPE_STRING:
1667                                 {
1668                                         _vconf_keynode_set_value_str(keynode, value);
1669                                         break;
1670                                 }
1671                                 default :
1672                                 {
1673                                         func_ret = VCONF_ERROR_WRONG_VALUE;
1674                                 }
1675                         }
1676                 } else {
1677                         if(atoi(type) == VCONF_TYPE_STRING) {
1678                                 _vconf_keynode_set_value_str(keynode, "");
1679                         } else {
1680                                 func_ret = VCONF_ERROR_WRONG_VALUE;
1681                         }
1682                 }
1683         }
1684
1685 out_return :
1686         if(err_no != 0) {
1687                 strerror_r(err_no, err_buf, 100);
1688                 ERR("_vconf_set_key_filesys(%d/%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
1689         }
1690
1691         if(value) free(value);
1692
1693         return func_ret;
1694 }
1695 #endif
1696
1697 static int _vconf_get_key_filesys(keynode_t *keynode, int prefix)
1698 {
1699         char path[VCONF_KEY_PATH_LEN] = {0,};
1700         int ret = -1;
1701         int func_ret = VCONF_OK;
1702         char err_buf[100] = { 0, };
1703         int err_no = 0;
1704         int type = 0;
1705         FILE *fp = NULL;
1706 #ifdef VCONF_USE_BACKUP_TRANSACTION
1707         char backup_path[VCONF_KEY_PATH_LEN] = {0,};
1708 #endif
1709
1710         errno = 0;
1711
1712         ret = _vconf_get_key_path(keynode->keyname, path);
1713         retv_if(ret != VCONF_OK, ret);
1714
1715         if(prefix == VCONF_BACKEND_MEMORY && VCONF_NOT_INITIALIZED)
1716         {
1717                 func_ret = VCONF_ERROR_NOT_INITIALIZED;
1718                 goto out_return;
1719         }
1720
1721 #ifdef VCONF_USE_BACKUP_TRANSACTION
1722         if(prefix == VCONF_BACKEND_DB) {
1723                 _vconf_get_backup_path(keynode->keyname, backup_path);
1724                 ret = _vconf_backup_check(path, backup_path);
1725                 if(ret != VCONF_OK) {
1726                         func_ret = ret;
1727                         err_no = errno;
1728                         goto out_return;
1729                 }
1730         }
1731 #endif
1732
1733         if( (fp = fopen(path, "r")) == NULL ) {
1734                 func_ret = VCONF_ERROR_FILE_OPEN;
1735                 err_no = errno;
1736                 goto out_return;
1737         }
1738
1739 #ifdef VCONF_USE_SQLFS_TRANSACTION
1740         if (prefix != VCONF_BACKEND_DB)
1741 #endif
1742         {
1743                 ret = _vconf_set_read_lock(fileno(fp));
1744                 if(ret == -1) {
1745                         func_ret = VCONF_ERROR_FILE_LOCK;
1746                         err_no = errno;
1747                         goto out_close;
1748                 }
1749         }
1750
1751         /* read data type */
1752         if(!fread((void*)&type, sizeof(int), 1, fp)) {
1753                 if(ferror(fp)) {
1754                         err_no = errno;
1755                 } else {
1756                         errno = EAGAIN;
1757                 }
1758                 func_ret = VCONF_ERROR_FILE_FREAD;
1759                 goto out_unlock;
1760         }
1761
1762         /* read data value */
1763         switch(type)
1764         {
1765                 case VCONF_TYPE_INT:
1766                 {
1767                         int value_int = 0;
1768                         if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
1769                                 if(ferror(fp)) {
1770                                         err_no = errno;
1771                                 } else {
1772                                         errno = EAGAIN;
1773                                 }
1774                                 func_ret = VCONF_ERROR_FILE_FREAD;
1775                                 goto out_unlock;
1776                         } else {
1777                                 _vconf_keynode_set_value_int(keynode, value_int);
1778                         }
1779
1780                         break;
1781                 }
1782                 case VCONF_TYPE_DOUBLE:
1783                 {
1784                         double value_dbl = 0;
1785                         if(!fread((void*)&value_dbl, sizeof(double), 1, fp)) {
1786                                 if(ferror(fp)) {
1787                                         err_no = errno;
1788                                 } else {
1789                                         errno = EAGAIN;
1790                                 }
1791                                 func_ret = VCONF_ERROR_FILE_FREAD;
1792                                 goto out_unlock;
1793                         } else {
1794                                 _vconf_keynode_set_value_dbl(keynode, value_dbl);
1795                         }
1796
1797                         break;
1798                 }
1799                 case VCONF_TYPE_BOOL:
1800                 {
1801                         int value_int = 0;
1802                         if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
1803                                 if(ferror(fp)) {
1804                                         err_no = errno;
1805                                 } else {
1806                                         errno = EAGAIN;
1807                                 }
1808                                 func_ret = VCONF_ERROR_FILE_FREAD;
1809                                 goto out_unlock;
1810                         } else {
1811                                 _vconf_keynode_set_value_bool(keynode, value_int);
1812                         }
1813
1814                         break;
1815                 }
1816                 case VCONF_TYPE_STRING:
1817                 {
1818                         char file_buf[BUF_LEN] = {0,};
1819                         char *value = NULL;
1820                         int value_size = 0;
1821
1822                         while(fgets(file_buf, sizeof(file_buf), fp))
1823                         {
1824                                 if(value) {
1825                                         value_size = value_size + strlen(file_buf);
1826                                         value = (char *) realloc(value, value_size);
1827                                         if(value == NULL) {
1828                                                 func_ret = VCONF_ERROR_NO_MEM;
1829                                                 break;
1830                                         }
1831                                         strncat(value, file_buf, strlen(file_buf));
1832                                 } else {
1833                                         value_size = strlen(file_buf) + 1;
1834                                         value = (char *)malloc(value_size);
1835                                         if(value == NULL) {
1836                                                 func_ret = VCONF_ERROR_NO_MEM;
1837                                                 break;
1838                                         }
1839                                         memset(value, 0x00, value_size);
1840                                         strncpy(value, file_buf, strlen(file_buf));
1841                                 }
1842                         }
1843
1844                         if(ferror(fp)) {
1845                                 err_no = errno;
1846                                 func_ret = VCONF_ERROR_FILE_FGETS;
1847                         } else {
1848                                 if(value) {
1849                                         _vconf_keynode_set_value_str(keynode, value);
1850                                 } else {
1851                                         _vconf_keynode_set_value_str(keynode, "");
1852                                 }
1853                         }
1854                         if(value)
1855                                 free(value);
1856
1857                         break;
1858                 }
1859                 default :
1860 #ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
1861                         func_ret = _vconf_get_key_elektra_format(keynode, fp);
1862 #else
1863                         func_ret = VCONF_ERROR_WRONG_TYPE;
1864 #endif
1865         }
1866
1867 out_unlock :
1868 #ifdef VCONF_USE_SQLFS_TRANSACTION
1869         if (prefix != VCONF_BACKEND_DB)
1870 #endif
1871         {
1872                 ret = _vconf_set_unlock(fileno(fp));
1873                 if(ret == -1) {
1874                         func_ret = VCONF_ERROR_FILE_LOCK;
1875                         err_no = errno;
1876                         goto out_close;
1877                 }
1878         }
1879
1880 out_close :
1881         fclose(fp);
1882
1883 out_return :
1884         if(err_no != 0) {
1885                 strerror_r(err_no, err_buf, 100);
1886                 ERR("_vconf_get_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
1887         }
1888
1889         return func_ret;
1890 }
1891
1892
1893 int _vconf_get_key(keynode_t *keynode)
1894 {
1895         int func_ret = VCONF_OK;
1896         int ret = 0;
1897         int is_busy_err = 0;
1898         int retry = -1;
1899         int prefix = 0;
1900
1901         ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
1902         retv_if(ret != VCONF_OK, ret);
1903
1904 #ifdef VCONF_USE_SQLFS_TRANSACTION
1905         if(prefix == VCONF_BACKEND_DB) {
1906                 _vconf_db_begin_transaction();
1907         }
1908 #endif
1909
1910         while((ret = _vconf_get_key_filesys(keynode, prefix)) != VCONF_OK)
1911         {
1912                 is_busy_err = 0;
1913                 retry++;
1914
1915                 if(VCONF_NOT_INITIALIZED)
1916                 {
1917                         ERR("%s : vconf is not initialized\n", keynode->keyname);
1918                         is_busy_err = 1;
1919                 }
1920                 else if(ret == VCONF_ERROR_FILE_OPEN)
1921                 {
1922                         switch (errno)
1923                         {
1924                                 case EAGAIN :
1925                                 case EMFILE :
1926                                 case ETXTBSY :
1927                                 {
1928                                         is_busy_err = 1;
1929                                 }
1930                         }
1931                 }
1932                 else if (ret == VCONF_ERROR_FILE_LOCK)
1933                 {
1934                         switch (errno)
1935                         {
1936                                 case EBADF :
1937                                 case EACCES :
1938                                 case EAGAIN :
1939                                 case ENOLCK :
1940                                 {
1941                                         is_busy_err = 1;
1942                                 }
1943                         }
1944                 }
1945                 else if (ret == VCONF_ERROR_FILE_FREAD)
1946                 {
1947                         switch (errno)
1948                         {
1949                                 case EAGAIN :
1950                                 case EINTR :
1951                                 case EIO :
1952                                 {
1953                                         is_busy_err = 1;
1954                                 }
1955                         }
1956                 }
1957                 else
1958                 {
1959                         is_busy_err = 0;
1960                 }
1961
1962                 if ((is_busy_err == 1) && (retry < VCONF_ERROR_RETRY_CNT)) {
1963                         ERR("%s : read buf error(%d). read will be retried(%d) , %d\n", keynode->keyname, ret, retry, (retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
1964                         usleep((retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
1965                         continue;
1966                 } else {
1967                         ERR("%s : read buf error(%d). break\n",  keynode->keyname, ret);
1968                         func_ret = VCONF_ERROR;
1969                         break;
1970                 }
1971         }
1972
1973 #ifdef VCONF_USE_SQLFS_TRANSACTION
1974         if(prefix == VCONF_BACKEND_DB) {
1975                 if(func_ret == VCONF_ERROR) {
1976                         _vconf_db_rollback_transaction();
1977                 } else {
1978                         _vconf_db_commit_transaction();
1979                 }
1980         }
1981 #endif
1982
1983         return func_ret;
1984 }
1985
1986 /*
1987 static int _vconf_check_value_integrity(const void *value, int type)
1988 {
1989         int i = 0;
1990
1991         if ((type == VCONF_TYPE_STRING) && (value != NULL)) {
1992                 return 0;
1993         }
1994
1995         if ((value) && (strlen(value) > 0)) {
1996                 if ((type == VCONF_TYPE_INT) ||
1997                         (type == VCONF_TYPE_BOOL)||
1998                         (type == VCONF_TYPE_DOUBLE)) {
1999                         while (*(((char *)value) + i) != '\0') {
2000                                 if ( !isdigit(*(((char *)value) + i)) ) {
2001                                         if ((type != VCONF_TYPE_BOOL) &&
2002                                                 (*(((char *)value) + i) != '-')) {
2003                                                 if ((type == VCONF_TYPE_DOUBLE) &&
2004                                                         (*(((char *)value) + i) != '.')) {
2005                                                         ERR("ERROR : vconf value is not digit.");
2006                                                         return -1;
2007                                                 }
2008                                         }
2009                                 }
2010                                 i++;
2011                         }
2012                 }
2013
2014                 return 0;
2015         } else {
2016                 ERR("ERROR : vconf value is NULL.");
2017                 return -2;
2018         }
2019 }
2020 */
2021
2022 int _vconf_path_is_dir(char* path)
2023 {
2024         struct stat entryInfo;
2025
2026         if(lstat(path, &entryInfo) == 0 ) {
2027                 if( S_ISDIR( entryInfo.st_mode ) ) {
2028                         return 1;
2029                 } else {
2030                         return 0;
2031                 }
2032         } else {
2033                 return VCONF_ERROR;
2034         }
2035 }
2036
2037 API int vconf_get(keylist_t *keylist, const char *dirpath, get_option_t option)
2038 {
2039         DIR *dir = NULL;
2040         struct dirent entry;
2041         struct dirent *result = NULL;
2042         char full_file_path[VCONF_KEY_PATH_LEN] = {0,};
2043         char file_path[VCONF_KEY_PATH_LEN] = {0,};
2044         char full_path[VCONF_KEY_PATH_LEN] = {0,};
2045         char err_buf[ERR_LEN] = {0,};
2046         int rc = 0;
2047         int func_ret = 0;
2048         int ret = 0;
2049         int is_dir = 0;
2050         int prefix = 0;
2051
2052         keynode_t *temp_keynode;
2053
2054         retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is null");
2055         retvm_if(dirpath == NULL, VCONF_ERROR, "Invalid argument: dirpath is null");
2056
2057         temp_keynode = _vconf_keylist_headnode(keylist);
2058
2059         if ((NULL != temp_keynode) && (VCONF_GET_KEY != option)) {
2060                 ERR("Not support mode : Only VCONF_GET_KEY \
2061                 option support To retrieve key with keylist");
2062                 return VCONF_ERROR;
2063         }
2064
2065         if(temp_keynode != NULL) {
2066                 while(_vconf_keynode_next(temp_keynode)) {
2067                         temp_keynode = _vconf_keynode_next(temp_keynode);
2068                 }
2069         }
2070
2071         ret = _vconf_get_key_path(dirpath, full_path);
2072         retvm_if(ret != VCONF_OK, ret, "Invalid argument: key is not valid");
2073
2074
2075         ret = _vconf_get_key_prefix(dirpath, &prefix);
2076         retv_if(ret != VCONF_OK, ret);
2077
2078 #ifdef VCONF_USE_SQLFS_TRANSACTION
2079         if(prefix == VCONF_BACKEND_DB) {
2080                 _vconf_db_begin_transaction();
2081         }
2082 #endif
2083
2084         is_dir = _vconf_path_is_dir(full_path);
2085         if(is_dir == 1) {
2086                 if((dir=opendir(full_path)) == NULL) {
2087                         strerror_r(errno, err_buf, ERR_LEN);
2088                         ERR("ERROR : open directory(%s) fail(%s)", dirpath, err_buf);
2089                         func_ret = VCONF_ERROR;
2090                         goto out_unlock;
2091                 }
2092
2093                 if((readdir_r(dir, &entry, &result)) != 0) {
2094                         strerror_r(errno, err_buf, ERR_LEN);
2095                         ERR("ERROR : read directory(%s) fail(%s)", dirpath, err_buf);
2096                         func_ret = VCONF_ERROR;
2097                 }
2098
2099                 while(result != NULL)
2100                 {
2101                         if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
2102                             goto NEXT;
2103                         }
2104
2105                         keynode_t* keynode = _vconf_keynode_new();
2106                         if(keynode == NULL) {
2107                                 closedir(dir);
2108                                 ERR("Invalid argument: key malloc fail");
2109                                 func_ret = VCONF_ERROR;
2110                                 goto out_unlock;
2111                         }
2112
2113                         snprintf(file_path, VCONF_KEY_PATH_LEN, "%s/%s", dirpath, entry.d_name);
2114                         snprintf(full_file_path, VCONF_KEY_PATH_LEN, "%s/%s", full_path, entry.d_name);
2115
2116                         rc = _vconf_path_is_dir(full_file_path);
2117                         if(rc != VCONF_ERROR) {
2118                                 if(rc == 1) {
2119                                         /* directory */
2120                                         if(option == VCONF_GET_KEY) {
2121                                                 _vconf_keynode_free(keynode);
2122                                                 goto NEXT;
2123                                         } else {
2124                                                 _vconf_keynode_set_keyname(keynode, file_path);
2125                                                 _vconf_keynode_set_dir(keynode);
2126                                         }
2127                                 } else {
2128                                         _vconf_keynode_set_keyname(keynode, file_path);
2129                                         _vconf_get_key(keynode);
2130                                 }
2131
2132                                 if (keylist->head && temp_keynode != NULL)
2133                                 {
2134                                         temp_keynode->next = keynode;
2135                                         temp_keynode = _vconf_keynode_next(temp_keynode);
2136                                 }
2137                                 else {
2138                                         keylist->head = keynode;
2139                                         temp_keynode = keylist->head;
2140                                 }
2141                                 keylist->num += 1;
2142                         } else {
2143                                 _vconf_keynode_free(keynode);
2144
2145                                 memset(err_buf, 0x00, sizeof(err_buf));
2146                                 strerror_r(errno, err_buf, sizeof(err_buf));
2147                                 ERR("ERROR : get path(%s) fail(%s)", file_path, err_buf);
2148                                 func_ret = VCONF_ERROR;
2149                         }
2150
2151         NEXT:
2152                         if((readdir_r(dir, &entry, &result)) != 0) {
2153                                 memset(err_buf, 0x00, sizeof(err_buf));
2154                                 strerror_r(errno, err_buf, sizeof(err_buf));
2155                                 ERR("ERROR : read directory(%s) fail(%s)", dirpath, err_buf);
2156                                 func_ret = VCONF_ERROR;
2157                         }
2158                 }
2159
2160                 if((closedir(dir)) != 0) {
2161                         memset(err_buf, 0x00, sizeof(err_buf));
2162                         strerror_r(errno, err_buf, sizeof(err_buf));
2163                         ERR("ERROR : close directory(%s) fail(%s)", dirpath, err_buf);
2164                         func_ret = VCONF_ERROR;
2165                 }
2166         } else if(is_dir == 0) {
2167                 keynode_t* keynode = _vconf_keynode_new();
2168                 retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: key malloc fail");
2169
2170                 _vconf_keynode_set_keyname(keynode, dirpath);
2171
2172                 _vconf_get_key(keynode);
2173
2174                 if (keylist->head && temp_keynode != NULL) {
2175                         temp_keynode->next = keynode;
2176                         //temp_keynode = _vconf_keynode_next(temp_keynode);
2177                 } else {
2178                         keylist->head = keynode;
2179                         temp_keynode = keylist->head;
2180                 }
2181                 keylist->num += 1;
2182         } else {
2183                 func_ret = VCONF_ERROR;
2184                 goto out_unlock;
2185         }
2186         vconf_keylist_rewind(keylist);
2187
2188 out_unlock:
2189 #ifdef VCONF_USE_SQLFS_TRANSACTION
2190         if(prefix == VCONF_BACKEND_DB) {
2191                 if(func_ret == VCONF_ERROR) {
2192                         _vconf_db_rollback_transaction();
2193                 } else {
2194                         _vconf_db_commit_transaction();
2195                 }
2196         }
2197 #endif
2198
2199         return func_ret;
2200 }
2201
2202 /*
2203  * This function get the integer value of given key
2204  * @param[in]   in_key  key
2205  * @param[out]  intval output buffer
2206  * @return 0 on success, -1 on error
2207  */
2208 API int vconf_get_int(const char *in_key, int *intval)
2209 {
2210         START_TIME_CHECK
2211
2212         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2213         retvm_if(intval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
2214
2215         int func_ret = VCONF_ERROR;
2216         keynode_t* pKeyNode = _vconf_keynode_new();
2217         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2218
2219         _vconf_keynode_set_keyname(pKeyNode, in_key);
2220
2221         if (_vconf_get_key(pKeyNode) != VCONF_OK)
2222                 ERR("vconf_get_int(%d) : %s error", getpid(), in_key);
2223         else {
2224                 *intval = pKeyNode->value.i;
2225
2226                 if(pKeyNode->type == VCONF_TYPE_INT) {
2227                         INFO("vconf_get_int(%d) : %s(%d) success", getpid(), in_key, *intval);
2228                         func_ret = VCONF_OK;
2229                 } else
2230                         ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
2231         }
2232
2233         _vconf_keynode_free(pKeyNode);
2234
2235         END_TIME_CHECK
2236
2237         return func_ret;
2238 }
2239
2240 /*
2241  * This function get the boolean value of given key
2242  * @param[in]   in_key  key
2243  * @param[out]  boolval output buffer
2244  * @return 0 on success, -1 on error
2245  */
2246 API int vconf_get_bool(const char *in_key, int *boolval)
2247 {
2248         START_TIME_CHECK
2249
2250         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2251         retvm_if(boolval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
2252
2253         int func_ret = VCONF_ERROR;
2254         keynode_t* pKeyNode = _vconf_keynode_new();
2255         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2256
2257         _vconf_keynode_set_keyname(pKeyNode, in_key);
2258
2259         if (_vconf_get_key(pKeyNode) != VCONF_OK)
2260                 ERR("vconf_get_bool(%d) : %s error", getpid(), in_key);
2261         else {
2262                 *boolval = !!(pKeyNode->value.b);
2263
2264                 if(pKeyNode->type == VCONF_TYPE_BOOL) {
2265                         INFO("vconf_get_bool(%d) : %s(%d) success", getpid(), in_key, *boolval);
2266                         func_ret = VCONF_OK;
2267                 } else
2268                         ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
2269         }
2270
2271         _vconf_keynode_free(pKeyNode);
2272
2273         END_TIME_CHECK
2274
2275         return func_ret;
2276 }
2277
2278 /*
2279  * This function get the double value of given key
2280  * @param[in]   in_key  key
2281  * @param[out]  dblval output buffer
2282  * @return 0 on success, -1 on error
2283  */
2284 API int vconf_get_dbl(const char *in_key, double *dblval)
2285 {
2286         START_TIME_CHECK
2287
2288         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2289         retvm_if(dblval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
2290
2291         int func_ret = VCONF_ERROR;
2292         keynode_t* pKeyNode = _vconf_keynode_new();
2293         retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2294
2295         _vconf_keynode_set_keyname(pKeyNode, in_key);
2296
2297         if (_vconf_get_key(pKeyNode) != VCONF_OK)
2298                 ERR("vconf_get_dbl(%d) : %s error", getpid(), in_key);
2299         else {
2300
2301                 *dblval = pKeyNode->value.d;
2302
2303                 if(pKeyNode->type == VCONF_TYPE_DOUBLE) {
2304                         INFO("vconf_get_dbl(%d) : %s(%f) success", getpid(), in_key, *dblval);
2305                         func_ret = VCONF_OK;
2306                 } else
2307                         ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
2308         }
2309
2310         _vconf_keynode_free(pKeyNode);
2311
2312         END_TIME_CHECK
2313
2314         return func_ret;
2315 }
2316
2317 /*
2318  * This function get the string value of given key
2319  * @param[in]   in_key  key
2320  * @return pointer of key value on success, NULL on error
2321  */
2322 API char *vconf_get_str(const char *in_key)
2323 {
2324         START_TIME_CHECK
2325
2326         retvm_if(in_key == NULL, NULL, "Invalid argument: key is null");
2327
2328         keynode_t* pKeyNode = _vconf_keynode_new();
2329         retvm_if(pKeyNode == NULL, NULL, "key malloc fail");
2330
2331         _vconf_keynode_set_keyname(pKeyNode, in_key);
2332
2333         char *strval = NULL;
2334         char *tempstr = NULL;
2335
2336         if (_vconf_get_key(pKeyNode) != VCONF_OK) {
2337                 ERR("vconf_get_str(%d) : %s error", getpid(), in_key);
2338         } else {
2339
2340                 if(pKeyNode->type == VCONF_TYPE_STRING)
2341                         tempstr = pKeyNode->value.s;
2342                 else
2343                         ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
2344
2345                 if(tempstr)
2346                         strval = strdup(tempstr);
2347                 INFO("vconf_get_str(%d) : %s(%s) success", getpid(), in_key, strval);
2348         }
2349
2350         _vconf_keynode_free(pKeyNode);
2351
2352         END_TIME_CHECK
2353
2354         return strval;
2355 }
2356
2357 /*
2358  * This function unset given key
2359  * @param[in]   in_key  key
2360  * @return 0 on success, -1 on error
2361  */
2362 API int vconf_unset(const char *in_key)
2363 {
2364         START_TIME_CHECK
2365
2366         char path[VCONF_KEY_PATH_LEN] = {0,};
2367         int ret = -1;
2368         int err_retry = VCONF_ERROR_RETRY_CNT;
2369         int func_ret = VCONF_OK;
2370
2371         WARN("vconf_unset: %s. THIS API(vconf_unset) WILL BE DEPRECATED", in_key);
2372
2373         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2374
2375         ret = _vconf_get_key_path(in_key, path);
2376         retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
2377
2378         retvm_if(access(path, F_OK) == -1, VCONF_ERROR, "Error : key(%s) is not exist", in_key);
2379
2380         do {
2381                 ret = remove(path);
2382                 if(ret == -1) {
2383                         ERR("vconf_unset error(%d) : %s", errno, in_key);
2384                         func_ret = VCONF_ERROR;
2385                 } else {
2386                         func_ret = VCONF_OK;
2387                         break;
2388                 }
2389         } while(err_retry--);
2390
2391         END_TIME_CHECK
2392
2393         return func_ret;
2394 }
2395
2396 /*
2397  * This function unset given key recursively
2398  * @param[in]   in_dir  Directory name for removing
2399  * @return 0 on success, -1 on error
2400  */
2401 API int vconf_unset_recursive(const char *in_dir)
2402 {
2403         START_TIME_CHECK
2404
2405         DIR *dir = NULL;
2406         struct dirent entry;
2407         struct dirent *result = NULL;
2408         char fullpath[VCONF_KEY_PATH_LEN] = {0,};
2409         char dirpath[VCONF_KEY_PATH_LEN] = {0,};
2410         char err_buf[ERR_LEN] = {0,};
2411         int rc = 0;
2412         int func_ret = 0;
2413         int ret = 0;
2414
2415         WARN("vconf_unset_recursive: %s. THIS API(vconf_unset_recursive) WILL BE DEPRECATED", in_dir);
2416
2417         retvm_if(in_dir == NULL, VCONF_ERROR, "Invalid argument: dir path is null");
2418
2419         ret = _vconf_get_key_path(in_dir, dirpath);
2420         retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
2421
2422         if((dir=opendir(dirpath)) == NULL) {
2423                 strerror_r(errno, err_buf, ERR_LEN);
2424                 ERR("ERROR : open directory(%s) fail(%s)", in_dir, err_buf);
2425                 return VCONF_ERROR;
2426         }
2427
2428         if((readdir_r(dir, &entry, &result)) != 0) {
2429                 strerror_r(errno, err_buf, ERR_LEN);
2430                 ERR("ERROR : read directory(%s) fail(%s)", in_dir, err_buf);
2431                 func_ret = VCONF_ERROR;
2432         }
2433
2434         while(result != NULL)
2435         {
2436                 if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
2437                     goto NEXT;
2438                 }
2439
2440                 snprintf(fullpath,VCONF_KEY_PATH_LEN, "%s/%s", dirpath, entry.d_name);
2441
2442                 ret = _vconf_path_is_dir(fullpath);
2443                 if(ret != VCONF_ERROR) {
2444                         if(ret == 1) {
2445                                 rc = vconf_unset_recursive(fullpath);
2446                                 if(rc == VCONF_ERROR)
2447                                         func_ret = VCONF_ERROR;
2448                         }
2449
2450                         rc = remove(fullpath);
2451                         if(rc == -1) {
2452                                 memset(err_buf, 0x00, sizeof(err_buf));
2453                                 strerror_r(errno, err_buf, sizeof(err_buf));
2454                                 ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
2455                                 func_ret = VCONF_ERROR;
2456                         }
2457                 } else {
2458                         memset(err_buf, 0x00, sizeof(err_buf));
2459                         strerror_r(errno, err_buf, sizeof(err_buf));
2460                         ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
2461                         func_ret = VCONF_ERROR;
2462                 }
2463 NEXT:
2464                 if((readdir_r(dir, &entry, &result)) != 0) {
2465                         memset(err_buf, 0x00, sizeof(err_buf));
2466                         strerror_r(errno, err_buf, sizeof(err_buf));
2467                         ERR("ERROR : read directory(%s) fail(%s)", in_dir, err_buf);
2468                         func_ret = VCONF_ERROR;
2469                 }
2470         }
2471
2472         if((closedir(dir)) != 0) {
2473                 memset(err_buf, 0x00, sizeof(err_buf));
2474                 strerror_r(errno, err_buf, sizeof(err_buf));
2475                 ERR("ERROR : close directory(%s) fail(%s)", in_dir, err_buf);
2476                 func_ret = VCONF_ERROR;
2477         }
2478 #if 0
2479         if(func_ret == VCONF_OK) {
2480                 if((remove(in_dir)) == -1) {
2481                         memset(err_buf, 0x00, sizeof(err_buf));
2482                         strerror_r(errno, err_buf, sizeof(err_buf));
2483                         ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
2484                         func_ret = VCONF_ERROR;
2485                 }
2486         }
2487 #endif
2488
2489         return func_ret;
2490 }
2491
2492 API int vconf_notify_key_changed(const char *in_key, vconf_callback_fn cb, void *user_data)
2493 {
2494         START_TIME_CHECK
2495
2496         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2497         retvm_if(cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
2498
2499         if (_vconf_kdb_add_notify(in_key, cb, user_data)) {
2500                 ERR("vconf_notify_key_changed : key(%s) add notify fail", in_key);
2501                 return VCONF_ERROR;
2502         }
2503
2504         INFO("vconf_notify_key_changed : %s noti is added", in_key);
2505
2506         END_TIME_CHECK
2507
2508         return VCONF_OK;
2509 }
2510
2511 API int vconf_ignore_key_changed(const char *in_key, vconf_callback_fn cb)
2512 {
2513         START_TIME_CHECK
2514
2515         retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2516         retvm_if(cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
2517
2518         if (_vconf_kdb_del_notify(in_key, cb)) {
2519                 ERR("vconf_ignore_key_changed() failed: key(%s)", in_key);
2520                 return VCONF_ERROR;
2521         }
2522
2523         INFO("vconf_ignore_key_changed : %s noti removed", in_key);
2524
2525         END_TIME_CHECK
2526
2527         return VCONF_OK;
2528 }
2529
2530 API mode_t vconf_set_permission(mode_t mode)
2531 {
2532         /* TODO: implement! */
2533         return mode;
2534 }
2535
2536 API int vconf_set_key_permission(const char *in_key, const mode_t mode)
2537 {
2538         /* TODO: implement! */
2539         return 0;
2540 }
2541