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