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