system/vold
Revisión | 00e25a3b7a267c968db82ef670be35c000f1f8e8 (tree) |
---|---|
Tiempo | 2015-09-11 02:02:23 |
Autor | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
Merge branch 'cm-12.1' into lollipop-x86
@@ -12,6 +12,9 @@ common_src_files := \ | ||
12 | 12 | Process.cpp \ |
13 | 13 | Ext4.cpp \ |
14 | 14 | Fat.cpp \ |
15 | + Ntfs.cpp \ | |
16 | + Exfat.cpp \ | |
17 | + F2FS.cpp \ | |
15 | 18 | Loop.cpp \ |
16 | 19 | Devmapper.cpp \ |
17 | 20 | ResponseCode.cpp \ |
@@ -23,6 +26,7 @@ common_src_files := \ | ||
23 | 26 | common_c_includes := \ |
24 | 27 | system/extras/ext4_utils \ |
25 | 28 | system/extras/f2fs_utils \ |
29 | + external/e2fsprogs/lib \ | |
26 | 30 | external/openssl/include \ |
27 | 31 | external/stlport/stlport \ |
28 | 32 | bionic \ |
@@ -41,6 +45,7 @@ common_shared_libraries := \ | ||
41 | 45 | libdiskconfig \ |
42 | 46 | libhardware_legacy \ |
43 | 47 | liblogwrap \ |
48 | + libext2_blkid \ | |
44 | 49 | libext4_utils \ |
45 | 50 | libf2fs_sparseblock \ |
46 | 51 | libcrypto \ |
@@ -15,7 +15,9 @@ | ||
15 | 15 | */ |
16 | 16 | |
17 | 17 | #include <stdlib.h> |
18 | +#include <sys/param.h> | |
18 | 19 | #include <sys/socket.h> |
20 | +#include <sys/stat.h> | |
19 | 21 | #include <sys/types.h> |
20 | 22 | #include <netinet/in.h> |
21 | 23 | #include <arpa/inet.h> |
@@ -317,8 +319,35 @@ void CommandListener::AsecCmd::listAsecsInDirectory(SocketClient *cli, const cha | ||
317 | 319 | while (!readdir_r(d, dent, &result) && result != NULL) { |
318 | 320 | if (dent->d_name[0] == '.') |
319 | 321 | continue; |
320 | - if (dent->d_type != DT_REG) | |
321 | - continue; | |
322 | + | |
323 | + if (dent->d_type != DT_UNKNOWN) { | |
324 | + if (dent->d_type != DT_REG) | |
325 | + continue; | |
326 | + } else { | |
327 | + // d_type is not guaranteed to be populated (e.g. ExFAT) | |
328 | + char path[MAXPATHLEN]; | |
329 | + struct stat sb; | |
330 | + | |
331 | + if (strlen(directory) + strlen(dent->d_name) + 2 > MAXPATHLEN) { | |
332 | + ALOGW("asec list: combined path length too long"); | |
333 | + continue; | |
334 | + } | |
335 | + | |
336 | + strcpy(path, directory); | |
337 | + strcat(path, "/"); | |
338 | + strcat(path, dent->d_name); | |
339 | + | |
340 | + if (lstat(path, &sb) < 0) { | |
341 | + ALOGW("asec list: error lstat on %s", path); | |
342 | + continue; | |
343 | + } | |
344 | + | |
345 | + if (!S_ISREG(sb.st_mode)) { | |
346 | + // Not a regular file | |
347 | + continue; | |
348 | + } | |
349 | + } | |
350 | + | |
322 | 351 | size_t name_len = strlen(dent->d_name); |
323 | 352 | if (name_len > 5 && name_len < 260 && |
324 | 353 | !strcmp(&dent->d_name[name_len - 5], ".asec")) { |
@@ -251,8 +251,8 @@ void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) | ||
251 | 251 | #ifdef PARTITION_DEBUG |
252 | 252 | SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor); |
253 | 253 | #endif |
254 | - if (part_num >= MAX_PARTITIONS) { | |
255 | - SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS-1); | |
254 | + if (part_num > MAX_PARTITIONS) { | |
255 | + SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS); | |
256 | 256 | } else { |
257 | 257 | if ((mPartMinors[part_num - 1] == -1) && mPendingPartCount) |
258 | 258 | mPendingPartCount--; |
@@ -0,0 +1,167 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2012 The Android Open Source Project | |
3 | + * Copyright (C) 2013 The CyanogenMod Project | |
4 | + * | |
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + * you may not use this file except in compliance with the License. | |
7 | + * You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | + | |
18 | +#include <stdio.h> | |
19 | +#include <stdlib.h> | |
20 | +#include <fcntl.h> | |
21 | +#include <unistd.h> | |
22 | +#include <errno.h> | |
23 | +#include <string.h> | |
24 | +#include <dirent.h> | |
25 | +#include <errno.h> | |
26 | +#include <fcntl.h> | |
27 | + | |
28 | +#include <sys/types.h> | |
29 | +#include <sys/stat.h> | |
30 | +#include <sys/types.h> | |
31 | +#include <sys/mman.h> | |
32 | +#include <sys/mount.h> | |
33 | +#include <sys/wait.h> | |
34 | + | |
35 | +#include <linux/kdev_t.h> | |
36 | +#include <logwrap/logwrap.h> | |
37 | +#include "VoldUtil.h" | |
38 | + | |
39 | +#define LOG_TAG "Vold" | |
40 | + | |
41 | +#include <cutils/log.h> | |
42 | +#include <cutils/properties.h> | |
43 | + | |
44 | +#include "Exfat.h" | |
45 | + | |
46 | +static char EXFAT_FSCK[] = "/system/bin/fsck.exfat"; | |
47 | +static char EXFAT_MKFS[] = "/system/bin/mkfs.exfat"; | |
48 | +static char EXFAT_MOUNT[] = "/system/bin/mount.exfat"; | |
49 | + | |
50 | +int Exfat::doMount(const char *fsPath, const char *mountPoint, | |
51 | + bool ro, bool remount, bool executable, | |
52 | + int ownerUid, int ownerGid, int permMask) { | |
53 | + | |
54 | + int rc = -1; | |
55 | + char mountData[255]; | |
56 | + const char *args[6]; | |
57 | + int status; | |
58 | + | |
59 | + if (access(EXFAT_MOUNT, X_OK)) { | |
60 | + SLOGE("Unable to mount, exFAT FUSE helper not found!"); | |
61 | + return rc; | |
62 | + } | |
63 | + | |
64 | + sprintf(mountData, | |
65 | + "noatime,nodev,nosuid,dirsync,uid=%d,gid=%d,fmask=%o,dmask=%o,%s,%s", | |
66 | + ownerUid, ownerGid, permMask, permMask, | |
67 | + (executable ? "exec" : "noexec"), | |
68 | + (ro ? "ro" : "rw")); | |
69 | + | |
70 | + args[0] = EXFAT_MOUNT; | |
71 | + args[1] = "-o"; | |
72 | + args[2] = mountData; | |
73 | + args[3] = fsPath; | |
74 | + args[4] = mountPoint; | |
75 | + args[5] = NULL; | |
76 | + | |
77 | + SLOGW("Executing exFAT mount (%s) -> (%s)", fsPath, mountPoint); | |
78 | + | |
79 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
80 | + true); | |
81 | + | |
82 | + if (rc && errno == EROFS) { | |
83 | + SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); | |
84 | + strcat(mountData, ",ro"); | |
85 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
86 | + true); | |
87 | + } | |
88 | + | |
89 | + return rc; | |
90 | +} | |
91 | + | |
92 | +int Exfat::check(const char *fsPath) { | |
93 | + | |
94 | + bool rw = true; | |
95 | + int rc = -1; | |
96 | + int status; | |
97 | + | |
98 | + if (access(EXFAT_FSCK, X_OK)) { | |
99 | + SLOGW("Skipping fs checks, exfatfsck not found.\n"); | |
100 | + return 0; | |
101 | + } | |
102 | + | |
103 | + do { | |
104 | + const char *args[3]; | |
105 | + args[0] = EXFAT_FSCK; | |
106 | + args[1] = fsPath; | |
107 | + args[2] = NULL; | |
108 | + | |
109 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
110 | + true); | |
111 | + | |
112 | + switch(rc) { | |
113 | + case 0: | |
114 | + SLOGI("exFAT filesystem check completed OK.\n"); | |
115 | + return 0; | |
116 | + case 1: | |
117 | + SLOGI("exFAT filesystem check completed, errors corrected OK.\n"); | |
118 | + return 0; | |
119 | + case 2: | |
120 | + SLOGE("exFAT filesystem check completed, errors corrected, need reboot.\n"); | |
121 | + return 0; | |
122 | + case 4: | |
123 | + SLOGE("exFAT filesystem errors left uncorrected.\n"); | |
124 | + return 0; | |
125 | + case 8: | |
126 | + SLOGE("exfatfsck operational error.\n"); | |
127 | + errno = EIO; | |
128 | + return -1; | |
129 | + default: | |
130 | + SLOGE("exFAT filesystem check failed (unknown exit code %d).\n", rc); | |
131 | + errno = EIO; | |
132 | + return -1; | |
133 | + } | |
134 | + } while (0); | |
135 | + | |
136 | + return 0; | |
137 | +} | |
138 | + | |
139 | +int Exfat::format(const char *fsPath) { | |
140 | + | |
141 | + int fd; | |
142 | + const char *args[3]; | |
143 | + int rc = -1; | |
144 | + int status; | |
145 | + | |
146 | + if (access(EXFAT_MKFS, X_OK)) { | |
147 | + SLOGE("Unable to format, mkexfatfs not found."); | |
148 | + return -1; | |
149 | + } | |
150 | + | |
151 | + args[0] = EXFAT_MKFS; | |
152 | + args[1] = fsPath; | |
153 | + args[2] = NULL; | |
154 | + | |
155 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
156 | + true); | |
157 | + | |
158 | + if (rc == 0) { | |
159 | + SLOGI("Filesystem (exFAT) formatted OK"); | |
160 | + return 0; | |
161 | + } else { | |
162 | + SLOGE("Format (exFAT) failed (unknown exit code %d)", rc); | |
163 | + errno = EIO; | |
164 | + return -1; | |
165 | + } | |
166 | + return 0; | |
167 | +} |
@@ -0,0 +1,30 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2013 The CyanogenMod Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +#ifndef _EXFAT_H | |
18 | +#define _EXFAT_H | |
19 | + | |
20 | +#include <unistd.h> | |
21 | + | |
22 | +class Exfat { | |
23 | +public: | |
24 | + static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, | |
25 | + bool executable, int ownerUid, int ownerGid, int permMask); | |
26 | + static int check(const char *fsPath); | |
27 | + static int format(const char *fsPath); | |
28 | +}; | |
29 | + | |
30 | +#endif |
@@ -40,16 +40,25 @@ | ||
40 | 40 | |
41 | 41 | #include <logwrap/logwrap.h> |
42 | 42 | |
43 | +#include <private/android_filesystem_config.h> | |
44 | + | |
43 | 45 | #include "Ext4.h" |
44 | 46 | #include "VoldUtil.h" |
45 | 47 | |
46 | -#define MKEXT4FS_PATH "/system/bin/make_ext4fs" | |
47 | -#define RESIZE2FS_PATH "/system/bin/resize2fs" | |
48 | +static char E2FSCK_PATH[] = "/system/bin/e2fsck"; | |
49 | +static char RESIZE2FS_PATH[] = "/system/bin/resize2fs"; | |
50 | +static char MKEXT4FS_PATH[] = "/system/bin/make_ext4fs"; | |
51 | +static char MKE2FS_PATH[] = "/system/bin/mke2fs"; | |
48 | 52 | |
49 | 53 | int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, |
50 | - bool executable) { | |
54 | + bool executable, bool sdcard, const char *mountOpts) { | |
51 | 55 | int rc; |
52 | 56 | unsigned long flags; |
57 | + char data[1024]; | |
58 | + | |
59 | + data[0] = '\0'; | |
60 | + if (mountOpts) | |
61 | + strlcat(data, mountOpts, sizeof(data)); | |
53 | 62 | |
54 | 63 | flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC; |
55 | 64 |
@@ -57,17 +66,78 @@ int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remo | ||
57 | 66 | flags |= (ro ? MS_RDONLY : 0); |
58 | 67 | flags |= (remount ? MS_REMOUNT : 0); |
59 | 68 | |
60 | - rc = mount(fsPath, mountPoint, "ext4", flags, NULL); | |
69 | +#ifdef HAVE_SELINUX | |
70 | + if (sdcard) { | |
71 | + // Mount external volumes with forced context | |
72 | + if (data[0]) | |
73 | + strlcat(data, ",", sizeof(data)); | |
74 | + strlcat(data, "context=u:object_r:sdcard_posix:s0", sizeof(data)); | |
75 | + } | |
76 | +#endif | |
77 | + rc = mount(fsPath, mountPoint, "ext4", flags, data); | |
78 | + | |
79 | + if (sdcard && rc == 0) { | |
80 | + // Write access workaround | |
81 | + chown(mountPoint, AID_MEDIA_RW, AID_MEDIA_RW); | |
82 | + chmod(mountPoint, 0755); | |
83 | + } | |
61 | 84 | |
62 | 85 | if (rc && errno == EROFS) { |
63 | 86 | SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); |
64 | 87 | flags |= MS_RDONLY; |
65 | - rc = mount(fsPath, mountPoint, "ext4", flags, NULL); | |
88 | + rc = mount(fsPath, mountPoint, "ext4", flags, data); | |
66 | 89 | } |
67 | 90 | |
68 | 91 | return rc; |
69 | 92 | } |
70 | 93 | |
94 | +int Ext4::check(const char *fsPath) { | |
95 | + bool rw = true; | |
96 | + if (access(E2FSCK_PATH, X_OK)) { | |
97 | + SLOGW("Skipping fs checks.\n"); | |
98 | + return 0; | |
99 | + } | |
100 | + | |
101 | + int rc = -1; | |
102 | + int status; | |
103 | + do { | |
104 | + const char *args[5]; | |
105 | + args[0] = E2FSCK_PATH; | |
106 | + args[1] = "-p"; | |
107 | + args[2] = "-f"; | |
108 | + args[3] = fsPath; | |
109 | + args[4] = NULL; | |
110 | + | |
111 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
112 | + true); | |
113 | + | |
114 | + switch(rc) { | |
115 | + case 0: | |
116 | + SLOGI("EXT4 Filesystem check completed OK.\n"); | |
117 | + return 0; | |
118 | + case 1: | |
119 | + SLOGI("EXT4 Filesystem check completed, errors corrected OK.\n"); | |
120 | + return 0; | |
121 | + case 2: | |
122 | + SLOGE("EXT4 Filesystem check completed, errors corrected, need reboot.\n"); | |
123 | + return 0; | |
124 | + case 4: | |
125 | + SLOGE("EXT4 Filesystem errors left uncorrected.\n"); | |
126 | + return 0; | |
127 | + case 8: | |
128 | + SLOGE("E2FSCK Operational error.\n"); | |
129 | + errno = EIO; | |
130 | + return -1; | |
131 | + default: | |
132 | + SLOGE("EXT4 Filesystem check failed (unknown exit code %d).\n", rc); | |
133 | + errno = EIO; | |
134 | + return -1; | |
135 | + } | |
136 | + } while (0); | |
137 | + | |
138 | + return 0; | |
139 | +} | |
140 | + | |
71 | 141 | int Ext4::resize(const char *fspath, unsigned int numSectors) { |
72 | 142 | const char *args[4]; |
73 | 143 | char* size_str; |
@@ -117,24 +187,32 @@ int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountp | ||
117 | 187 | int rc; |
118 | 188 | int status; |
119 | 189 | |
120 | - args[0] = MKEXT4FS_PATH; | |
121 | - args[1] = "-J"; | |
122 | - args[2] = "-a"; | |
123 | - args[3] = mountpoint; | |
124 | - if (numSectors) { | |
125 | - char tmp[32]; | |
126 | - snprintf(tmp, sizeof(tmp), "%u", numSectors * 512); | |
127 | - const char *size = tmp; | |
128 | - args[4] = "-l"; | |
129 | - args[5] = size; | |
130 | - args[6] = fsPath; | |
131 | - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); | |
132 | - } else { | |
190 | + if (mountpoint == NULL) { | |
191 | + args[0] = MKE2FS_PATH; | |
192 | + args[1] = "-j"; | |
193 | + args[2] = "-T"; | |
194 | + args[3] = "ext4"; | |
133 | 195 | args[4] = fsPath; |
134 | 196 | rc = android_fork_execvp(5, (char **)args, &status, false, true); |
197 | + } else { | |
198 | + args[0] = MKEXT4FS_PATH; | |
199 | + args[1] = "-J"; | |
200 | + args[2] = "-a"; | |
201 | + args[3] = mountpoint; | |
202 | + if (numSectors) { | |
203 | + char tmp[32]; | |
204 | + snprintf(tmp, sizeof(tmp), "%u", numSectors * 512); | |
205 | + const char *size = tmp; | |
206 | + args[4] = "-l"; | |
207 | + args[5] = size; | |
208 | + args[6] = fsPath; | |
209 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); | |
210 | + } else { | |
211 | + args[4] = fsPath; | |
212 | + rc = android_fork_execvp(5, (char **)args, &status, false, true); | |
213 | + } | |
135 | 214 | } |
136 | - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
137 | - true); | |
215 | + | |
138 | 216 | if (rc != 0) { |
139 | 217 | SLOGE("Filesystem (ext4) format failed due to logwrap error"); |
140 | 218 | errno = EIO; |
@@ -22,7 +22,8 @@ | ||
22 | 22 | class Ext4 { |
23 | 23 | public: |
24 | 24 | static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, |
25 | - bool executable); | |
25 | + bool executable, bool sdcard, const char *mountOpts = NULL); | |
26 | + static int check(const char *fsPath); | |
26 | 27 | static int format(const char *fsPath, unsigned int numSectors, const char *mountpoint); |
27 | 28 | static int resize(const char *fsPath, unsigned int numSectors); |
28 | 29 | }; |
@@ -0,0 +1,156 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2012 The Android Open Source Project | |
3 | + * Copyright (C) 2014 The CyanogenMod Project | |
4 | + * | |
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + * you may not use this file except in compliance with the License. | |
7 | + * You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | + | |
18 | +#include <stdio.h> | |
19 | +#include <stdlib.h> | |
20 | +#include <fcntl.h> | |
21 | +#include <unistd.h> | |
22 | +#include <errno.h> | |
23 | +#include <string.h> | |
24 | +#include <dirent.h> | |
25 | +#include <errno.h> | |
26 | +#include <fcntl.h> | |
27 | + | |
28 | +#include <sys/types.h> | |
29 | +#include <sys/stat.h> | |
30 | +#include <sys/mman.h> | |
31 | +#include <sys/mount.h> | |
32 | +#include <sys/wait.h> | |
33 | + | |
34 | +#include <linux/kdev_t.h> | |
35 | +#include <logwrap/logwrap.h> | |
36 | +#include "VoldUtil.h" | |
37 | + | |
38 | +#define LOG_TAG "Vold" | |
39 | +#include <cutils/log.h> | |
40 | +#include <cutils/properties.h> | |
41 | + | |
42 | +#include <private/android_filesystem_config.h> | |
43 | + | |
44 | +#include "F2FS.h" | |
45 | + | |
46 | +static char F2FS_FSCK[] = "/system/bin/fsck.f2fs"; | |
47 | +static char F2FS_MKFS[] = "/system/bin/mkfs.f2fs"; | |
48 | + | |
49 | +int F2FS::doMount(const char *fsPath, const char *mountPoint, bool ro, bool | |
50 | + remount, bool executable, bool sdcard) { | |
51 | + int rc; | |
52 | + unsigned long flags; | |
53 | + char data[255] = "inline_xattr,background_gc=off,active_logs=2"; | |
54 | + | |
55 | + flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC; | |
56 | + | |
57 | + flags |= (executable ? 0 : MS_NOEXEC); | |
58 | + flags |= (ro ? MS_RDONLY : 0); | |
59 | + flags |= (remount ? MS_REMOUNT : 0); | |
60 | + | |
61 | + if (sdcard) { | |
62 | + // Mount external volumes with forced context | |
63 | + strcat(data, ",context=u:object_r:sdcard_posix:s0"); | |
64 | + } | |
65 | + | |
66 | + rc = mount(fsPath, mountPoint, "f2fs", flags, data); | |
67 | + | |
68 | + if (sdcard && rc == 0) { | |
69 | + // Write access workaround | |
70 | + chown(mountPoint, AID_MEDIA_RW, AID_MEDIA_RW); | |
71 | + chmod(mountPoint, 0755); | |
72 | + } | |
73 | + | |
74 | + if (rc && errno == EROFS) { | |
75 | + SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); | |
76 | + flags |= MS_RDONLY; | |
77 | + rc = mount(fsPath, mountPoint, "f2fs", flags, data); | |
78 | + } | |
79 | + | |
80 | + return rc; | |
81 | +} | |
82 | + | |
83 | +int F2FS::check(const char *fsPath) { | |
84 | + | |
85 | + int rc = -1; | |
86 | + int status; | |
87 | + | |
88 | + if (access(F2FS_FSCK, X_OK)) { | |
89 | + SLOGW("Skipping fs checks, fsck.f2fs not found.\n"); | |
90 | + return 0; | |
91 | + } | |
92 | + | |
93 | + do { | |
94 | + const char *args[3]; | |
95 | + args[0] = F2FS_FSCK; | |
96 | + args[1] = fsPath; | |
97 | + args[2] = NULL; | |
98 | + | |
99 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
100 | + true); | |
101 | + | |
102 | + switch(rc) { | |
103 | + case 0: | |
104 | + SLOGI("F2FS filesystem check completed OK.\n"); | |
105 | + return 0; | |
106 | + case 1: | |
107 | + SLOGI("F2FS filesystem check completed, errors corrected OK.\n"); | |
108 | + return 0; | |
109 | + case 2: | |
110 | + SLOGE("F2FS filesystem check completed, errors corrected, need reboot.\n"); | |
111 | + return 0; | |
112 | + case 4: | |
113 | + SLOGE("F2FS filesystem errors left uncorrected.\n"); | |
114 | + return 0; | |
115 | + case 8: | |
116 | + SLOGE("F2FS.fsck operational error.\n"); | |
117 | + errno = EIO; | |
118 | + return -1; | |
119 | + default: | |
120 | + SLOGE("F2FS filesystem check failed (unknown exit code %d).\n", rc); | |
121 | + errno = EIO; | |
122 | + return -1; | |
123 | + } | |
124 | + } while (0); | |
125 | + | |
126 | + return 0; | |
127 | +} | |
128 | + | |
129 | +int F2FS::format(const char *fsPath) { | |
130 | + | |
131 | + const char *args[3]; | |
132 | + int rc = -1; | |
133 | + int status; | |
134 | + | |
135 | + if (access(F2FS_MKFS, X_OK)) { | |
136 | + SLOGE("Unable to format, mkfs.f2fs not found."); | |
137 | + return -1; | |
138 | + } | |
139 | + | |
140 | + args[0] = F2FS_MKFS; | |
141 | + args[1] = fsPath; | |
142 | + args[2] = NULL; | |
143 | + | |
144 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
145 | + true); | |
146 | + | |
147 | + if (rc == 0) { | |
148 | + SLOGI("Filesystem (F2FS) formatted OK"); | |
149 | + return 0; | |
150 | + } else { | |
151 | + SLOGE("Format (F2FS) failed (unknown exit code %d)", rc); | |
152 | + errno = EIO; | |
153 | + return -1; | |
154 | + } | |
155 | + return 0; | |
156 | +} |
@@ -0,0 +1,30 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2012 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +#ifndef _F2FS_H | |
18 | +#define _F2FS_H | |
19 | + | |
20 | +#include <unistd.h> | |
21 | + | |
22 | +class F2FS { | |
23 | +public: | |
24 | + static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, | |
25 | + bool executable, bool sdcard); | |
26 | + static int check(const char *fsPath); | |
27 | + static int format(const char *fsPath); | |
28 | +}; | |
29 | + | |
30 | +#endif |
@@ -0,0 +1,197 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2008 The Android Open Source Project | |
3 | + * Copyright (C) 2012 Freescale Semiconductor, Inc. | |
4 | + * | |
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + * you may not use this file except in compliance with the License. | |
7 | + * You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | + | |
18 | +#include <stdio.h> | |
19 | +#include <stdlib.h> | |
20 | +#include <fcntl.h> | |
21 | +#include <unistd.h> | |
22 | +#include <errno.h> | |
23 | +#include <string.h> | |
24 | +#include <dirent.h> | |
25 | +#include <errno.h> | |
26 | +#include <fcntl.h> | |
27 | + | |
28 | +#include <sys/types.h> | |
29 | +#include <sys/stat.h> | |
30 | +#include <sys/types.h> | |
31 | +#include <sys/mman.h> | |
32 | +#include <sys/mount.h> | |
33 | + | |
34 | +#include <linux/kdev_t.h> | |
35 | +#include <linux/fs.h> | |
36 | +#include <logwrap/logwrap.h> | |
37 | +#include "VoldUtil.h" | |
38 | + | |
39 | +#define LOG_TAG "Vold" | |
40 | + | |
41 | +#include <cutils/log.h> | |
42 | +#include <cutils/properties.h> | |
43 | + | |
44 | +#include "Ntfs.h" | |
45 | + | |
46 | +static char NTFS_FIX_PATH[] = "/system/bin/ntfsfix"; | |
47 | +static char NTFS_MOUNT_PATH[] = "/system/bin/ntfs-3g"; | |
48 | +static char MKNTFS_PATH[] = "/system/bin/mkntfs"; | |
49 | + | |
50 | +int Ntfs::check(const char *fsPath) { | |
51 | + | |
52 | + if (access(NTFS_FIX_PATH, X_OK)) { | |
53 | + SLOGW("Skipping fs checks\n"); | |
54 | + return 0; | |
55 | + } | |
56 | + | |
57 | + int rc = 0; | |
58 | + int status; | |
59 | + const char *args[4]; | |
60 | + /* we first use -n to do ntfs detection */ | |
61 | + args[0] = NTFS_FIX_PATH; | |
62 | + args[1] = "-n"; | |
63 | + args[2] = fsPath; | |
64 | + args[3] = NULL; | |
65 | + | |
66 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
67 | + true); | |
68 | + if (rc) { | |
69 | + errno = ENODATA; | |
70 | + return -1; | |
71 | + } | |
72 | + | |
73 | + SLOGI("Ntfs filesystem existed"); | |
74 | + | |
75 | + /* do the real fix */ | |
76 | + /* redo the ntfsfix without -n to fix problems */ | |
77 | + args[1] = fsPath; | |
78 | + args[2] = NULL; | |
79 | + | |
80 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
81 | + true); | |
82 | + if (rc) { | |
83 | + errno = EIO; | |
84 | + SLOGE("Filesystem check failed (unknown exit code %d)", rc); | |
85 | + return -1; | |
86 | + } | |
87 | + | |
88 | + SLOGI("Ntfs filesystem check completed OK"); | |
89 | + return 0; | |
90 | +} | |
91 | + | |
92 | +int Ntfs::doMount(const char *fsPath, const char *mountPoint, | |
93 | + bool ro, bool remount, bool executable, | |
94 | + int ownerUid, int ownerGid, int permMask, bool createLost) { | |
95 | + int rc; | |
96 | + char mountData[255]; | |
97 | + const char *args[6]; | |
98 | + int status; | |
99 | + | |
100 | + /* | |
101 | + * Note: This is a temporary hack. If the sampling profiler is enabled, | |
102 | + * we make the SD card world-writable so any process can write snapshots. | |
103 | + * | |
104 | + * TODO: Remove this code once we have a drop box in system_server. | |
105 | + */ | |
106 | + char value[PROPERTY_VALUE_MAX]; | |
107 | + property_get("persist.sampling_profiler", value, ""); | |
108 | + if (value[0] == '1') { | |
109 | + SLOGW("The SD card is world-writable because the" | |
110 | + " 'persist.sampling_profiler' system property is set to '1'."); | |
111 | + permMask = 0; | |
112 | + } | |
113 | + | |
114 | + sprintf(mountData, | |
115 | + "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o," | |
116 | + "shortname=mixed,nodev,nosuid,dirsync", | |
117 | + ownerUid, ownerGid, permMask, permMask); | |
118 | + | |
119 | + if (!executable) | |
120 | + strcat(mountData, ",noexec"); | |
121 | + if (ro) | |
122 | + strcat(mountData, ",ro"); | |
123 | + if (remount) | |
124 | + strcat(mountData, ",remount"); | |
125 | + | |
126 | + SLOGD("Mounting ntfs with options:%s\n", mountData); | |
127 | + | |
128 | + args[0] = NTFS_MOUNT_PATH; | |
129 | + args[1] = "-o"; | |
130 | + args[2] = mountData; | |
131 | + args[3] = fsPath; | |
132 | + args[4] = mountPoint; | |
133 | + args[5] = NULL; | |
134 | + | |
135 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
136 | + true); | |
137 | + | |
138 | + if (rc && errno == EROFS) { | |
139 | + SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); | |
140 | + strcat(mountData, ",ro"); | |
141 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
142 | + true); | |
143 | + | |
144 | + } | |
145 | + | |
146 | + if (rc == 0 && createLost) { | |
147 | + char *lost_path; | |
148 | + asprintf(&lost_path, "%s/LOST.DIR", mountPoint); | |
149 | + if (access(lost_path, F_OK)) { | |
150 | + /* | |
151 | + * Create a LOST.DIR in the root so we have somewhere to put | |
152 | + * lost cluster chains (fsck_msdos doesn't currently do this) | |
153 | + */ | |
154 | + if (mkdir(lost_path, 0755)) { | |
155 | + SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); | |
156 | + } | |
157 | + } | |
158 | + free(lost_path); | |
159 | + } | |
160 | + | |
161 | + return rc; | |
162 | +} | |
163 | + | |
164 | +int Ntfs::format(const char *fsPath, bool wipe) { | |
165 | + | |
166 | + const char *args[4]; | |
167 | + int rc = -1; | |
168 | + int status; | |
169 | + | |
170 | + if (access(MKNTFS_PATH, X_OK)) { | |
171 | + SLOGE("Unable to format, mkntfs not found."); | |
172 | + return -1; | |
173 | + } | |
174 | + | |
175 | + args[0] = MKNTFS_PATH; | |
176 | + if (wipe) { | |
177 | + args[1] = fsPath; | |
178 | + args[2] = NULL; | |
179 | + } else { | |
180 | + args[1] = "-f"; | |
181 | + args[2] = fsPath; | |
182 | + args[3] = NULL; | |
183 | + } | |
184 | + | |
185 | + rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, | |
186 | + true); | |
187 | + | |
188 | + if (rc == 0) { | |
189 | + SLOGI("Filesystem (NTFS) formatted OK"); | |
190 | + return 0; | |
191 | + } else { | |
192 | + SLOGE("Format (NTFS) failed (unknown exit code %d)", rc); | |
193 | + errno = EIO; | |
194 | + return -1; | |
195 | + } | |
196 | + return 0; | |
197 | +} |
@@ -0,0 +1,33 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2008 The Android Open Source Project | |
3 | + * Copyright (C) 2012 Freescale Semiconductor, Inc. | |
4 | + * | |
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + * you may not use this file except in compliance with the License. | |
7 | + * You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | + | |
18 | +#ifndef _NTFS_H | |
19 | +#define _NTFS_H | |
20 | + | |
21 | +#include <unistd.h> | |
22 | + | |
23 | +class Ntfs { | |
24 | +public: | |
25 | + static int check(const char *fsPath); | |
26 | + static int doMount(const char *fsPath, const char *mountPoint, | |
27 | + bool ro, bool remount, bool executable, | |
28 | + int ownerUid, int ownerGid, int permMask, | |
29 | + bool createLost); | |
30 | + static int format(const char *fsPath, bool wipe); | |
31 | +}; | |
32 | + | |
33 | +#endif |
@@ -19,11 +19,11 @@ | ||
19 | 19 | |
20 | 20 | unsigned int get_blkdev_size(int fd) |
21 | 21 | { |
22 | - unsigned int nr_sec; | |
22 | + unsigned long nr_sec; | |
23 | 23 | |
24 | 24 | if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) { |
25 | 25 | nr_sec = 0; |
26 | 26 | } |
27 | 27 | |
28 | - return nr_sec; | |
28 | + return (unsigned int)nr_sec; | |
29 | 29 | } |
@@ -35,6 +35,8 @@ | ||
35 | 35 | |
36 | 36 | #include <private/android_filesystem_config.h> |
37 | 37 | |
38 | +#include <blkid/blkid.h> | |
39 | + | |
38 | 40 | #define LOG_TAG "Vold" |
39 | 41 | |
40 | 42 | #include <cutils/fs.h> |
@@ -45,7 +47,11 @@ | ||
45 | 47 | #include "Volume.h" |
46 | 48 | #include "VolumeManager.h" |
47 | 49 | #include "ResponseCode.h" |
50 | +#include "Ext4.h" | |
48 | 51 | #include "Fat.h" |
52 | +#include "Ntfs.h" | |
53 | +#include "Exfat.h" | |
54 | +#include "F2FS.h" | |
49 | 55 | #include "Process.h" |
50 | 56 | #include "cryptfs.h" |
51 | 57 |
@@ -118,6 +124,7 @@ Volume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) { | ||
118 | 124 | mUserLabel = NULL; |
119 | 125 | mState = Volume::State_Init; |
120 | 126 | mFlags = flags; |
127 | + mOpts = (rec->fs_options ? strdup(rec->fs_options) : NULL); | |
121 | 128 | mCurrentlyMountedKdev = -1; |
122 | 129 | mPartIdx = rec->partnum; |
123 | 130 | mRetryMount = false; |
@@ -127,6 +134,7 @@ Volume::~Volume() { | ||
127 | 134 | free(mLabel); |
128 | 135 | free(mUuid); |
129 | 136 | free(mUserLabel); |
137 | + free(mOpts); | |
130 | 138 | } |
131 | 139 | |
132 | 140 | void Volume::setDebug(bool enable) { |
@@ -141,6 +149,22 @@ dev_t Volume::getShareDevice() { | ||
141 | 149 | return getDiskDevice(); |
142 | 150 | } |
143 | 151 | |
152 | +char *getFsType(const char * devicePath) { | |
153 | + char *fstype = NULL; | |
154 | + | |
155 | + SLOGD("Trying to get filesystem type for %s \n", devicePath); | |
156 | + | |
157 | + fstype = blkid_get_tag_value(NULL, "TYPE", devicePath); | |
158 | + if (fstype) { | |
159 | + SLOGD("Found %s filesystem on %s\n", fstype, devicePath); | |
160 | + } else { | |
161 | + SLOGE("None or unknown filesystem on %s\n", devicePath); | |
162 | + return NULL; | |
163 | + } | |
164 | + | |
165 | + return fstype; | |
166 | +} | |
167 | + | |
144 | 168 | void Volume::handleVolumeShared() { |
145 | 169 | } |
146 | 170 |
@@ -231,6 +255,8 @@ int Volume::createDeviceNode(const char *path, int major, int minor) { | ||
231 | 255 | |
232 | 256 | int Volume::formatVol(bool wipe) { |
233 | 257 | |
258 | + char* fstype = NULL; | |
259 | + | |
234 | 260 | if (getState() == Volume::State_NoMedia) { |
235 | 261 | errno = ENODEV; |
236 | 262 | return -1; |
@@ -271,16 +297,36 @@ int Volume::formatVol(bool wipe) { | ||
271 | 297 | sprintf(devicePath, "/dev/block/vold/%d:%d", |
272 | 298 | major(partNode), minor(partNode)); |
273 | 299 | |
300 | + fstype = getFsType((const char*)devicePath); | |
301 | + | |
302 | + /* If the device has no filesystem, let's default to vfat. | |
303 | + * A NULL fstype will cause a MAPERR in the format | |
304 | + * switch below */ | |
305 | + if (fstype == NULL) { | |
306 | + fstype = strdup("vfat"); | |
307 | + } | |
308 | + | |
274 | 309 | if (mDebug) { |
275 | - SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); | |
310 | + SLOGI("Formatting volume %s (%s) as %s", getLabel(), devicePath, fstype); | |
311 | + } | |
312 | + | |
313 | + if (strcmp(fstype, "f2fs") == 0) { | |
314 | + ret = F2FS::format(devicePath); | |
315 | + } else if (strcmp(fstype, "exfat") == 0) { | |
316 | + ret = Exfat::format(devicePath); | |
317 | + } else if (strcmp(fstype, "ext4") == 0) { | |
318 | + ret = Ext4::format(devicePath, 0, NULL); | |
319 | + } else if (strcmp(fstype, "ntfs") == 0) { | |
320 | + ret = Ntfs::format(devicePath, wipe); | |
321 | + } else { | |
322 | + ret = Fat::format(devicePath, 0, wipe); | |
276 | 323 | } |
277 | 324 | |
278 | - if (Fat::format(devicePath, 0, wipe)) { | |
325 | + if (ret < 0) { | |
279 | 326 | SLOGE("Failed to format (%s)", strerror(errno)); |
280 | - goto err; | |
281 | 327 | } |
282 | 328 | |
283 | - ret = 0; | |
329 | + free(fstype); | |
284 | 330 | |
285 | 331 | err: |
286 | 332 | setState(Volume::State_Idle); |
@@ -414,6 +460,7 @@ int Volume::mountVol() { | ||
414 | 460 | |
415 | 461 | for (i = 0; i < n; i++) { |
416 | 462 | char devicePath[255]; |
463 | + char *fstype = NULL; | |
417 | 464 | |
418 | 465 | sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]), |
419 | 466 | minor(deviceNodes[i])); |
@@ -423,25 +470,112 @@ int Volume::mountVol() { | ||
423 | 470 | errno = 0; |
424 | 471 | setState(Volume::State_Checking); |
425 | 472 | |
426 | - if (Fat::check(devicePath)) { | |
427 | - if (errno == ENODATA) { | |
428 | - SLOGW("%s does not contain a FAT filesystem\n", devicePath); | |
429 | - continue; | |
430 | - } | |
431 | - errno = EIO; | |
432 | - /* Badness - abort the mount */ | |
433 | - SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); | |
434 | - setState(Volume::State_Idle); | |
435 | - return -1; | |
436 | - } | |
437 | - | |
438 | 473 | errno = 0; |
439 | 474 | int gid; |
440 | 475 | |
441 | - if (Fat::doMount(devicePath, getMountpoint(), false, false, false, | |
442 | - AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { | |
443 | - SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); | |
444 | - continue; | |
476 | + fstype = getFsType((const char *)devicePath); | |
477 | + | |
478 | + if (fstype != NULL) { | |
479 | + if (strcmp(fstype, "vfat") == 0) { | |
480 | + | |
481 | + if (Fat::check(devicePath)) { | |
482 | + errno = EIO; | |
483 | + /* Badness - abort the mount */ | |
484 | + SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); | |
485 | + setState(Volume::State_Idle); | |
486 | + free(fstype); | |
487 | + return -1; | |
488 | + } | |
489 | + | |
490 | + if (Fat::doMount(devicePath, getMountpoint(), false, false, false, | |
491 | + AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { | |
492 | + SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); | |
493 | + continue; | |
494 | + } | |
495 | + | |
496 | + } else if (strcmp(fstype, "ext4") == 0) { | |
497 | + | |
498 | + if (Ext4::check(devicePath)) { | |
499 | + errno = EIO; | |
500 | + /* Badness - abort the mount */ | |
501 | + SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); | |
502 | + setState(Volume::State_Idle); | |
503 | + free(fstype); | |
504 | + return -1; | |
505 | + } | |
506 | + | |
507 | + if (Ext4::doMount(devicePath, getMountpoint(), false, false, false, true, mOpts)) { | |
508 | + SLOGE("%s failed to mount via EXT4 (%s)\n", devicePath, strerror(errno)); | |
509 | + continue; | |
510 | + } | |
511 | + | |
512 | + } else if (strcmp(fstype, "ntfs") == 0) { | |
513 | + | |
514 | + if (Ntfs::doMount(devicePath, getMountpoint(), false, false, false, | |
515 | + AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { | |
516 | + SLOGE("%s failed to mount via NTFS (%s)\n", devicePath, strerror(errno)); | |
517 | + continue; | |
518 | + } | |
519 | + | |
520 | + } else if (strcmp(fstype, "f2fs") == 0) { | |
521 | + /* | |
522 | + * fsck.f2fs does not fix any inconsistencies "yet". | |
523 | + * | |
524 | + * Disable fsck routine as this is just wasting time | |
525 | + * consumed to mount f2fs volumes. | |
526 | + * | |
527 | + * The kernel can determine if a f2fs volume is too damaged | |
528 | + * that it shouldn't get mounted. | |
529 | + */ | |
530 | + #if 0 | |
531 | + if (F2FS::check(devicePath)) { | |
532 | + errno = EIO; | |
533 | + /* Badness - abort the mount */ | |
534 | + SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); | |
535 | + setState(Volume::State_Idle); | |
536 | + free(fstype); | |
537 | + return -1; | |
538 | + } | |
539 | + #endif | |
540 | + | |
541 | + if (F2FS::doMount(devicePath, getMountpoint(), false, false, false, true)) { | |
542 | + SLOGE("%s failed to mount via F2FS (%s)\n", devicePath, strerror(errno)); | |
543 | + continue; | |
544 | + } | |
545 | + | |
546 | + } else if (strcmp(fstype, "exfat") == 0) { | |
547 | + | |
548 | + if (Exfat::check(devicePath)) { | |
549 | + errno = EIO; | |
550 | + /* Badness - abort the mount */ | |
551 | + SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); | |
552 | + setState(Volume::State_Idle); | |
553 | + free(fstype); | |
554 | + return -1; | |
555 | + } | |
556 | + | |
557 | + if (Exfat::doMount(devicePath, getMountpoint(), false, false, false, | |
558 | + AID_MEDIA_RW, AID_MEDIA_RW, 0007)) { | |
559 | + SLOGE("%s failed to mount via EXFAT (%s)\n", devicePath, strerror(errno)); | |
560 | + continue; | |
561 | + } | |
562 | + | |
563 | + } else { | |
564 | + // Unsupported filesystem | |
565 | + errno = ENODATA; | |
566 | + setState(Volume::State_Idle); | |
567 | + free(fstype); | |
568 | + return -1; | |
569 | + } | |
570 | + | |
571 | + free(fstype); | |
572 | + | |
573 | + } else { | |
574 | + // Unsupported filesystem | |
575 | + errno = ENODATA; | |
576 | + setState(Volume::State_Idle); | |
577 | + free(fstype); | |
578 | + return -1; | |
445 | 579 | } |
446 | 580 | |
447 | 581 | extractMetadata(devicePath); |
@@ -27,6 +27,7 @@ class Volume { | ||
27 | 27 | private: |
28 | 28 | int mState; |
29 | 29 | int mFlags; |
30 | + char* mOpts; | |
30 | 31 | |
31 | 32 | public: |
32 | 33 | static const int State_Init = -1; |
@@ -552,7 +552,7 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha | ||
552 | 552 | |
553 | 553 | int mountStatus; |
554 | 554 | if (usingExt4) { |
555 | - mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false); | |
555 | + mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false, false); | |
556 | 556 | } else { |
557 | 557 | mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000, |
558 | 558 | false); |
@@ -771,7 +771,7 @@ int VolumeManager::finalizeAsec(const char *id) { | ||
771 | 771 | |
772 | 772 | int result = 0; |
773 | 773 | if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { |
774 | - result = Ext4::doMount(loopDevice, mountPoint, true, true, true); | |
774 | + result = Ext4::doMount(loopDevice, mountPoint, true, true, true, false); | |
775 | 775 | } else { |
776 | 776 | result = Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false); |
777 | 777 | } |
@@ -840,7 +840,8 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f | ||
840 | 840 | int ret = Ext4::doMount(loopDevice, mountPoint, |
841 | 841 | false /* read-only */, |
842 | 842 | true /* remount */, |
843 | - false /* executable */); | |
843 | + false /* executable */, | |
844 | + false /* sdcard */); | |
844 | 845 | if (ret) { |
845 | 846 | SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno)); |
846 | 847 | return -1; |
@@ -902,7 +903,8 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f | ||
902 | 903 | result |= Ext4::doMount(loopDevice, mountPoint, |
903 | 904 | true /* read-only */, |
904 | 905 | true /* remount */, |
905 | - true /* execute */); | |
906 | + true /* execute */, | |
907 | + false /* sdcard */); | |
906 | 908 | |
907 | 909 | if (result) { |
908 | 910 | SLOGE("ASEC fix permissions failed (%s)", strerror(errno)); |
@@ -1339,7 +1341,7 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool | ||
1339 | 1341 | |
1340 | 1342 | int result; |
1341 | 1343 | if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { |
1342 | - result = Ext4::doMount(dmDevice, mountPoint, readOnly, false, readOnly); | |
1344 | + result = Ext4::doMount(dmDevice, mountPoint, readOnly, false, readOnly, false); | |
1343 | 1345 | } else { |
1344 | 1346 | result = Fat::doMount(dmDevice, mountPoint, readOnly, false, readOnly, ownerUid, 0, 0222, false); |
1345 | 1347 | } |
@@ -573,6 +573,7 @@ static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t o | ||
573 | 573 | /* Need to initialize the persistent data area */ |
574 | 574 | if (lseek64(fd, pdata_offset, SEEK_SET) == -1) { |
575 | 575 | SLOGE("Cannot seek to persisent data offset\n"); |
576 | + free(pdata); | |
576 | 577 | return; |
577 | 578 | } |
578 | 579 | /* Write all zeros to the first copy, making it invalid */ |
@@ -587,6 +588,7 @@ static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t o | ||
587 | 588 | crypt_ftr->persist_data_offset[0] = pdata_offset; |
588 | 589 | crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE; |
589 | 590 | crypt_ftr->minor_version = 1; |
591 | + free(pdata); | |
590 | 592 | } |
591 | 593 | |
592 | 594 | if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) { |
@@ -874,13 +876,13 @@ static int save_persistent_data(void) | ||
874 | 876 | } |
875 | 877 | |
876 | 878 | /* Write the new copy first, if successful, then erase the old copy */ |
877 | - if (lseek(fd, write_offset, SEEK_SET) < 0) { | |
879 | + if (lseek64(fd, write_offset, SEEK_SET) < 0) { | |
878 | 880 | SLOGE("Cannot seek to write persistent data"); |
879 | 881 | goto err2; |
880 | 882 | } |
881 | 883 | if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) == |
882 | 884 | (int) crypt_ftr.persist_data_size) { |
883 | - if (lseek(fd, erase_offset, SEEK_SET) < 0) { | |
885 | + if (lseek64(fd, erase_offset, SEEK_SET) < 0) { | |
884 | 886 | SLOGE("Cannot seek to erase previous persistent data"); |
885 | 887 | goto err2; |
886 | 888 | } |
@@ -215,8 +215,7 @@ static int process_config(VolumeManager *vm) | ||
215 | 215 | flags |= VOL_ENCRYPTABLE; |
216 | 216 | } |
217 | 217 | /* Only set this flag if there is not an emulated sd card */ |
218 | - if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) && | |
219 | - !strcmp(fstab->recs[i].fs_type, "vfat")) { | |
218 | + if (fs_mgr_is_noemulatedsd(&fstab->recs[i])) { | |
220 | 219 | flags |= VOL_PROVIDES_ASEC; |
221 | 220 | } |
222 | 221 |