blob: 68cc530ddf1776938f82e8e2e21d150d09d7e14c [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
Yu Ningc01022a2017-07-26 17:54:08 +080036const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
37
Colin Cross5edee2a2014-01-23 14:22:48 -080038struct fs_mgr_flag_values {
39 char *key_loc;
Paul Lawrence9dbe97b2017-04-21 12:41:48 -070040 char* key_dir;
Sami Tolvanen946a0f32015-03-22 12:40:05 +000041 char *verity_loc;
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -080042 char *sysfs_path;
Colin Cross5edee2a2014-01-23 14:22:48 -080043 long long part_length;
44 char *label;
45 int partnum;
46 int swap_prio;
Peter Enderborg4d217f02016-08-26 15:09:35 +020047 int max_comp_streams;
Colin Cross5edee2a2014-01-23 14:22:48 -080048 unsigned int zram_size;
liminghao9a0fd1d2016-07-22 11:48:14 +080049 uint64_t reserved_size;
Eric Biggersb478f702017-02-02 14:46:24 -080050 unsigned int file_contents_mode;
51 unsigned int file_names_mode;
Connor O'Brien46fec482017-01-24 17:50:39 -080052 unsigned int erase_blk_size;
53 unsigned int logical_blk_size;
Colin Cross5edee2a2014-01-23 14:22:48 -080054};
55
56struct flag_list {
57 const char *name;
Paul Lawrence4e898a02016-05-24 04:56:37 -070058 unsigned int flag;
Colin Cross5edee2a2014-01-23 14:22:48 -080059};
60
61static struct flag_list mount_flags[] = {
62 { "noatime", MS_NOATIME },
63 { "noexec", MS_NOEXEC },
64 { "nosuid", MS_NOSUID },
65 { "nodev", MS_NODEV },
66 { "nodiratime", MS_NODIRATIME },
67 { "ro", MS_RDONLY },
68 { "rw", 0 },
69 { "remount", MS_REMOUNT },
70 { "bind", MS_BIND },
71 { "rec", MS_REC },
72 { "unbindable", MS_UNBINDABLE },
73 { "private", MS_PRIVATE },
74 { "slave", MS_SLAVE },
75 { "shared", MS_SHARED },
76 { "defaults", 0 },
77 { 0, 0 },
78};
79
80static struct flag_list fs_mgr_flags[] = {
Paul Lawrence9dbe97b2017-04-21 12:41:48 -070081 {"wait", MF_WAIT},
82 {"check", MF_CHECK},
83 {"encryptable=", MF_CRYPT},
84 {"forceencrypt=", MF_FORCECRYPT},
85 {"fileencryption=", MF_FILEENCRYPTION},
86 {"forcefdeorfbe=", MF_FORCEFDEORFBE},
87 {"keydirectory=", MF_KEYDIRECTORY},
88 {"nonremovable", MF_NONREMOVABLE},
89 {"voldmanaged=", MF_VOLDMANAGED},
90 {"length=", MF_LENGTH},
91 {"recoveryonly", MF_RECOVERYONLY},
92 {"swapprio=", MF_SWAPPRIO},
93 {"zramsize=", MF_ZRAMSIZE},
94 {"max_comp_streams=", MF_MAX_COMP_STREAMS},
95 {"verifyatboot", MF_VERIFYATBOOT},
96 {"verify", MF_VERIFY},
97 {"avb", MF_AVB},
98 {"noemulatedsd", MF_NOEMULATEDSD},
99 {"notrim", MF_NOTRIM},
100 {"formattable", MF_FORMATTABLE},
101 {"slotselect", MF_SLOTSELECT},
102 {"nofail", MF_NOFAIL},
103 {"latemount", MF_LATEMOUNT},
104 {"reservedsize=", MF_RESERVEDSIZE},
105 {"quota", MF_QUOTA},
106 {"eraseblk=", MF_ERASEBLKSIZE},
107 {"logicalblk=", MF_LOGICALBLKSIZE},
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800108 {"sysfs_path=", MF_SYSFS},
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700109 {"defaults", 0},
110 {0, 0},
Colin Cross5edee2a2014-01-23 14:22:48 -0800111};
112
Eric Biggersb478f702017-02-02 14:46:24 -0800113#define EM_AES_256_XTS 1
114#define EM_ICE 2
115#define EM_AES_256_CTS 3
116#define EM_AES_256_HEH 4
Paul Crowley49c27c52018-03-30 09:44:53 -0700117#define EM_SPECK_128_256_XTS 5
118#define EM_SPECK_128_256_CTS 6
Paul Lawrence4e898a02016-05-24 04:56:37 -0700119
Eric Biggersb478f702017-02-02 14:46:24 -0800120static const struct flag_list file_contents_encryption_modes[] = {
121 {"aes-256-xts", EM_AES_256_XTS},
Paul Crowley49c27c52018-03-30 09:44:53 -0700122 {"speck128/256-xts", EM_SPECK_128_256_XTS},
Eric Biggersb478f702017-02-02 14:46:24 -0800123 {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
Paul Crowley49c27c52018-03-30 09:44:53 -0700124 {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
Eric Biggersb478f702017-02-02 14:46:24 -0800125 {0, 0},
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700126};
127
Eric Biggersb478f702017-02-02 14:46:24 -0800128static const struct flag_list file_names_encryption_modes[] = {
129 {"aes-256-cts", EM_AES_256_CTS},
130 {"aes-256-heh", EM_AES_256_HEH},
Paul Crowley49c27c52018-03-30 09:44:53 -0700131 {"speck128/256-cts", EM_SPECK_128_256_CTS},
Eric Biggersb478f702017-02-02 14:46:24 -0800132 {0, 0},
133};
134
135static unsigned int encryption_mode_to_flag(const struct flag_list *list,
136 const char *mode, const char *type)
137{
138 const struct flag_list *j;
139
140 for (j = list; j->name; ++j) {
141 if (!strcmp(mode, j->name)) {
142 return j->flag;
143 }
144 }
145 LERROR << "Unknown " << type << " encryption mode: " << mode;
146 return 0;
147}
148
149static const char *flag_to_encryption_mode(const struct flag_list *list,
150 unsigned int flag)
151{
152 const struct flag_list *j;
153
154 for (j = list; j->name; ++j) {
155 if (flag == j->flag) {
156 return j->name;
157 }
158 }
159 return nullptr;
160}
161
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700162static uint64_t calculate_zram_size(unsigned int percentage)
163{
164 uint64_t total;
165
166 total = sysconf(_SC_PHYS_PAGES);
167 total *= percentage;
168 total /= 100;
169
170 total *= sysconf(_SC_PAGESIZE);
171
172 return total;
173}
174
liminghao9a0fd1d2016-07-22 11:48:14 +0800175static uint64_t parse_size(const char *arg)
176{
177 char *endptr;
178 uint64_t size = strtoull(arg, &endptr, 10);
179 if (*endptr == 'k' || *endptr == 'K')
180 size *= 1024LL;
181 else if (*endptr == 'm' || *endptr == 'M')
182 size *= 1024LL * 1024LL;
183 else if (*endptr == 'g' || *endptr == 'G')
184 size *= 1024LL * 1024LL * 1024LL;
185
186 return size;
187}
188
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800189/* fills 'dt_value' with the underlying device tree value string without
190 * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
191 * otherwise.
192 */
193static bool read_dt_file(const std::string& file_name, std::string* dt_value)
194{
195 if (android::base::ReadFileToString(file_name, dt_value)) {
196 if (!dt_value->empty()) {
197 // trim the trailing '\0' out, otherwise the comparison
198 // will produce false-negatives.
199 dt_value->resize(dt_value->size() - 1);
200 return true;
201 }
202 }
203
204 return false;
205}
206
Colin Cross5edee2a2014-01-23 14:22:48 -0800207static int parse_flags(char *flags, struct flag_list *fl,
208 struct fs_mgr_flag_values *flag_vals,
209 char *fs_options, int fs_options_len)
210{
211 int f = 0;
212 int i;
213 char *p;
214 char *savep;
215
216 /* initialize flag values. If we find a relevant flag, we'll
217 * update the value */
218 if (flag_vals) {
219 memset(flag_vals, 0, sizeof(*flag_vals));
220 flag_vals->partnum = -1;
221 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
222 }
223
224 /* initialize fs_options to the null string */
225 if (fs_options && (fs_options_len > 0)) {
226 fs_options[0] = '\0';
227 }
228
229 p = strtok_r(flags, ",", &savep);
230 while (p) {
231 /* Look for the flag "p" in the flag list "fl"
232 * If not found, the loop exits with fl[i].name being null.
233 */
234 for (i = 0; fl[i].name; i++) {
235 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
236 f |= fl[i].flag;
237 if ((fl[i].flag == MF_CRYPT) && flag_vals) {
238 /* The encryptable flag is followed by an = and the
239 * location of the keys. Get it and return it.
240 */
241 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
Sami Tolvanen946a0f32015-03-22 12:40:05 +0000242 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) {
243 /* If the verify flag is followed by an = and the
244 * location for the verity state, get it and return it.
245 */
246 char *start = strchr(p, '=');
247 if (start) {
248 flag_vals->verity_loc = strdup(start + 1);
249 }
Paul Lawrence2e5ae0a2014-04-04 09:34:19 -0700250 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
251 /* The forceencrypt flag is followed by an = and the
252 * location of the keys. Get it and return it.
253 */
254 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
Paul Lawrenceb262d682015-10-29 10:31:02 -0700255 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) {
256 /* The forcefdeorfbe flag is followed by an = and the
257 * location of the keys. Get it and return it.
258 */
259 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
Eric Biggersb478f702017-02-02 14:46:24 -0800260 flag_vals->file_contents_mode = EM_AES_256_XTS;
261 flag_vals->file_names_mode = EM_AES_256_CTS;
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700262 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
Eric Biggersb478f702017-02-02 14:46:24 -0800263 /* The fileencryption flag is followed by an = and
264 * the mode of contents encryption, then optionally a
265 * : and the mode of filenames encryption (defaults
266 * to aes-256-cts). Get it and return it.
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700267 */
Eric Biggersb478f702017-02-02 14:46:24 -0800268 char *mode = strchr(p, '=') + 1;
269 char *colon = strchr(mode, ':');
270 if (colon) {
271 *colon = '\0';
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700272 }
Eric Biggersb478f702017-02-02 14:46:24 -0800273 flag_vals->file_contents_mode =
274 encryption_mode_to_flag(file_contents_encryption_modes,
275 mode, "file contents");
276 if (colon) {
277 flag_vals->file_names_mode =
278 encryption_mode_to_flag(file_names_encryption_modes,
279 colon + 1, "file names");
280 } else {
281 flag_vals->file_names_mode = EM_AES_256_CTS;
Paul Lawrence5b8a1082016-05-05 11:00:44 -0700282 }
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700283 } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
284 /* The metadata flag is followed by an = and the
285 * directory for the keys. Get it and return it.
286 */
287 flag_vals->key_dir = strdup(strchr(p, '=') + 1);
Colin Cross5edee2a2014-01-23 14:22:48 -0800288 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
289 /* The length flag is followed by an = and the
290 * size of the partition. Get it and return it.
291 */
292 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
293 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
294 /* The voldmanaged flag is followed by an = and the
295 * label, a colon and the partition number or the
296 * word "auto", e.g.
297 * voldmanaged=sdcard:3
298 * Get and return them.
299 */
300 char *label_start;
301 char *label_end;
302 char *part_start;
303
304 label_start = strchr(p, '=') + 1;
305 label_end = strchr(p, ':');
306 if (label_end) {
307 flag_vals->label = strndup(label_start,
308 (int) (label_end - label_start));
309 part_start = strchr(p, ':') + 1;
310 if (!strcmp(part_start, "auto")) {
311 flag_vals->partnum = -1;
312 } else {
313 flag_vals->partnum = strtol(part_start, NULL, 0);
314 }
315 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800316 LERROR << "Warning: voldmanaged= flag malformed";
Colin Cross5edee2a2014-01-23 14:22:48 -0800317 }
318 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
319 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
Peter Enderborg4d217f02016-08-26 15:09:35 +0200320 } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) {
321 flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0);
Colin Cross5edee2a2014-01-23 14:22:48 -0800322 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700323 int is_percent = !!strrchr(p, '%');
324 unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0);
325 if (is_percent)
326 flag_vals->zram_size = calculate_zram_size(val);
327 else
328 flag_vals->zram_size = val;
liminghao9a0fd1d2016-07-22 11:48:14 +0800329 } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
330 /* The reserved flag is followed by an = and the
331 * reserved size of the partition. Get it and return it.
332 */
333 flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
Connor O'Brien46fec482017-01-24 17:50:39 -0800334 } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) {
335 /* The erase block size flag is followed by an = and the flash
336 * erase block size. Get it, check that it is a power of 2 and
337 * at least 4096, and return it.
338 */
339 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
340 if (val >= 4096 && (val & (val - 1)) == 0)
341 flag_vals->erase_blk_size = val;
342 } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) {
343 /* The logical block size flag is followed by an = and the flash
344 * logical block size. Get it, check that it is a power of 2 and
345 * at least 4096, and return it.
346 */
347 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
348 if (val >= 4096 && (val & (val - 1)) == 0)
349 flag_vals->logical_blk_size = val;
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800350 } else if ((fl[i].flag == MF_SYSFS) && flag_vals) {
351 /* The path to trigger device gc by idle-maint of vold. */
352 flag_vals->sysfs_path = strdup(strchr(p, '=') + 1);
Colin Cross5edee2a2014-01-23 14:22:48 -0800353 }
354 break;
355 }
356 }
357
358 if (!fl[i].name) {
359 if (fs_options) {
360 /* It's not a known flag, so it must be a filesystem specific
361 * option. Add it to fs_options if it was passed in.
362 */
363 strlcat(fs_options, p, fs_options_len);
364 strlcat(fs_options, ",", fs_options_len);
365 } else {
366 /* fs_options was not passed in, so if the flag is unknown
367 * it's an error.
368 */
bowgotsai47878de2017-01-23 14:04:34 +0800369 LERROR << "Warning: unknown flag " << p;
Colin Cross5edee2a2014-01-23 14:22:48 -0800370 }
371 }
372 p = strtok_r(NULL, ",", &savep);
373 }
374
Colin Cross5edee2a2014-01-23 14:22:48 -0800375 if (fs_options && fs_options[0]) {
376 /* remove the last trailing comma from the list of options */
377 fs_options[strlen(fs_options) - 1] = '\0';
378 }
379
380 return f;
381}
382
Yu Ningc01022a2017-07-26 17:54:08 +0800383static std::string init_android_dt_dir() {
384 std::string android_dt_dir;
385 // The platform may specify a custom Android DT path in kernel cmdline
386 if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
387 // Fall back to the standard procfs-based path
388 android_dt_dir = kDefaultAndroidDtDir;
389 }
390 return android_dt_dir;
391}
392
393// FIXME: The same logic is duplicated in system/core/init/
394const std::string& get_android_dt_dir() {
395 // Set once and saves time for subsequent calls to this function
396 static const std::string kAndroidDtDir = init_android_dt_dir();
397 return kAndroidDtDir;
398}
399
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800400static bool is_dt_fstab_compatible() {
401 std::string dt_value;
Yu Ningc01022a2017-07-26 17:54:08 +0800402 std::string file_name = get_android_dt_dir() + "/fstab/compatible";
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800403 if (read_dt_file(file_name, &dt_value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800404 if (dt_value == "android,fstab") {
405 return true;
406 }
407 }
408
409 return false;
410}
411
412static std::string read_fstab_from_dt() {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800413 if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
Bowgo Tsai80281892017-12-12 00:47:43 +0800414 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800415 }
416
Yu Ningc01022a2017-07-26 17:54:08 +0800417 std::string fstabdir_name = get_android_dt_dir() + "/fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800418 std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
Bowgo Tsai80281892017-12-12 00:47:43 +0800419 if (!fstabdir) return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800420
421 dirent* dp;
Bowgo Tsai80281892017-12-12 00:47:43 +0800422 // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
423 std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800424 while ((dp = readdir(fstabdir.get())) != NULL) {
Bowgo Tsai06ed6132017-06-08 10:43:41 +0800425 // skip over name, compatible and .
426 if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800427
428 // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
429 std::vector<std::string> fstab_entry;
430 std::string file_name;
431 std::string value;
Sandeep Patilbe4302b2017-05-26 18:09:06 -0700432 // skip a partition entry if the status property is present and not set to ok
433 file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
434 if (read_dt_file(file_name, &value)) {
435 if (value != "okay" && value != "ok") {
436 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
437 continue;
438 }
439 }
440
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800441 file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800442 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800443 LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800444 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800445 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800446 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800447
448 std::string mount_point;
449 file_name =
450 android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
451 if (read_dt_file(file_name, &value)) {
452 LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
453 mount_point = value;
454 } else {
455 mount_point = android::base::StringPrintf("/%s", dp->d_name);
456 }
457 fstab_entry.push_back(mount_point);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800458
459 file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800460 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800461 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800462 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800463 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800464 fstab_entry.push_back(value);
465
466 file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800467 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800468 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800469 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800470 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800471 fstab_entry.push_back(value);
472
473 file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800474 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800475 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800476 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800477 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800478 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800479 // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
480 fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800481 }
482
Bowgo Tsai80281892017-12-12 00:47:43 +0800483 // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
484 std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
485 [](const auto& a, const auto& b) { return a.first < b.first; });
486
487 std::string fstab_result;
488 for (const auto& [_, dt_entry] : fstab_dt_entries) {
489 fstab_result += dt_entry + "\n";
490 }
491 return fstab_result;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800492}
493
Sandeep Patile396c602017-02-24 11:04:49 -0800494bool is_dt_compatible() {
Yu Ningc01022a2017-07-26 17:54:08 +0800495 std::string file_name = get_android_dt_dir() + "/compatible";
Sandeep Patile396c602017-02-24 11:04:49 -0800496 std::string dt_value;
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800497 if (read_dt_file(file_name, &dt_value)) {
498 if (dt_value == "android,firmware") {
499 return true;
Sandeep Patile396c602017-02-24 11:04:49 -0800500 }
501 }
502
503 return false;
504}
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800505
Bowgo Tsai47d34272017-03-06 22:22:07 +0800506static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
Colin Cross5edee2a2014-01-23 14:22:48 -0800507{
Colin Cross5edee2a2014-01-23 14:22:48 -0800508 int cnt, entries;
509 ssize_t len;
510 size_t alloc_len = 0;
511 char *line = NULL;
512 const char *delim = " \t";
513 char *save_ptr, *p;
514 struct fstab *fstab = NULL;
Colin Cross5edee2a2014-01-23 14:22:48 -0800515 struct fs_mgr_flag_values flag_vals;
516#define FS_OPTIONS_LEN 1024
517 char tmp_fs_options[FS_OPTIONS_LEN];
518
Colin Cross5edee2a2014-01-23 14:22:48 -0800519 entries = 0;
520 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
521 /* if the last character is a newline, shorten the string by 1 byte */
522 if (line[len - 1] == '\n') {
523 line[len - 1] = '\0';
524 }
525 /* Skip any leading whitespace */
526 p = line;
527 while (isspace(*p)) {
528 p++;
529 }
530 /* ignore comments or empty lines */
531 if (*p == '#' || *p == '\0')
532 continue;
533 entries++;
534 }
535
536 if (!entries) {
bowgotsai47878de2017-01-23 14:04:34 +0800537 LERROR << "No entries found in fstab";
Colin Cross5edee2a2014-01-23 14:22:48 -0800538 goto err;
539 }
540
541 /* Allocate and init the fstab structure */
bowgotsaicea7ea72017-01-16 21:49:49 +0800542 fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
Colin Cross5edee2a2014-01-23 14:22:48 -0800543 fstab->num_entries = entries;
bowgotsaicea7ea72017-01-16 21:49:49 +0800544 fstab->recs = static_cast<struct fstab_rec *>(
545 calloc(fstab->num_entries, sizeof(struct fstab_rec)));
Colin Cross5edee2a2014-01-23 14:22:48 -0800546
547 fseek(fstab_file, 0, SEEK_SET);
548
549 cnt = 0;
550 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
551 /* if the last character is a newline, shorten the string by 1 byte */
552 if (line[len - 1] == '\n') {
553 line[len - 1] = '\0';
554 }
555
556 /* Skip any leading whitespace */
557 p = line;
558 while (isspace(*p)) {
559 p++;
560 }
561 /* ignore comments or empty lines */
562 if (*p == '#' || *p == '\0')
563 continue;
564
565 /* If a non-comment entry is greater than the size we allocated, give an
566 * error and quit. This can happen in the unlikely case the file changes
567 * between the two reads.
568 */
569 if (cnt >= entries) {
bowgotsai47878de2017-01-23 14:04:34 +0800570 LERROR << "Tried to process more entries than counted";
Colin Cross5edee2a2014-01-23 14:22:48 -0800571 break;
572 }
573
574 if (!(p = strtok_r(line, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800575 LERROR << "Error parsing mount source";
Colin Cross5edee2a2014-01-23 14:22:48 -0800576 goto err;
577 }
578 fstab->recs[cnt].blk_device = strdup(p);
579
580 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800581 LERROR << "Error parsing mount_point";
Colin Cross5edee2a2014-01-23 14:22:48 -0800582 goto err;
583 }
584 fstab->recs[cnt].mount_point = strdup(p);
585
586 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800587 LERROR << "Error parsing fs_type";
Colin Cross5edee2a2014-01-23 14:22:48 -0800588 goto err;
589 }
590 fstab->recs[cnt].fs_type = strdup(p);
591
592 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800593 LERROR << "Error parsing mount_flags";
Colin Cross5edee2a2014-01-23 14:22:48 -0800594 goto err;
595 }
596 tmp_fs_options[0] = '\0';
597 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
598 tmp_fs_options, FS_OPTIONS_LEN);
599
600 /* fs_options are optional */
601 if (tmp_fs_options[0]) {
602 fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
603 } else {
604 fstab->recs[cnt].fs_options = NULL;
605 }
606
607 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800608 LERROR << "Error parsing fs_mgr_options";
Colin Cross5edee2a2014-01-23 14:22:48 -0800609 goto err;
610 }
611 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
612 &flag_vals, NULL, 0);
613 fstab->recs[cnt].key_loc = flag_vals.key_loc;
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700614 fstab->recs[cnt].key_dir = flag_vals.key_dir;
Sami Tolvanen946a0f32015-03-22 12:40:05 +0000615 fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
Colin Cross5edee2a2014-01-23 14:22:48 -0800616 fstab->recs[cnt].length = flag_vals.part_length;
617 fstab->recs[cnt].label = flag_vals.label;
618 fstab->recs[cnt].partnum = flag_vals.partnum;
619 fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
Peter Enderborg4d217f02016-08-26 15:09:35 +0200620 fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
Colin Cross5edee2a2014-01-23 14:22:48 -0800621 fstab->recs[cnt].zram_size = flag_vals.zram_size;
liminghao9a0fd1d2016-07-22 11:48:14 +0800622 fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
Eric Biggersb478f702017-02-02 14:46:24 -0800623 fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
624 fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
Connor O'Brien46fec482017-01-24 17:50:39 -0800625 fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
626 fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800627 fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
Colin Cross5edee2a2014-01-23 14:22:48 -0800628 cnt++;
629 }
David Zeuthen227ef3c2015-09-03 12:23:12 -0400630 /* If an A/B partition, modify block device to be the real block device */
Bowgo Tsai87d08362017-04-05 00:02:33 +0800631 if (!fs_mgr_update_for_slotselect(fstab)) {
bowgotsai47878de2017-01-23 14:04:34 +0800632 LERROR << "Error updating for slotselect";
David Zeuthen744a8f82015-09-09 18:03:13 -0400633 goto err;
David Zeuthen227ef3c2015-09-03 12:23:12 -0400634 }
Colin Cross5edee2a2014-01-23 14:22:48 -0800635 free(line);
636 return fstab;
637
638err:
Colin Cross5edee2a2014-01-23 14:22:48 -0800639 free(line);
640 if (fstab)
641 fs_mgr_free_fstab(fstab);
642 return NULL;
643}
644
Bowgo Tsai47d34272017-03-06 22:22:07 +0800645/* merges fstab entries from both a and b, then returns the merged result.
646 * note that the caller should only manage the return pointer without
647 * doing further memory management for the two inputs, i.e. only need to
648 * frees up memory of the return value without touching a and b. */
649static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
650{
Chris Morinb183e052018-01-04 17:59:45 -0800651 if (!a && !b) return nullptr;
Bowgo Tsai47d34272017-03-06 22:22:07 +0800652 if (!a) return b;
653 if (!b) return a;
654
655 int total_entries = a->num_entries + b->num_entries;
656 a->recs = static_cast<struct fstab_rec *>(realloc(
657 a->recs, total_entries * (sizeof(struct fstab_rec))));
658 if (!a->recs) {
659 LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
660 // If realloc() fails the original block is left untouched;
661 // it is not freed or moved. So we have to free both a and b here.
662 fs_mgr_free_fstab(a);
663 fs_mgr_free_fstab(b);
664 return nullptr;
665 }
666
667 for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
Chris Morin517ed632018-01-04 14:46:01 -0800668 // Copy the structs by assignment.
Bowgo Tsai47d34272017-03-06 22:22:07 +0800669 a->recs[i] = b->recs[j];
670 }
671
Chris Morin517ed632018-01-04 14:46:01 -0800672 // We can't call fs_mgr_free_fstab because a->recs still references the
673 // memory allocated by strdup.
674 free(b->recs);
Bowgo Tsai47d34272017-03-06 22:22:07 +0800675 free(b->fstab_filename);
676 free(b);
677
678 a->num_entries = total_entries;
679 return a;
680}
681
Bowgo Tsai5ee7dae2018-05-16 18:33:44 +0800682/* Extracts <device>s from the by-name symlinks specified in a fstab:
683 * /dev/block/<type>/<device>/by-name/<partition>
684 *
685 * <type> can be: platform, pci or vbd.
686 *
687 * For example, given the following entries in the input fstab:
688 * /dev/block/platform/soc/1da4000.ufshc/by-name/system
689 * /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
690 * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
691 */
692static std::set<std::string> extract_boot_devices(const fstab& fstab) {
693 std::set<std::string> boot_devices;
694
695 for (int i = 0; i < fstab.num_entries; i++) {
696 std::string blk_device(fstab.recs[i].blk_device);
697 // Skips blk_device that doesn't conform to the format.
698 if (!android::base::StartsWith(blk_device, "/dev/block") ||
699 android::base::StartsWith(blk_device, "/dev/block/by-name") ||
700 android::base::StartsWith(blk_device, "/dev/block/bootdevice/by-name")) {
701 continue;
702 }
703 // Skips non-by_name blk_device.
704 // /dev/block/<type>/<device>/by-name/<partition>
705 // ^ slash_by_name
706 auto slash_by_name = blk_device.find("/by-name");
707 if (slash_by_name == std::string::npos) continue;
708 blk_device.erase(slash_by_name); // erases /by-name/<partition>
709
710 // Erases /dev/block/, now we have <type>/<device>
711 blk_device.erase(0, std::string("/dev/block/").size());
712
713 // <type>/<device>
714 // ^ first_slash
715 auto first_slash = blk_device.find('/');
716 if (first_slash == std::string::npos) continue;
717
718 auto boot_device = blk_device.substr(first_slash + 1);
719 if (!boot_device.empty()) boot_devices.insert(std::move(boot_device));
720 }
721
722 return boot_devices;
723}
724
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800725struct fstab *fs_mgr_read_fstab(const char *fstab_path)
726{
727 FILE *fstab_file;
728 struct fstab *fstab;
729
730 fstab_file = fopen(fstab_path, "r");
731 if (!fstab_file) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800732 PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
733 return nullptr;
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800734 }
Bowgo Tsai47d34272017-03-06 22:22:07 +0800735
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800736 fstab = fs_mgr_read_fstab_file(fstab_file);
737 if (fstab) {
738 fstab->fstab_filename = strdup(fstab_path);
Bowgo Tsai47d34272017-03-06 22:22:07 +0800739 } else {
740 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800741 }
Bowgo Tsai47d34272017-03-06 22:22:07 +0800742
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800743 fclose(fstab_file);
744 return fstab;
745}
746
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800747/* Returns fstab entries parsed from the device tree if they
748 * exist
749 */
750struct fstab *fs_mgr_read_fstab_dt()
751{
752 std::string fstab_buf = read_fstab_from_dt();
753 if (fstab_buf.empty()) {
bowgotsai172c1d82017-03-16 10:25:39 +0900754 LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
Bowgo Tsai47d34272017-03-06 22:22:07 +0800755 return nullptr;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800756 }
757
758 std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
759 fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
760 fstab_buf.length(), "r"), fclose);
761 if (!fstab_file) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800762 PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
763 return nullptr;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800764 }
765
766 struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
767 if (!fstab) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800768 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
769 << std::endl << fstab_buf;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800770 }
771
772 return fstab;
773}
774
Bowgo Tsai46c6dc12017-03-07 18:52:03 +0800775/*
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700776 * Identify path to fstab file. Lookup is based on pattern
777 * fstab.<hardware>, fstab.<hardware.platform> in folders
778 /odm/etc, vendor/etc, or /.
779 */
780static std::string get_fstab_path()
781{
782 for (const char* prop : {"hardware", "hardware.platform"}) {
783 std::string hw;
784
785 if (!fs_mgr_get_boot_config(prop, &hw)) continue;
786
787 for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) {
788 std::string fstab_path = prefix + hw;
789 if (access(fstab_path.c_str(), F_OK) == 0) {
790 return fstab_path;
791 }
792 }
793 }
794
795 return std::string();
796}
797
798/*
799 * loads the fstab file and combines with fstab entries passed in from device tree.
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800800 */
801struct fstab *fs_mgr_read_fstab_default()
802{
Bowgo Tsai47d34272017-03-06 22:22:07 +0800803 std::string default_fstab;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800804
Bowgo Tsaid05a2f72017-03-28 01:28:29 +0800805 // Use different fstab paths for normal boot and recovery boot, respectively
806 if (access("/sbin/recovery", F_OK) == 0) {
807 default_fstab = "/etc/recovery.fstab";
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700808 } else { // normal boot
809 default_fstab = get_fstab_path();
810 }
811
Chris Morinb183e052018-01-04 17:59:45 -0800812 struct fstab* fstab = nullptr;
813 if (!default_fstab.empty()) {
814 fstab = fs_mgr_read_fstab(default_fstab.c_str());
815 } else {
816 LINFO << __FUNCTION__ << "(): failed to find device default fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800817 }
818
Chris Morinb183e052018-01-04 17:59:45 -0800819 struct fstab* fstab_dt = fs_mgr_read_fstab_dt();
820
Bowgo Tsaiacc1c3c2017-03-29 16:19:45 +0800821 // combines fstab entries passed in from device tree with
822 // the ones found from default_fstab file
Bowgo Tsaiacc1c3c2017-03-29 16:19:45 +0800823 return in_place_merge(fstab_dt, fstab);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800824}
825
Colin Cross5edee2a2014-01-23 14:22:48 -0800826void fs_mgr_free_fstab(struct fstab *fstab)
827{
828 int i;
829
830 if (!fstab) {
831 return;
832 }
833
834 for (i = 0; i < fstab->num_entries; i++) {
835 /* Free the pointers return by strdup(3) */
836 free(fstab->recs[i].blk_device);
837 free(fstab->recs[i].mount_point);
838 free(fstab->recs[i].fs_type);
839 free(fstab->recs[i].fs_options);
840 free(fstab->recs[i].key_loc);
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700841 free(fstab->recs[i].key_dir);
Colin Cross5edee2a2014-01-23 14:22:48 -0800842 free(fstab->recs[i].label);
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800843 free(fstab->recs[i].sysfs_path);
Colin Cross5edee2a2014-01-23 14:22:48 -0800844 }
845
846 /* Free the fstab_recs array created by calloc(3) */
847 free(fstab->recs);
848
849 /* Free the fstab filename */
850 free(fstab->fstab_filename);
851
852 /* Free fstab */
853 free(fstab);
854}
855
856/* Add an entry to the fstab, and return 0 on success or -1 on error */
857int fs_mgr_add_entry(struct fstab *fstab,
858 const char *mount_point, const char *fs_type,
Sasha Levitskiycdc1cfb2014-04-10 17:10:21 -0700859 const char *blk_device)
Colin Cross5edee2a2014-01-23 14:22:48 -0800860{
861 struct fstab_rec *new_fstab_recs;
862 int n = fstab->num_entries;
863
864 new_fstab_recs = (struct fstab_rec *)
865 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
866
867 if (!new_fstab_recs) {
868 return -1;
869 }
870
871 /* A new entry was added, so initialize it */
872 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
873 new_fstab_recs[n].mount_point = strdup(mount_point);
874 new_fstab_recs[n].fs_type = strdup(fs_type);
875 new_fstab_recs[n].blk_device = strdup(blk_device);
876 new_fstab_recs[n].length = 0;
877
878 /* Update the fstab struct */
879 fstab->recs = new_fstab_recs;
880 fstab->num_entries++;
881
882 return 0;
883}
884
JP Abgrall5c01dac2014-06-18 14:54:37 -0700885/*
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800886 * Returns the fstab_rec* whose mount_point is path.
887 * Returns nullptr if not found.
JP Abgrall5c01dac2014-06-18 14:54:37 -0700888 */
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800889struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800890 if (!fstab) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800891 return nullptr;
Colin Cross5edee2a2014-01-23 14:22:48 -0800892 }
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800893 for (int i = 0; i < fstab->num_entries; i++) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800894 if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800895 return &fstab->recs[i];
896 }
897 }
Bowgo Tsaicc323952017-09-26 18:03:23 +0800898 return nullptr;
JP Abgralla794f862014-06-17 16:58:46 -0700899}
900
Bowgo Tsai5ee7dae2018-05-16 18:33:44 +0800901std::set<std::string> fs_mgr_get_boot_devices() {
902 // boot_devices can be specified in device tree.
903 std::string dt_value;
904 std::string file_name = get_android_dt_dir() + "/boot_devices";
905 if (read_dt_file(file_name, &dt_value)) {
906 auto boot_devices = android::base::Split(dt_value, ",");
907 return std::set<std::string>(boot_devices.begin(), boot_devices.end());
908 }
909
910 // Fallback to extract boot devices from fstab.
911 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
912 fs_mgr_free_fstab);
913 if (fstab) return extract_boot_devices(*fstab);
914
915 return {};
916}
917
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000918int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800919{
920 return fstab->fs_mgr_flags & MF_VOLDMANAGED;
921}
922
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000923int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800924{
925 return fstab->fs_mgr_flags & MF_NONREMOVABLE;
926}
927
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000928int fs_mgr_is_verified(const struct fstab_rec *fstab)
Paul Lawrencebbb36312014-10-09 14:22:49 +0000929{
930 return fstab->fs_mgr_flags & MF_VERIFY;
931}
932
Bowgo Tsai80d1ad12017-04-13 13:05:42 +0800933int fs_mgr_is_avb(const struct fstab_rec *fstab)
934{
935 return fstab->fs_mgr_flags & MF_AVB;
936}
937
Sandeep Patil05ff38b2017-02-16 17:04:11 -0800938int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
939{
940 return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
941}
942
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000943int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800944{
Paul Lawrenceb262d682015-10-29 10:31:02 -0700945 return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
Colin Cross5edee2a2014-01-23 14:22:48 -0800946}
947
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000948int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
949{
950 return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
951}
952
Eric Biggersb478f702017-02-02 14:46:24 -0800953void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
954 const char **contents_mode_ret,
955 const char **filenames_mode_ret)
Paul Lawrence4e898a02016-05-24 04:56:37 -0700956{
Eric Biggersb478f702017-02-02 14:46:24 -0800957 *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes,
958 fstab->file_contents_mode);
959 *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes,
960 fstab->file_names_mode);
Paul Lawrence4e898a02016-05-24 04:56:37 -0700961}
962
Paul Lawrenceb262d682015-10-29 10:31:02 -0700963int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
964{
965 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
966}
967
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000968int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800969{
970 return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
971}
JP Abgrallfe6fcc42015-03-05 17:30:53 -0800972
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700973int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
JP Abgrallfe6fcc42015-03-05 17:30:53 -0800974 return fstab->fs_mgr_flags & MF_NOTRIM;
975}
Ed Tame498c7c2015-04-13 18:01:33 -0700976
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700977int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
Chris Fries79f33842013-09-05 13:19:21 -0500978 return fstab->fs_mgr_flags & (MF_FORMATTABLE);
979}
Daniel Rosenbergeb65ce02015-09-01 12:41:18 -0700980
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700981int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
Daniel Rosenberg8bb2f362015-08-27 13:42:20 -0700982 return fstab->fs_mgr_flags & MF_SLOTSELECT;
983}
Daniel Rosenberge3a32882016-04-12 14:28:09 -0700984
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700985int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -0700986 return fstab->fs_mgr_flags & MF_NOFAIL;
987}
Wei Wangd61a7e22016-08-23 11:58:09 -0700988
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700989int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
Wei Wangd61a7e22016-08-23 11:58:09 -0700990 return fstab->fs_mgr_flags & MF_LATEMOUNT;
991}
Jeff Sharkey6d896102016-12-14 12:00:51 -0700992
Eric Biggers8d3bcd42017-07-05 12:21:15 -0700993int fs_mgr_is_quota(const struct fstab_rec* fstab) {
Jeff Sharkey6d896102016-12-14 12:00:51 -0700994 return fstab->fs_mgr_flags & MF_QUOTA;
995}
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800996
997int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
998{
999 return fstab->fs_mgr_flags & MF_SYSFS;
1000}