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