diff options
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | Fat.cpp | 191 | ||||
-rw-r--r-- | Fat.h | 29 | ||||
-rw-r--r-- | Volume.cpp | 166 | ||||
-rw-r--r-- | Volume.h | 3 |
5 files changed, 228 insertions, 164 deletions
@@ -21,7 +21,8 @@ LOCAL_SRC_FILES:= \ DirectVolume.cpp \ logwrapper.c \ ProcessKiller.c \ - geom_mbr_enc.c + geom_mbr_enc.c \ + Fat.cpp LOCAL_MODULE:= vold @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2008 The Android Open Source 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 <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 <linux/kdev_t.h> + +#define LOG_TAG "Vold" + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include "Fat.h" + +static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; +static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; +extern "C" int logwrap(int argc, const char **argv, int background); +extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); + +int Fat::check(const char *fsPath) { + bool rw = true; + if (access(FSCK_MSDOS_PATH, X_OK)) { + LOGW("Skipping fs checks\n"); + return 0; + } + + int pass = 1; + int rc = 0; + do { + const char *args[5]; + args[0] = FSCK_MSDOS_PATH; + args[1] = "-p"; + args[2] = "-f"; + args[3] = fsPath; + args[4] = NULL; + + rc = logwrap(4, args, 1); + + switch(rc) { + case 0: + LOGI("Filesystem check completed OK"); + return 0; + + case 2: + LOGE("Filesystem check failed (not a FAT filesystem)"); + errno = ENODATA; + return -1; + + case 4: + if (pass++ <= 3) { + LOGW("Filesystem modified - rechecking (pass %d)", + pass); + continue; + } + LOGE("Failing check after too many rechecks"); + errno = EIO; + return -1; + + default: + LOGE("Filesystem check failed (unknown exit code %d)", rc); + errno = EIO; + return -1; + } + } while (0); + + return 0; +} + +int Fat::doMount(const char *fsPath, const char *mountPoint) { + int rc; + unsigned long flags; + + flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; + + /* + * Note: This is a temporary hack. If the sampling profiler is enabled, + * we make the SD card world-writable so any process can write snapshots. + * + * TODO: Remove this code once we have a drop box in system_server. + */ + char value[PROPERTY_VALUE_MAX]; + property_get("persist.sampling_profiler", value, ""); + if (value[0] == '1') { + LOGW("The SD card is world-writable because the" + " 'persist.sampling_profiler' system property is set to '1'."); + rc = mount(fsPath, mountPoint, (const char *) "vfat", (unsigned long) flags, + (const void *) "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed"); + } else { + /* + * The mount masks restrict access so that: + * 1. The 'system' user cannot access the SD card at all - + * (protects system_server from grabbing file references) + * 2. Group users can RWX + * 3. Others can only RX + */ + rc = mount(fsPath, mountPoint, "vfat", flags, + "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); + } + + if (rc && errno == EROFS) { + LOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); + flags |= MS_RDONLY; + rc = mount(fsPath, mountPoint, "vfat", flags, + "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); + } + + if (rc == 0) { + char *lost_path; + asprintf(&lost_path, "%s/LOST.DIR", mountPoint); + if (access(lost_path, F_OK)) { + /* + * Create a LOST.DIR in the root so we have somewhere to put + * lost cluster chains (fsck_msdos doesn't currently do this) + */ + if (mkdir(lost_path, 0755)) { + LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); + } + } + free(lost_path); + } + + return rc; +} + +int Fat::format(const char *fsPath) { + unsigned int nr_sec; + int fd; + + if ((fd = open(fsPath, O_RDWR)) < 0) { + LOGE("Error opening disk file (%s)", strerror(errno)); + return -1; + } + + if (ioctl(fd, BLKGETSIZE, &nr_sec)) { + LOGE("Unable to get device size (%s)", strerror(errno)); + close(fd); + return -1; + } + close(fd); + + const char *args[7]; + int rc; + args[0] = MKDOSFS_PATH; + args[1] = "-F"; + if ((nr_sec * 512) <= ((unsigned int) (1024*1024*1024) * 2)) + args[2] = "16"; + else + args[2] = "32"; + + args[3] = "-O"; + args[4] = "android"; + args[5] = fsPath; + args[6] = NULL; + rc = logwrap(7, args, 1); + + if (rc == 0) { + LOGI("Filesystem formatted OK"); + return 0; + } else { + LOGE("Format failed (unknown exit code %d)", rc); + errno = EIO; + return -1; + } + return 0; +} @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2008 The Android Open Source 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 _FAT_H +#define _FAT_H + +#include <unistd.h> + +class Fat { +public: + static int check(const char *fsPath); + static int doMount(const char *fsPath, const char *mountPoint); + static int format(const char *fsPath); +}; + +#endif @@ -39,16 +39,12 @@ #include "Volume.h" #include "VolumeManager.h" #include "ResponseCode.h" +#include "Fat.h" -extern "C" int logwrap(int argc, const char **argv, int background); -extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); extern "C" void KillProcessesWithOpenFiles(const char *, int, int, int); extern "C" void dos_partition_dec(void const *pp, struct dos_partition *d); extern "C" void dos_partition_enc(void *pp, struct dos_partition *d); -static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; -static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; - static const char *stateToStr(int state) { if (state == Volume::State_Init) return "Initializing"; @@ -172,7 +168,7 @@ int Volume::formatVol() { LOGI("Volume %s (%s) being formatted", getLabel(), devicePath); - if (doFormatVfat(devicePath)) { + if (Fat::format(devicePath)) { LOGE("Failed to format (%s)", strerror(errno)); goto err; } @@ -250,7 +246,9 @@ int Volume::mountVol() { LOGI("%s being considered for volume %s\n", devicePath, getLabel()); errno = 0; - if ((rc = checkFilesystem(devicePath))) { + setState(Volume::State_Checking); + + if ((rc = Fat::check(devicePath))) { if (errno == ENODATA) { LOGW("%s does not contain a FAT filesystem\n", devicePath); continue; @@ -270,7 +268,7 @@ int Volume::mountVol() { LOGI("%s checks out - attempting to mount\n", devicePath); errno = 0; - if (!(rc = doMountVfat(devicePath, getMountpoint()))) { + if (!(rc = Fat::doMount(devicePath, getMountpoint()))) { LOGI("%s sucessfully mounted for volume %s\n", devicePath, getLabel()); setState(Volume::State_Mounted); @@ -299,116 +297,6 @@ out: return rc; } - -int Volume::doMountVfat(const char *deviceNode, const char *mountPoint) -{ - int rc; - unsigned long flags; - - flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; - - /* - * Note: This is a temporary hack. If the sampling profiler is enabled, - * we make the SD card world-writable so any process can write snapshots. - * - * TODO: Remove this code once we have a drop box in system_server. - */ - char value[PROPERTY_VALUE_MAX]; - property_get("persist.sampling_profiler", value, ""); - if (value[0] == '1') { - LOGW("The SD card is world-writable because the" - " 'persist.sampling_profiler' system property is set to '1'."); - rc = mount(deviceNode, mountPoint, (const char *) "vfat", (unsigned long) flags, - (const void *) "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed"); - } else { - /* - * The mount masks restrict access so that: - * 1. The 'system' user cannot access the SD card at all - - * (protects system_server from grabbing file references) - * 2. Group users can RWX - * 3. Others can only RX - */ - rc = mount(deviceNode, mountPoint, "vfat", flags, - "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); - } - - if (rc && errno == EROFS) { - LOGE("%s appears to be a read only filesystem - retrying mount RO", - deviceNode); - flags |= MS_RDONLY; - rc = mount(deviceNode, mountPoint, "vfat", flags, - "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); - } - - if (rc == 0) { - char *lost_path; - asprintf(&lost_path, "%s/LOST.DIR", mountPoint); - if (access(lost_path, F_OK)) { - /* - * Create a LOST.DIR in the root so we have somewhere to put - * lost cluster chains (fsck_msdos doesn't currently do this) - */ - if (mkdir(lost_path, 0755)) { - LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); - } - } - free(lost_path); - } - - return rc; -} - -int Volume::checkFilesystem(const char *nodepath) { - - bool rw = true; - if (access(FSCK_MSDOS_PATH, X_OK)) { - LOGW("Skipping fs checks\n"); - return 0; - } - - setState(Volume::State_Checking); - int pass = 1; - int rc = 0; - do { - const char *args[5]; - args[0] = FSCK_MSDOS_PATH; - args[1] = "-p"; - args[2] = "-f"; - args[3] = nodepath; - args[4] = NULL; - - rc = logwrap(4, args, 1); - - switch(rc) { - case 0: - LOGI("Filesystem check completed OK"); - return 0; - - case 2: - LOGE("Filesystem check failed (not a FAT filesystem)"); - errno = ENODATA; - return -1; - - case 4: - if (pass++ <= 3) { - LOGW("Filesystem modified - rechecking (pass %d)", - pass); - continue; - } - LOGE("Failing check after too many rechecks"); - errno = EIO; - return -1; - - default: - LOGE("Filesystem check failed (unknown exit code %d)", rc); - errno = EIO; - return -1; - } - } while (0); - - return 0; -} - int Volume::unmountVol() { int i, rc; @@ -497,45 +385,3 @@ int Volume::initializeMbr(const char *deviceNode) { close(fd); return 0; } - -int Volume::doFormatVfat(const char *deviceNode) { - unsigned int nr_sec; - int fd; - - if ((fd = open(deviceNode, O_RDWR)) < 0) { - LOGE("Error opening disk file (%s)", strerror(errno)); - return -1; - } - - if (ioctl(fd, BLKGETSIZE, &nr_sec)) { - LOGE("Unable to get device size (%s)", strerror(errno)); - close(fd); - return -1; - } - close(fd); - - const char *args[7]; - int rc; - args[0] = MKDOSFS_PATH; - args[1] = "-F"; - if ((nr_sec * 512) <= ((unsigned int) (1024*1024*1024) * 2)) - args[2] = "16"; - else - args[2] = "32"; - - args[3] = "-O"; - args[4] = "android"; - args[5] = deviceNode; - args[6] = NULL; - rc = logwrap(7, args, 1); - - if (rc == 0) { - LOGI("Filesystem formatted OK"); - return 0; - } else { - LOGE("Format failed (unknown exit code %d)", rc); - errno = EIO; - return -1; - } - return 0; -} @@ -73,9 +73,6 @@ protected: int createDeviceNode(const char *path, int major, int minor); private: - int checkFilesystem(const char *nodepath); - int doMountVfat(const char *deviceNode, const char *mountPoint); - int doFormatVfat(const char *deviceNode); int initializeMbr(const char *deviceNode); bool isMountpointMounted(const char *path); }; |