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