Tizen 2.1 base
[framework/multimedia/media-server.git] / common / media-server-inotify.c
1 /*
2  *  Media Server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /**
23  * This file defines api utilities of contents manager engines.
24  *
25  * @file                media-server-inotify.c
26  * @author      Yong Yeon Kim(yy9875.kim@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30 #include <errno.h>
31 #include <dirent.h>
32 #include <malloc.h>
33 #include <vconf.h>
34
35 #include "media-util.h"
36 #include "media-server-dbg.h"
37 #include "media-server-utils.h"
38 #include "media-server-db-svc.h"
39 #include "media-server-inotify-internal.h"
40 #include "media-server-inotify.h"
41
42 #if MS_INOTI_ENABLE
43
44 bool power_off;
45 extern int inoti_fd;
46 extern int mmc_state;
47 ms_inoti_dir_data *first_inoti_node;
48 ms_ignore_file_info *latest_ignore_file;
49
50 int _ms_inoti_directory_scan_and_register_file(void **handle, char *dir_path)
51 {
52         struct dirent ent;
53         struct dirent *res = NULL;
54         DIR *dp = NULL;
55         char path[MS_FILE_PATH_LEN_MAX] = { 0 };
56         int err;
57
58         if (dir_path == NULL)
59                 return MS_MEDIA_ERR_INVALID_PATH;
60
61         dp = opendir(dir_path);
62         if (dp == NULL) {
63                 MS_DBG_ERR("Fail to open dir %s", dir_path);
64                 return MS_MEDIA_ERR_DIR_OPEN_FAIL;
65         }
66
67         ms_inoti_add_watch(dir_path);
68
69         while (!readdir_r(dp, &ent, &res)) {
70                 if (res == NULL)
71                         break;
72
73                 if (ent.d_name[0] == '.')
74                         continue;
75
76                 err = ms_strappend(path, sizeof(path), "%s/%s", dir_path, ent.d_name);
77                 if (err != MS_MEDIA_ERR_NONE) {
78                         MS_DBG_ERR("ms_strappend error : %d", err);
79                         continue;
80                 }
81
82                 /*in case of directory */
83                 if (ent.d_type == DT_DIR) {
84                         _ms_inoti_directory_scan_and_register_file(handle, path);
85                 } else {
86                         err = ms_register_file(handle, path, NULL);
87                         if (err != MS_MEDIA_ERR_NONE) {
88                                 MS_DBG_ERR("ms_register_file error : %d", err);
89                                 continue;
90                         }
91                 }
92         }
93
94         closedir(dp);
95
96         return 0;
97 }
98
99 int _ms_inoti_scan_renamed_folder(void **handle, char *org_path, char *chg_path)
100 {
101         int err = -1;
102         struct dirent ent;
103         struct dirent *res = NULL;
104
105         DIR *dp = NULL;
106         char path_from[MS_FILE_PATH_LEN_MAX] = { 0 };
107         char path_to[MS_FILE_PATH_LEN_MAX] = { 0 };
108         ms_storage_type_t src_storage = 0;
109         ms_storage_type_t des_storage = 0;
110
111         if (org_path == NULL || chg_path == NULL) {
112                 MS_DBG_ERR("Parameter is wrong");
113                 return MS_MEDIA_ERR_INVALID_PARAMETER;
114         }
115
116         dp = opendir(chg_path);
117         if (dp == NULL) {
118                 MS_DBG_ERR("Fail to open dir %s", chg_path);
119                 return MS_MEDIA_ERR_DIR_OPEN_FAIL;
120         } else {
121                 MS_DBG("Modify added watch");
122                 ms_inoti_modify_watch(org_path, chg_path);
123         }
124
125         while (!readdir_r(dp, &ent, &res)) {
126                 if (res == NULL)
127                         break;
128
129                 if (ent.d_name[0] == '.')
130                         continue;
131
132                 err = ms_strappend(path_from, sizeof(path_from), "%s/%s", org_path, ent.d_name);
133                 if (err != MS_MEDIA_ERR_NONE) {
134                         MS_DBG_ERR("ms_strappend error : %d", err);
135                         continue;
136                 }
137
138                 err =  ms_strappend(path_to, sizeof(path_to), "%s/%s", chg_path, ent.d_name);
139                 if (err != MS_MEDIA_ERR_NONE) {
140                         MS_DBG_ERR("ms_strappend error : %d", err);
141                         continue;
142                 }
143
144                 /*in case of directory */
145                 if (ent.d_type == DT_DIR) {
146                         _ms_inoti_scan_renamed_folder(handle, path_from, path_to);
147                 }
148
149                 /*in case of file */
150                 if (ent.d_type == DT_REG) {
151                         src_storage = ms_get_storage_type_by_full(path_from);
152                         des_storage = ms_get_storage_type_by_full(path_to);
153
154                         if ((src_storage != MS_MEDIA_ERR_INVALID_PATH)
155                             && (des_storage != MS_MEDIA_ERR_INVALID_PATH))
156                                 ms_move_item(handle, src_storage, des_storage, path_from, path_to);
157                         else {
158                                 MS_DBG_ERR("src_storage : %s", src_storage);
159                                 MS_DBG_ERR("des_storage : %s", des_storage);
160                         }
161                 }
162         }
163
164         closedir(dp);
165
166         return 0;
167 }
168
169 int ms_inoti_add_ignore_file(const char *path)
170 {
171         ms_ignore_file_info *new_node;
172
173         new_node = ms_inoti_find_ignore_file(path);
174         if (new_node != NULL)
175                 return MS_MEDIA_ERR_NONE;
176
177         new_node = malloc(sizeof(ms_ignore_file_info));
178         new_node->path = strdup(path);
179
180         /*first created file */
181         if (latest_ignore_file == NULL) {
182                 latest_ignore_file = malloc(sizeof(ms_ignore_file_info));
183                 new_node->previous = NULL;
184         } else {
185                 latest_ignore_file->next = new_node;
186                 new_node->previous = latest_ignore_file;
187         }
188         new_node->next = NULL;
189
190         latest_ignore_file = new_node;
191
192         return MS_MEDIA_ERR_NONE;
193 }
194
195 int ms_inoti_delete_ignore_file(ms_ignore_file_info * delete_node)
196 {
197         if (delete_node->previous != NULL)
198                 delete_node->previous->next = delete_node->next;
199         if (delete_node->next != NULL)
200                 delete_node->next->previous = delete_node->previous;
201
202         if (delete_node == latest_ignore_file) {
203                 latest_ignore_file = delete_node->previous;
204         }
205
206         MS_SAFE_FREE(delete_node->path);
207         MS_SAFE_FREE(delete_node);
208
209
210         return MS_MEDIA_ERR_NONE;
211 }
212
213 ms_ignore_file_info *ms_inoti_find_ignore_file(const char *path)
214 {
215         ms_ignore_file_info *node = NULL;
216         
217         node = latest_ignore_file;
218         while (node != NULL) {
219                 if (strcmp(node->path, path) == 0) {
220                         return node;
221                 }
222
223                 node = node->previous;
224         }
225
226         return NULL;
227 }
228
229 void ms_inoti_delete_mmc_ignore_file(void)
230 {
231         ms_ignore_file_info *prv_node = NULL;
232         ms_ignore_file_info *cur_node = NULL;
233         ms_ignore_file_info *del_node = NULL;
234
235         if (latest_ignore_file != NULL) {
236                 cur_node = latest_ignore_file;
237                 while (cur_node != NULL) {
238                         if (strstr(cur_node->path, MEDIA_ROOT_PATH_SDCARD) != NULL) {
239                                 if (prv_node != NULL) {
240                                         prv_node->previous = cur_node->previous;
241                                 }
242
243                                 if (cur_node == latest_ignore_file)
244                                         latest_ignore_file = latest_ignore_file->previous;
245
246                                 del_node = cur_node;
247                         } else {
248                                 prv_node = cur_node;
249                         }
250
251                         cur_node = cur_node->previous;
252
253                         if (del_node != NULL) {
254                                 MS_SAFE_FREE(del_node->path);
255                                 MS_SAFE_FREE(del_node);
256                         }
257                 }
258         }
259
260         /*active flush */
261         malloc_trim(0);
262 }
263
264 int ms_inoti_init(void)
265 {
266         inoti_fd = inotify_init();
267         if (inoti_fd < 0) {
268                 perror("inotify_init");
269                 MS_DBG_ERR("inotify_init failed");
270                 return inoti_fd;
271         }
272
273         return MS_MEDIA_ERR_NONE;
274 }
275
276 void ms_inoti_add_watch(char *path)
277 {
278         ms_inoti_dir_data *current_dir = NULL;
279         ms_inoti_dir_data *prv_node = NULL;
280         ms_inoti_dir_data *last_node = NULL;
281
282         /*find same folder */
283         if (first_inoti_node != NULL) {
284                 last_node = first_inoti_node;
285                 while (last_node != NULL) {
286                         if (strcmp(path, last_node->name) == 0) {
287                                 MS_DBG("watch is already added: %s", path);
288                                 return;
289                         }
290                         prv_node = last_node;
291                         last_node = last_node->next;
292                 }
293         }
294
295         /*there is no same path. */
296         current_dir = malloc(sizeof(ms_inoti_dir_data));
297         current_dir->wd = inotify_add_watch(inoti_fd, path,
298                               IN_CLOSE_WRITE | IN_CREATE | IN_DELETE |
299                               IN_MOVED_FROM | IN_MOVED_TO);
300
301         if (current_dir->wd > 0) {
302                 current_dir->name = strdup(path);
303                 current_dir->next = NULL;
304
305                 if (first_inoti_node == NULL) {
306                         first_inoti_node = current_dir;
307                 } else {
308                         /*if next node of current node is NULL, it is the lastest node. */
309                         prv_node->next = current_dir;
310                 }
311                 MS_DBG("add watch : %s", path);
312         } else {
313                 MS_DBG_ERR("inotify_add_watch failed");
314                 MS_SAFE_FREE(current_dir);
315         }
316 }
317
318 int ms_inoti_add_watch_with_node(ms_dir_scan_info * const node, int depth)
319 {
320         int err;
321         char full_path[MS_FILE_PATH_LEN_MAX] = { 0 };
322         ms_inoti_dir_data *current_dir = NULL;
323         ms_inoti_dir_data *prv_node = NULL;
324         ms_inoti_dir_data *last_node = NULL;
325
326         err = ms_get_full_path_from_node(node, full_path, depth);
327         if (err != MS_MEDIA_ERR_NONE)
328                 return MS_MEDIA_ERR_INVALID_PATH;
329
330         /*find same folder */
331         if (first_inoti_node != NULL) {
332                 last_node = first_inoti_node;
333                 while (last_node != NULL) {
334                         if (strcmp(full_path, last_node->name) == 0) {
335                                 return MS_MEDIA_ERR_NONE;
336                         }
337                         prv_node = last_node;
338                         last_node = last_node->next;
339                 }
340         }
341
342         /*there is no same path. */
343         current_dir = malloc(sizeof(ms_inoti_dir_data));
344         current_dir->wd = inotify_add_watch(inoti_fd, full_path,
345                               IN_CLOSE_WRITE | IN_CREATE | IN_DELETE |
346                               IN_MOVED_FROM | IN_MOVED_TO);
347         if( current_dir->wd > 0) {
348                 current_dir->name = strdup(full_path);
349                 current_dir->next = NULL;
350
351                 if (first_inoti_node == NULL) {
352                         first_inoti_node = current_dir;
353                 } else {
354                         /*if next node of current node is NULL, it is the lastest node. */
355                         prv_node->next = current_dir;
356                 }
357                 MS_DBG("add watch : %s", full_path);
358         } else {
359                 MS_DBG_ERR("inotify_add_watch  failed : %d", current_dir->wd);
360                 MS_SAFE_FREE(current_dir);
361         }
362
363         return MS_MEDIA_ERR_NONE;
364 }
365
366 void ms_inoti_remove_watch_recursive(char *path)
367 {
368         ms_inoti_dir_data *prv_node = NULL;
369         ms_inoti_dir_data *cur_node = NULL;
370         ms_inoti_dir_data *del_node = NULL;
371
372         if (first_inoti_node != NULL) {
373                 cur_node = first_inoti_node;
374                 while (cur_node != NULL) {
375                         if (strstr(cur_node->name, path) != NULL) {
376                                 if (prv_node != NULL) {
377                                         prv_node->next =
378                                             cur_node->next;
379                                 }
380
381                                 if (cur_node == first_inoti_node)
382                                         first_inoti_node =
383                                             first_inoti_node->next;
384
385                                 del_node = cur_node;
386                         } else {
387                                 prv_node = cur_node;
388                         }
389
390                         cur_node = cur_node->next;
391
392                         if (del_node != NULL) {
393                                 MS_SAFE_FREE(del_node->name);
394                                 MS_SAFE_FREE(del_node);
395                         }
396                 }
397         }
398
399         /*active flush */
400          malloc_trim(0);
401 }
402
403 void ms_inoti_remove_watch(char *path)
404 {
405         ms_inoti_dir_data *del_node = NULL;
406         ms_inoti_dir_data *prv_node = NULL;
407
408         if (strcmp(first_inoti_node->name, path) == 0) {
409                 del_node = first_inoti_node;
410                 first_inoti_node = first_inoti_node->next;
411         } else {
412                 /*find same folder */
413                 if (first_inoti_node != NULL) {
414                         del_node = first_inoti_node;
415                         while (del_node != NULL) {
416                                 MS_DBG("current node %s", del_node->name);
417                                 if (strcmp(path, del_node->name) == 0) {
418                                         MS_DBG("find delete node: %s", del_node->name);
419                                         if (prv_node != NULL) {
420                                                 MS_DBG("previous_node : %s", prv_node->name);
421                                                 prv_node->next = del_node->next;
422                                         }
423                                         /*free deleted node */
424                                         MS_SAFE_FREE(del_node->name);
425                                         MS_SAFE_FREE(del_node);
426                                         break;
427                                 }
428                                 prv_node = del_node;
429                                 del_node = del_node->next;
430                         }
431                 }
432         }
433
434         /*active flush */
435         malloc_trim(0);
436 }
437
438 void ms_inoti_modify_watch(char *path_from, char *path_to)
439 {
440         bool find = false;
441         ms_inoti_dir_data *mod_node;
442
443         if (strcmp(first_inoti_node->name, path_from) == 0) {
444                 mod_node = first_inoti_node;
445         } else {
446                 /*find same folder */
447                 if (first_inoti_node != NULL) {
448                         mod_node = first_inoti_node;
449                         while (mod_node != NULL) {
450                                 /*find previous directory*/
451                                 if (strcmp(path_from, mod_node->name) == 0) { 
452                                         /*change path of directory*/
453                                         /*free previous name of node */
454                                         MS_SAFE_FREE(mod_node->name);
455
456                                         /*add new name */
457                                         mod_node->name = strdup(path_to);
458
459                                         /*active flush */
460                                         malloc_trim(0);
461
462                                         find = true;
463                                         break;
464                                 }
465                                 mod_node = mod_node->next;
466                         }
467                 }
468         }
469
470         /*this is new directory*/
471         if (find == false) {
472                 ms_inoti_add_watch(path_to);
473         }
474 }
475
476 #define STOP_INOTI "stop_inoti"
477
478 gboolean ms_inoti_thread(void *data)
479 {
480         uint32_t i;
481         int length;
482         int err;
483         int prev_mask = 0;
484         int prev_wd = -1;
485         bool res;
486         char name[MS_FILE_NAME_LEN_MAX + 1] = { 0 };
487         char prev_name[MS_FILE_NAME_LEN_MAX + 1] = { 0 };
488         char buffer[INOTI_BUF_LEN] = { 0 };
489         char path[MS_FILE_PATH_LEN_MAX] = { 0 };
490         struct inotify_event *event;
491         void **handle = NULL;
492
493         MS_DBG("START INOTIFY");
494
495         err = ms_connect_db(&handle);
496         if (err != MS_MEDIA_ERR_NONE) {
497                 MS_DBG_ERR(" INOTIFY : sqlite3_open: ret = %d", err);
498                 return false;
499         }
500
501         while (1) {
502                 i = 0;
503                 length = read(inoti_fd, buffer, sizeof(buffer) - 1);
504
505                 if (length < 0 || length > sizeof(buffer)) {    /*this is error */
506                         continue;
507                 }
508
509                 while (i < length && i < INOTI_BUF_LEN) {
510                         /*check poweroff status*/
511                         if(power_off) {
512                                 MS_DBG("power off");
513                                 goto _POWEROFF;
514                         }
515
516                         /*it's possible that ums lets reset phone data... */
517                         event = (struct inotify_event *)&buffer[i];
518
519                         if (strcmp(event->name, POWEROFF_DIR_NAME) == 0) {
520                                 MS_DBG("power off");
521                                 goto _POWEROFF;
522                         } else if (strcmp(event->name, STOP_INOTI) == 0) {
523                                 MS_DBG("stop inotify thread");
524                                 goto _POWEROFF;
525                         } else if (event->name[0] == '.') {
526                                 /*event of hidden folder is ignored */
527                                 goto NEXT_INOTI_EVENT;
528                         } else if (event->wd < 1) {
529                                 /*this is error */
530                                 MS_DBG_ERR("invalid wd : %d", event->wd);
531                                 goto NEXT_INOTI_EVENT;
532                         }
533
534                         /*start of one event */
535                         if (event->len && (event->len <= MS_FILE_NAME_LEN_MAX + 1)) {
536                                 /*Add for fixing prevent defect 2011-02-15 */
537                                 err = ms_strcopy(name, sizeof(name), "%s", event->name);
538                                 if (err != MS_MEDIA_ERR_NONE) {
539                                         MS_DBG_ERR("ms_strcopy error : %d", err);
540                                         goto NEXT_INOTI_EVENT;
541                                 }
542
543                                 /*get full path of file or directory */
544                                 res = _ms_inoti_get_full_path(event->wd, name, path, sizeof(path));
545                                 if (res == false) {
546                                         MS_DBG_ERR("_ms_inoti_get_full_path error");
547                                         goto NEXT_INOTI_EVENT;
548                                 }
549
550                                 MS_DBG("INOTIFY[%d : %s]", event->wd, name);
551                                 if (event->mask & IN_ISDIR) {
552                                         MS_DBG("DIRECTORY INOTIFY");
553                                         
554                                         if (event->mask & IN_MOVED_FROM) {
555                                                 MS_DBG("MOVED_FROM");
556
557                                                 prev_mask = event->mask;
558                                                 prev_wd = event->wd;
559
560                                                 err = ms_strcopy(prev_name, sizeof(prev_name), "%s", event->name);
561                                                 if (err != MS_MEDIA_ERR_NONE) {
562                                                         MS_DBG_ERR("ms_strcopy fail");
563                                                         goto NEXT_INOTI_EVENT;
564                                                 }
565                                         } 
566                                         else if (event->mask & IN_MOVED_TO) {
567                                                 MS_DBG("MOVED_TO");
568
569                                                 char full_path_from[MS_FILE_PATH_LEN_MAX] = { 0 };
570
571                                                 res = _ms_inoti_get_full_path(prev_wd, prev_name, full_path_from, sizeof(full_path_from));
572                                                 if (res == false) {
573                                                         MS_DBG_ERR("_ms_inoti_get_full_path error");
574                                                         goto NEXT_INOTI_EVENT;
575                                                 }
576                                                 /*enable bundle commit*/
577                                                 ms_move_start(handle);
578
579                                                 /*need update file information under renamed directory */
580                                                 _ms_inoti_scan_renamed_folder(handle, full_path_from, path);
581
582                                                 /*disable bundle commit*/
583                                                 ms_move_end(handle);
584
585                                                 prev_mask = prev_wd = 0;        /*reset */
586                                         }
587                                         else if (event->mask & IN_CREATE) {
588                                                 MS_DBG("CREATE");
589
590                                                 _ms_inoti_directory_scan_and_register_file(handle, path);
591                                                 prev_mask = event->mask;
592                                         }
593                                         else if (event->mask & IN_DELETE) {
594                                                 MS_DBG("DELETE");
595
596                                                 ms_inoti_remove_watch(path);
597                                         }
598                                 }
599                                 else {
600                                         MS_DBG("FILE INOTIFY");
601
602                                         if (event->mask & IN_MOVED_FROM) {
603                                                 MS_DBG("MOVED_FROM");
604
605                                                 err = ms_delete_item(handle, path);
606                                                 if (err != MS_MEDIA_ERR_NONE) {
607                                                         MS_DBG_ERR("ms_media_db_delete fail error : %d", err);
608                                                 }
609                                         }
610                                         else if (event->mask & IN_MOVED_TO) {
611                                                 MS_DBG("MOVED_TO");
612
613                                                 err = ms_register_file(handle, path, NULL);
614                                                 if (err != MS_MEDIA_ERR_NONE) {
615                                                         MS_DBG_ERR("ms_register_file error : %d", err);
616                                                 }
617                                         }
618                                         else if (event->mask & IN_CREATE) {
619                                                 MS_DBG("CREATE");
620
621                                                 _ms_inoti_add_create_file_list(event->wd, name);
622                                         }
623                                         else if (event->mask & IN_DELETE) {
624                                                 MS_DBG("DELETE");
625                                                 
626                                                 err = ms_delete_item(handle, path);
627                                                 if (err != MS_MEDIA_ERR_NONE) {
628                                                         MS_DBG_ERR("ms_media_db_delete error : %d", err);
629                                                 }
630                                         }
631                                         else if (event->mask & IN_CLOSE_WRITE) {
632                                                 MS_DBG("CLOSE_WRITE");
633                                                 ms_create_file_info *node;
634
635                                                 node = _ms_inoti_find_create_file_list (event->wd, name);
636                                                 if (node != NULL || ((prev_mask & IN_ISDIR) & IN_CREATE)) {
637                                                         err = ms_register_file(handle, path, NULL);
638                                                         if (err != MS_MEDIA_ERR_NONE) {
639                                                                 MS_DBG_ERR("ms_register_file error : %d", err);
640                                                         }
641                                                         if (node != NULL)
642                                                                 _ms_inoti_delete_create_file_list(node);
643                                                 }
644                                                 else {
645                                                         ms_ignore_file_info  *ignore_file;
646
647                                                         ignore_file = ms_inoti_find_ignore_file(path);
648                                                         if (ignore_file == NULL) {
649                                                                 /*in case of replace */
650                                                                 MS_DBG("This case is replacement or changing meta data.");
651                                                                 err = ms_refresh_item(handle, path);
652                                                                 if (err != MS_MEDIA_ERR_NONE) {
653                                                                         MS_DBG_ERR("ms_refresh_item error : %d", err);
654                                                                         goto NEXT_INOTI_EVENT;
655                                                                 }
656                                                         } else {
657                                                                 /*This is ignore case*/
658                                                         }
659                                                 }
660                                                 prev_mask = prev_wd = 0;        /*reset */
661                                         }
662                                 }
663                         } /*end of one event */
664                         else {
665                                 /*This is ignore case*/
666                                 if (event->mask & IN_IGNORED) {
667                                         MS_DBG("This case is ignored");
668                                 }
669                         }
670  NEXT_INOTI_EVENT:      ;
671                         i += INOTI_EVENT_SIZE + event->len;
672                 }
673
674                 /*Active flush */
675                 malloc_trim(0);
676         }
677 _POWEROFF:
678         ms_inoti_remove_watch_recursive(MEDIA_ROOT_PATH_INTERNAL);
679         ms_inoti_remove_watch_recursive(MEDIA_ROOT_PATH_SDCARD);
680
681         close(inoti_fd);
682
683         if (handle) ms_disconnect_db(&handle);
684
685         return false;
686 }
687
688 int _ms_get_path_from_current_node(int find_folder,
689                                    ms_dir_scan_info **current_root,
690                                    ms_dir_scan_info **real_root, char **path, int *depth)
691 {
692         int err = MS_MEDIA_ERR_NONE;
693         char get_path[FAT_FILEPATH_LEN_MAX] = { 0 };
694
695         if (find_folder == 0) {
696                 if ((*current_root)->Rbrother != NULL) {
697                         *current_root = (*current_root)->Rbrother;
698                 } else {
699                         while (1) {
700                                 if ((*current_root)->parent == *real_root
701                                     || (*current_root)->parent == NULL) {
702                                         *current_root = NULL;
703                                         *depth = 0;
704                                         return MS_MEDIA_ERR_NONE;
705                                 } else if ((*current_root)->parent->Rbrother == NULL) {
706                                         *current_root = (*current_root)->parent;
707                                         (*depth) --;
708                                 } else {
709                                         *current_root = (*current_root)->parent->Rbrother;
710                                         (*depth) --;
711                                         break;
712                                 }
713                         }
714                 }
715                 (*depth) --;
716         }
717
718         err = ms_get_full_path_from_node(*current_root, get_path, *depth);
719         if (err != MS_MEDIA_ERR_NONE)
720                 return MS_MEDIA_ERR_INVALID_PATH;
721
722         *path = strdup(get_path);
723
724         return err;
725 }
726
727 void ms_inoti_add_watch_all_directory(ms_storage_type_t storage_type)
728 {
729         int err = 0;
730         int depth = 0;
731         int find_folder = 0;
732         char get_path[MS_FILE_PATH_LEN_MAX] = { 0 };
733         char *path = NULL;
734         DIR *dp = NULL;
735         struct dirent entry;
736         struct dirent *result;
737
738         ms_dir_scan_info *root;
739         ms_dir_scan_info *tmp_root = NULL;
740         ms_dir_scan_info *cur_node = NULL; /*current node*/
741         ms_dir_scan_info *prv_node = NULL; /*previous node*/
742         ms_dir_scan_info *next_node = NULL;
743
744         root = malloc(sizeof(ms_dir_scan_info));
745         if (root == NULL) {
746                 MS_DBG_ERR("malloc fail");
747                 return;
748         }
749
750         if (storage_type == MS_STORAGE_INTERNAL)
751                 root->name = strdup(MEDIA_ROOT_PATH_INTERNAL);
752         else
753                 root->name = strdup(MEDIA_ROOT_PATH_SDCARD);
754         if (root->name  == NULL) {
755                 MS_DBG_ERR("strdup fail");
756                 MS_SAFE_FREE(root);
757                 return;
758         }
759
760         root->parent = NULL;
761         root->Rbrother = NULL;
762         root->next = NULL;
763         tmp_root = root;
764         prv_node = root;
765
766         path = malloc(sizeof(char) * MS_FILE_PATH_LEN_MAX);
767
768         err = ms_get_full_path_from_node(tmp_root, path, depth);
769         if (err != MS_MEDIA_ERR_NONE) {
770                 MS_SAFE_FREE(path);
771                 MS_SAFE_FREE(root);
772                 return;
773         }
774
775         ms_inoti_add_watch_with_node(root, depth);
776
777         while (1) {
778                 /*check poweroff status*/
779                 if (power_off) {
780                         MS_DBG("Power off");
781                         goto FREE_RESOURCES;
782                 }
783
784                 /*check SD card in out*/
785                 if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL))
786                         goto FREE_RESOURCES;
787
788                 depth ++;
789                 dp = opendir(path);
790                 if (dp == NULL) {
791                         MS_DBG_ERR("%s folder opendir fails", path);
792                         goto NEXT_DIR;
793                 }
794
795                 while (!readdir_r(dp, &entry, &result)) {
796                         /*check poweroff status*/
797                         if (power_off) {
798                                 MS_DBG("Power off");
799                                 goto FREE_RESOURCES;
800                         }
801
802                         if (result == NULL)
803                                 break;
804
805                         if (entry.d_name[0] == '.')
806                                 continue;
807
808                         /*check SD card in out*/
809                         if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL)) {
810                                 goto FREE_RESOURCES;
811                         }
812
813                         if (entry.d_type & DT_DIR) {
814                                 DIR *tmp_dp = NULL;
815                                 err = ms_strappend(get_path, sizeof(get_path), "%s/%s",path, entry.d_name);
816                                 if (err != MS_MEDIA_ERR_NONE) {
817                                         MS_DBG_ERR("ms_strappend error");
818                                         continue;
819                                 }
820
821                                 tmp_dp = opendir(get_path);
822                                 if (tmp_dp == NULL) {
823                                         MS_DBG_ERR("%s folder opendir fails", get_path);
824                                         MS_DBG("error : %d, %s", errno ,strerror(errno));
825                                         continue;
826                                 }
827                                 else
828                                         closedir(tmp_dp);
829
830                                 cur_node = malloc(sizeof(ms_dir_scan_info));
831                                 if (cur_node == NULL) {
832                                         MS_DBG_ERR("malloc fail");
833
834                                         goto FREE_RESOURCES;
835                                 }
836
837                                 cur_node->name = strdup(entry.d_name);
838                                 cur_node->Rbrother = NULL;
839                                 cur_node->next = NULL;
840
841                                 /*1. 1st folder */
842                                 if (find_folder == 0) {
843                                         cur_node->parent = tmp_root;
844                                         tmp_root = cur_node;
845                                 } else {
846                                         cur_node->parent = tmp_root->parent;
847                                         prv_node->Rbrother = cur_node;
848                                 }
849                                 prv_node->next = cur_node;
850
851                                 /*add watch */
852                                 ms_inoti_add_watch_with_node(cur_node, depth);
853
854                                 /*change previous */
855                                 prv_node = cur_node;
856                                 find_folder++;
857                         }
858                 }
859 NEXT_DIR:
860                 if (dp) closedir(dp);
861                 MS_SAFE_FREE(path);
862                 dp = NULL;
863                 path = NULL;
864
865                 err = _ms_get_path_from_current_node(find_folder, &tmp_root, &root, &path, &depth);
866                 if (err != MS_MEDIA_ERR_NONE)
867                         break;
868
869                 if (tmp_root == NULL)
870                         break;
871
872                 find_folder = 0;
873         }
874
875 FREE_RESOURCES:
876         /*free allocated memory */
877         if (dp) closedir(dp);
878         MS_SAFE_FREE(path);
879
880         cur_node = root;
881         while (cur_node != NULL) {
882                 next_node = cur_node->next;
883                 MS_SAFE_FREE(cur_node->name);
884                 MS_SAFE_FREE(cur_node);
885                 cur_node = next_node;
886         }
887 }
888
889 #endif