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>
36 #ifdef PREFERENCE_TIMECHECK
41 #define API __attribute__ ((visibility("default")))
44 #define PREFERENCE_ERROR_RETRY_CNT 7
45 #define PREFERENCE_ERROR_RETRY_SLEEP_UTIME 10000
49 static int g_posix_errno;
50 static int g_preference_errno;
51 static char *g_pref_dir_path = NULL;
53 enum preference_op_t {
54 PREFERENCE_OP_GET = 0,
58 #ifdef PREFERENCE_TIMECHECK
59 double correction, startT;
61 double set_start_time(void)
66 gettimeofday(&tv, NULL);
67 curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
71 double exec_time(double start)
73 double end = set_start_time();
74 return (end - start - correction);
80 temp_t = set_start_time();
81 correction = exec_time(temp_t);
87 char* _preference_get_pref_dir_path()
89 char *app_data_path = NULL;
91 if (!g_pref_dir_path) {
92 g_pref_dir_path = (char *)malloc(PREFERENCE_KEY_PATH_LEN + 1);
94 if ((app_data_path = app_get_data_path()) == NULL) {
95 ERR("IO_ERROR(0x%08x) : fail to get data directory", PREFERENCE_ERROR_IO_ERROR);
96 free(g_pref_dir_path);
97 g_pref_dir_path = NULL;
101 snprintf(g_pref_dir_path, PREFERENCE_KEY_PATH_LEN, "%s%s", app_data_path, PREF_DIR);
102 INFO("pref_dir_path: %s", g_pref_dir_path);
105 return g_pref_dir_path;
108 int _preference_keynode_set_keyname(keynode_t *keynode, const char *keyname)
110 if (keynode->keyname) free(keynode->keyname);
111 keynode->keyname = strndup(keyname, PREFERENCE_KEY_PATH_LEN);
112 retvm_if(keynode->keyname == NULL, PREFERENCE_ERROR_IO_ERROR, "strndup Fails");
113 return PREFERENCE_ERROR_NONE;
116 static inline void _preference_keynode_set_value_int(keynode_t *keynode, const int value)
118 keynode->type = PREFERENCE_TYPE_INT;
119 keynode->value.i = value;
122 static inline void _preference_keynode_set_value_boolean(keynode_t *keynode, const int value)
124 keynode->type = PREFERENCE_TYPE_BOOLEAN;
125 keynode->value.b = !!value;
128 static inline void _preference_keynode_set_value_double(keynode_t *keynode, const double value)
130 keynode->type = PREFERENCE_TYPE_DOUBLE;
131 keynode->value.d = value;
134 static inline void _preference_keynode_set_value_string(keynode_t *keynode, const char *value)
136 keynode->type = PREFERENCE_TYPE_STRING;
137 keynode->value.s = strdup(value);
140 inline keynode_t *_preference_keynode_new(void)
143 keynode = calloc(1, sizeof(keynode_t));
148 inline void _preference_keynode_free(keynode_t *keynode)
151 if (keynode->keyname)
152 free(keynode->keyname);
153 if (keynode->type == PREFERENCE_TYPE_STRING && keynode->value.s)
154 free(keynode->value.s);
159 int _preference_get_key_name(const char *path, char **keyname)
162 size_t keyname_len = 0;
163 char *convert_key = NULL;
166 if( (fp = fopen(path, "r")) == NULL ) {
167 return PREFERENCE_ERROR_FILE_OPEN;
170 read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
171 if (read_size <= 0) {
173 return PREFERENCE_ERROR_FILE_FREAD;
176 convert_key = (char *)calloc(1, keyname_len+1);
177 if (convert_key == NULL) {
178 LOGE("memory alloc failed");
180 return PREFERENCE_ERROR_OUT_OF_MEMORY;
183 read_size = fread((void *)convert_key, keyname_len, 1, fp);
184 if (read_size <= 0) {
187 return PREFERENCE_ERROR_FILE_FREAD;
190 *keyname = convert_key;
194 return PREFERENCE_ERROR_NONE;
197 int _preference_get_key_path(keynode_t *keynode, char *path)
199 const char *key = NULL;
200 char *pref_dir_path = NULL;
202 char *keyname = keynode->keyname;
205 LOGE("keyname is null");
206 return PREFERENCE_ERROR_WRONG_PREFIX;
209 pref_dir_path = _preference_get_pref_dir_path();
210 if (!pref_dir_path) {
211 LOGE("_preference_get_pref_dir_path() failed.");
212 return PREFERENCE_ERROR_IO_ERROR;
215 convert_key = g_compute_checksum_for_string(G_CHECKSUM_SHA1,
218 if (convert_key == NULL) {
219 LOGE("fail to convert");
220 return PREFERENCE_ERROR_IO_ERROR;
223 key = (const char*)convert_key;
225 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, key);
229 return PREFERENCE_ERROR_NONE;
232 static int _preference_set_key_check_pref_dir()
234 char *pref_dir_path = NULL;
235 mode_t dir_mode = 0664 | 0111;
237 pref_dir_path = _preference_get_pref_dir_path();
238 if (!pref_dir_path) {
239 LOGE("_preference_get_pref_dir_path() failed.");
240 return PREFERENCE_ERROR_IO_ERROR;
243 if (access(pref_dir_path, F_OK) < 0) {
244 if (mkdir(pref_dir_path, dir_mode) < 0) {
245 ERR("mkdir() failed(%d/%s)", errno, strerror(errno));
246 return PREFERENCE_ERROR_IO_ERROR;
250 return PREFERENCE_ERROR_NONE;
253 static int _preference_set_key_creation(const char* path)
258 fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
262 ERR("open(rdwr,create) error: %d(%s)", errno, strerror(errno));
263 return PREFERENCE_ERROR_IO_ERROR;
267 return PREFERENCE_ERROR_NONE;
270 static int _preference_set_file_lock(int fd, short type)
275 l.l_start= 0; /*Start at begin*/
276 l.l_whence = SEEK_SET;
277 l.l_len = 0; /*Do it with whole file*/
279 return fcntl(fd, F_SETLK, &l);
282 static int _preference_get_pid_of_file_lock_owner(int fd, short type)
287 l.l_start= 0; /*Start at begin*/
288 l.l_whence = SEEK_SET;
289 l.l_len = 0; /*Do it with whole file*/
291 if(fcntl(fd, F_GETLK, &l) < 0) {
292 WARN("error in getting lock info");
296 if(l.l_type == F_UNLCK)
303 static int _preference_set_read_lock(int fd)
305 return _preference_set_file_lock(fd, F_RDLCK);
308 static int _preference_set_write_lock(int fd)
310 return _preference_set_file_lock(fd, F_WRLCK);
313 static int _preference_set_unlock(int fd)
315 return _preference_set_file_lock(fd, F_UNLCK);
318 static void _preference_log_subject_label(void)
322 char smack_label[256] = {0,};
323 char curren_path[256] = {0,};
326 tid = (int)syscall(SYS_gettid);
327 snprintf(curren_path, sizeof(curren_path)-1, "/proc/%d/attr/current", tid);
328 fd = open(curren_path, O_RDONLY);
330 LOGE("fail to open self current attr (err: %s)", strerror(errno));
334 ret = read(fd, smack_label, sizeof(smack_label)-1);
337 LOGE("fail to open self current attr (err: %s)", strerror(errno));
341 ERR("current(%d) subject label : %s", tid, smack_label);
346 static int _preference_check_retry_err(keynode_t *keynode, int preference_errno, int io_errno, int op_type)
350 if (preference_errno == PREFERENCE_ERROR_FILE_OPEN)
356 if(op_type == PREFERENCE_OP_SET)
359 char path[PATH_MAX] = {0,};
360 rc = _preference_get_key_path(keynode, path);
361 if (rc != PREFERENCE_ERROR_NONE) {
362 ERR("_preference_get_key_path error");
363 _preference_log_subject_label();
367 rc = _preference_set_key_check_pref_dir();
368 if (rc != PREFERENCE_ERROR_NONE) {
369 ERR("_preference_set_key_check_pref_dir() failed.");
370 _preference_log_subject_label();
374 rc = _preference_set_key_creation(path);
375 if (rc != PREFERENCE_ERROR_NONE) {
376 ERR("_preference_set_key_creation error : %s", path);
377 _preference_log_subject_label();
380 INFO("%s key is created", keynode->keyname);
388 _preference_log_subject_label();
400 else if (preference_errno == PREFERENCE_ERROR_FILE_CHMOD)
411 else if (preference_errno == PREFERENCE_ERROR_FILE_LOCK)
423 else if (preference_errno == PREFERENCE_ERROR_FILE_WRITE)
437 else if (preference_errno == PREFERENCE_ERROR_FILE_FREAD)
454 if (is_busy_err == 1) {
459 ERR("key(%s), check retry err: %d/(%d/%s).",keynode->keyname, preference_errno, io_errno, strerror(io_errno));
464 static int _preference_set_key_filesys(keynode_t *keynode, int *io_errno)
466 char path[PATH_MAX] = {0,};
469 int func_ret = PREFERENCE_ERROR_NONE;
471 char err_buf[100] = { 0, };
472 int is_write_error = 0;
474 size_t keyname_len = 0;
479 func_ret = PREFERENCE_ERROR_NONE;
481 ret = _preference_get_key_path(keynode, path);
482 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
484 if( (fp = fopen(path, "r+")) == NULL ) {
485 func_ret = PREFERENCE_ERROR_FILE_OPEN;
493 func_ret = PREFERENCE_ERROR_NONE;
495 ret = _preference_set_write_lock(fileno(fp));
497 func_ret = PREFERENCE_ERROR_FILE_LOCK;
499 ERR("file(%s) lock owner(%d)",
501 _preference_get_pid_of_file_lock_owner(fileno(fp), F_WRLCK));
505 /* write keyname and size */
506 keyname_len = strlen(keynode->keyname);
508 ret = fwrite((void *)&keyname_len, sizeof(int), 1, fp);
511 LOGW("number of written items is 0. try again");
515 func_ret = PREFERENCE_ERROR_FILE_WRITE;
519 ret = fwrite((void *)keynode->keyname, keyname_len, 1, fp);
522 LOGW("number of written items is 0. try again");
526 func_ret = PREFERENCE_ERROR_FILE_WRITE;
531 ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
534 LOGW("number of written items is 0. try again");
538 func_ret = PREFERENCE_ERROR_FILE_WRITE;
542 /* write key value */
543 switch (keynode->type) {
544 case PREFERENCE_TYPE_INT:
545 ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
546 if (ret <= 0) is_write_error = 1;
548 case PREFERENCE_TYPE_DOUBLE:
549 ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
550 if (ret <= 0) is_write_error = 1;
552 case PREFERENCE_TYPE_BOOLEAN:
553 ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
554 if (ret <= 0) is_write_error = 1;
556 case PREFERENCE_TYPE_STRING:
557 ret = fprintf(fp,"%s",keynode->value.s);
558 if (ret < strlen(keynode->value.s)) is_write_error = 1;
559 if (ftruncate(fileno(fp), ret) == -1)
563 func_ret = PREFERENCE_ERROR_WRONG_TYPE;
567 if (is_write_error) {
569 LOGW("number of written items is 0. try again");
573 func_ret = PREFERENCE_ERROR_FILE_WRITE;
580 ret = _preference_set_unlock(fileno(fp));
582 func_ret = PREFERENCE_ERROR_FILE_LOCK;
588 if (func_ret != PREFERENCE_ERROR_NONE) {
589 strerror_r(err_no, err_buf, 100);
590 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_SET)) {
591 if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT) {
592 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);
594 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
601 ERR("_preference_set_key_filesys(%d-%s) step(%d) faild(%d / %s) over the retry count.",
602 keynode->type, keynode->keyname, func_ret, err_no, err_buf);
605 ERR("_preference_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
609 DBG("_preference_set_key_filesys ok with retry cnt(%d)", retry_cnt);
614 if (func_ret == PREFERENCE_ERROR_NONE) {
615 ret = fdatasync(fileno(fp));
618 func_ret = PREFERENCE_ERROR_FILE_SYNC;
628 static int _preference_set_key(keynode_t *keynode)
632 char err_buf[100] = { 0, };
634 ret = _preference_set_key_filesys(keynode, &io_errno);
635 if (ret == PREFERENCE_ERROR_NONE) {
636 g_posix_errno = PREFERENCE_ERROR_NONE;
637 g_preference_errno = PREFERENCE_ERROR_NONE;
639 strerror_r(io_errno, err_buf, 100);
640 ERR("_preference_set_key(%s) step(%d) failed(%d / %s)", keynode->keyname, ret, io_errno, err_buf);
641 g_posix_errno = io_errno;
642 g_preference_errno = ret;
650 * This function set the integer value of given key
652 * @param[in] intval integer value to set
653 * @return 0 on success, -1 on error
655 API int preference_set_int(const char *key, int intval)
659 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
661 int func_ret = PREFERENCE_ERROR_NONE;
663 keynode_t* pKeyNode = _preference_keynode_new();
664 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
666 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
667 if (func_ret != PREFERENCE_ERROR_NONE) {
668 ERR("set key name error");
669 _preference_keynode_free(pKeyNode);
670 return PREFERENCE_ERROR_IO_ERROR;
672 _preference_keynode_set_value_int(pKeyNode, intval);
674 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
675 ERR("preference_set_int(%d) : key(%s/%d) error", getpid(), key, intval);
676 func_ret = PREFERENCE_ERROR_IO_ERROR;
678 INFO("%s(%d) success", key, intval);
681 _preference_keynode_free(pKeyNode);
689 * This function set the boolean value of given key
691 * @param[in] boolval boolean value to set
692 (Integer value 1 is 'True', and 0 is 'False')
693 * @return 0 on success, -1 on error
695 API int preference_set_boolean(const char *key, bool boolval)
699 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
701 int func_ret = PREFERENCE_ERROR_NONE;
702 keynode_t* pKeyNode = _preference_keynode_new();
703 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
705 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
706 if (func_ret != PREFERENCE_ERROR_NONE) {
707 ERR("set key name error");
708 _preference_keynode_free(pKeyNode);
709 return PREFERENCE_ERROR_IO_ERROR;
711 _preference_keynode_set_value_boolean(pKeyNode, boolval);
713 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
714 ERR("preference_set_boolean(%d) : key(%s/%d) error", getpid(), key, boolval);
715 func_ret = PREFERENCE_ERROR_IO_ERROR;
717 INFO("%s(%d) success", key, boolval);
720 _preference_keynode_free(pKeyNode);
728 * This function set the double value of given key
730 * @param[in] dblval double value to set
731 * @return 0 on success, -1 on error
733 API int preference_set_double(const char *key, double dblval)
737 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
739 int func_ret = PREFERENCE_ERROR_NONE;
740 keynode_t* pKeyNode = _preference_keynode_new();
741 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
743 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
744 if (func_ret != PREFERENCE_ERROR_NONE) {
745 ERR("set key name error");
746 _preference_keynode_free(pKeyNode);
747 return PREFERENCE_ERROR_IO_ERROR;
749 _preference_keynode_set_value_double(pKeyNode, dblval);
751 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
752 ERR("preference_set_double(%d) : key(%s/%f) error", getpid(), key, dblval);
753 func_ret = PREFERENCE_ERROR_IO_ERROR;
755 INFO("%s(%f) success", key, dblval);
758 _preference_keynode_free(pKeyNode);
766 * This function set the string value of given key
768 * @param[in] strval string value to set
769 * @return 0 on success, -1 on error
771 API int preference_set_string(const char *key, const char *strval)
775 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
776 retvm_if(strval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: value is NULL");
778 int func_ret = PREFERENCE_ERROR_NONE;
779 keynode_t* pKeyNode = _preference_keynode_new();
780 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
782 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
783 if (func_ret != PREFERENCE_ERROR_NONE) {
784 ERR("set key name error");
785 _preference_keynode_free(pKeyNode);
786 return PREFERENCE_ERROR_IO_ERROR;
788 _preference_keynode_set_value_string(pKeyNode, strval);
790 if (_preference_set_key(pKeyNode) != PREFERENCE_ERROR_NONE) {
791 ERR("preference_set_string(%d) : key(%s/%s) error", getpid(), key, strval);
792 func_ret = PREFERENCE_ERROR_IO_ERROR;
794 INFO("%s(%s) success", key, strval);
797 _preference_keynode_free(pKeyNode);
804 static int _preference_get_key_filesys(keynode_t *keynode, int* io_errno)
806 char path[PATH_MAX] = {0,};
808 int func_ret = PREFERENCE_ERROR_NONE;
809 char err_buf[100] = { 0, };
815 size_t keyname_len = 0;
819 func_ret = PREFERENCE_ERROR_NONE;
821 ret = _preference_get_key_path(keynode, path);
822 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
824 if( (fp = fopen(path, "r")) == NULL ) {
825 func_ret = PREFERENCE_ERROR_FILE_OPEN;
832 func_ret = PREFERENCE_ERROR_NONE;
834 ret = _preference_set_read_lock(fileno(fp));
836 func_ret = PREFERENCE_ERROR_FILE_LOCK;
841 read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
842 if ((read_size <= 0) || (read_size > sizeof(int))) {
847 func_ret = PREFERENCE_ERROR_FILE_FREAD;
851 ret = fseek(fp, keyname_len, SEEK_CUR);
857 func_ret = PREFERENCE_ERROR_FILE_FREAD;
861 read_size = fread((void *)&type, sizeof(int), 1, fp);
862 if (read_size <= 0) {
867 func_ret = PREFERENCE_ERROR_FILE_FREAD;
871 /* read data value */
874 case PREFERENCE_TYPE_INT:
877 read_size = fread((void*)&value_int, sizeof(int), 1, fp);
878 if ((read_size <= 0) || (read_size > sizeof(int))) {
880 LOGW("number of read items for value is wrong. err : %d", errno);
883 func_ret = PREFERENCE_ERROR_FILE_FREAD;
886 _preference_keynode_set_value_int(keynode, value_int);
891 case PREFERENCE_TYPE_DOUBLE:
893 double value_dbl = 0;
894 read_size = fread((void*)&value_dbl, sizeof(double), 1, fp);
895 if ((read_size <= 0) || (read_size > sizeof(double))) {
897 LOGW("number of read items for value is wrong. err : %d", errno);
900 func_ret = PREFERENCE_ERROR_FILE_FREAD;
903 _preference_keynode_set_value_double(keynode, value_dbl);
908 case PREFERENCE_TYPE_BOOLEAN:
911 read_size = fread((void*)&value_int, sizeof(int), 1, fp);
912 if ((read_size <= 0) || (read_size > sizeof(int))) {
914 LOGW("number of read items for value is wrong. err : %d", errno);
917 func_ret = PREFERENCE_ERROR_FILE_FREAD;
920 _preference_keynode_set_value_boolean(keynode, value_int);
925 case PREFERENCE_TYPE_STRING:
927 char file_buf[BUF_LEN] = {0,};
931 while(fgets(file_buf, sizeof(file_buf), fp))
934 value_size = value_size + strlen(file_buf);
935 value = (char *) realloc(value, value_size);
937 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
940 strncat(value, file_buf, strlen(file_buf));
942 value_size = strlen(file_buf) + 1;
943 value = (char *)malloc(value_size);
945 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
948 memset(value, 0x00, value_size);
949 strncpy(value, file_buf, strlen(file_buf));
955 func_ret = PREFERENCE_ERROR_FILE_FGETS;
958 _preference_keynode_set_value_string(keynode, value);
960 _preference_keynode_set_value_string(keynode, "");
969 func_ret = PREFERENCE_ERROR_WRONG_TYPE;
973 ret = _preference_set_unlock(fileno(fp));
975 func_ret = PREFERENCE_ERROR_FILE_LOCK;
982 if (func_ret != PREFERENCE_ERROR_NONE) {
983 strerror_r(err_no, err_buf, 100);
985 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_GET)) {
986 if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT) {
988 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
996 ERR("_preference_get_key_filesys(%s) step(%d) faild(%d / %s) over the retry count.",
997 keynode->keyname, func_ret, err_no, err_buf);
1010 int _preference_get_key(keynode_t *keynode)
1014 char err_buf[100] = {0,};
1016 ret = _preference_get_key_filesys(keynode, &io_errno);
1017 if (ret == PREFERENCE_ERROR_NONE) {
1018 g_posix_errno = PREFERENCE_ERROR_NONE;
1019 g_preference_errno = PREFERENCE_ERROR_NONE;
1022 if (io_errno == ENOENT)
1023 ret = PREFERENCE_ERROR_NO_KEY;
1025 ret = PREFERENCE_ERROR_IO_ERROR;
1027 strerror_r(io_errno, err_buf, 100);
1028 ERR("_preference_get_key(%s) step(%d) failed(%d / %s)\n", keynode->keyname, ret, io_errno, err_buf);
1029 g_posix_errno = io_errno;
1030 g_preference_errno = ret;
1038 * This function get the integer value of given key
1039 * @param[in] key key
1040 * @param[out] intval output buffer
1041 * @return 0 on success, -1 on error
1043 API int preference_get_int(const char *key, int *intval)
1047 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1048 retvm_if(intval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1050 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1051 keynode_t* pKeyNode = _preference_keynode_new();
1052 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1054 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1055 if (func_ret != PREFERENCE_ERROR_NONE) {
1056 ERR("set key name error");
1057 _preference_keynode_free(pKeyNode);
1058 return PREFERENCE_ERROR_IO_ERROR;
1061 func_ret = _preference_get_key(pKeyNode);
1062 if (func_ret != PREFERENCE_ERROR_NONE) {
1063 ERR("preference_get_int(%d) : key(%s) error", getpid(), key);
1065 *intval = pKeyNode->value.i;
1066 if (pKeyNode->type == PREFERENCE_TYPE_INT) {
1067 INFO("%s(%d) success", key, *intval);
1068 func_ret = PREFERENCE_ERROR_NONE;
1070 ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
1071 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1075 _preference_keynode_free(pKeyNode);
1083 * This function get the boolean value of given key
1084 * @param[in] key key
1085 * @param[out] boolval output buffer
1086 * @return 0 on success, -1 on error
1088 API int preference_get_boolean(const char *key, bool *boolval)
1092 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1093 retvm_if(boolval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1095 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1096 keynode_t* pKeyNode = _preference_keynode_new();
1097 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1099 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1100 if (func_ret != PREFERENCE_ERROR_NONE) {
1101 ERR("set key name error");
1102 _preference_keynode_free(pKeyNode);
1103 return PREFERENCE_ERROR_IO_ERROR;
1106 func_ret = _preference_get_key(pKeyNode);
1108 if (func_ret != PREFERENCE_ERROR_NONE) {
1109 ERR("preference_get_boolean(%d) : %s error", getpid(), key);
1111 *boolval = !!(pKeyNode->value.b);
1112 if (pKeyNode->type == PREFERENCE_TYPE_BOOLEAN) {
1113 INFO("%s(%d) success", key, *boolval);
1114 func_ret = PREFERENCE_ERROR_NONE;
1116 ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
1117 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1121 _preference_keynode_free(pKeyNode);
1129 * This function get the double value of given key
1130 * @param[in] key key
1131 * @param[out] dblval output buffer
1132 * @return 0 on success, -1 on error
1134 API int preference_get_double(const char *key, double *dblval)
1138 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1139 retvm_if(dblval == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1141 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1142 keynode_t* pKeyNode = _preference_keynode_new();
1143 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1145 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1146 if (func_ret != PREFERENCE_ERROR_NONE) {
1147 ERR("set key name error");
1148 _preference_keynode_free(pKeyNode);
1149 return PREFERENCE_ERROR_IO_ERROR;
1152 func_ret = _preference_get_key(pKeyNode);
1154 if (func_ret != PREFERENCE_ERROR_NONE) {
1155 ERR("preference_get_double(%d) : %s error", getpid(), key);
1157 *dblval = pKeyNode->value.d;
1158 if (pKeyNode->type == PREFERENCE_TYPE_DOUBLE) {
1159 INFO("%s(%f) success", key, *dblval);
1160 func_ret = PREFERENCE_ERROR_NONE;
1162 ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
1163 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1167 _preference_keynode_free(pKeyNode);
1175 * This function get the string value of given key
1176 * @param[in] key key
1177 * @param[out] value output buffer
1178 * @return 0 on success, -1 on error
1180 API int preference_get_string(const char *key, char **value)
1184 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1185 retvm_if(value == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: output buffer is null");
1187 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1188 keynode_t* pKeyNode = _preference_keynode_new();
1189 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1191 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1192 if (func_ret != PREFERENCE_ERROR_NONE) {
1193 ERR("set key name error");
1194 _preference_keynode_free(pKeyNode);
1195 return PREFERENCE_ERROR_IO_ERROR;
1198 char *tempstr = NULL;
1199 func_ret = _preference_get_key(pKeyNode);
1201 if (func_ret != PREFERENCE_ERROR_NONE) {
1202 ERR("preference_get_string(%d) : %s error", getpid(), key);
1204 if (pKeyNode->type == PREFERENCE_TYPE_STRING)
1205 tempstr = pKeyNode->value.s;
1207 ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
1208 func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1212 *value = strdup(tempstr);
1213 INFO("%s(%s) success", key, value);
1217 _preference_keynode_free(pKeyNode);
1225 * This function unset given key
1226 * @param[in] key key
1227 * @return 0 on success, -1 on error
1229 API int preference_remove(const char *key)
1233 char path[PATH_MAX] = {0,};
1235 int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1236 int func_ret = PREFERENCE_ERROR_NONE;
1238 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1240 keynode_t* pKeyNode = _preference_keynode_new();
1241 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1243 ret = _preference_keynode_set_keyname(pKeyNode, key);
1244 if (ret != PREFERENCE_ERROR_NONE) {
1245 ERR("set key name error");
1246 _preference_keynode_free(pKeyNode);
1247 return PREFERENCE_ERROR_IO_ERROR;
1250 ret = _preference_get_key_path(pKeyNode, path);
1251 if (ret != PREFERENCE_ERROR_NONE) {
1252 ERR("Invalid argument: key is not valid");
1253 _preference_keynode_free(pKeyNode);
1254 return PREFERENCE_ERROR_INVALID_PARAMETER;
1257 if (access(path, F_OK) == -1) {
1258 ERR("Error : key(%s) is not exist", key);
1259 _preference_keynode_free(pKeyNode);
1260 return PREFERENCE_ERROR_NO_KEY;
1266 ERR("preference_remove() failed. ret=%d(%s), key(%s)", errno, strerror(errno), key);
1267 func_ret = PREFERENCE_ERROR_IO_ERROR;
1269 func_ret = PREFERENCE_ERROR_NONE;
1272 } while(err_retry--);
1276 _preference_keynode_free(pKeyNode);
1281 API int preference_remove_all(void)
1286 int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1287 int func_ret = PREFERENCE_ERROR_NONE;
1289 struct dirent *dent = NULL;
1290 char *pref_dir_path = NULL;
1292 pref_dir_path = _preference_get_pref_dir_path();
1295 LOGE("_preference_get_pref_dir_path() failed.");
1296 return PREFERENCE_ERROR_IO_ERROR;
1299 dir = opendir(pref_dir_path);
1302 LOGE("opendir() failed. pref_path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1303 return PREFERENCE_ERROR_IO_ERROR;
1306 keynode_t* pKeyNode = _preference_keynode_new();
1307 if (pKeyNode == NULL)
1309 ERR("key malloc fail");
1311 return PREFERENCE_ERROR_OUT_OF_MEMORY;
1314 while ((dent = readdir(dir)))
1316 const char *entry = dent->d_name;
1317 char *keyname = NULL;
1318 char path[PATH_MAX] = {0,};
1320 if (entry[0] == '.') {
1324 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, entry);
1326 ret = _preference_get_key_name(path, &keyname);
1327 if (ret != PREFERENCE_ERROR_NONE) {
1328 ERR("_preference_get_key_name() failed(%d)", ret);
1329 _preference_keynode_free(pKeyNode);
1334 ret = preference_unset_changed_cb(keyname);
1335 if (ret != PREFERENCE_ERROR_NONE) {
1336 ERR("preference_unset_changed_cb() failed(%d)", ret);
1337 _preference_keynode_free(pKeyNode);
1340 return PREFERENCE_ERROR_IO_ERROR;
1346 ERR("preference_remove_all error: %d(%s)", errno, strerror(errno));
1347 func_ret = PREFERENCE_ERROR_IO_ERROR;
1349 func_ret = PREFERENCE_ERROR_NONE;
1352 } while(err_retry--);
1357 _preference_keynode_free(pKeyNode);
1365 int preference_is_existing(const char *key, bool *exist)
1369 char path[PATH_MAX] = {0,};
1371 int func_ret = PREFERENCE_ERROR_NONE;
1373 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1374 retvm_if(exist == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1376 keynode_t* pKeyNode = _preference_keynode_new();
1377 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1379 ret = _preference_keynode_set_keyname(pKeyNode, key);
1380 if (ret != PREFERENCE_ERROR_NONE) {
1381 ERR("set key name error");
1382 _preference_keynode_free(pKeyNode);
1383 return PREFERENCE_ERROR_IO_ERROR;
1386 ret = _preference_get_key_path(pKeyNode, path);
1387 if (ret != PREFERENCE_ERROR_NONE) {
1388 _preference_keynode_free(pKeyNode);
1392 ret = access(path, F_OK);
1394 ERR("Error : key(%s) is not exist", key);
1400 _preference_keynode_free(pKeyNode);
1408 API int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
1412 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1413 retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1415 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1417 keynode_t* pKeyNode = _preference_keynode_new();
1418 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1420 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1421 if (func_ret != PREFERENCE_ERROR_NONE) {
1422 ERR("set key name error");
1423 _preference_keynode_free(pKeyNode);
1424 return PREFERENCE_ERROR_IO_ERROR;
1427 if (_preference_kdb_add_notify(pKeyNode, callback, user_data)) {
1428 if (errno == ENOENT) {
1429 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
1430 _preference_keynode_free(pKeyNode);
1431 return PREFERENCE_ERROR_NO_KEY;
1432 } else if(errno != 0) {
1433 ERR("preference_notify_key_changed : key(%s) add notify fail", key);
1434 _preference_keynode_free(pKeyNode);
1435 return PREFERENCE_ERROR_IO_ERROR;
1438 INFO("%s noti is added", key);
1439 _preference_keynode_free(pKeyNode);
1443 return PREFERENCE_ERROR_NONE;
1446 API int preference_unset_changed_cb(const char *key)
1450 int func_ret = PREFERENCE_ERROR_IO_ERROR;
1452 retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1454 keynode_t* pKeyNode = _preference_keynode_new();
1455 retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1457 func_ret = _preference_keynode_set_keyname(pKeyNode, key);
1458 if (func_ret != PREFERENCE_ERROR_NONE) {
1459 ERR("set key name error");
1460 _preference_keynode_free(pKeyNode);
1461 return PREFERENCE_ERROR_IO_ERROR;
1464 if (_preference_kdb_del_notify(pKeyNode)) {
1465 if (errno == ENOENT) {
1466 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
1467 _preference_keynode_free(pKeyNode);
1468 return PREFERENCE_ERROR_NO_KEY;
1469 } else if (errno != 0) {
1470 ERR("preference_unset_changed_cb() failed: key(%s) error(%d/%s)", key, errno, strerror(errno));
1471 _preference_keynode_free(pKeyNode);
1472 return PREFERENCE_ERROR_IO_ERROR;
1475 INFO("%s noti removed", key);
1476 _preference_keynode_free(pKeyNode);
1480 return PREFERENCE_ERROR_NONE;
1484 API int preference_foreach_item(preference_item_cb callback, void *user_data)
1488 retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1492 struct dirent *dent = NULL;
1493 char *pref_dir_path = NULL;
1495 pref_dir_path = _preference_get_pref_dir_path();
1496 if (!pref_dir_path) {
1497 LOGE("_preference_get_pref_dir_path() failed.");
1498 return PREFERENCE_ERROR_IO_ERROR;
1501 dir = opendir(pref_dir_path);
1503 LOGE("opendir() failed. path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1504 return PREFERENCE_ERROR_IO_ERROR;
1507 while((dent = readdir(dir))) {
1508 const char *entry = dent->d_name;
1509 char *keyname = NULL;
1510 char path[PATH_MAX] = {0,};
1512 if (entry[0] == '.') {
1516 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, entry);
1518 ret = _preference_get_key_name(path, &keyname);
1519 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
1521 callback(keyname, user_data);
1528 return PREFERENCE_ERROR_NONE;