3d1551a0f3434863e7f385c2f50468774a7398c1
[platform/core/system/storaged.git] / src / block / ext4.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
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/mount.h>
23 #include <limits.h>
24 #include <vconf.h>
25 #include <signal.h>
26 #include <fcntl.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <time.h>
30
31 #include "common.h"
32 #include "log.h"
33 #include "block.h"
34
35 #define FS_EXT4_NAME    "ext4"
36
37 static const char *check_smack_arg[] = {
38         "/usr/bin/mmc-smack-label",
39         NULL, NULL,
40 };
41
42 static const char *ext4_arg[] = {
43         "/sbin/mkfs.ext4",
44         NULL, NULL,
45 };
46
47 static const char *ext4_check_arg[] = {
48         "/sbin/fsck.ext4",
49         "-f", "-y", NULL, NULL,
50 };
51
52 static struct fs_check ext4_info = {
53         FS_TYPE_EXT4,
54         "ext4",
55         0x438,
56         2,
57         {0x53, 0xef},
58 };
59
60 static bool ext4_match(const char *devpath)
61 {
62         char buf[4];
63         int fd, r;
64
65         fd = open(devpath, O_RDONLY);
66         if (fd < 0) {
67                 _E("failed to open fd(%s) : %d", devpath, errno);
68                 return false;
69         }
70
71         /* check fs type with magic code */
72         r = lseek(fd, ext4_info.offset, SEEK_SET);
73         if (r < 0)
74                 goto error;
75
76         r = read(fd, buf, 2);
77         if (r < 0)
78                 goto error;
79
80         _I("ext4 search magic : 0x%2x, 0x%2x", buf[0], buf[1]);
81         if (memcmp(buf, ext4_info.magic, ext4_info.magic_sz))
82                 goto error;
83
84         close(fd);
85         _I("Storage type : %s", ext4_info.name);
86         return true;
87
88 error:
89         close(fd);
90         _E("failed to match with ext4(%s)", devpath);
91         return false;
92 }
93
94 static int ext4_check(const char *devpath)
95 {
96         int argc;
97         argc = ARRAY_SIZE(ext4_check_arg);
98         ext4_check_arg[argc - 2] = devpath;
99         return run_child(argc, ext4_check_arg);
100 }
101
102 static int mmc_check_smack(const char *mount_point)
103 {
104         char buf[NAME_MAX] = {0,};
105         int argc;
106         int ret;
107
108         snprintf(buf, sizeof(buf), "%s", mount_point);
109
110         argc = ARRAY_SIZE(check_smack_arg);
111         check_smack_arg[argc - 2] = buf;
112         ret = run_child(argc, check_smack_arg);
113
114         return ret;
115 }
116
117 static int check_smack_popup(void)
118 {
119         /* TODO: show smack popup */
120         return 0;
121 }
122
123 static int ext4_mount(bool smack, const char *devpath, const char *mount_point)
124 {
125         int r, retry = RETRY_COUNT;
126         struct timespec time = {0,};
127         unsigned long mountflags = MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_DIRSYNC;
128
129         do {
130                 r = mount(devpath, mount_point, "ext4", mountflags, NULL);
131                 if (!r) {
132                         _I("Storage Mounted[ext4]");
133                         if (smack) {
134                                 check_smack_popup();
135                                 mmc_check_smack(mount_point);
136                         }
137                         return 0;
138                 }
139                 _I("mount fail : r = %d, err = %d", r, errno);
140                 time.tv_nsec = 100 * NANO_SECOND_MULTIPLIER;
141                 nanosleep(&time, NULL);
142                 if (r < 0 && errno == EROFS)
143                         mountflags |= MS_RDONLY;
144         } while (r < 0 && (errno == ENOENT || errno == EROFS) && retry-- > 0);
145
146         return -errno;
147 }
148
149 static int ext4_format(const char *devpath)
150 {
151         int argc;
152         argc = ARRAY_SIZE(ext4_arg);
153         ext4_arg[argc - 2] = devpath;
154         return run_child(argc, ext4_arg);
155 }
156
157 static const struct block_fs_ops ext4_ops = {
158         .type = FS_TYPE_EXT4,
159         .name = "ext4",
160         .match = ext4_match,
161         .check = ext4_check,
162         .mount = ext4_mount,
163         .format = ext4_format,
164 };
165
166 static void __CONSTRUCTOR__ module_init(void)
167 {
168         add_fs(&ext4_ops);
169 }
170 /*
171 static void __DESTRUCTOR__ module_exit(void)
172 {
173         remove_fs(&ext4_ops);
174 }
175 */