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