common: Remove readdir
[platform/core/system/storaged.git] / src / block / block.c
1 /*
2  * storaged
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #define _GNU_SOURCE
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/mount.h>
28 #include <sys/statvfs.h>
29 #include <fnmatch.h>
30 #include <errno.h>
31 #include <dirent.h>
32 #include <sys/statfs.h>
33 #include <stdbool.h>
34 #include <pthread.h>
35 #include <time.h>
36 #include <assert.h>
37 #include <vconf.h>
38 #include <ctype.h>
39 #include <tzplatform_config.h>
40 #include <app2ext_interface.h>
41 #include <libmount.h>
42 #include <blkid/blkid.h>
43
44 #include "log.h"
45 #include "config-parser.h"
46 #include "module-intf.h"
47 #include "udev.h"
48 #include "list.h"
49 #include "block.h"
50 #include "dbus.h"
51 #include "fd_handler.h"
52 #include "utils.h"
53
54 /**
55  * TODO  Assume root device is always mmcblk0*.
56  */
57 #define MMC_PATH            "*/mmcblk[0-9]*"
58 #define MMC_PARTITION_PATH  "mmcblk[0-9]p[0-9]"
59 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
60 #define MMC_LINK_PATH       "*/sdcard/*"
61 #define SCSI_PATH           "*/sd[a-z]*"
62 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
63 #define SCSI_PARTITION_LENGTH 9
64
65 #define FILESYSTEM          "filesystem"
66
67 #define DEV_PREFIX          "/dev/"
68 #define ROOT_DIR            "/"
69
70 #define UNMOUNT_RETRY   5
71 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
72
73 #define SIGNAL_BOOTING_DONE     "BootingDone"
74 #define SIGNAL_POWEROFF_STATE   "ChangeState"
75
76 #define BLOCK_DEVICE_ADDED      "DeviceAdded"
77 #define BLOCK_DEVICE_REMOVED    "DeviceRemoved"
78 #define BLOCK_DEVICE_BLOCKED    "DeviceBlocked"
79 #define BLOCK_DEVICE_CHANGED    "DeviceChanged"
80 #define BLOCK_DEVICE_CHANGED_2  "DeviceChanged2"
81
82 #define BLOCK_TYPE_MMC          "mmc"
83 #define BLOCK_TYPE_SCSI         "scsi"
84 #define BLOCK_TYPE_ALL          "all"
85
86 #define BLOCK_MMC_NODE_PREFIX   "SDCard"
87 #define BLOCK_SCSI_NODE_PREFIX  "USBDrive"
88
89 #define BLOCK_CONF_FILE         "/etc/storaged/block.conf"
90
91 #define EXTERNAL_STORAGE_PATH   "/run/external-storage"
92 #define PATH_LEN                55
93
94 /* Minimum value of block id */
95 #define BLOCK_ID_MIN 10
96 /* For 2.4 Backward Compatibility */
97 #define EXT_PRIMARY_SD_FIXID    1
98
99 /* Maximum number of thread */
100 #define THREAD_MAX 5
101
102 #define PKGDIR_BUS_NAME         "org.tizen.pkgdir_tool"
103 #define PKGDIR_PATH             "/org/tizen/pkgdir_tool"
104 #define PKGDIR_INTERFACE        "org.tizen.pkgdir_tool"
105
106 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
107
108 enum block_dev_operation {
109         BLOCK_DEV_MOUNT,
110         BLOCK_DEV_UNMOUNT,
111         BLOCK_DEV_FORMAT,
112         BLOCK_DEV_INSERT,
113         BLOCK_DEV_REMOVE,
114 };
115
116 enum private_operation_state {
117         REQ_NORMAL,
118         REQ_PRIVATE,
119         REQ_PRIVATE_FORMAT,
120 };
121
122 struct operation_queue {
123         enum block_dev_operation op;
124         dbus_method_reply_handle_h reply_handle;
125         void *data;
126         bool done;
127 };
128
129 struct block_device {
130         struct block_data *data;
131         dd_list *op_queue;
132         int thread_id;          /* Current thread ID */
133         bool removed;           /* True when device is physically removed but operation is not precessed yet */
134         enum private_operation_state on_private_op;
135         bool mount_point_updated;
136         pid_t private_pid;
137 };
138
139 struct format_data {
140         struct block_device *bdev;
141         char *fs_type;
142         enum unmount_operation option;
143 };
144
145 struct pipe_data {
146         enum block_dev_operation op;
147         struct block_device *bdev;
148         int result;
149 };
150
151 static struct block_conf {
152         bool multimount;
153 } block_conf[BLOCK_MMC_DEV + 1];
154
155 static struct manage_thread {
156         dd_list *th_node_list;  /* List of devnode which thread dealt with. Only main thread access */
157         dd_list *block_dev_list; /* Use thread mutex */
158         pthread_t th;
159         pthread_mutex_t mutex;
160         pthread_cond_t cond;
161         int num_dev;            /* Number of devices which thread holds. Only main thread access */
162         int op_len;             /* Number of operation of thread. Use thread mutex */
163         int thread_id;          /* Never changed */
164         bool start_th;
165 } th_manager[THREAD_MAX];
166
167 static dd_list *fs_head;
168 static dd_list *block_ops_list;
169 static bool smack;
170 static int pfds[2];
171 static fd_handler_h phandler;
172 static bool block_control = false;
173 static bool block_boot = false;
174
175 /* Assume there is only one physical internal storage */
176 static int dev_internal = -1;
177 static char dev_internal_scsi = '\0';
178 static char dev_internal_emul = '\0';
179
180 static int add_operation(struct block_device *bdev,
181                 enum block_dev_operation operation,
182                 dbus_method_reply_handle_h reply_handle, void *data);
183 static void remove_operation(struct block_device *bdev);
184 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
185 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
186 static int change_mount_point(struct block_device *bdev, const char *mount_point);
187
188 static void uevent_block_handler(struct udev_device *dev);
189 static struct uevent_handler uh = {
190         .subsystem = BLOCK_SUBSYSTEM,
191         .uevent_func = uevent_block_handler,
192 };
193
194 static void __CONSTRUCTOR__ smack_check(void)
195 {
196         FILE *fp;
197         char buf[128];
198
199         fp = fopen("/proc/filesystems", "r");
200         if (!fp)
201                 return;
202
203         while (fgets(buf, sizeof(buf), fp) != NULL) {
204                 if (strstr(buf, "smackfs")) {
205                         smack = true;
206                         break;
207                 }
208         }
209
210         fclose(fp);
211 }
212
213 void add_fs(const struct block_fs_ops *fs)
214 {
215         DD_LIST_APPEND(fs_head, (void *)fs);
216 }
217
218 void remove_fs(const struct block_fs_ops *fs)
219 {
220         DD_LIST_REMOVE(fs_head, (void *)fs);
221 }
222
223 const struct block_fs_ops *find_fs(enum block_fs_type type)
224 {
225         struct block_fs_ops *fs;
226         dd_list *elem;
227
228         DD_LIST_FOREACH(fs_head, elem, fs) {
229                 if (fs->type == type)
230                         return fs;
231         }
232         return NULL;
233 }
234
235 void add_block_dev(const struct block_dev_ops *ops)
236 {
237         DD_LIST_APPEND(block_ops_list, (void *)ops);
238 }
239
240 void remove_block_dev(const struct block_dev_ops *ops)
241 {
242         DD_LIST_REMOVE(block_ops_list, (void *)ops);
243 }
244
245 static void broadcast_block_info(enum block_dev_operation op,
246                 struct block_data *data, int result)
247 {
248         struct block_dev_ops *ops;
249         dd_list *elem;
250
251         DD_LIST_FOREACH(block_ops_list, elem, ops) {
252                 if (ops->block_type != data->block_type)
253                         continue;
254                 if (op == BLOCK_DEV_MOUNT)
255                         ops->mounted(data, result);
256                 else if (op == BLOCK_DEV_UNMOUNT)
257                         ops->unmounted(data, result);
258                 else if (op == BLOCK_DEV_FORMAT)
259                         ops->formatted(data, result);
260                 else if (op == BLOCK_DEV_INSERT)
261                         ops->inserted(data);
262                 else if (op == BLOCK_DEV_REMOVE)
263                         ops->removed(data);
264         }
265 }
266
267 // Called by MainThread - Insert
268 static int block_get_new_id(void)
269 {
270         static int id = BLOCK_ID_MIN;
271         struct block_device *bdev;
272         dd_list *elem;
273         bool found;
274         int i, j;
275
276         for (i = 0 ; i < INT_MAX ; i++) {
277                 found = false;
278                 for (j = 0; j < THREAD_MAX; j++) {
279                         pthread_mutex_lock(&(th_manager[j].mutex));
280                         DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
281                                 if (bdev->data->id == id) {
282                                         found = true;
283                                         break;
284                                 }
285                         }
286                         pthread_mutex_unlock(&(th_manager[j].mutex));
287                         if (found)
288                                 break;
289                 }
290
291                 if (!found)
292                         return id++;
293
294                 if (++id == INT_MAX)
295                         id = BLOCK_ID_MIN;
296         }
297
298         return -ENOENT;
299 }
300
301 static void remove_file(int id)
302 {
303         char file_name[PATH_LEN];
304         int ret;
305
306         if (id < 0)
307                 return;
308
309         snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
310
311         ret = remove(file_name);
312         if (ret < 0)
313                 _E("Fail to remove %s. errno: %d", file_name, errno);
314 }
315
316 static void create_file(int id, char *mount_point)
317 {
318         FILE *fp;
319         char file_name[PATH_LEN];
320
321         if (id < 0)
322                 return;
323
324         snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
325
326         fp = fopen(file_name, "w+");
327         if (fp) {
328                 fprintf(fp, "%s", mount_point);
329                 fclose(fp);
330         } else
331                 _E("Fail to open %s", file_name);
332 }
333
334 static void signal_device_blocked(struct block_device *bdev)
335 {
336         struct block_data *data;
337         char *arr[13];
338         char str_block_type[32];
339         char str_readonly[32];
340         char str_state[32];
341         char str_primary[32];
342         char str_flags[32];
343         char str_id[32];
344         char *str_null = "";
345         int flags;
346
347         if (!bdev || !bdev->data)
348                 return;
349
350         data = bdev->data;
351         flags = 0;
352
353         /* Broadcast outside with BlockManager iface */
354         snprintf(str_block_type, sizeof(str_block_type),
355                         "%d", data->block_type);
356         arr[0] = str_block_type;
357         arr[1] = (data->devnode ? data->devnode : str_null);
358         arr[2] = (data->syspath ? data->syspath : str_null);
359         arr[3] = (data->fs_usage ? data->fs_usage : str_null);
360         arr[4] = (data->fs_type ? data->fs_type : str_null);
361         arr[5] = (data->fs_version ? data->fs_version : str_null);
362         arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
363         snprintf(str_readonly, sizeof(str_readonly),
364                         "%d", data->readonly);
365         arr[7] = str_readonly;
366         arr[8] = (data->mount_point ? data->mount_point : str_null);
367         snprintf(str_state, sizeof(str_state),
368                         "%d", data->state);
369         arr[9] = str_state;
370         snprintf(str_primary, sizeof(str_primary),
371                         "%d", data->primary);
372         arr[10] = str_primary;
373         snprintf(str_flags, sizeof(str_flags), "%d", flags);
374         arr[11] = str_flags;
375         snprintf(str_id, sizeof(str_id), "%d", data->id);
376         arr[12] = str_id;
377
378         broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
379                         STORAGED_INTERFACE_BLOCK_MANAGER,
380                         BLOCK_DEVICE_BLOCKED,
381                         "issssssisibii", arr);
382 }
383
384 static void signal_device_changed(struct block_device *bdev,
385                 enum block_dev_operation op)
386 {
387         struct block_data *data;
388         char *arr[13];
389         char str_block_type[32];
390         char str_readonly[32];
391         char str_state[32];
392         char str_primary[32];
393         char str_flags[32];
394         char str_id[32];
395         char *str_null = "";
396         int flags;
397
398         if (!bdev || !bdev->data)
399                 return;
400
401         data = bdev->data;
402
403         switch (op) {
404         case BLOCK_DEV_MOUNT:
405                 BLOCK_GET_MOUNT_FLAGS(data, flags);
406                 break;
407         case BLOCK_DEV_UNMOUNT:
408                 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
409                 break;
410         case BLOCK_DEV_FORMAT:
411                 BLOCK_GET_FORMAT_FLAGS(data, flags);
412                 break;
413         default:
414                 flags = 0;
415                 break;
416         }
417
418         /* Broadcast outside with BlockManager iface */
419         snprintf(str_block_type, sizeof(str_block_type),
420                         "%d", data->block_type);
421         arr[0] = str_block_type;
422         arr[1] = (data->devnode ? data->devnode : str_null);
423         arr[2] = (data->syspath ? data->syspath : str_null);
424         arr[3] = (data->fs_usage ? data->fs_usage : str_null);
425         arr[4] = (data->fs_type ? data->fs_type : str_null);
426         arr[5] = (data->fs_version ? data->fs_version : str_null);
427         arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
428         snprintf(str_readonly, sizeof(str_readonly),
429                         "%d", data->readonly);
430         arr[7] = str_readonly;
431         arr[8] = (data->mount_point ? data->mount_point : str_null);
432         snprintf(str_state, sizeof(str_state),
433                         "%d", data->state);
434         arr[9] = str_state;
435         snprintf(str_primary, sizeof(str_primary),
436                         "%d", data->primary);
437         arr[10] = str_primary;
438         snprintf(str_flags, sizeof(str_flags), "%d", flags);
439         arr[11] = str_flags;
440         snprintf(str_id, sizeof(str_id), "%d", data->id);
441         arr[12] = str_id;
442
443         if (op == BLOCK_DEV_INSERT)
444                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
445                                 STORAGED_INTERFACE_BLOCK_MANAGER,
446                                 BLOCK_DEVICE_ADDED,
447                                 "issssssisibii", arr);
448         else if (op == BLOCK_DEV_REMOVE)
449                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
450                                 STORAGED_INTERFACE_BLOCK_MANAGER,
451                                 BLOCK_DEVICE_REMOVED,
452                                 "issssssisibii", arr);
453         else {
454                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
455                                 STORAGED_INTERFACE_BLOCK_MANAGER,
456                                 BLOCK_DEVICE_CHANGED,
457                                 "issssssisibii", arr);
458                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
459                                 STORAGED_INTERFACE_BLOCK_MANAGER,
460                                 BLOCK_DEVICE_CHANGED_2,
461                                 "issssssisibi", arr);
462         }
463 }
464
465 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
466 {
467         char *name = devnode;
468         int dev = -1, part = -1;
469         char emul[32] = { 0, };
470         int i;
471
472         if (!name)
473                 return -EINVAL;
474
475         /* Check Target */
476         sscanf(name, "mmcblk%dp%d", &dev, &part);
477         if (dev >= 0) {
478                 if (part < 0)
479                         snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
480                 else
481                         snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
482                 return 0;
483         }
484
485         /* Check Emulator */
486         sscanf(name, "vd%s", emul);
487         if (emul[0] == '\0')
488                 return -EINVAL;
489         for (i = 0 ; i < strlen(emul) ; i++)
490                 emul[i] = toupper(emul[i]);
491         snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
492         return 0;
493 }
494
495 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
496 {
497         char dev[64], *name;
498         int i;
499
500         if (!devnode)
501                 return -EINVAL;
502
503         snprintf(dev, sizeof(dev), "%s", devnode);
504
505         if (!strstr(dev, "sd"))
506                 return -EINVAL;
507
508         name = dev;
509         name += strlen("sd");
510
511         for (i = 0 ; i < strlen(name) ; i++)
512                 name[i] = toupper(name[i]);
513         snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
514
515         return 0;
516 }
517
518 static char *generate_mount_path(struct block_data *data)
519 {
520         const char *str;
521         char *name, node[64];
522         int ret;
523
524         if (!data || !data->devnode)
525                 return NULL;
526
527         name = strrchr(data->devnode, '/');
528         if (!name)
529                 goto out;
530         name++;
531
532         switch (data->block_type) {
533         case BLOCK_MMC_DEV:
534                 ret = get_mmc_mount_node(name, node, sizeof(node));
535                 break;
536         case BLOCK_SCSI_DEV:
537                 ret = get_scsi_mount_node(name, node, sizeof(node));
538                 break;
539         default:
540                 _E("Invalid block type (%d)", data->block_type);
541                 return NULL;
542         }
543         if (ret < 0)
544                 goto out;
545
546         str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
547         if (!str)
548                 return NULL;
549         return strdup(str);
550
551 out:
552         _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
553         return NULL;
554 }
555
556 static bool check_primary_partition(const char *devnode)
557 {
558         struct block_fs_ops *fs;
559         blkid_probe probe;
560         dd_list *elem;
561         const char *filesystem = NULL;
562         char *temp;
563         char str[PATH_MAX];
564         char str2[PATH_MAX];
565         size_t fs_len;
566         int len;
567         int ret;
568         int i;
569         bool found = false;
570
571         if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
572                 fnmatch(MMC_PATH, devnode, 0) &&
573                 fnmatch(SCSI_PATH, devnode, 0))
574                 return false;
575
576         temp = strrchr(devnode, '/');
577         if (!temp)
578                 return false;
579         if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
580                 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
581                 return true;
582
583         /* Emulator support only one partition */
584         if (is_emulator())
585                 return true;
586
587         snprintf(str, sizeof(str), "%s", devnode);
588
589         len = strlen(str);
590         str[len - 1] = '\0';
591
592         for (i = 1; i <= 9; ++i) {
593                 snprintf(str2, sizeof(str2), "%s%d", str, i);
594                 if (access(str2, R_OK) != 0)
595                         continue;
596
597                 probe = blkid_new_probe_from_filename(str2);
598                 if (!probe)
599                         continue;
600                 if (blkid_do_probe(probe) != 0)
601                         continue;
602
603                 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
604                 if (ret < 0) {
605                         blkid_free_probe(probe);
606                         continue;
607                 }
608                 DD_LIST_FOREACH(fs_head, elem, fs) {
609                         if (!strncmp(fs->name, filesystem, fs_len)) {
610                                 found = true;
611                                 break;
612                         }
613                 }
614                 blkid_free_probe(probe);
615                 if (!found)
616                         continue;
617                 break;
618         }
619
620         if (found && !strncmp(devnode, str2, strlen(str2) + 1))
621                 return true;
622
623         return false;
624 }
625
626 /* Whole data in struct block_data should be freed. */
627 static struct block_data *make_block_data(const char *devnode,
628                 const char *syspath,
629                 const char *fs_usage,
630                 const char *fs_type,
631                 const char *fs_version,
632                 const char *fs_uuid_enc,
633                 const char *readonly)
634 {
635         struct block_data *data;
636
637         /* devnode is unique value so it should exist. */
638         if (!devnode)
639                 return NULL;
640
641         if (!fs_type) {
642                 _E("Not support extended partition");
643                 return NULL;
644         }
645
646         data = calloc(1, sizeof(struct block_data));
647         if (!data) {
648                 _E("calloc() failed");
649                 return NULL;
650         }
651
652         data->devnode = strdup(devnode);
653         if (syspath)
654                 data->syspath = strdup(syspath);
655         if (fs_usage)
656                 data->fs_usage = strdup(fs_usage);
657         if (fs_type)
658                 data->fs_type = strdup(fs_type);
659         if (fs_version)
660                 data->fs_version = strdup(fs_version);
661         if (fs_uuid_enc)
662                 data->fs_uuid_enc = strdup(fs_uuid_enc);
663         if (readonly)
664                 data->readonly = atoi(readonly);
665         data->primary = check_primary_partition(devnode);
666
667         /* TODO should we know block dev type? */
668         if (!fnmatch(MMC_LINK_PATH, devnode, 0))
669                 data->block_type = BLOCK_MMC_DEV;
670         else if (!fnmatch(MMC_PATH, devnode, 0))
671                 data->block_type = BLOCK_MMC_DEV;
672         else if (!fnmatch(SCSI_PATH, devnode, 0))
673                 data->block_type = BLOCK_SCSI_DEV;
674         else
675                 data->block_type = -1;
676
677         data->mount_point = generate_mount_path(data);
678         BLOCK_FLAG_CLEAR_ALL(data);
679
680         /* for 2.4 backward compatibility */
681         if (data->primary == true && data->block_type == BLOCK_MMC_DEV)
682                 data->id = EXT_PRIMARY_SD_FIXID;
683         else
684                 data->id = block_get_new_id();
685
686         return data;
687 }
688
689 static void free_block_data(struct block_data *data)
690 {
691         if (!data)
692                 return;
693         free(data->devnode);
694         free(data->syspath);
695         free(data->fs_usage);
696         free(data->fs_type);
697         free(data->fs_version);
698         free(data->fs_uuid_enc);
699         free(data->mount_point);
700         free(data);
701 }
702
703 static int update_block_data(struct block_data *data,
704                 const char *fs_usage,
705                 const char *fs_type,
706                 const char *fs_version,
707                 const char *fs_uuid_enc,
708                 const char *readonly,
709                 bool mount_point_updated)
710 {
711         if (!data)
712                 return -EINVAL;
713
714         free(data->fs_usage);
715         data->fs_usage = NULL;
716         if (fs_usage)
717                 data->fs_usage = strdup(fs_usage);
718
719         free(data->fs_type);
720         data->fs_type = NULL;
721         if (fs_type)
722                 data->fs_type = strdup(fs_type);
723
724         free(data->fs_version);
725         data->fs_version = NULL;
726         if (fs_version)
727                 data->fs_version = strdup(fs_version);
728
729         free(data->fs_uuid_enc);
730         data->fs_uuid_enc = NULL;
731         if (fs_uuid_enc)
732                 data->fs_uuid_enc = strdup(fs_uuid_enc);
733
734         /* generate_mount_path function should be invoked
735          * after fs_uuid_enc is updated */
736         if (!mount_point_updated) {
737                 free(data->mount_point);
738                 data->mount_point = generate_mount_path(data);
739         }
740
741         data->readonly = false;
742         if (readonly)
743                 data->readonly = atoi(readonly);
744
745         BLOCK_FLAG_MOUNT_CLEAR(data);
746
747         return 0;
748 }
749
750 static struct block_device *make_block_device(struct block_data *data)
751 {
752         struct block_device *bdev;
753
754         if (!data)
755                 return NULL;
756
757         bdev = calloc(1, sizeof(struct block_device));
758         if (!bdev)
759                 return NULL;
760
761         bdev->data = data;
762         bdev->thread_id = -1;
763         bdev->removed = false;
764         bdev->on_private_op = REQ_NORMAL;
765         bdev->private_pid = 0;
766         bdev->mount_point_updated = false;
767
768         return bdev;
769 }
770
771 // Called by MainThread - Remove DevNode
772 static void free_block_device(struct block_device *bdev)
773 {
774         dd_list *l, *next;
775         struct operation_queue *op;
776         int thread_id;
777
778         if (!bdev)
779                 return;
780
781         thread_id = bdev->thread_id;
782         if (thread_id < 0 || thread_id >= THREAD_MAX)
783                 return;
784
785         /* Remove file for block device /run/external-storage/id */
786         remove_file(bdev->data->id);
787
788         pthread_mutex_lock(&(th_manager[thread_id].mutex));
789
790         th_manager[thread_id].num_dev--;
791         DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
792         free_block_data(bdev->data);
793
794         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
795                 if (!op->done)
796                         th_manager[thread_id].op_len--;
797                 DD_LIST_REMOVE(bdev->op_queue, op);
798                 free(op);
799         }
800         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
801
802         free(bdev);
803 }
804
805 // Called By MainThread - Remove Device
806 static struct block_device *find_block_device(const char *devnode)
807 {
808         struct block_device *bdev;
809         dd_list *elem;
810         int len;
811         int i;
812
813         len = strlen(devnode) + 1;
814         for (i = 0; i < THREAD_MAX; i++) {
815                 pthread_mutex_lock(&(th_manager[i].mutex));
816                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
817                         if (bdev->data && !bdev->removed &&
818                             !strncmp(bdev->data->devnode, devnode, len)) {
819                                 pthread_mutex_unlock(&(th_manager[i].mutex));
820                                 return bdev;
821                         }
822                 }
823                 pthread_mutex_unlock(&(th_manager[i].mutex));
824         }
825
826         return NULL;
827 }
828
829 // Called By MainThread - Mount,Unmount,Format,GetInfo
830 static struct block_device *find_block_device_by_id(int id)
831 {
832         struct block_device *bdev;
833         dd_list *elem;
834         int i;
835
836         for (i = 0; i < THREAD_MAX; i++) {
837                 pthread_mutex_lock(&(th_manager[i].mutex));
838                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
839                         if (!bdev->data)
840                                 continue;
841                         if (bdev->removed)
842                                 continue;
843                         if (bdev->data->id == id) {
844                                 pthread_mutex_unlock(&(th_manager[i].mutex));
845                                 return bdev;
846                         }
847                 }
848                 pthread_mutex_unlock(&(th_manager[i].mutex));
849         }
850
851         return NULL;
852 }
853
854 static char *get_operation_char(enum block_dev_operation op,
855                 char *name, unsigned int len)
856 {
857         char *str = "unknown";
858
859         if (!name)
860                 return NULL;
861
862         switch (op) {
863         case BLOCK_DEV_MOUNT:
864                 str = "MOUNT";
865                 break;
866         case BLOCK_DEV_UNMOUNT:
867                 str = "UNMOUNT";
868                 break;
869         case BLOCK_DEV_FORMAT:
870                 str = "FORMAT";
871                 break;
872         case BLOCK_DEV_INSERT:
873                 str = "INSERT";
874                 break;
875         case BLOCK_DEV_REMOVE:
876                 str = "REMOVE";
877                 break;
878         default:
879                 _E("invalid operation (%d)", op);
880                 break;
881         }
882
883         snprintf(name, len, "%s", str);
884         return name;
885 }
886
887 static void create_external_apps_directory(void)
888 {
889         int ret;
890
891         ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
892                         PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
893                         NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
894         if (ret)
895                 _E("Fail to create external directory");
896 }
897
898 static int pipe_trigger(enum block_dev_operation op,
899                 struct block_device *bdev, int result)
900 {
901         struct pipe_data pdata = { op, bdev, result };
902         int n;
903         char name[16];
904
905         _D("op : %s, bdev : %p, result : %d",
906                         get_operation_char(pdata.op, name, sizeof(name)),
907                         pdata.bdev, pdata.result);
908
909         n = write(pfds[1], &pdata, sizeof(struct pipe_data));
910
911         return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
912 }
913
914 static bool pipe_cb(int fd, void *data)
915 {
916         struct pipe_data pdata = {0,};
917         int n;
918         int thread_id;
919         int ret;
920         char name[16];
921
922         n = read(fd, &pdata, sizeof(pdata));
923         if (n != sizeof(pdata) || !pdata.bdev) {
924                 _E("fail to read struct pipe data");
925                 goto out;
926         }
927
928         _I("op : %s, bdev : %p, result : %d",
929                         get_operation_char(pdata.op, name, sizeof(name)),
930                         pdata.bdev, pdata.result);
931
932         if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
933                 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
934                         ret = change_mount_point(pdata.bdev, "");
935                         /* Modify /run/external-storage/id file */
936                         if (ret == 0)
937                                 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point);
938                 }
939                 goto out;
940         }
941         if (pdata.op == BLOCK_DEV_MOUNT &&
942                 pdata.bdev->data->state == BLOCK_MOUNT &&
943                 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
944                 pdata.bdev->data->primary)
945                 create_external_apps_directory();
946
947         /* Broadcast to mmc and usb storage module */
948         broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
949
950         /* Broadcast outside with Block iface */
951         if (pdata.bdev->on_private_op == REQ_NORMAL)
952                 signal_device_changed(pdata.bdev, pdata.op);
953         else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
954                 if (pdata.op == BLOCK_DEV_UNMOUNT) {
955                         pdata.bdev->on_private_op = REQ_NORMAL;
956                         _D("Private operation state: %d", pdata.bdev->on_private_op);
957                 }
958         } else {
959                 if (pdata.op == BLOCK_DEV_MOUNT) {
960                         pdata.bdev->on_private_op = REQ_PRIVATE;
961                         _D("Private operation state: %d", pdata.bdev->on_private_op);
962                 }
963         }
964
965         if (pdata.op == BLOCK_DEV_REMOVE) {
966                 thread_id = pdata.bdev->thread_id;
967                 if (thread_id < 0 || thread_id >= THREAD_MAX)
968                         return true;
969                 free_block_device(pdata.bdev);
970         }
971
972 out:
973         return true;
974 }
975
976 static int pipe_init(void)
977 {
978         int ret;
979
980         ret = pipe2(pfds, O_CLOEXEC);
981         if (ret == -1)
982                 return -errno;
983
984         ret = add_fd_read_handler(pfds[0], pipe_cb,
985                         NULL, NULL, &phandler);
986         if (ret < 0) {
987                 _E("Failed to add pipe handler (%d)", ret);
988                 return ret;
989         }
990
991         return 0;
992 }
993
994 static void pipe_exit(void)
995 {
996         if (phandler) {
997                 remove_fd_read_handler(&phandler);
998                 phandler = NULL;
999         }
1000
1001         if (pfds[0])
1002                 close(pfds[0]);
1003         if (pfds[1])
1004                 close(pfds[1]);
1005 }
1006
1007 static int mmc_check_and_unmount(const char *path)
1008 {
1009         int ret = 0;
1010         int retry = 0;
1011
1012         if (!path)
1013                 return 0;
1014
1015         while (mount_check(path)) {
1016                 ret = umount(path);
1017                 if (ret < 0) {
1018                         retry++;
1019                         if (retry > UNMOUNT_RETRY)
1020                                 return -errno;
1021                 }
1022         }
1023         return ret;
1024 }
1025
1026 static bool check_rw_mount(const char *szPath)
1027 {
1028         struct statvfs mount_stat;
1029
1030         if (!statvfs(szPath, &mount_stat)) {
1031                 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1032                         return false;
1033         }
1034         return true;
1035 }
1036
1037 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1038 {
1039         struct udev *udev;
1040         struct udev_device *dev;
1041         int r;
1042
1043         if (!data)
1044                 return -EINVAL;
1045
1046         udev = udev_new();
1047         if (!udev) {
1048                 _E("fail to create udev library context");
1049                 return -EPERM;
1050         }
1051
1052         dev = udev_device_new_from_syspath(udev, data->syspath);
1053         if (!dev) {
1054                 _E("fail to create new udev device");
1055                 udev_unref(udev);
1056                 return -EPERM;
1057         }
1058
1059         r = update_block_data(data,
1060                         udev_device_get_property_value(dev, "ID_FS_USAGE"),
1061                         udev_device_get_property_value(dev, "ID_FS_TYPE"),
1062                         udev_device_get_property_value(dev, "ID_FS_VERSION"),
1063                         udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1064                         udev_device_get_sysattr_value(dev, "ro"),
1065                         mount_point_updated);
1066         if (r < 0)
1067                 _E("fail to update block data for %s", data->devnode);
1068
1069         udev_device_unref(dev);
1070         udev_unref(udev);
1071         return r;
1072 }
1073
1074 static int block_mount(struct block_data *data)
1075 {
1076         struct block_fs_ops *fs;
1077         dd_list *elem;
1078         int r;
1079         int len;
1080
1081         if (!data || !data->devnode || !data->mount_point)
1082                 return -EINVAL;
1083
1084         /* check existing mounted */
1085         if (mount_check(data->mount_point))
1086                 return -EEXIST;
1087
1088         /* create mount point */
1089         if (access(data->mount_point, R_OK) != 0) {
1090                 if (mkdir(data->mount_point, 0755) < 0)
1091                         return -errno;
1092         }
1093
1094         /* check matched file system */
1095         if (!data->fs_usage ||
1096             strncmp(data->fs_usage, FILESYSTEM,
1097                     sizeof(FILESYSTEM)) != 0) {
1098                 r = -ENODEV;
1099                 goto out;
1100         }
1101
1102         if (!data->fs_type) {
1103                 _E("There is no file system");
1104                 BLOCK_FLAG_SET(data, FS_EMPTY);
1105                 r = -ENODATA;
1106                 goto out;
1107         }
1108
1109         fs = NULL;
1110         len = strlen(data->fs_type) + 1;
1111         DD_LIST_FOREACH(fs_head, elem, fs) {
1112                 if (!strncmp(fs->name, data->fs_type, len))
1113                         break;
1114         }
1115
1116         if (!fs) {
1117                 _E("Not supported file system (%s)", data->fs_type);
1118                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1119                 r = -ENOTSUP;
1120                 goto out;
1121         }
1122
1123         r = fs->mount(smack, data->devnode, data->mount_point);
1124
1125         if (r == -EIO)
1126                 BLOCK_FLAG_SET(data, FS_BROKEN);
1127
1128         if (r < 0)
1129                 goto out;
1130
1131         r = check_rw_mount(data->mount_point);
1132         if (!r)
1133                 return -EROFS;
1134
1135         return 0;
1136
1137 out:
1138         rmdir(data->mount_point);
1139         return r;
1140 }
1141
1142 static int mount_start(struct block_device *bdev)
1143 {
1144         struct block_data *data;
1145         int ret;
1146         int r;
1147
1148         assert(bdev);
1149         assert(bdev->data);
1150
1151         data = bdev->data;
1152         _I("Mount Start : (%s -> %s)",
1153                         data->devnode, data->mount_point);
1154
1155         /* mount operation */
1156         r = block_mount(data);
1157         if (r != -EROFS && r < 0) {
1158                 _E("fail to mount %s device : %d", data->devnode, r);
1159                 goto out;
1160         }
1161
1162         if (r == -EROFS) {
1163                 data->readonly = true;
1164                 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1165         }
1166
1167         data->state = BLOCK_MOUNT;
1168
1169         if (data->block_type == BLOCK_MMC_DEV) {
1170                 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1171                 ret = app2ext_migrate_legacy_all();
1172                 if (ret < 0)
1173                         _E("app2ext failed");
1174         }
1175
1176 out:
1177         if (r < 0 && r != -EROFS)
1178                 data->state = BLOCK_UNMOUNT;
1179
1180         _I("%s result : %s, %d", __func__, data->devnode, r);
1181
1182         if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1183                 _E("fail to trigger pipe");
1184
1185         return r;
1186 }
1187
1188 static int change_mount_point(struct block_device *bdev,
1189                 const char *mount_point)
1190 {
1191         struct block_data *data;
1192
1193         if (!bdev)
1194                 return -EINVAL;
1195
1196         data = bdev->data;
1197         free(data->mount_point);
1198
1199         /* If the mount path already exists, the path cannot be used */
1200         if (mount_point &&
1201                 access(mount_point, F_OK) != 0) {
1202                 data->mount_point = strdup(mount_point);
1203                 bdev->mount_point_updated = true;
1204         } else {
1205                 data->mount_point = generate_mount_path(data);
1206                 bdev->mount_point_updated = false;
1207         }
1208
1209         return 0;
1210 }
1211
1212 static int mount_block_device(struct block_device *bdev)
1213 {
1214         struct block_data *data;
1215         int r;
1216
1217         if (!bdev || !bdev->data)
1218                 return -EINVAL;
1219
1220         data = bdev->data;
1221         if (data->state == BLOCK_MOUNT) {
1222                 _I("%s is already mounted", data->devnode);
1223                 return 0;
1224         }
1225
1226         if (!block_conf[data->block_type].multimount &&
1227             !data->primary) {
1228                 _I("Not support multi mount by config info");
1229                 return 0;
1230         }
1231
1232         r = mount_start(bdev);
1233         if (r < 0) {
1234                 _E("Failed to mount (%s)", data->devnode);
1235                 return r;
1236         }
1237
1238         return 0;
1239 }
1240
1241 static int block_unmount(struct block_device *bdev,
1242                 enum unmount_operation option)
1243 {
1244         struct block_data *data;
1245         int r, retry = 0;
1246         struct timespec time = {0,};
1247
1248         if (!bdev || !bdev->data || !bdev->data->mount_point)
1249                 return -EINVAL;
1250
1251         data = bdev->data;
1252
1253         if (bdev->on_private_op == REQ_NORMAL)
1254                 signal_device_blocked(bdev);
1255
1256         /* it must called before unmounting mmc */
1257         r = mmc_check_and_unmount(data->mount_point);
1258         if (!r)
1259                 goto out;
1260         if (option == UNMOUNT_NORMAL) {
1261                 _I("Failed to unmount with normal option : %d", r);
1262                 return r;
1263         }
1264
1265         _I("Execute force unmount!");
1266         /* Force Unmount Scenario */
1267         while (1) {
1268                 switch (retry++) {
1269                 case 0:
1270                         /* Mobile specific:
1271                          * should unmount the below vconf key. */
1272                         if (data->block_type == BLOCK_MMC_DEV && data->primary) {
1273                                 /* At first, notify to other app
1274                                  * who already access sdcard */
1275                                 _I("Notify to other app who already access sdcard");
1276                                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1277                                                 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1278                         }
1279                         break;
1280                 case 1:
1281                         /* Second, kill app with SIGTERM */
1282                         _I("Kill app with SIGTERM");
1283                         terminate_process(data->mount_point, false);
1284                         break;
1285                 case 2:
1286                         /* Last time, kill app with SIGKILL */
1287                         _I("Kill app with SIGKILL");
1288                         terminate_process(data->mount_point, true);
1289                         break;
1290                 default:
1291                         if (umount2(data->mount_point, MNT_DETACH) != 0) {
1292                                 _I("Failed to unmount with lazy option : %d",
1293                                                 errno);
1294                                 return -errno;
1295                         }
1296                         goto out;
1297                 }
1298
1299                 /* it takes some seconds til other app completely clean up */
1300                 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1301                 nanosleep(&time, NULL);
1302
1303                 print_open_files(data->mount_point);
1304
1305                 r = mmc_check_and_unmount(data->mount_point);
1306                 if (!r) {
1307                         _D("Success to unmount (%s)", data->mount_point);
1308                         break;
1309                 }
1310         }
1311
1312 out:
1313         data->state = BLOCK_UNMOUNT;
1314
1315         if (rmdir(data->mount_point) < 0)
1316                 _E("fail to remove %s directory", data->mount_point);
1317
1318         return r;
1319 }
1320
1321 static int unmount_block_device(struct block_device *bdev,
1322                 enum unmount_operation option)
1323 {
1324         struct block_data *data;
1325         int r;
1326
1327         if (!bdev || !bdev->data)
1328                 return -EINVAL;
1329
1330         data = bdev->data;
1331         if (data->state == BLOCK_UNMOUNT) {
1332                 _I("%s is already unmounted", data->devnode);
1333                 r = mmc_check_and_unmount(data->mount_point);
1334                 if (r < 0)
1335                         _E("The path was existed, but could not delete it(%s)",
1336                                         data->mount_point);
1337                 return 0;
1338         }
1339
1340         _I("Unmount Start : (%s -> %s)",
1341                         data->devnode, data->mount_point);
1342
1343         r = block_unmount(bdev, option);
1344         if (r < 0) {
1345                 _E("fail to unmount %s device : %d", data->devnode, r);
1346                 goto out;
1347         }
1348
1349         BLOCK_FLAG_MOUNT_CLEAR(data);
1350
1351 out:
1352         _I("%s result : %s, %d", __func__, data->devnode, r);
1353
1354         if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1355                 _E("fail to trigger pipe");
1356
1357         return r;
1358 }
1359
1360 static int block_format(struct block_data *data,
1361                 const char *fs_type, bool mount_point_updated)
1362 {
1363         const struct block_fs_ops *fs;
1364         dd_list *elem;
1365         int len;
1366         int r;
1367
1368         if (!data || !data->devnode || !data->mount_point)
1369                 return -EINVAL;
1370
1371         if (!fs_type)
1372                 fs_type = data->fs_type;
1373
1374         fs = NULL;
1375         len = strlen(fs_type);
1376         DD_LIST_FOREACH(fs_head, elem, fs) {
1377                 if (!strncmp(fs->name, fs_type, len))
1378                         break;
1379         }
1380
1381         if (!fs) {
1382                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1383                 _E("not supported file system(%s)", fs_type);
1384                 return -ENOTSUP;
1385         }
1386
1387         _I("format path : %s", data->devnode);
1388         fs->check(data->devnode);
1389         r = fs->format(data->devnode);
1390         if (r < 0) {
1391                 _E("fail to format block data for %s", data->devnode);
1392                 goto out;
1393         }
1394
1395         /* need to update the partition data.
1396          * It can be changed in doing format. */
1397         retrieve_udev_device(data, mount_point_updated);
1398
1399 out:
1400         return r;
1401 }
1402
1403 static int format_block_device(struct block_device *bdev,
1404                 const char *fs_type,
1405                 enum unmount_operation option)
1406 {
1407         struct block_data *data;
1408         int r;
1409
1410         assert(bdev);
1411         assert(bdev->data);
1412
1413         data = bdev->data;
1414
1415         _I("Format Start : (%s -> %s)",
1416                         data->devnode, data->mount_point);
1417
1418         if (data->state == BLOCK_MOUNT) {
1419                 r = block_unmount(bdev, option);
1420                 if (r < 0) {
1421                         _E("fail to unmount %s device : %d", data->devnode, r);
1422                         goto out;
1423                 }
1424         }
1425
1426         r = block_format(data, fs_type, bdev->mount_point_updated);
1427         if (r < 0)
1428                 _E("fail to format %s device : %d", data->devnode, r);
1429
1430 out:
1431         _I("%s result : %s, %d", __func__, data->devnode, r);
1432
1433         r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1434         if (r < 0)
1435                 _E("fail to trigger pipe");
1436
1437         return r;
1438 }
1439
1440 static struct format_data *get_format_data(
1441                 const char *fs_type, enum unmount_operation option)
1442 {
1443         struct format_data *fdata;
1444
1445         fdata = (struct format_data *)malloc(sizeof(struct format_data));
1446         if (!fdata) {
1447                 _E("fail to allocate format data");
1448                 return NULL;
1449         }
1450
1451         if (fs_type)
1452                 fdata->fs_type = strdup(fs_type);
1453         else
1454                 fdata->fs_type = NULL;
1455         fdata->option = option;
1456
1457         return fdata;
1458 }
1459
1460 static void release_format_data(struct format_data *data)
1461 {
1462         if (data) {
1463                 free(data->fs_type);
1464                 free(data);
1465         }
1466 }
1467
1468 // Called by BlockThread - Real Mount Op
1469 static int block_mount_device(struct block_device *bdev, void *data)
1470 {
1471         dd_list *l;
1472         int ret;
1473         int thread_id;
1474
1475         if (!bdev)
1476                 return -EINVAL;
1477
1478         thread_id = bdev->thread_id;
1479         if (thread_id < 0 || thread_id >= THREAD_MAX)
1480                 return -EINVAL;
1481         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1482         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1483         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1484         if (!l) {
1485                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1486                 return -ENOENT;
1487         }
1488
1489         /* mount automatically */
1490         ret = mount_block_device(bdev);
1491         if (ret < 0)
1492                 _E("fail to mount block device for %s", bdev->data->devnode);
1493
1494         return ret;
1495 }
1496
1497 // Called by BlockThread - Real Format Op
1498 static int block_format_device(struct block_device *bdev, void *data)
1499 {
1500         dd_list *l;
1501         int ret;
1502         int thread_id;
1503         struct format_data *fdata = (struct format_data *)data;
1504
1505         if (!bdev || !fdata) {
1506                 ret = -EINVAL;
1507                 goto out;
1508         }
1509
1510         thread_id = bdev->thread_id;
1511         if (thread_id < 0 || thread_id >= THREAD_MAX)
1512                 return -EINVAL;
1513         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1514         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1515         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1516         if (!l) {
1517                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1518                 ret = -ENOENT;
1519                 goto out;
1520         }
1521
1522         ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1523         if (ret < 0)
1524                 _E("fail to mount block device for %s", bdev->data->devnode);
1525
1526 out:
1527         release_format_data(fdata);
1528
1529         return ret;
1530 }
1531
1532 // Called by BlockThread - Real Unmount Op
1533 static int block_unmount_device(struct block_device *bdev, void *data)
1534 {
1535         int ret;
1536         long option = (long)data;
1537
1538         if (!bdev)
1539                 return -EINVAL;
1540
1541         ret = unmount_block_device(bdev, option);
1542         if (ret < 0) {
1543                 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1544                 return ret;
1545         }
1546
1547         return 0;
1548 }
1549
1550 /* Called by BlockThread - Remove Operation
1551    Direct Call at BlockThread
1552    Previously this function was called by MainThread. However, it will increase complexity.
1553    Need thread lock before to call remove_operation
1554 */
1555 static void remove_operation(struct block_device *bdev)
1556 {
1557         struct operation_queue *op;
1558         dd_list *l, *next;
1559         char name[16];
1560         int thread_id;
1561
1562         assert(bdev);
1563
1564         thread_id = bdev->thread_id;
1565         if (thread_id < 0 || thread_id >= THREAD_MAX)
1566                 return;
1567
1568         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1569                 if (op->done) {
1570                         _D("Remove operation (%s, %s)",
1571                                         get_operation_char(op->op, name, sizeof(name)),
1572                                         bdev->data->devnode);
1573
1574                         DD_LIST_REMOVE(bdev->op_queue, op);
1575                         free(op);
1576                 }
1577         }
1578 }
1579
1580 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1581 {
1582         DBusMessage *rep;
1583
1584         if (!reply_handle)
1585                 return;
1586
1587         rep = make_dbus_reply_message_simple(reply_handle, result);
1588         reply_dbus_method_result(reply_handle, rep);
1589 }
1590
1591 // Called by BlockThread
1592 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1593 {
1594         struct operation_queue *temp;
1595         dd_list *l;
1596         int thread_id;
1597
1598         if (!bdev)
1599                 return;
1600
1601         if (!queue)
1602                 return;
1603
1604         if (!op)
1605                 return;
1606
1607         thread_id = bdev->thread_id;
1608         if (thread_id < 0 || thread_id >= THREAD_MAX)
1609                 return;
1610
1611         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1612
1613         DD_LIST_FOREACH(*queue, l, temp) {
1614                 if (temp->op == BLOCK_DEV_REMOVE) {
1615                         *op = temp;
1616                         break;
1617                 }
1618                 temp->done = true;
1619                 th_manager[thread_id].op_len--;
1620                 block_send_dbus_reply((*op)->reply_handle, 0);
1621         }
1622
1623         remove_operation(bdev);
1624         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1625 }
1626
1627 // Called by BlockThread
1628 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1629 {
1630         struct operation_queue *temp;
1631         dd_list *l;
1632         int thread_id;
1633         bool unmounted = false;
1634
1635         if (!bdev)
1636                 return false;
1637
1638         if (!queue)
1639                 return false;
1640
1641         if (!op)
1642                 return false;
1643
1644         thread_id = bdev->thread_id;
1645         if (thread_id < 0 || thread_id >= THREAD_MAX)
1646                 return false;
1647
1648         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1649         DD_LIST_FOREACH(*queue, l, temp) {
1650                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1651                         unmounted = true;
1652                         _D("Operation queue has unmount operation");
1653                         break;
1654                 }
1655         }
1656         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1657
1658         if (!unmounted)
1659                 return unmounted;
1660
1661         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1662
1663         DD_LIST_FOREACH(*queue, l, temp) {
1664                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1665                         *op = temp;
1666                         break;
1667                 }
1668                 temp->done = true;
1669                 th_manager[thread_id].op_len--;
1670                 block_send_dbus_reply((*op)->reply_handle, 0);
1671         }
1672
1673         remove_operation(bdev);
1674         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1675
1676         return unmounted;
1677 }
1678
1679 // Called by BlockThread
1680 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1681 {
1682         int ret = 0;
1683         int thread_id;
1684         char devnode[PATH_MAX];
1685         char name[16];
1686         enum block_dev_operation operation;
1687         bool unmounted = false;
1688
1689         assert(bdev);
1690
1691         if (!queue)
1692                 return;
1693
1694         thread_id = bdev->thread_id;
1695         if (thread_id < 0 || thread_id >= THREAD_MAX)
1696                 return;
1697
1698         snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1699
1700         do {
1701                 if (!op)
1702                         return;
1703                 if (op->done)
1704                         return;
1705
1706                 operation = op->op;
1707
1708                 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1709                         get_operation_char(operation, name, sizeof(name)), devnode);
1710
1711                 unmounted = false;
1712                 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1713                         check_removed(bdev, &queue, &op);
1714                         operation = op->op;
1715                         _D("Trigger operation again (%s, %s)",
1716                                 get_operation_char(operation, name, sizeof(name)), devnode);
1717                 }
1718                 if (operation == BLOCK_DEV_MOUNT) {
1719                         unmounted = check_unmount(bdev, &queue, &op);
1720                         if (unmounted) {
1721                                 operation = op->op;
1722                                 _D("Trigger operation again (%s, %s)",
1723                                         get_operation_char(operation, name, sizeof(name)), devnode);
1724                         }
1725                 }
1726
1727                 switch (operation) {
1728                 case BLOCK_DEV_INSERT:
1729                         break;
1730                 case BLOCK_DEV_MOUNT:
1731                         ret = block_mount_device(bdev, op->data);
1732                         _D("Mount (%s) result:(%d)", devnode, ret);
1733                         break;
1734                 case BLOCK_DEV_FORMAT:
1735                         ret = block_format_device(bdev, op->data);
1736                         _D("Format (%s) result:(%d)", devnode, ret);
1737                         break;
1738                 case BLOCK_DEV_UNMOUNT:
1739                         ret = block_unmount_device(bdev, op->data);
1740                         _D("Unmount (%s) result:(%d)", devnode, ret);
1741                         break;
1742                 case BLOCK_DEV_REMOVE:
1743                         /* Do nothing */
1744                         break;
1745                 default:
1746                         _E("Operation type is invalid (%d)", op->op);
1747                         ret = -EINVAL;
1748                         break;
1749                 }
1750
1751                 /* LOCK
1752                  * during checking the queue length */
1753                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1754
1755                 op->done = true;
1756                 th_manager[thread_id].op_len--;
1757
1758                 block_send_dbus_reply(op->reply_handle, ret);
1759
1760                 queue = bdev->op_queue;
1761                 if (queue != NULL) {
1762                         queue = DD_LIST_NEXT(queue);
1763                         if (queue != NULL)
1764                                 op = DD_LIST_NTH(queue, 0);
1765                         else
1766                                 op = NULL;
1767                 } else
1768                         op = NULL;
1769
1770                 remove_operation(bdev);
1771
1772                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1773                 /* UNLOCK */
1774
1775
1776                 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1777                         if (pipe_trigger(operation, bdev, 0) < 0)
1778                                 _E("fail to trigger pipe");
1779                 }
1780
1781         } while (true);
1782
1783 }
1784
1785 // Called by BlockThread
1786 static void *block_th_start(void *arg)
1787 {
1788         struct block_device *temp;
1789         struct manage_thread *th = (struct manage_thread *)arg;
1790         struct operation_queue *op = NULL;
1791         dd_list *elem;
1792         dd_list *queue = NULL;
1793         int thread_id;
1794
1795         assert(th);
1796
1797         thread_id = th->thread_id;
1798         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1799                 _E("Thread Number: %d", th->thread_id);
1800                 return NULL;
1801         }
1802
1803         do {
1804                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1805                 if (th_manager[thread_id].op_len == 0) {
1806                         _D("Operation queue of thread is empty");
1807                         pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1808                         _D("Wake up %d", thread_id);
1809                 }
1810
1811                 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1812                         queue = temp->op_queue;
1813                         do {
1814                                 op = DD_LIST_NTH(queue, 0);
1815                                 if (!op) {
1816                                         _D("Operation queue for device %s is Empty", temp->data->devnode);
1817                                         break;
1818                                 }
1819                                 if (op->done) {
1820                                         queue = DD_LIST_NEXT(queue);
1821                                         continue;
1822                                 }
1823                                 break;
1824                         } while (true);
1825                         if (op)
1826                                 break;
1827                 }
1828                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1829
1830                 if (op && !op->done)
1831                         trigger_operation(temp, queue, op);
1832
1833         } while (true);
1834 }
1835
1836 // This function will be refactored later
1837 // Especially, we don't need to keep th_node_list.
1838 static int find_thread(char *devnode)
1839 {
1840         dd_list *elem;
1841         char str[PATH_MAX];
1842         char *th_node;
1843         char *temp;
1844         char dev_scsi;
1845         int i, len, min, min_num;
1846         int dev_mmc = -1, part = -1, num;
1847
1848         len = 0;
1849         if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1850                 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1851                 num = dev_mmc;
1852                 while (num > 0) {
1853                         num = num / 10;
1854                         len++;
1855                 }
1856                 len = len + 12;
1857                 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1858                 th_node = strdup(str);
1859         } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1860                 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1861                 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1862                 th_node = strdup(str);
1863         } else
1864                 th_node = devnode;
1865
1866         len = strlen(th_node) + 1;
1867         min_num = 1000;
1868         min = -1;
1869         for (i = 0; i < THREAD_MAX; i++) {
1870                 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1871                         if (!strncmp(temp, th_node, len))
1872                                 return i;
1873                 }
1874                 if (th_manager[i].num_dev < min_num) {
1875                         min_num = th_manager[i].num_dev;
1876                         min = i;
1877                 }
1878         }
1879
1880         if (min >= 0 && min < THREAD_MAX) {
1881                 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1882                 return min;
1883         }
1884
1885         _E("Finding thread is failed");
1886         DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1887         return 0;
1888 }
1889
1890 /* Only Main thread is permmited */
1891 // Called by MainThread
1892 static int add_operation(struct block_device *bdev,
1893                 enum block_dev_operation operation,
1894                 dbus_method_reply_handle_h reply_handle, void *data)
1895 {
1896         struct operation_queue *op;
1897         int ret;
1898         int thread_id;
1899         bool start_th;
1900         char name[16];
1901
1902         if (!bdev)
1903                 return -EINVAL;
1904
1905
1906         _I("Add operation (%s, %s)",
1907                         get_operation_char(operation, name, sizeof(name)),
1908                         bdev->data->devnode);
1909
1910         thread_id = bdev->thread_id;
1911         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1912                 _E("Fail to find thread to add");
1913                 return -EPERM;
1914         }
1915
1916         op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
1917         if (!op) {
1918                 _E("malloc failed");
1919                 return -ENOMEM;
1920         }
1921
1922         op->op = operation;
1923         op->data = data;
1924         op->reply_handle = reply_handle;
1925
1926         /* LOCK
1927          * during adding queue and checking the queue length */
1928         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1929
1930         /* Only modified between lock and unlock of mutex */
1931         op->done = false;
1932
1933         start_th = th_manager[thread_id].start_th;
1934         DD_LIST_APPEND(bdev->op_queue, op);
1935         th_manager[thread_id].op_len++;
1936
1937         if (th_manager[thread_id].op_len == 1 && !start_th)
1938                 pthread_cond_signal(&(th_manager[thread_id].cond));
1939
1940         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1941         /* UNLOCK */
1942
1943         /* Need to disble app2ext whenever unmounting mmc */
1944         if (op->op == BLOCK_DEV_UNMOUNT &&
1945                 bdev->data->state == BLOCK_MOUNT &&
1946                 bdev->data->block_type == BLOCK_MMC_DEV &&
1947                 bdev->data->primary)
1948                 if (app2ext_disable_all_external_pkgs() < 0)
1949                         _E("app2ext_disable_all_external_pkgs() failed");
1950
1951
1952         if (start_th) {
1953                 _D("Start New thread for block device");
1954                 th_manager[thread_id].start_th = false;
1955                 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
1956                 if (ret != 0) {
1957                         _E("fail to create thread for %s", bdev->data->devnode);
1958                         return -EPERM;
1959                 }
1960
1961                 pthread_detach(th_manager[thread_id].th);
1962         }
1963
1964         return 0;
1965 }
1966
1967 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
1968 {
1969         DIR *dp;
1970         struct dirent entry;
1971         struct dirent *dir;
1972         const char *syspath;
1973         bool ret = false;
1974
1975         syspath = udev_device_get_syspath(dev);
1976         if (!syspath)
1977                 goto out;
1978
1979         dp = opendir(syspath);
1980         if (!dp) {
1981                 _E("fail to open %s", syspath);
1982                 goto out;
1983         }
1984
1985         /* TODO compare devname and d_name */
1986         while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
1987                 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
1988                     !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
1989                         ret = true;
1990                         break;
1991                 }
1992         }
1993
1994         closedir(dp);
1995
1996 out:
1997         return ret;
1998 }
1999
2000 static bool check_partition(struct udev_device *dev)
2001 {
2002         const char *devtype;
2003         const char *part_table_type;
2004         const char *fs_usage;
2005         bool ret = false;
2006
2007         /* only consider disk type, never partitions */
2008         devtype = udev_device_get_devtype(dev);
2009         if (!devtype)
2010                 goto out;
2011
2012         if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2013                                 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2014                 goto out;
2015
2016         part_table_type = udev_device_get_property_value(dev,
2017                         "ID_PART_TABLE_TYPE");
2018         if (part_table_type) {
2019                 fs_usage = udev_device_get_property_value(dev,
2020                                 "ID_FS_USAGE");
2021                 if (fs_usage &&
2022                     strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2023                         if (!disk_is_partitioned_by_kernel(dev))
2024                                         goto out;
2025                 }
2026                 ret = true;
2027                 goto out;
2028         }
2029
2030         if (disk_is_partitioned_by_kernel(dev)) {
2031                 ret = true;
2032                 goto out;
2033         }
2034
2035 out:
2036         return ret;
2037 }
2038
2039 // Called by MainThread
2040 static int add_block_device(struct udev_device *dev, const char *devnode)
2041 {
2042         struct block_data *data;
2043         struct block_device *bdev;
2044         bool partition;
2045         int ret;
2046         int thread_id;
2047
2048         partition = check_partition(dev);
2049         if (partition) {
2050                 /* if there is a partition, skip this request */
2051                 _I("%s device has partitions, skip this time", devnode);
2052                 return 0;
2053         }
2054
2055         data = make_block_data(devnode,
2056                         udev_device_get_syspath(dev),
2057                         udev_device_get_property_value(dev, "ID_FS_USAGE"),
2058                         udev_device_get_property_value(dev, "ID_FS_TYPE"),
2059                         udev_device_get_property_value(dev, "ID_FS_VERSION"),
2060                         udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2061                         udev_device_get_sysattr_value(dev, "ro"));
2062         if (!data) {
2063                 _E("fail to make block data for %s", devnode);
2064                 return -EPERM;
2065         }
2066
2067         if (!block_conf[data->block_type].multimount && !data->primary) {
2068                 _D("Not support multi mount by config info");
2069                 return -EPERM;
2070         }
2071
2072         bdev = make_block_device(data);
2073         if (!bdev) {
2074                 _E("fail to make block device for %s", devnode);
2075                 free_block_data(data);
2076                 return -EPERM;
2077         }
2078
2079         thread_id = find_thread(bdev->data->devnode);
2080         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2081                 _E("Fail to find thread to add");
2082                 free_block_data(data);
2083                 free_block_device(bdev);
2084                 return -EPERM;
2085         }
2086         bdev->thread_id = thread_id;
2087
2088         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2089         th_manager[thread_id].num_dev++;
2090         DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2091
2092         /* Create file for block device /run/external-storage/id */
2093         create_file(bdev->data->id, bdev->data->mount_point);
2094
2095         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2096
2097         ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2098         if (ret < 0) {
2099                 _E("Failed to add operation (insert %s)", devnode);
2100                 free_block_data(data);
2101                 free_block_device(bdev);
2102                 return ret;
2103         }
2104
2105         ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2106         if (ret < 0) {
2107                 _E("Failed to add operation (mount %s)", devnode);
2108                 free_block_data(data);
2109                 free_block_device(bdev);
2110                 return ret;
2111         }
2112
2113         return 0;
2114 }
2115
2116 static int remove_block_device(struct udev_device *dev, const char *devnode)
2117 {
2118         struct block_device *bdev;
2119         int ret;
2120
2121         bdev = find_block_device(devnode);
2122         if (!bdev) {
2123                 _E("fail to find block data for %s", devnode);
2124                 return -ENODEV;
2125         }
2126
2127         BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2128
2129         bdev->removed = true;
2130         if (bdev->on_private_op != REQ_NORMAL) {
2131                 bdev->on_private_op = REQ_NORMAL;
2132                 _D("Private operation state: %d", bdev->on_private_op);
2133         }
2134
2135         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2136         if (ret < 0) {
2137                 _E("Failed to add operation (unmount %s)", devnode);
2138                 return ret;
2139         }
2140
2141         ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2142         if (ret < 0) {
2143                 _E("Failed to add operation (remove %s)", devnode);
2144                 return ret;
2145         }
2146
2147         return 0;
2148 }
2149
2150 static int get_internal_storage_number(void)
2151 {
2152         struct libmnt_table *t = NULL;
2153         struct libmnt_fs *fs;
2154         const char *temp;
2155         char *name;
2156         int r = 0, dev_temp;
2157
2158         if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2159                 (is_emulator() && dev_internal_emul != '\0'))
2160                 return 0;
2161
2162         t = mnt_new_table();
2163         if (!t)
2164                 return -EPERM;
2165
2166         r = mnt_table_parse_mtab(t, NULL);
2167         if (r < 0) {
2168                 mnt_free_table(t);
2169                 return -EPERM;
2170         }
2171
2172         fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2173
2174         if (!fs) {
2175                 mnt_free_table(t);
2176                 return -EPERM;
2177         }
2178         temp = mnt_fs_get_srcpath(fs);
2179         name = strrchr(temp, '/');
2180         if (!name)
2181                 return -EPERM;
2182         name++;
2183         /* Boot from USB is not handled */
2184         if (!is_emulator()) {
2185                 if (!fnmatch(MMC_PATH, temp, 0))
2186                         sscanf(name, "mmcblk%d", &dev_internal);
2187                 else if (!fnmatch(SCSI_PATH, temp, 0))
2188                         sscanf(name, "sd%c", &dev_internal_scsi);
2189         } else {
2190                 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2191                         sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2192                 else
2193                         dev_internal_emul = '\0';
2194         }
2195
2196         mnt_free_table(t);
2197
2198         return 0;
2199 }
2200
2201 static int check_external_storage(const char* devnode)
2202 {
2203         char dev_scsi = '\0';
2204         char *name;
2205         char emul = '\0';
2206         int dev_num = -1, dev_temp;
2207
2208         if (!devnode)
2209                 return -EPERM;
2210
2211         name = strrchr(devnode, '/');
2212         if (!name)
2213                 return -EPERM;
2214         name++;
2215         if (!is_emulator()) {
2216                 if (!fnmatch(MMC_PATH, devnode, 0)) {
2217                         sscanf(name, "mmcblk%d", &dev_num);
2218                         if (dev_internal == dev_num) {
2219                                 _D("%s is internal storage", devnode);
2220                                 return 0;
2221                         }
2222                 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2223                         sscanf(name, "sd%c", &dev_scsi);
2224                         if (dev_internal_scsi == dev_scsi) {
2225                                 _D("%s is internal storage", devnode);
2226                                 return 0;
2227                         }
2228                 }
2229         } else {
2230                 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2231                         sscanf(name, "vd%c%d", &emul, &dev_temp);
2232                         if (dev_internal_emul == emul) {
2233                                 _D("%s is internal storage", devnode);
2234                                 return 0;
2235                         }
2236                 }
2237         }
2238
2239         return 1;
2240 }
2241
2242 static int check_already_handled(const char* devnode)
2243 {
2244         struct block_device *bdev;
2245         struct block_data *data;
2246         dd_list *elem;
2247         int i;
2248
2249         for (i = 0; i < THREAD_MAX; i++) {
2250                 pthread_mutex_lock(&(th_manager[i].mutex));
2251                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2252                         data = bdev->data;
2253                         if (!data)
2254                                 continue;
2255                         if (bdev->removed)
2256                                 continue;
2257                         if (!strncmp(data->devnode, devnode, sizeof(devnode) + 1)) {
2258                                 pthread_mutex_unlock(&(th_manager[i].mutex));
2259                                 return -1;
2260                         }
2261                 }
2262                 pthread_mutex_unlock(&(th_manager[i].mutex));
2263         }
2264
2265         return 0;
2266 }
2267
2268 static int block_init_from_udev_enumerate(void)
2269 {
2270         struct udev *udev;
2271         struct udev_enumerate *enumerate;
2272         struct udev_list_entry *list_entry, *list_sub_entry;
2273         struct udev_device *dev;
2274         const char *syspath;
2275         const char *devnode;
2276         int r = 0;
2277
2278         udev = udev_new();
2279         if (!udev) {
2280                 _E("fail to create udev library context");
2281                 return -EPERM;
2282         }
2283
2284         /* create a list of the devices in the 'usb' subsystem */
2285         enumerate = udev_enumerate_new(udev);
2286         if (!enumerate) {
2287                 _E("fail to create an enumeration context");
2288                 return -EPERM;
2289         }
2290
2291         if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2292                 (is_emulator() && dev_internal_emul == '\0')) {
2293                 r = get_internal_storage_number();
2294                 if (r < 0)
2295                         return -EPERM;
2296         }
2297
2298         udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2299         udev_enumerate_add_match_property(enumerate,
2300                         UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2301         udev_enumerate_add_match_property(enumerate,
2302                         UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2303         udev_enumerate_scan_devices(enumerate);
2304
2305         udev_list_entry_foreach(list_entry,
2306                         udev_enumerate_get_list_entry(enumerate)) {
2307                 syspath = udev_list_entry_get_name(list_entry);
2308                 if (!syspath)
2309                         continue;
2310
2311                 dev = udev_device_new_from_syspath(
2312                                 udev_enumerate_get_udev(enumerate),
2313                                 syspath);
2314                 if (!dev)
2315                         continue;
2316
2317                 devnode = NULL;
2318                 udev_list_entry_foreach(list_sub_entry,
2319                                 udev_device_get_devlinks_list_entry(dev)) {
2320                         const char *devlink = udev_list_entry_get_name(list_sub_entry);
2321                         if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2322                                 devnode = devlink;
2323                                 break;
2324                         }
2325                 }
2326
2327                 if (!devnode) {
2328                         devnode = udev_device_get_devnode(dev);
2329                         if (!devnode)
2330                                 continue;
2331
2332                         if (fnmatch(MMC_PATH, devnode, 0) &&
2333                             fnmatch(SCSI_PATH, devnode, 0))
2334                                 continue;
2335                 }
2336
2337                 r = check_external_storage(devnode);
2338                 if (r <= 0)
2339                         continue;
2340
2341                 r = check_already_handled(devnode);
2342                 if (r < 0) {
2343                         _I("%s is already handled", devnode);
2344                         continue;
2345                 }
2346
2347                 _I("%s device add", devnode);
2348                 add_block_device(dev, devnode);
2349
2350                 udev_device_unref(dev);
2351         }
2352
2353         udev_enumerate_unref(enumerate);
2354         udev_unref(udev);
2355         return 0;
2356 }
2357
2358 // Called by MainThread
2359 static void show_block_device_list(void)
2360 {
2361         struct block_device *bdev;
2362         struct block_data *data;
2363         dd_list *elem;
2364         int i;
2365
2366         for (i = 0; i < THREAD_MAX; i++) {
2367                 pthread_mutex_lock(&(th_manager[i].mutex));
2368                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2369                         data = bdev->data;
2370                         if (!data)
2371                                 continue;
2372                         if (bdev->removed)
2373                                 continue;
2374                         _D("%s:", data->devnode);
2375                         _D("\tSyspath: %s", data->syspath);
2376                         _D("\tBlock type: %s",
2377                                         (data->block_type == BLOCK_MMC_DEV ?
2378                                          BLOCK_TYPE_MMC : BLOCK_TYPE_SCSI));
2379                         _D("\tFs type: %s", data->fs_type);
2380                         _D("\tFs usage: %s", data->fs_usage);
2381                         _D("\tFs version: %s", data->fs_version);
2382                         _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2383                         _D("\tReadonly: %s",
2384                                         (data->readonly ? "true" : "false"));
2385                         _D("\tMount point: %s", data->mount_point);
2386                         _D("\tMount state: %s",
2387                                         (data->state == BLOCK_MOUNT ?
2388                                          "mount" : "unmount"));
2389                         _D("\tPrimary: %s",
2390                                         (data->primary ? "true" : "false"));
2391                         _D("\tID: %d", data->id);
2392                 }
2393                 pthread_mutex_unlock(&(th_manager[i].mutex));
2394         }
2395 }
2396
2397 // Called by MainThread
2398 static void remove_whole_block_device(void)
2399 {
2400         struct block_device *bdev;
2401         dd_list *elem;
2402         dd_list *next;
2403         int r;
2404         int i;
2405
2406         for (i = 0; i < THREAD_MAX; i++) {
2407                 do {
2408                         pthread_mutex_lock(&(th_manager[i].mutex));
2409                         DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2410                                 if (bdev->removed == false)
2411                                         break;
2412                         }
2413                         pthread_mutex_unlock(&(th_manager[i].mutex));
2414
2415                         if (bdev && bdev->removed == false) {
2416                                 bdev->removed = true;
2417                                 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2418                                 if (r < 0)
2419                                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2420
2421                                 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2422                                 if (r < 0)
2423                                         _E("Failed to add operation (remove %s)", bdev->data->devnode);
2424                         } else
2425                                 break;
2426                 } while (true);
2427         }
2428 }
2429
2430 static void booting_done(const char *sender_name,
2431                 const char *object_path, const char *interface_name,
2432                 const char *signal_name, DBusMessage *msg,
2433                 void *data)
2434 {
2435         static int done = 0;
2436         if (done > 0)
2437                 return;
2438         done = 1;
2439         _I("Booting done");
2440         /* if there is the attached device, try to mount */
2441         block_init_from_udev_enumerate();
2442         block_control = true;
2443         block_boot = true;
2444 }
2445
2446 static void block_poweroff(const char *sender_name,
2447                 const char *object_path, const char *interface_name,
2448                 const char *signal_name, DBusMessage *msg,
2449                 void *data)
2450 {
2451         static int status = 0;
2452         if (status > 0)
2453                 return;
2454         status = 1;
2455         _I("Power off");
2456         /* unregister mmc uevent control routine */
2457         unregister_udev_uevent_control(&uh);
2458         remove_whole_block_device();
2459 }
2460
2461 static void uevent_block_handler(struct udev_device *dev)
2462 {
2463         const char *devnode = NULL;
2464         const char *action;
2465         struct udev_list_entry *list_entry;
2466         int r;
2467
2468         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2469                 const char *devlink = udev_list_entry_get_name(list_entry);
2470                 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2471                         devnode = devlink;
2472                         break;
2473                 }
2474         }
2475
2476         if (!devnode) {
2477                 devnode = udev_device_get_devnode(dev);
2478                 if (!devnode)
2479                         return;
2480
2481                 if (fnmatch(MMC_PATH, devnode, 0) &&
2482                     fnmatch(SCSI_PATH, devnode, 0))
2483                         return;
2484         }
2485
2486         r = check_external_storage(devnode);
2487         if (r <= 0)
2488                 return;
2489
2490         action = udev_device_get_action(dev);
2491         if (!action)
2492                 return;
2493
2494         _I("%s device %s", devnode, action);
2495         if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD))) {
2496                 r = check_already_handled(devnode);
2497                 if (r < 0) {
2498                         _I("%s is already handled", devnode);
2499                         return;
2500                 }
2501
2502                 add_block_device(dev, devnode);
2503         } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE)))
2504                 remove_block_device(dev, devnode);
2505 }
2506
2507 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2508                 DBusMessage *msg, bool onprivate)
2509 {
2510         struct block_device *bdev;
2511         char *mount_point;
2512         int id;
2513         int ret = -EBADMSG;
2514
2515         if (!reply_handle || !msg)
2516                 goto out;
2517
2518         ret = dbus_message_get_args(msg, NULL,
2519                         DBUS_TYPE_INT32, &id,
2520                         DBUS_TYPE_STRING, &mount_point,
2521                         DBUS_TYPE_INVALID);
2522         if (!ret)
2523                 goto out;
2524
2525         bdev = find_block_device_by_id(id);
2526         if (!bdev) {
2527                 _E("Failed to find (%d) in the device list", id);
2528                 ret = -ENOENT;
2529                 goto out;
2530         }
2531         if (bdev->on_private_op != REQ_NORMAL) {
2532                 ret = -EPERM;
2533                 goto out;
2534         }
2535
2536         if (bdev->data->state == BLOCK_MOUNT) {
2537                 _I("%s is already mounted", bdev->data->devnode);
2538                 ret = -EALREADY;
2539                 goto out;
2540         }
2541
2542         if (onprivate) {
2543                 bdev->on_private_op = REQ_PRIVATE;
2544                 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2545                 _D("Private operation state: %d", bdev->on_private_op);
2546         } else {
2547                 if (bdev->on_private_op != REQ_NORMAL) {
2548                         _E("Failed to process mount operation");
2549                         ret = -EPERM;
2550                         goto out;
2551                 }
2552         }
2553
2554         /* if requester want to use a specific mount point */
2555         if (mount_point && strncmp(mount_point, "", 1) != 0) {
2556                 ret = change_mount_point(bdev, mount_point);
2557                 if (ret < 0) {
2558                         ret = -EPERM;
2559                         goto out;
2560                 }
2561
2562                 /* Modify /run/external-storage/id file */
2563                 create_file(bdev->data->id, bdev->data->mount_point);
2564         }
2565
2566         ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2567         if (ret < 0) {
2568                 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2569                 goto out;
2570         }
2571
2572         return NULL;
2573
2574 out:
2575         return make_dbus_reply_message_simple(reply_handle, ret);
2576 }
2577
2578 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2579                 DBusMessage *msg)
2580 {
2581         return request_mount_block(reply_handle, msg, false);
2582 }
2583
2584 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2585                 DBusMessage *msg)
2586 {
2587         return request_mount_block(reply_handle, msg, true);
2588 }
2589
2590 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2591                 DBusMessage *msg, bool onprivate)
2592 {
2593         struct block_device *bdev;
2594         pid_t pid;
2595         long option;
2596         int id;
2597         int ret = -EBADMSG;
2598
2599         if (!reply_handle || !msg)
2600                 goto out;
2601
2602         ret = dbus_message_get_args(msg, NULL,
2603                         DBUS_TYPE_INT32, &id,
2604                         DBUS_TYPE_INT32, &option,
2605                         DBUS_TYPE_INVALID);
2606         if (!ret)
2607                 goto out;
2608
2609         bdev = find_block_device_by_id(id);
2610         if (!bdev) {
2611                 _E("Failed to find (%d) in the device list", id);
2612                 ret = -ENOENT;
2613                 goto out;
2614         }
2615
2616         if (onprivate) {
2617                 pid = get_dbus_method_sender_pid(reply_handle);
2618                 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2619                         _E("Failed to process private unmount operation");
2620                         ret = -EPERM;
2621                         goto out;
2622                 }
2623         } else {
2624                 if (bdev->on_private_op != REQ_NORMAL) {
2625                         _E("Failed to process unmount operation");
2626                         ret = -EPERM;
2627                         goto out;
2628                 }
2629         }
2630
2631         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2632         if (ret < 0) {
2633                 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2634                 goto out;
2635         }
2636
2637         return NULL;
2638
2639 out:
2640         return make_dbus_reply_message_simple(reply_handle, ret);
2641 }
2642
2643 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2644                 DBusMessage *msg)
2645 {
2646         return request_unmount_block(reply_handle, msg, false);
2647 }
2648
2649 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2650                 DBusMessage *msg)
2651 {
2652         return request_unmount_block(reply_handle, msg, true);
2653 }
2654
2655 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2656                 DBusMessage *msg)
2657 {
2658         struct block_device *bdev;
2659         struct format_data *fdata;
2660         pid_t pid;
2661         int id;
2662         int option;
2663         int ret = -EBADMSG;
2664         int prev_state;
2665
2666         if (!reply_handle || !msg)
2667                 goto out;
2668
2669         ret = dbus_message_get_args(msg, NULL,
2670                         DBUS_TYPE_INT32, &id,
2671                         DBUS_TYPE_INT32, &option,
2672                         DBUS_TYPE_INVALID);
2673         if (!ret)
2674                 goto out;
2675
2676         bdev = find_block_device_by_id(id);
2677         if (!bdev) {
2678                 _E("Failed to find (%d) in the device list", id);
2679                 goto out;
2680         }
2681
2682         pid = get_dbus_method_sender_pid(reply_handle);
2683         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2684                 _E("Failed to format on private state");
2685                 ret = -EPERM;
2686                 goto out;
2687         }
2688
2689         fdata = get_format_data(NULL, option);
2690         if (!fdata) {
2691                 _E("Failed to get format data");
2692                 goto out;
2693         }
2694
2695         prev_state = bdev->data->state;
2696         if (prev_state == BLOCK_MOUNT) {
2697                 if (bdev->on_private_op == REQ_PRIVATE) {
2698                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
2699                         _D("Private operation state: %d", bdev->on_private_op);
2700                 }
2701                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2702                 if (ret < 0) {
2703                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2704                         release_format_data(fdata);
2705                         goto out;
2706                 }
2707         }
2708
2709         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2710         if (ret < 0) {
2711                 _E("Failed to add operation (format %s)", bdev->data->devnode);
2712                 release_format_data(fdata);
2713         }
2714
2715         /* Maintain previous state of mount/unmount */
2716         if (prev_state == BLOCK_MOUNT) {
2717                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2718                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
2719                         goto out;
2720                 }
2721         }
2722
2723         return NULL;
2724
2725 out:
2726         return make_dbus_reply_message_simple(reply_handle, ret);
2727 }
2728
2729 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
2730 {
2731         char *str_null = "";
2732
2733         if (!data || !piter)
2734                 return -EINVAL;
2735
2736         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2737                         &(data->block_type));
2738         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2739                         data->devnode ? &(data->devnode) : &str_null);
2740         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2741                         data->syspath ? &(data->syspath) : &str_null);
2742         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2743                         data->fs_usage ? &(data->fs_usage) : &str_null);
2744         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2745                         data->fs_type ? &(data->fs_type) : &str_null);
2746         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2747                         data->fs_version ? &(data->fs_version) : &str_null);
2748         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2749                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2750         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2751                         &(data->readonly));
2752         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2753                         data->mount_point ? &(data->mount_point) : &str_null);
2754         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2755                         &(data->state));
2756         dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
2757                         &(data->primary));
2758         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2759                         &(data->flags));
2760         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2761                         &(data->id));
2762
2763         return 0;
2764 }
2765
2766
2767 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
2768 {
2769         DBusMessageIter piter;
2770
2771         if (!data || !iter)
2772                 return -EINVAL;
2773
2774         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2775         add_device_to_iter(data, &piter);
2776         dbus_message_iter_close_container(iter, &piter);
2777
2778         return 0;
2779 }
2780
2781 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
2782 {
2783         DBusMessageIter piter;
2784         char *str_null = "";
2785
2786         if (!data || !iter)
2787                 return -EINVAL;
2788
2789         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2790         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2791                         &(data->block_type));
2792         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2793                         data->devnode ? &(data->devnode) : &str_null);
2794         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2795                         data->syspath ? &(data->syspath) : &str_null);
2796         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2797                         data->fs_usage ? &(data->fs_usage) : &str_null);
2798         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2799                         data->fs_type ? &(data->fs_type) : &str_null);
2800         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2801                         data->fs_version ? &(data->fs_version) : &str_null);
2802         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2803                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2804         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2805                         &(data->readonly));
2806         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2807                         data->mount_point ? &(data->mount_point) : &str_null);
2808         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2809                         &(data->state));
2810         dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
2811                         &(data->primary));
2812         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2813                         &(data->flags));
2814         dbus_message_iter_close_container(iter, &piter);
2815
2816         return 0;
2817 }
2818
2819 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
2820                 DBusMessage *msg)
2821 {
2822         DBusMessageIter iter;
2823         DBusMessage *reply;
2824         struct block_device *bdev;
2825         struct block_data *data;
2826         int ret, id;
2827
2828         if (!reply_handle || !msg)
2829                 return NULL;
2830
2831         reply = make_dbus_reply_message(reply_handle);
2832         if (!reply)
2833                 goto out;
2834
2835         ret = dbus_message_get_args(msg, NULL,
2836                         DBUS_TYPE_INT32, &id,
2837                         DBUS_TYPE_INVALID);
2838         if (!ret)
2839                 goto out;
2840
2841         bdev = find_block_device_by_id(id);
2842         if (!bdev)
2843                 goto out;
2844         data = bdev->data;
2845         if (!data)
2846                 goto out;
2847
2848         dbus_message_iter_init_append(reply, &iter);
2849         add_device_to_iter(data, &iter);
2850
2851 out:
2852         return reply;
2853 }
2854
2855 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
2856                 DBusMessage *msg)
2857 {
2858         show_block_device_list();
2859         return make_dbus_reply_message(reply_handle);
2860 }
2861
2862 // Called by MainThread
2863 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
2864                 DBusMessage *msg)
2865 {
2866         DBusMessageIter iter;
2867         DBusMessageIter aiter;
2868         DBusMessage *reply;
2869         struct block_device *bdev;
2870         struct block_data *data;
2871         dd_list *elem;
2872         char *type = NULL;
2873         int ret = -EBADMSG;
2874         int block_type;
2875         int i;
2876
2877         reply = make_dbus_reply_message(reply_handle);
2878
2879         ret = dbus_message_get_args(msg, NULL,
2880                         DBUS_TYPE_STRING, &type,
2881                         DBUS_TYPE_INVALID);
2882         if (!ret) {
2883                 _E("Failed to get args");
2884                 goto out;
2885         }
2886
2887         if (!type) {
2888                 _E("Delivered type is NULL");
2889                 goto out;
2890         }
2891
2892         _D("Block (%s) device list is requested", type);
2893
2894         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
2895                 block_type = BLOCK_SCSI_DEV;
2896         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
2897                 block_type = BLOCK_MMC_DEV;
2898         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
2899                 block_type = -1;
2900         else {
2901                 _E("Invalid type (%s) is requested", type);
2902                 goto out;
2903         }
2904
2905         dbus_message_iter_init_append(reply, &iter);
2906         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
2907
2908         for (i = 0; i < THREAD_MAX; i++) {
2909                 pthread_mutex_lock(&(th_manager[i].mutex));
2910                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2911                         data = bdev->data;
2912                         if (!data)
2913                                 continue;
2914                         if (bdev->removed)
2915                                 continue;
2916
2917                         switch (block_type) {
2918                         case BLOCK_SCSI_DEV:
2919                         case BLOCK_MMC_DEV:
2920                                 if (data->block_type != block_type)
2921                                         continue;
2922                                 break;
2923                         default:
2924                                 break;
2925                         }
2926                         add_device_to_struct_iter(data, &aiter);
2927                 }
2928                 pthread_mutex_unlock(&(th_manager[i].mutex));
2929         }
2930         dbus_message_iter_close_container(&iter, &aiter);
2931
2932 out:
2933         return reply;
2934 }
2935
2936 // Called by MainThread
2937 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
2938                 DBusMessage *msg)
2939 {
2940         DBusMessageIter iter;
2941         DBusMessageIter aiter;
2942         DBusMessage *reply;
2943         struct block_device *bdev;
2944         struct block_data *data;
2945         dd_list *elem;
2946         char *type = NULL;
2947         int ret = -EBADMSG;
2948         int block_type;
2949         int i;
2950
2951         reply = make_dbus_reply_message(reply_handle);
2952
2953         ret = dbus_message_get_args(msg, NULL,
2954                         DBUS_TYPE_STRING, &type,
2955                         DBUS_TYPE_INVALID);
2956         if (!ret) {
2957                 _E("Failed to get args");
2958                 goto out;
2959         }
2960
2961         if (!type) {
2962                 _E("Delivered type is NULL");
2963                 goto out;
2964         }
2965
2966         _D("Block (%s) device list is requested", type);
2967
2968         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
2969                 block_type = BLOCK_SCSI_DEV;
2970         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
2971                 block_type = BLOCK_MMC_DEV;
2972         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
2973                 block_type = -1;
2974         else {
2975                 _E("Invalid type (%s) is requested", type);
2976                 goto out;
2977         }
2978
2979         dbus_message_iter_init_append(reply, &iter);
2980         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
2981
2982         for (i = 0; i < THREAD_MAX; i++) {
2983                 pthread_mutex_lock(&(th_manager[i].mutex));
2984                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2985                         data = bdev->data;
2986                         if (!data)
2987                                 continue;
2988                         if (bdev->removed)
2989                                 continue;
2990
2991                         switch (block_type) {
2992                         case BLOCK_SCSI_DEV:
2993                         case BLOCK_MMC_DEV:
2994                                 if (data->block_type != block_type)
2995                                         continue;
2996                                 break;
2997                         default:
2998                                 break;
2999                         }
3000
3001                         add_device_to_iter_2(data, &aiter);
3002                 }
3003                 pthread_mutex_unlock(&(th_manager[i].mutex));
3004         }
3005         dbus_message_iter_close_container(&iter, &aiter);
3006
3007 out:
3008         return reply;
3009 }
3010
3011 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3012                 DBusMessage *msg)
3013 {
3014         DBusMessageIter iter;
3015         DBusMessage *reply;
3016         struct block_device *bdev;
3017         struct block_data *data, nodata = {0,};
3018         dd_list *elem;
3019         bool found;
3020         int i;
3021
3022         if (!reply_handle || !msg)
3023                 return NULL;
3024
3025         reply = make_dbus_reply_message(reply_handle);
3026         if (!reply)
3027                 goto out;
3028
3029         found = false;
3030         for (i = 0; i < THREAD_MAX; i++) {
3031                 pthread_mutex_lock(&(th_manager[i].mutex));
3032                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3033                         data = bdev->data;
3034                         if (!data)
3035                                 continue;
3036                         if (bdev->removed)
3037                                 continue;
3038                         if (data->block_type != BLOCK_MMC_DEV)
3039                                 continue;
3040                         if (!data->primary)
3041                                 continue;
3042                         found = true;
3043                         break;
3044                 }
3045                 pthread_mutex_unlock(&(th_manager[i].mutex));
3046                 if (found)
3047                         break;
3048         }
3049
3050         dbus_message_iter_init_append(reply, &iter);
3051         if (found)
3052                 add_device_to_iter(data, &iter);
3053         else {
3054                 nodata.id = -ENODEV;
3055                 add_device_to_iter(&nodata, &iter);
3056         }
3057
3058 out:
3059         return reply;
3060 }
3061
3062 /* 
3063   Method name      Method call format string  Reply format string 
3064 { "ShowDeviceList",                      NULL,               NULL, request_show_device_list },
3065 { "GetDeviceList" ,                       "s", "a(issssssisibii)", request_get_device_list },
3066 { "GetDeviceList2",                       "s",  "a(issssssisibi)", request_get_device_list_2 },
3067 { "Mount",                               "is",                "i", request_public_mount_block },
3068 { "Unmount",                             "ii",                "i", request_public_unmount_block },
3069 { "Format",                              "ii",                "i", request_format_block },
3070 { "GetDeviceInfo",                        "i",  "(issssssisibii)", request_get_device_info },
3071 { "GetMmcPrimary" ,                      NULL, "(issssssisibii)" , request_get_mmc_primary },
3072 { "PrivateMount",                        "is",                "i", request_private_mount_block },
3073 { "PrivateUnmount",                      "ii",                "i", request_private_unmount_block },
3074 */
3075
3076 static const dbus_method_s manager_methods[] = {
3077         { "ShowDeviceList",  NULL, request_show_device_list },
3078         { "GetDeviceList" ,   "s", request_get_device_list },
3079         { "GetDeviceList2",   "s", request_get_device_list_2 },
3080         { "Mount",           "is", request_public_mount_block },
3081         { "Unmount",         "ii", request_public_unmount_block },
3082         { "Format",          "ii", request_format_block },
3083         { "GetDeviceInfo",    "i", request_get_device_info },
3084         { "GetMmcPrimary" ,  NULL, request_get_mmc_primary },
3085         { "PrivateMount",    "is", request_private_mount_block },
3086         { "PrivateUnmount",  "ii", request_private_unmount_block },
3087 };
3088
3089 static dbus_interface_s block_interface = {
3090         .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3091         .methods = manager_methods,
3092         .nr_methods = ARRAY_SIZE(manager_methods),
3093 };
3094
3095 static int load_config(struct parse_result *result, void *user_data)
3096 {
3097         int index;
3098
3099         if (MATCH(result->section, "Block"))
3100                 return 0;
3101
3102         if (MATCH(result->section, "SCSI"))
3103                 index = BLOCK_SCSI_DEV;
3104         else if (MATCH(result->section, "MMC"))
3105                 index = BLOCK_MMC_DEV;
3106         else
3107                 return -EINVAL;
3108
3109         if (MATCH(result->name, "Multimount"))
3110                 block_conf[index].multimount =
3111                         (MATCH(result->value, "yes") ? true : false);
3112
3113         return 0;
3114 }
3115
3116 #ifdef BLOCK_TMPFS
3117 static int mount_root_path_tmpfs(void)
3118 {
3119         int ret;
3120         const char *root;
3121
3122         root = tzplatform_getenv(TZ_SYS_MEDIA);
3123         if (!root)
3124                 return -ENOTSUP;
3125
3126         if (access(root, F_OK) != 0)
3127                 return -ENODEV;
3128
3129         if (mount_check(root))
3130                 return 0;
3131
3132         ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3133         if (ret < 0) {
3134                 ret = -errno;
3135                 _E("tmpfs mount failed (%d)", ret);
3136                 return ret;
3137         }
3138
3139         return 0;
3140 }
3141 #else
3142 #define mount_root_path_tmpfs() 0
3143 #endif
3144
3145 static void block_init(void *data)
3146 {
3147         struct stat buf;
3148         int ret;
3149         int i;
3150         dbus_handle_h handle;
3151
3152         udev_init(NULL);
3153
3154         /* load config */
3155         ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3156         if (ret < 0)
3157                 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3158
3159         ret = mount_root_path_tmpfs();
3160         if (ret < 0)
3161                 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3162
3163         ret = dbus_get_connection(&handle);
3164         if (ret < 0)
3165                 _E("Failed to get dbus connection(%d)", ret);
3166
3167         /* register block manager object and interface */
3168         ret = register_dbus_methods(handle,
3169                         STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3170                         NULL, NULL);
3171         if (ret < 0)
3172                 _E("Failed to register block interface and methods (%d)", ret);
3173
3174         /* init pipe */
3175         ret = pipe_init();
3176         if (ret < 0)
3177                 _E("fail to init pipe");
3178
3179         /* register mmc uevent control routine */
3180         ret = register_udev_uevent_control(&uh);
3181         if (ret < 0)
3182                 _E("fail to register block uevent : %d", ret);
3183
3184         /* register notifier for below each event */
3185         register_dbus_signal(DEVICED_PATH_CORE,
3186                         DEVICED_INTERFACE_CORE,
3187                         SIGNAL_BOOTING_DONE,
3188                         booting_done, NULL, NULL);
3189
3190         register_dbus_signal(DEVICED_PATH_POWEROFF,
3191                         DEVICED_INTERFACE_POWEROFF,
3192                         SIGNAL_POWEROFF_STATE,
3193                         block_poweroff, NULL, NULL);
3194
3195         for (i = 0; i < THREAD_MAX; i++) {
3196                 th_manager[i].num_dev = 0;
3197                 th_manager[i].op_len = 0;
3198                 th_manager[i].start_th = true;
3199                 th_manager[i].thread_id = i;
3200                 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3201                 pthread_cond_init(&(th_manager[i].cond), NULL);
3202         }
3203
3204         ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3205         if (ret < 0) {
3206                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3207                 if (ret < 0)
3208                         _E("Failed to make directory: %d", errno);
3209         } else if (!S_ISDIR(buf.st_mode)) {
3210                 ret = remove(EXTERNAL_STORAGE_PATH);
3211                 if (ret < 0)
3212                         _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3213                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3214                 if (ret < 0)
3215                         _E("Failed to make directory: %d", errno);
3216         } else {
3217                 ret = chmod(EXTERNAL_STORAGE_PATH, 644);
3218                 if (ret < 0)
3219                         _E("Fail to change permissions of a file");
3220         }
3221 }
3222
3223 static void block_exit(void *data)
3224 {
3225         int ret, i;
3226
3227         udev_exit(NULL);
3228
3229         /* unregister notifier for below each event */
3230         unregister_dbus_signal(DEVICED_PATH_CORE,
3231                         DEVICED_INTERFACE_CORE,
3232                         SIGNAL_BOOTING_DONE, booting_done);
3233
3234         unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3235                         DEVICED_INTERFACE_POWEROFF,
3236                         SIGNAL_POWEROFF_STATE, block_poweroff);
3237
3238         /* exit pipe */
3239         pipe_exit();
3240
3241         /* unregister mmc uevent control routine */
3242         ret = unregister_udev_uevent_control(&uh);
3243         if (ret < 0)
3244                 _E("fail to unregister block uevent : %d", ret);
3245
3246         /* remove remaining blocks */
3247         remove_whole_block_device();
3248
3249         for (i = 0; i < THREAD_MAX; i++) {
3250                 if (!th_manager[i].start_th)
3251                         pthread_cancel(th_manager[i].th);
3252         }
3253
3254         block_control = false;
3255 }
3256
3257 static int block_start(void *data)
3258 {
3259         int ret;
3260
3261         if (!block_boot) {
3262                 _E("Cannot be started. Booting is not ready");
3263                 return -ENODEV;
3264         }
3265
3266         if (block_control) {
3267                 _I("Already started");
3268                 return 0;
3269         }
3270
3271         /* register mmc uevent control routine */
3272         ret = register_udev_uevent_control(&uh);
3273         if (ret < 0)
3274                 _E("fail to register block uevent : %d", ret);
3275
3276         block_init_from_udev_enumerate();
3277
3278         block_control = true;
3279
3280         _I("start");
3281         return 0;
3282 }
3283
3284 static int block_stop(void *data)
3285 {
3286         if (!block_boot) {
3287                 _E("Cannot be stopped. Booting is not ready");
3288                 return -ENODEV;
3289         }
3290
3291         if (!block_control) {
3292                 _I("Already stopped");
3293                 return 0;
3294         }
3295
3296         /* unregister mmc uevent control routine */
3297         unregister_udev_uevent_control(&uh);
3298
3299         /* remove the existing blocks */
3300         remove_whole_block_device();
3301
3302         block_control = false;
3303
3304         _I("stop");
3305         return 0;
3306 }
3307
3308 static storaged_module_interface block_module = {
3309         .name     = "block",
3310         .init     = block_init,
3311         .exit     = block_exit,
3312         .start    = block_start,
3313         .stop     = block_stop,
3314 };
3315
3316 __attribute__ ((visibility("default")))storaged_module_interface *
3317 storaged_get_module_interface(void)
3318 {
3319         return &block_module;
3320 }