Android-x86
Fork
Donation

  • R/O
  • HTTP
  • SSH
  • HTTPS

system-vold: Commit

system/vold


Commit MetaInfo

Revisión00e25a3b7a267c968db82ef670be35c000f1f8e8 (tree)
Tiempo2015-09-11 02:02:23
AutorChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Log Message

Merge branch 'cm-12.1' into lollipop-x86

Cambiar Resumen

Diferencia incremental

--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,9 @@ common_src_files := \
1212 Process.cpp \
1313 Ext4.cpp \
1414 Fat.cpp \
15+ Ntfs.cpp \
16+ Exfat.cpp \
17+ F2FS.cpp \
1518 Loop.cpp \
1619 Devmapper.cpp \
1720 ResponseCode.cpp \
@@ -23,6 +26,7 @@ common_src_files := \
2326 common_c_includes := \
2427 system/extras/ext4_utils \
2528 system/extras/f2fs_utils \
29+ external/e2fsprogs/lib \
2630 external/openssl/include \
2731 external/stlport/stlport \
2832 bionic \
@@ -41,6 +45,7 @@ common_shared_libraries := \
4145 libdiskconfig \
4246 libhardware_legacy \
4347 liblogwrap \
48+ libext2_blkid \
4449 libext4_utils \
4550 libf2fs_sparseblock \
4651 libcrypto \
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -15,7 +15,9 @@
1515 */
1616
1717 #include <stdlib.h>
18+#include <sys/param.h>
1819 #include <sys/socket.h>
20+#include <sys/stat.h>
1921 #include <sys/types.h>
2022 #include <netinet/in.h>
2123 #include <arpa/inet.h>
@@ -317,8 +319,35 @@ void CommandListener::AsecCmd::listAsecsInDirectory(SocketClient *cli, const cha
317319 while (!readdir_r(d, dent, &result) && result != NULL) {
318320 if (dent->d_name[0] == '.')
319321 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+
322351 size_t name_len = strlen(dent->d_name);
323352 if (name_len > 5 && name_len < 260 &&
324353 !strcmp(&dent->d_name[name_len - 5], ".asec")) {
--- a/DirectVolume.cpp
+++ b/DirectVolume.cpp
@@ -251,8 +251,8 @@ void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt)
251251 #ifdef PARTITION_DEBUG
252252 SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor);
253253 #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);
256256 } else {
257257 if ((mPartMinors[part_num - 1] == -1) && mPendingPartCount)
258258 mPendingPartCount--;
--- /dev/null
+++ b/Exfat.cpp
@@ -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+}
--- /dev/null
+++ b/Exfat.h
@@ -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
--- a/Ext4.cpp
+++ b/Ext4.cpp
@@ -40,16 +40,25 @@
4040
4141 #include <logwrap/logwrap.h>
4242
43+#include <private/android_filesystem_config.h>
44+
4345 #include "Ext4.h"
4446 #include "VoldUtil.h"
4547
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";
4852
4953 int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
50- bool executable) {
54+ bool executable, bool sdcard, const char *mountOpts) {
5155 int rc;
5256 unsigned long flags;
57+ char data[1024];
58+
59+ data[0] = '\0';
60+ if (mountOpts)
61+ strlcat(data, mountOpts, sizeof(data));
5362
5463 flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
5564
@@ -57,17 +66,78 @@ int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remo
5766 flags |= (ro ? MS_RDONLY : 0);
5867 flags |= (remount ? MS_REMOUNT : 0);
5968
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+ }
6184
6285 if (rc && errno == EROFS) {
6386 SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
6487 flags |= MS_RDONLY;
65- rc = mount(fsPath, mountPoint, "ext4", flags, NULL);
88+ rc = mount(fsPath, mountPoint, "ext4", flags, data);
6689 }
6790
6891 return rc;
6992 }
7093
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+
71141 int Ext4::resize(const char *fspath, unsigned int numSectors) {
72142 const char *args[4];
73143 char* size_str;
@@ -117,24 +187,32 @@ int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountp
117187 int rc;
118188 int status;
119189
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";
133195 args[4] = fsPath;
134196 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+ }
135214 }
136- rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false,
137- true);
215+
138216 if (rc != 0) {
139217 SLOGE("Filesystem (ext4) format failed due to logwrap error");
140218 errno = EIO;
--- a/Ext4.h
+++ b/Ext4.h
@@ -22,7 +22,8 @@
2222 class Ext4 {
2323 public:
2424 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);
2627 static int format(const char *fsPath, unsigned int numSectors, const char *mountpoint);
2728 static int resize(const char *fsPath, unsigned int numSectors);
2829 };
--- /dev/null
+++ b/F2FS.cpp
@@ -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+}
--- /dev/null
+++ b/F2FS.h
@@ -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
--- /dev/null
+++ b/Ntfs.cpp
@@ -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+}
--- /dev/null
+++ b/Ntfs.h
@@ -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
--- a/VoldUtil.c
+++ b/VoldUtil.c
@@ -19,11 +19,11 @@
1919
2020 unsigned int get_blkdev_size(int fd)
2121 {
22- unsigned int nr_sec;
22+ unsigned long nr_sec;
2323
2424 if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
2525 nr_sec = 0;
2626 }
2727
28- return nr_sec;
28+ return (unsigned int)nr_sec;
2929 }
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -35,6 +35,8 @@
3535
3636 #include <private/android_filesystem_config.h>
3737
38+#include <blkid/blkid.h>
39+
3840 #define LOG_TAG "Vold"
3941
4042 #include <cutils/fs.h>
@@ -45,7 +47,11 @@
4547 #include "Volume.h"
4648 #include "VolumeManager.h"
4749 #include "ResponseCode.h"
50+#include "Ext4.h"
4851 #include "Fat.h"
52+#include "Ntfs.h"
53+#include "Exfat.h"
54+#include "F2FS.h"
4955 #include "Process.h"
5056 #include "cryptfs.h"
5157
@@ -118,6 +124,7 @@ Volume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) {
118124 mUserLabel = NULL;
119125 mState = Volume::State_Init;
120126 mFlags = flags;
127+ mOpts = (rec->fs_options ? strdup(rec->fs_options) : NULL);
121128 mCurrentlyMountedKdev = -1;
122129 mPartIdx = rec->partnum;
123130 mRetryMount = false;
@@ -127,6 +134,7 @@ Volume::~Volume() {
127134 free(mLabel);
128135 free(mUuid);
129136 free(mUserLabel);
137+ free(mOpts);
130138 }
131139
132140 void Volume::setDebug(bool enable) {
@@ -141,6 +149,22 @@ dev_t Volume::getShareDevice() {
141149 return getDiskDevice();
142150 }
143151
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+
144168 void Volume::handleVolumeShared() {
145169 }
146170
@@ -231,6 +255,8 @@ int Volume::createDeviceNode(const char *path, int major, int minor) {
231255
232256 int Volume::formatVol(bool wipe) {
233257
258+ char* fstype = NULL;
259+
234260 if (getState() == Volume::State_NoMedia) {
235261 errno = ENODEV;
236262 return -1;
@@ -271,16 +297,36 @@ int Volume::formatVol(bool wipe) {
271297 sprintf(devicePath, "/dev/block/vold/%d:%d",
272298 major(partNode), minor(partNode));
273299
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+
274309 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);
276323 }
277324
278- if (Fat::format(devicePath, 0, wipe)) {
325+ if (ret < 0) {
279326 SLOGE("Failed to format (%s)", strerror(errno));
280- goto err;
281327 }
282328
283- ret = 0;
329+ free(fstype);
284330
285331 err:
286332 setState(Volume::State_Idle);
@@ -414,6 +460,7 @@ int Volume::mountVol() {
414460
415461 for (i = 0; i < n; i++) {
416462 char devicePath[255];
463+ char *fstype = NULL;
417464
418465 sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]),
419466 minor(deviceNodes[i]));
@@ -423,25 +470,112 @@ int Volume::mountVol() {
423470 errno = 0;
424471 setState(Volume::State_Checking);
425472
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-
438473 errno = 0;
439474 int gid;
440475
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;
445579 }
446580
447581 extractMetadata(devicePath);
--- a/Volume.h
+++ b/Volume.h
@@ -27,6 +27,7 @@ class Volume {
2727 private:
2828 int mState;
2929 int mFlags;
30+ char* mOpts;
3031
3132 public:
3233 static const int State_Init = -1;
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -552,7 +552,7 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
552552
553553 int mountStatus;
554554 if (usingExt4) {
555- mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false);
555+ mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false, false);
556556 } else {
557557 mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000,
558558 false);
@@ -771,7 +771,7 @@ int VolumeManager::finalizeAsec(const char *id) {
771771
772772 int result = 0;
773773 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);
775775 } else {
776776 result = Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false);
777777 }
@@ -840,7 +840,8 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f
840840 int ret = Ext4::doMount(loopDevice, mountPoint,
841841 false /* read-only */,
842842 true /* remount */,
843- false /* executable */);
843+ false /* executable */,
844+ false /* sdcard */);
844845 if (ret) {
845846 SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
846847 return -1;
@@ -902,7 +903,8 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f
902903 result |= Ext4::doMount(loopDevice, mountPoint,
903904 true /* read-only */,
904905 true /* remount */,
905- true /* execute */);
906+ true /* execute */,
907+ false /* sdcard */);
906908
907909 if (result) {
908910 SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
@@ -1339,7 +1341,7 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool
13391341
13401342 int result;
13411343 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);
13431345 } else {
13441346 result = Fat::doMount(dmDevice, mountPoint, readOnly, false, readOnly, ownerUid, 0, 0222, false);
13451347 }
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -573,6 +573,7 @@ static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t o
573573 /* Need to initialize the persistent data area */
574574 if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
575575 SLOGE("Cannot seek to persisent data offset\n");
576+ free(pdata);
576577 return;
577578 }
578579 /* 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
587588 crypt_ftr->persist_data_offset[0] = pdata_offset;
588589 crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE;
589590 crypt_ftr->minor_version = 1;
591+ free(pdata);
590592 }
591593
592594 if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) {
@@ -874,13 +876,13 @@ static int save_persistent_data(void)
874876 }
875877
876878 /* 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) {
878880 SLOGE("Cannot seek to write persistent data");
879881 goto err2;
880882 }
881883 if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) ==
882884 (int) crypt_ftr.persist_data_size) {
883- if (lseek(fd, erase_offset, SEEK_SET) < 0) {
885+ if (lseek64(fd, erase_offset, SEEK_SET) < 0) {
884886 SLOGE("Cannot seek to erase previous persistent data");
885887 goto err2;
886888 }
--- a/main.cpp
+++ b/main.cpp
@@ -215,8 +215,7 @@ static int process_config(VolumeManager *vm)
215215 flags |= VOL_ENCRYPTABLE;
216216 }
217217 /* 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])) {
220219 flags |= VOL_PROVIDES_ASEC;
221220 }
222221
Show on old repository browser