Fat.cpp revision fcf24fe62f98c5d44431aa575555569c2c7a29b0
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, 96 bool ro, bool remount, int ownerUid, int ownerGid, 97 int permMask, bool createLost) { 98 int rc; 99 unsigned long flags; 100 char mountData[255]; 101 102 flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; 103 104 flags |= (ro ? MS_RDONLY : 0); 105 flags |= (remount ? MS_REMOUNT : 0); 106 107 /* 108 * Note: This is a temporary hack. If the sampling profiler is enabled, 109 * we make the SD card world-writable so any process can write snapshots. 110 * 111 * TODO: Remove this code once we have a drop box in system_server. 112 */ 113 char value[PROPERTY_VALUE_MAX]; 114 property_get("persist.sampling_profiler", value, ""); 115 if (value[0] == '1') { 116 LOGW("The SD card is world-writable because the" 117 " 'persist.sampling_profiler' system property is set to '1'."); 118 permMask = 0; 119 } 120 121 sprintf(mountData, 122 "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", 123 ownerUid, ownerGid, permMask, permMask); 124 125 rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 126 127 if (rc && errno == EROFS) { 128 LOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 129 flags |= MS_RDONLY; 130 rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 131 } 132 133 if (rc == 0 && createLost) { 134 char *lost_path; 135 asprintf(&lost_path, "%s/LOST.DIR", mountPoint); 136 if (access(lost_path, F_OK)) { 137 /* 138 * Create a LOST.DIR in the root so we have somewhere to put 139 * lost cluster chains (fsck_msdos doesn't currently do this) 140 */ 141 if (mkdir(lost_path, 0755)) { 142 LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); 143 } 144 } 145 free(lost_path); 146 } 147 148 return rc; 149} 150 151int Fat::format(const char *fsPath, unsigned int numSectors) { 152 int fd; 153 const char *args[11]; 154 int rc; 155 156 args[0] = MKDOSFS_PATH; 157 args[1] = "-F"; 158 args[2] = "32"; 159 args[3] = "-O"; 160 args[4] = "android"; 161 args[5] = "-c"; 162 args[6] = "8"; 163 164 if (numSectors) { 165 char tmp[32]; 166 snprintf(tmp, sizeof(tmp), "%u", numSectors); 167 const char *size = tmp; 168 args[7] = "-s"; 169 args[8] = size; 170 args[9] = fsPath; 171 args[10] = NULL; 172 rc = logwrap(11, args, 1); 173 } else { 174 args[7] = fsPath; 175 args[8] = NULL; 176 rc = logwrap(9, args, 1); 177 } 178 179 if (rc == 0) { 180 LOGI("Filesystem formatted OK"); 181 return 0; 182 } else { 183 LOGE("Format failed (unknown exit code %d)", rc); 184 errno = EIO; 185 return -1; 186 } 187 return 0; 188} 189