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