Fat.cpp revision a19b250bd273455933ca3502cf2c2e0a803aff77
1/* 2 * Copyright (C) 2008 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#include <stdio.h> 18#include <fcntl.h> 19#include <unistd.h> 20#include <errno.h> 21#include <string.h> 22#include <dirent.h> 23#include <errno.h> 24#include <fcntl.h> 25 26#include <sys/types.h> 27#include <sys/stat.h> 28#include <sys/types.h> 29#include <sys/mman.h> 30#include <sys/mount.h> 31 32#include <linux/kdev_t.h> 33 34#define LOG_TAG "Vold" 35 36#include <cutils/log.h> 37#include <cutils/properties.h> 38 39#include "Fat.h" 40 41static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; 42static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; 43extern "C" int logwrap(int argc, const char **argv, int background); 44extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); 45 46int Fat::check(const char *fsPath) { 47 bool rw = true; 48 if (access(FSCK_MSDOS_PATH, X_OK)) { 49 LOGW("Skipping fs checks\n"); 50 return 0; 51 } 52 53 int pass = 1; 54 int rc = 0; 55 do { 56 const char *args[5]; 57 args[0] = FSCK_MSDOS_PATH; 58 args[1] = "-p"; 59 args[2] = "-f"; 60 args[3] = fsPath; 61 args[4] = NULL; 62 63 rc = logwrap(4, args, 1); 64 65 switch(rc) { 66 case 0: 67 LOGI("Filesystem check completed OK"); 68 return 0; 69 70 case 2: 71 LOGE("Filesystem check failed (not a FAT filesystem)"); 72 errno = ENODATA; 73 return -1; 74 75 case 4: 76 if (pass++ <= 3) { 77 LOGW("Filesystem modified - rechecking (pass %d)", 78 pass); 79 continue; 80 } 81 LOGE("Failing check after too many rechecks"); 82 errno = EIO; 83 return -1; 84 85 default: 86 LOGE("Filesystem check failed (unknown exit code %d)", rc); 87 errno = EIO; 88 return -1; 89 } 90 } while (0); 91 92 return 0; 93} 94 95int Fat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount) { 96 int rc; 97 unsigned long flags; 98 99 flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; 100 101 flags |= (ro ? MS_RDONLY : 0); 102 flags |= (remount ? MS_REMOUNT : 0); 103 104 /* 105 * Note: This is a temporary hack. If the sampling profiler is enabled, 106 * we make the SD card world-writable so any process can write snapshots. 107 * 108 * TODO: Remove this code once we have a drop box in system_server. 109 */ 110 char value[PROPERTY_VALUE_MAX]; 111 property_get("persist.sampling_profiler", value, ""); 112 if (value[0] == '1') { 113 LOGW("The SD card is world-writable because the" 114 " 'persist.sampling_profiler' system property is set to '1'."); 115 rc = mount(fsPath, mountPoint, (const char *) "vfat", (unsigned long) flags, 116 (const void *) "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed"); 117 } else { 118 /* 119 * The mount masks restrict access so that: 120 * 1. The 'system' user cannot access the SD card at all - 121 * (protects system_server from grabbing file references) 122 * 2. Group users can RWX 123 * 3. Others can only RX 124 */ 125 rc = mount(fsPath, mountPoint, "vfat", flags, 126 "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); 127 } 128 129 if (rc && errno == EROFS) { 130 LOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 131 flags |= MS_RDONLY; 132 rc = mount(fsPath, mountPoint, "vfat", flags, 133 "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); 134 } 135 136 if (rc == 0) { 137 char *lost_path; 138 asprintf(&lost_path, "%s/LOST.DIR", mountPoint); 139 if (access(lost_path, F_OK)) { 140 /* 141 * Create a LOST.DIR in the root so we have somewhere to put 142 * lost cluster chains (fsck_msdos doesn't currently do this) 143 */ 144 if (mkdir(lost_path, 0755)) { 145 LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); 146 } 147 } 148 free(lost_path); 149 } 150 151 return rc; 152} 153 154int Fat::format(const char *fsPath) { 155 unsigned int nr_sec; 156 int fd; 157 158 if ((fd = open(fsPath, O_RDWR)) < 0) { 159 LOGE("Error opening disk file (%s)", strerror(errno)); 160 return -1; 161 } 162 163 if (ioctl(fd, BLKGETSIZE, &nr_sec)) { 164 LOGE("Unable to get device size (%s)", strerror(errno)); 165 close(fd); 166 return -1; 167 } 168 close(fd); 169 170 const char *args[7]; 171 int rc; 172 args[0] = MKDOSFS_PATH; 173 args[1] = "-F"; 174 if ((nr_sec * 512) <= ((unsigned int) (1024*1024) * 32)) 175 args[2] = "12"; 176 else if ((nr_sec * 512) <= ((unsigned int) (1024*1024*1024) * 2)) 177 args[2] = "16"; 178 else 179 args[2] = "32"; 180 181 args[3] = "-O"; 182 args[4] = "android"; 183 args[5] = fsPath; 184 args[6] = NULL; 185 rc = logwrap(7, args, 1); 186 187 if (rc == 0) { 188 LOGI("Filesystem formatted OK"); 189 return 0; 190 } else { 191 LOGE("Format failed (unknown exit code %d)", rc); 192 errno = EIO; 193 return -1; 194 } 195 return 0; 196} 197