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