Fat.cpp revision bf04185c88161f13118b9975cdff7967d49a4fa0
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 95bf04185c88161f13118b9975cdff7967d49a4fa0San Mehatint Fat::doMount(const char *fsPath, const char *mountPoint) { 96bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int rc; 97bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat unsigned long flags; 98bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 99bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; 100bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 101bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat /* 102bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * Note: This is a temporary hack. If the sampling profiler is enabled, 103bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * we make the SD card world-writable so any process can write snapshots. 104bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 105bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * TODO: Remove this code once we have a drop box in system_server. 106bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat */ 107bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat char value[PROPERTY_VALUE_MAX]; 108bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat property_get("persist.sampling_profiler", value, ""); 109bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (value[0] == '1') { 110bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGW("The SD card is world-writable because the" 111bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat " 'persist.sampling_profiler' system property is set to '1'."); 112bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = mount(fsPath, mountPoint, (const char *) "vfat", (unsigned long) flags, 113bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat (const void *) "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed"); 114bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } else { 115bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat /* 116bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * The mount masks restrict access so that: 117bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 1. The 'system' user cannot access the SD card at all - 118bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * (protects system_server from grabbing file references) 119bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 2. Group users can RWX 120bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat * 3. Others can only RX 121bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat */ 122bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = mount(fsPath, mountPoint, "vfat", flags, 123bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); 124bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 125bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 126bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc && errno == EROFS) { 127bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 128bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat flags |= MS_RDONLY; 129bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = mount(fsPath, mountPoint, "vfat", flags, 130bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); 131bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 132bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 133bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc == 0) { 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"; 171bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if ((nr_sec * 512) <= ((unsigned int) (1024*1024*1024) * 2)) 172bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[2] = "16"; 173bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat else 174bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[2] = "32"; 175bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 176bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[3] = "-O"; 177bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[4] = "android"; 178bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[5] = fsPath; 179bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[6] = NULL; 180bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat rc = logwrap(7, args, 1); 181bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 182bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc == 0) { 183bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGI("Filesystem formatted OK"); 184bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 185bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } else { 186bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Format failed (unknown exit code %d)", rc); 187bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = EIO; 188bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 189bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 190bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 191bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat} 192