4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hakjoo Ko <hakjoo.ko@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "vconf-internals.h"
30 #include <sys/xattr.h>
32 #include <tzplatform_config.h>
35 #define API __attribute__ ((visibility("default")))
38 #define VCONF_ERROR_RETRY_CNT 20
39 #define VCONF_ERROR_RETRY_SLEEP_UTIME 10000
41 #ifdef VCONF_USE_SQLFS_TRANSACTION
44 #define VCONF_MOUNT_PATH tzplatform_mkpath(TZ_SYS_CONFIG,"db")
45 #define VCONF_MOUNT_PATH_CHECK \
48 IN_SBOX = access(tzplatform_mkpath(TZ_SYS_CONFIG,"kdb_first_boot"), F_OK) + 2; \
49 if(2==IN_SBOX) return 0;\
52 __thread int is_transaction;
55 #ifdef VCONF_TIMECHECK
56 double correction, startT;
58 double set_start_time(void)
63 gettimeofday(&tv, NULL);
64 curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
68 double exec_time(double start)
70 double end = set_start_time();
71 return (end - start - correction);
77 temp_t = set_start_time();
78 correction = exec_time(temp_t);
84 int _vconf_keynode_set_keyname(keynode_t *keynode, const char *keyname)
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");
92 static inline void _vconf_keynode_set_dir(keynode_t *keynode)
94 keynode->type = VCONF_TYPE_DIR;
97 static inline void _vconf_keynode_set_value_int(keynode_t *keynode, const int value)
99 keynode->type = VCONF_TYPE_INT;
100 keynode->value.i = value;
103 static inline void _vconf_keynode_set_value_bool(keynode_t *keynode, const int value)
105 keynode->type = VCONF_TYPE_BOOL;
106 keynode->value.b = !!value;
109 static inline void _vconf_keynode_set_value_dbl(keynode_t *keynode, const double value)
111 keynode->type = VCONF_TYPE_DOUBLE;
112 keynode->value.d = value;
115 static inline void _vconf_keynode_set_value_str(keynode_t *keynode, const char *value)
117 keynode->type = VCONF_TYPE_STRING;
118 keynode->value.s = strdup(value);
121 inline void _vconf_keynode_set_null(keynode_t *keynode)
123 keynode->type = VCONF_TYPE_NONE;
124 //keynode->value.d = NULL;
127 static inline keynode_t *_vconf_keynode_next(keynode_t *keynode)
129 return keynode->next;
132 inline keynode_t *_vconf_keynode_new(void)
135 keynode = calloc(1, sizeof(keynode_t));
140 inline void _vconf_keynode_free(keynode_t *keynode)
143 if (keynode->keyname)
144 free(keynode->keyname);
145 if (keynode->type == VCONF_TYPE_STRING && keynode->value.s)
146 free(keynode->value.s);
151 static inline keynode_t *_vconf_keylist_headnode(keylist_t *keylist)
153 return keylist->head;
156 static keynode_t *_vconf_keylist_lookup(keylist_t *keylist, const char *keyname,
157 keynode_t **before_keynode)
159 keynode_t *found_node, *temp_node = NULL;
160 size_t length = 1 + strlen(keyname);
162 found_node = _vconf_keylist_headnode(keylist);
165 if(found_node->keyname == NULL) {
166 ERR("key node has null keyname");
170 if (!memcmp(keyname, found_node->keyname, length)) {
171 if (before_keynode) {
172 *before_keynode = temp_node;
177 temp_node = found_node;
178 found_node = _vconf_keynode_next(found_node);
184 * This function get Key name of the keynode.
185 * @param[in] keynode The Key
186 * @return Key Name of the keynode
188 API char *vconf_keynode_get_name(keynode_t *keynode)
190 retvm_if(keynode == NULL, NULL, "Invalid argument: keynode is NULL");
191 retvm_if(keynode->keyname == NULL, NULL, "The name of keynode is NULL");
193 return keynode->keyname;
197 * This function get value type of the keynode.
198 * @param[in] keynode The Key
199 * @return Type of the keynode
201 API int vconf_keynode_get_type(keynode_t *keynode)
203 retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
205 return keynode->type;
208 API int vconf_keynode_get_int(keynode_t *keynode)
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);
214 return keynode->value.i;
217 API double vconf_keynode_get_dbl(keynode_t *keynode)
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);
223 return keynode->value.d;
227 * This function get Boolean value of the keynode.
228 * @param[in] keynode The Key
229 * @return Boolean value, -1 on error
231 API int vconf_keynode_get_bool(keynode_t *keynode)
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);
237 return !!(keynode->value.b);
241 * This function get String value of the keynode.
242 * @param[in] keynode The Key
243 * @return String value, NULL on error
245 API char *vconf_keynode_get_str(keynode_t *keynode)
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);
251 return keynode->value.s;
255 * Allocate, initialize and return a new Keylist object.
256 * @return The pointer of New keylist, NULL on error
258 API keylist_t *vconf_keylist_new(void)
261 keylist = calloc(1, sizeof(keylist_t));
267 * This function rewinds the KeyList internal cursor.
268 * @param[in] keylist Key List
269 * @return 0 on success, -1 on error
271 API int vconf_keylist_rewind(keylist_t *keylist)
273 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
275 keylist->cursor = NULL;
281 * A destructor for Keylist objects.
282 * @param[in] keylist Key List
283 * @return 0 on success, -1 on error
285 API int vconf_keylist_free(keylist_t *keylist)
287 keynode_t *keynode, *temp;
289 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
292 keynode = _vconf_keylist_headnode(keylist);
294 temp = _vconf_keynode_next(keynode);
295 _vconf_keynode_free(keynode);
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
311 vconf_keylist_lookup(keylist_t *keylist,
312 const char *keyname, keynode_t **return_node)
314 keynode_t *found_node;
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");
320 found_node = _vconf_keylist_lookup(keylist, keyname, NULL);
321 if (NULL == found_node)
325 *return_node = found_node;
326 return found_node->type;
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
335 API keynode_t *vconf_keylist_nextnode(keylist_t *keylist)
337 retvm_if(keylist == NULL, NULL, "Invalid argument: keylist is NULL");
340 keylist->cursor = _vconf_keynode_next(keylist->cursor);
342 keylist->cursor = keylist->head;
344 return keylist->cursor;
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
356 vconf_keylist_add_int(keylist_t *keylist, const char *keyname, const int value)
358 keynode_t *keynode = NULL, *addition = NULL;
360 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
361 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
363 if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
364 _vconf_keynode_set_value_int(keynode, value);
367 if ((keynode = _vconf_keylist_headnode(keylist)))
368 while (_vconf_keynode_next(keynode))
369 keynode = _vconf_keynode_next(keynode);
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;
378 keylist->head = addition;
381 ERR("(maybe)not enought memory");
382 free(addition), addition = NULL;
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
398 vconf_keylist_add_bool(keylist_t *keylist, const char *keyname, const int value)
400 keynode_t *keynode = NULL, *addition = NULL;
402 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
403 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
405 if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
406 _vconf_keynode_set_value_bool(keynode, value);
409 if ((keynode = _vconf_keylist_headnode(keylist)))
410 while (_vconf_keynode_next(keynode))
411 keynode = _vconf_keynode_next(keynode);
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;
420 keylist->head = addition;
423 ERR("(maybe)not enought memory");
424 free(addition), addition = NULL;
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
440 vconf_keylist_add_dbl(keylist_t *keylist,
441 const char *keyname, const double value)
443 keynode_t *keynode = NULL, *addition = NULL;
445 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
446 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
448 if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
449 _vconf_keynode_set_value_dbl(keynode, value);
452 if ((keynode = _vconf_keylist_headnode(keylist)))
453 while (_vconf_keynode_next(keynode))
454 keynode = _vconf_keynode_next(keynode);
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;
463 keylist->head = addition;
466 ERR("(maybe)not enought memory");
467 free(addition), addition = NULL;
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
483 vconf_keylist_add_str(keylist_t *keylist,
484 const char *keyname, const char *value)
486 keynode_t *keynode = NULL, *addition = NULL;
488 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
489 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
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);
497 if (NULL != (keynode = _vconf_keylist_headnode(keylist)))
498 while (_vconf_keynode_next(keynode))
499 keynode = _vconf_keynode_next(keynode);
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;
508 keylist->head = addition;
511 ERR("(maybe)not enought memory");
512 free(addition), addition = NULL;
520 * This function Appends a new Keynode to the keylist without value.
522 * @param[in] keylist Key List
523 * @param[in] keyname Key
524 * @return Number of keynode included in the keylist, -1 on error
526 API int vconf_keylist_add_null(keylist_t *keylist, const char *keyname)
528 keynode_t *keynode = NULL, *addition = NULL;
530 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
531 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
533 if (NULL != (keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
535 keynode->value.d = 0;
538 if ((keynode = _vconf_keylist_headnode(keylist)))
539 while (_vconf_keynode_next(keynode))
540 keynode = _vconf_keynode_next(keynode);
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;
548 keylist->head = addition;
551 ERR("(maybe)not enought memory");
552 free(addition), addition = NULL;
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
565 API int vconf_keylist_del(keylist_t *keylist, const char *keyname)
567 keynode_t *found_node, *before_node = NULL;
569 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
570 retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
572 if ((found_node = _vconf_keylist_lookup(keylist, keyname, &before_node))) {
574 before_node->next = found_node->next;
576 /* requested key is headnode of keylist */
577 keylist->head = found_node->next;
580 _vconf_keynode_free(found_node);
588 int _vconf_get_key_prefix(const char *keyname, int *prefix)
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;
597 ERR("Invalid argument: wrong prefix of key(%s)", keyname);
598 *prefix = VCONF_BACKEND_NULL;
599 return VCONF_ERROR_WRONG_PREFIX;
605 int _vconf_get_key_path(const char *keyname, char *path)
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);
614 ERR("Invalid argument: wrong prefix of key(%s)", keyname);
615 return VCONF_ERROR_WRONG_PREFIX;
621 #ifdef VCONF_USE_BACKUP_TRANSACTION
622 int _vconf_get_backup_path(const char *keyname, char *path)
624 char key_buf[VCONF_KEY_PATH_LEN] = {0, };
627 for(i = 0; i<VCONF_KEY_PATH_LEN-1 && keyname[i] != '\0' ; i++) {
628 if (keyname[i] == '/')
631 key_buf[i] = keyname[i];
634 snprintf(path, VCONF_KEY_PATH_LEN, "%s%s%s%s", BACKEND_SYSTEM_DIR, BACKEND_DB_PREFIX, ".backup/", key_buf);
640 #ifndef DISABLE_RUNTIME_KEY_CREATION
641 static int _vconf_set_key_check_parent_dir(const char* path)
644 struct stat stat_info;
646 char path_buf[VCONF_KEY_PATH_LEN] = {0,};
649 mode_t dir_mode = 0664 | 0111;
651 parent = strrchr(path, '/');
652 strncpy(path_buf, path, parent-path);
653 path_buf[parent-path]=0;
655 exists = stat(path_buf,&stat_info);
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);
672 static int _vconf_set_key_creation(const char* path)
677 fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
680 ERR("open(rdwr,create) error\n");
689 static int _vconf_set_file_lock(int fd, short type)
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*/
698 return fcntl(fd, F_SETLKW, &l);
701 static int _vconf_set_read_lock(int fd)
703 return _vconf_set_file_lock(fd, F_RDLCK);
706 static int _vconf_set_write_lock(int fd)
708 return _vconf_set_file_lock(fd, F_WRLCK);
711 static int _vconf_set_unlock(int fd)
713 return _vconf_set_file_lock(fd, F_UNLCK);
716 #ifdef VCONF_USE_SQLFS_TRANSACTION
717 static void _vconf_acquire_transaction_delay(int ms)
719 struct timeval timeout;
720 timeout.tv_sec = ms / 1000 ;
721 timeout.tv_usec = 1000 * ( ms % 1000 );
723 select(0, 0, 0, 0, &timeout);
726 static int _vconf_db_begin_transaction()
729 VCONF_MOUNT_PATH_CHECK;
731 if(is_transaction == 0) {
734 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_start", &value, sizeof(value), 0) == -1)
736 //ERR("someone access vconf. retrying...(%d)", errno);
737 _vconf_acquire_transaction_delay(50);
738 goto transaction_retry;
749 static int _vconf_db_commit_transaction()
752 VCONF_MOUNT_PATH_CHECK;
754 retv_if(is_transaction <= 0, VCONF_ERROR);
756 if(is_transaction == 1) {
759 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_stop", &value, sizeof(value), 0) == -1)
761 //ERR("setxattr failed. retrying...(%d)", errno);
762 _vconf_acquire_transaction_delay(50);
763 goto transaction_retry;
774 static int _vconf_db_rollback_transaction()
777 VCONF_MOUNT_PATH_CHECK;
779 retv_if(is_transaction <= 0, VCONF_ERROR);
781 if(is_transaction == 1) {
784 if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_rb", &value, sizeof(value), 0) == -1)
786 //ERR("setxattr failed. retrying...(%d)", errno);
787 _vconf_acquire_transaction_delay(50);
788 goto transaction_retry;
798 #endif //VCONF_USE_SQLFS_TRANSACTION
800 #ifdef VCONF_USE_BACKUP_TRANSACTION
802 static int _vconf_backup_check(char* vconf_path, char* backup_path)
807 char file_buf[BUF_LEN] = { 0, };
808 char err_buf[100] = { 0, };
809 int complete_mark = 0;
812 int is_recovered = 0;
815 if (access(vconf_path, F_OK) == -1 || access(backup_path, F_OK) == -1)
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;
826 if(_vconf_set_write_lock(vconf_fd) == -1) {
827 ERR("set write lock %s failed", vconf_path);
828 ret = VCONF_ERROR_FILE_LOCK;
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;
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;
847 } else if (file_size < FILE_ATOMIC_GUARANTEE_SIZE + VCONF_BACKUP_COMP_MARK_SIZE) {
851 if (lseek(backup_fd, 0, SEEK_SET) != 0) {
852 ERR("seek %s failed", backup_path);
853 ret = VCONF_ERROR_FILE_SEEK;
858 read_len = read(backup_fd, &complete_mark, sizeof(int));
859 if (read_len < sizeof(int))
862 if (complete_mark != VCONF_BACKUP_COMPLETE_MARK)
865 if (ftruncate(vconf_fd, 0) == -1) {
866 ERR("truncate %s failed", vconf_path);
867 ret = VCONF_ERROR_FILE_TRUNCATE;
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;
884 if(_vconf_set_unlock(vconf_fd)==-1) {
885 ERR("unset write lock %s failed", vconf_path);
886 ret = VCONF_ERROR_FILE_LOCK;
897 if(ret == VCONF_OK) {
898 if(remove(backup_path) == -1) {
899 ret = VCONF_ERROR_FILE_REMOVE;
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);
910 WARN("vconf(%s)'s non-complete backup file is removed", vconf_path, backup_path);
915 static int _vconf_backup_write_str(char* backup_path, char* value)
918 char err_buf[100] = { 0, };
922 int complete_mark = VCONF_BACKUP_COMPLETE_MARK;
924 int vconf_type_str = VCONF_TYPE_STRING;
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;
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;
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;
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;
957 if (fdatasync(backup_fd) == -1) {
958 ERR("sync %s failed", backup_path);
959 ret = VCONF_ERROR_FILE_SYNC;
964 if (lseek(backup_fd, 0, SEEK_SET) != 0) {
965 ERR("seek %s failed", backup_path);
966 ret = VCONF_ERROR_FILE_SEEK;
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;
978 if (fdatasync(backup_fd) == -1) {
979 ERR("sync %s failed", backup_path);
980 ret = VCONF_ERROR_FILE_SYNC;
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);
998 static int _vconf_backup_commit(char* backup_path)
1001 char err_buf[100] = { 0, };
1004 if(remove(backup_path) == -1) {
1005 ERR("remove %s failed", backup_path);
1006 ret = VCONF_ERROR_FILE_REMOVE;
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);
1018 #endif // VCONF_USE_BACKUP_TRANSACTION
1020 static int _vconf_set_key_filesys(keynode_t *keynode, int prefix)
1022 char path[VCONF_KEY_PATH_LEN] = {0,};
1025 int func_ret = VCONF_OK;
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;
1037 ret = _vconf_get_key_path(keynode->keyname, path);
1038 retv_if(ret != VCONF_OK, ret);
1041 #ifdef VCONF_CHECK_IS_INITIALIZED
1042 if(prefix == VCONF_BACKEND_MEMORY && VCONF_NOT_INITIALIZED) {
1043 func_ret = VCONF_ERROR_NOT_INITIALIZED;
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) {
1060 if( (fp = fopen(path, "r+")) == NULL ) {
1061 func_ret = VCONF_ERROR_FILE_OPEN;
1066 #ifdef VCONF_USE_SQLFS_TRANSACTION
1067 if (prefix != VCONF_BACKEND_DB)
1070 ret = _vconf_set_write_lock(fileno(fp));
1072 func_ret = VCONF_ERROR_FILE_LOCK;
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) {
1084 ret = _vconf_backup_write_str(backup_path, keynode->value.s);
1085 if(ret != VCONF_OK) {
1090 WARN("vconf backup file for(%s) is created. file size(%d)", path, file_size);
1095 if (ftruncate(fileno(fp), 0) == -1) {
1096 func_ret = VCONF_ERROR_FILE_TRUNCATE;
1101 /* write key type */
1102 ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
1110 func_ret = VCONF_ERROR_FILE_WRITE;
1114 /* write key value */
1115 switch(keynode->type)
1117 case VCONF_TYPE_INT:
1118 ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
1119 if(ret <= 0) is_write_error = 1;
1121 case VCONF_TYPE_DOUBLE:
1122 ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
1123 if(ret <= 0) is_write_error = 1;
1125 case VCONF_TYPE_BOOL:
1126 ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
1127 if(ret <= 0) is_write_error = 1;
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);
1135 func_ret = VCONF_ERROR_WRONG_TYPE;
1145 func_ret = VCONF_ERROR_FILE_WRITE;
1149 #ifdef VCONF_USE_SQLFS_TRANSACTION
1150 if(prefix == VCONF_BACKEND_FILE)
1152 if(prefix == VCONF_BACKEND_FILE || prefix == VCONF_BACKEND_DB)
1157 ret = fdatasync(fileno(fp));
1160 func_ret = VCONF_ERROR_FILE_SYNC;
1164 #ifdef VCONF_USE_BACKUP_TRANSACTION
1165 if (is_backup_need) {
1166 ret = _vconf_backup_commit(backup_path);
1167 if(ret != VCONF_OK) {
1176 #ifdef VCONF_USE_SQLFS_TRANSACTION
1177 if (prefix != VCONF_BACKEND_DB)
1180 ret = _vconf_set_unlock(fileno(fp));
1182 func_ret = VCONF_ERROR_FILE_LOCK;
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);
1199 static int _vconf_set_key(keynode_t *keynode)
1201 int func_ret = VCONF_OK;
1203 int is_busy_err = 0;
1208 ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
1209 retv_if(ret != VCONF_OK, ret);
1211 #ifdef VCONF_USE_SQLFS_TRANSACTION
1212 if(prefix == VCONF_BACKEND_DB) {
1213 _vconf_db_begin_transaction();
1217 while((ret = _vconf_set_key_filesys(keynode, prefix)) != VCONF_OK)
1222 #ifdef VCONF_CHECK_INITIALIZED
1223 if(VCONF_NOT_INITIALIZED)
1225 ERR("%s : vconf is not initialized\n", keynode->keyname);
1228 else if(ret == VCONF_ERROR_FILE_OPEN)
1231 if(ret == VCONF_ERROR_FILE_OPEN)
1236 /* file is not exist, make path */
1237 #ifndef DISABLE_RUNTIME_KEY_CREATION
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");
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);
1254 rc = _vconf_set_key_creation(path);
1255 if(rc != VCONF_OK) {
1256 ERR("_vconf_set_key_creation error : %s", path);
1259 INFO("%s key is created", keynode->keyname);
1271 else if (ret == VCONF_ERROR_FILE_CHMOD)
1282 else if (ret == VCONF_ERROR_FILE_LOCK)
1295 else if (ret == VCONF_ERROR_FILE_WRITE)
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);
1319 ERR("%s : write buf error(%d). break. (%d)\n", keynode->keyname, ret, retry);
1320 func_ret = VCONF_ERROR;
1325 #ifdef VCONF_USE_SQLFS_TRANSACTION
1326 if(prefix == VCONF_BACKEND_DB) {
1327 if(func_ret == VCONF_ERROR) {
1328 _vconf_db_rollback_transaction();
1330 _vconf_db_commit_transaction();
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
1343 API int vconf_set(keylist_t *keylist)
1347 keynode_t *got_node;
1349 int func_ret = VCONF_OK;
1353 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
1355 INFO("vconf_set (%d)START", keylist->num);
1357 got_node = _vconf_keylist_headnode(keylist);
1359 retvm_if(got_node == NULL, VCONF_ERROR, "Invalid argument: headnode is NULL");
1361 ret = _vconf_get_key_prefix(got_node->keyname, &prefix);
1362 retv_if(ret != VCONF_OK, ret);
1364 #ifdef VCONF_USE_SQLFS_TRANSACTION
1365 if(prefix == VCONF_BACKEND_DB) {
1366 _vconf_db_begin_transaction();
1370 while (got_node != NULL) {
1371 ret = _vconf_set_key(got_node);
1372 if(ret != VCONF_OK) {
1373 func_ret = VCONF_ERROR;
1376 got_node = _vconf_keynode_next(got_node);
1379 #ifdef VCONF_USE_SQLFS_TRANSACTION
1380 if(prefix == VCONF_BACKEND_DB) {
1381 if(func_ret == VCONF_ERROR) {
1382 _vconf_db_rollback_transaction();
1384 _vconf_db_commit_transaction();
1394 API int vconf_sync_key(const char *in_key)
1399 char path[VCONF_KEY_PATH_LEN] = {0,};
1402 ret = _vconf_get_key_path(in_key, path);
1403 if(ret != VCONF_OK) return VCONF_ERROR;
1405 fd = open(path, O_RDWR);
1406 if(fd == -1) return VCONF_ERROR;
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
1422 API int vconf_set_int(const char *in_key, const int intval)
1426 retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1428 int func_ret = VCONF_OK;
1430 keynode_t* pKeyNode = _vconf_keynode_new();
1431 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
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");
1439 _vconf_keynode_set_value_int(pKeyNode, intval);
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;
1445 INFO("vconf_set_int(%d) : %s(%d) success", getpid(), in_key, intval);
1448 _vconf_keynode_free(pKeyNode);
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
1462 API int vconf_set_bool(const char *in_key, const int boolval)
1466 retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1468 int func_ret = VCONF_OK;
1469 keynode_t* pKeyNode = _vconf_keynode_new();
1470 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
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");
1478 _vconf_keynode_set_value_bool(pKeyNode, boolval);
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;
1484 INFO("vconf_set_bool(%d) : %s(%d) success", getpid(), in_key, boolval);
1487 _vconf_keynode_free(pKeyNode);
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
1500 API int vconf_set_dbl(const char *in_key, const double dblval)
1504 retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1506 int func_ret = VCONF_OK;
1507 keynode_t* pKeyNode = _vconf_keynode_new();
1508 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
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");
1516 _vconf_keynode_set_value_dbl(pKeyNode, dblval);
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;
1522 INFO("vconf_set_dbl(%d) : %s(%f) success", getpid(), in_key, dblval);
1525 _vconf_keynode_free(pKeyNode);
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
1538 API int vconf_set_str(const char *in_key, const char *strval)
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");
1545 int func_ret = VCONF_OK;
1546 keynode_t* pKeyNode = _vconf_keynode_new();
1547 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
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");
1555 _vconf_keynode_set_value_str(pKeyNode, strval);
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;
1561 INFO("vconf_set_str(%d) : %s(%s) success", getpid(), in_key, strval);
1564 _vconf_keynode_free(pKeyNode);
1572 #ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
1573 /* keyFileUnserialize function of ELEKTRA */
1574 static int _vconf_get_key_elektra_format(keynode_t *keynode, FILE *fp)
1576 char version[10] = {0,};
1577 char type[5] = {0,};
1578 char comment[8] = {0,};
1579 char file_buf[BUF_LEN] = {0,};
1583 char err_buf[100] = { 0, };
1584 int func_ret = VCONF_OK;
1587 INFO("_vconf_get_key_elektra_format start");
1591 if (!fgets(version, sizeof(version), fp))
1598 func_ret = VCONF_ERROR_FILE_FGETS;
1601 if (strncmp(version,"RG",2)) {
1602 func_ret = VCONF_ERROR_WRONG_TYPE;
1606 if (!fgets(type, sizeof(type), fp))
1613 func_ret = VCONF_ERROR_FILE_FGETS;
1617 if (!fgets(comment, sizeof(comment), fp))
1624 func_ret = VCONF_ERROR_FILE_FGETS;
1628 while(fgets(file_buf, sizeof(file_buf), fp))
1631 value_size = value_size + strlen(file_buf);
1632 tmp = (char *) realloc(value, value_size);
1635 func_ret = VCONF_ERROR_NO_MEM;
1639 strncat(value, file_buf, strlen(file_buf));
1641 value_size = strlen(file_buf) + 1;
1642 value = (char *)malloc(value_size);
1644 func_ret = VCONF_ERROR_NO_MEM;
1647 memset(value, 0x00, value_size);
1648 strncpy(value, file_buf, strlen(file_buf));
1654 func_ret = VCONF_ERROR_FILE_FGETS;
1659 case VCONF_TYPE_INT:
1661 _vconf_keynode_set_value_int(keynode, atoi(value));
1664 case VCONF_TYPE_DOUBLE:
1666 _vconf_keynode_set_value_dbl(keynode, atof(value));
1669 case VCONF_TYPE_BOOL:
1671 _vconf_keynode_set_value_bool(keynode, atoi(value));
1674 case VCONF_TYPE_STRING:
1676 _vconf_keynode_set_value_str(keynode, value);
1681 func_ret = VCONF_ERROR_WRONG_VALUE;
1685 if(atoi(type) == VCONF_TYPE_STRING) {
1686 _vconf_keynode_set_value_str(keynode, "");
1688 func_ret = VCONF_ERROR_WRONG_VALUE;
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);
1699 if(value) free(value);
1705 static int _vconf_get_key_filesys(keynode_t *keynode, int prefix)
1707 char path[VCONF_KEY_PATH_LEN] = {0,};
1709 int func_ret = VCONF_OK;
1710 char err_buf[100] = { 0, };
1714 #ifdef VCONF_USE_BACKUP_TRANSACTION
1715 char backup_path[VCONF_KEY_PATH_LEN] = {0,};
1720 ret = _vconf_get_key_path(keynode->keyname, path);
1721 retv_if(ret != VCONF_OK, ret);
1723 #ifdef VCONF_CHECK_INITIALIZED
1724 if(prefix == VCONF_BACKEND_MEMORY && VCONF_NOT_INITIALIZED)
1726 func_ret = VCONF_ERROR_NOT_INITIALIZED;
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) {
1743 if( (fp = fopen(path, "r")) == NULL ) {
1744 func_ret = VCONF_ERROR_FILE_OPEN;
1749 #ifdef VCONF_USE_SQLFS_TRANSACTION
1750 if (prefix != VCONF_BACKEND_DB)
1753 ret = _vconf_set_read_lock(fileno(fp));
1755 func_ret = VCONF_ERROR_FILE_LOCK;
1761 /* read data type */
1762 if(!fread((void*)&type, sizeof(int), 1, fp)) {
1768 func_ret = VCONF_ERROR_FILE_FREAD;
1772 /* read data value */
1775 case VCONF_TYPE_INT:
1778 if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
1784 func_ret = VCONF_ERROR_FILE_FREAD;
1787 _vconf_keynode_set_value_int(keynode, value_int);
1792 case VCONF_TYPE_DOUBLE:
1794 double value_dbl = 0;
1795 if(!fread((void*)&value_dbl, sizeof(double), 1, fp)) {
1801 func_ret = VCONF_ERROR_FILE_FREAD;
1804 _vconf_keynode_set_value_dbl(keynode, value_dbl);
1809 case VCONF_TYPE_BOOL:
1812 if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
1818 func_ret = VCONF_ERROR_FILE_FREAD;
1821 _vconf_keynode_set_value_bool(keynode, value_int);
1826 case VCONF_TYPE_STRING:
1828 char file_buf[BUF_LEN] = {0,};
1832 while(fgets(file_buf, sizeof(file_buf), fp))
1835 value_size = value_size + strlen(file_buf);
1836 value = (char *) realloc(value, value_size);
1838 func_ret = VCONF_ERROR_NO_MEM;
1841 strncat(value, file_buf, strlen(file_buf));
1843 value_size = strlen(file_buf) + 1;
1844 value = (char *)malloc(value_size);
1846 func_ret = VCONF_ERROR_NO_MEM;
1849 memset(value, 0x00, value_size);
1850 strncpy(value, file_buf, strlen(file_buf));
1856 func_ret = VCONF_ERROR_FILE_FGETS;
1859 _vconf_keynode_set_value_str(keynode, value);
1861 _vconf_keynode_set_value_str(keynode, "");
1870 #ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
1871 func_ret = _vconf_get_key_elektra_format(keynode, fp);
1873 func_ret = VCONF_ERROR_WRONG_TYPE;
1878 #ifdef VCONF_USE_SQLFS_TRANSACTION
1879 if (prefix != VCONF_BACKEND_DB)
1882 ret = _vconf_set_unlock(fileno(fp));
1884 func_ret = VCONF_ERROR_FILE_LOCK;
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);
1903 int _vconf_get_key(keynode_t *keynode)
1905 int func_ret = VCONF_OK;
1907 int is_busy_err = 0;
1911 ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
1912 retv_if(ret != VCONF_OK, ret);
1914 #ifdef VCONF_USE_SQLFS_TRANSACTION
1915 if(prefix == VCONF_BACKEND_DB) {
1916 _vconf_db_begin_transaction();
1920 while((ret = _vconf_get_key_filesys(keynode, prefix)) != VCONF_OK)
1925 #ifdef VCONF_CHECK_INITIALIZED
1926 if(VCONF_NOT_INITIALIZED)
1928 ERR("%s : vconf is not initialized\n", keynode->keyname);
1931 else if(ret == VCONF_ERROR_FILE_OPEN)
1933 if(ret == VCONF_ERROR_FILE_OPEN)
1946 else if (ret == VCONF_ERROR_FILE_LOCK)
1959 else if (ret == VCONF_ERROR_FILE_FREAD)
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);
1981 ERR("%s : read buf error(%d). break\n", keynode->keyname, ret);
1982 func_ret = VCONF_ERROR;
1987 #ifdef VCONF_USE_SQLFS_TRANSACTION
1988 if(prefix == VCONF_BACKEND_DB) {
1989 if(func_ret == VCONF_ERROR) {
1990 _vconf_db_rollback_transaction();
1992 _vconf_db_commit_transaction();
2001 static int _vconf_check_value_integrity(const void *value, int type)
2005 if ((type == VCONF_TYPE_STRING) && (value != NULL)) {
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.");
2030 ERR("ERROR : vconf value is NULL.");
2036 int _vconf_path_is_dir(char* path)
2038 struct stat entryInfo;
2040 if(lstat(path, &entryInfo) == 0 ) {
2041 if( S_ISDIR( entryInfo.st_mode ) ) {
2051 API int vconf_get(keylist_t *keylist, const char *dirpath, get_option_t option)
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,};
2066 keynode_t *temp_keynode;
2068 retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is null");
2069 retvm_if(dirpath == NULL, VCONF_ERROR, "Invalid argument: dirpath is null");
2071 temp_keynode = _vconf_keylist_headnode(keylist);
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");
2079 if(temp_keynode != NULL) {
2080 while(_vconf_keynode_next(temp_keynode)) {
2081 temp_keynode = _vconf_keynode_next(temp_keynode);
2085 ret = _vconf_get_key_path(dirpath, full_path);
2086 retvm_if(ret != VCONF_OK, ret, "Invalid argument: key is not valid");
2089 ret = _vconf_get_key_prefix(dirpath, &prefix);
2090 retv_if(ret != VCONF_OK, ret);
2092 #ifdef VCONF_USE_SQLFS_TRANSACTION
2093 if(prefix == VCONF_BACKEND_DB) {
2094 _vconf_db_begin_transaction();
2098 is_dir = _vconf_path_is_dir(full_path);
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;
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;
2113 while(result != NULL)
2115 if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
2119 keynode_t* keynode = _vconf_keynode_new();
2120 if(keynode == NULL) {
2122 ERR("Invalid argument: key malloc fail");
2123 func_ret = VCONF_ERROR;
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);
2130 rc = _vconf_path_is_dir(full_file_path);
2131 if(rc != VCONF_ERROR) {
2134 if(option == VCONF_GET_KEY) {
2135 _vconf_keynode_free(keynode);
2138 _vconf_keynode_set_keyname(keynode, file_path);
2139 _vconf_keynode_set_dir(keynode);
2142 _vconf_keynode_set_keyname(keynode, file_path);
2143 _vconf_get_key(keynode);
2146 if (keylist->head && temp_keynode != NULL)
2148 temp_keynode->next = keynode;
2149 temp_keynode = _vconf_keynode_next(temp_keynode);
2152 keylist->head = keynode;
2153 temp_keynode = keylist->head;
2157 _vconf_keynode_free(keynode);
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;
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;
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;
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");
2184 _vconf_keynode_set_keyname(keynode, dirpath);
2186 _vconf_get_key(keynode);
2188 if (keylist->head && temp_keynode != NULL) {
2189 temp_keynode->next = keynode;
2190 //temp_keynode = _vconf_keynode_next(temp_keynode);
2192 keylist->head = keynode;
2193 temp_keynode = keylist->head;
2197 func_ret = VCONF_ERROR;
2200 vconf_keylist_rewind(keylist);
2203 #ifdef VCONF_USE_SQLFS_TRANSACTION
2204 if(prefix == VCONF_BACKEND_DB) {
2205 if(func_ret == VCONF_ERROR) {
2206 _vconf_db_rollback_transaction();
2208 _vconf_db_commit_transaction();
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
2222 API int vconf_get_int(const char *in_key, int *intval)
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");
2229 int func_ret = VCONF_ERROR;
2230 keynode_t* pKeyNode = _vconf_keynode_new();
2231 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2233 _vconf_keynode_set_keyname(pKeyNode, in_key);
2235 if (_vconf_get_key(pKeyNode) != VCONF_OK)
2236 ERR("vconf_get_int(%d) : %s error", getpid(), in_key);
2238 *intval = pKeyNode->value.i;
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;
2244 ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
2247 _vconf_keynode_free(pKeyNode);
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
2260 API int vconf_get_bool(const char *in_key, int *boolval)
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");
2267 int func_ret = VCONF_ERROR;
2268 keynode_t* pKeyNode = _vconf_keynode_new();
2269 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2271 _vconf_keynode_set_keyname(pKeyNode, in_key);
2273 if (_vconf_get_key(pKeyNode) != VCONF_OK)
2274 ERR("vconf_get_bool(%d) : %s error", getpid(), in_key);
2276 *boolval = !!(pKeyNode->value.b);
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;
2282 ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
2285 _vconf_keynode_free(pKeyNode);
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
2298 API int vconf_get_dbl(const char *in_key, double *dblval)
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");
2305 int func_ret = VCONF_ERROR;
2306 keynode_t* pKeyNode = _vconf_keynode_new();
2307 retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
2309 _vconf_keynode_set_keyname(pKeyNode, in_key);
2311 if (_vconf_get_key(pKeyNode) != VCONF_OK)
2312 ERR("vconf_get_dbl(%d) : %s error", getpid(), in_key);
2315 *dblval = pKeyNode->value.d;
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;
2321 ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
2324 _vconf_keynode_free(pKeyNode);
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
2336 API char *vconf_get_str(const char *in_key)
2340 retvm_if(in_key == NULL, NULL, "Invalid argument: key is null");
2342 keynode_t* pKeyNode = _vconf_keynode_new();
2343 retvm_if(pKeyNode == NULL, NULL, "key malloc fail");
2345 _vconf_keynode_set_keyname(pKeyNode, in_key);
2347 char *strval = NULL;
2348 char *tempstr = NULL;
2350 if (_vconf_get_key(pKeyNode) != VCONF_OK) {
2351 ERR("vconf_get_str(%d) : %s error", getpid(), in_key);
2354 if(pKeyNode->type == VCONF_TYPE_STRING)
2355 tempstr = pKeyNode->value.s;
2357 ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
2360 strval = strdup(tempstr);
2361 INFO("vconf_get_str(%d) : %s(%s) success", getpid(), in_key, strval);
2364 _vconf_keynode_free(pKeyNode);
2372 * This function unset given key
2373 * @param[in] in_key key
2374 * @return 0 on success, -1 on error
2376 API int vconf_unset(const char *in_key)
2380 char path[VCONF_KEY_PATH_LEN] = {0,};
2382 int err_retry = VCONF_ERROR_RETRY_CNT;
2383 int func_ret = VCONF_OK;
2385 WARN("vconf_unset: %s. THIS API(vconf_unset) WILL BE DEPRECATED", in_key);
2387 retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
2389 ret = _vconf_get_key_path(in_key, path);
2390 retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
2392 retvm_if(access(path, F_OK) == -1, VCONF_ERROR, "Error : key(%s) is not exist", in_key);
2397 ERR("vconf_unset error(%d) : %s", errno, in_key);
2398 func_ret = VCONF_ERROR;
2400 func_ret = VCONF_OK;
2403 } while(err_retry--);
2411 * This function unset given key recursively
2412 * @param[in] in_dir Directory name for removing
2413 * @return 0 on success, -1 on error
2415 API int vconf_unset_recursive(const char *in_dir)
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,};
2429 WARN("vconf_unset_recursive: %s. THIS API(vconf_unset_recursive) WILL BE DEPRECATED", in_dir);
2431 retvm_if(in_dir == NULL, VCONF_ERROR, "Invalid argument: dir path is null");
2433 ret = _vconf_get_key_path(in_dir, dirpath);
2434 retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
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);
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;
2448 while(result != NULL)
2450 if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
2454 snprintf(fullpath,VCONF_KEY_PATH_LEN, "%s/%s", dirpath, entry.d_name);
2456 ret = _vconf_path_is_dir(fullpath);
2457 if(ret != VCONF_ERROR) {
2459 rc = vconf_unset_recursive(fullpath);
2460 if(rc == VCONF_ERROR)
2461 func_ret = VCONF_ERROR;
2464 rc = remove(fullpath);
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;
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;
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;
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;
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;
2506 API int vconf_notify_key_changed(const char *in_key, vconf_callback_fn cb, void *user_data)
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);
2513 if (_vconf_kdb_add_notify(in_key, cb, user_data)) {
2514 ERR("vconf_notify_key_changed : key(%s) add notify fail", in_key);
2518 INFO("vconf_notify_key_changed : %s noti is added", in_key);
2525 API int vconf_ignore_key_changed(const char *in_key, vconf_callback_fn cb)
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);
2532 if (_vconf_kdb_del_notify(in_key, cb)) {
2533 ERR("vconf_ignore_key_changed() failed: key(%s)", in_key);
2537 INFO("vconf_ignore_key_changed : %s noti removed", in_key);
2544 API mode_t vconf_set_permission(mode_t mode)
2546 /* TODO: implement! */
2550 API int vconf_set_key_permission(const char *in_key, const mode_t mode)
2552 /* TODO: implement! */