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