summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <shade@chemlab.org>2013-07-06 04:00:54 -0700
committerSteve Kondik <shade@chemlab.org>2013-07-07 12:27:47 -0700
commitce6e95e153201be046736e2360f51d3bca48c9f4 (patch)
tree3dab5e2b68fe7587ca02e05c8ee51b1ea0ba7752
parente336c0ca31f2768661063220e2a1cb83fd55b92d (diff)
downloadsystem_vold-ce6e95e153201be046736e2360f51d3bca48c9f4.zip
system_vold-ce6e95e153201be046736e2360f51d3bca48c9f4.tar.gz
system_vold-ce6e95e153201be046736e2360f51d3bca48c9f4.tar.bz2
vold: exFAT support
* Add support for exFAT using FUSE implementation. Change-Id: I590c7b1bc8fbcb8c0b2c669f4073ac022857e4da
-rw-r--r--Android.mk1
-rw-r--r--Exfat.cpp160
-rw-r--r--Exfat.h30
-rw-r--r--Volume.cpp18
4 files changed, 209 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index b53c8e7..8eadd85 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,6 +14,7 @@ common_src_files := \
Ext4.cpp \
Fat.cpp \
Ntfs.cpp \
+ Exfat.cpp \
Loop.cpp \
Devmapper.cpp \
ResponseCode.cpp \
diff --git a/Exfat.cpp b/Exfat.cpp
new file mode 100644
index 0000000..7252e6e
--- /dev/null
+++ b/Exfat.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+
+#include <linux/kdev_t.h>
+
+#define LOG_TAG "Vold"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "Exfat.h"
+
+static char EXFAT_FSCK[] = "/system/bin/fsck.exfat";
+static char EXFAT_MKFS[] = "/system/bin/mkfs.exfat";
+static char EXFAT_MOUNT[] = "/system/bin/mount.exfat";
+
+extern "C" int logwrap(int argc, const char **argv, int background);
+
+int Exfat::doMount(const char *fsPath, const char *mountPoint,
+ bool ro, bool remount, bool executable,
+ int ownerUid, int ownerGid, int permMask) {
+
+ int rc = -1;
+ char mountData[255];
+ const char *args[6];
+
+ if (access(EXFAT_MOUNT, X_OK)) {
+ SLOGE("Unable to mount, exFAT FUSE helper not found!");
+ return rc;
+ }
+
+ sprintf(mountData,
+ "noatime,nodev,nosuid,dirsync,uid=%d,gid=%d,fmask=%o,dmask=%o,%s,%s",
+ ownerUid, ownerGid, permMask, permMask,
+ (executable ? "exec" : "noexec"),
+ (ro ? "ro" : "rw"));
+
+ args[0] = EXFAT_MOUNT;
+ args[1] = "-o";
+ args[2] = mountData;
+ args[3] = fsPath;
+ args[4] = mountPoint;
+ args[5] = NULL;
+
+ SLOGW("Executing exFAT mount (%s) -> (%s)", fsPath, mountPoint);
+
+ rc = logwrap(5, args, 1);
+
+ if (rc && errno == EROFS) {
+ SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
+ strcat(mountData, ",ro");
+ rc = logwrap(5, args, 1);
+ }
+
+ return rc;
+}
+
+int Exfat::check(const char *fsPath) {
+
+ bool rw = true;
+ int rc = -1;
+
+ if (access(EXFAT_FSCK, X_OK)) {
+ SLOGW("Skipping fs checks, exfatfsck not found.\n");
+ return 0;
+ }
+
+ do {
+ const char *args[3];
+ args[0] = EXFAT_FSCK;
+ args[1] = fsPath;
+ args[2] = NULL;
+
+ rc = logwrap(3, args, 1);
+
+ switch(rc) {
+ case 0:
+ SLOGI("exFAT filesystem check completed OK.\n");
+ return 0;
+ case 1:
+ SLOGI("exFAT filesystem check completed, errors corrected OK.\n");
+ return 0;
+ case 2:
+ SLOGE("exFAT filesystem check completed, errors corrected, need reboot.\n");
+ return 0;
+ case 4:
+ SLOGE("exFAT filesystem errors left uncorrected.\n");
+ return 0;
+ case 8:
+ SLOGE("exfatfsck operational error.\n");
+ errno = EIO;
+ return -1;
+ default:
+ SLOGE("exFAT filesystem check failed (unknown exit code %d).\n", rc);
+ errno = EIO;
+ return -1;
+ }
+ } while (0);
+
+ return 0;
+}
+
+int Exfat::format(const char *fsPath) {
+
+ int fd;
+ const char *args[3];
+ int rc = -1;
+
+ if (access(EXFAT_MKFS, X_OK)) {
+ SLOGE("Unable to format, mkexfatfs not found.");
+ return -1;
+ }
+
+ args[0] = EXFAT_MKFS;
+ args[1] = fsPath;
+ args[2] = NULL;
+
+ rc = logwrap(3, args, 1);
+
+ if (rc == 0) {
+ SLOGI("Filesystem (exFAT) formatted OK");
+ return 0;
+ } else {
+ SLOGE("Format (exFAT) failed (unknown exit code %d)", rc);
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+}
diff --git a/Exfat.h b/Exfat.h
new file mode 100644
index 0000000..94c1d05
--- /dev/null
+++ b/Exfat.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _EXFAT_H
+#define _EXFAT_H
+
+#include <unistd.h>
+
+class Exfat {
+public:
+ static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
+ bool executable, int ownerUid, int ownerGid, int permMask);
+ static int check(const char *fsPath);
+ static int format(const char *fsPath);
+};
+
+#endif
diff --git a/Volume.cpp b/Volume.cpp
index f651277..c175f93 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -48,6 +48,7 @@
#include "Ext4.h"
#include "Fat.h"
#include "Ntfs.h"
+#include "Exfat.h"
#include "Process.h"
#include "cryptfs.h"
@@ -537,6 +538,23 @@ int Volume::mountVol() {
continue;
}
+ } else if (strcmp(fstype, "exfat") == 0) {
+
+ if (Exfat::check(devicePath)) {
+ errno = EIO;
+ /* Badness - abort the mount */
+ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
+ setState(Volume::State_Idle);
+ free(fstype);
+ return -1;
+ }
+
+ if (Exfat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
+ AID_SYSTEM, gid, 0702)) {
+ SLOGE("%s failed to mount via EXFAT (%s)\n", devicePath, strerror(errno));
+ continue;
+ }
+
} else {
// Unsupported filesystem
errno = ENODATA;