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