8ae6dd5bb042214de216412dca1b164d3549749e
[platform/core/api/application.git] / preference / preference.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <stdlib.h>
18 #include <limits.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <dirent.h>
23 #include <sys/stat.h>
24 #include <sys/xattr.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <execinfo.h>
28 #include <glib.h>
29
30 #include <app_preference.h>
31 #include <app_preference_internal.h>
32 #include <app_common.h>
33
34 #include <sys/syscall.h>
35
36
37 #ifndef API
38 #define API __attribute__ ((visibility("default")))
39 #endif
40
41 #define PREFERENCE_ERROR_RETRY_CNT 7
42 #define PREFERENCE_ERROR_RETRY_SLEEP_UTIME 10000
43
44 #define DELIMITER 29
45
46 static int g_posix_errno;
47 static int g_preference_errno;
48 static char *g_pref_dir_path = NULL;
49
50 enum preference_op_t {
51     PREFERENCE_OP_GET = 0,
52     PREFERENCE_OP_SET = 1
53 };
54
55 #ifdef PREFERENCE_TIMECHECK
56 double correction, startT;
57
58 double set_start_time(void)
59 {
60         struct timeval tv;
61         double curtime;
62
63         gettimeofday(&tv, NULL);
64         curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
65         return curtime;
66 }
67
68 double exec_time(double start)
69 {
70         double end = set_start_time();
71         return (end - start - correction);
72 }
73
74 int init_time(void)
75 {
76         double temp_t;
77         temp_t = set_start_time();
78         correction = exec_time(temp_t);
79
80         return 0;
81 }
82 #endif
83
84 char* _preference_get_pref_dir_path()
85 {
86         char *app_data_path = NULL;
87
88         if (!g_pref_dir_path) {
89                 g_pref_dir_path = (char *)malloc(PREFERENCE_KEY_PATH_LEN + 1);
90
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;
95                         return NULL;
96                 }
97
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);
100                 free(app_data_path);
101         }
102         return g_pref_dir_path;
103 }
104
105 int _preference_keynode_set_keyname(keynode_t *keynode, const char *keyname)
106 {
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;
111 }
112
113 static inline void _preference_keynode_set_value_int(keynode_t *keynode, const int value)
114 {
115         keynode->type = PREFERENCE_TYPE_INT;
116         keynode->value.i = value;
117 }
118
119 static inline void _preference_keynode_set_value_boolean(keynode_t *keynode, const int value)
120 {
121         keynode->type = PREFERENCE_TYPE_BOOLEAN;
122         keynode->value.b = !!value;
123 }
124
125 static inline void _preference_keynode_set_value_double(keynode_t *keynode, const double value)
126 {
127         keynode->type = PREFERENCE_TYPE_DOUBLE;
128         keynode->value.d = value;
129 }
130
131 static inline void _preference_keynode_set_value_string(keynode_t *keynode, const char *value)
132 {
133         keynode->type = PREFERENCE_TYPE_STRING;
134         keynode->value.s = strdup(value);
135 }
136
137 inline keynode_t *_preference_keynode_new(void)
138 {
139         keynode_t *keynode;
140         keynode = calloc(1, sizeof(keynode_t));
141
142         return keynode;
143 }
144
145 inline void _preference_keynode_free(keynode_t *keynode)
146 {
147         if(keynode) {
148                 if (keynode->keyname)
149                         free(keynode->keyname);
150                 if (keynode->type == PREFERENCE_TYPE_STRING && keynode->value.s)
151                         free(keynode->value.s);
152                 free(keynode);
153         }
154 }
155
156 int _preference_get_key_name(const char *keyfile, char *keyname)
157 {
158         unsigned int i = 0;
159         char convert_key[PATH_MAX] = {0,};
160         guchar *key_name = NULL;
161         gsize key_path_len = 0;
162
163         strncpy(convert_key, keyfile, PATH_MAX - 1);
164
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;
169                         break;
170                 case PREF_KEYNAME_C_UNDERSCORE:
171                         convert_key[i] = PREF_KEYNAME_C_PLUS;
172                         break;
173                 case PREF_KEYNAME_C_HYPHEN:
174                         convert_key[i] = PREF_KEYNAME_C_SLASH;
175                         break;
176                 default:
177                         break;
178                 }
179         }
180
181         key_name = g_base64_decode((const gchar *)convert_key, &key_path_len);
182         snprintf(keyname, PREFERENCE_KEY_PATH_LEN-1, "%s", key_name);
183         free(key_name);
184
185         return PREFERENCE_ERROR_NONE;
186 }
187
188 int _preference_get_key_path(keynode_t *keynode, char *path)
189 {
190         unsigned int i = 0;
191         const char *key = NULL;
192         char *keyname = keynode->keyname;
193
194         if (!keyname) {
195                 ERR("keyname is null");
196                 return PREFERENCE_ERROR_WRONG_PREFIX;
197         }
198
199         char *convert_key = NULL;
200         char *pref_dir_path = NULL;
201
202         convert_key = g_base64_encode((const guchar *)keyname, strlen(keyname));
203
204         pref_dir_path = _preference_get_pref_dir_path();
205         if (!pref_dir_path) {
206                 LOGE("_preference_get_pref_dir_path() failed.");
207                 g_free(convert_key);
208                 return PREFERENCE_ERROR_IO_ERROR;
209         }
210
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;
215                         break;
216                 case PREF_KEYNAME_C_PLUS:
217                         convert_key[i] = PREF_KEYNAME_C_UNDERSCORE;
218                         break;
219                 case PREF_KEYNAME_C_SLASH:
220                         convert_key[i] = PREF_KEYNAME_C_HYPHEN;
221                         break;
222                 default:
223                         break;
224                 }
225         }
226
227         key = (const char*)convert_key;
228
229         snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, key);
230         g_free(convert_key);
231
232         return PREFERENCE_ERROR_NONE;
233 }
234
235 static int _preference_set_key_check_pref_dir()
236 {
237         char *pref_dir_path = NULL;
238         mode_t dir_mode = 0664 | 0111;
239
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;
244         }
245
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;
250                 }
251         }
252
253         return PREFERENCE_ERROR_NONE;
254 }
255
256 static int _preference_set_key_creation(const char* path)
257 {
258         int fd;
259         mode_t temp;
260         temp = umask(0000);
261         fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
262         umask(temp);
263
264         if(fd == -1) {
265                 ERR("open(rdwr,create) error: %d(%s)", errno, strerror(errno));
266                 return PREFERENCE_ERROR_IO_ERROR;
267         }
268         close(fd);
269
270         return PREFERENCE_ERROR_NONE;
271 }
272
273 static int _preference_set_file_lock(int fd, short type)
274 {
275         struct flock l;
276
277         l.l_type = 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*/
281
282         return fcntl(fd, F_SETLK, &l);
283 }
284
285 static int _preference_get_pid_of_file_lock_owner(int fd, short type)
286 {
287         struct flock l;
288
289         l.l_type = 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*/
293
294         if(fcntl(fd, F_GETLK, &l) < 0) {
295                 WARN("error in getting lock info");
296                 return -1;
297         }
298
299         if(l.l_type == F_UNLCK)
300                 return 0;
301         else
302                 return l.l_pid;
303 }
304
305
306 static int _preference_set_read_lock(int fd)
307 {
308         return _preference_set_file_lock(fd, F_RDLCK);
309 }
310
311 static int _preference_set_write_lock(int fd)
312 {
313         return _preference_set_file_lock(fd, F_WRLCK);
314 }
315
316 static int _preference_set_unlock(int fd)
317 {
318         return _preference_set_file_lock(fd, F_UNLCK);
319 }
320
321 static void _preference_log_subject_label(void)
322 {
323         int fd;
324         int ret;
325         char smack_label[256] = {0,};
326         char curren_path[256] = {0,};
327         int tid;
328
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);
332         if (fd < 0) {
333                 LOGE("fail to open self current attr (err: %s)", strerror(errno));
334                 return;
335         }
336
337         ret = read(fd, smack_label, sizeof(smack_label)-1);
338         if (ret < 0) {
339                 close(fd);
340                 LOGE("fail to open self current attr (err: %s)", strerror(errno));
341                 return;
342         }
343
344         ERR("current(%d) subject label : %s", tid, smack_label);
345
346         close(fd);
347 }
348
349 static int _preference_check_retry_err(keynode_t *keynode, int preference_errno, int io_errno, int op_type)
350 {
351         int is_busy_err = 0;
352
353         if (preference_errno == PREFERENCE_ERROR_FILE_OPEN)
354         {
355                 switch (io_errno)
356                 {
357                         case ENOENT :
358                         {
359                                 if(op_type == PREFERENCE_OP_SET)
360                                 {
361                                         int rc = 0;
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();
367                                                 break;
368                                         }
369
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();
374                                                 break;
375                                         }
376
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();
381                                                 break;
382                                         }
383                                         INFO("%s key is created", keynode->keyname);
384
385                                         is_busy_err = 1;
386                                 }
387                                 break;
388                         }
389                         case EACCES :
390                         {
391                                 _preference_log_subject_label();
392                                 break;
393                         }
394                         case EAGAIN :
395                         case EMFILE :
396                         case ENFILE :
397                         case ETXTBSY :
398                         {
399                                 is_busy_err = 1;
400                         }
401                 }
402         }
403         else if (preference_errno == PREFERENCE_ERROR_FILE_CHMOD)
404         {
405                 switch (io_errno)
406                 {
407                         case EINTR :
408                         case EBADF :
409                         {
410                                 is_busy_err = 1;
411                         }
412                 }
413         }
414         else if (preference_errno == PREFERENCE_ERROR_FILE_LOCK)
415         {
416                 switch (io_errno)
417                 {
418                         case EBADF :
419                         case EAGAIN :
420                         case ENOLCK :
421                         {
422                                 is_busy_err = 1;
423                         }
424                 }
425         }
426         else if (preference_errno == PREFERENCE_ERROR_FILE_WRITE)
427         {
428                 switch (io_errno)
429                 {
430                         case 0 :
431                         case EAGAIN :
432                         case EINTR :
433                         case EIO :
434                         case ENOMEM :
435                         {
436                                 is_busy_err = 1;
437                         }
438                 }
439         }
440         else if (preference_errno == PREFERENCE_ERROR_FILE_FREAD)
441         {
442                 switch (io_errno)
443                 {
444                         case EAGAIN :
445                         case EINTR :
446                         case EIO :
447                         {
448                                 is_busy_err = 1;
449                         }
450                 }
451         }
452         else
453         {
454                 is_busy_err = 0;
455         }
456
457         if (is_busy_err == 1) {
458                 return 1;
459         }
460         else
461         {
462                 ERR("key(%s), check retry err: %d/(%d/%s).",keynode->keyname, preference_errno, io_errno, strerror(io_errno));
463                 return 0;
464         }
465 }
466
467 static int _preference_set_key_filesys(keynode_t *keynode, int *io_errno)
468 {
469         char path[PATH_MAX] = {0,};
470         FILE *fp = NULL;
471         int ret = -1;
472         int func_ret = PREFERENCE_ERROR_NONE;
473         int err_no = 0;
474         char err_buf[100] = { 0, };
475         int is_write_error = 0;
476         int retry_cnt = 0;
477
478 retry_open :
479         errno = 0;
480         err_no = 0;
481         func_ret = PREFERENCE_ERROR_NONE;
482
483         ret = _preference_get_key_path(keynode, path);
484         retv_if(ret != PREFERENCE_ERROR_NONE, ret);
485
486         if( (fp = fopen(path, "r+")) == NULL ) {
487                 func_ret = PREFERENCE_ERROR_FILE_OPEN;
488                 err_no = errno;
489                 goto out_return;
490         }
491
492 retry :
493         errno = 0;
494         err_no = 0;
495         func_ret = PREFERENCE_ERROR_NONE;
496
497         ret = _preference_set_write_lock(fileno(fp));
498         if(ret == -1) {
499                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
500                 err_no = errno;
501                 ERR("file(%s) lock owner(%d)",
502                         keynode->keyname,
503                         _preference_get_pid_of_file_lock_owner(fileno(fp), F_WRLCK));
504                 goto out_return;
505         }
506
507         /* write key type */
508         ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
509         if(ret <= 0)
510         {
511                 if(!errno) {
512                         LOGW("number of written items is 0. try again");
513                         errno = EAGAIN;
514                 }
515                 err_no = errno;
516                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
517                 goto out_unlock;
518         }
519
520         /* write key value */
521         switch(keynode->type)
522         {
523                 case PREFERENCE_TYPE_INT:
524                         ret = fwrite((void *)&(keynode->value.i), sizeof(int), 1, fp);
525                         if(ret <= 0) is_write_error = 1;
526                         break;
527                 case PREFERENCE_TYPE_DOUBLE:
528                         ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
529                         if(ret <= 0) is_write_error = 1;
530                         break;
531                 case PREFERENCE_TYPE_BOOLEAN:
532                         ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
533                         if(ret <= 0) is_write_error = 1;
534                         break;
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) {
539                                 is_write_error = 1;
540                         }
541                         break;
542                 default :
543                         func_ret = PREFERENCE_ERROR_WRONG_TYPE;
544                         goto out_unlock;
545         }
546         if(is_write_error)
547         {
548                 if(!errno) {
549                         LOGW("number of written items is 0. try again");
550                         errno = EAGAIN;
551                 }
552                 err_no = errno;
553                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
554                 goto out_unlock;
555         }
556
557         fflush(fp);
558
559 out_unlock :
560         ret = _preference_set_unlock(fileno(fp));
561         if(ret == -1) {
562                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
563                 err_no = errno;
564                 goto out_return;
565         }
566
567 out_return :
568         if (func_ret != PREFERENCE_ERROR_NONE)
569         {
570                 strerror_r(err_no, err_buf, 100);
571                 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_SET))
572                 {
573                         if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT)
574                         {
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);
576                                 retry_cnt++;
577                                 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
578
579                                 if (fp)
580                                         goto retry;
581                                 else
582                                         goto retry_open;
583                         }
584                         else
585                         {
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);
588                         }
589                 }
590                 else
591                 {
592                         ERR("_preference_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
593                 }
594         } else {
595                 if(retry_cnt > 0) {
596                         DBG("_preference_set_key_filesys ok with retry cnt(%d)", retry_cnt);
597                 }
598         }
599
600         if (fp)
601         {
602                 if(func_ret == PREFERENCE_ERROR_NONE)
603                 {
604                         ret = fdatasync(fileno(fp));
605                         if(ret == -1) {
606                                 err_no = errno;
607                                 func_ret = PREFERENCE_ERROR_FILE_SYNC;
608                         }
609                 }
610                 fclose(fp);
611         }
612         *io_errno = err_no;
613
614         return func_ret;
615 }
616
617 static int _preference_set_key(keynode_t *keynode)
618 {
619         int ret = 0;
620         int io_errno = 0;
621         char err_buf[100] = { 0, };
622
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;
627         } else {
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;
632         }
633
634         return ret;
635 }
636
637
638 /*
639  * This function set the integer value of given key
640  * @param[in]   key     key
641  * @param[in]   intval integer value to set
642  * @return 0 on success, -1 on error
643  */
644 API int preference_set_int(const char *key, int intval)
645 {
646         START_TIME_CHECK
647
648         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
649
650         int func_ret = PREFERENCE_ERROR_NONE;
651
652         keynode_t* pKeyNode = _preference_keynode_new();
653         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
654
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;
660         }
661         _preference_keynode_set_value_int(pKeyNode, intval);
662
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;
666         } else {
667                 INFO("%s(%d) success", key, intval);
668         }
669
670         _preference_keynode_free(pKeyNode);
671
672         END_TIME_CHECK
673
674         return func_ret;
675 }
676
677 /*
678 * This function set the boolean value of given key
679 * @param[in]    key     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
683 */
684 API int preference_set_boolean(const char *key, bool boolval)
685 {
686         START_TIME_CHECK
687
688         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
689
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");
693
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;
699         }
700         _preference_keynode_set_value_boolean(pKeyNode, boolval);
701
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;
705         } else {
706                 INFO("%s(%d) success", key, boolval);
707         }
708
709         _preference_keynode_free(pKeyNode);
710
711         END_TIME_CHECK
712
713         return func_ret;
714 }
715
716 /*
717  * This function set the double value of given key
718  * @param[in]   key     key
719  * @param[in]   dblval double value to set
720  * @return 0 on success, -1 on error
721  */
722 API int preference_set_double(const char *key, double dblval)
723 {
724         START_TIME_CHECK
725
726         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
727
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");
731
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;
737         }
738         _preference_keynode_set_value_double(pKeyNode, dblval);
739
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;
743         } else {
744                 INFO("%s(%f) success", key, dblval);
745         }
746
747         _preference_keynode_free(pKeyNode);
748
749         END_TIME_CHECK
750
751         return func_ret;
752 }
753
754 /*
755  * This function set the string value of given key
756  * @param[in]   key     key
757  * @param[in]   strval string value to set
758  * @return 0 on success, -1 on error
759  */
760 API int preference_set_string(const char *key, const char *strval)
761 {
762         START_TIME_CHECK
763
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");
766
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");
770
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;
776         }
777         _preference_keynode_set_value_string(pKeyNode, strval);
778
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;
782         } else {
783                 INFO("%s(%s) success", key, strval);
784         }
785
786         _preference_keynode_free(pKeyNode);
787
788         END_TIME_CHECK
789
790         return func_ret;
791 }
792
793 static int _preference_get_key_filesys(keynode_t *keynode, int* io_errno)
794 {
795         char path[PATH_MAX] = {0,};
796         int ret = -1;
797         int func_ret = PREFERENCE_ERROR_NONE;
798         char err_buf[100] = { 0, };
799         int err_no = 0;
800         int type = 0;
801         FILE *fp = NULL;
802         int retry_cnt = 0;
803         int read_size = 0;
804
805 retry_open :
806         errno = 0;
807         func_ret = PREFERENCE_ERROR_NONE;
808
809         ret = _preference_get_key_path(keynode, path);
810         retv_if(ret != PREFERENCE_ERROR_NONE, ret);
811
812         if( (fp = fopen(path, "r")) == NULL ) {
813                 func_ret = PREFERENCE_ERROR_FILE_OPEN;
814                 err_no = errno;
815                 goto out_return;
816         }
817
818 retry :
819         err_no = 0;
820         func_ret = PREFERENCE_ERROR_NONE;
821
822         ret = _preference_set_read_lock(fileno(fp));
823         if(ret == -1) {
824                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
825                 err_no = errno;
826                 goto out_return;
827         }
828
829
830         /* read data type */
831         read_size = fread((void*)&type, sizeof(int), 1, fp);
832         if((read_size <= 0) || (read_size > sizeof(int))) {
833                 if(!ferror(fp)) {
834                         LOGW("number of read items for type is 0 with false ferror. err : %d", errno);
835                         errno = ENODATA;
836                 }
837                 err_no = errno;
838                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
839                 goto out_unlock;
840         }
841
842         /* read data value */
843         switch(type)
844         {
845                 case PREFERENCE_TYPE_INT:
846                 {
847                         int value_int = 0;
848                         read_size = fread((void*)&value_int, sizeof(int), 1, fp);
849                         if((read_size <= 0) || (read_size > sizeof(int))) {
850                                 if(!ferror(fp)) {
851                                         LOGW("number of read items for value is wrong. err : %d", errno);
852                                 }
853                                 err_no = errno;
854                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
855                                 goto out_unlock;
856                         } else {
857                                 _preference_keynode_set_value_int(keynode, value_int);
858                         }
859
860                         break;
861                 }
862                 case PREFERENCE_TYPE_DOUBLE:
863                 {
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))) {
867                                 if(!ferror(fp)) {
868                                         LOGW("number of read items for value is wrong. err : %d", errno);
869                                 }
870                                 err_no = errno;
871                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
872                                 goto out_unlock;
873                         } else {
874                                 _preference_keynode_set_value_double(keynode, value_dbl);
875                         }
876
877                         break;
878                 }
879                 case PREFERENCE_TYPE_BOOLEAN:
880                 {
881                         int value_int = 0;
882                         read_size = fread((void*)&value_int, sizeof(int), 1, fp);
883                         if((read_size <= 0) || (read_size > sizeof(int))) {
884                                 if(!ferror(fp)) {
885                                         LOGW("number of read items for value is wrong. err : %d", errno);
886                                 }
887                                 err_no = errno;
888                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
889                                 goto out_unlock;
890                         } else {
891                                 _preference_keynode_set_value_boolean(keynode, value_int);
892                         }
893
894                         break;
895                 }
896                 case PREFERENCE_TYPE_STRING:
897                 {
898                         char file_buf[BUF_LEN] = {0,};
899                         char *value = NULL;
900                         int value_size = 0;
901
902                         while(fgets(file_buf, sizeof(file_buf), fp))
903                         {
904                                 if(value) {
905                                         value_size = value_size + strlen(file_buf);
906                                         value = (char *) realloc(value, value_size);
907                                         if(value == NULL) {
908                                                 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
909                                                 break;
910                                         }
911                                         strncat(value, file_buf, strlen(file_buf));
912                                 } else {
913                                         value_size = strlen(file_buf) + 1;
914                                         value = (char *)malloc(value_size);
915                                         if(value == NULL) {
916                                                 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
917                                                 break;
918                                         }
919                                         memset(value, 0x00, value_size);
920                                         strncpy(value, file_buf, strlen(file_buf));
921                                 }
922                         }
923
924                         if(ferror(fp)) {
925                                 err_no = errno;
926                                 func_ret = PREFERENCE_ERROR_FILE_FGETS;
927                         } else {
928                                 if(value) {
929                                         _preference_keynode_set_value_string(keynode, value);
930                                 } else {
931                                         _preference_keynode_set_value_string(keynode, "");
932                                 }
933                         }
934                         if(value)
935                                 free(value);
936
937                         break;
938                 }
939                 default :
940                         func_ret = PREFERENCE_ERROR_WRONG_TYPE;
941         }
942
943 out_unlock :
944         ret = _preference_set_unlock(fileno(fp));
945         if(ret == -1) {
946                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
947                 err_no = errno;
948                 goto out_return;
949         }
950
951
952 out_return :
953         if (func_ret != PREFERENCE_ERROR_NONE) {
954                 strerror_r(err_no, err_buf, 100);
955
956                 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_GET)) {
957                         if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT) {
958                                 retry_cnt++;
959                                 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
960
961                                 if (fp)
962                                         goto retry;
963                                 else
964                                         goto retry_open;
965                         }
966                         else {
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);
969                         }
970                 }
971         }
972
973         if (fp)
974                 fclose(fp);
975
976         *io_errno = err_no;
977
978         return func_ret;
979 }
980
981 int _preference_get_key(keynode_t *keynode)
982 {
983         int ret = 0;
984         int io_errno = 0;
985         char err_buf[100] = {0,};
986
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;
991         }
992         else {
993                 if (io_errno == ENOENT)
994                         ret = PREFERENCE_ERROR_NO_KEY;
995                 else
996                         ret = PREFERENCE_ERROR_IO_ERROR;
997
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;
1002         }
1003
1004         return ret;
1005 }
1006
1007
1008 /*
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
1013  */
1014 API int preference_get_int(const char *key, int *intval)
1015 {
1016         START_TIME_CHECK
1017
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");
1020
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");
1024
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;
1030         }
1031
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);
1035         } else {
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;
1040                 } else {
1041                         ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
1042                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1043                 }
1044         }
1045
1046         _preference_keynode_free(pKeyNode);
1047
1048         END_TIME_CHECK
1049
1050         return func_ret;
1051 }
1052
1053 /*
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
1058  */
1059 API int preference_get_boolean(const char *key, bool *boolval)
1060 {
1061         START_TIME_CHECK
1062
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");
1065
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");
1069
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;
1075         }
1076
1077         func_ret = _preference_get_key(pKeyNode);
1078
1079         if (func_ret != PREFERENCE_ERROR_NONE) {
1080                 ERR("preference_get_boolean(%d) : %s error", getpid(), key);
1081         } else {
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;
1086                 } else {
1087                         ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
1088                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1089                 }
1090         }
1091
1092         _preference_keynode_free(pKeyNode);
1093
1094         END_TIME_CHECK
1095
1096         return func_ret;
1097 }
1098
1099 /*
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
1104  */
1105 API int preference_get_double(const char *key, double *dblval)
1106 {
1107         START_TIME_CHECK
1108
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");
1111
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");
1115
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;
1121         }
1122
1123         func_ret = _preference_get_key(pKeyNode);
1124
1125         if (func_ret != PREFERENCE_ERROR_NONE) {
1126                 ERR("preference_get_double(%d) : %s error", getpid(), key);
1127         } else {
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;
1132                 } else {
1133                         ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
1134                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1135                 }
1136         }
1137
1138         _preference_keynode_free(pKeyNode);
1139
1140         END_TIME_CHECK
1141
1142         return func_ret;
1143 }
1144
1145 /*
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
1150  */
1151 API int preference_get_string(const char *key, char **value)
1152 {
1153         START_TIME_CHECK
1154
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");
1157
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");
1161
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;
1167         }
1168
1169         char *tempstr = NULL;
1170         func_ret = _preference_get_key(pKeyNode);
1171
1172         if (func_ret != PREFERENCE_ERROR_NONE) {
1173                 ERR("preference_get_string(%d) : %s error", getpid(), key);
1174         } else {
1175                 if (pKeyNode->type == PREFERENCE_TYPE_STRING)
1176                         tempstr = pKeyNode->value.s;
1177                 else {
1178                         ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
1179                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1180                 }
1181
1182                 if(tempstr) {
1183                         *value = strdup(tempstr);
1184                         INFO("%s(%s) success", key, value);
1185                 }
1186         }
1187
1188         _preference_keynode_free(pKeyNode);
1189
1190         END_TIME_CHECK
1191
1192         return func_ret;
1193 }
1194
1195 /*
1196  * This function unset given key
1197  * @param[in]   key     key
1198  * @return 0 on success, -1 on error
1199  */
1200 API int preference_remove(const char *key)
1201 {
1202         START_TIME_CHECK
1203
1204         char path[PATH_MAX] = {0,};
1205         int ret = -1;
1206         int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1207         int func_ret = PREFERENCE_ERROR_NONE;
1208
1209         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1210
1211         keynode_t* pKeyNode = _preference_keynode_new();
1212         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1213
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;
1219         }
1220
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;
1226         }
1227
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;
1232         }
1233
1234         do {
1235                 ret = remove(path);
1236                 if(ret == -1) {
1237                         ERR("preference_remove() failed. ret=%d(%s), key(%s)", errno, strerror(errno), key);
1238                         func_ret = PREFERENCE_ERROR_IO_ERROR;
1239                 } else {
1240                         func_ret = PREFERENCE_ERROR_NONE;
1241                         break;
1242                 }
1243         } while(err_retry--);
1244
1245         END_TIME_CHECK;
1246
1247         _preference_keynode_free(pKeyNode);
1248
1249         return func_ret;
1250 }
1251
1252 API int preference_remove_all(void)
1253 {
1254         START_TIME_CHECK
1255
1256         int ret = -1;
1257         int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1258         int func_ret = PREFERENCE_ERROR_NONE;
1259         DIR *dir;
1260         struct dirent *dent = NULL;
1261         char *pref_dir_path = NULL;
1262
1263         pref_dir_path = _preference_get_pref_dir_path();
1264         if (!pref_dir_path)
1265         {
1266                 LOGE("_preference_get_pref_dir_path() failed.");
1267                 return PREFERENCE_ERROR_IO_ERROR;
1268         }
1269
1270         dir = opendir(pref_dir_path);
1271         if (dir == NULL)
1272         {
1273                 LOGE("opendir() failed. pref_path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1274                 return PREFERENCE_ERROR_IO_ERROR;
1275         }
1276
1277         keynode_t* pKeyNode = _preference_keynode_new();
1278         if (pKeyNode == NULL)
1279         {
1280                 ERR("key malloc fail");
1281                 closedir(dir);
1282                 return PREFERENCE_ERROR_OUT_OF_MEMORY;
1283         }
1284
1285         while ((dent = readdir(dir)))
1286         {
1287                 const char *entry = dent->d_name;
1288                 char keyname[PREFERENCE_KEY_PATH_LEN] = {0,};
1289                 char path[PATH_MAX] = {0,};
1290
1291                 if (entry[0] == '.') {
1292                         continue;
1293                 }
1294
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);
1299                         closedir(dir);
1300                         return ret;
1301                 }
1302
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);
1307                         closedir(dir);
1308                         return PREFERENCE_ERROR_IO_ERROR;
1309                 }
1310
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);
1315                         closedir(dir);
1316                         return PREFERENCE_ERROR_IO_ERROR;
1317                 }
1318
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);
1323                         closedir(dir);
1324                         return ret;
1325                 }
1326
1327         // delete
1328                 do {
1329                         ret = remove(path);
1330                         if(ret == -1) {
1331                                 ERR("preference_remove_all error: %d(%s)", errno, strerror(errno));
1332                                 func_ret = PREFERENCE_ERROR_IO_ERROR;
1333                         } else {
1334                                 func_ret = PREFERENCE_ERROR_NONE;
1335                                 break;
1336                         }
1337                 } while(err_retry--);
1338         }
1339
1340         _preference_keynode_free(pKeyNode);
1341         closedir(dir);
1342
1343         END_TIME_CHECK
1344
1345         return func_ret;
1346 }
1347
1348 int preference_is_existing(const char *key, bool *exist)
1349 {
1350         START_TIME_CHECK
1351
1352         char path[PATH_MAX] = {0,};
1353         int ret = -1;
1354         int func_ret = PREFERENCE_ERROR_NONE;
1355
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");
1358
1359         keynode_t* pKeyNode = _preference_keynode_new();
1360         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1361
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;
1367         }
1368
1369         ret = _preference_get_key_path(pKeyNode, path);
1370         if (ret != PREFERENCE_ERROR_NONE) {
1371                 _preference_keynode_free(pKeyNode);
1372                 return ret;
1373         }
1374
1375         ret = access(path, F_OK);
1376         if (ret == -1) {
1377                 ERR("Error : key(%s) is not exist", key);
1378                 *exist = 0;
1379         } else {
1380                 *exist = 1;
1381         }
1382
1383         _preference_keynode_free(pKeyNode);
1384
1385         END_TIME_CHECK
1386
1387         return func_ret;
1388 }
1389
1390
1391 API int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
1392 {
1393         START_TIME_CHECK
1394
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);
1397
1398         int func_ret = PREFERENCE_ERROR_IO_ERROR;
1399
1400         keynode_t* pKeyNode = _preference_keynode_new();
1401         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1402
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;
1408         }
1409
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;
1419                 }
1420         }
1421         INFO("%s noti is added", key);
1422         _preference_keynode_free(pKeyNode);
1423
1424         END_TIME_CHECK
1425
1426         return PREFERENCE_ERROR_NONE;
1427 }
1428
1429 API int preference_unset_changed_cb(const char *key)
1430 {
1431         START_TIME_CHECK
1432
1433         int func_ret = PREFERENCE_ERROR_IO_ERROR;
1434
1435         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1436
1437         keynode_t* pKeyNode = _preference_keynode_new();
1438         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1439
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;
1445         }
1446
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;
1456                 }
1457         }
1458         INFO("%s noti removed", key);
1459         _preference_keynode_free(pKeyNode);
1460
1461         END_TIME_CHECK
1462
1463         return PREFERENCE_ERROR_NONE;
1464 }
1465
1466
1467 API int preference_foreach_item(preference_item_cb callback, void *user_data)
1468 {
1469         START_TIME_CHECK
1470
1471         retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1472
1473         int ret = 0;
1474         DIR *dir;
1475         struct dirent *dent = NULL;
1476         char *pref_dir_path = NULL;
1477
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;
1482         }
1483
1484         dir = opendir(pref_dir_path);
1485         if (dir == NULL) {
1486                 LOGE("opendir() failed. path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1487                 return PREFERENCE_ERROR_IO_ERROR;
1488         }
1489
1490         while((dent = readdir(dir))) {
1491                 const char *entry = dent->d_name;
1492                 char keyname[PREFERENCE_KEY_PATH_LEN] = {0,};
1493
1494                 if (entry[0] == '.') {
1495                         continue;
1496                 }
1497
1498                 ret = _preference_get_key_name(entry, keyname);
1499                 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
1500
1501                 callback(keyname, user_data);
1502         }
1503
1504         closedir(dir);
1505         END_TIME_CHECK
1506
1507         return PREFERENCE_ERROR_NONE;
1508 }