2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <sys/xattr.h>
30 #include <app_preference.h>
31 #include <app_preference_internal.h>
32 #include <app_common.h>
34 #include <sys/syscall.h>
38 #define API __attribute__ ((visibility("default")))
41 #define PREFERENCE_ERROR_RETRY_CNT 7
42 #define PREFERENCE_ERROR_RETRY_SLEEP_UTIME 10000
46 static int g_posix_errno;
47 static int g_preference_errno;
48 static char *g_pref_dir_path = NULL;
50 enum preference_op_t {
51 PREFERENCE_OP_GET = 0,
55 #ifdef PREFERENCE_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 char* _preference_get_pref_dir_path()
86 char *app_data_path = NULL;
88 if (!g_pref_dir_path) {
89 g_pref_dir_path = (char *)malloc(PREFERENCE_KEY_PATH_LEN + 1);
91 if ((app_data_path = app_get_data_path()) == NULL) {
92 ERR("IO_ERROR(0x%08x) : fail to get data directory", PREFERENCE_ERROR_IO_ERROR);
93 free(g_pref_dir_path);
94 g_pref_dir_path = NULL;
98 snprintf(g_pref_dir_path, PREFERENCE_KEY_PATH_LEN, "%s%s", app_data_path, PREF_DIR);
99 INFO("pref_dir_path: %s", g_pref_dir_path);
102 return g_pref_dir_path;
105 int _preference_keynode_set_keyname(keynode_t *keynode, const char *keyname)
107 if (keynode->keyname) free(keynode->keyname);
108 keynode->keyname = strndup(keyname, PREFERENCE_KEY_PATH_LEN);
109 retvm_if(keynode->keyname == NULL, PREFERENCE_ERROR_IO_ERROR, "strndup Fails");
110 return PREFERENCE_ERROR_NONE;
113 static inline void _preference_keynode_set_value_int(keynode_t *keynode, const int value)
115 keynode->type = PREFERENCE_TYPE_INT;
116 keynode->value.i = value;
119 static inline void _preference_keynode_set_value_boolean(keynode_t *keynode, const int value)
121 keynode->type = PREFERENCE_TYPE_BOOLEAN;
122 keynode->value.b = !!value;
125 static inline void _preference_keynode_set_value_double(keynode_t *keynode, const double value)
127 keynode->type = PREFERENCE_TYPE_DOUBLE;
128 keynode->value.d = value;
131 static inline void _preference_keynode_set_value_string(keynode_t *keynode, const char *value)
133 keynode->type = PREFERENCE_TYPE_STRING;
134 keynode->value.s = strdup(value);
137 inline keynode_t *_preference_keynode_new(void)
140 keynode = calloc(1, sizeof(keynode_t));
145 inline void _preference_keynode_free(keynode_t *keynode)
148 if (keynode->keyname)
149 free(keynode->keyname);
150 if (keynode->type == PREFERENCE_TYPE_STRING && keynode->value.s)
151 free(keynode->value.s);
156 int _preference_get_key_name(const char *keyfile, char *keyname)
159 char convert_key[PATH_MAX] = {0,};
160 guchar *key_name = NULL;
161 gsize key_path_len = 0;
163 strncpy(convert_key, keyfile, PATH_MAX - 1);
165 for (i = 0; i < strlen(convert_key); i++) {
166 switch (convert_key[i]) {
167 case PREF_KEYNAME_C_DOT:
168 convert_key[i] = PREF_KEYNAME_C_PAD;
170 case PREF_KEYNAME_C_UNDERSCORE:
171 convert_key[i] = PREF_KEYNAME_C_PLUS;
173 case PREF_KEYNAME_C_HYPHEN:
174 convert_key[i] = PREF_KEYNAME_C_SLASH;
181 key_name = g_base64_decode((const gchar *)convert_key, &key_path_len);
182 snprintf(keyname, PREFERENCE_KEY_PATH_LEN-1, "%s", key_name);
185 return PREFERENCE_ERROR_NONE;
188 int _preference_get_key_path(keynode_t *keynode, char *path)
191 const char *key = NULL;
192 char *keyname = keynode->keyname;
195 ERR("keyname is null");
196 return PREFERENCE_ERROR_WRONG_PREFIX;
199 char *convert_key = NULL;
200 char *pref_dir_path = NULL;
202 convert_key = g_base64_encode((const guchar *)keyname, strlen(keyname));
204 pref_dir_path = _preference_get_pref_dir_path();
205 if (!pref_dir_path) {
206 LOGE("_preference_get_pref_dir_path() failed.");
208 return PREFERENCE_ERROR_IO_ERROR;
211 for (i = 0; i < strlen(convert_key); i++) {
212 switch (convert_key[i]) {
213 case PREF_KEYNAME_C_PAD:
214 convert_key[i] = PREF_KEYNAME_C_DOT;
216 case PREF_KEYNAME_C_PLUS:
217 convert_key[i] = PREF_KEYNAME_C_UNDERSCORE;
219 case PREF_KEYNAME_C_SLASH:
220 convert_key[i] = PREF_KEYNAME_C_HYPHEN;
227 key = (const char*)convert_key;
229 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, key);
232 return PREFERENCE_ERROR_NONE;
235 static int _preference_set_key_check_pref_dir()
237 char *pref_dir_path = NULL;
238 mode_t dir_mode = 0664 | 0111;
240 pref_dir_path = _preference_get_pref_dir_path();
241 if (!pref_dir_path) {
242 LOGE("_preference_get_pref_dir_path() failed.");
243 return PREFERENCE_ERROR_IO_ERROR;
246 if (access(pref_dir_path, F_OK) < 0) {
247 if (mkdir(pref_dir_path, dir_mode) < 0) {
248 ERR("mkdir() failed(%d/%s)", errno, strerror(errno));
249 return PREFERENCE_ERROR_IO_ERROR;
253 return PREFERENCE_ERROR_NONE;
256 static int _preference_set_key_creation(const char* path)
261 fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
265 ERR("open(rdwr,create) error: %d(%s)", errno, strerror(errno));
266 return PREFERENCE_ERROR_IO_ERROR;
270 return PREFERENCE_ERROR_NONE;
273 static int _preference_set_file_lock(int fd, short type)
278 l.l_start= 0; /*Start at begin*/
279 l.l_whence = SEEK_SET;
280 l.l_len = 0; /*Do it with whole file*/
282 return fcntl(fd, F_SETLK, &l);
285 static int _preference_get_pid_of_file_lock_owner(int fd, short type)
290 l.l_start= 0; /*Start at begin*/
291 l.l_whence = SEEK_SET;
292 l.l_len = 0; /*Do it with whole file*/
294 if(fcntl(fd, F_GETLK, &l) < 0) {
295 WARN("error in getting lock info");
299 if(l.l_type == F_UNLCK)
306 static int _preference_set_read_lock(int fd)
308 return _preference_set_file_lock(fd, F_RDLCK);
311 static int _preference_set_write_lock(int fd)
313 return _preference_set_file_lock(fd, F_WRLCK);
316 static int _preference_set_unlock(int fd)
318 return _preference_set_file_lock(fd, F_UNLCK);
321 static void _preference_log_subject_label(void)
325 char smack_label[256] = {0,};
326 char curren_path[256] = {0,};
329 tid = (int)syscall(SYS_gettid);
330 snprintf(curren_path, sizeof(curren_path)-1, "/proc/%d/attr/current", tid);
331 fd = open(curren_path, O_RDONLY);
333 LOGE("fail to open self current attr (err: %s)", strerror(errno));
337 ret = read(fd, smack_label, sizeof(smack_label)-1);
340 LOGE("fail to open self current attr (err: %s)", strerror(errno));
344 ERR("current(%d) subject label : %s", tid, smack_label);
349 static int _preference_check_retry_err(keynode_t *keynode, int preference_errno, int io_errno, int op_type)
353 if (preference_errno == PREFERENCE_ERROR_FILE_OPEN)
359 if(op_type == PREFERENCE_OP_SET)
362 char path[PATH_MAX] = {0,};
363 rc = _preference_get_key_path(keynode, path);
364 if (rc != PREFERENCE_ERROR_NONE) {
365 ERR("_preference_get_key_path error");
366 _preference_log_subject_label();
370 rc = _preference_set_key_check_pref_dir();
371 if (rc != PREFERENCE_ERROR_NONE) {
372 ERR("_preference_set_key_check_pref_dir() failed.");
373 _preference_log_subject_label();
377 rc = _preference_set_key_creation(path);
378 if (rc != PREFERENCE_ERROR_NONE) {
379 ERR("_preference_set_key_creation error : %s", path);
380 _preference_log_subject_label();
383 INFO("%s key is created", keynode->keyname);
391 _preference_log_subject_label();
403 else if (preference_errno == PREFERENCE_ERROR_FILE_CHMOD)
414 else if (preference_errno == PREFERENCE_ERROR_FILE_LOCK)
426 else if (preference_errno == PREFERENCE_ERROR_FILE_WRITE)
440 else if (preference_errno == PREFERENCE_ERROR_FILE_FREAD)
457 if (is_busy_err == 1) {
462 ERR("key(%s), check retry err: %d/(%d/%s).",keynode->keyname, preference_errno, io_errno, strerror(io_errno));
467 static int _preference_set_key_filesys(keynode_t *keynode, int *io_errno)
469 char path[PATH_MAX] = {0,};
472 int func_ret = PREFERENCE_ERROR_NONE;
474 char err_buf[100] = { 0, };
475 int is_write_error = 0;
481 func_ret = PREFERENCE_ERROR_NONE;
483 ret = _preference_get_key_path(keynode, path);
484 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
486 if( (fp = fopen(path, "r+")) == NULL ) {
487 func_ret = PREFERENCE_ERROR_FILE_OPEN;
495 func_ret = PREFERENCE_ERROR_NONE;
497 ret = _preference_set_write_lock(fileno(fp));
499 func_ret = PREFERENCE_ERROR_FILE_LOCK;
501 ERR("file(%s) lock owner(%d)",
503 _preference_get_pid_of_file_lock_owner(fileno(fp), F_WRLCK));
508 ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
512 LOGW("number of written items is 0. try again");
516 func_ret = PREFERENCE_ERROR_FILE_WRITE;
520 /* write key value */
521 switch(keynode->type)
523 case PREFERENCE_TYPE_INT:
524 ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
525 if(ret <= 0) is_write_error = 1;
527 case PREFERENCE_TYPE_DOUBLE:
528 ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
529 if(ret <= 0) is_write_error = 1;
531 case PREFERENCE_TYPE_BOOLEAN:
532 ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
533 if(ret <= 0) is_write_error = 1;
535 case PREFERENCE_TYPE_STRING:
536 ret = fprintf(fp,"%s",keynode->value.s);
537 if(ret < strlen(keynode->value.s)) is_write_error = 1;
538 if (ftruncate(fileno(fp), ret) == -1) {
543 func_ret = PREFERENCE_ERROR_WRONG_TYPE;
549 LOGW("number of written items is 0. try again");
553 func_ret = PREFERENCE_ERROR_FILE_WRITE;
560 ret = _preference_set_unlock(fileno(fp));
562 func_ret = PREFERENCE_ERROR_FILE_LOCK;
568 if (func_ret != PREFERENCE_ERROR_NONE)
570 strerror_r(err_no, err_buf, 100);
571 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_SET))
573 if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT)
575 WARN("_preference_set_key_filesys(%d-%s) step(%d) failed(%d / %s) retry(%d)", keynode->type, keynode->keyname, func_ret, err_no, err_buf, retry_cnt);
577 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
586 ERR("_preference_set_key_filesys(%d-%s) step(%d) faild(%d / %s) over the retry count.",
587 keynode->type, keynode->keyname, func_ret, err_no, err_buf);
592 ERR("_preference_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
596 DBG("_preference_set_key_filesys ok with retry cnt(%d)", retry_cnt);
602 if(func_ret == PREFERENCE_ERROR_NONE)
604 ret = fdatasync(fileno(fp));
607 func_ret = PREFERENCE_ERROR_FILE_SYNC;
617 static int _preference_set_key(keynode_t *keynode)
621 char err_buf[100] = { 0, };
623 ret = _preference_set_key_filesys(keynode, &io_errno);
624 if (ret == PREFERENCE_ERROR_NONE) {
625 g_posix_errno = PREFERENCE_ERROR_NONE;
626 g_preference_errno = PREFERENCE_ERROR_NONE;
628 strerror_r(io_errno, err_buf, 100);
629 ERR("_preference_set_key(%s) step(%d) failed(%d / %s)", keynode->keyname, ret, io_errno, err_buf);
630 g_posix_errno = io_errno;
631 g_preference_errno = ret;
639 * This function set the integer value of given key
641 * @param[in] intval integer value to set
642 * @return 0 on success, -1 on error
644 API int preference_set_int(const char *key, int intval)
648 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
650 int func_ret = PREFERENCE_ERROR_NONE;
652 keynode_t* pKeyNode = _preference_keynode_new();
653 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
655 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
656 if (func_ret != PREFERENCE_ERROR_NONE) {
657 ERR("set key name error");
658 _preference_keynode_free(pKeyNode);
659 return PREFERENCE_ERROR_IO_ERROR;
661 _preference_keynode_set_value_int(pKeyNode, intval);
663 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
664 ERR("preference_set_int(%d) : key(%s/%d) error", getpid(), key, intval);
665 func_ret = PREFERENCE_ERROR_IO_ERROR;
667 INFO("%s(%d) success", key, intval);
670 _preference_keynode_free(pKeyNode);
678 * This function set the boolean value of given key
680 * @param[in] boolval boolean value to set
681 (Integer value 1 is 'True', and 0 is 'False')
682 * @return 0 on success, -1 on error
684 API int preference_set_boolean(const char *key, bool boolval)
688 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
690 int func_ret = PREFERENCE_ERROR_NONE;
691 keynode_t* pKeyNode = _preference_keynode_new();
692 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
694 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
695 if (func_ret != PREFERENCE_ERROR_NONE) {
696 ERR("set key name error");
697 _preference_keynode_free(pKeyNode);
698 return PREFERENCE_ERROR_IO_ERROR;
700 _preference_keynode_set_value_boolean(pKeyNode, boolval);
702 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
703 ERR("preference_set_boolean(%d) : key(%s/%d) error", getpid(), key, boolval);
704 func_ret = PREFERENCE_ERROR_IO_ERROR;
706 INFO("%s(%d) success", key, boolval);
709 _preference_keynode_free(pKeyNode);
717 * This function set the double value of given key
719 * @param[in] dblval double value to set
720 * @return 0 on success, -1 on error
722 API int preference_set_double(const char *key, double dblval)
726 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
728 int func_ret = PREFERENCE_ERROR_NONE;
729 keynode_t* pKeyNode = _preference_keynode_new();
730 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
732 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
733 if (func_ret != PREFERENCE_ERROR_NONE) {
734 ERR("set key name error");
735 _preference_keynode_free(pKeyNode);
736 return PREFERENCE_ERROR_IO_ERROR;
738 _preference_keynode_set_value_double(pKeyNode, dblval);
740 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
741 ERR("preference_set_double(%d) : key(%s/%f) error", getpid(), key, dblval);
742 func_ret = PREFERENCE_ERROR_IO_ERROR;
744 INFO("%s(%f) success", key, dblval);
747 _preference_keynode_free(pKeyNode);
755 * This function set the string value of given key
757 * @param[in] strval string value to set
758 * @return 0 on success, -1 on error
760 API int preference_set_string(const char *key, const char *strval)
764 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
765 retvm_if(strval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: value is NULL");
767 int func_ret = PREFERENCE_ERROR_NONE;
768 keynode_t* pKeyNode = _preference_keynode_new();
769 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
771 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
772 if (func_ret != PREFERENCE_ERROR_NONE) {
773 ERR("set key name error");
774 _preference_keynode_free(pKeyNode);
775 return PREFERENCE_ERROR_IO_ERROR;
777 _preference_keynode_set_value_string(pKeyNode, strval);
779 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
780 ERR("preference_set_string(%d) : key(%s/%s) error", getpid(), key, strval);
781 func_ret = PREFERENCE_ERROR_IO_ERROR;
783 INFO("%s(%s) success", key, strval);
786 _preference_keynode_free(pKeyNode);
793 static int _preference_get_key_filesys(keynode_t *keynode, int* io_errno)
795 char path[PATH_MAX] = {0,};
797 int func_ret = PREFERENCE_ERROR_NONE;
798 char err_buf[100] = { 0, };
807 func_ret = PREFERENCE_ERROR_NONE;
809 ret = _preference_get_key_path(keynode, path);
810 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
812 if( (fp = fopen(path, "r")) == NULL ) {
813 func_ret = PREFERENCE_ERROR_FILE_OPEN;
820 func_ret = PREFERENCE_ERROR_NONE;
822 ret = _preference_set_read_lock(fileno(fp));
824 func_ret = PREFERENCE_ERROR_FILE_LOCK;
831 read_size = fread((void*)&type, sizeof(int), 1, fp);
832 if((read_size <= 0) || (read_size > sizeof(int))) {
834 LOGW("number of read items for type is 0 with false ferror. err : %d", errno);
838 func_ret = PREFERENCE_ERROR_FILE_FREAD;
842 /* read data value */
845 case PREFERENCE_TYPE_INT:
848 read_size = fread((void*)&value_int, sizeof(int), 1, fp);
849 if((read_size <= 0) || (read_size > sizeof(int))) {
851 LOGW("number of read items for value is wrong. err : %d", errno);
854 func_ret = PREFERENCE_ERROR_FILE_FREAD;
857 _preference_keynode_set_value_int(keynode, value_int);
862 case PREFERENCE_TYPE_DOUBLE:
864 double value_dbl = 0;
865 read_size = fread((void*)&value_dbl, sizeof(double), 1, fp);
866 if((read_size <= 0) || (read_size > sizeof(double))) {
868 LOGW("number of read items for value is wrong. err : %d", errno);
871 func_ret = PREFERENCE_ERROR_FILE_FREAD;
874 _preference_keynode_set_value_double(keynode, value_dbl);
879 case PREFERENCE_TYPE_BOOLEAN:
882 read_size = fread((void*)&value_int, sizeof(int), 1, fp);
883 if((read_size <= 0) || (read_size > sizeof(int))) {
885 LOGW("number of read items for value is wrong. err : %d", errno);
888 func_ret = PREFERENCE_ERROR_FILE_FREAD;
891 _preference_keynode_set_value_boolean(keynode, value_int);
896 case PREFERENCE_TYPE_STRING:
898 char file_buf[BUF_LEN] = {0,};
902 while(fgets(file_buf, sizeof(file_buf), fp))
905 value_size = value_size + strlen(file_buf);
906 value = (char *) realloc(value, value_size);
908 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
911 strncat(value, file_buf, strlen(file_buf));
913 value_size = strlen(file_buf) + 1;
914 value = (char *)malloc(value_size);
916 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
919 memset(value, 0x00, value_size);
920 strncpy(value, file_buf, strlen(file_buf));
926 func_ret = PREFERENCE_ERROR_FILE_FGETS;
929 _preference_keynode_set_value_string(keynode, value);
931 _preference_keynode_set_value_string(keynode, "");
940 func_ret = PREFERENCE_ERROR_WRONG_TYPE;
944 ret = _preference_set_unlock(fileno(fp));
946 func_ret = PREFERENCE_ERROR_FILE_LOCK;
953 if (func_ret != PREFERENCE_ERROR_NONE) {
954 strerror_r(err_no, err_buf, 100);
956 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_GET)) {
957 if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT) {
959 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
967 ERR("_preference_get_key_filesys(%s) step(%d) faild(%d / %s) over the retry count.",
968 keynode->keyname, func_ret, err_no, err_buf);
981 int _preference_get_key(keynode_t *keynode)
985 char err_buf[100] = {0,};
987 ret = _preference_get_key_filesys(keynode, &io_errno);
988 if (ret == PREFERENCE_ERROR_NONE) {
989 g_posix_errno = PREFERENCE_ERROR_NONE;
990 g_preference_errno = PREFERENCE_ERROR_NONE;
993 if (io_errno == ENOENT)
994 ret = PREFERENCE_ERROR_NO_KEY;
996 ret = PREFERENCE_ERROR_IO_ERROR;
998 strerror_r(io_errno, err_buf, 100);
999 ERR("_preference_get_key(%s) step(%d) failed(%d / %s)\n", keynode->keyname, ret, io_errno, err_buf);
1000 g_posix_errno = io_errno;
1001 g_preference_errno = ret;
1009 * This function get the integer value of given key
1010 * @param[in] key key
1011 * @param[out] intval output buffer
1012 * @return 0 on success, -1 on error
1014 API int preference_get_int(const char *key, int *intval)
1018 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1019 retvm_if(intval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1021 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1022 keynode_t* pKeyNode = _preference_keynode_new();
1023 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1025 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1026 if (func_ret != PREFERENCE_ERROR_NONE) {
1027 ERR("set key name error");
1028 _preference_keynode_free(pKeyNode);
1029 return PREFERENCE_ERROR_IO_ERROR;
1032 func_ret = _preference_get_key(pKeyNode);
1033 if (func_ret != PREFERENCE_ERROR_NONE) {
1034 ERR("preference_get_int(%d) : key(%s) error", getpid(), key);
1036 *intval = pKeyNode->value.i;
1037 if (pKeyNode->type == PREFERENCE_TYPE_INT) {
1038 INFO("%s(%d) success", key, *intval);
1039 func_ret = PREFERENCE_ERROR_NONE;
1041 ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
1042 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1046 _preference_keynode_free(pKeyNode);
1054 * This function get the boolean value of given key
1055 * @param[in] key key
1056 * @param[out] boolval output buffer
1057 * @return 0 on success, -1 on error
1059 API int preference_get_boolean(const char *key, bool *boolval)
1063 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1064 retvm_if(boolval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1066 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1067 keynode_t* pKeyNode = _preference_keynode_new();
1068 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1070 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1071 if (func_ret != PREFERENCE_ERROR_NONE) {
1072 ERR("set key name error");
1073 _preference_keynode_free(pKeyNode);
1074 return PREFERENCE_ERROR_IO_ERROR;
1077 func_ret = _preference_get_key(pKeyNode);
1079 if (func_ret != PREFERENCE_ERROR_NONE) {
1080 ERR("preference_get_boolean(%d) : %s error", getpid(), key);
1082 *boolval = !!(pKeyNode->value.b);
1083 if (pKeyNode->type == PREFERENCE_TYPE_BOOLEAN) {
1084 INFO("%s(%d) success", key, *boolval);
1085 func_ret = PREFERENCE_ERROR_NONE;
1087 ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
1088 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1092 _preference_keynode_free(pKeyNode);
1100 * This function get the double value of given key
1101 * @param[in] key key
1102 * @param[out] dblval output buffer
1103 * @return 0 on success, -1 on error
1105 API int preference_get_double(const char *key, double *dblval)
1109 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1110 retvm_if(dblval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1112 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1113 keynode_t* pKeyNode = _preference_keynode_new();
1114 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1116 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1117 if (func_ret != PREFERENCE_ERROR_NONE) {
1118 ERR("set key name error");
1119 _preference_keynode_free(pKeyNode);
1120 return PREFERENCE_ERROR_IO_ERROR;
1123 func_ret = _preference_get_key(pKeyNode);
1125 if (func_ret != PREFERENCE_ERROR_NONE) {
1126 ERR("preference_get_double(%d) : %s error", getpid(), key);
1128 *dblval = pKeyNode->value.d;
1129 if (pKeyNode->type == PREFERENCE_TYPE_DOUBLE) {
1130 INFO("%s(%f) success", key, *dblval);
1131 func_ret = PREFERENCE_ERROR_NONE;
1133 ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
1134 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1138 _preference_keynode_free(pKeyNode);
1146 * This function get the string value of given key
1147 * @param[in] key key
1148 * @param[out] value output buffer
1149 * @return 0 on success, -1 on error
1151 API int preference_get_string(const char *key, char **value)
1155 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1156 retvm_if(value == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1158 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1159 keynode_t* pKeyNode = _preference_keynode_new();
1160 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1162 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1163 if (func_ret != PREFERENCE_ERROR_NONE) {
1164 ERR("set key name error");
1165 _preference_keynode_free(pKeyNode);
1166 return PREFERENCE_ERROR_IO_ERROR;
1169 char *tempstr = NULL;
1170 func_ret = _preference_get_key(pKeyNode);
1172 if (func_ret != PREFERENCE_ERROR_NONE) {
1173 ERR("preference_get_string(%d) : %s error", getpid(), key);
1175 if (pKeyNode->type == PREFERENCE_TYPE_STRING)
1176 tempstr = pKeyNode->value.s;
1178 ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
1179 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1183 *value = strdup(tempstr);
1184 INFO("%s(%s) success", key, value);
1188 _preference_keynode_free(pKeyNode);
1196 * This function unset given key
1197 * @param[in] key key
1198 * @return 0 on success, -1 on error
1200 API int preference_remove(const char *key)
1204 char path[PATH_MAX] = {0,};
1206 int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1207 int func_ret = PREFERENCE_ERROR_NONE;
1209 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1211 keynode_t* pKeyNode = _preference_keynode_new();
1212 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1214 ret = _preference_keynode_set_keyname(pKeyNode, key);
1215 if (ret != PREFERENCE_ERROR_NONE) {
1216 ERR("set key name error");
1217 _preference_keynode_free(pKeyNode);
1218 return PREFERENCE_ERROR_IO_ERROR;
1221 ret = _preference_get_key_path(pKeyNode, path);
1222 if (ret != PREFERENCE_ERROR_NONE) {
1223 ERR("Invalid argument: key is not valid");
1224 _preference_keynode_free(pKeyNode);
1225 return PREFERENCE_ERROR_INVALID_PARAMETER;
1228 if (access(path, F_OK) == -1) {
1229 ERR("Error : key(%s) is not exist", key);
1230 _preference_keynode_free(pKeyNode);
1231 return PREFERENCE_ERROR_NO_KEY;
1237 ERR("preference_remove() failed. ret=%d(%s), key(%s)", errno, strerror(errno), key);
1238 func_ret = PREFERENCE_ERROR_IO_ERROR;
1240 func_ret = PREFERENCE_ERROR_NONE;
1243 } while(err_retry--);
1247 _preference_keynode_free(pKeyNode);
1252 API int preference_remove_all(void)
1257 int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1258 int func_ret = PREFERENCE_ERROR_NONE;
1260 struct dirent *dent = NULL;
1261 char *pref_dir_path = NULL;
1263 pref_dir_path = _preference_get_pref_dir_path();
1266 LOGE("_preference_get_pref_dir_path() failed.");
1267 return PREFERENCE_ERROR_IO_ERROR;
1270 dir = opendir(pref_dir_path);
1273 LOGE("opendir() failed. pref_path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1274 return PREFERENCE_ERROR_IO_ERROR;
1277 keynode_t* pKeyNode = _preference_keynode_new();
1278 if (pKeyNode == NULL)
1280 ERR("key malloc fail");
1282 return PREFERENCE_ERROR_OUT_OF_MEMORY;
1285 while ((dent = readdir(dir)))
1287 const char *entry = dent->d_name;
1288 char keyname[PREFERENCE_KEY_PATH_LEN] = {0,};
1289 char path[PATH_MAX] = {0,};
1291 if (entry[0] == '.') {
1295 ret = _preference_get_key_name(entry, keyname);
1296 if (ret != PREFERENCE_ERROR_NONE) {
1297 ERR("_preference_get_key_name() failed(%d)", ret);
1298 _preference_keynode_free(pKeyNode);
1303 ret = preference_unset_changed_cb(keyname);
1304 if (ret != PREFERENCE_ERROR_NONE) {
1305 ERR("preference_unset_changed_cb() failed(%d)", ret);
1306 _preference_keynode_free(pKeyNode);
1308 return PREFERENCE_ERROR_IO_ERROR;
1311 ret = _preference_keynode_set_keyname(pKeyNode, keyname);
1312 if (ret != PREFERENCE_ERROR_NONE) {
1313 ERR("set key name error");
1314 _preference_keynode_free(pKeyNode);
1316 return PREFERENCE_ERROR_IO_ERROR;
1319 ret = _preference_get_key_path(pKeyNode, path);
1320 if (ret != PREFERENCE_ERROR_NONE) {
1321 ERR("_preference_get_key_path() failed(%d)", ret);
1322 _preference_keynode_free(pKeyNode);
1331 ERR("preference_remove_all error: %d(%s)", errno, strerror(errno));
1332 func_ret = PREFERENCE_ERROR_IO_ERROR;
1334 func_ret = PREFERENCE_ERROR_NONE;
1337 } while(err_retry--);
1340 _preference_keynode_free(pKeyNode);
1348 int preference_is_existing(const char *key, bool *exist)
1352 char path[PATH_MAX] = {0,};
1354 int func_ret = PREFERENCE_ERROR_NONE;
1356 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1357 retvm_if(exist == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1359 keynode_t* pKeyNode = _preference_keynode_new();
1360 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1362 ret = _preference_keynode_set_keyname(pKeyNode, key);
1363 if (ret != PREFERENCE_ERROR_NONE) {
1364 ERR("set key name error");
1365 _preference_keynode_free(pKeyNode);
1366 return PREFERENCE_ERROR_IO_ERROR;
1369 ret = _preference_get_key_path(pKeyNode, path);
1370 if (ret != PREFERENCE_ERROR_NONE) {
1371 _preference_keynode_free(pKeyNode);
1375 ret = access(path, F_OK);
1377 ERR("Error : key(%s) is not exist", key);
1383 _preference_keynode_free(pKeyNode);
1391 API int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
1395 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1396 retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1398 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1400 keynode_t* pKeyNode = _preference_keynode_new();
1401 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1403 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1404 if (func_ret != PREFERENCE_ERROR_NONE) {
1405 ERR("set key name error");
1406 _preference_keynode_free(pKeyNode);
1407 return PREFERENCE_ERROR_IO_ERROR;
1410 if (_preference_kdb_add_notify(pKeyNode, callback, user_data)) {
1411 if (errno == ENOENT) {
1412 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
1413 _preference_keynode_free(pKeyNode);
1414 return PREFERENCE_ERROR_NO_KEY;
1415 } else if(errno != 0) {
1416 ERR("preference_notify_key_changed : key(%s) add notify fail", key);
1417 _preference_keynode_free(pKeyNode);
1418 return PREFERENCE_ERROR_IO_ERROR;
1421 INFO("%s noti is added", key);
1422 _preference_keynode_free(pKeyNode);
1426 return PREFERENCE_ERROR_NONE;
1429 API int preference_unset_changed_cb(const char *key)
1433 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1435 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1437 keynode_t* pKeyNode = _preference_keynode_new();
1438 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1440 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1441 if (func_ret != PREFERENCE_ERROR_NONE) {
1442 ERR("set key name error");
1443 _preference_keynode_free(pKeyNode);
1444 return PREFERENCE_ERROR_IO_ERROR;
1447 if (_preference_kdb_del_notify(pKeyNode)) {
1448 if (errno == ENOENT) {
1449 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
1450 _preference_keynode_free(pKeyNode);
1451 return PREFERENCE_ERROR_NO_KEY;
1452 } else if (errno != 0) {
1453 ERR("preference_unset_changed_cb() failed: key(%s) error(%d/%s)", key, errno, strerror(errno));
1454 _preference_keynode_free(pKeyNode);
1455 return PREFERENCE_ERROR_IO_ERROR;
1458 INFO("%s noti removed", key);
1459 _preference_keynode_free(pKeyNode);
1463 return PREFERENCE_ERROR_NONE;
1467 API int preference_foreach_item(preference_item_cb callback, void *user_data)
1471 retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1475 struct dirent *dent = NULL;
1476 char *pref_dir_path = NULL;
1478 pref_dir_path = _preference_get_pref_dir_path();
1479 if (!pref_dir_path) {
1480 LOGE("_preference_get_pref_dir_path() failed.");
1481 return PREFERENCE_ERROR_IO_ERROR;
1484 dir = opendir(pref_dir_path);
1486 LOGE("opendir() failed. path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1487 return PREFERENCE_ERROR_IO_ERROR;
1490 while((dent = readdir(dir))) {
1491 const char *entry = dent->d_name;
1492 char keyname[PREFERENCE_KEY_PATH_LEN] = {0,};
1494 if (entry[0] == '.') {
1498 ret = _preference_get_key_name(entry, keyname);
1499 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
1501 callback(keyname, user_data);
1507 return PREFERENCE_ERROR_NONE;