fs_mgr.c revision 5dc5bfefa078f2aded34f85db4613ba91ad49b76
1c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/*
2c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * Copyright (C) 2012 The Android Open Source Project
3c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *
4c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * Licensed under the Apache License, Version 2.0 (the "License");
5c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * you may not use this file except in compliance with the License.
6c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * You may obtain a copy of the License at
7c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *
8c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *      http://www.apache.org/licenses/LICENSE-2.0
9c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *
10c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * Unless required by applicable law or agreed to in writing, software
11c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * distributed under the License is distributed on an "AS IS" BASIS,
12c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * See the License for the specific language governing permissions and
14c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * limitations under the License.
15c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
16c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
17c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/* TO DO:
18c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *   1. Re-direct fsck output to the kernel log?
19c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *
20c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
21c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
22c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <stdio.h>
23c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <stdlib.h>
24c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <string.h>
25c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <unistd.h>
26c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <fcntl.h>
27c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <ctype.h>
28c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <sys/mount.h>
29c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <sys/stat.h>
30c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <errno.h>
31c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <sys/types.h>
32c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <sys/wait.h>
33c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <libgen.h>
34c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <time.h>
35c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
36c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <private/android_filesystem_config.h>
37c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <cutils/partition_utils.h>
38c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include <cutils/properties.h>
39c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
40c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#include "fs_mgr_priv.h"
41c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
42c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
43c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#define KEY_IN_FOOTER  "footer"
44c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
45c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#define E2FSCK_BIN      "/system/bin/e2fsck"
46c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
47c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstruct flag_list {
48c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    const char *name;
49c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    unsigned flag;
50c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall};
51c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
52c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic struct flag_list mount_flags[] = {
53c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "noatime",    MS_NOATIME },
54c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "noexec",     MS_NOEXEC },
55c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "nosuid",     MS_NOSUID },
56c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "nodev",      MS_NODEV },
57c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "nodiratime", MS_NODIRATIME },
58c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "ro",         MS_RDONLY },
59c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "rw",         0 },
60c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "remount",    MS_REMOUNT },
61c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "defaults",   0 },
62c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { 0,            0 },
63c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall};
64c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
65c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic struct flag_list fs_mgr_flags[] = {
66c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "wait",        MF_WAIT },
67c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "check",       MF_CHECK },
68c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "encryptable=",MF_CRYPT },
69c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { "defaults",    0 },
70c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    { 0,             0 },
71c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall};
72c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
73c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/*
74c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * gettime() - returns the time in seconds of the system's monotonic clock or
75c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * zero on error.
76c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
77c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic time_t gettime(void)
78c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
79c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct timespec ts;
80c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret;
81c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
82c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
83c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (ret < 0) {
84c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
85c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return 0;
86c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
87c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
88c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ts.tv_sec;
89c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
90c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
91c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic int wait_for_file(const char *filename, int timeout)
92c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
93c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct stat info;
94c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    time_t timeout_time = gettime() + timeout;
95c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret = -1;
96c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
97c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0))
98c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        usleep(10000);
99c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
100c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ret;
101c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
102c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
103c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
104c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                       char *fs_options, int fs_options_len)
105c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
106c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int f = 0;
107c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i;
108c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *p;
109c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *savep;
110c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
111c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* initialize key_loc to null, if we find an MF_CRYPT flag,
112c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall     * then we'll set key_loc to the proper value */
113c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (key_loc) {
114c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        *key_loc = NULL;
115c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
116c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* initialize fs_options to the null string */
117c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (fs_options && (fs_options_len > 0)) {
118c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fs_options[0] = '\0';
119c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
120c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
121c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    p = strtok_r(flags, ",", &savep);
122c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (p) {
123c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* Look for the flag "p" in the flag list "fl"
124c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         * If not found, the loop exits with fl[i].name being null.
125c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         */
126c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        for (i = 0; fl[i].name; i++) {
127c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
128c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                f |= fl[i].flag;
129c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                if ((fl[i].flag == MF_CRYPT) && key_loc) {
130c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                    /* The encryptable flag is followed by an = and the
131c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                     * location of the keys.  Get it and return it.
132c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                     */
133c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                    *key_loc = strdup(strchr(p, '=') + 1);
134c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                }
135c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                break;
136c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            }
137c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
138c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
139c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!fl[i].name) {
140c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            if (fs_options) {
141c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                /* It's not a known flag, so it must be a filesystem specific
142c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                 * option.  Add it to fs_options if it was passed in.
143c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                 */
144c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                strlcat(fs_options, p, fs_options_len);
145c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                strlcat(fs_options, ",", fs_options_len);
146c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            } else {
147c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                /* fs_options was not passed in, so if the flag is unknown
148c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                 * it's an error.
149c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                 */
150c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                ERROR("Warning: unknown flag %s\n", p);
151c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            }
152c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
153c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        p = strtok_r(NULL, ",", &savep);
154c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
155c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
156c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallout:
157c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (fs_options && fs_options[0]) {
158c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* remove the last trailing comma from the list of options */
159c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fs_options[strlen(fs_options) - 1] = '\0';
160c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
161c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
162c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return f;
163c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
164c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
165c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/* Read a line of text till the next newline character.
166c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * If no newline is found before the buffer is full, continue reading till a new line is seen,
167c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * then return an empty buffer.  This effectively ignores lines that are too long.
168c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * On EOF, return null.
169c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
170c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic char *getline(char *buf, int size, FILE *file)
171c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
172c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int cnt = 0;
173c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int eof = 0;
174c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int eol = 0;
175c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int c;
176c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
177c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (size < 1) {
178c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return NULL;
179c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
180c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
181c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (cnt < (size - 1)) {
182c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        c = getc(file);
183c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (c == EOF) {
184c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            eof = 1;
185c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            break;
186c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
187c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
188c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        *(buf + cnt) = c;
189c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        cnt++;
190c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
191c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (c == '\n') {
192c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            eol = 1;
193c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            break;
194c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
195c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
196c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
197c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Null terminate what we've read */
198c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    *(buf + cnt) = '\0';
199c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
200c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (eof) {
201c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (cnt) {
202c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return buf;
203c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
204c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return NULL;
205c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
206c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    } else if (eol) {
207c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return buf;
208c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    } else {
209c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* The line is too long.  Read till a newline or EOF.
210c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         * If EOF, return null, if newline, return an empty buffer.
211c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         */
212c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        while(1) {
213c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            c = getc(file);
214c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            if (c == EOF) {
215c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                return NULL;
216c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            } else if (c == '\n') {
217c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                *buf = '\0';
218c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                return buf;
219c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            }
220c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
221c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
222c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
223c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
224c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic struct fstab_rec *read_fstab(char *fstab_path)
225c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
226c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    FILE *fstab_file;
227c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int cnt, entries;
228c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int len;
229c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char line[256];
230c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    const char *delim = " \t";
231c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *save_ptr, *p;
232c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct fstab_rec *fstab;
233c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *key_loc;
234c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall#define FS_OPTIONS_LEN 1024
235c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char tmp_fs_options[FS_OPTIONS_LEN];
236c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
237c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    fstab_file = fopen(fstab_path, "r");
238c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!fstab_file) {
239c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ERROR("Cannot open file %s\n", fstab_path);
240c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return 0;
241c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
242c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
243c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    entries = 0;
244c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (getline(line, sizeof(line), fstab_file)) {
245c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* if the last character is a newline, shorten the string by 1 byte */
246c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        len = strlen(line);
247c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (line[len - 1] == '\n') {
248c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            line[len - 1] = '\0';
249c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
250c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* Skip any leading whitespace */
251c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        p = line;
252c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        while (isspace(*p)) {
253c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            p++;
254c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
255c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* ignore comments or empty lines */
256c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (*p == '#' || *p == '\0')
257c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            continue;
258c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        entries++;
259c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
260c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
261c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!entries) {
262c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ERROR("No entries found in fstab\n");
263c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return 0;
264c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
265c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
266c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    fstab = calloc(entries + 1, sizeof(struct fstab_rec));
267c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
268c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    fseek(fstab_file, 0, SEEK_SET);
269c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
270c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    cnt = 0;
271c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (getline(line, sizeof(line), fstab_file)) {
272c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* if the last character is a newline, shorten the string by 1 byte */
273c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        len = strlen(line);
274c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (line[len - 1] == '\n') {
275c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            line[len - 1] = '\0';
276c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
277c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
278c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* Skip any leading whitespace */
279c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        p = line;
280c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        while (isspace(*p)) {
281c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            p++;
282c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
283c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* ignore comments or empty lines */
284c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (*p == '#' || *p == '\0')
285c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            continue;
286c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
287c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* If a non-comment entry is greater than the size we allocated, give an
288c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         * error and quit.  This can happen in the unlikely case the file changes
289c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         * between the two reads.
290c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall         */
291c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (cnt >= entries) {
292c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Tried to process more entries than counted\n");
293c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            break;
294c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
295c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
296c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(p = strtok_r(line, delim, &save_ptr))) {
297c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Error parsing mount source\n");
298c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return 0;
299c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
300c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].blk_dev = strdup(p);
301c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
302c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
303c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Error parsing mnt_point\n");
304c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return 0;
305c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
306c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].mnt_point = strdup(p);
307c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
308c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
309c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Error parsing fs_type\n");
310c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return 0;
311c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
312c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].type = strdup(p);
313c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
314c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
315c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Error parsing mount_flags\n");
316c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return 0;
317c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
318c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        tmp_fs_options[0] = '\0';
319c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN);
320c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
321c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* fs_options are optional */
322c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (tmp_fs_options[0]) {
323c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            fstab[cnt].fs_options = strdup(tmp_fs_options);
324c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
325c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            fstab[cnt].fs_options = NULL;
326c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
327c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
328c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
329c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Error parsing fs_mgr_options\n");
330c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            return 0;
331c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
332c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0);
333c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        fstab[cnt].key_loc = key_loc;
334c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
335c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        cnt++;
336c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
337c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    fclose(fstab_file);
338c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
339c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return fstab;
340c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
341c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
342c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic void free_fstab(struct fstab_rec *fstab)
343c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
344c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i = 0;
345c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
346c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (fstab[i].blk_dev) {
347c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* Free the pointers return by strdup(3) */
348c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        free(fstab[i].blk_dev);
349c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        free(fstab[i].mnt_point);
350c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        free(fstab[i].type);
351c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        free(fstab[i].fs_options);
352c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        free(fstab[i].key_loc);
353c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
354c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        i++;
355c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
356c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
357c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Free the actual fstab array created by calloc(3) */
358c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free(fstab);
359c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
360c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
3615dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrallstatic void check_fs(char *blk_dev, char *type, char *target)
362c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
363c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    pid_t pid;
364c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int status;
3655dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall    int ret;
3665dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
3675dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall    char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
368c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
369c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Check for the types of filesystems we know how to check */
370c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) {
3715dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall        /*
3725dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * First try to mount and unmount the filesystem.  We do this because
3735dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * the kernel is more efficient than e2fsck in running the journal and
3745dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * processing orphaned inodes, and on at least one device with a
3755dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
3765dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * to do what the kernel does in about a second.
3775dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         *
3785dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * After mounting and unmounting the filesystem, run e2fsck, and if an
3795dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * error is recorded in the filesystem superblock, e2fsck will do a full
3805dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * check.  Otherwise, it does nothing.  If the kernel cannot mount the
3815dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * filesytsem due to an error, e2fsck is still run to do a full check
3825dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         * fix the filesystem.
3835dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall         */
3845dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall        ret = mount(blk_dev, target, type, tmpmnt_flags, tmpmnt_opts);
3855dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall        if (! ret) {
3865dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall            umount(target);
3875dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall        }
3885dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall
389c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev);
390c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        pid = fork();
391c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (pid > 0) {
392c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* Parent, wait for the child to return */
393c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            waitpid(pid, &status, 0);
394c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else if (pid == 0) {
395c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* child, run checker */
396c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL);
397c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
398c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* Only gets here on error */
399c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN);
400c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
401c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* No need to check for error in fork, we can't really handle it now */
402c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Fork failed trying to run %s\n", E2FSCK_BIN);
403c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
404c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
405c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
406c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return;
407c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
408c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
409c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic void remove_trailing_slashes(char *n)
410c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
411c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int len;
412c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
413c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    len = strlen(n) - 1;
414c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while ((*(n + len) == '/') && len) {
415c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall      *(n + len) = '\0';
416c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall      len--;
417c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
418c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
419c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
420c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallstatic int fs_match(char *in1, char *in2)
421c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
422c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *n1;
423c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *n2;
424c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret;
425c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
426c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    n1 = strdup(in1);
427c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    n2 = strdup(in2);
428c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
429c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    remove_trailing_slashes(n1);
430c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    remove_trailing_slashes(n2);
431c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
432c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    ret = !strcmp(n1, n2);
433c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
434c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free(n1);
435c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free(n2);
436c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
437c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ret;
438c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
439c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
440c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallint fs_mgr_mount_all(char *fstab_file)
441c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
442c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i = 0;
443c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int encrypted = 0;
444c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret = -1;
445c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int mret;
446c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct fstab_rec *fstab = 0;
447c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
448c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!(fstab = read_fstab(fstab_file))) {
449c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return ret;
450c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
451c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
452c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    for (i = 0; fstab[i].blk_dev; i++) {
453c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (fstab[i].fs_mgr_flags & MF_WAIT) {
454c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
455c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
456c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
457c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (fstab[i].fs_mgr_flags & MF_CHECK) {
4585dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall            check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point);
459c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
460c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
461c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type,
462c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                     fstab[i].flags, fstab[i].fs_options);
463c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!mret) {
464c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* Success!  Go get the next one */
465c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            continue;
466c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
467c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
468c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* mount(2) returned an error, check if it's encrypted and deal with it */
469c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) {
470c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            /* Need to mount a tmpfs at this mountpoint for now, and set
471c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall             * properties that vold will query later for decrypting
472c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall             */
473c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            if (mount("tmpfs", fstab[i].mnt_point, "tmpfs",
474c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                  MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
475c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n",
476c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                        fstab[i].mnt_point);
477c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                goto out;
478c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            }
479c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            encrypted = 1;
480c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
481c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Cannot mount filesystem on %s at %s\n",
482c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                    fstab[i].blk_dev, fstab[i].mnt_point);
483c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            goto out;
484c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
485c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
486c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
487c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (encrypted) {
488c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ret = 1;
489c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    } else {
490c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ret = 0;
491c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
492c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
493c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallout:
494c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free_fstab(fstab);
495c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ret;
496c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
497c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
498c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/* If tmp_mnt_point is non-null, mount the filesystem there.  This is for the
499c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * tmp mount we do to check the user password
500c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
501c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallint fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point)
502c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
503c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i = 0;
504c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret = -1;
505c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct fstab_rec *fstab = 0;
506c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    char *m;
507c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
508c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!(fstab = read_fstab(fstab_file))) {
509c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return ret;
510c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
511c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
512c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    for (i = 0; fstab[i].blk_dev; i++) {
513c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!fs_match(fstab[i].mnt_point, n_name)) {
514c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            continue;
515c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
516c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
517c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* We found our match */
518c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* First check the filesystem if requested */
519c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (fstab[i].fs_mgr_flags & MF_WAIT) {
520c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
521c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
522c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
523c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (fstab[i].fs_mgr_flags & MF_CHECK) {
5245dc5bfefa078f2aded34f85db4613ba91ad49b76Ken Sumrall            check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point);
525c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
526c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
527c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* Now mount it where requested */
528c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (tmp_mnt_point) {
529c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            m = tmp_mnt_point;
530c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
531c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            m = fstab[i].mnt_point;
532c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
533c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (mount(n_blk_dev, m, fstab[i].type,
534c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                  fstab[i].flags, fstab[i].fs_options)) {
535c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Cannot mount filesystem on %s at %s\n",
536c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                    n_blk_dev, m);
537c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            goto out;
538c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        } else {
539c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ret = 0;
540c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            goto out;
541c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
542c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
543c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
544c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* We didn't find a match, say so and return an error */
545c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point);
546c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
547c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallout:
548c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free_fstab(fstab);
549c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ret;
550c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
551c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
552c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/*
553c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * mount a tmpfs filesystem at the given point.
554c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * return 0 on success, non-zero on failure.
555c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
556c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallint fs_mgr_do_tmpfs_mount(char *n_name)
557c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
558c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret;
559c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
560c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    ret = mount("tmpfs", n_name, "tmpfs",
561c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall                MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS);
562c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (ret < 0) {
563c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        ERROR("Cannot mount tmpfs filesystem at %s\n", n_name);
564c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return -1;
565c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
566c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
567c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Success */
568c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return 0;
569c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
570c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
571c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallint fs_mgr_unmount_all(char *fstab_file)
572c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
573c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i = 0;
574c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int ret = 0;
575c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct fstab_rec *fstab = 0;
576c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
577c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!(fstab = read_fstab(fstab_file))) {
578c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return -1;
579c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
580c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
581c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    while (fstab[i].blk_dev) {
582c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (umount(fstab[i].mnt_point)) {
583c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point);
584c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            ret = -1;
585c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
586c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        i++;
587c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
588c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
589c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free_fstab(fstab);
590c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return ret;
591c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
592c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall/*
593c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * key_loc must be at least PROPERTY_VALUE_MAX bytes long
594c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall *
595c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall * real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long
596c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall */
597c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrallint fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size)
598c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall{
599c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    int i = 0;
600c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    struct fstab_rec *fstab = 0;
601c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
602c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (!(fstab = read_fstab(fstab_file))) {
603c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        return -1;
604c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
605c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Initialize return values to null strings */
606c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (key_loc) {
607c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        *key_loc = '\0';
608c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
609c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    if (real_blk_dev) {
610c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        *real_blk_dev = '\0';
611c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
612c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
613c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    /* Look for the encryptable partition to find the data */
614c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    for (i = 0; fstab[i].blk_dev; i++) {
615c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) {
616c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            continue;
617c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
618c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
619c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        /* We found a match */
620c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (key_loc) {
621c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            strlcpy(key_loc, fstab[i].key_loc, size);
622c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
623c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        if (real_blk_dev) {
624c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall            strlcpy(real_blk_dev, fstab[i].blk_dev, size);
625c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        }
626c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall        break;
627c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    }
628c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
629c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    free_fstab(fstab);
630c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall    return 0;
631c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall}
632c1bf89663ca71949b508007d4df2b5b06038f96dKen Sumrall
633