Fat.cpp revision fcf24fe62f98c5d44431aa575555569c2c7a29b0
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 151fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehatint Fat::format(const char *fsPath, unsigned int numSectors) { 152bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int fd; 153fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat const char *args[11]; 154bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat int rc; 155fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 156bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[0] = MKDOSFS_PATH; 157bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[1] = "-F"; 1588d934caeae971d7d08ca33e98dae294eb57c402dSan Mehat args[2] = "32"; 159bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[3] = "-O"; 160bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat args[4] = "android"; 161b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat args[5] = "-c"; 162b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat args[6] = "8"; 163fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 164fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat if (numSectors) { 165fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat char tmp[32]; 166fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat snprintf(tmp, sizeof(tmp), "%u", numSectors); 167fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat const char *size = tmp; 168fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[7] = "-s"; 169fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[8] = size; 170fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[9] = fsPath; 171fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[10] = NULL; 172fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat rc = logwrap(11, args, 1); 173fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } else { 174fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[7] = fsPath; 175fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat args[8] = NULL; 176fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat rc = logwrap(9, args, 1); 177fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } 178bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 179bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (rc == 0) { 180bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGI("Filesystem formatted OK"); 181bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 182bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } else { 183bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat LOGE("Format failed (unknown exit code %d)", rc); 184bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat errno = EIO; 185bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return -1; 186bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat } 187bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat return 0; 188bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat} 189