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