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 <stdlib.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <errno.h> 22 #include <string.h> 23 #include <dirent.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <sys/mman.h> 31 #include <sys/mount.h> 32 33 #include <linux/kdev_t.h> 34 #include <linux/fs.h> 35 36 #define LOG_TAG "Vold" 37 38 #include <cutils/log.h> 39 #include <cutils/properties.h> 40 41 #include "Fat.h" 42 43 static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; 44 static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; 45 extern "C" int logwrap(int argc, const char **argv, int background); 46 extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); 47 48 int Fat::check(const char *fsPath) { 49 bool rw = true; 50 if (access(FSCK_MSDOS_PATH, X_OK)) { 51 SLOGW("Skipping fs checks\n"); 52 return 0; 53 } 54 55 int pass = 1; 56 int rc = 0; 57 do { 58 const char *args[5]; 59 args[0] = FSCK_MSDOS_PATH; 60 args[1] = "-p"; 61 args[2] = "-f"; 62 args[3] = fsPath; 63 args[4] = NULL; 64 65 rc = logwrap(4, args, 1); 66 67 switch(rc) { 68 case 0: 69 SLOGI("Filesystem check completed OK"); 70 return 0; 71 72 case 2: 73 SLOGE("Filesystem check failed (not a FAT filesystem)"); 74 errno = ENODATA; 75 return -1; 76 77 case 4: 78 if (pass++ <= 3) { 79 SLOGW("Filesystem modified - rechecking (pass %d)", 80 pass); 81 continue; 82 } 83 SLOGE("Failing check after too many rechecks"); 84 errno = EIO; 85 return -1; 86 87 default: 88 SLOGE("Filesystem check failed (unknown exit code %d)", rc); 89 errno = EIO; 90 return -1; 91 } 92 } while (0); 93 94 return 0; 95 } 96 97 int Fat::doMount(const char *fsPath, const char *mountPoint, 98 bool ro, bool remount, bool executable, 99 int ownerUid, int ownerGid, int permMask, bool createLost) { 100 int rc; 101 unsigned long flags; 102 char mountData[255]; 103 104 flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; 105 106 flags |= (executable ? 0 : MS_NOEXEC); 107 flags |= (ro ? MS_RDONLY : 0); 108 flags |= (remount ? MS_REMOUNT : 0); 109 110 /* 111 * Note: This is a temporary hack. If the sampling profiler is enabled, 112 * we make the SD card world-writable so any process can write snapshots. 113 * 114 * TODO: Remove this code once we have a drop box in system_server. 115 */ 116 char value[PROPERTY_VALUE_MAX]; 117 property_get("persist.sampling_profiler", value, ""); 118 if (value[0] == '1') { 119 SLOGW("The SD card is world-writable because the" 120 " 'persist.sampling_profiler' system property is set to '1'."); 121 permMask = 0; 122 } 123 124 sprintf(mountData, 125 "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", 126 ownerUid, ownerGid, permMask, permMask); 127 128 rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 129 130 if (rc && errno == EROFS) { 131 SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 132 flags |= MS_RDONLY; 133 rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 134 } 135 136 if (rc == 0 && createLost) { 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 SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); 146 } 147 } 148 free(lost_path); 149 } 150 151 return rc; 152 } 153 154 int Fat::format(const char *fsPath, unsigned int numSectors) { 155 int fd; 156 const char *args[11]; 157 int rc; 158 159 args[0] = MKDOSFS_PATH; 160 args[1] = "-F"; 161 args[2] = "32"; 162 args[3] = "-O"; 163 args[4] = "android"; 164 args[5] = "-c"; 165 args[6] = "8"; 166 167 if (numSectors) { 168 char tmp[32]; 169 snprintf(tmp, sizeof(tmp), "%u", numSectors); 170 const char *size = tmp; 171 args[7] = "-s"; 172 args[8] = size; 173 args[9] = fsPath; 174 args[10] = NULL; 175 rc = logwrap(11, args, 1); 176 } else { 177 args[7] = fsPath; 178 args[8] = NULL; 179 rc = logwrap(9, args, 1); 180 } 181 182 if (rc == 0) { 183 SLOGI("Filesystem formatted OK"); 184 return 0; 185 } else { 186 SLOGE("Format failed (unknown exit code %d)", rc); 187 errno = EIO; 188 return -1; 189 } 190 return 0; 191 } 192