blob: 13e2fd092edcbd348926587a33fd8a65a1bf9ec9 [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>
Tom Cherry7e34f752019-01-22 15:37:08 -080027#include <array>
Bowgo Tsai80281892017-12-12 00:47:43 +080028#include <utility>
29#include <vector>
30
Sandeep Patilc20c0c22017-02-23 16:09:34 -080031#include <android-base/file.h>
Jaegeuk Kim2aedc822018-11-20 13:27:06 -080032#include <android-base/parseint.h>
Sandeep Patilc20c0c22017-02-23 16:09:34 -080033#include <android-base/stringprintf.h>
34#include <android-base/strings.h>
David Anderson0e330f12019-01-03 18:16:56 -080035#include <libgsi/libgsi.h>
Sandeep Patilc20c0c22017-02-23 16:09:34 -080036
Colin Cross5edee2a2014-01-23 14:22:48 -080037#include "fs_mgr_priv.h"
38
Tom Cherry6bbe9472018-12-13 10:58:37 -080039using android::base::Split;
Tom Marshall66f6a6d2018-03-06 16:19:18 +010040using android::base::StartsWith;
41
Yu Ningc01022a2017-07-26 17:54:08 +080042const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
43
Colin Cross5edee2a2014-01-23 14:22:48 -080044struct fs_mgr_flag_values {
Tom Cherryd0be7a52018-11-29 13:04:52 -080045 std::string key_loc;
46 std::string key_dir;
47 std::string verity_loc;
48 std::string sysfs_path;
Jaegeuk Kim2aedc822018-11-20 13:27:06 -080049 std::string zram_loopback_path;
50 uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default
51 std::string zram_backing_dev_path;
Tom Cherryd0be7a52018-11-29 13:04:52 -080052 off64_t part_length = 0;
53 std::string label;
54 int partnum = -1;
55 int swap_prio = -1;
56 int max_comp_streams = 0;
57 off64_t zram_size = 0;
58 off64_t reserved_size = 0;
Tom Cherry7e34f752019-01-22 15:37:08 -080059 std::string file_contents_mode;
60 std::string file_names_mode;
Tom Cherryd0be7a52018-11-29 13:04:52 -080061 off64_t erase_blk_size = 0;
62 off64_t logical_blk_size = 0;
Tom Cherryde545a42018-12-12 10:57:23 -080063 std::string vbmeta_partition;
Colin Cross5edee2a2014-01-23 14:22:48 -080064};
65
66struct flag_list {
67 const char *name;
Bowgo Tsai4c80edf2018-12-12 23:21:13 +080068 uint64_t flag;
Colin Cross5edee2a2014-01-23 14:22:48 -080069};
70
71static struct flag_list mount_flags[] = {
72 { "noatime", MS_NOATIME },
73 { "noexec", MS_NOEXEC },
74 { "nosuid", MS_NOSUID },
75 { "nodev", MS_NODEV },
76 { "nodiratime", MS_NODIRATIME },
77 { "ro", MS_RDONLY },
78 { "rw", 0 },
79 { "remount", MS_REMOUNT },
80 { "bind", MS_BIND },
81 { "rec", MS_REC },
82 { "unbindable", MS_UNBINDABLE },
83 { "private", MS_PRIVATE },
84 { "slave", MS_SLAVE },
85 { "shared", MS_SHARED },
86 { "defaults", 0 },
87 { 0, 0 },
88};
89
90static struct flag_list fs_mgr_flags[] = {
Daniel Rosenberg4c93b252018-08-28 01:41:18 -070091 {"wait", MF_WAIT},
92 {"check", MF_CHECK},
93 {"encryptable=", MF_CRYPT},
94 {"forceencrypt=", MF_FORCECRYPT},
95 {"fileencryption=", MF_FILEENCRYPTION},
96 {"forcefdeorfbe=", MF_FORCEFDEORFBE},
97 {"keydirectory=", MF_KEYDIRECTORY},
98 {"nonremovable", MF_NONREMOVABLE},
99 {"voldmanaged=", MF_VOLDMANAGED},
100 {"length=", MF_LENGTH},
101 {"recoveryonly", MF_RECOVERYONLY},
102 {"swapprio=", MF_SWAPPRIO},
103 {"zramsize=", MF_ZRAMSIZE},
104 {"max_comp_streams=", MF_MAX_COMP_STREAMS},
105 {"verifyatboot", MF_VERIFYATBOOT},
106 {"verify", MF_VERIFY},
107 {"avb", MF_AVB},
Tom Cherryde545a42018-12-12 10:57:23 -0800108 {"avb=", MF_AVB},
Daniel Rosenberg4c93b252018-08-28 01:41:18 -0700109 {"noemulatedsd", MF_NOEMULATEDSD},
110 {"notrim", MF_NOTRIM},
111 {"formattable", MF_FORMATTABLE},
112 {"slotselect", MF_SLOTSELECT},
113 {"nofail", MF_NOFAIL},
Tom Cherrye68bf852018-10-25 16:10:23 -0700114 {"first_stage_mount", MF_FIRST_STAGE_MOUNT},
Daniel Rosenberg4c93b252018-08-28 01:41:18 -0700115 {"latemount", MF_LATEMOUNT},
116 {"reservedsize=", MF_RESERVEDSIZE},
117 {"quota", MF_QUOTA},
118 {"eraseblk=", MF_ERASEBLKSIZE},
119 {"logicalblk=", MF_LOGICALBLKSIZE},
120 {"sysfs_path=", MF_SYSFS},
121 {"defaults", 0},
122 {"logical", MF_LOGICAL},
123 {"checkpoint=block", MF_CHECKPOINT_BLK},
124 {"checkpoint=fs", MF_CHECKPOINT_FS},
Bowgo Tsai4c80edf2018-12-12 23:21:13 +0800125 {"slotselect_other", MF_SLOTSELECT_OTHER},
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800126 {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
127 {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
128 {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
Leo Liou0b721d32019-01-15 20:43:37 +0800129 {"fsverity", MF_FS_VERITY},
Daniel Rosenberg4c93b252018-08-28 01:41:18 -0700130 {0, 0},
Colin Cross5edee2a2014-01-23 14:22:48 -0800131};
132
Tom Cherryfafbb642018-11-29 13:24:09 -0800133static off64_t calculate_zram_size(unsigned int percentage) {
134 off64_t total;
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700135
136 total = sysconf(_SC_PHYS_PAGES);
137 total *= percentage;
138 total /= 100;
139
140 total *= sysconf(_SC_PAGESIZE);
141
142 return total;
143}
144
Tom Cherryfafbb642018-11-29 13:24:09 -0800145static off64_t parse_size(const char* arg) {
liminghao9a0fd1d2016-07-22 11:48:14 +0800146 char *endptr;
Tom Cherryfafbb642018-11-29 13:24:09 -0800147 off64_t size = strtoll(arg, &endptr, 10);
liminghao9a0fd1d2016-07-22 11:48:14 +0800148 if (*endptr == 'k' || *endptr == 'K')
149 size *= 1024LL;
150 else if (*endptr == 'm' || *endptr == 'M')
151 size *= 1024LL * 1024LL;
152 else if (*endptr == 'g' || *endptr == 'G')
153 size *= 1024LL * 1024LL * 1024LL;
154
155 return size;
156}
157
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800158/* fills 'dt_value' with the underlying device tree value string without
159 * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
160 * otherwise.
161 */
162static bool read_dt_file(const std::string& file_name, std::string* dt_value)
163{
164 if (android::base::ReadFileToString(file_name, dt_value)) {
165 if (!dt_value->empty()) {
166 // trim the trailing '\0' out, otherwise the comparison
167 // will produce false-negatives.
168 dt_value->resize(dt_value->size() - 1);
169 return true;
170 }
171 }
172
173 return false;
174}
175
Tom Cherry7e34f752019-01-22 15:37:08 -0800176const static std::array<const char*, 3> kFileContentsEncryptionMode = {
177 "aes-256-xts",
178 "adiantum",
179 "ice",
180};
181
182const static std::array<const char*, 3> kFileNamesEncryptionMode = {
183 "aes-256-cts",
184 "aes-256-heh",
185 "adiantum",
186};
187
188static void ParseFileEncryption(const std::string& arg, struct fs_mgr_flag_values* flag_vals) {
189 // The fileencryption flag is followed by an = and the mode of contents encryption, then
190 // optionally a and the mode of filenames encryption (defaults to aes-256-cts). Get it and
191 // return it.
192
193 auto parts = Split(arg, ":");
194 if (parts.empty() || parts.size() > 2) {
195 LWARNING << "Warning: fileencryption= flag malformed: " << arg;
196 return;
197 }
198
199 // Alias for backwards compatibility.
200 if (parts[0] == "software") {
201 parts[0] = "aes-256-xts";
202 }
203
204 if (std::find(kFileContentsEncryptionMode.begin(), kFileContentsEncryptionMode.end(),
205 parts[0]) == kFileContentsEncryptionMode.end()) {
206 LWARNING << "fileencryption= flag malformed, file contents encryption mode not found: "
207 << arg;
208 return;
209 }
210
211 flag_vals->file_contents_mode = parts[0];
212
213 if (parts.size() == 2) {
214 if (std::find(kFileNamesEncryptionMode.begin(), kFileNamesEncryptionMode.end(), parts[1]) ==
215 kFileNamesEncryptionMode.end()) {
216 LWARNING << "fileencryption= flag malformed, file names encryption mode not found: "
217 << arg;
218 return;
219 }
220
221 flag_vals->file_names_mode = parts[1];
222 } else if (flag_vals->file_contents_mode == "adiantum") {
223 flag_vals->file_names_mode = "adiantum";
224 } else {
225 flag_vals->file_names_mode = "aes-256-cts";
226 }
227}
228
Bowgo Tsai4c80edf2018-12-12 23:21:13 +0800229static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals,
Bowgo Tsaifa416f92019-01-07 15:30:27 +0800230 std::string* fs_options) {
Bowgo Tsai4c80edf2018-12-12 23:21:13 +0800231 uint64_t f = 0;
Colin Cross5edee2a2014-01-23 14:22:48 -0800232 int i;
233 char *p;
234 char *savep;
235
Colin Cross5edee2a2014-01-23 14:22:48 -0800236 p = strtok_r(flags, ",", &savep);
237 while (p) {
238 /* Look for the flag "p" in the flag list "fl"
239 * If not found, the loop exits with fl[i].name being null.
240 */
241 for (i = 0; fl[i].name; i++) {
Mark Salyzyneba47062018-06-20 13:07:28 -0700242 auto name = fl[i].name;
243 auto len = strlen(name);
244 auto end = len;
245 if (name[end - 1] == '=') --end;
246 if (!strncmp(p, name, len) && (p[end] == name[end])) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800247 f |= fl[i].flag;
Mark Salyzyneba47062018-06-20 13:07:28 -0700248 if (!flag_vals) break;
249 if (p[end] != '=') break;
250 char* arg = p + end + 1;
251 auto flag = fl[i].flag;
252 if (flag == MF_CRYPT) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800253 /* The encryptable flag is followed by an = and the
254 * location of the keys. Get it and return it.
255 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800256 flag_vals->key_loc = arg;
Mark Salyzyneba47062018-06-20 13:07:28 -0700257 } else if (flag == MF_VERIFY) {
Sami Tolvanen946a0f32015-03-22 12:40:05 +0000258 /* If the verify flag is followed by an = and the
259 * location for the verity state, get it and return it.
260 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800261 flag_vals->verity_loc = arg;
Mark Salyzyneba47062018-06-20 13:07:28 -0700262 } else if (flag == MF_FORCECRYPT) {
Paul Lawrence2e5ae0a2014-04-04 09:34:19 -0700263 /* The forceencrypt flag is followed by an = and the
264 * location of the keys. Get it and return it.
265 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800266 flag_vals->key_loc = arg;
Mark Salyzyneba47062018-06-20 13:07:28 -0700267 } else if (flag == MF_FORCEFDEORFBE) {
Paul Lawrenceb262d682015-10-29 10:31:02 -0700268 /* The forcefdeorfbe flag is followed by an = and the
269 * location of the keys. Get it and return it.
270 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800271 flag_vals->key_loc = arg;
Tom Cherry7e34f752019-01-22 15:37:08 -0800272 flag_vals->file_contents_mode = "aes-256-xts";
273 flag_vals->file_names_mode = "aes-256-cts";
Mark Salyzyneba47062018-06-20 13:07:28 -0700274 } else if (flag == MF_FILEENCRYPTION) {
Tom Cherry7e34f752019-01-22 15:37:08 -0800275 ParseFileEncryption(arg, flag_vals);
Mark Salyzyneba47062018-06-20 13:07:28 -0700276 } else if (flag == MF_KEYDIRECTORY) {
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700277 /* The metadata flag is followed by an = and the
278 * directory for the keys. Get it and return it.
279 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800280 flag_vals->key_dir = arg;
Mark Salyzyneba47062018-06-20 13:07:28 -0700281 } else if (flag == MF_LENGTH) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800282 /* The length flag is followed by an = and the
283 * size of the partition. Get it and return it.
284 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700285 flag_vals->part_length = strtoll(arg, NULL, 0);
286 } else if (flag == MF_VOLDMANAGED) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800287 /* The voldmanaged flag is followed by an = and the
288 * label, a colon and the partition number or the
289 * word "auto", e.g.
290 * voldmanaged=sdcard:3
291 * Get and return them.
292 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700293 auto label_start = arg;
294 auto label_end = strchr(label_start, ':');
Colin Cross5edee2a2014-01-23 14:22:48 -0800295
Colin Cross5edee2a2014-01-23 14:22:48 -0800296 if (label_end) {
Tom Cherryd0be7a52018-11-29 13:04:52 -0800297 flag_vals->label = std::string(label_start, (int)(label_end - label_start));
Mark Salyzyneba47062018-06-20 13:07:28 -0700298 auto part_start = label_end + 1;
Colin Cross5edee2a2014-01-23 14:22:48 -0800299 if (!strcmp(part_start, "auto")) {
300 flag_vals->partnum = -1;
301 } else {
302 flag_vals->partnum = strtol(part_start, NULL, 0);
303 }
304 } else {
bowgotsai47878de2017-01-23 14:04:34 +0800305 LERROR << "Warning: voldmanaged= flag malformed";
Colin Cross5edee2a2014-01-23 14:22:48 -0800306 }
Mark Salyzyneba47062018-06-20 13:07:28 -0700307 } else if (flag == MF_SWAPPRIO) {
308 flag_vals->swap_prio = strtoll(arg, NULL, 0);
309 } else if (flag == MF_MAX_COMP_STREAMS) {
310 flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
Tom Cherryde545a42018-12-12 10:57:23 -0800311 } else if (flag == MF_AVB) {
312 flag_vals->vbmeta_partition = arg;
Mark Salyzyneba47062018-06-20 13:07:28 -0700313 } else if (flag == MF_ZRAMSIZE) {
314 auto is_percent = !!strrchr(arg, '%');
315 auto val = strtoll(arg, NULL, 0);
Iliyan Malchev3ea902f2015-05-01 14:05:04 -0700316 if (is_percent)
317 flag_vals->zram_size = calculate_zram_size(val);
318 else
319 flag_vals->zram_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700320 } else if (flag == MF_RESERVEDSIZE) {
liminghao9a0fd1d2016-07-22 11:48:14 +0800321 /* The reserved flag is followed by an = and the
322 * reserved size of the partition. Get it and return it.
323 */
Mark Salyzyneba47062018-06-20 13:07:28 -0700324 flag_vals->reserved_size = parse_size(arg);
325 } else if (flag == MF_ERASEBLKSIZE) {
Connor O'Brien46fec482017-01-24 17:50:39 -0800326 /* The erase block size flag is followed by an = and the flash
327 * erase block size. Get it, check that it is a power of 2 and
328 * at least 4096, and return it.
329 */
Tom Cherryfafbb642018-11-29 13:24:09 -0800330 auto val = strtoll(arg, nullptr, 0);
Connor O'Brien46fec482017-01-24 17:50:39 -0800331 if (val >= 4096 && (val & (val - 1)) == 0)
332 flag_vals->erase_blk_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700333 } else if (flag == MF_LOGICALBLKSIZE) {
Connor O'Brien46fec482017-01-24 17:50:39 -0800334 /* The logical block size flag is followed by an = and the flash
335 * logical block size. Get it, check that it is a power of 2 and
336 * at least 4096, and return it.
337 */
Tom Cherryfafbb642018-11-29 13:24:09 -0800338 auto val = strtoll(arg, nullptr, 0);
Connor O'Brien46fec482017-01-24 17:50:39 -0800339 if (val >= 4096 && (val & (val - 1)) == 0)
340 flag_vals->logical_blk_size = val;
Mark Salyzyneba47062018-06-20 13:07:28 -0700341 } else if (flag == MF_SYSFS) {
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800342 /* The path to trigger device gc by idle-maint of vold. */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800343 flag_vals->sysfs_path = arg;
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800344 } else if (flag == MF_ZRAM_LOOPBACK_PATH) {
345 /* The path to use loopback for zram. */
346 flag_vals->zram_loopback_path = arg;
347 } else if (flag == MF_ZRAM_LOOPBACK_SIZE) {
348 if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) {
349 LERROR << "Warning: zram_loopback_size = flag malformed";
350 }
351 } else if (flag == MF_ZRAM_BACKING_DEV_PATH) {
352 /* The path to use loopback for zram. */
353 flag_vals->zram_backing_dev_path = arg;
Colin Cross5edee2a2014-01-23 14:22:48 -0800354 }
355 break;
356 }
357 }
358
359 if (!fl[i].name) {
360 if (fs_options) {
Bowgo Tsaifa416f92019-01-07 15:30:27 +0800361 // It's not a known flag, so it must be a filesystem specific
362 // option. Add it to fs_options if it was passed in.
363 if (!fs_options->empty()) {
364 fs_options->append(","); // appends a comma if not the first
365 }
366 fs_options->append(p);
Colin Cross5edee2a2014-01-23 14:22:48 -0800367 } else {
Bowgo Tsaifa416f92019-01-07 15:30:27 +0800368 // fs_options was not passed in, so if the flag is unknown it's an error.
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 return f;
376}
377
Yu Ningc01022a2017-07-26 17:54:08 +0800378static std::string init_android_dt_dir() {
379 std::string android_dt_dir;
380 // The platform may specify a custom Android DT path in kernel cmdline
381 if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
382 // Fall back to the standard procfs-based path
383 android_dt_dir = kDefaultAndroidDtDir;
384 }
385 return android_dt_dir;
386}
387
388// FIXME: The same logic is duplicated in system/core/init/
389const std::string& get_android_dt_dir() {
390 // Set once and saves time for subsequent calls to this function
391 static const std::string kAndroidDtDir = init_android_dt_dir();
392 return kAndroidDtDir;
393}
394
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800395static bool is_dt_fstab_compatible() {
396 std::string dt_value;
Yu Ningc01022a2017-07-26 17:54:08 +0800397 std::string file_name = get_android_dt_dir() + "/fstab/compatible";
Tom Cherry1eb04562018-11-06 10:42:09 -0800398
399 if (read_dt_file(file_name, &dt_value) && dt_value == "android,fstab") {
400 // If there's no status property or its set to "ok" or "okay", then we use the DT fstab.
401 std::string status_value;
402 std::string status_file_name = get_android_dt_dir() + "/fstab/status";
403 return !read_dt_file(status_file_name, &status_value) || status_value == "ok" ||
404 status_value == "okay";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800405 }
406
407 return false;
408}
409
410static std::string read_fstab_from_dt() {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800411 if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
Bowgo Tsai80281892017-12-12 00:47:43 +0800412 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800413 }
414
Yu Ningc01022a2017-07-26 17:54:08 +0800415 std::string fstabdir_name = get_android_dt_dir() + "/fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800416 std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
Bowgo Tsai80281892017-12-12 00:47:43 +0800417 if (!fstabdir) return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800418
419 dirent* dp;
Bowgo Tsai80281892017-12-12 00:47:43 +0800420 // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
421 std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800422 while ((dp = readdir(fstabdir.get())) != NULL) {
Bowgo Tsai06ed6132017-06-08 10:43:41 +0800423 // skip over name, compatible and .
424 if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800425
426 // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
427 std::vector<std::string> fstab_entry;
428 std::string file_name;
429 std::string value;
Sandeep Patilbe4302b2017-05-26 18:09:06 -0700430 // skip a partition entry if the status property is present and not set to ok
431 file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
432 if (read_dt_file(file_name, &value)) {
433 if (value != "okay" && value != "ok") {
434 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
435 continue;
436 }
437 }
438
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800439 file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800440 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800441 LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800442 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800443 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800444 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800445
446 std::string mount_point;
447 file_name =
448 android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
449 if (read_dt_file(file_name, &value)) {
450 LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
451 mount_point = value;
452 } else {
453 mount_point = android::base::StringPrintf("/%s", dp->d_name);
454 }
455 fstab_entry.push_back(mount_point);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800456
457 file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800458 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800459 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800460 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800461 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800462 fstab_entry.push_back(value);
463
464 file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800465 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800466 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800467 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800468 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800469 fstab_entry.push_back(value);
470
471 file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800472 if (!read_dt_file(file_name, &value)) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800473 LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
Bowgo Tsai80281892017-12-12 00:47:43 +0800474 return {};
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800475 }
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800476 fstab_entry.push_back(value);
Bowgo Tsai80281892017-12-12 00:47:43 +0800477 // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
478 fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800479 }
480
Bowgo Tsai80281892017-12-12 00:47:43 +0800481 // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
482 std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
483 [](const auto& a, const auto& b) { return a.first < b.first; });
484
485 std::string fstab_result;
486 for (const auto& [_, dt_entry] : fstab_dt_entries) {
487 fstab_result += dt_entry + "\n";
488 }
489 return fstab_result;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800490}
491
Sandeep Patile396c602017-02-24 11:04:49 -0800492bool is_dt_compatible() {
Yu Ningc01022a2017-07-26 17:54:08 +0800493 std::string file_name = get_android_dt_dir() + "/compatible";
Sandeep Patile396c602017-02-24 11:04:49 -0800494 std::string dt_value;
Sandeep Patil4cd9a462017-02-24 13:03:39 -0800495 if (read_dt_file(file_name, &dt_value)) {
496 if (dt_value == "android,firmware") {
497 return true;
Sandeep Patile396c602017-02-24 11:04:49 -0800498 }
499 }
500
501 return false;
502}
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800503
Tom Cherryd0be7a52018-11-29 13:04:52 -0800504static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800505 ssize_t len;
506 size_t alloc_len = 0;
507 char *line = NULL;
508 const char *delim = " \t";
509 char *save_ptr, *p;
Tom Cherryd0be7a52018-11-29 13:04:52 -0800510 Fstab fstab;
Colin Cross5edee2a2014-01-23 14:22:48 -0800511 struct fs_mgr_flag_values flag_vals;
Colin Cross5edee2a2014-01-23 14:22:48 -0800512
Colin Cross5edee2a2014-01-23 14:22:48 -0800513 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
514 /* if the last character is a newline, shorten the string by 1 byte */
515 if (line[len - 1] == '\n') {
516 line[len - 1] = '\0';
517 }
518
519 /* Skip any leading whitespace */
520 p = line;
521 while (isspace(*p)) {
522 p++;
523 }
524 /* ignore comments or empty lines */
525 if (*p == '#' || *p == '\0')
526 continue;
527
Tom Cherryd0be7a52018-11-29 13:04:52 -0800528 FstabEntry entry;
Colin Cross5edee2a2014-01-23 14:22:48 -0800529
530 if (!(p = strtok_r(line, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800531 LERROR << "Error parsing mount source";
Colin Cross5edee2a2014-01-23 14:22:48 -0800532 goto err;
533 }
Tom Cherryd0be7a52018-11-29 13:04:52 -0800534 entry.blk_device = p;
Colin Cross5edee2a2014-01-23 14:22:48 -0800535
536 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800537 LERROR << "Error parsing mount_point";
Colin Cross5edee2a2014-01-23 14:22:48 -0800538 goto err;
539 }
Tom Cherryd0be7a52018-11-29 13:04:52 -0800540 entry.mount_point = p;
Colin Cross5edee2a2014-01-23 14:22:48 -0800541
542 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800543 LERROR << "Error parsing fs_type";
Colin Cross5edee2a2014-01-23 14:22:48 -0800544 goto err;
545 }
Tom Cherryd0be7a52018-11-29 13:04:52 -0800546 entry.fs_type = p;
Colin Cross5edee2a2014-01-23 14:22:48 -0800547
548 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800549 LERROR << "Error parsing mount_flags";
Colin Cross5edee2a2014-01-23 14:22:48 -0800550 goto err;
551 }
Bowgo Tsaifa416f92019-01-07 15:30:27 +0800552 entry.flags = parse_flags(p, mount_flags, nullptr, &entry.fs_options);
Colin Cross5edee2a2014-01-23 14:22:48 -0800553
Mark Salyzyneba47062018-06-20 13:07:28 -0700554 // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
555 if (proc_mounts) {
556 p += strlen(p);
557 } else if (!(p = strtok_r(NULL, delim, &save_ptr))) {
bowgotsai47878de2017-01-23 14:04:34 +0800558 LERROR << "Error parsing fs_mgr_options";
Colin Cross5edee2a2014-01-23 14:22:48 -0800559 goto err;
560 }
Bowgo Tsaifa416f92019-01-07 15:30:27 +0800561 entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, nullptr);
Tom Cherryd0be7a52018-11-29 13:04:52 -0800562
563 entry.key_loc = std::move(flag_vals.key_loc);
564 entry.key_dir = std::move(flag_vals.key_dir);
565 entry.verity_loc = std::move(flag_vals.verity_loc);
566 entry.length = flag_vals.part_length;
567 entry.label = std::move(flag_vals.label);
568 entry.partnum = flag_vals.partnum;
569 entry.swap_prio = flag_vals.swap_prio;
570 entry.max_comp_streams = flag_vals.max_comp_streams;
571 entry.zram_size = flag_vals.zram_size;
572 entry.reserved_size = flag_vals.reserved_size;
Tom Cherry7e34f752019-01-22 15:37:08 -0800573 entry.file_contents_mode = std::move(flag_vals.file_contents_mode);
574 entry.file_names_mode = std::move(flag_vals.file_names_mode);
Tom Cherryd0be7a52018-11-29 13:04:52 -0800575 entry.erase_blk_size = flag_vals.erase_blk_size;
576 entry.logical_blk_size = flag_vals.logical_blk_size;
577 entry.sysfs_path = std::move(flag_vals.sysfs_path);
Tom Cherryde545a42018-12-12 10:57:23 -0800578 entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition);
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800579 entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path);
580 entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size);
581 entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path);
Tom Cherryd0be7a52018-11-29 13:04:52 -0800582 if (entry.fs_mgr_flags.logical) {
583 entry.logical_partition_name = entry.blk_device;
David Anderson62e5b202018-05-01 17:09:17 -0700584 }
585
Tom Cherryd0be7a52018-11-29 13:04:52 -0800586 fstab.emplace_back(std::move(entry));
Colin Cross5edee2a2014-01-23 14:22:48 -0800587 }
Tom Cherryd0be7a52018-11-29 13:04:52 -0800588
589 if (fstab.empty()) {
590 LERROR << "No entries found in fstab";
591 goto err;
592 }
593
David Zeuthen227ef3c2015-09-03 12:23:12 -0400594 /* If an A/B partition, modify block device to be the real block device */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800595 if (!fs_mgr_update_for_slotselect(&fstab)) {
bowgotsai47878de2017-01-23 14:04:34 +0800596 LERROR << "Error updating for slotselect";
David Zeuthen744a8f82015-09-09 18:03:13 -0400597 goto err;
David Zeuthen227ef3c2015-09-03 12:23:12 -0400598 }
Colin Cross5edee2a2014-01-23 14:22:48 -0800599 free(line);
Tom Cherryd0be7a52018-11-29 13:04:52 -0800600 *fstab_out = std::move(fstab);
601 return true;
Colin Cross5edee2a2014-01-23 14:22:48 -0800602
603err:
Colin Cross5edee2a2014-01-23 14:22:48 -0800604 free(line);
Tom Cherryd0be7a52018-11-29 13:04:52 -0800605 return false;
Bowgo Tsai47d34272017-03-06 22:22:07 +0800606}
607
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800608/* Extracts <device>s from the by-name symlinks specified in a fstab:
609 * /dev/block/<type>/<device>/by-name/<partition>
610 *
611 * <type> can be: platform, pci or vbd.
612 *
613 * For example, given the following entries in the input fstab:
614 * /dev/block/platform/soc/1da4000.ufshc/by-name/system
615 * /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
616 * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
617 */
Tom Cherryd0be7a52018-11-29 13:04:52 -0800618static std::set<std::string> extract_boot_devices(const Fstab& fstab) {
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800619 std::set<std::string> boot_devices;
620
Tom Cherryd0be7a52018-11-29 13:04:52 -0800621 for (const auto& entry : fstab) {
622 std::string blk_device = entry.blk_device;
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800623 // Skips blk_device that doesn't conform to the format.
624 if (!android::base::StartsWith(blk_device, "/dev/block") ||
625 android::base::StartsWith(blk_device, "/dev/block/by-name") ||
626 android::base::StartsWith(blk_device, "/dev/block/bootdevice/by-name")) {
627 continue;
628 }
629 // Skips non-by_name blk_device.
630 // /dev/block/<type>/<device>/by-name/<partition>
631 // ^ slash_by_name
632 auto slash_by_name = blk_device.find("/by-name");
633 if (slash_by_name == std::string::npos) continue;
634 blk_device.erase(slash_by_name); // erases /by-name/<partition>
635
636 // Erases /dev/block/, now we have <type>/<device>
637 blk_device.erase(0, std::string("/dev/block/").size());
638
639 // <type>/<device>
640 // ^ first_slash
641 auto first_slash = blk_device.find('/');
642 if (first_slash == std::string::npos) continue;
643
644 auto boot_device = blk_device.substr(first_slash + 1);
645 if (!boot_device.empty()) boot_devices.insert(std::move(boot_device));
646 }
647
648 return boot_devices;
649}
650
David Anderson0e330f12019-01-03 18:16:56 -0800651static void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
652 auto iter = std::remove_if(fstab->begin(), fstab->end(),
653 [&](const auto& entry) { return entry.mount_point == mount_point; });
654 fstab->erase(iter, fstab->end());
655}
656
657static void TransformFstabForGsi(Fstab* fstab) {
658 EraseFstabEntry(fstab, "/system");
659 EraseFstabEntry(fstab, "/data");
660
661 fstab->emplace_back(BuildGsiSystemFstabEntry());
662
663 constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
664
665 FstabEntry userdata = {
666 .blk_device = "userdata_gsi",
667 .mount_point = "/data",
668 .fs_type = "ext4",
669 .flags = kFlags,
670 .reserved_size = 128 * 1024 * 1024,
671 };
672 userdata.fs_mgr_flags.wait = true;
673 userdata.fs_mgr_flags.check = true;
674 userdata.fs_mgr_flags.logical = true;
675 userdata.fs_mgr_flags.quota = true;
676 userdata.fs_mgr_flags.late_mount = true;
677 fstab->emplace_back(userdata);
678}
679
Tom Cherryd0be7a52018-11-29 13:04:52 -0800680bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
681 auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800682 if (!fstab_file) {
Tom Cherryd0be7a52018-11-29 13:04:52 -0800683 PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
684 return false;
685 }
686
David Anderson0e330f12019-01-03 18:16:56 -0800687 bool is_proc_mounts = path == "/proc/mounts";
688
689 if (!fs_mgr_read_fstab_file(fstab_file.get(), is_proc_mounts, fstab)) {
Tom Cherryd0be7a52018-11-29 13:04:52 -0800690 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
691 return false;
692 }
David Anderson0e330f12019-01-03 18:16:56 -0800693 if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
694 TransformFstabForGsi(fstab);
695 }
Tom Cherryd0be7a52018-11-29 13:04:52 -0800696
697 return true;
698}
699
700struct fstab* fs_mgr_read_fstab(const char* fstab_path) {
701 Fstab fstab;
702 if (!ReadFstabFromFile(fstab_path, &fstab)) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800703 return nullptr;
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800704 }
Bowgo Tsai47d34272017-03-06 22:22:07 +0800705
Tom Cherryd0be7a52018-11-29 13:04:52 -0800706 return FstabToLegacyFstab(fstab);
Hung-ying Tyan99c4a8a2016-02-01 15:07:40 +0800707}
708
Tom Cherryd0be7a52018-11-29 13:04:52 -0800709// Returns fstab entries parsed from the device tree if they exist
710bool ReadFstabFromDt(Fstab* fstab) {
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800711 std::string fstab_buf = read_fstab_from_dt();
712 if (fstab_buf.empty()) {
bowgotsai172c1d82017-03-16 10:25:39 +0900713 LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
Tom Cherryd0be7a52018-11-29 13:04:52 -0800714 return false;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800715 }
716
717 std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
718 fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
719 fstab_buf.length(), "r"), fclose);
720 if (!fstab_file) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800721 PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
Tom Cherryd0be7a52018-11-29 13:04:52 -0800722 return false;
723 }
724
725 if (!fs_mgr_read_fstab_file(fstab_file.get(), false, fstab)) {
726 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
727 << std::endl << fstab_buf;
728 return false;
729 }
730
731 return true;
732}
733
734struct fstab* fs_mgr_read_fstab_dt() {
735 Fstab fstab;
736 if (!ReadFstabFromDt(&fstab)) {
Bowgo Tsai47d34272017-03-06 22:22:07 +0800737 return nullptr;
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800738 }
739
Tom Cherryd0be7a52018-11-29 13:04:52 -0800740 return FstabToLegacyFstab(fstab);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800741}
742
Bowgo Tsai46c6dc12017-03-07 18:52:03 +0800743/*
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700744 * Identify path to fstab file. Lookup is based on pattern
745 * fstab.<hardware>, fstab.<hardware.platform> in folders
746 /odm/etc, vendor/etc, or /.
747 */
748static std::string get_fstab_path()
749{
750 for (const char* prop : {"hardware", "hardware.platform"}) {
751 std::string hw;
752
753 if (!fs_mgr_get_boot_config(prop, &hw)) continue;
754
755 for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) {
756 std::string fstab_path = prefix + hw;
757 if (access(fstab_path.c_str(), F_OK) == 0) {
758 return fstab_path;
759 }
760 }
761 }
762
763 return std::string();
764}
765
Tom Cherryd0be7a52018-11-29 13:04:52 -0800766// Loads the fstab file and combines with fstab entries passed in from device tree.
767bool ReadDefaultFstab(Fstab* fstab) {
768 Fstab dt_fstab;
769 ReadFstabFromDt(&dt_fstab);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800770
Tom Cherryd0be7a52018-11-29 13:04:52 -0800771 *fstab = std::move(dt_fstab);
772
773 std::string default_fstab_path;
Bowgo Tsaid05a2f72017-03-28 01:28:29 +0800774 // Use different fstab paths for normal boot and recovery boot, respectively
Jerry Zhang5de2be52018-07-03 16:03:28 -0700775 if (access("/system/bin/recovery", F_OK) == 0) {
Tom Cherryd0be7a52018-11-29 13:04:52 -0800776 default_fstab_path = "/etc/recovery.fstab";
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700777 } else { // normal boot
Tom Cherryd0be7a52018-11-29 13:04:52 -0800778 default_fstab_path = get_fstab_path();
Oleg Matcovschi018d7f62017-10-30 19:26:32 -0700779 }
780
Tom Cherryd0be7a52018-11-29 13:04:52 -0800781 Fstab default_fstab;
782 if (!default_fstab_path.empty()) {
783 ReadFstabFromFile(default_fstab_path, &default_fstab);
Chris Morinb183e052018-01-04 17:59:45 -0800784 } else {
785 LINFO << __FUNCTION__ << "(): failed to find device default fstab";
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800786 }
787
Tom Cherryd0be7a52018-11-29 13:04:52 -0800788 for (auto&& entry : default_fstab) {
789 fstab->emplace_back(std::move(entry));
790 }
Chris Morinb183e052018-01-04 17:59:45 -0800791
Tom Cherryd0be7a52018-11-29 13:04:52 -0800792 return !fstab->empty();
793}
794
795struct fstab* fs_mgr_read_fstab_default() {
796 Fstab fstab;
797 if (!ReadDefaultFstab(&fstab)) {
798 return nullptr;
799 }
800
801 return FstabToLegacyFstab(fstab);
Sandeep Patilc20c0c22017-02-23 16:09:34 -0800802}
803
Colin Cross5edee2a2014-01-23 14:22:48 -0800804void fs_mgr_free_fstab(struct fstab *fstab)
805{
806 int i;
807
808 if (!fstab) {
809 return;
810 }
811
812 for (i = 0; i < fstab->num_entries; i++) {
813 /* Free the pointers return by strdup(3) */
814 free(fstab->recs[i].blk_device);
David Anderson62e5b202018-05-01 17:09:17 -0700815 free(fstab->recs[i].logical_partition_name);
Colin Cross5edee2a2014-01-23 14:22:48 -0800816 free(fstab->recs[i].mount_point);
817 free(fstab->recs[i].fs_type);
818 free(fstab->recs[i].fs_options);
819 free(fstab->recs[i].key_loc);
Paul Lawrence9dbe97b2017-04-21 12:41:48 -0700820 free(fstab->recs[i].key_dir);
Colin Cross5edee2a2014-01-23 14:22:48 -0800821 free(fstab->recs[i].label);
Tom Cherry7e34f752019-01-22 15:37:08 -0800822 free(fstab->recs[i].file_contents_mode);
823 free(fstab->recs[i].file_names_mode);
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -0800824 free(fstab->recs[i].sysfs_path);
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800825 free(fstab->recs[i].zram_loopback_path);
826 free(fstab->recs[i].zram_backing_dev_path);
Colin Cross5edee2a2014-01-23 14:22:48 -0800827 }
828
829 /* Free the fstab_recs array created by calloc(3) */
830 free(fstab->recs);
831
Colin Cross5edee2a2014-01-23 14:22:48 -0800832 /* Free fstab */
833 free(fstab);
834}
835
836/* Add an entry to the fstab, and return 0 on success or -1 on error */
837int fs_mgr_add_entry(struct fstab *fstab,
838 const char *mount_point, const char *fs_type,
Sasha Levitskiycdc1cfb2014-04-10 17:10:21 -0700839 const char *blk_device)
Colin Cross5edee2a2014-01-23 14:22:48 -0800840{
841 struct fstab_rec *new_fstab_recs;
842 int n = fstab->num_entries;
843
844 new_fstab_recs = (struct fstab_rec *)
845 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
846
847 if (!new_fstab_recs) {
848 return -1;
849 }
850
851 /* A new entry was added, so initialize it */
852 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
853 new_fstab_recs[n].mount_point = strdup(mount_point);
854 new_fstab_recs[n].fs_type = strdup(fs_type);
855 new_fstab_recs[n].blk_device = strdup(blk_device);
856 new_fstab_recs[n].length = 0;
857
858 /* Update the fstab struct */
859 fstab->recs = new_fstab_recs;
860 fstab->num_entries++;
861
862 return 0;
863}
864
JP Abgrall5c01dac2014-06-18 14:54:37 -0700865/*
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800866 * Returns the fstab_rec* whose mount_point is path.
867 * Returns nullptr if not found.
JP Abgrall5c01dac2014-06-18 14:54:37 -0700868 */
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800869struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800870 if (!fstab) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800871 return nullptr;
Colin Cross5edee2a2014-01-23 14:22:48 -0800872 }
Bowgo Tsaic55f1882017-09-27 18:00:10 +0800873 for (int i = 0; i < fstab->num_entries; i++) {
Bowgo Tsaicc323952017-09-26 18:03:23 +0800874 if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
Colin Cross5edee2a2014-01-23 14:22:48 -0800875 return &fstab->recs[i];
876 }
877 }
Bowgo Tsaicc323952017-09-26 18:03:23 +0800878 return nullptr;
JP Abgralla794f862014-06-17 16:58:46 -0700879}
880
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800881std::set<std::string> fs_mgr_get_boot_devices() {
Tom Cherry6bbe9472018-12-13 10:58:37 -0800882 // First check the kernel commandline, then try the device tree otherwise
883 std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
884 std::string value;
885 if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) ||
886 read_dt_file(dt_file_name, &value)) {
887 auto boot_devices = Split(value, ",");
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800888 return std::set<std::string>(boot_devices.begin(), boot_devices.end());
889 }
890
891 // Fallback to extract boot devices from fstab.
Tom Cherryd0be7a52018-11-29 13:04:52 -0800892 Fstab fstab;
893 if (!ReadDefaultFstab(&fstab)) {
894 return {};
895 }
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800896
Tom Cherryd0be7a52018-11-29 13:04:52 -0800897 return extract_boot_devices(fstab);
898}
899
900FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
901 FstabEntry entry;
902 entry.blk_device = fstab_rec->blk_device;
903 entry.logical_partition_name = fstab_rec->logical_partition_name;
904 entry.mount_point = fstab_rec->mount_point;
905 entry.fs_type = fstab_rec->fs_type;
906 entry.flags = fstab_rec->flags;
907 entry.fs_options = fstab_rec->fs_options;
908 entry.fs_mgr_flags.val = fstab_rec->fs_mgr_flags;
909 entry.key_loc = fstab_rec->key_loc;
910 entry.key_dir = fstab_rec->key_dir;
911 entry.verity_loc = fstab_rec->verity_loc;
912 entry.length = fstab_rec->length;
913 entry.label = fstab_rec->label;
914 entry.partnum = fstab_rec->partnum;
915 entry.swap_prio = fstab_rec->swap_prio;
916 entry.max_comp_streams = fstab_rec->max_comp_streams;
917 entry.zram_size = fstab_rec->zram_size;
918 entry.reserved_size = fstab_rec->reserved_size;
919 entry.file_contents_mode = fstab_rec->file_contents_mode;
920 entry.file_names_mode = fstab_rec->file_names_mode;
921 entry.erase_blk_size = fstab_rec->erase_blk_size;
922 entry.logical_blk_size = fstab_rec->logical_blk_size;
923 entry.sysfs_path = fstab_rec->sysfs_path;
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800924 entry.zram_loopback_path = fstab_rec->zram_loopback_path;
925 entry.zram_loopback_size = fstab_rec->zram_loopback_size;
926 entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
Tom Cherryd0be7a52018-11-29 13:04:52 -0800927
928 return entry;
929}
930
931Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab) {
932 Fstab fstab;
933 for (int i = 0; i < legacy_fstab->num_entries; i++) {
934 fstab.emplace_back(FstabRecToFstabEntry(&legacy_fstab->recs[i]));
935 }
936
937 return fstab;
938}
939
940fstab* FstabToLegacyFstab(const Fstab& fstab) {
941 struct fstab* legacy_fstab = static_cast<struct fstab*>(calloc(1, sizeof(struct fstab)));
942 legacy_fstab->num_entries = fstab.size();
943 legacy_fstab->recs =
944 static_cast<fstab_rec*>(calloc(legacy_fstab->num_entries, sizeof(fstab_rec)));
945
946 for (int i = 0; i < legacy_fstab->num_entries; i++) {
947 legacy_fstab->recs[i].blk_device = strdup(fstab[i].blk_device.c_str());
948 legacy_fstab->recs[i].logical_partition_name =
949 strdup(fstab[i].logical_partition_name.c_str());
950 legacy_fstab->recs[i].mount_point = strdup(fstab[i].mount_point.c_str());
951 legacy_fstab->recs[i].fs_type = strdup(fstab[i].fs_type.c_str());
952 legacy_fstab->recs[i].flags = fstab[i].flags;
953 legacy_fstab->recs[i].fs_options = strdup(fstab[i].fs_options.c_str());
954 legacy_fstab->recs[i].fs_mgr_flags = fstab[i].fs_mgr_flags.val;
955 legacy_fstab->recs[i].key_loc = strdup(fstab[i].key_loc.c_str());
956 legacy_fstab->recs[i].key_dir = strdup(fstab[i].key_dir.c_str());
957 legacy_fstab->recs[i].verity_loc = strdup(fstab[i].verity_loc.c_str());
958 legacy_fstab->recs[i].length = fstab[i].length;
959 legacy_fstab->recs[i].label = strdup(fstab[i].label.c_str());
960 legacy_fstab->recs[i].partnum = fstab[i].partnum;
961 legacy_fstab->recs[i].swap_prio = fstab[i].swap_prio;
962 legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
963 legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
964 legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
Tom Cherry7e34f752019-01-22 15:37:08 -0800965 legacy_fstab->recs[i].file_contents_mode = strdup(fstab[i].file_contents_mode.c_str());
966 legacy_fstab->recs[i].file_names_mode = strdup(fstab[i].file_names_mode.c_str());
Tom Cherryd0be7a52018-11-29 13:04:52 -0800967 legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
968 legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
969 legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
Jaegeuk Kim2aedc822018-11-20 13:27:06 -0800970 legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
971 legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
972 legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
Tom Cherryd0be7a52018-11-29 13:04:52 -0800973 }
974 return legacy_fstab;
Bowgo Tsai8eec38f2018-05-16 18:33:44 +0800975}
976
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000977int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800978{
979 return fstab->fs_mgr_flags & MF_VOLDMANAGED;
980}
981
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000982int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -0800983{
984 return fstab->fs_mgr_flags & MF_NONREMOVABLE;
985}
986
Paul Lawrencec410b3b2015-03-26 15:49:42 +0000987int fs_mgr_is_verified(const struct fstab_rec *fstab)
Paul Lawrencebbb36312014-10-09 14:22:49 +0000988{
989 return fstab->fs_mgr_flags & MF_VERIFY;
990}
991
Bowgo Tsai80d1ad12017-04-13 13:05:42 +0800992int fs_mgr_is_avb(const struct fstab_rec *fstab)
993{
994 return fstab->fs_mgr_flags & MF_AVB;
995}
996
Sandeep Patil05ff38b2017-02-16 17:04:11 -0800997int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
998{
999 return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
1000}
1001
Paul Lawrencec410b3b2015-03-26 15:49:42 +00001002int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -08001003{
Paul Lawrenceb262d682015-10-29 10:31:02 -07001004 return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
Colin Cross5edee2a2014-01-23 14:22:48 -08001005}
1006
Paul Lawrencec410b3b2015-03-26 15:49:42 +00001007int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
1008{
1009 return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
1010}
1011
Tom Cherry7e34f752019-01-22 15:37:08 -08001012void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
1013 const char** filenames_mode_ret) {
1014 *contents_mode_ret = fstab->file_contents_mode;
1015 *filenames_mode_ret = fstab->file_names_mode;
Paul Lawrence4e898a02016-05-24 04:56:37 -07001016}
1017
Paul Lawrenceb262d682015-10-29 10:31:02 -07001018int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
1019{
1020 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
1021}
1022
Paul Lawrencec410b3b2015-03-26 15:49:42 +00001023int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
Colin Cross5edee2a2014-01-23 14:22:48 -08001024{
1025 return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
1026}
JP Abgrallfe6fcc42015-03-05 17:30:53 -08001027
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001028int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
JP Abgrallfe6fcc42015-03-05 17:30:53 -08001029 return fstab->fs_mgr_flags & MF_NOTRIM;
1030}
Ed Tame498c7c2015-04-13 18:01:33 -07001031
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001032int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
Chris Fries79f33842013-09-05 13:19:21 -05001033 return fstab->fs_mgr_flags & (MF_FORMATTABLE);
1034}
Daniel Rosenbergeb65ce02015-09-01 12:41:18 -07001035
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001036int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
Daniel Rosenberg8bb2f362015-08-27 13:42:20 -07001037 return fstab->fs_mgr_flags & MF_SLOTSELECT;
1038}
Daniel Rosenberge3a32882016-04-12 14:28:09 -07001039
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001040int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
Daniel Rosenbergd38e3c52016-04-07 20:10:25 -07001041 return fstab->fs_mgr_flags & MF_NOFAIL;
1042}
Wei Wangd61a7e22016-08-23 11:58:09 -07001043
Tom Cherrye68bf852018-10-25 16:10:23 -07001044int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab) {
1045 return fstab->fs_mgr_flags & MF_FIRST_STAGE_MOUNT;
1046}
1047
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001048int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
Wei Wangd61a7e22016-08-23 11:58:09 -07001049 return fstab->fs_mgr_flags & MF_LATEMOUNT;
1050}
Jeff Sharkey6d896102016-12-14 12:00:51 -07001051
Eric Biggers8d3bcd42017-07-05 12:21:15 -07001052int fs_mgr_is_quota(const struct fstab_rec* fstab) {
Jeff Sharkey6d896102016-12-14 12:00:51 -07001053 return fstab->fs_mgr_flags & MF_QUOTA;
1054}
Jaegeuk Kimefd3b9c2018-02-22 18:10:05 -08001055
1056int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
1057{
1058 return fstab->fs_mgr_flags & MF_SYSFS;
1059}
David Anderson62e5b202018-05-01 17:09:17 -07001060
1061int fs_mgr_is_logical(const struct fstab_rec* fstab) {
1062 return fstab->fs_mgr_flags & MF_LOGICAL;
1063}
Daniel Rosenberg4c93b252018-08-28 01:41:18 -07001064
1065int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
1066 return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
1067}
1068
1069int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
1070 return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
1071}
1072
1073int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
1074 return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
1075}
David Anderson0e330f12019-01-03 18:16:56 -08001076
Leo Liou0b721d32019-01-15 20:43:37 +08001077int fs_mgr_is_fs_verity(const struct fstab_rec* fstab) {
1078 return fstab->fs_mgr_flags & MF_FS_VERITY;
1079}
1080
David Anderson0e330f12019-01-03 18:16:56 -08001081FstabEntry BuildGsiSystemFstabEntry() {
1082 FstabEntry system = {
1083 .blk_device = "system_gsi",
1084 .mount_point = "/system",
1085 .fs_type = "ext4",
1086 .flags = MS_RDONLY,
1087 .fs_options = "barrier=1",
1088 };
1089 system.fs_mgr_flags.wait = true;
1090 system.fs_mgr_flags.logical = true;
1091 system.fs_mgr_flags.first_stage_mount = true;
1092 return system;
1093}