blob: e89c91c6a9fddfd3ceea36f9ba3f0a3ac10a1814 [file] [log] [blame]
Colin Cross5edee2a2014-01-23 14:22:48 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <ctype.h>
Sandeep Patilc20c0c22017-02-23 16:09:34 -080018#include <dirent.h>
Iliyan Malchev3ea902f2015-05-01 14:05:04 -070019#include <errno.h>
Colin Cross5edee2a2014-01-23 14:22:48 -080020#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/mount.h>
Iliyan Malchev3ea902f2015-05-01 14:05:04 -070024#include <unistd.h>
Colin Cross5edee2a2014-01-23 14:22:48 -080025
Bowgo Tsai80281892017-12-12 00:47:43 +080026#include <algorithm>
27#include <utility>
28#include <vector>
29
Sandeep Patilc20c0c22017-02-23 16:09:34 -080030#include <android-base/file.h>
31#include <android-base/stringprintf.h>
32#include <android-base/strings.h>
33
Colin Cross5edee2a2014-01-23 14:22:48 -080034#include "fs_mgr_priv.h"
35
Tom Marshall66f6a6d2018-03-06 16:19:18 +010036using android::base::StartsWith;
37
Yu Ningc01022a2017-07-26 17:54:08 +080038const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
39
Colin Cross5edee2a2014-01-23 14:22:48 -080040struct fs_mgr_flag_values {
41 char *key_loc;
Paul Lawrence9dbe97b2017-04-21 12:41:48 -070042 char* key_dir;
Sami Tolvanen946a0f32015-03-22 12:40:05 +000043 char *verity_loc;
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -080044 char *sysfs_path;
Colin Cross5edee2a2014-01-23 14:22:48 -080045 long long part_length;
46 char *label;
47 int partnum;
48 int swap_prio;
Peter Enderborg4d217f02016-08-26 15:09:35 +020049 int max_comp_streams;
Colin Cross5edee2a2014-01-23 14:22:48 -080050 unsigned int zram_size;
liminghao9a0fd1d2016-07-22 11:48:14 +080051 uint64_t reserved_size;
Eric Biggersb478f702017-02-02 14:46:24 -080052 unsigned int file_contents_mode;
53 unsigned int file_names_mode;
Connor O'Brien46fec482017-01-24 17:50:39 -080054 unsigned int erase_blk_size;
55 unsigned int logical_blk_size;
Colin Cross5edee2a2014-01-23 14:22:48 -080056};
57
58struct flag_list {
59 const char *name;
Paul Lawrence4e898a02016-05-24 04:56:37 -070060 unsigned int flag;
Colin Cross5edee2a2014-01-23 14:22:48 -080061};
62
63static struct flag_list mount_flags[] = {
64 { "noatime", MS_NOATIME },
65 { "noexec", MS_NOEXEC },
66 { "nosuid", MS_NOSUID },
67 { "nodev", MS_NODEV },
68 { "nodiratime", MS_NODIRATIME },
69 { "ro", MS_RDONLY },
70 { "rw", 0 },
71 { "remount", MS_REMOUNT },
72 { "bind", MS_BIND },
73 { "rec", MS_REC },
74 { "unbindable", MS_UNBINDABLE },
75 { "private", MS_PRIVATE },
76 { "slave", MS_SLAVE },
77 { "shared", MS_SHARED },
78 { "defaults", 0 },
79 { 0, 0 },
80};
81
82static struct flag_list fs_mgr_flags[] = {
Daniel Rosenberg4c93b252018-08-28 01:41:18 -070083 {"wait", MF_WAIT},
84 {"check", MF_CHECK},
85 {"encryptable=", MF_CRYPT},
86 {"forceencrypt=", MF_FORCECRYPT},
87 {"fileencryption=", MF_FILEENCRYPTION},
88 {"forcefdeorfbe=", MF_FORCEFDEORFBE},
89 {"keydirectory=", MF_KEYDIRECTORY},
90 {"nonremovable", MF_NONREMOVABLE},
91 {"voldmanaged=", MF_VOLDMANAGED},
92 {"length=", MF_LENGTH},
93 {"recoveryonly", MF_RECOVERYONLY},
94 {"swapprio=", MF_SWAPPRIO},
95 {"zramsize=", MF_ZRAMSIZE},
96 {"max_comp_streams=", MF_MAX_COMP_STREAMS},
97 {"verifyatboot", MF_VERIFYATBOOT},
98 {"verify", MF_VERIFY},
99 {"avb", MF_AVB},
100 {"noemulatedsd", MF_NOEMULATEDSD},
101 {"notrim", MF_NOTRIM},
102 {"formattable", MF_FORMATTABLE},
103 {"slotselect", MF_SLOTSELECT},
104 {"nofail", MF_NOFAIL},
105 {"latemount", MF_LATEMOUNT},
106 {"reservedsize=", MF_RESERVEDSIZE},
107 {"quota", MF_QUOTA},
108 {"eraseblk=", MF_ERASEBLKSIZE},
109 {"logicalblk=", MF_LOGICALBLKSIZE},
110 {"sysfs_path=", MF_SYSFS},
111 {"defaults", 0},
112 {"logical", MF_LOGICAL},
113 {"checkpoint=block", MF_CHECKPOINT_BLK},
114 {"checkpoint=fs", MF_CHECKPOINT_FS},
115 {0, 0},
Colin Cross5edee2a2014-01-23 14:22:48 -0800116};
117
Eric Biggersb478f702017-02-02 14:46:24 -0800118#define EM_AES_256_XTS 1
119#define EM_ICE 2
120#define EM_AES_256_CTS 3
121#define EM_AES_256_HEH 4
Paul Lawrence4e898a02016-05-24 04:56:37 -0700122
Eric Biggersb478f702017-02-02 14:46:24 -0800123static const struct flag_list file_contents_encryption_modes[] = {
124 {"aes-256-xts", EM_AES_256_XTS},
125 {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
Greg Kaiser954c1412018-08-01 12:34:32 -0700126 {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
Eric Biggersb478f702017-02-02 14:46:24 -0800127 {0, 0},
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700128};
129
Eric Biggersb478f702017-02-02 14:46:24 -0800130static const struct flag_list file_names_encryption_modes[] = {
131 {"aes-256-cts", EM_AES_256_CTS},
132 {"aes-256-heh", EM_AES_256_HEH},
133 {0, 0},
134};
135
136static unsigned int encryption_mode_to_flag(const struct flag_list *list,
137 const char *mode, const char *type)
138{
139 const struct flag_list *j;
140
141 for (j = list; j->name; ++j) {
142 if (!strcmp(mode, j->name)) {
143 return j->flag;
144 }
145 }
146 LERROR << "Unknown " << type << " encryption mode: " << mode;
147 return 0;
148}
149
150static const char *flag_to_encryption_mode(const struct flag_list *list,
151 unsigned int flag)
152{
153 const struct flag_list *j;
154
155 for (j = list; j->name; ++j) {
156 if (flag == j->flag) {
157 return j->name;
158 }
159 }
160 return nullptr;
161}
162
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700163static uint64_t calculate_zram_size(unsigned int percentage)
164{
165 uint64_t total;
166
167 total = sysconf(_SC_PHYS_PAGES);
168 total *= percentage;
169 total /= 100;
170
171 total *= sysconf(_SC_PAGESIZE);
172
173 return total;
174}
175
liminghao9a0fd1d2016-07-22 11:48:14 +0800176static uint64_t parse_size(const char *arg)
177{
178 char *endptr;
179 uint64_t size = strtoull(arg, &endptr, 10);
180 if (*endptr == 'k' || *endptr == 'K')
181 size *= 1024LL;
182 else if (*endptr == 'm' || *endptr == 'M')
183 size *= 1024LL * 1024LL;
184 else if (*endptr == 'g' || *endptr == 'G')
185 size *= 1024LL * 1024LL * 1024LL;
186
187 return size;
188}
189
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800190/* fills 'dt_value' with the underlying device tree value string without
191 * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
192 * otherwise.
193 */
194static bool read_dt_file(const std::string& file_name, std::string* dt_value)
195{
196 if (android::base::ReadFileToString(file_name, dt_value)) {
197 if (!dt_value->empty()) {
198 // trim the trailing '\0' out, otherwise the comparison
199 // will produce false-negatives.
200 dt_value->resize(dt_value->size() - 1);
201 return true;
202 }
203 }
204
205 return false;
206}
207
Colin Cross5edee2a2014-01-23 14:22:48 -0800208static int parse_flags(char *flags, struct flag_list *fl,
209 struct fs_mgr_flag_values *flag_vals,
210 char *fs_options, int fs_options_len)
211{
212 int f = 0;
213 int i;
214 char *p;
215 char *savep;
216
217 /* initialize flag values. If we find a relevant flag, we'll
218 * update the value */
219 if (flag_vals) {
220 memset(flag_vals, 0, sizeof(*flag_vals));
221 flag_vals->partnum = -1;
222 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
223 }
224
225 /* initialize fs_options to the null string */
226 if (fs_options && (fs_options_len > 0)) {
227 fs_options[0] = '\0';
228 }
229
230 p = strtok_r(flags, ",", &savep);
231 while (p) {
232 /* Look for the flag "p" in the flag list "fl"
233 * If not found, the loop exits with fl[i].name being null.
234 */
235 for (i = 0; fl[i].name; i++) {
Mark Salyzyneba47062018-06-20 13:07:28 -0700236 auto name = fl[i].name;
237 auto len = strlen(name);
238 auto end = len;
239 if (name[end - 1] == '=') --end;
240 if (!strncmp(p, name, len) && (p[end] == name[end])) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800241 f |= fl[i].flag;
Mark Salyzyneba47062018-06-20 13:07:28 -0700242 if (!flag_vals) break;
243 if (p[end] != '=') break;
244 char* arg = p + end + 1;
245 auto flag = fl[i].flag;
246 if (flag == MF_CRYPT) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800247 /* The encryptable flag is followed by an = and the
248 * location of the keys. Get it and return it.
249 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700250 flag_vals->key_loc = strdup(arg);
251 } else if (flag == MF_VERIFY) {
Sami Tolvanen946a0f32015-03-22 12:40:05 +0000252 /* If the verify flag is followed by an = and the
253 * location for the verity state, get it and return it.
254 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700255 flag_vals->verity_loc = strdup(arg);
256 } else if (flag == MF_FORCECRYPT) {
Paul Lawrence2e5ae0a2014-04-04 09:34:19 -0700257 /* The forceencrypt flag is followed by an = and the
258 * location of the keys. Get it and return it.
259 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700260 flag_vals->key_loc = strdup(arg);
261 } else if (flag == MF_FORCEFDEORFBE) {
Paul Lawrenceb262d682015-10-29 10:31:02 -0700262 /* The forcefdeorfbe flag is followed by an = and the
263 * location of the keys. Get it and return it.
264 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700265 flag_vals->key_loc = strdup(arg);
Eric Biggersb478f702017-02-02 14:46:24 -0800266 flag_vals->file_contents_mode = EM_AES_256_XTS;
267 flag_vals->file_names_mode = EM_AES_256_CTS;
Mark Salyzyneba47062018-06-20 13:07:28 -0700268 } else if (flag == MF_FILEENCRYPTION) {
Eric Biggersb478f702017-02-02 14:46:24 -0800269 /* The fileencryption flag is followed by an = and
270 * the mode of contents encryption, then optionally a
271 * : and the mode of filenames encryption (defaults
272 * to aes-256-cts). Get it and return it.
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700273 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700274 auto mode = arg;
275 auto colon = strchr(mode, ':');
Eric Biggersb478f702017-02-02 14:46:24 -0800276 if (colon) {
277 *colon = '\0';
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700278 }
Eric Biggersb478f702017-02-02 14:46:24 -0800279 flag_vals->file_contents_mode =
280 encryption_mode_to_flag(file_contents_encryption_modes,
281 mode, "file contents");
282 if (colon) {
283 flag_vals->file_names_mode =
284 encryption_mode_to_flag(file_names_encryption_modes,
285 colon + 1, "file names");
286 } else {
287 flag_vals->file_names_mode = EM_AES_256_CTS;
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700288 }
Mark Salyzyneba47062018-06-20 13:07:28 -0700289 } else if (flag == MF_KEYDIRECTORY) {
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700290 /* The metadata flag is followed by an = and the
291 * directory for the keys. Get it and return it.
292 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700293 flag_vals->key_dir = strdup(arg);
294 } else if (flag == MF_LENGTH) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800295 /* The length flag is followed by an = and the
296 * size of the partition. Get it and return it.
297 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700298 flag_vals->part_length = strtoll(arg, NULL, 0);
299 } else if (flag == MF_VOLDMANAGED) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800300 /* The voldmanaged flag is followed by an = and the
301 * label, a colon and the partition number or the
302 * word "auto", e.g.
303 * voldmanaged=sdcard:3
304 * Get and return them.
305 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700306 auto label_start = arg;
307 auto label_end = strchr(label_start, ':');
Colin Cross5edee2a2014-01-23 14:22:48 -0800308
Colin Cross5edee2a2014-01-23 14:22:48 -0800309 if (label_end) {
310 flag_vals->label = strndup(label_start,
311 (int) (label_end - label_start));
Mark Salyzyneba47062018-06-20 13:07:28 -0700312 auto part_start = label_end + 1;
Colin Cross5edee2a2014-01-23 14:22:48 -0800313 if (!strcmp(part_start, "auto")) {
314 flag_vals->partnum = -1;
315 } else {
316 flag_vals->partnum = strtol(part_start, NULL, 0);
317 }
318 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800319 LERROR << "Warning: voldmanaged= flag malformed";
Colin Cross5edee2a2014-01-23 14:22:48 -0800320 }
Mark Salyzyneba47062018-06-20 13:07:28 -0700321 } else if (flag == MF_SWAPPRIO) {
322 flag_vals->swap_prio = strtoll(arg, NULL, 0);
323 } else if (flag == MF_MAX_COMP_STREAMS) {
324 flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
325 } else if (flag == MF_ZRAMSIZE) {
326 auto is_percent = !!strrchr(arg, '%');
327 auto val = strtoll(arg, NULL, 0);
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700328 if (is_percent)
329 flag_vals->zram_size = calculate_zram_size(val);
330 else
331 flag_vals->zram_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700332 } else if (flag == MF_RESERVEDSIZE) {
liminghao9a0fd1d2016-07-22 11:48:14 +0800333 /* The reserved flag is followed by an = and the
334 * reserved size of the partition. Get it and return it.
335 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700336 flag_vals->reserved_size = parse_size(arg);
337 } else if (flag == MF_ERASEBLKSIZE) {
Connor O'Brien46fec482017-01-24 17:50:39 -0800338 /* The erase block size flag is followed by an = and the flash
339 * erase block size. Get it, check that it is a power of 2 and
340 * at least 4096, and return it.
341 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700342 auto val = strtoul(arg, NULL, 0);
Connor O'Brien46fec482017-01-24 17:50:39 -0800343 if (val >= 4096 && (val & (val - 1)) == 0)
344 flag_vals->erase_blk_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700345 } else if (flag == MF_LOGICALBLKSIZE) {
Connor O'Brien46fec482017-01-24 17:50:39 -0800346 /* The logical block size flag is followed by an = and the flash
347 * logical block size. Get it, check that it is a power of 2 and
348 * at least 4096, and return it.
349 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700350 auto val = strtoul(arg, NULL, 0);
Connor O'Brien46fec482017-01-24 17:50:39 -0800351 if (val >= 4096 && (val & (val - 1)) == 0)
352 flag_vals->logical_blk_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700353 } else if (flag == MF_SYSFS) {
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800354 /* The path to trigger device gc by idle-maint of vold. */
Mark Salyzyneba47062018-06-20 13:07:28 -0700355 flag_vals->sysfs_path = strdup(arg);
Colin Cross5edee2a2014-01-23 14:22:48 -0800356 }
357 break;
358 }
359 }
360
361 if (!fl[i].name) {
362 if (fs_options) {
363 /* It's not a known flag, so it must be a filesystem specific
364 * option. Add it to fs_options if it was passed in.
365 */
366 strlcat(fs_options, p, fs_options_len);
367 strlcat(fs_options, ",", fs_options_len);
368 } else {
369 /* fs_options was not passed in, so if the flag is unknown
370 * it's an error.
371 */
bowgotsai47878de2017-01-23 14:04:34 +0800372 LERROR << "Warning: unknown flag " << p;
Colin Cross5edee2a2014-01-23 14:22:48 -0800373 }
374 }
375 p = strtok_r(NULL, ",", &savep);
376 }
377
Colin Cross5edee2a2014-01-23 14:22:48 -0800378 if (fs_options && fs_options[0]) {
379 /* remove the last trailing comma from the list of options */
380 fs_options[strlen(fs_options) - 1] = '\0';
381 }
382
383 return f;
384}
385
Yu Ningc01022a2017-07-26 17:54:08 +0800386static std::string init_android_dt_dir() {
387 std::string android_dt_dir;
388 // The platform may specify a custom Android DT path in kernel cmdline
389 if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
390 // Fall back to the standard procfs-based path
391 android_dt_dir = kDefaultAndroidDtDir;
392 }
393 return android_dt_dir;
394}
395
396// FIXME: The same logic is duplicated in system/core/init/
397const std::string& get_android_dt_dir() {
398 // Set once and saves time for subsequent calls to this function
399 static const std::string kAndroidDtDir = init_android_dt_dir();
400 return kAndroidDtDir;
401}
402
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800403static bool is_dt_fstab_compatible() {
404 std::string dt_value;
Yu Ningc01022a2017-07-26 17:54:08 +0800405 std::string file_name = get_android_dt_dir() + "/fstab/compatible";
Tom Cherry1eb04562018-11-06 10:42:09 -0800406
407 if (read_dt_file(file_name, &dt_value) && dt_value == "android,fstab") {
408 // If there's no status property or its set to "ok" or "okay", then we use the DT fstab.
409 std::string status_value;
410 std::string status_file_name = get_android_dt_dir() + "/fstab/status";
411 return !read_dt_file(status_file_name, &status_value) || status_value == "ok" ||
412 status_value == "okay";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800413 }
414
415 return false;
416}
417
418static std::string read_fstab_from_dt() {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800419 if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
Bowgo Tsai80281892017-12-12 00:47:43 +0800420 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800421 }
422
Yu Ningc01022a2017-07-26 17:54:08 +0800423 std::string fstabdir_name = get_android_dt_dir() + "/fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800424 std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
Bowgo Tsai80281892017-12-12 00:47:43 +0800425 if (!fstabdir) return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800426
427 dirent* dp;
Bowgo Tsai80281892017-12-12 00:47:43 +0800428 // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
429 std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800430 while ((dp = readdir(fstabdir.get())) != NULL) {
Bowgo Tsai06ed6132017-06-08 10:43:41 +0800431 // skip over name, compatible and .
432 if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800433
434 // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
435 std::vector<std::string> fstab_entry;
436 std::string file_name;
437 std::string value;
Sandeep Patilbe4302b2017-05-26 18:09:06 -0700438 // skip a partition entry if the status property is present and not set to ok
439 file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
440 if (read_dt_file(file_name, &value)) {
441 if (value != "okay" && value != "ok") {
442 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
443 continue;
444 }
445 }
446
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800447 file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800448 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800449 LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800450 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800451 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800452 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800453
454 std::string mount_point;
455 file_name =
456 android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
457 if (read_dt_file(file_name, &value)) {
458 LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
459 mount_point = value;
460 } else {
461 mount_point = android::base::StringPrintf("/%s", dp->d_name);
462 }
463 fstab_entry.push_back(mount_point);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800464
465 file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800466 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800467 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800468 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800469 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800470 fstab_entry.push_back(value);
471
472 file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800473 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800474 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800475 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800476 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800477 fstab_entry.push_back(value);
478
479 file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800480 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800481 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800482 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800483 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800484 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800485 // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
486 fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800487 }
488
Bowgo Tsai80281892017-12-12 00:47:43 +0800489 // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
490 std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
491 [](const auto& a, const auto& b) { return a.first < b.first; });
492
493 std::string fstab_result;
494 for (const auto& [_, dt_entry] : fstab_dt_entries) {
495 fstab_result += dt_entry + "\n";
496 }
497 return fstab_result;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800498}
499
Sandeep Patile396c602017-02-24 11:04:49 -0800500bool is_dt_compatible() {
Yu Ningc01022a2017-07-26 17:54:08 +0800501 std::string file_name = get_android_dt_dir() + "/compatible";
Sandeep Patile396c602017-02-24 11:04:49 -0800502 std::string dt_value;
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800503 if (read_dt_file(file_name, &dt_value)) {
504 if (dt_value == "android,firmware") {
505 return true;
Sandeep Patile396c602017-02-24 11:04:49 -0800506 }
507 }
508
509 return false;
510}
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800511
Mark Salyzyneba47062018-06-20 13:07:28 -0700512static struct fstab* fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800513 int cnt, entries;
514 ssize_t len;
515 size_t alloc_len = 0;
516 char *line = NULL;
517 const char *delim = " \t";
518 char *save_ptr, *p;
519 struct fstab *fstab = NULL;
Colin Cross5edee2a2014-01-23 14:22:48 -0800520 struct fs_mgr_flag_values flag_vals;
521#define FS_OPTIONS_LEN 1024
522 char tmp_fs_options[FS_OPTIONS_LEN];
523
Colin Cross5edee2a2014-01-23 14:22:48 -0800524 entries = 0;
525 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
526 /* if the last character is a newline, shorten the string by 1 byte */
527 if (line[len - 1] == '\n') {
528 line[len - 1] = '\0';
529 }
530 /* Skip any leading whitespace */
531 p = line;
532 while (isspace(*p)) {
533 p++;
534 }
535 /* ignore comments or empty lines */
536 if (*p == '#' || *p == '\0')
537 continue;
538 entries++;
539 }
540
541 if (!entries) {
bowgotsai47878de2017-01-23 14:04:34 +0800542 LERROR << "No entries found in fstab";
Colin Cross5edee2a2014-01-23 14:22:48 -0800543 goto err;
544 }
545
546 /* Allocate and init the fstab structure */
bowgotsaicea7ea72017-01-16 21:49:49 +0800547 fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
Colin Cross5edee2a2014-01-23 14:22:48 -0800548 fstab->num_entries = entries;
bowgotsaicea7ea72017-01-16 21:49:49 +0800549 fstab->recs = static_cast<struct fstab_rec *>(
550 calloc(fstab->num_entries, sizeof(struct fstab_rec)));
Colin Cross5edee2a2014-01-23 14:22:48 -0800551
552 fseek(fstab_file, 0, SEEK_SET);
553
554 cnt = 0;
555 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
556 /* if the last character is a newline, shorten the string by 1 byte */
557 if (line[len - 1] == '\n') {
558 line[len - 1] = '\0';
559 }
560
561 /* Skip any leading whitespace */
562 p = line;
563 while (isspace(*p)) {
564 p++;
565 }
566 /* ignore comments or empty lines */
567 if (*p == '#' || *p == '\0')
568 continue;
569
570 /* If a non-comment entry is greater than the size we allocated, give an
571 * error and quit. This can happen in the unlikely case the file changes
572 * between the two reads.
573 */
574 if (cnt >= entries) {
bowgotsai47878de2017-01-23 14:04:34 +0800575 LERROR << "Tried to process more entries than counted";
Colin Cross5edee2a2014-01-23 14:22:48 -0800576 break;
577 }
578
579 if (!(p = strtok_r(line, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800580 LERROR << "Error parsing mount source";
Colin Cross5edee2a2014-01-23 14:22:48 -0800581 goto err;
582 }
583 fstab->recs[cnt].blk_device = strdup(p);
584
585 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800586 LERROR << "Error parsing mount_point";
Colin Cross5edee2a2014-01-23 14:22:48 -0800587 goto err;
588 }
589 fstab->recs[cnt].mount_point = strdup(p);
590
591 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800592 LERROR << "Error parsing fs_type";
Colin Cross5edee2a2014-01-23 14:22:48 -0800593 goto err;
594 }
595 fstab->recs[cnt].fs_type = strdup(p);
596
597 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800598 LERROR << "Error parsing mount_flags";
Colin Cross5edee2a2014-01-23 14:22:48 -0800599 goto err;
600 }
601 tmp_fs_options[0] = '\0';
602 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
603 tmp_fs_options, FS_OPTIONS_LEN);
604
605 /* fs_options are optional */
606 if (tmp_fs_options[0]) {
607 fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
608 } else {
609 fstab->recs[cnt].fs_options = NULL;
610 }
611
Mark Salyzyneba47062018-06-20 13:07:28 -0700612 // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
613 if (proc_mounts) {
614 p += strlen(p);
615 } else if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800616 LERROR << "Error parsing fs_mgr_options";
Colin Cross5edee2a2014-01-23 14:22:48 -0800617 goto err;
618 }
619 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
620 &flag_vals, NULL, 0);
621 fstab->recs[cnt].key_loc = flag_vals.key_loc;
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700622 fstab->recs[cnt].key_dir = flag_vals.key_dir;
Sami Tolvanen946a0f32015-03-22 12:40:05 +0000623 fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
Colin Cross5edee2a2014-01-23 14:22:48 -0800624 fstab->recs[cnt].length = flag_vals.part_length;
625 fstab->recs[cnt].label = flag_vals.label;
626 fstab->recs[cnt].partnum = flag_vals.partnum;
627 fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
Peter Enderborg4d217f02016-08-26 15:09:35 +0200628 fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
Colin Cross5edee2a2014-01-23 14:22:48 -0800629 fstab->recs[cnt].zram_size = flag_vals.zram_size;
liminghao9a0fd1d2016-07-22 11:48:14 +0800630 fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
Eric Biggersb478f702017-02-02 14:46:24 -0800631 fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
632 fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
Connor O'Brien46fec482017-01-24 17:50:39 -0800633 fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
634 fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800635 fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
David Anderson62e5b202018-05-01 17:09:17 -0700636 if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) {
637 fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device);
638 }
639
Colin Cross5edee2a2014-01-23 14:22:48 -0800640 cnt++;
641 }
David Zeuthen227ef3c2015-09-03 12:23:12 -0400642 /* If an A/B partition, modify block device to be the real block device */
Bowgo Tsai87d08362017-04-05 00:02:33 +0800643 if (!fs_mgr_update_for_slotselect(fstab)) {
bowgotsai47878de2017-01-23 14:04:34 +0800644 LERROR << "Error updating for slotselect";
David Zeuthen744a8f82015-09-09 18:03:13 -0400645 goto err;
David Zeuthen227ef3c2015-09-03 12:23:12 -0400646 }
Colin Cross5edee2a2014-01-23 14:22:48 -0800647 free(line);
648 return fstab;
649
650err:
Colin Cross5edee2a2014-01-23 14:22:48 -0800651 free(line);
652 if (fstab)
653 fs_mgr_free_fstab(fstab);
654 return NULL;
655}
656
Bowgo Tsai47d34272017-03-06 22:22:07 +0800657/* merges fstab entries from both a and b, then returns the merged result.
658 * note that the caller should only manage the return pointer without
659 * doing further memory management for the two inputs, i.e. only need to
660 * frees up memory of the return value without touching a and b. */
661static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
662{
Chris Morinb183e052018-01-04 17:59:45 -0800663 if (!a && !b) return nullptr;
Bowgo Tsai47d34272017-03-06 22:22:07 +0800664 if (!a) return b;
665 if (!b) return a;
666
667 int total_entries = a->num_entries + b->num_entries;
668 a->recs = static_cast<struct fstab_rec *>(realloc(
669 a->recs, total_entries * (sizeof(struct fstab_rec))));
670 if (!a->recs) {
671 LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
672 // If realloc() fails the original block is left untouched;
673 // it is not freed or moved. So we have to free both a and b here.
674 fs_mgr_free_fstab(a);
675 fs_mgr_free_fstab(b);
676 return nullptr;
677 }
678
679 for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
Chris Morin517ed632018-01-04 14:46:01 -0800680 // Copy the structs by assignment.
Bowgo Tsai47d34272017-03-06 22:22:07 +0800681 a->recs[i] = b->recs[j];
682 }
683
Chris Morin517ed632018-01-04 14:46:01 -0800684 // We can't call fs_mgr_free_fstab because a->recs still references the
685 // memory allocated by strdup.
686 free(b->recs);
Bowgo Tsai47d34272017-03-06 22:22:07 +0800687 free(b);
688
689 a->num_entries = total_entries;
690 return a;
691}
692
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800693/* Extracts <device>s from the by-name symlinks specified in a fstab:
694 * /dev/block/<type>/<device>/by-name/<partition>
695 *
696 * <type> can be: platform, pci or vbd.
697 *
698 * For example, given the following entries in the input fstab:
699 * /dev/block/platform/soc/1da4000.ufshc/by-name/system
700 * /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
701 * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
702 */
703static std::set<std::string> extract_boot_devices(const fstab& fstab) {
704 std::set<std::string> boot_devices;
705
706 for (int i = 0; i < fstab.num_entries; i++) {
707 std::string blk_device(fstab.recs[i].blk_device);
708 // Skips blk_device that doesn't conform to the format.
709 if (!android::base::StartsWith(blk_device, "/dev/block") ||
710 android::base::StartsWith(blk_device, "/dev/block/by-name") ||
711 android::base::StartsWith(blk_device, "/dev/block/bootdevice/by-name")) {
712 continue;
713 }
714 // Skips non-by_name blk_device.
715 // /dev/block/<type>/<device>/by-name/<partition>
716 // ^ slash_by_name
717 auto slash_by_name = blk_device.find("/by-name");
718 if (slash_by_name == std::string::npos) continue;
719 blk_device.erase(slash_by_name); // erases /by-name/<partition>
720
721 // Erases /dev/block/, now we have <type>/<device>
722 blk_device.erase(0, std::string("/dev/block/").size());
723
724 // <type>/<device>
725 // ^ first_slash
726 auto first_slash = blk_device.find('/');
727 if (first_slash == std::string::npos) continue;
728
729 auto boot_device = blk_device.substr(first_slash + 1);
730 if (!boot_device.empty()) boot_devices.insert(std::move(boot_device));
731 }
732
733 return boot_devices;
734}
735
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800736struct fstab *fs_mgr_read_fstab(const char *fstab_path)
737{
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800738 struct fstab *fstab;
739
Tom Cherryf274e782018-10-03 13:13:41 -0700740 auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fstab_path, "re"), fclose};
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800741 if (!fstab_file) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800742 PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
743 return nullptr;
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800744 }
Bowgo Tsai47d34272017-03-06 22:22:07 +0800745
Tom Cherryf274e782018-10-03 13:13:41 -0700746 fstab = fs_mgr_read_fstab_file(fstab_file.get(), !strcmp("/proc/mounts", fstab_path));
Tom Cherrye6eabf42018-06-07 15:31:51 -0700747 if (!fstab) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800748 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800749 }
Bowgo Tsai47d34272017-03-06 22:22:07 +0800750
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800751 return fstab;
752}
753
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800754/* Returns fstab entries parsed from the device tree if they
755 * exist
756 */
757struct fstab *fs_mgr_read_fstab_dt()
758{
759 std::string fstab_buf = read_fstab_from_dt();
760 if (fstab_buf.empty()) {
bowgotsai172c1d82017-03-16 10:25:39 +0900761 LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
Bowgo Tsai47d34272017-03-06 22:22:07 +0800762 return nullptr;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800763 }
764
765 std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
766 fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
767 fstab_buf.length(), "r"), fclose);
768 if (!fstab_file) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800769 PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
770 return nullptr;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800771 }
772
Mark Salyzyneba47062018-06-20 13:07:28 -0700773 struct fstab* fstab = fs_mgr_read_fstab_file(fstab_file.get(), false);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800774 if (!fstab) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800775 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
776 << std::endl << fstab_buf;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800777 }
778
779 return fstab;
780}
781
Bowgo Tsai46c6dc12017-03-07 18:52:03 +0800782/*
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700783 * Identify path to fstab file. Lookup is based on pattern
784 * fstab.<hardware>, fstab.<hardware.platform> in folders
785 /odm/etc, vendor/etc, or /.
786 */
787static std::string get_fstab_path()
788{
789 for (const char* prop : {"hardware", "hardware.platform"}) {
790 std::string hw;
791
792 if (!fs_mgr_get_boot_config(prop, &hw)) continue;
793
794 for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) {
795 std::string fstab_path = prefix + hw;
796 if (access(fstab_path.c_str(), F_OK) == 0) {
797 return fstab_path;
798 }
799 }
800 }
801
802 return std::string();
803}
804
805/*
806 * loads the fstab file and combines with fstab entries passed in from device tree.
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800807 */
808struct fstab *fs_mgr_read_fstab_default()
809{
Bowgo Tsai47d34272017-03-06 22:22:07 +0800810 std::string default_fstab;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800811
Bowgo Tsaid05a2f72017-03-28 01:28:29 +0800812 // Use different fstab paths for normal boot and recovery boot, respectively
Jerry Zhang5de2be52018-07-03 16:03:28 -0700813 if (access("/system/bin/recovery", F_OK) == 0) {
Bowgo Tsaid05a2f72017-03-28 01:28:29 +0800814 default_fstab = "/etc/recovery.fstab";
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700815 } else { // normal boot
816 default_fstab = get_fstab_path();
817 }
818
Chris Morinb183e052018-01-04 17:59:45 -0800819 struct fstab* fstab = nullptr;
820 if (!default_fstab.empty()) {
821 fstab = fs_mgr_read_fstab(default_fstab.c_str());
822 } else {
823 LINFO << __FUNCTION__ << "(): failed to find device default fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800824 }
825
Chris Morinb183e052018-01-04 17:59:45 -0800826 struct fstab* fstab_dt = fs_mgr_read_fstab_dt();
827
Bowgo Tsaiacc1c3c2017-03-29 16:19:45 +0800828 // combines fstab entries passed in from device tree with
829 // the ones found from default_fstab file
Bowgo Tsaiacc1c3c2017-03-29 16:19:45 +0800830 return in_place_merge(fstab_dt, fstab);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800831}
832
Colin Cross5edee2a2014-01-23 14:22:48 -0800833void fs_mgr_free_fstab(struct fstab *fstab)
834{
835 int i;
836
837 if (!fstab) {
838 return;
839 }
840
841 for (i = 0; i < fstab->num_entries; i++) {
842 /* Free the pointers return by strdup(3) */
843 free(fstab->recs[i].blk_device);
David Anderson62e5b202018-05-01 17:09:17 -0700844 free(fstab->recs[i].logical_partition_name);
Colin Cross5edee2a2014-01-23 14:22:48 -0800845 free(fstab->recs[i].mount_point);
846 free(fstab->recs[i].fs_type);
847 free(fstab->recs[i].fs_options);
848 free(fstab->recs[i].key_loc);
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700849 free(fstab->recs[i].key_dir);
Colin Cross5edee2a2014-01-23 14:22:48 -0800850 free(fstab->recs[i].label);
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800851 free(fstab->recs[i].sysfs_path);
Colin Cross5edee2a2014-01-23 14:22:48 -0800852 }
853
854 /* Free the fstab_recs array created by calloc(3) */
855 free(fstab->recs);
856
Colin Cross5edee2a2014-01-23 14:22:48 -0800857 /* Free fstab */
858 free(fstab);
859}
860
861/* Add an entry to the fstab, and return 0 on success or -1 on error */
862int fs_mgr_add_entry(struct fstab *fstab,
863 const char *mount_point, const char *fs_type,
Sasha Levitskiycdc1cfb2014-04-10 17:10:21 -0700864 const char *blk_device)
Colin Cross5edee2a2014-01-23 14:22:48 -0800865{
866 struct fstab_rec *new_fstab_recs;
867 int n = fstab->num_entries;
868
869 new_fstab_recs = (struct fstab_rec *)
870 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
871
872 if (!new_fstab_recs) {
873 return -1;
874 }
875
876 /* A new entry was added, so initialize it */
877 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
878 new_fstab_recs[n].mount_point = strdup(mount_point);
879 new_fstab_recs[n].fs_type = strdup(fs_type);
880 new_fstab_recs[n].blk_device = strdup(blk_device);
881 new_fstab_recs[n].length = 0;
882
883 /* Update the fstab struct */
884 fstab->recs = new_fstab_recs;
885 fstab->num_entries++;
886
887 return 0;
888}
889
JP Abgrall5c01dac2014-06-18 14:54:37 -0700890/*
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800891 * Returns the fstab_rec* whose mount_point is path.
892 * Returns nullptr if not found.
JP Abgrall5c01dac2014-06-18 14:54:37 -0700893 */
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800894struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800895 if (!fstab) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800896 return nullptr;
Colin Cross5edee2a2014-01-23 14:22:48 -0800897 }
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800898 for (int i = 0; i < fstab->num_entries; i++) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800899 if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800900 return &fstab->recs[i];
901 }
902 }
Bowgo Tsaicc323952017-09-26 18:03:23 +0800903 return nullptr;
JP Abgralla794f862014-06-17 16:58:46 -0700904}
905
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800906std::set<std::string> fs_mgr_get_boot_devices() {
907 // boot_devices can be specified in device tree.
908 std::string dt_value;
909 std::string file_name = get_android_dt_dir() + "/boot_devices";
910 if (read_dt_file(file_name, &dt_value)) {
911 auto boot_devices = android::base::Split(dt_value, ",");
912 return std::set<std::string>(boot_devices.begin(), boot_devices.end());
913 }
914
915 // Fallback to extract boot devices from fstab.
916 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
917 fs_mgr_free_fstab);
918 if (fstab) return extract_boot_devices(*fstab);
919
920 return {};
921}
922
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000923int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800924{
925 return fstab->fs_mgr_flags & MF_VOLDMANAGED;
926}
927
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000928int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800929{
930 return fstab->fs_mgr_flags & MF_NONREMOVABLE;
931}
932
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000933int fs_mgr_is_verified(const struct fstab_rec *fstab)
Paul Lawrencebbb36312014-10-09 14:22:49 +0000934{
935 return fstab->fs_mgr_flags & MF_VERIFY;
936}
937
Bowgo Tsai80d1ad12017-04-13 13:05:42 +0800938int fs_mgr_is_avb(const struct fstab_rec *fstab)
939{
940 return fstab->fs_mgr_flags & MF_AVB;
941}
942
Sandeep Patil05ff38b2017-02-16 17:04:11 -0800943int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
944{
945 return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
946}
947
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000948int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800949{
Paul Lawrenceb262d682015-10-29 10:31:02 -0700950 return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
Colin Cross5edee2a2014-01-23 14:22:48 -0800951}
952
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000953int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
954{
955 return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
956}
957
Eric Biggersb478f702017-02-02 14:46:24 -0800958void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
959 const char **contents_mode_ret,
960 const char **filenames_mode_ret)
Paul Lawrence4e898a02016-05-24 04:56:37 -0700961{
Eric Biggersb478f702017-02-02 14:46:24 -0800962 *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes,
963 fstab->file_contents_mode);
964 *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes,
965 fstab->file_names_mode);
Paul Lawrence4e898a02016-05-24 04:56:37 -0700966}
967
Paul Lawrenceb262d682015-10-29 10:31:02 -0700968int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
969{
970 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
971}
972
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000973int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800974{
975 return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
976}
JP Abgrallfe6fcc42015-03-05 17:30:53 -0800977
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700978int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
JP Abgrallfe6fcc42015-03-05 17:30:53 -0800979 return fstab->fs_mgr_flags & MF_NOTRIM;
980}
Ed Tame498c7c2015-04-13 18:01:33 -0700981
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700982int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
Chris Fries79f33842013-09-05 13:19:21 -0500983 return fstab->fs_mgr_flags & (MF_FORMATTABLE);
984}
Daniel Rosenbergeb65ce02015-09-01 12:41:18 -0700985
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700986int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
Daniel Rosenberg8bb2f362015-08-27 13:42:20 -0700987 return fstab->fs_mgr_flags & MF_SLOTSELECT;
988}
Daniel Rosenberge3a32882016-04-12 14:28:09 -0700989
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700990int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -0700991 return fstab->fs_mgr_flags & MF_NOFAIL;
992}
Wei Wangd61a7e22016-08-23 11:58:09 -0700993
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700994int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
Wei Wangd61a7e22016-08-23 11:58:09 -0700995 return fstab->fs_mgr_flags & MF_LATEMOUNT;
996}
Jeff Sharkey6d896102016-12-14 12:00:51 -0700997
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700998int fs_mgr_is_quota(const struct fstab_rec* fstab) {
Jeff Sharkey6d896102016-12-14 12:00:51 -0700999 return fstab->fs_mgr_flags & MF_QUOTA;
1000}
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -08001001
1002int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
1003{
1004 return fstab->fs_mgr_flags & MF_SYSFS;
1005}
David Anderson62e5b202018-05-01 17:09:17 -07001006
1007int fs_mgr_is_logical(const struct fstab_rec* fstab) {
1008 return fstab->fs_mgr_flags & MF_LOGICAL;
1009}
Daniel Rosenberg4c93b252018-08-28 01:41:18 -07001010
1011int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
1012 return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
1013}
1014
1015int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
1016 return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
1017}
1018
1019int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
1020 return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
1021}