diff options
author | Steve Kondik <shade@chemlab.org> | 2013-07-06 04:00:54 -0700 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2013-07-07 12:27:47 -0700 |
commit | ce6e95e153201be046736e2360f51d3bca48c9f4 (patch) | |
tree | 3dab5e2b68fe7587ca02e05c8ee51b1ea0ba7752 | |
parent | e336c0ca31f2768661063220e2a1cb83fd55b92d (diff) | |
download | system_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.mk | 1 | ||||
-rw-r--r-- | Exfat.cpp | 160 | ||||
-rw-r--r-- | Exfat.h | 30 | ||||
-rw-r--r-- | Volume.cpp | 18 |
4 files changed, 209 insertions, 0 deletions
@@ -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; +} @@ -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 @@ -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; |