Fat.cpp revision 8d934caeae971d7d08ca33e98dae294eb57c402d
1bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat/* 2bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Copyright (C) 2008 The Android Open Source Project 3bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 4bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * you may not use this file except in compliance with the License. 6bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * You may obtain a copy of the License at 7bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 8bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 10bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Unless required by applicable law or agreed to in writing, software 11bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * See the License for the specific language governing permissions and 14bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * limitations under the License. 15bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat */ 16bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 17bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <stdio.h> 18bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <fcntl.h> 19bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <unistd.h> 20bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <errno.h> 21bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <string.h> 22bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <dirent.h> 23bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <errno.h> 24bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <fcntl.h> 25bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 26bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <sys/types.h> 27bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <sys/stat.h> 28bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <sys/types.h> 29bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <sys/mman.h> 30bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <sys/mount.h> 31bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 32bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <linux/kdev_t.h> 33bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 34bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#define LOG_TAG "Vold" 35bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 36bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <cutils/log.h> 37bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include <cutils/properties.h> 38bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 39bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include "Fat.h" 40bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 41bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatstatic char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; 42bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatstatic char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; 43bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatextern "C" int logwrap(int argc, const char **argv, int background); 44bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatextern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); 45bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 46bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatint Fat::check(const char *fsPath) { 47bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat bool rw = true; 48bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (access(FSCK_MSDOS_PATH, X_OK)) { 49bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGW("Skipping fs checks\n"); 50bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 51bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 52bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 53bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int pass = 1; 54bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int rc = 0; 55bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat do { 56bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat const char *args[5]; 57bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[0] = FSCK_MSDOS_PATH; 58bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[1] = "-p"; 59bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[2] = "-f"; 60bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[3] = fsPath; 61bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[4] = NULL; 62bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 63bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = logwrap(4, args, 1); 64bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 65bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat switch(rc) { 66bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat case 0: 67bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGI("Filesystem check completed OK"); 68bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 69bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 70bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat case 2: 71bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Filesystem check failed (not a FAT filesystem)"); 72bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = ENODATA; 73bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 74bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 75bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat case 4: 76bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (pass++ <= 3) { 77bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGW("Filesystem modified - rechecking (pass %d)", 78bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat pass); 79bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat continue; 80bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 81bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Failing check after too many rechecks"); 82bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = EIO; 83bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 84bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 85bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat default: 86bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Filesystem check failed (unknown exit code %d)", rc); 87bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = EIO; 88bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 89bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 90bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } while (0); 91bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 92bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 93bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat} 94bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 95fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehatint Fat::doMount(const char *fsPath, const char *mountPoint, 96fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat bool ro, bool remount, int ownerUid, int ownerGid, 97fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat int permMask, bool createLost) { 98bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int rc; 99bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat unsigned long flags; 100fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat char mountData[255]; 101bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 102bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; 103bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 104a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat flags |= (ro ? MS_RDONLY : 0); 105a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat flags |= (remount ? MS_REMOUNT : 0); 106a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 107bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat /* 108bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Note: This is a temporary hack. If the sampling profiler is enabled, 109bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * we make the SD card world-writable so any process can write snapshots. 110bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 111bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * TODO: Remove this code once we have a drop box in system_server. 112bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat */ 113bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat char value[PROPERTY_VALUE_MAX]; 114bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat property_get("persist.sampling_profiler", value, ""); 115bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (value[0] == '1') { 116bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGW("The SD card is world-writable because the" 117bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat " 'persist.sampling_profiler' system property is set to '1'."); 118fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat permMask = 0; 119bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 120bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 121fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat sprintf(mountData, 122fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", 123fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat ownerUid, ownerGid, permMask, permMask); 124fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat 125fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 126fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat 127bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc && errno == EROFS) { 128bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 129bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat flags |= MS_RDONLY; 130fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat rc = mount(fsPath, mountPoint, "vfat", flags, mountData); 131bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 132bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 133fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat if (rc == 0 && createLost) { 134bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat char *lost_path; 135bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat asprintf(&lost_path, "%s/LOST.DIR", mountPoint); 136bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (access(lost_path, F_OK)) { 137bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat /* 138bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Create a LOST.DIR in the root so we have somewhere to put 139bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * lost cluster chains (fsck_msdos doesn't currently do this) 140bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat */ 141bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (mkdir(lost_path, 0755)) { 142bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); 143bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 144bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 145bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat free(lost_path); 146bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 147bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 148bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return rc; 149bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat} 150bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 151bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatint Fat::format(const char *fsPath) { 152bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat unsigned int nr_sec; 153bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int fd; 154bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 155bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if ((fd = open(fsPath, O_RDWR)) < 0) { 156bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Error opening disk file (%s)", strerror(errno)); 157bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 158bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 159bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 160bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (ioctl(fd, BLKGETSIZE, &nr_sec)) { 161bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Unable to get device size (%s)", strerror(errno)); 162bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat close(fd); 163bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 164bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 165bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat close(fd); 166bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 167bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat const char *args[7]; 168bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int rc; 169bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[0] = MKDOSFS_PATH; 170bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[1] = "-F"; 1718d934caeae971d7d08ca33e98dae294eb57c402dSan Mehat args[2] = "32"; 172bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[3] = "-O"; 173bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[4] = "android"; 174bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[5] = fsPath; 175bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[6] = NULL; 176bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = logwrap(7, args, 1); 177bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 178bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc == 0) { 179bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGI("Filesystem formatted OK"); 180bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 181bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } else { 182bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Format failed (unknown exit code %d)", rc); 183bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = EIO; 184bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 185bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 186bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 187bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat} 188