Add ro.boot.fstab_suffix and modify mount_all to use it

Currently the ReadDefaultFstab function, which calls GetFstabPath,
makes some assumptions about what the fstab will be called and where
it is located. This is being used by vold to set up userdata encryption
and for gsid, and is even used in the default boot control HAL, so it
has become quite baked.

The original way for a board to specify things to mount was to use the
"mount_all /path/to/fstab" command in init.rc. However, due to the
above functionality, the path after mount_all is no longer very useful,
as it cannot differ from the inferred path, or userdata encryption and
other features will be broken.

On Cuttlefish, we have an interest in being able to test alternative
userdata configurations (ext4 vs f2fs, encryption on/off, etc.) and
currently the only way to achieve this is to either a) modify the
ro.hardware or ro.hardware.platform properties, which breaks a bunch
of things like default HAL filenames, or regenerate our odm.img or
vendor.img filesystems. We can't simply install another fstab and
point to it with "mount_all".

This change allows the fstab path to be omitted from "mount_all", and
adds another property which overrides the existing checks for
fstab.${ro.hardware} and fstab.${ro.hardware.platform}. Specifying
${ro.boot.fstab_suffix} will cause fstab.${ro.boot.fstab_suffix}
to be checked first.

Bug: 142424832
Test: booted cuttlefish with 'mount_all ${ro.hardware} --late'
Test: booted cuttlefish with 'mount_all --late'
Test: booted cuttlefish with 'mount_all --late' and fstab_suffix=f2fs
Test: partially booted cuttlefish with 'mount_all ${ro.hardware}'
Test: partially booted cuttlefish with 'mount_all'
Change-Id: I3e10f66aecfcd48bdb9ebf1d304b7aae745cbd3c
diff --git a/init/util.cpp b/init/util.cpp
index f9be055..40f24b1 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -572,6 +572,48 @@
     return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option};
 }
 
+Result<MountAllOptions> ParseMountAll(const std::vector<std::string>& args) {
+    bool compat_mode = false;
+    bool import_rc = false;
+    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
+        if (args.size() <= 1) {
+            return Error() << "mount_all requires at least 1 argument";
+        }
+        compat_mode = true;
+        import_rc = true;
+    }
+
+    std::size_t first_option_arg = args.size();
+    enum mount_mode mode = MOUNT_MODE_DEFAULT;
+
+    // If we are <= Q, then stop looking for non-fstab arguments at slot 2.
+    // Otherwise, stop looking at slot 1 (as the fstab path argument is optional >= R).
+    for (std::size_t na = args.size() - 1; na > (compat_mode ? 1 : 0); --na) {
+        if (args[na] == "--early") {
+            first_option_arg = na;
+            mode = MOUNT_MODE_EARLY;
+        } else if (args[na] == "--late") {
+            first_option_arg = na;
+            mode = MOUNT_MODE_LATE;
+            import_rc = false;
+        }
+    }
+
+    std::string fstab_path;
+    if (first_option_arg > 1) {
+        fstab_path = args[1];
+    } else if (compat_mode) {
+        return Error() << "mount_all argument 1 must be the fstab path";
+    }
+
+    std::vector<std::string> rc_paths;
+    for (std::size_t na = 2; na < first_option_arg; ++na) {
+        rc_paths.push_back(args[na]);
+    }
+
+    return MountAllOptions{rc_paths, fstab_path, mode, import_rc};
+}
+
 Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
         const std::vector<std::string>& args) {
     struct flag_type {
@@ -612,6 +654,15 @@
     return std::pair(flag, paths);
 }
 
+Result<std::string> ParseUmountAll(const std::vector<std::string>& args) {
+    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
+        if (args.size() <= 1) {
+            return Error() << "umount_all requires at least 1 argument";
+        }
+    }
+    return args[1];
+}
+
 static void InitAborter(const char* abort_message) {
     // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
     // simply abort instead of trying to reboot the system.