To use hash value for file name.
[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 #ifdef PREFERENCE_TIMECHECK
37 #include <sys/time.h>
38 #endif
39
40 #ifndef API
41 #define API __attribute__ ((visibility("default")))
42 #endif
43
44 #define PREFERENCE_ERROR_RETRY_CNT 7
45 #define PREFERENCE_ERROR_RETRY_SLEEP_UTIME 10000
46
47 #define DELIMITER 29
48
49 static int g_posix_errno;
50 static int g_preference_errno;
51 static char *g_pref_dir_path = NULL;
52
53 enum preference_op_t {
54     PREFERENCE_OP_GET = 0,
55     PREFERENCE_OP_SET = 1
56 };
57
58 #ifdef PREFERENCE_TIMECHECK
59 double correction, startT;
60
61 double set_start_time(void)
62 {
63         struct timeval tv;
64         double curtime;
65
66         gettimeofday(&tv, NULL);
67         curtime = tv.tv_sec * 1000 + (double)tv.tv_usec / 1000;
68         return curtime;
69 }
70
71 double exec_time(double start)
72 {
73         double end = set_start_time();
74         return (end - start - correction);
75 }
76
77 int init_time(void)
78 {
79         double temp_t;
80         temp_t = set_start_time();
81         correction = exec_time(temp_t);
82
83         return 0;
84 }
85 #endif
86
87 char* _preference_get_pref_dir_path()
88 {
89         char *app_data_path = NULL;
90
91         if (!g_pref_dir_path) {
92                 g_pref_dir_path = (char *)malloc(PREFERENCE_KEY_PATH_LEN + 1);
93
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;
98                         return NULL;
99                 }
100
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);
103                 free(app_data_path);
104         }
105         return g_pref_dir_path;
106 }
107
108 int _preference_keynode_set_keyname(keynode_t *keynode, const char *keyname)
109 {
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;
114 }
115
116 static inline void _preference_keynode_set_value_int(keynode_t *keynode, const int value)
117 {
118         keynode->type = PREFERENCE_TYPE_INT;
119         keynode->value.i = value;
120 }
121
122 static inline void _preference_keynode_set_value_boolean(keynode_t *keynode, const int value)
123 {
124         keynode->type = PREFERENCE_TYPE_BOOLEAN;
125         keynode->value.b = !!value;
126 }
127
128 static inline void _preference_keynode_set_value_double(keynode_t *keynode, const double value)
129 {
130         keynode->type = PREFERENCE_TYPE_DOUBLE;
131         keynode->value.d = value;
132 }
133
134 static inline void _preference_keynode_set_value_string(keynode_t *keynode, const char *value)
135 {
136         keynode->type = PREFERENCE_TYPE_STRING;
137         keynode->value.s = strdup(value);
138 }
139
140 inline keynode_t *_preference_keynode_new(void)
141 {
142         keynode_t *keynode;
143         keynode = calloc(1, sizeof(keynode_t));
144
145         return keynode;
146 }
147
148 inline void _preference_keynode_free(keynode_t *keynode)
149 {
150         if(keynode) {
151                 if (keynode->keyname)
152                         free(keynode->keyname);
153                 if (keynode->type == PREFERENCE_TYPE_STRING && keynode->value.s)
154                         free(keynode->value.s);
155                 free(keynode);
156         }
157 }
158
159 int _preference_get_key_name(const char *path, char **keyname)
160 {
161         int read_size = 0;
162         size_t keyname_len = 0;
163         char *convert_key = NULL;
164         FILE *fp = NULL;
165
166         if( (fp = fopen(path, "r")) == NULL ) {
167                 return PREFERENCE_ERROR_FILE_OPEN;
168         }
169
170         read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
171         if (read_size <= 0) {
172                 fclose(fp);
173                 return PREFERENCE_ERROR_FILE_FREAD;
174         }
175
176         convert_key = (char *)calloc(1, keyname_len+1);
177         if (convert_key == NULL) {
178                 LOGE("memory alloc failed");
179                 fclose(fp);
180                 return PREFERENCE_ERROR_OUT_OF_MEMORY;
181         }
182
183         read_size = fread((void *)convert_key, keyname_len, 1, fp);
184         if (read_size <= 0) {
185                 free(convert_key);
186                 fclose(fp);
187                 return PREFERENCE_ERROR_FILE_FREAD;
188         }
189
190         *keyname = convert_key;
191
192         fclose(fp);
193
194         return PREFERENCE_ERROR_NONE;
195 }
196
197 int _preference_get_key_path(keynode_t *keynode, char *path)
198 {
199         const char *key = NULL;
200         char *pref_dir_path = NULL;
201         gchar *convert_key;
202         char *keyname = keynode->keyname;
203
204         if(!keyname) {
205                 LOGE("keyname is null");
206                 return PREFERENCE_ERROR_WRONG_PREFIX;
207         }
208
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;
213         }
214
215         convert_key = g_compute_checksum_for_string(G_CHECKSUM_SHA1,
216                                                         keyname,
217                                                         strlen(keyname));
218         if (convert_key == NULL) {
219                 LOGE("fail to convert");
220                 return PREFERENCE_ERROR_IO_ERROR;
221         }
222
223         key = (const char*)convert_key;
224
225         snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, key);
226
227         g_free(convert_key);
228
229         return PREFERENCE_ERROR_NONE;
230 }
231
232 static int _preference_set_key_check_pref_dir()
233 {
234         char *pref_dir_path = NULL;
235         mode_t dir_mode = 0664 | 0111;
236
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;
241         }
242
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;
247                 }
248         }
249
250         return PREFERENCE_ERROR_NONE;
251 }
252
253 static int _preference_set_key_creation(const char* path)
254 {
255         int fd;
256         mode_t temp;
257         temp = umask(0000);
258         fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
259         umask(temp);
260
261         if(fd == -1) {
262                 ERR("open(rdwr,create) error: %d(%s)", errno, strerror(errno));
263                 return PREFERENCE_ERROR_IO_ERROR;
264         }
265         close(fd);
266
267         return PREFERENCE_ERROR_NONE;
268 }
269
270 static int _preference_set_file_lock(int fd, short type)
271 {
272         struct flock l;
273
274         l.l_type = 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*/
278
279         return fcntl(fd, F_SETLK, &l);
280 }
281
282 static int _preference_get_pid_of_file_lock_owner(int fd, short type)
283 {
284         struct flock l;
285
286         l.l_type = 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*/
290
291         if(fcntl(fd, F_GETLK, &l) < 0) {
292                 WARN("error in getting lock info");
293                 return -1;
294         }
295
296         if(l.l_type == F_UNLCK)
297                 return 0;
298         else
299                 return l.l_pid;
300 }
301
302
303 static int _preference_set_read_lock(int fd)
304 {
305         return _preference_set_file_lock(fd, F_RDLCK);
306 }
307
308 static int _preference_set_write_lock(int fd)
309 {
310         return _preference_set_file_lock(fd, F_WRLCK);
311 }
312
313 static int _preference_set_unlock(int fd)
314 {
315         return _preference_set_file_lock(fd, F_UNLCK);
316 }
317
318 static void _preference_log_subject_label(void)
319 {
320         int fd;
321         int ret;
322         char smack_label[256] = {0,};
323         char curren_path[256] = {0,};
324         int tid;
325
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);
329         if (fd < 0) {
330                 LOGE("fail to open self current attr (err: %s)", strerror(errno));
331                 return;
332         }
333
334         ret = read(fd, smack_label, sizeof(smack_label)-1);
335         if (ret < 0) {
336                 close(fd);
337                 LOGE("fail to open self current attr (err: %s)", strerror(errno));
338                 return;
339         }
340
341         ERR("current(%d) subject label : %s", tid, smack_label);
342
343         close(fd);
344 }
345
346 static int _preference_check_retry_err(keynode_t *keynode, int preference_errno, int io_errno, int op_type)
347 {
348         int is_busy_err = 0;
349
350         if (preference_errno == PREFERENCE_ERROR_FILE_OPEN)
351         {
352                 switch (io_errno)
353                 {
354                         case ENOENT :
355                         {
356                                 if(op_type == PREFERENCE_OP_SET)
357                                 {
358                                         int rc = 0;
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();
364                                                 break;
365                                         }
366
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();
371                                                 break;
372                                         }
373
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();
378                                                 break;
379                                         }
380                                         INFO("%s key is created", keynode->keyname);
381
382                                         is_busy_err = 1;
383                                 }
384                                 break;
385                         }
386                         case EACCES :
387                         {
388                                 _preference_log_subject_label();
389                                 break;
390                         }
391                         case EAGAIN :
392                         case EMFILE :
393                         case ENFILE :
394                         case ETXTBSY :
395                         {
396                                 is_busy_err = 1;
397                         }
398                 }
399         }
400         else if (preference_errno == PREFERENCE_ERROR_FILE_CHMOD)
401         {
402                 switch (io_errno)
403                 {
404                         case EINTR :
405                         case EBADF :
406                         {
407                                 is_busy_err = 1;
408                         }
409                 }
410         }
411         else if (preference_errno == PREFERENCE_ERROR_FILE_LOCK)
412         {
413                 switch (io_errno)
414                 {
415                         case EBADF :
416                         case EAGAIN :
417                         case ENOLCK :
418                         {
419                                 is_busy_err = 1;
420                         }
421                 }
422         }
423         else if (preference_errno == PREFERENCE_ERROR_FILE_WRITE)
424         {
425                 switch (io_errno)
426                 {
427                         case 0 :
428                         case EAGAIN :
429                         case EINTR :
430                         case EIO :
431                         case ENOMEM :
432                         {
433                                 is_busy_err = 1;
434                         }
435                 }
436         }
437         else if (preference_errno == PREFERENCE_ERROR_FILE_FREAD)
438         {
439                 switch (io_errno)
440                 {
441                         case EAGAIN :
442                         case EINTR :
443                         case EIO :
444                         {
445                                 is_busy_err = 1;
446                         }
447                 }
448         }
449         else
450         {
451                 is_busy_err = 0;
452         }
453
454         if (is_busy_err == 1) {
455                 return 1;
456         }
457         else
458         {
459                 ERR("key(%s), check retry err: %d/(%d/%s).",keynode->keyname, preference_errno, io_errno, strerror(io_errno));
460                 return 0;
461         }
462 }
463
464 static int _preference_set_key_filesys(keynode_t *keynode, int *io_errno)
465 {
466         char path[PATH_MAX] = {0,};
467         FILE *fp = NULL;
468         int ret = -1;
469         int func_ret = PREFERENCE_ERROR_NONE;
470         int err_no = 0;
471         char err_buf[100] = { 0, };
472         int is_write_error = 0;
473         int retry_cnt = 0;
474         size_t keyname_len = 0;
475
476 retry_open :
477         errno = 0;
478         err_no = 0;
479         func_ret = PREFERENCE_ERROR_NONE;
480
481         ret = _preference_get_key_path(keynode, path);
482         retv_if(ret != PREFERENCE_ERROR_NONE, ret);
483
484         if( (fp = fopen(path, "r+")) == NULL ) {
485                 func_ret = PREFERENCE_ERROR_FILE_OPEN;
486                 err_no = errno;
487                 goto out_return;
488         }
489
490 retry :
491         errno = 0;
492         err_no = 0;
493         func_ret = PREFERENCE_ERROR_NONE;
494
495         ret = _preference_set_write_lock(fileno(fp));
496         if (ret == -1) {
497                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
498                 err_no = errno;
499                 ERR("file(%s) lock owner(%d)",
500                         keynode->keyname,
501                         _preference_get_pid_of_file_lock_owner(fileno(fp), F_WRLCK));
502                 goto out_return;
503         }
504
505         /* write keyname and size */
506         keyname_len = strlen(keynode->keyname);
507
508         ret = fwrite((void *)&keyname_len, sizeof(int), 1, fp);
509         if (ret <= 0) {
510                 if (!errno) {
511                         LOGW("number of written items is 0. try again");
512                         errno = EAGAIN;
513                 }
514                 err_no = errno;
515                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
516                 goto out_unlock;
517         }
518
519         ret = fwrite((void *)keynode->keyname, keyname_len, 1, fp);
520         if (ret <= 0) {
521                 if (!errno) {
522                         LOGW("number of written items is 0. try again");
523                         errno = EAGAIN;
524                 }
525                 err_no = errno;
526                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
527                 goto out_unlock;
528         }
529
530         /* write key type */
531         ret = fwrite((void *)&(keynode->type), sizeof(int), 1, fp);
532         if (ret <= 0) {
533                 if (!errno) {
534                         LOGW("number of written items is 0. try again");
535                         errno = EAGAIN;
536                 }
537                 err_no = errno;
538                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
539                 goto out_unlock;
540         }
541
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;
547                 break;
548         case PREFERENCE_TYPE_DOUBLE:
549                 ret = fwrite((void *)&(keynode->value.d), sizeof(double), 1, fp);
550                 if (ret <= 0) is_write_error = 1;
551                 break;
552         case PREFERENCE_TYPE_BOOLEAN:
553                 ret = fwrite((void *)&(keynode->value.b), sizeof(int), 1, fp);
554                 if (ret <= 0) is_write_error = 1;
555                 break;
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)
560                         is_write_error = 1;
561                 break;
562         default :
563                 func_ret = PREFERENCE_ERROR_WRONG_TYPE;
564                 goto out_unlock;
565         }
566
567         if (is_write_error) {
568                 if (!errno) {
569                         LOGW("number of written items is 0. try again");
570                         errno = EAGAIN;
571                 }
572                 err_no = errno;
573                 func_ret = PREFERENCE_ERROR_FILE_WRITE;
574                 goto out_unlock;
575         }
576
577         fflush(fp);
578
579 out_unlock :
580         ret = _preference_set_unlock(fileno(fp));
581         if (ret == -1) {
582                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
583                 err_no = errno;
584                 goto out_return;
585         }
586
587 out_return :
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);
593                                 retry_cnt++;
594                                 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
595
596                                 if (fp)
597                                         goto retry;
598                                 else
599                                         goto retry_open;
600                         } else {
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);
603                         }
604                 } else {
605                         ERR("_preference_set_key_filesys(%d-%s) step(%d) failed(%d / %s)\n", keynode->type, keynode->keyname, func_ret, err_no, err_buf);
606                 }
607         } else {
608                 if(retry_cnt > 0) {
609                         DBG("_preference_set_key_filesys ok with retry cnt(%d)", retry_cnt);
610                 }
611         }
612
613         if (fp) {
614                 if (func_ret == PREFERENCE_ERROR_NONE) {
615                         ret = fdatasync(fileno(fp));
616                         if (ret == -1) {
617                                 err_no = errno;
618                                 func_ret = PREFERENCE_ERROR_FILE_SYNC;
619                         }
620                 }
621                 fclose(fp);
622         }
623         *io_errno = err_no;
624
625         return func_ret;
626 }
627
628 static int _preference_set_key(keynode_t *keynode)
629 {
630         int ret = 0;
631         int io_errno = 0;
632         char err_buf[100] = { 0, };
633
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;
638         } else {
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;
643         }
644
645         return ret;
646 }
647
648
649 /*
650  * This function set the integer value of given key
651  * @param[in]   key     key
652  * @param[in]   intval integer value to set
653  * @return 0 on success, -1 on error
654  */
655 API int preference_set_int(const char *key, int intval)
656 {
657         START_TIME_CHECK
658
659         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
660
661         int func_ret = PREFERENCE_ERROR_NONE;
662
663         keynode_t* pKeyNode = _preference_keynode_new();
664         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
665
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;
671         }
672         _preference_keynode_set_value_int(pKeyNode, intval);
673
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;
677         } else {
678                 INFO("%s(%d) success", key, intval);
679         }
680
681         _preference_keynode_free(pKeyNode);
682
683         END_TIME_CHECK
684
685         return func_ret;
686 }
687
688 /*
689 * This function set the boolean value of given key
690 * @param[in]    key     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
694 */
695 API int preference_set_boolean(const char *key, bool boolval)
696 {
697         START_TIME_CHECK
698
699         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
700
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");
704
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;
710         }
711         _preference_keynode_set_value_boolean(pKeyNode, boolval);
712
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;
716         } else {
717                 INFO("%s(%d) success", key, boolval);
718         }
719
720         _preference_keynode_free(pKeyNode);
721
722         END_TIME_CHECK
723
724         return func_ret;
725 }
726
727 /*
728  * This function set the double value of given key
729  * @param[in]   key     key
730  * @param[in]   dblval double value to set
731  * @return 0 on success, -1 on error
732  */
733 API int preference_set_double(const char *key, double dblval)
734 {
735         START_TIME_CHECK
736
737         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is NULL");
738
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");
742
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;
748         }
749         _preference_keynode_set_value_double(pKeyNode, dblval);
750
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;
754         } else {
755                 INFO("%s(%f) success", key, dblval);
756         }
757
758         _preference_keynode_free(pKeyNode);
759
760         END_TIME_CHECK
761
762         return func_ret;
763 }
764
765 /*
766  * This function set the string value of given key
767  * @param[in]   key     key
768  * @param[in]   strval string value to set
769  * @return 0 on success, -1 on error
770  */
771 API int preference_set_string(const char *key, const char *strval)
772 {
773         START_TIME_CHECK
774
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");
777
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");
781
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;
787         }
788         _preference_keynode_set_value_string(pKeyNode, strval);
789
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;
793         } else {
794                 INFO("%s(%s) success", key, strval);
795         }
796
797         _preference_keynode_free(pKeyNode);
798
799         END_TIME_CHECK
800
801         return func_ret;
802 }
803
804 static int _preference_get_key_filesys(keynode_t *keynode, int* io_errno)
805 {
806         char path[PATH_MAX] = {0,};
807         int ret = -1;
808         int func_ret = PREFERENCE_ERROR_NONE;
809         char err_buf[100] = { 0, };
810         int err_no = 0;
811         int type = 0;
812         FILE *fp = NULL;
813         int retry_cnt = 0;
814         int read_size = 0;
815         size_t keyname_len = 0;
816
817 retry_open :
818         errno = 0;
819         func_ret = PREFERENCE_ERROR_NONE;
820
821         ret = _preference_get_key_path(keynode, path);
822         retv_if(ret != PREFERENCE_ERROR_NONE, ret);
823
824         if( (fp = fopen(path, "r")) == NULL ) {
825                 func_ret = PREFERENCE_ERROR_FILE_OPEN;
826                 err_no = errno;
827                 goto out_return;
828         }
829
830 retry :
831         err_no = 0;
832         func_ret = PREFERENCE_ERROR_NONE;
833
834         ret = _preference_set_read_lock(fileno(fp));
835         if (ret == -1) {
836                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
837                 err_no = errno;
838                 goto out_return;
839         }
840
841         read_size = fread((void *)&keyname_len, sizeof(int), 1, fp);
842         if ((read_size <= 0) || (read_size > sizeof(int))) {
843                 if(!ferror(fp)) {
844                         errno = ENODATA;
845                 }
846                 err_no = errno;
847                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
848                 goto out_unlock;
849         }
850
851         ret = fseek(fp, keyname_len, SEEK_CUR);
852         if (ret) {
853                 if(!ferror(fp)) {
854                         errno = ENODATA;
855                 }
856                 err_no = errno;
857                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
858                 goto out_unlock;
859         }
860
861         read_size = fread((void *)&type, sizeof(int), 1, fp);
862         if (read_size <= 0) {
863                 if(!ferror(fp)) {
864                         errno = ENODATA;
865                 }
866                 err_no = errno;
867                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
868                 goto out_unlock;
869         }
870
871         /* read data value */
872         switch(type)
873         {
874                 case PREFERENCE_TYPE_INT:
875                 {
876                         int value_int = 0;
877                         read_size = fread((void*)&value_int, sizeof(int), 1, fp);
878                         if ((read_size <= 0) || (read_size > sizeof(int))) {
879                                 if (!ferror(fp)) {
880                                         LOGW("number of read items for value is wrong. err : %d", errno);
881                                 }
882                                 err_no = errno;
883                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
884                                 goto out_unlock;
885                         } else {
886                                 _preference_keynode_set_value_int(keynode, value_int);
887                         }
888
889                         break;
890                 }
891                 case PREFERENCE_TYPE_DOUBLE:
892                 {
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))) {
896                                 if (!ferror(fp)) {
897                                         LOGW("number of read items for value is wrong. err : %d", errno);
898                                 }
899                                 err_no = errno;
900                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
901                                 goto out_unlock;
902                         } else {
903                                 _preference_keynode_set_value_double(keynode, value_dbl);
904                         }
905
906                         break;
907                 }
908                 case PREFERENCE_TYPE_BOOLEAN:
909                 {
910                         int value_int = 0;
911                         read_size = fread((void*)&value_int, sizeof(int), 1, fp);
912                         if ((read_size <= 0) || (read_size > sizeof(int))) {
913                                 if (!ferror(fp)) {
914                                         LOGW("number of read items for value is wrong. err : %d", errno);
915                                 }
916                                 err_no = errno;
917                                 func_ret = PREFERENCE_ERROR_FILE_FREAD;
918                                 goto out_unlock;
919                         } else {
920                                 _preference_keynode_set_value_boolean(keynode, value_int);
921                         }
922
923                         break;
924                 }
925                 case PREFERENCE_TYPE_STRING:
926                 {
927                         char file_buf[BUF_LEN] = {0,};
928                         char *value = NULL;
929                         int value_size = 0;
930
931                         while(fgets(file_buf, sizeof(file_buf), fp))
932                         {
933                                 if (value) {
934                                         value_size = value_size + strlen(file_buf);
935                                         value = (char *) realloc(value, value_size);
936                                         if (value == NULL) {
937                                                 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
938                                                 break;
939                                         }
940                                         strncat(value, file_buf, strlen(file_buf));
941                                 } else {
942                                         value_size = strlen(file_buf) + 1;
943                                         value = (char *)malloc(value_size);
944                                         if (value == NULL) {
945                                                 func_ret = PREFERENCE_ERROR_OUT_OF_MEMORY;
946                                                 break;
947                                         }
948                                         memset(value, 0x00, value_size);
949                                         strncpy(value, file_buf, strlen(file_buf));
950                                 }
951                         }
952
953                         if (ferror(fp)) {
954                                 err_no = errno;
955                                 func_ret = PREFERENCE_ERROR_FILE_FGETS;
956                         } else {
957                                 if (value) {
958                                         _preference_keynode_set_value_string(keynode, value);
959                                 } else {
960                                         _preference_keynode_set_value_string(keynode, "");
961                                 }
962                         }
963                         if (value)
964                                 free(value);
965
966                         break;
967                 }
968                 default :
969                         func_ret = PREFERENCE_ERROR_WRONG_TYPE;
970         }
971
972 out_unlock :
973         ret = _preference_set_unlock(fileno(fp));
974         if (ret == -1) {
975                 func_ret = PREFERENCE_ERROR_FILE_LOCK;
976                 err_no = errno;
977                 goto out_return;
978         }
979
980
981 out_return :
982         if (func_ret != PREFERENCE_ERROR_NONE) {
983                 strerror_r(err_no, err_buf, 100);
984
985                 if (_preference_check_retry_err(keynode, func_ret, err_no, PREFERENCE_OP_GET)) {
986                         if (retry_cnt < PREFERENCE_ERROR_RETRY_CNT) {
987                                 retry_cnt++;
988                                 usleep((retry_cnt)*PREFERENCE_ERROR_RETRY_SLEEP_UTIME);
989
990                                 if (fp)
991                                         goto retry;
992                                 else
993                                         goto retry_open;
994                         }
995                         else {
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);
998                         }
999                 }
1000         }
1001
1002         if (fp)
1003                 fclose(fp);
1004
1005         *io_errno = err_no;
1006
1007         return func_ret;
1008 }
1009
1010 int _preference_get_key(keynode_t *keynode)
1011 {
1012         int ret = 0;
1013         int io_errno = 0;
1014         char err_buf[100] = {0,};
1015
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;
1020         }
1021         else {
1022                 if (io_errno == ENOENT)
1023                         ret = PREFERENCE_ERROR_NO_KEY;
1024                 else
1025                         ret = PREFERENCE_ERROR_IO_ERROR;
1026
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;
1031         }
1032
1033         return ret;
1034 }
1035
1036
1037 /*
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
1042  */
1043 API int preference_get_int(const char *key, int *intval)
1044 {
1045         START_TIME_CHECK
1046
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");
1049
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");
1053
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;
1059         }
1060
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);
1064         } else {
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;
1069                 } else {
1070                         ERR("The type(%d) of keynode(%s) is not INT", pKeyNode->type, pKeyNode->keyname);
1071                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1072                 }
1073         }
1074
1075         _preference_keynode_free(pKeyNode);
1076
1077         END_TIME_CHECK
1078
1079         return func_ret;
1080 }
1081
1082 /*
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
1087  */
1088 API int preference_get_boolean(const char *key, bool *boolval)
1089 {
1090         START_TIME_CHECK
1091
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");
1094
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");
1098
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;
1104         }
1105
1106         func_ret = _preference_get_key(pKeyNode);
1107
1108         if (func_ret != PREFERENCE_ERROR_NONE) {
1109                 ERR("preference_get_boolean(%d) : %s error", getpid(), key);
1110         } else {
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;
1115                 } else {
1116                         ERR("The type(%d) of keynode(%s) is not BOOL", pKeyNode->type, pKeyNode->keyname);
1117                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1118                 }
1119         }
1120
1121         _preference_keynode_free(pKeyNode);
1122
1123         END_TIME_CHECK
1124
1125         return func_ret;
1126 }
1127
1128 /*
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
1133  */
1134 API int preference_get_double(const char *key, double *dblval)
1135 {
1136         START_TIME_CHECK
1137
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");
1140
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");
1144
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;
1150         }
1151
1152         func_ret = _preference_get_key(pKeyNode);
1153
1154         if (func_ret != PREFERENCE_ERROR_NONE) {
1155                 ERR("preference_get_double(%d) : %s error", getpid(), key);
1156         } else {
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;
1161                 } else {
1162                         ERR("The type(%d) of keynode(%s) is not DBL", pKeyNode->type, pKeyNode->keyname);
1163                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1164                 }
1165         }
1166
1167         _preference_keynode_free(pKeyNode);
1168
1169         END_TIME_CHECK
1170
1171         return func_ret;
1172 }
1173
1174 /*
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
1179  */
1180 API int preference_get_string(const char *key, char **value)
1181 {
1182         START_TIME_CHECK
1183
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");
1186
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");
1190
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;
1196         }
1197
1198         char *tempstr = NULL;
1199         func_ret = _preference_get_key(pKeyNode);
1200
1201         if (func_ret != PREFERENCE_ERROR_NONE) {
1202                 ERR("preference_get_string(%d) : %s error", getpid(), key);
1203         } else {
1204                 if (pKeyNode->type == PREFERENCE_TYPE_STRING)
1205                         tempstr = pKeyNode->value.s;
1206                 else {
1207                         ERR("The type(%d) of keynode(%s) is not STR", pKeyNode->type, pKeyNode->keyname);
1208                         func_ret = PREFERENCE_ERROR_INVALID_PARAMETER;
1209                 }
1210
1211                 if(tempstr) {
1212                         *value = strdup(tempstr);
1213                         INFO("%s(%s) success", key, value);
1214                 }
1215         }
1216
1217         _preference_keynode_free(pKeyNode);
1218
1219         END_TIME_CHECK
1220
1221         return func_ret;
1222 }
1223
1224 /*
1225  * This function unset given key
1226  * @param[in]   key     key
1227  * @return 0 on success, -1 on error
1228  */
1229 API int preference_remove(const char *key)
1230 {
1231         START_TIME_CHECK
1232
1233         char path[PATH_MAX] = {0,};
1234         int ret = -1;
1235         int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1236         int func_ret = PREFERENCE_ERROR_NONE;
1237
1238         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1239
1240         keynode_t* pKeyNode = _preference_keynode_new();
1241         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1242
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;
1248         }
1249
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;
1255         }
1256
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;
1261         }
1262
1263         do {
1264                 ret = remove(path);
1265                 if(ret == -1) {
1266                         ERR("preference_remove() failed. ret=%d(%s), key(%s)", errno, strerror(errno), key);
1267                         func_ret = PREFERENCE_ERROR_IO_ERROR;
1268                 } else {
1269                         func_ret = PREFERENCE_ERROR_NONE;
1270                         break;
1271                 }
1272         } while(err_retry--);
1273
1274         END_TIME_CHECK;
1275
1276         _preference_keynode_free(pKeyNode);
1277
1278         return func_ret;
1279 }
1280
1281 API int preference_remove_all(void)
1282 {
1283         START_TIME_CHECK
1284
1285         int ret = -1;
1286         int err_retry = PREFERENCE_ERROR_RETRY_CNT;
1287         int func_ret = PREFERENCE_ERROR_NONE;
1288         DIR *dir;
1289         struct dirent *dent = NULL;
1290         char *pref_dir_path = NULL;
1291
1292         pref_dir_path = _preference_get_pref_dir_path();
1293         if (!pref_dir_path)
1294         {
1295                 LOGE("_preference_get_pref_dir_path() failed.");
1296                 return PREFERENCE_ERROR_IO_ERROR;
1297         }
1298
1299         dir = opendir(pref_dir_path);
1300         if (dir == NULL)
1301         {
1302                 LOGE("opendir() failed. pref_path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1303                 return PREFERENCE_ERROR_IO_ERROR;
1304         }
1305
1306         keynode_t* pKeyNode = _preference_keynode_new();
1307         if (pKeyNode == NULL)
1308         {
1309                 ERR("key malloc fail");
1310                 closedir(dir);
1311                 return PREFERENCE_ERROR_OUT_OF_MEMORY;
1312         }
1313
1314         while ((dent = readdir(dir)))
1315         {
1316                 const char *entry = dent->d_name;
1317                 char *keyname = NULL;
1318                 char path[PATH_MAX] = {0,};
1319
1320                 if (entry[0] == '.') {
1321                         continue;
1322                 }
1323
1324                 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, entry);
1325
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);
1330                         closedir(dir);
1331                         return ret;
1332                 }
1333
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);
1338                         closedir(dir);
1339                         free(keyname);
1340                         return PREFERENCE_ERROR_IO_ERROR;
1341                 }
1342
1343                 do {
1344                         ret = remove(path);
1345                         if (ret == -1) {
1346                                 ERR("preference_remove_all error: %d(%s)", errno, strerror(errno));
1347                                 func_ret = PREFERENCE_ERROR_IO_ERROR;
1348                         } else {
1349                                 func_ret = PREFERENCE_ERROR_NONE;
1350                                 break;
1351                         }
1352                 } while(err_retry--);
1353
1354                 free(keyname);
1355         }
1356
1357         _preference_keynode_free(pKeyNode);
1358         closedir(dir);
1359
1360         END_TIME_CHECK
1361
1362         return func_ret;
1363 }
1364
1365 int preference_is_existing(const char *key, bool *exist)
1366 {
1367         START_TIME_CHECK
1368
1369         char path[PATH_MAX] = {0,};
1370         int ret = -1;
1371         int func_ret = PREFERENCE_ERROR_NONE;
1372
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");
1375
1376         keynode_t* pKeyNode = _preference_keynode_new();
1377         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1378
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;
1384         }
1385
1386         ret = _preference_get_key_path(pKeyNode, path);
1387         if (ret != PREFERENCE_ERROR_NONE) {
1388                 _preference_keynode_free(pKeyNode);
1389                 return ret;
1390         }
1391
1392         ret = access(path, F_OK);
1393         if (ret == -1) {
1394                 ERR("Error : key(%s) is not exist", key);
1395                 *exist = 0;
1396         } else {
1397                 *exist = 1;
1398         }
1399
1400         _preference_keynode_free(pKeyNode);
1401
1402         END_TIME_CHECK
1403
1404         return func_ret;
1405 }
1406
1407
1408 API int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
1409 {
1410         START_TIME_CHECK
1411
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);
1414
1415         int func_ret = PREFERENCE_ERROR_IO_ERROR;
1416
1417         keynode_t* pKeyNode = _preference_keynode_new();
1418         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1419
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;
1425         }
1426
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;
1436                 }
1437         }
1438         INFO("%s noti is added", key);
1439         _preference_keynode_free(pKeyNode);
1440
1441         END_TIME_CHECK
1442
1443         return PREFERENCE_ERROR_NONE;
1444 }
1445
1446 API int preference_unset_changed_cb(const char *key)
1447 {
1448         START_TIME_CHECK
1449
1450         int func_ret = PREFERENCE_ERROR_IO_ERROR;
1451
1452         retvm_if(key == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: key is null");
1453
1454         keynode_t* pKeyNode = _preference_keynode_new();
1455         retvm_if(pKeyNode == NULL, PREFERENCE_ERROR_OUT_OF_MEMORY, "key malloc fail");
1456
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;
1462         }
1463
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;
1473                 }
1474         }
1475         INFO("%s noti removed", key);
1476         _preference_keynode_free(pKeyNode);
1477
1478         END_TIME_CHECK
1479
1480         return PREFERENCE_ERROR_NONE;
1481 }
1482
1483
1484 API int preference_foreach_item(preference_item_cb callback, void *user_data)
1485 {
1486         START_TIME_CHECK
1487
1488         retvm_if(callback == NULL, PREFERENCE_ERROR_INVALID_PARAMETER, "Invalid argument: cb(%p)", callback);
1489
1490         int ret = 0;
1491         DIR *dir;
1492         struct dirent *dent = NULL;
1493         char *pref_dir_path = NULL;
1494
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;
1499         }
1500
1501         dir = opendir(pref_dir_path);
1502         if (dir == NULL) {
1503                 LOGE("opendir() failed. path: %s, error: %d(%s)", pref_dir_path, errno, strerror(errno));
1504                 return PREFERENCE_ERROR_IO_ERROR;
1505         }
1506
1507         while((dent = readdir(dir))) {
1508                 const char *entry = dent->d_name;
1509                 char *keyname = NULL;
1510                 char path[PATH_MAX] = {0,};
1511
1512                 if (entry[0] == '.') {
1513                         continue;
1514                 }
1515
1516                 snprintf(path, PATH_MAX-1, "%s%s", pref_dir_path, entry);
1517
1518                 ret = _preference_get_key_name(path, &keyname);
1519                 retv_if(ret != PREFERENCE_ERROR_NONE, ret);
1520
1521                 callback(keyname, user_data);
1522                 free(keyname);
1523         }
1524
1525         closedir(dir);
1526         END_TIME_CHECK
1527
1528         return PREFERENCE_ERROR_NONE;
1529 }