summaryrefslogtreecommitdiff
path: root/vconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'vconf.c')
-rwxr-xr-xvconf.c2138
1 files changed, 2138 insertions, 0 deletions
diff --git a/vconf.c b/vconf.c
new file mode 100755
index 0000000..99d20c5
--- /dev/null
+++ b/vconf.c
@@ -0,0 +1,2138 @@
+/*
+ * libslp-setting
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hakjoo Ko <hakjoo.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "vconf-internals.h"
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
+#include <ctype.h>
+
+#ifndef API
+#define API __attribute__ ((visibility("default")))
+#endif
+
+#define VCONF_ERROR_RETRY_CNT 10
+#define VCONF_ERROR_RETRY_SLEEP_UTIME 5000
+
+int IN_SBOX=0;
+
+#define VCONF_MOUNT_PATH "/opt/var/kdb/db"
+#define VCONF_MOUNT_PATH_CHECK \
+do{\
+ if(!IN_SBOX) \
+ IN_SBOX = access("/opt/var/kdb/kdb_first_boot", F_OK) + 2; \
+ if(2==IN_SBOX) return 0;\
+}while(0)
+
+__thread int is_transaction;
+
+#ifdef VCONF_TIMECHECK
+double correction, startT;
+
+double set_start_time(void)
+{
+ struct timeval tv;
+ double curtime;
+
+ gettimeofday(&tv, NULL);
+ curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
+ return curtime;
+}
+
+double exec_time(double start)
+{
+ double end = set_start_time();
+ return (end - start - correction);
+}
+
+int init_time(void)
+{
+ double temp_t;
+ temp_t = set_start_time();
+ correction = exec_time(temp_t);
+
+ return 0;
+}
+#endif
+
+int _vconf_keynode_set_keyname(keynode_t *keynode, const char *keyname)
+{
+ if (keynode->keyname) free(keynode->keyname);
+ keynode->keyname = strndup(keyname, BUF_LEN);
+ retvm_if(keynode->keyname == NULL, VCONF_ERROR, "strndup Fails");
+ return VCONF_OK;
+}
+
+static inline void _vconf_keynode_set_dir(keynode_t *keynode)
+{
+ keynode->type = VCONF_TYPE_DIR;
+}
+
+static inline void _vconf_keynode_set_value_int(keynode_t *keynode, const int value)
+{
+ keynode->type = VCONF_TYPE_INT;
+ keynode->value.i = value;
+}
+
+static inline void _vconf_keynode_set_value_bool(keynode_t *keynode, const int value)
+{
+ keynode->type = VCONF_TYPE_BOOL;
+ keynode->value.b = !!value;
+}
+
+static inline void _vconf_keynode_set_value_dbl(keynode_t *keynode, const double value)
+{
+ keynode->type = VCONF_TYPE_DOUBLE;
+ keynode->value.d = value;
+}
+
+static inline void _vconf_keynode_set_value_str(keynode_t *keynode, const char *value)
+{
+ keynode->type = VCONF_TYPE_STRING;
+ keynode->value.s = strdup(value);
+}
+
+inline void _vconf_keynode_set_null(keynode_t *keynode)
+{
+ keynode->type = VCONF_TYPE_NONE;
+ //keynode->value.d = NULL;
+}
+
+static inline keynode_t *_vconf_keynode_next(keynode_t *keynode)
+{
+ return keynode->next;
+}
+
+inline keynode_t *_vconf_keynode_new(void)
+{
+ keynode_t *keynode;
+ keynode = calloc(1, sizeof(keynode_t));
+
+ return keynode;
+}
+
+inline void _vconf_keynode_free(keynode_t *keynode)
+{
+ if(keynode) {
+ if (keynode->keyname)
+ free(keynode->keyname);
+ if (keynode->type == VCONF_TYPE_STRING && keynode->value.s)
+ free(keynode->value.s);
+ free(keynode);
+ }
+}
+
+static inline keynode_t *_vconf_keylist_headnode(keylist_t *keylist)
+{
+ return keylist->head;
+}
+
+static keynode_t *_vconf_keylist_lookup(keylist_t *keylist, const char *keyname,
+ keynode_t **before_keynode)
+{
+ keynode_t *found_node, *temp_node = NULL;
+
+ found_node = _vconf_keylist_headnode(keylist);
+
+ while (found_node) {
+ if(found_node->keyname == NULL) {
+ ERR("key node has null keyname");
+ return NULL;
+ }
+
+ if (!strncmp(keyname, found_node->keyname, strlen(keyname))) {
+ if (before_keynode) {
+ *before_keynode = temp_node;
+ }
+ return found_node;
+ }
+
+ temp_node = found_node;
+ found_node = _vconf_keynode_next(found_node);
+ }
+ return NULL;
+}
+
+/*
+ * This function get Key name of the keynode.
+ * @param[in] keynode The Key
+ * @return Key Name of the keynode
+ */
+API char *vconf_keynode_get_name(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, NULL, "Invalid argument: keynode is NULL");
+ retvm_if(keynode->keyname == NULL, NULL, "The name of keynode is NULL");
+
+ return keynode->keyname;
+}
+
+/*
+ * This function get value type of the keynode.
+ * @param[in] keynode The Key
+ * @return Type of the keynode
+ */
+API int vconf_keynode_get_type(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
+
+ return keynode->type;
+}
+
+API int vconf_keynode_get_int(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
+ retvm_if(keynode->type != VCONF_TYPE_INT, VCONF_ERROR,
+ "The type(%d) of keynode(%s) is not INT", keynode->type, keynode->keyname);
+
+ return keynode->value.i;
+}
+
+API double vconf_keynode_get_dbl(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, -1.0, "Invalid argument: keynode is NULL");
+ retvm_if(keynode->type != VCONF_TYPE_DOUBLE, -1.0,
+ "The type(%d) of keynode(%s) is not DBL", keynode->type, keynode->keyname);
+
+ return keynode->value.d;
+}
+
+/*
+ * This function get Boolean value of the keynode.
+ * @param[in] keynode The Key
+ * @return Boolean value, -1 on error
+ */
+API int vconf_keynode_get_bool(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: keynode is NULL");
+ retvm_if(keynode->type != VCONF_TYPE_BOOL, VCONF_ERROR,
+ "The type(%d) of keynode(%s) is not BOOL", keynode->type, keynode->keyname);
+
+ return !!(keynode->value.b);
+}
+
+/*
+ * This function get String value of the keynode.
+ * @param[in] keynode The Key
+ * @return String value, NULL on error
+ */
+API char *vconf_keynode_get_str(keynode_t *keynode)
+{
+ retvm_if(keynode == NULL, NULL, "Invalid argument: keynode is NULL");
+ retvm_if(keynode->type != VCONF_TYPE_STRING, NULL,
+ "The type(%d) of keynode(%s) is not STR", keynode->type, keynode->keyname);
+
+ return keynode->value.s;
+}
+
+/*
+ * Allocate, initialize and return a new Keylist object.
+ * @return The pointer of New keylist, NULL on error
+ */
+API keylist_t *vconf_keylist_new(void)
+{
+ keylist_t *keylist;
+ keylist = calloc(1, sizeof(keylist_t));
+
+ return keylist;
+}
+
+/*
+ * This function rewinds the KeyList internal cursor.
+ * @param[in] keylist Key List
+ * @return 0 on success, -1 on error
+ */
+API int vconf_keylist_rewind(keylist_t *keylist)
+{
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+
+ keylist->cursor = NULL;
+
+ return 0;
+}
+
+/*
+ * A destructor for Keylist objects.
+ * @param[in] keylist Key List
+ * @return 0 on success, -1 on error
+ */
+API int vconf_keylist_free(keylist_t *keylist)
+{
+ keynode_t *keynode, *temp;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+
+ if (keylist->num) {
+ keynode = _vconf_keylist_headnode(keylist);
+ while (keynode) {
+ temp = _vconf_keynode_next(keynode);
+ _vconf_keynode_free(keynode);
+ keynode = temp;
+ }
+ }
+ free(keylist);
+ return 0;
+}
+
+/*
+ * This function look for a Keynode contained in keylist that matches keyname.
+ * @param[in] keylist Key List
+ * @param[in] keyname Key to find
+ * @param[out] return_node pointer of keynode to set
+ * @return Type of the found key
+ */
+API int
+vconf_keylist_lookup(keylist_t *keylist,
+ const char *keyname, keynode_t **return_node)
+{
+ keynode_t *found_node;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+ retvm_if(return_node == NULL, VCONF_ERROR, "Invalid argument: return_node is NULL");
+
+ found_node = _vconf_keylist_lookup(keylist, keyname, NULL);
+ if (NULL == found_node)
+ return 0;
+
+ if (return_node)
+ *return_node = found_node;
+ return found_node->type;
+}
+
+/*
+ * This function returns the next Key in a Keylist.
+ * Next key is known by the keylist internal cursor.
+ * @param[in] keylist Key List
+ * @return The next Keynode, NULL on error
+ */
+API keynode_t *vconf_keylist_nextnode(keylist_t *keylist)
+{
+ retvm_if(keylist == NULL, NULL, "Invalid argument: keylist is NULL");
+
+ if (keylist->cursor)
+ keylist->cursor = _vconf_keynode_next(keylist->cursor);
+ else
+ keylist->cursor = keylist->head;
+
+ return keylist->cursor;
+}
+
+/*
+ * This function appends a new Keynode included integer value to the keylist.
+ * If same keyname exist, the keynode will change.
+ * @param[in] keylist Key List
+ * @param[in] keyname Key
+ * @param[in] value The integer value
+ * @return Number of keynode included in the keylist, -1 on error
+ */
+API int
+vconf_keylist_add_int(keylist_t *keylist, const char *keyname, const int value)
+{
+ keynode_t *keynode = NULL, *addition = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
+ _vconf_keynode_set_value_int(keynode, value);
+ return keylist->num;
+ }
+ if ((keynode = _vconf_keylist_headnode(keylist)))
+ while (_vconf_keynode_next(keynode))
+ keynode = _vconf_keynode_next(keynode);
+
+ addition = calloc(1, sizeof(keynode_t));
+ retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
+ if (!_vconf_keynode_set_keyname(addition, keyname)) {
+ _vconf_keynode_set_value_int(addition, value);
+ if (keylist->head && NULL != keynode)
+ keynode->next = addition;
+ else
+ keylist->head = addition;
+ keylist->num += 1;
+ } else {
+ ERR("(maybe)not enought memory");
+ free(addition), addition = NULL;
+ return VCONF_ERROR;
+ }
+
+ return keylist->num;
+}
+
+/*
+ * This function appends a new Keynode included boolean value to the keylist.
+ * If same keyname exist, the keynode will change.
+ * @param[in] keylist Key List
+ * @param[in] keyname Key
+ * @param[in] value The boolean value
+ * @return Number of keynode included in the keylist, -1 on error
+ */
+API int
+vconf_keylist_add_bool(keylist_t *keylist, const char *keyname, const int value)
+{
+ keynode_t *keynode = NULL, *addition = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
+ _vconf_keynode_set_value_bool(keynode, value);
+ return keylist->num;
+ }
+ if ((keynode = _vconf_keylist_headnode(keylist)))
+ while (_vconf_keynode_next(keynode))
+ keynode = _vconf_keynode_next(keynode);
+
+ addition = calloc(1, sizeof(keynode_t));
+ retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
+ if (!_vconf_keynode_set_keyname(addition, keyname)) {
+ _vconf_keynode_set_value_bool(addition, value);
+ if (keylist->head && NULL != keynode)
+ keynode->next = addition;
+ else
+ keylist->head = addition;
+ keylist->num += 1;
+ } else {
+ ERR("(maybe)not enought memory");
+ free(addition), addition = NULL;
+ return VCONF_ERROR;
+ }
+
+ return keylist->num;
+}
+
+/*
+ * This function appends a new Keynode included double value to the keylist.
+ * If same keyname exist, the keynode will change.
+ * @param[in] keylist Key List
+ * @param[in] keyname Key
+ * @param[in] value The double value
+ * @return Number of keynode included in the keylist, -1 on error
+ */
+API int
+vconf_keylist_add_dbl(keylist_t *keylist,
+ const char *keyname, const double value)
+{
+ keynode_t *keynode = NULL, *addition = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
+ _vconf_keynode_set_value_dbl(keynode, value);
+ return keylist->num;
+ }
+ if ((keynode = _vconf_keylist_headnode(keylist)))
+ while (_vconf_keynode_next(keynode))
+ keynode = _vconf_keynode_next(keynode);
+
+ addition = calloc(1, sizeof(keynode_t));
+ retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
+ if (!_vconf_keynode_set_keyname(addition, keyname)) {
+ _vconf_keynode_set_value_dbl(addition, value);
+ if (keylist->head && NULL != keynode)
+ keynode->next = addition;
+ else
+ keylist->head = addition;
+ keylist->num += 1;
+ } else {
+ ERR("(maybe)not enought memory");
+ free(addition), addition = NULL;
+ return VCONF_ERROR;
+ }
+
+ return keylist->num;
+}
+
+/*
+ * This function appends a new Keynode included string value to the keylist.
+ * If same keyname exist, the keynode will change.
+ * @param[in] keylist Key List
+ * @param[in] keyname Key
+ * @param[in] value The pointer of string value
+ * @return Number of keynode included in the keylist, -1 on error
+ */
+API int
+vconf_keylist_add_str(keylist_t *keylist,
+ const char *keyname, const char *value)
+{
+ keynode_t *keynode = NULL, *addition = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if ((keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
+ if (VCONF_TYPE_STRING == keynode->type && keynode->value.s)
+ free(keynode->value.s);
+ _vconf_keynode_set_value_str(keynode, value);
+ return keylist->num;
+ }
+ if (NULL != (keynode = _vconf_keylist_headnode(keylist)))
+ while (_vconf_keynode_next(keynode))
+ keynode = _vconf_keynode_next(keynode);
+
+ addition = calloc(1, sizeof(keynode_t));
+ retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
+ if (!_vconf_keynode_set_keyname(addition, keyname)) {
+ _vconf_keynode_set_value_str(addition, value);
+ if (keylist->head && NULL != keynode)
+ keynode->next = addition;
+ else
+ keylist->head = addition;
+ keylist->num += 1;
+ } else {
+ ERR("(maybe)not enought memory");
+ free(addition), addition = NULL;
+ return VCONF_ERROR;
+ }
+
+ return keylist->num;
+}
+
+/*
+ * This function Appends a new Keynode to the keylist without value.
+ * Use on vconf_get()
+ * @param[in] keylist Key List
+ * @param[in] keyname Key
+ * @return Number of keynode included in the keylist, -1 on error
+ */
+API int vconf_keylist_add_null(keylist_t *keylist, const char *keyname)
+{
+ keynode_t *keynode = NULL, *addition = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if (NULL != (keynode = _vconf_keylist_lookup(keylist, keyname, NULL))) {
+ keynode->type = 0;
+ keynode->value.d = 0;
+ return keylist->num;
+ }
+ if ((keynode = _vconf_keylist_headnode(keylist)))
+ while (_vconf_keynode_next(keynode))
+ keynode = _vconf_keynode_next(keynode);
+
+ addition = calloc(1, sizeof(keynode_t));
+ retvm_if(addition == NULL, VCONF_ERROR, "(maybe)not enought memory");
+ if (!_vconf_keynode_set_keyname(addition, keyname)) {
+ if (keylist->head && keynode)
+ keynode->next = addition;
+ else
+ keylist->head = addition;
+ keylist->num += 1;
+ } else {
+ ERR("(maybe)not enought memory");
+ free(addition), addition = NULL;
+ return VCONF_ERROR;
+ }
+
+ return keylist->num;
+}
+
+/*
+ * This function remove the keynode that matches keyname.
+ * @param[in] keylist the keylist included the keyname
+ * @param[in] keyname key
+ * @return 0 on success, -1(Invalid parameter), -2(Not exist keyname in keylist) on error
+ */
+API int vconf_keylist_del(keylist_t *keylist, const char *keyname)
+{
+ keynode_t *found_node, *before_node = NULL;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+ retvm_if(keyname == NULL, VCONF_ERROR, "Invalid argument: keyname is NULL");
+
+ if ((found_node = _vconf_keylist_lookup(keylist, keyname, &before_node))) {
+ if(before_node) {
+ before_node->next = found_node->next;
+ } else {
+ /* requested key is headnode of keylist */
+ keylist->head = found_node->next;
+ }
+
+ _vconf_keynode_free(found_node);
+ } else
+ return VCONF_ERROR;
+
+ return VCONF_OK;
+}
+
+
+int _vconf_get_key_prefix(const char *keyname, int *prefix)
+{
+ if (strncmp(keyname, BACKEND_DB_PREFIX, sizeof(BACKEND_DB_PREFIX) - 1) == 0) {
+ *prefix = VCONF_BACKEND_DB;
+ } else if (0 == strncmp(keyname, BACKEND_FILE_PREFIX, sizeof(BACKEND_FILE_PREFIX) - 1)) {
+ *prefix = VCONF_BACKEND_FILE;
+ } else if (0 == strncmp(keyname, BACKEND_MEMORY_PREFIX, sizeof(BACKEND_MEMORY_PREFIX) - 1)) {
+ *prefix = VCONF_BACKEND_MEMORY;
+ } else {
+ ERR("Invalid argument: wrong prefix of key(%s)", keyname);
+ *prefix = VCONF_BACKEND_NULL;
+ return VCONF_ERROR_WRONG_PREFIX;
+ }
+
+ return VCONF_OK;
+}
+
+int _vconf_get_key_path(const char *keyname, char *path)
+{
+ if (strncmp(keyname, BACKEND_DB_PREFIX, sizeof(BACKEND_DB_PREFIX) - 1) == 0) {
+ snprintf(path, KEY_PATH, "%s%s", BACKEND_SYSTEM_DIR, keyname);
+ } else if (0 == strncmp(keyname, BACKEND_FILE_PREFIX, sizeof(BACKEND_FILE_PREFIX) - 1)) {
+ snprintf(path, KEY_PATH, "%s%s", BACKEND_SYSTEM_DIR, keyname);
+ } else if (0 == strncmp(keyname, BACKEND_MEMORY_PREFIX, sizeof(BACKEND_MEMORY_PREFIX) - 1)) {
+ snprintf(path, KEY_PATH, "%s%s", BACKEND_MEMORY_DIR, keyname);
+ } else {
+ ERR("Invalid argument: wrong prefix of key(%s)", keyname);
+ return VCONF_ERROR_WRONG_PREFIX;
+ }
+
+ return VCONF_OK;
+}
+
+#ifndef DISABLE_RUNTIME_KEY_CREATION
+static int _vconf_set_key_check_parent_dir(const char* path)
+{
+ int exists = 0;
+ struct stat stat_info;
+ char* parent;
+ char path_buf[KEY_PATH] = {0,};
+ int ret = 0;
+
+ mode_t dir_mode = 0664 | 0111;
+
+ parent = strrchr(path, '/');
+ strncpy(path_buf, path, parent-path);
+ path_buf[parent-path]=0;
+
+ exists = stat(path_buf,&stat_info);
+ if(exists){
+ if(mkdir(path_buf, dir_mode) != 0) {
+ if(errno == ENOENT) {
+ ret = _vconf_set_key_check_parent_dir((const char*)path_buf);
+ if(ret != VCONF_OK) return ret;
+ if(mkdir(path_buf, dir_mode) != 0) {
+ ERR("mkdir error(%d)", errno);
+ return VCONF_ERROR;
+ }
+ }
+ }
+ }
+
+ return VCONF_OK;
+}
+
+static int _vconf_set_key_creation(const char* path)
+{
+ int fd;
+ mode_t temp;
+ temp = umask(0000);
+ fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+ umask(temp);
+ if(fd == -1) {
+ ERR("open(rdwr,create) error\n");
+ return VCONF_ERROR;
+ }
+ close(fd);
+
+ return VCONF_OK;
+}
+#endif
+
+static int _vconf_set_file_lock(int fd, short type)
+{
+#ifdef HAVE_FCNTL_H
+ int ret = 0;
+ struct flock l;
+
+ l.l_type = type; /*Do read Lock*/
+ l.l_start= 0; /*Start at begin*/
+ l.l_whence = SEEK_SET;
+ l.l_len = 0; /*Do it with whole file*/
+ ret = fcntl(fd, F_SETLKW, &l);
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+static int _vconf_set_read_lock(int fd)
+{
+ return _vconf_set_file_lock(fd, F_RDLCK);
+}
+
+static int _vconf_set_write_lock(int fd)
+{
+ return _vconf_set_file_lock(fd, F_WRLCK);
+}
+
+static int _vconf_set_unlock(int fd)
+{
+ return _vconf_set_file_lock(fd, F_UNLCK);
+}
+
+static void _vconf_acquire_transaction_delay(int ms)
+{
+ struct timeval timeout;
+ timeout.tv_sec = ms / 1000 ;
+ timeout.tv_usec = 1000 * ( ms % 1000 );
+
+ select(0, 0, 0, 0, &timeout);
+}
+
+static int _vconf_db_begin_transaction()
+{
+ pid_t value;
+ VCONF_MOUNT_PATH_CHECK;
+
+ if(is_transaction == 0) {
+ value = getpid();
+transaction_retry:
+ if(setxattr(VCONF_MOUNT_PATH, "full_db_transaction_start", &value, sizeof(value), 0) == -1)
+ {
+ _vconf_acquire_transaction_delay(50);
+ goto transaction_retry;
+ } else {
+ is_transaction++;
+ }
+ } else {
+ is_transaction++;
+ }
+
+ return VCONF_OK;
+}
+
+static int _vconf_db_commit_transaction()
+{
+ pid_t value;
+ VCONF_MOUNT_PATH_CHECK;
+
+ retv_if(is_transaction <= 0, VCONF_ERROR);
+
+ if(is_transaction == 1) {
+ value = getpid();
+ setxattr(VCONF_MOUNT_PATH, "full_db_transaction_stop", &value, sizeof(value), 0);
+ is_transaction = 0;
+ } else {
+ is_transaction --;
+ }
+
+ return 0;
+}
+
+static int _vconf_db_rollback_transaction()
+{
+ pid_t value;
+ VCONF_MOUNT_PATH_CHECK;
+
+ retv_if(is_transaction <= 0, VCONF_ERROR);
+
+ if(is_transaction == 1) {
+ value = getpid();
+ setxattr(VCONF_MOUNT_PATH, "full_db_transaction_rb", &value, sizeof(value), 0);
+ is_transaction = 0;
+ } else {
+ is_transaction --;
+ }
+
+ return 0;
+}
+
+static int _vconf_set_key_filesys(keynode_t *keynode, int prefix)
+{
+ char path[KEY_PATH] = {0,};
+ FILE *fp = NULL;
+ int ret = -1;
+ int func_ret = VCONF_OK;
+ int err_no = 0;
+ char err_buf[100] = { 0, };
+ int is_write_error = 0;
+
+ errno = 0;
+
+ ret = _vconf_get_key_path(keynode->keyname, path);
+ retv_if(ret != VCONF_OK, ret);
+
+ if( (fp = fopen(path, "w")) == NULL ) {
+ func_ret = VCONF_ERROR_FILE_OPEN;
+ err_no = errno;
+ goto out_return;
+ }
+
+ if(prefix != VCONF_BACKEND_DB) {
+ (void) _vconf_set_write_lock(fileno(fp));
+ if(errno != 0) {
+ func_ret = VCONF_ERROR_FILE_LOCK;
+ err_no = errno;
+ goto out_close;
+ }
+ }
+
+ /* write key type */
+ ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
+ if(ret <= 0)
+ {
+ if(errno) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_WRITE;
+ goto out_unlock;
+ }
+
+ /* write key value */
+ switch(keynode->type)
+ {
+ case VCONF_TYPE_INT:
+ ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
+ if(ret <= 0) is_write_error = 1;
+ break;
+ case VCONF_TYPE_DOUBLE:
+ ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
+ if(ret <= 0) is_write_error = 1;
+ break;
+ case VCONF_TYPE_BOOL:
+ ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
+ if(ret <= 0) is_write_error = 1;
+ break;
+ case VCONF_TYPE_STRING:
+ ret = fprintf(fp,"%s",keynode->value.s);
+ if(ret < strlen(keynode->value.s)) is_write_error = 1;
+ //ret = fwrite((void *)keynode->value.s, sizeof(char), strlen(keynode->value.s), fp);
+ break;
+ default :
+ func_ret = VCONF_ERROR_WRONG_TYPE;
+ goto out_unlock;
+ }
+ if(is_write_error)
+ {
+ if(errno) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_WRITE;
+ goto out_unlock;
+ }
+
+#ifdef ENABLE_FDATASYNC
+ if(prefix == VCONF_BACKEND_FILE) {
+ fflush(fp);
+
+ ret = fdatasync(fileno(fp));
+ if(ret == -1) {
+ err_no = errno;
+ func_ret = VCONF_ERROR_FILE_SYNC;
+ }
+ }
+#endif
+
+out_unlock :
+ if(prefix != VCONF_BACKEND_DB) {
+ (void) _vconf_set_unlock(fileno(fp));
+ if(errno != 0) {
+ func_ret = VCONF_ERROR_FILE_LOCK;
+ err_no = errno;
+ goto out_close;
+ }
+ }
+
+out_close :
+ fclose(fp);
+
+out_return :
+ if(err_no != 0) {
+ strerror_r(err_no, err_buf, 100);
+ ERR("_vconf_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
+ }
+
+ return func_ret;
+}
+
+static int _vconf_set_key(keynode_t *keynode)
+{
+ int func_ret = VCONF_OK;
+ int ret = 0;
+ int is_busy_err = 0;
+ int retry = -1;
+ int prefix = 0;
+ int rc = 0;
+
+ ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
+ retv_if(ret != VCONF_OK, ret);
+
+ if(prefix == VCONF_BACKEND_DB) {
+ _vconf_db_begin_transaction();
+ }
+
+ while((ret = _vconf_set_key_filesys(keynode, prefix)) != VCONF_OK)
+ {
+ is_busy_err = 0;
+ retry++;
+
+ if(ret == VCONF_ERROR_FILE_OPEN)
+ {
+ switch (errno)
+ {
+ /* file is not exist, make path */
+#ifndef DISABLE_RUNTIME_KEY_CREATION
+ case EFAULT :
+ case ENOENT :
+ {
+ char path[KEY_PATH] = {0,};
+ rc = _vconf_get_key_path(keynode->keyname, path);
+ if(rc != VCONF_OK) {
+ ERR("_vconf_get_key_path error");
+ break;
+ }
+
+ ret = _vconf_set_key_check_parent_dir(path);
+ if(rc != VCONF_OK) {
+ ERR("_vconf_set_key_check_parent_dir error : %s", path);
+ break;
+ }
+
+ ret = _vconf_set_key_creation(path);
+ if(rc != VCONF_OK) {
+ ERR("_vconf_set_key_creation error : %s", path);
+ break;
+ }
+ INFO("%s key is created", keynode->keyname);
+ }
+#endif
+ case EAGAIN :
+ case EMFILE :
+ case ENFILE :
+ case ETXTBSY :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else if (ret == VCONF_ERROR_FILE_CHMOD)
+ {
+ switch (errno)
+ {
+ case EINTR :
+ case EBADF :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else if (ret == VCONF_ERROR_FILE_LOCK)
+ {
+ switch (errno)
+ {
+ case EBADF :
+ case EACCES :
+ case EAGAIN :
+ case ENOLCK :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else if (ret == VCONF_ERROR_FILE_WRITE)
+ {
+ switch (errno)
+ {
+ case 0 :
+ case EAGAIN :
+ case EINTR :
+ case EIO :
+ case ENOMEM :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else
+ {
+ is_busy_err = 0;
+ }
+
+ if ((is_busy_err == 1) && (retry < VCONF_ERROR_RETRY_CNT)) {
+ 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);
+ usleep((retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
+ continue;
+ } else {
+ ERR("%s : write buf error(%d). break. (%d)\n", keynode->keyname, ret, retry);
+ func_ret = VCONF_ERROR;
+ break;
+ }
+ }
+
+ if(prefix == VCONF_BACKEND_DB) {
+ if(func_ret == VCONF_ERROR) {
+ _vconf_db_rollback_transaction();
+ } else {
+ _vconf_db_commit_transaction();
+ }
+ }
+
+ return func_ret;
+}
+
+/*
+ * This function set the value of given keys
+ * @param[in] keylist the keylist which should contain changed keys
+ * @return 0 on success, -1 on error
+ */
+API int vconf_set(keylist_t *keylist)
+{
+ START_TIME_CHECK
+
+ keynode_t *got_node;
+
+ int func_ret = VCONF_OK;
+ int ret = 0;
+ int prefix = 0;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is NULL");
+
+ INFO("vconf_set (%d)START", keylist->num);
+
+ got_node = _vconf_keylist_headnode(keylist);
+
+ retvm_if(got_node == NULL, VCONF_ERROR, "Invalid argument: headnode is NULL");
+
+ ret = _vconf_get_key_prefix(got_node->keyname, &prefix);
+ retv_if(ret != VCONF_OK, ret);
+
+ if(prefix == VCONF_BACKEND_DB) {
+ _vconf_db_begin_transaction();
+ }
+
+ while (got_node != NULL) {
+ ret = _vconf_set_key(got_node);
+ if(ret != VCONF_OK) {
+ func_ret = VCONF_ERROR;
+ }
+
+ got_node = _vconf_keynode_next(got_node);
+ }
+
+ if(prefix == VCONF_BACKEND_DB) {
+ if(func_ret == VCONF_ERROR) {
+ _vconf_db_rollback_transaction();
+ } else {
+ _vconf_db_commit_transaction();
+ }
+ }
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+API int vconf_sync_key(const char *in_key)
+{
+ START_TIME_CHECK
+
+ int fd;
+ char path[KEY_PATH] = {0,};
+ int ret = -1;
+
+ ret = _vconf_get_key_path(in_key, path);
+ if(ret != VCONF_OK) return VCONF_ERROR;
+
+ fd = open(path, O_RDWR);
+ if(fd == -1) return VCONF_ERROR;
+
+ fsync(fd);
+ close(fd);
+
+ END_TIME_CHECK
+
+ return 0;
+}
+
+/*
+ * This function set the integer value of given key
+ * @param[in] in_key key
+ * @param[in] intval integer value to set
+ * @return 0 on success, -1 on error
+ */
+API int vconf_set_int(const char *in_key, const int intval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
+
+ int func_ret = VCONF_OK;
+
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
+ if(func_ret != VCONF_OK) {
+ _vconf_keynode_free(pKeyNode);
+ ERR("set key name error");
+ return VCONF_ERROR;
+ }
+ _vconf_keynode_set_value_int(pKeyNode, intval);
+
+ if (_vconf_set_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_set_int(%d) : %s(%d) error", getpid(), in_key, intval);
+ func_ret = VCONF_ERROR;
+ } else{
+ INFO("vconf_set_int(%d) : %s(%d) success", getpid(), in_key, intval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+* This function set the boolean value of given key
+* @param[in] in_key key
+* @param[in] boolval boolean value to set
+ (Integer value 1 is 'True', and 0 is 'False')
+* @return 0 on success, -1 on error
+*/
+API int vconf_set_bool(const char *in_key, const int boolval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
+ if(func_ret != VCONF_OK) {
+ _vconf_keynode_free(pKeyNode);
+ ERR("set key name error");
+ return VCONF_ERROR;
+ }
+ _vconf_keynode_set_value_bool(pKeyNode, boolval);
+
+ if (_vconf_set_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_set_bool(%d) : %s(%d) error", getpid(), in_key, boolval);
+ func_ret = VCONF_ERROR;
+ } else {
+ INFO("vconf_set_bool(%d) : %s(%d) success", getpid(), in_key, boolval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function set the double value of given key
+ * @param[in] in_key key
+ * @param[in] dblval double value to set
+ * @return 0 on success, -1 on error
+ */
+API int vconf_set_dbl(const char *in_key, const double dblval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
+ if(func_ret != VCONF_OK) {
+ _vconf_keynode_free(pKeyNode);
+ ERR("set key name error");
+ return VCONF_ERROR;
+ }
+ _vconf_keynode_set_value_dbl(pKeyNode, dblval);
+
+ if (_vconf_set_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_set_dbl(%d) : %s(%f) error", getpid(), in_key, dblval);
+ func_ret = VCONF_ERROR;
+ } else {
+ INFO("vconf_set_dbl(%d) : %s(%f) success", getpid(), in_key, dblval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function set the string value of given key
+ * @param[in] in_key key
+ * @param[in] strval string value to set
+ * @return 0 on success, -1 on error
+ */
+API int vconf_set_str(const char *in_key, const char *strval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
+ retvm_if(strval == NULL, VCONF_ERROR, "Invalid argument: value is NULL");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ func_ret = _vconf_keynode_set_keyname(pKeyNode, in_key);
+ if(func_ret != VCONF_OK) {
+ _vconf_keynode_free(pKeyNode);
+ ERR("set key name error");
+ return VCONF_ERROR;
+ }
+ _vconf_keynode_set_value_str(pKeyNode, strval);
+
+ if (_vconf_set_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_set_str(%d) : %s(%s) error", getpid(), in_key, strval);
+ func_ret = VCONF_ERROR;
+ } else {
+ INFO("vconf_set_str(%d) : %s(%s) success", getpid(), in_key, strval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+
+#ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
+/* keyFileUnserialize function of ELEKTRA */
+static int _vconf_get_key_elektra_format(keynode_t *keynode, FILE *fp)
+{
+ char version[10] = {0,};
+ char type[5] = {0,};
+ char comment[8] = {0,};
+ char file_buf[BUF_LEN] = {0,};
+ char *value = NULL;
+ int value_size = 0;
+ int err_no = 0;
+ char err_buf[100] = { 0, };
+ int func_ret = VCONF_OK;
+
+ INFO("_vconf_get_key_elektra_format start");
+
+ rewind(fp);
+
+ if (!fgets(version, sizeof(version), fp))
+ {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ err_no = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FGETS;
+ goto out_return;
+ }
+ if (strncmp(version,"RG",2)) {
+ func_ret = VCONF_ERROR_WRONG_TYPE;
+ goto out_return;
+ }
+
+ if (!fgets(type, sizeof(type), fp))
+ {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ err_no = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FGETS;
+ goto out_return;
+ }
+
+ if (!fgets(comment, sizeof(comment), fp))
+ {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ err_no = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FGETS;
+ goto out_return;
+ }
+
+ while(fgets(file_buf, sizeof(file_buf), fp))
+ {
+ if(value) {
+ value_size = value_size + strlen(file_buf);
+ value = (char *) realloc(value, value_size);
+ if(value == NULL) {
+ func_ret = VCONF_ERROR_NO_MEM;
+ break;
+ }
+ strncat(value, file_buf, strlen(file_buf));
+ } else {
+ value_size = strlen(file_buf) + 1;
+ value = (char *)malloc(value_size);
+ if(value == NULL) {
+ func_ret = VCONF_ERROR_NO_MEM;
+ break;
+ }
+ memset(value, 0x00, value_size);
+ strncpy(value, file_buf, strlen(file_buf));
+ }
+ }
+
+ if(ferror(fp)) {
+ err_no = errno;
+ func_ret = VCONF_ERROR_FILE_FGETS;
+ } else {
+ if(value) {
+ switch(atoi(type))
+ {
+ case VCONF_TYPE_INT:
+ {
+ _vconf_keynode_set_value_int(keynode, atoi(value));
+ break;
+ }
+ case VCONF_TYPE_DOUBLE:
+ {
+ _vconf_keynode_set_value_dbl(keynode, atof(value));
+ break;
+ }
+ case VCONF_TYPE_BOOL:
+ {
+ _vconf_keynode_set_value_bool(keynode, atoi(value));
+ break;
+ }
+ case VCONF_TYPE_STRING:
+ {
+ _vconf_keynode_set_value_str(keynode, value);
+ break;
+ }
+ default :
+ {
+ func_ret = VCONF_ERROR_WRONG_VALUE;
+ }
+ }
+ } else {
+ if(atoi(type) == VCONF_TYPE_STRING) {
+ _vconf_keynode_set_value_str(keynode, "");
+ } else {
+ func_ret = VCONF_ERROR_WRONG_VALUE;
+ }
+ }
+ }
+
+out_return :
+ if(err_no != 0) {
+ strerror_r(err_no, err_buf, 100);
+ ERR("_vconf_set_key_filesys(%d/%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
+ }
+
+ if(value) free(value);
+
+ return func_ret;
+}
+#endif
+
+static int _vconf_get_key_filesys(keynode_t *keynode, int prefix)
+{
+ char path[KEY_PATH] = {0,};
+ int ret = -1;
+ int func_ret = VCONF_OK;
+ char err_buf[100] = { 0, };
+ int err_no = 0;
+ int type = 0;
+ FILE *fp = NULL;
+
+ errno = 0;
+
+ ret = _vconf_get_key_path(keynode->keyname, path);
+ retv_if(ret != VCONF_OK, ret);
+
+ if( (fp = fopen(path, "r")) == NULL ) {
+ func_ret = VCONF_ERROR_FILE_OPEN;
+ err_no = errno;
+ goto out_return;
+ }
+
+ if(prefix != VCONF_BACKEND_DB) {
+ (void) _vconf_set_read_lock(fileno(fp));
+ if(errno != 0) {
+ func_ret = VCONF_ERROR_FILE_LOCK;
+ err_no = errno;
+ goto out_close;
+ }
+ }
+
+ /* read data type */
+ if(!fread((void*)&type, sizeof(int), 1, fp)) {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FREAD;
+ goto out_unlock;
+ }
+
+ /* read data value */
+ switch(type)
+ {
+ case VCONF_TYPE_INT:
+ {
+ int value_int = 0;
+ if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FREAD;
+ goto out_unlock;
+ } else {
+ _vconf_keynode_set_value_int(keynode, value_int);
+ }
+
+ break;
+ }
+ case VCONF_TYPE_DOUBLE:
+ {
+ double value_dbl = 0;
+ if(!fread((void*)&value_dbl, sizeof(double), 1, fp)) {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FREAD;
+ goto out_unlock;
+ } else {
+ _vconf_keynode_set_value_dbl(keynode, value_dbl);
+ }
+
+ break;
+ }
+ case VCONF_TYPE_BOOL:
+ {
+ int value_int = 0;
+ if(!fread((void*)&value_int, sizeof(int), 1, fp)) {
+ if(ferror(fp)) {
+ err_no = errno;
+ } else {
+ errno = EAGAIN;
+ }
+ func_ret = VCONF_ERROR_FILE_FREAD;
+ goto out_unlock;
+ } else {
+ _vconf_keynode_set_value_bool(keynode, value_int);
+ }
+
+ break;
+ }
+ case VCONF_TYPE_STRING:
+ {
+ char file_buf[BUF_LEN] = {0,};
+ char *value = NULL;
+ int value_size = 0;
+
+ while(fgets(file_buf, sizeof(file_buf), fp))
+ {
+ if(value) {
+ value_size = value_size + strlen(file_buf);
+ value = (char *) realloc(value, value_size);
+ if(value == NULL) {
+ func_ret = VCONF_ERROR_NO_MEM;
+ break;
+ }
+ strncat(value, file_buf, strlen(file_buf));
+ } else {
+ value_size = strlen(file_buf) + 1;
+ value = (char *)malloc(value_size);
+ if(value == NULL) {
+ func_ret = VCONF_ERROR_NO_MEM;
+ break;
+ }
+ memset(value, 0x00, value_size);
+ strncpy(value, file_buf, strlen(file_buf));
+ }
+ }
+
+ if(ferror(fp)) {
+ err_no = errno;
+ func_ret = VCONF_ERROR_FILE_FGETS;
+ } else {
+ if(value) {
+ _vconf_keynode_set_value_str(keynode, value);
+ } else {
+ _vconf_keynode_set_value_str(keynode, "");
+ }
+ }
+ if(value)
+ free(value);
+
+ break;
+ }
+ default :
+#ifdef SUPPORT_ELEKTRA_VALUE_FORMAT
+ func_ret = _vconf_get_key_elektra_format(keynode, fp);
+#else
+ func_ret = VCONF_ERROR_WRONG_TYPE;
+#endif
+ }
+
+out_unlock :
+ if(prefix != VCONF_BACKEND_DB) {
+ (void) _vconf_set_unlock(fileno(fp));
+ if(errno != 0) {
+ func_ret = VCONF_ERROR_FILE_LOCK;
+ err_no = errno;
+ goto out_close;
+ }
+ }
+
+out_close :
+ fclose(fp);
+
+out_return :
+ if(err_no != 0) {
+ strerror_r(err_no, err_buf, 100);
+ ERR("_vconf_get_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
+ }
+
+ return func_ret;
+}
+
+
+int _vconf_get_key(keynode_t *keynode)
+{
+ int func_ret = VCONF_OK;
+ int ret = 0;
+ int is_busy_err = 0;
+ int retry = -1;
+ int prefix = 0;
+
+ ret = _vconf_get_key_prefix(keynode->keyname, &prefix);
+ retv_if(ret != VCONF_OK, ret);
+
+ if(prefix == VCONF_BACKEND_DB) {
+ _vconf_db_begin_transaction();
+ }
+
+ while((ret = _vconf_get_key_filesys(keynode, prefix)) != VCONF_OK)
+ {
+ is_busy_err = 0;
+ retry++;
+
+ if(ret == VCONF_ERROR_FILE_OPEN)
+ {
+ switch (errno)
+ {
+ case EAGAIN :
+ case EMFILE :
+ case ETXTBSY :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else if (ret == VCONF_ERROR_FILE_LOCK)
+ {
+ switch (errno)
+ {
+ case EBADF :
+ case EACCES :
+ case EAGAIN :
+ case ENOLCK :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else if (ret == VCONF_ERROR_FILE_FREAD)
+ {
+ switch (errno)
+ {
+ case EAGAIN :
+ case EINTR :
+ case EIO :
+ {
+ is_busy_err = 1;
+ }
+ }
+ }
+ else
+ {
+ is_busy_err = 0;
+ }
+
+ if ((is_busy_err == 1) && (retry < VCONF_ERROR_RETRY_CNT)) {
+ ERR("%s : read buf error(%d). read will be retried(%d) , %d\n", keynode->keyname, ret, retry, (retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
+ usleep((retry)*VCONF_ERROR_RETRY_SLEEP_UTIME);
+ continue;
+ } else {
+ ERR("%s : read buf error(%d). break\n", keynode->keyname, ret);
+ func_ret = VCONF_ERROR;
+ break;
+ }
+ }
+
+ if(prefix == VCONF_BACKEND_DB) {
+ if(func_ret == VCONF_ERROR) {
+ _vconf_db_rollback_transaction();
+ } else {
+ _vconf_db_commit_transaction();
+ }
+ }
+
+ return func_ret;
+}
+
+static int _vconf_check_value_integrity(const void *value, int type)
+{
+ int i = 0;
+
+ if ((type == VCONF_TYPE_STRING) && (value != NULL)) {
+ return 0;
+ }
+
+ if ((value) && (strlen(value) > 0)) {
+ if ((type == VCONF_TYPE_INT) ||
+ (type == VCONF_TYPE_BOOL)||
+ (type == VCONF_TYPE_DOUBLE)) {
+ while (*(((char *)value) + i) != '\0') {
+ if ( !isdigit(*(((char *)value) + i)) ) {
+ if ((type != VCONF_TYPE_BOOL) &&
+ (*(((char *)value) + i) != '-')) {
+ if ((type == VCONF_TYPE_DOUBLE) &&
+ (*(((char *)value) + i) != '.')) {
+ ERR("ERROR : vconf value is not digit.");
+ return -1;
+ }
+ }
+ }
+ i++;
+ }
+ }
+
+ return 0;
+ } else {
+ ERR("ERROR : vconf value is NULL.");
+ return -2;
+ }
+}
+
+int _vconf_path_is_dir(char* path)
+{
+ struct stat entryInfo;
+
+ if(lstat(path, &entryInfo) == 0 ) {
+ if( S_ISDIR( entryInfo.st_mode ) ) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return VCONF_ERROR;
+ }
+}
+
+API int vconf_get(keylist_t *keylist, const char *dirpath, get_option_t option)
+{
+ DIR *dir = NULL;
+ struct dirent entry;
+ struct dirent *result = NULL;
+ char full_file_path[KEY_PATH] = {0,};
+ char file_path[KEY_PATH] = {0,};
+ char full_path[KEY_PATH] = {0,};
+ char err_buf[ERR_LEN] = {0,};
+ int rc = 0;
+ int func_ret = 0;
+ int ret = 0;
+ int is_dir = 0;
+ int prefix = 0;
+
+ keynode_t *temp_keynode;
+
+ retvm_if(keylist == NULL, VCONF_ERROR, "Invalid argument: keylist is null");
+ retvm_if(dirpath == NULL, VCONF_ERROR, "Invalid argument: dirpath is null");
+
+ temp_keynode = _vconf_keylist_headnode(keylist);
+
+ if ((NULL != temp_keynode) && (VCONF_GET_KEY != option)) {
+ ERR("Not support mode : Only VCONF_GET_KEY \
+ option support To retrieve key with keylist");
+ return VCONF_ERROR;
+ }
+
+ if(temp_keynode != NULL) {
+ while(_vconf_keynode_next(temp_keynode)) {
+ temp_keynode = _vconf_keynode_next(temp_keynode);
+ }
+ }
+
+ ret = _vconf_get_key_path(dirpath, full_path);
+ retvm_if(ret != VCONF_OK, ret, "Invalid argument: key is not valid");
+
+
+ ret = _vconf_get_key_prefix(dirpath, &prefix);
+ retv_if(ret != VCONF_OK, ret);
+
+ if(prefix == VCONF_BACKEND_DB) {
+ _vconf_db_begin_transaction();
+ }
+
+ is_dir = _vconf_path_is_dir(full_path);
+ if(is_dir == 1) {
+ if((dir=opendir(full_path)) == NULL) {
+ strerror_r(errno, err_buf, ERR_LEN);
+ ERR("ERROR : open directory(%s) fail(%s)", dirpath, err_buf);
+ return VCONF_ERROR;
+ }
+
+ if((readdir_r(dir, &entry, &result)) != 0) {
+ strerror_r(errno, err_buf, ERR_LEN);
+ ERR("ERROR : read directory(%s) fail(%s)", dirpath, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+
+ while(result != NULL)
+ {
+ if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
+ goto NEXT;
+ }
+
+ keynode_t* keynode = _vconf_keynode_new();
+ if(keynode == NULL) {
+ closedir(dir);
+ ERR("Invalid argument: key malloc fail");
+ return VCONF_ERROR;
+ }
+
+ snprintf(file_path, KEY_PATH, "%s/%s", dirpath, entry.d_name);
+ snprintf(full_file_path, KEY_PATH, "%s/%s", full_path, entry.d_name);
+
+ rc = _vconf_path_is_dir(full_file_path);
+ if(rc != VCONF_ERROR) {
+ if(rc == 1) {
+ /* directory */
+ if(option == VCONF_GET_KEY) {
+ _vconf_keynode_free(keynode);
+ goto NEXT;
+ } else {
+ _vconf_keynode_set_keyname(keynode, file_path);
+ _vconf_keynode_set_dir(keynode);
+ }
+ } else {
+ _vconf_keynode_set_keyname(keynode, file_path);
+ _vconf_get_key(keynode);
+ }
+
+ if (keylist->head && temp_keynode != NULL)
+ {
+ temp_keynode->next = keynode;
+ temp_keynode = _vconf_keynode_next(temp_keynode);
+ }
+ else {
+ keylist->head = keynode;
+ temp_keynode = keylist->head;
+ }
+ keylist->num += 1;
+ } else {
+ _vconf_keynode_free(keynode);
+
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : get path(%s) fail(%s)", file_path, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+
+ NEXT:
+ if((readdir_r(dir, &entry, &result)) != 0) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : read directory(%s) fail(%s)", dirpath, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+ }
+
+ if((closedir(dir)) != 0) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : close directory(%s) fail(%s)", dirpath, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+ } else if(is_dir == 0) {
+ keynode_t* keynode = _vconf_keynode_new();
+ retvm_if(keynode == NULL, VCONF_ERROR, "Invalid argument: key malloc fail");
+
+ _vconf_keynode_set_keyname(keynode, dirpath);
+
+ _vconf_get_key(keynode);
+
+ if (keylist->head && temp_keynode != NULL) {
+ temp_keynode->next = keynode;
+ //temp_keynode = _vconf_keynode_next(temp_keynode);
+ } else {
+ keylist->head = keynode;
+ temp_keynode = keylist->head;
+ }
+ keylist->num += 1;
+ } else {
+ return VCONF_ERROR;
+ }
+ vconf_keylist_rewind(keylist);
+
+ if(prefix == VCONF_BACKEND_DB) {
+ if(func_ret == VCONF_ERROR) {
+ _vconf_db_rollback_transaction();
+ } else {
+ _vconf_db_commit_transaction();
+ }
+ }
+
+ return func_ret;
+}
+
+/*
+ * This function get the integer value of given key
+ * @param[in] in_key key
+ * @param[out] intval output buffer
+ * @return 0 on success, -1 on error
+ */
+API int vconf_get_int(const char *in_key, int *intval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+ retvm_if(intval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ _vconf_keynode_set_keyname(pKeyNode, in_key);
+
+ if (_vconf_get_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_get_int(%d) : %s error", getpid(), in_key);
+ func_ret = VCONF_ERROR;
+ } else {
+ *intval = vconf_keynode_get_int(pKeyNode);
+ INFO("vconf_get_int(%d) : %s(%d) success", getpid(), in_key, *intval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function get the boolean value of given key
+ * @param[in] in_key key
+ * @param[out] boolval output buffer
+ * @return 0 on success, -1 on error
+ */
+API int vconf_get_bool(const char *in_key, int *boolval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+ retvm_if(boolval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ _vconf_keynode_set_keyname(pKeyNode, in_key);
+
+ if (_vconf_get_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_get_bool(%d) : %s error", getpid(), in_key);
+ func_ret = VCONF_ERROR;
+ } else {
+ *boolval = vconf_keynode_get_bool(pKeyNode);
+ INFO("vconf_get_bool(%d) : %s(%d) success", getpid(), in_key, *boolval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function get the double value of given key
+ * @param[in] in_key key
+ * @param[out] dblval output buffer
+ * @return 0 on success, -1 on error
+ */
+API int vconf_get_dbl(const char *in_key, double *dblval)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+ retvm_if(dblval == NULL, VCONF_ERROR, "Invalid argument: output buffer is null");
+
+ int func_ret = VCONF_OK;
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, VCONF_ERROR, "key malloc fail");
+
+ _vconf_keynode_set_keyname(pKeyNode, in_key);
+
+ if (_vconf_get_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_get_dbl(%d) : %s error", getpid(), in_key);
+ func_ret = VCONF_ERROR;
+ } else {
+ *dblval = vconf_keynode_get_dbl(pKeyNode);
+ INFO("vconf_get_dbl(%d) : %s(%f) success", getpid(), in_key, *dblval);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function get the string value of given key
+ * @param[in] in_key key
+ * @return pointer of key value on success, NULL on error
+ */
+API char *vconf_get_str(const char *in_key)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, NULL, "Invalid argument: key is null");
+
+ keynode_t* pKeyNode = _vconf_keynode_new();
+ retvm_if(pKeyNode == NULL, NULL, "key malloc fail");
+
+ _vconf_keynode_set_keyname(pKeyNode, in_key);
+
+ char *strval = NULL;
+ char *tempstr = NULL;
+
+ if (_vconf_get_key(pKeyNode) != VCONF_OK) {
+ ERR("vconf_get_str(%d) : %s error", getpid(), in_key);
+ } else {
+ tempstr = vconf_keynode_get_str(pKeyNode);
+ if(tempstr)
+ strval = strdup(tempstr);
+ INFO("vconf_get_str(%d) : %s success", getpid(), in_key);
+ }
+
+ _vconf_keynode_free(pKeyNode);
+
+ END_TIME_CHECK
+
+ return strval;
+}
+
+/*
+ * This function unset given key
+ * @param[in] in_key key
+ * @return 0 on success, -1 on error
+ */
+API int vconf_unset(const char *in_key)
+{
+ START_TIME_CHECK
+
+ char path[KEY_PATH] = {0,};
+ int ret = -1;
+ int err_retry = VCONF_ERROR_RETRY_CNT;
+ int func_ret = VCONF_OK;
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+
+ ret = _vconf_get_key_path(in_key, path);
+ retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
+
+ do {
+ ret = remove(path);
+ if(ret == -1) {
+ ERR("vconf_unset error(%d) : %s", errno, in_key);
+ func_ret = VCONF_ERROR;
+ } else {
+ func_ret = VCONF_OK;
+ break;
+ }
+ } while(err_retry--);
+
+ INFO("vconf_unset success : %s", in_key);
+
+ END_TIME_CHECK
+
+ return func_ret;
+}
+
+/*
+ * This function unset given key recursively
+ * @param[in] in_dir Directory name for removing
+ * @return 0 on success, -1 on error
+ */
+API int vconf_unset_recursive(const char *in_dir)
+{
+ START_TIME_CHECK
+
+ DIR *dir = NULL;
+ struct dirent entry;
+ struct dirent *result = NULL;
+ char fullpath[KEY_PATH] = {0,};
+ char dirpath[KEY_PATH] = {0,};
+ char err_buf[ERR_LEN] = {0,};
+ int rc = 0;
+ int func_ret = 0;
+ int ret = 0;
+
+ retvm_if(in_dir == NULL, VCONF_ERROR, "Invalid argument: dir path is null");
+
+ ret = _vconf_get_key_path(in_dir, dirpath);
+ retvm_if(ret != VCONF_OK, VCONF_ERROR, "Invalid argument: key is not valid");
+
+ if((dir=opendir(dirpath)) == NULL) {
+ strerror_r(errno, err_buf, ERR_LEN);
+ ERR("ERROR : open directory(%s) fail(%s)", in_dir, err_buf);
+ return VCONF_ERROR;
+ }
+
+ if((readdir_r(dir, &entry, &result)) != 0) {
+ strerror_r(errno, err_buf, ERR_LEN);
+ ERR("ERROR : read directory(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+
+ while(result != NULL)
+ {
+ if(( strcmp( entry.d_name, ".") == 0 ) || ( strcmp( entry.d_name, "..") == 0 )) {
+ goto NEXT;
+ }
+
+ snprintf(fullpath,KEY_PATH, "%s/%s", dirpath, entry.d_name);
+
+ ret = _vconf_path_is_dir(fullpath);
+ if(ret != VCONF_ERROR) {
+ if(ret == 1) {
+ rc = vconf_unset_recursive(fullpath);
+ if(rc == VCONF_ERROR)
+ func_ret = VCONF_ERROR;
+ }
+
+ rc = remove(fullpath);
+ if(rc == -1) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+ } else {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+NEXT:
+ if((readdir_r(dir, &entry, &result)) != 0) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : read directory(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+ }
+
+ if((closedir(dir)) != 0) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : close directory(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+#if 0
+ if(func_ret == VCONF_OK) {
+ if((remove(in_dir)) == -1) {
+ memset(err_buf, 0x00, sizeof(err_buf));
+ strerror_r(errno, err_buf, sizeof(err_buf));
+ ERR("ERROR : remove path(%s) fail(%s)", in_dir, err_buf);
+ func_ret = VCONF_ERROR;
+ }
+ }
+#endif
+
+ return func_ret;
+}
+
+API int vconf_notify_key_changed(const char *in_key, vconf_callback_fn cb, void *user_data)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+ retvm_if(cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
+
+ if (_vconf_kdb_add_notify(in_key, cb, user_data)) {
+ ERR("vconf_notify_key_changed : key(%s) add notify fail", in_key);
+ return VCONF_ERROR;
+ }
+
+ INFO("vconf_notify_key_changed : %s noti is added", in_key);
+
+ END_TIME_CHECK
+
+ return VCONF_OK;
+}
+
+API int vconf_ignore_key_changed(const char *in_key, vconf_callback_fn cb)
+{
+ START_TIME_CHECK
+
+ retvm_if(in_key == NULL, VCONF_ERROR, "Invalid argument: key is null");
+ retvm_if(cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
+
+ if (_vconf_kdb_del_notify(in_key, cb)) {
+ ERR("vconf_ignore_key_changed() failed: key(%s)", in_key);
+ return VCONF_ERROR;
+ }
+
+ INFO("vconf_ignore_key_changed : %s noti removed", in_key);
+
+ END_TIME_CHECK
+
+ return VCONF_OK;
+}
+
+API mode_t vconf_set_permission(mode_t mode)
+{
+ /* TODO: implement! */
+ return mode;
+}
+
+API int vconf_set_key_permission(const char *in_key, const mode_t mode)
+{
+ /* TODO: implement! */
+ return 0;
+}
+