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