Merge "liblp: Allocate "b" extents in the second half of super."
diff --git a/adb/Android.bp b/adb/Android.bp
index e994075..ae8e386 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -25,7 +25,6 @@
         "-Wvla",
     ],
     rtti: true,
-    cpp_std: "gnu++17",
 
     use_version_lib: true,
 
@@ -72,7 +71,7 @@
                 "-DUNICODE=1",
                 "-D_UNICODE=1",
 
-                // -std=gnu++11 doesn't set _GNU_SOURCE on Windows.
+                // Unlike on Linux, -std=gnu++ doesn't set _GNU_SOURCE on Windows.
                 "-D_GNU_SOURCE",
 
                 // MinGW hides some things behind _POSIX_SOURCE.
diff --git a/adb/NOTICE b/adb/NOTICE
index ff47c95..9ffcc08 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,63 +189,3 @@
 
    END OF TERMS AND CONDITIONS
 
-------------------------------------------------------------
-libwinpthread license:
-------------------------------------------------------------
-Copyright (c) 2011 mingw-w64 project
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-
-/*
- * Parts of this library are derived by:
- *
- * Posix Threads library for Microsoft Windows
- *
- * Use at own risk, there is no implied warranty to this code.
- * It uses undocumented features of Microsoft Windows that can change
- * at any time in the future.
- *
- * (C) 2010 Lockless Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *
- *  * Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *  * Neither the name of Lockless Inc. nor the names of its contributors may be
- *    used to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
diff --git a/adb/transport.cpp b/adb/transport.cpp
index c2d4917..8741654 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -764,6 +764,10 @@
 #if ADB_HOST
         if (t->IsTcpDevice() && !t->kicked()) {
             D("transport: %s unref (attempting reconnection)", t->serial.c_str());
+
+            // We need to clear the transport's keys, so that on the next connection, it tries
+            // again from the beginning.
+            t->ResetKeys();
             reconnect_handler.TrackTransport(t);
         } else {
             D("transport: %s unref (kicking and closing)", t->serial.c_str());
@@ -1009,14 +1013,11 @@
 const FeatureSet& supported_features() {
     // Local static allocation to avoid global non-POD variables.
     static const FeatureSet* features = new FeatureSet{
-        kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir,
-#if ADB_HOST
-                kFeatureApex
-#endif
-        // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
-        // to know about. Otherwise, the client can be stuck running an old
-        // version of the server even after upgrading their copy of adb.
-        // (http://b/24370690)
+            kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir, kFeatureApex
+            // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
+            // to know about. Otherwise, the client can be stuck running an old
+            // version of the server even after upgrading their copy of adb.
+            // (http://b/24370690)
     };
 
     return *features;
@@ -1331,10 +1332,20 @@
 
 #if ADB_HOST
 std::shared_ptr<RSA> atransport::NextKey() {
-    if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+    if (keys_.empty()) {
+        LOG(INFO) << "fetching keys for transport " << this->serial_name();
+        keys_ = adb_auth_get_private_keys();
+
+        // We should have gotten at least one key: the one that's automatically generated.
+        CHECK(!keys_.empty());
+    }
 
     std::shared_ptr<RSA> result = keys_[0];
     keys_.pop_front();
     return result;
 }
+
+void atransport::ResetKeys() {
+    keys_.clear();
+}
 #endif
diff --git a/adb/transport.h b/adb/transport.h
index 9894bdf..d593700 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -258,6 +258,7 @@
 
 #if ADB_HOST
     std::shared_ptr<RSA> NextKey();
+    void ResetKeys();
 #endif
 
     char token[TOKEN_SIZE] = {};
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 4e3879b..4e6c879 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <dirent.h>
 #include <fcntl.h>
 
 #if !defined(_WIN32)
@@ -231,3 +232,13 @@
 template <typename T>
 int close(const android::base::unique_fd_impl<T>&)
     __attribute__((__unavailable__("close called on unique_fd")));
+
+template <typename T>
+FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
+    __attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
+                                   "unique_fd, or use android::base::Fdopen to pass ownership")));
+
+template <typename T>
+DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
+    __unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
+                    "unique_fd, or use android::base::Fdopendir to pass ownership")));
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 03b3287..d9fae52 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -9,7 +9,6 @@
         "-Wno-nullability-completeness",
         "-Os",
     ],
-    cpp_std: "gnu++17",
 
     local_include_dirs: ["include"],
 }
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 8006c41..ead2105 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -144,8 +144,6 @@
     static_libs: [
         "libhealthhalutils",
     ],
-
-    cpp_std: "c++17",
 }
 
 cc_defaults {
@@ -212,7 +210,6 @@
     name: "libfastboot",
     defaults: ["fastboot_host_defaults"],
 
-    cpp_std: "c++17",
     srcs: [
         "bootimg_utils.cpp",
         "fastboot.cpp",
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index f150af3..99231ac 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -25,9 +25,6 @@
         "-Werror",
         "-Wno-unused-variable",
     ],
-    cppflags: [
-        "-std=gnu++1z",
-    ],
 }
 
 cc_library {
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index d715d7b..2d42d6c 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -89,4 +89,9 @@
   if higher than 4.6.
 - *adb enable-verity* will free up overlayfs and as a bonus the
   device will be reverted pristine to before any content was updated.
+- If dynamic partitions runs out of space, resizing a logical
+  partition larger may fail because of the scratch partition.
+  If this happens, either fastboot flashall or adb enable-verity can
+  be used to clear scratch storage to permit the flash.
+  Then reinstate the overrides and continue.
 - File bugs or submit fixes for review.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6f863ad..750ed71 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1411,89 +1411,74 @@
     return 0;
 }
 
-/* This must be called after mount_all, because the mkswap command needs to be
- * available.
- */
-int fs_mgr_swapon_all(fstab* fstab) {
-    int i = 0;
-    int flags = 0;
-    int err = 0;
-    int ret = 0;
-    int status;
-    const char *mkswap_argv[2] = {
-        MKSWAP_BIN,
-        nullptr
-    };
-
-    if (!fstab) {
-        return -1;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        /* Skip non-swap entries */
-        if (strcmp(fstab->recs[i].fs_type, "swap")) {
+bool fs_mgr_swapon_all(const Fstab& fstab) {
+    bool ret = true;
+    for (const auto& entry : fstab) {
+        // Skip non-swap entries.
+        if (entry.fs_type != "swap") {
             continue;
         }
 
-        if (fstab->recs[i].zram_size > 0) {
-            /* A zram_size was specified, so we need to configure the
-             * device.  There is no point in having multiple zram devices
-             * on a system (all the memory comes from the same pool) so
-             * we can assume the device number is 0.
-             */
-            if (fstab->recs[i].max_comp_streams >= 0) {
+        if (entry.zram_size > 0) {
+            // A zram_size was specified, so we need to configure the
+            // device.  There is no point in having multiple zram devices
+            // on a system (all the memory comes from the same pool) so
+            // we can assume the device number is 0.
+            if (entry.max_comp_streams >= 0) {
                 auto zram_mcs_fp = std::unique_ptr<FILE, decltype(&fclose)>{
                         fopen(ZRAM_CONF_MCS, "re"), fclose};
-                if (zram_mcs_fp == NULL) {
+                if (zram_mcs_fp == nullptr) {
                     LERROR << "Unable to open zram conf comp device " << ZRAM_CONF_MCS;
-                    ret = -1;
+                    ret = false;
                     continue;
                 }
-                fprintf(zram_mcs_fp.get(), "%d\n", fstab->recs[i].max_comp_streams);
+                fprintf(zram_mcs_fp.get(), "%d\n", entry.max_comp_streams);
             }
 
             auto zram_fp =
                     std::unique_ptr<FILE, decltype(&fclose)>{fopen(ZRAM_CONF_DEV, "re+"), fclose};
-            if (zram_fp == NULL) {
+            if (zram_fp == nullptr) {
                 LERROR << "Unable to open zram conf device " << ZRAM_CONF_DEV;
-                ret = -1;
+                ret = false;
                 continue;
             }
-            fprintf(zram_fp.get(), "%" PRId64 "\n", fstab->recs[i].zram_size);
+            fprintf(zram_fp.get(), "%" PRId64 "\n", entry.zram_size);
         }
 
-        if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
-            !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
-            LERROR << "Skipping mkswap for '" << fstab->recs[i].blk_device << "'";
-            ret = -1;
+        if (entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(entry.blk_device, 20s)) {
+            LERROR << "Skipping mkswap for '" << entry.blk_device << "'";
+            ret = false;
             continue;
         }
 
-        /* Initialize the swap area */
-        mkswap_argv[1] = fstab->recs[i].blk_device;
-        err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv),
-                                      const_cast<char **>(mkswap_argv),
-                                      &status, true, LOG_KLOG, false, NULL,
-                                      NULL, 0);
+        // Initialize the swap area.
+        const char* mkswap_argv[2] = {
+                MKSWAP_BIN,
+                entry.blk_device.c_str(),
+        };
+        int err = 0;
+        int status;
+        err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), const_cast<char**>(mkswap_argv),
+                                      &status, true, LOG_KLOG, false, nullptr, nullptr, 0);
         if (err) {
-            LERROR << "mkswap failed for " << fstab->recs[i].blk_device;
-            ret = -1;
+            LERROR << "mkswap failed for " << entry.blk_device;
+            ret = false;
             continue;
         }
 
         /* If -1, then no priority was specified in fstab, so don't set
          * SWAP_FLAG_PREFER or encode the priority */
-        if (fstab->recs[i].swap_prio >= 0) {
-            flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
-                    SWAP_FLAG_PRIO_MASK;
+        int flags = 0;
+        if (entry.swap_prio >= 0) {
+            flags = (entry.swap_prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK;
             flags |= SWAP_FLAG_PREFER;
         } else {
             flags = 0;
         }
-        err = swapon(fstab->recs[i].blk_device, flags);
+        err = swapon(entry.blk_device.c_str(), flags);
         if (err) {
-            LERROR << "swapon failed for " << fstab->recs[i].blk_device;
-            ret = -1;
+            LERROR << "swapon failed for " << entry.blk_device;
+            ret = false;
         }
     }
 
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 52eeb83..31b0944 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -38,21 +38,21 @@
 const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
 
 struct fs_mgr_flag_values {
-    char *key_loc;
-    char* key_dir;
-    char *verity_loc;
-    char *sysfs_path;
-    off64_t part_length;
-    char *label;
-    int partnum;
-    int swap_prio;
-    int max_comp_streams;
-    off64_t zram_size;
-    off64_t reserved_size;
-    int file_contents_mode;
-    int file_names_mode;
-    off64_t erase_blk_size;
-    off64_t logical_blk_size;
+    std::string key_loc;
+    std::string key_dir;
+    std::string verity_loc;
+    std::string sysfs_path;
+    off64_t part_length = 0;
+    std::string label;
+    int partnum = -1;
+    int swap_prio = -1;
+    int max_comp_streams = 0;
+    off64_t zram_size = 0;
+    off64_t reserved_size = 0;
+    int file_contents_mode = 0;
+    int file_names_mode = 0;
+    off64_t erase_blk_size = 0;
+    off64_t logical_blk_size = 0;
 };
 
 struct flag_list {
@@ -209,14 +209,6 @@
     char *p;
     char *savep;
 
-    /* initialize flag values.  If we find a relevant flag, we'll
-     * update the value */
-    if (flag_vals) {
-        memset(flag_vals, 0, sizeof(*flag_vals));
-        flag_vals->partnum = -1;
-        flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
-    }
-
     /* initialize fs_options to the null string */
     if (fs_options && (fs_options_len > 0)) {
         fs_options[0] = '\0';
@@ -242,22 +234,22 @@
                     /* The encryptable flag is followed by an = and the
                      * location of the keys.  Get it and return it.
                      */
-                    flag_vals->key_loc = strdup(arg);
+                    flag_vals->key_loc = arg;
                 } else if (flag == MF_VERIFY) {
                     /* If the verify flag is followed by an = and the
                      * location for the verity state,  get it and return it.
                      */
-                    flag_vals->verity_loc = strdup(arg);
+                    flag_vals->verity_loc = arg;
                 } else if (flag == MF_FORCECRYPT) {
                     /* The forceencrypt flag is followed by an = and the
                      * location of the keys.  Get it and return it.
                      */
-                    flag_vals->key_loc = strdup(arg);
+                    flag_vals->key_loc = arg;
                 } else if (flag == MF_FORCEFDEORFBE) {
                     /* The forcefdeorfbe flag is followed by an = and the
                      * location of the keys.  Get it and return it.
                      */
-                    flag_vals->key_loc = strdup(arg);
+                    flag_vals->key_loc = arg;
                     flag_vals->file_contents_mode = EM_AES_256_XTS;
                     flag_vals->file_names_mode = EM_AES_256_CTS;
                 } else if (flag == MF_FILEENCRYPTION) {
@@ -285,7 +277,7 @@
                     /* The metadata flag is followed by an = and the
                      * directory for the keys.  Get it and return it.
                      */
-                    flag_vals->key_dir = strdup(arg);
+                    flag_vals->key_dir = arg;
                 } else if (flag == MF_LENGTH) {
                     /* The length flag is followed by an = and the
                      * size of the partition.  Get it and return it.
@@ -302,8 +294,7 @@
                     auto label_end = strchr(label_start, ':');
 
                     if (label_end) {
-                        flag_vals->label = strndup(label_start,
-                                                   (int) (label_end - label_start));
+                        flag_vals->label = std::string(label_start, (int)(label_end - label_start));
                         auto part_start = label_end + 1;
                         if (!strcmp(part_start, "auto")) {
                             flag_vals->partnum = -1;
@@ -347,7 +338,7 @@
                         flag_vals->logical_blk_size = val;
                 } else if (flag == MF_SYSFS) {
                     /* The path to trigger device gc by idle-maint of vold. */
-                    flag_vals->sysfs_path = strdup(arg);
+                    flag_vals->sysfs_path = arg;
                 }
                 break;
             }
@@ -504,49 +495,17 @@
     return false;
 }
 
-static struct fstab* fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts) {
-    int cnt, entries;
+static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {
     ssize_t len;
     size_t alloc_len = 0;
     char *line = NULL;
     const char *delim = " \t";
     char *save_ptr, *p;
-    struct fstab *fstab = NULL;
+    Fstab fstab;
     struct fs_mgr_flag_values flag_vals;
 #define FS_OPTIONS_LEN 1024
     char tmp_fs_options[FS_OPTIONS_LEN];
 
-    entries = 0;
-    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
-        /* if the last character is a newline, shorten the string by 1 byte */
-        if (line[len - 1] == '\n') {
-            line[len - 1] = '\0';
-        }
-        /* Skip any leading whitespace */
-        p = line;
-        while (isspace(*p)) {
-            p++;
-        }
-        /* ignore comments or empty lines */
-        if (*p == '#' || *p == '\0')
-            continue;
-        entries++;
-    }
-
-    if (!entries) {
-        LERROR << "No entries found in fstab";
-        goto err;
-    }
-
-    /* Allocate and init the fstab structure */
-    fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
-    fstab->num_entries = entries;
-    fstab->recs = static_cast<struct fstab_rec *>(
-        calloc(fstab->num_entries, sizeof(struct fstab_rec)));
-
-    fseek(fstab_file, 0, SEEK_SET);
-
-    cnt = 0;
     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
         if (line[len - 1] == '\n') {
@@ -562,46 +521,36 @@
         if (*p == '#' || *p == '\0')
             continue;
 
-        /* If a non-comment entry is greater than the size we allocated, give an
-         * error and quit.  This can happen in the unlikely case the file changes
-         * between the two reads.
-         */
-        if (cnt >= entries) {
-            LERROR << "Tried to process more entries than counted";
-            break;
-        }
+        FstabEntry entry;
 
         if (!(p = strtok_r(line, delim, &save_ptr))) {
             LERROR << "Error parsing mount source";
             goto err;
         }
-        fstab->recs[cnt].blk_device = strdup(p);
+        entry.blk_device = p;
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             LERROR << "Error parsing mount_point";
             goto err;
         }
-        fstab->recs[cnt].mount_point = strdup(p);
+        entry.mount_point = p;
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             LERROR << "Error parsing fs_type";
             goto err;
         }
-        fstab->recs[cnt].fs_type = strdup(p);
+        entry.fs_type = p;
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             LERROR << "Error parsing mount_flags";
             goto err;
         }
         tmp_fs_options[0] = '\0';
-        fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
-                                       tmp_fs_options, FS_OPTIONS_LEN);
+        entry.flags = parse_flags(p, mount_flags, NULL, tmp_fs_options, FS_OPTIONS_LEN);
 
         /* fs_options are optional */
         if (tmp_fs_options[0]) {
-            fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
-        } else {
-            fstab->recs[cnt].fs_options = NULL;
+            entry.fs_options = tmp_fs_options;
         }
 
         // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
@@ -611,78 +560,47 @@
             LERROR << "Error parsing fs_mgr_options";
             goto err;
         }
-        fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
-                                                    &flag_vals, NULL, 0);
-        fstab->recs[cnt].key_loc = flag_vals.key_loc;
-        fstab->recs[cnt].key_dir = flag_vals.key_dir;
-        fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
-        fstab->recs[cnt].length = flag_vals.part_length;
-        fstab->recs[cnt].label = flag_vals.label;
-        fstab->recs[cnt].partnum = flag_vals.partnum;
-        fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
-        fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
-        fstab->recs[cnt].zram_size = flag_vals.zram_size;
-        fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
-        fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
-        fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
-        fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
-        fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
-        fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
-        if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) {
-            fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device);
+        entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0);
+
+        entry.key_loc = std::move(flag_vals.key_loc);
+        entry.key_dir = std::move(flag_vals.key_dir);
+        entry.verity_loc = std::move(flag_vals.verity_loc);
+        entry.length = flag_vals.part_length;
+        entry.label = std::move(flag_vals.label);
+        entry.partnum = flag_vals.partnum;
+        entry.swap_prio = flag_vals.swap_prio;
+        entry.max_comp_streams = flag_vals.max_comp_streams;
+        entry.zram_size = flag_vals.zram_size;
+        entry.reserved_size = flag_vals.reserved_size;
+        entry.file_contents_mode = flag_vals.file_contents_mode;
+        entry.file_names_mode = flag_vals.file_names_mode;
+        entry.erase_blk_size = flag_vals.erase_blk_size;
+        entry.logical_blk_size = flag_vals.logical_blk_size;
+        entry.sysfs_path = std::move(flag_vals.sysfs_path);
+        if (entry.fs_mgr_flags.logical) {
+            entry.logical_partition_name = entry.blk_device;
         }
 
-        cnt++;
+        fstab.emplace_back(std::move(entry));
     }
+
+    if (fstab.empty()) {
+        LERROR << "No entries found in fstab";
+        goto err;
+    }
+
     /* If an A/B partition, modify block device to be the real block device */
-    if (!fs_mgr_update_for_slotselect(fstab)) {
+    if (!fs_mgr_update_for_slotselect(&fstab)) {
         LERROR << "Error updating for slotselect";
         goto err;
     }
     free(line);
-    return fstab;
+    *fstab_out = std::move(fstab);
+    return true;
 
 err:
     free(line);
-    if (fstab)
-        fs_mgr_free_fstab(fstab);
-    return NULL;
-}
-
-/* merges fstab entries from both a and b, then returns the merged result.
- * note that the caller should only manage the return pointer without
- * doing further memory management for the two inputs, i.e. only need to
- * frees up memory of the return value without touching a and b. */
-static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
-{
-    if (!a && !b) return nullptr;
-    if (!a) return b;
-    if (!b) return a;
-
-    int total_entries = a->num_entries + b->num_entries;
-    a->recs = static_cast<struct fstab_rec *>(realloc(
-        a->recs, total_entries * (sizeof(struct fstab_rec))));
-    if (!a->recs) {
-        LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
-        // If realloc() fails the original block is left untouched;
-        // it is not freed or moved. So we have to free both a and b here.
-        fs_mgr_free_fstab(a);
-        fs_mgr_free_fstab(b);
-        return nullptr;
-    }
-
-    for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
-        // Copy the structs by assignment.
-        a->recs[i] = b->recs[j];
-    }
-
-    // We can't call fs_mgr_free_fstab because a->recs still references the
-    // memory allocated by strdup.
-    free(b->recs);
-    free(b);
-
-    a->num_entries = total_entries;
-    return a;
+    return false;
 }
 
 /* Extracts <device>s from the by-name symlinks specified in a fstab:
@@ -695,11 +613,11 @@
  *   /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
  * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
  */
-static std::set<std::string> extract_boot_devices(const fstab& fstab) {
+static std::set<std::string> extract_boot_devices(const Fstab& fstab) {
     std::set<std::string> boot_devices;
 
-    for (int i = 0; i < fstab.num_entries; i++) {
-        std::string blk_device(fstab.recs[i].blk_device);
+    for (const auto& entry : fstab) {
+        std::string blk_device = entry.blk_device;
         // Skips blk_device that doesn't conform to the format.
         if (!android::base::StartsWith(blk_device, "/dev/block") ||
             android::base::StartsWith(blk_device, "/dev/block/by-name") ||
@@ -728,33 +646,36 @@
     return boot_devices;
 }
 
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
-{
-    struct fstab *fstab;
-
-    auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fstab_path, "re"), fclose};
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
+    auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
     if (!fstab_file) {
-        PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
+        PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
+        return false;
+    }
+
+    if (!fs_mgr_read_fstab_file(fstab_file.get(), path == "/proc/mounts", fstab)) {
+        LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
+        return false;
+    }
+
+    return true;
+}
+
+struct fstab* fs_mgr_read_fstab(const char* fstab_path) {
+    Fstab fstab;
+    if (!ReadFstabFromFile(fstab_path, &fstab)) {
         return nullptr;
     }
 
-    fstab = fs_mgr_read_fstab_file(fstab_file.get(), !strcmp("/proc/mounts", fstab_path));
-    if (!fstab) {
-        LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
-    }
-
-    return fstab;
+    return FstabToLegacyFstab(fstab);
 }
 
-/* Returns fstab entries parsed from the device tree if they
- * exist
- */
-struct fstab *fs_mgr_read_fstab_dt()
-{
+// Returns fstab entries parsed from the device tree if they exist
+bool ReadFstabFromDt(Fstab* fstab) {
     std::string fstab_buf = read_fstab_from_dt();
     if (fstab_buf.empty()) {
         LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
-        return nullptr;
+        return false;
     }
 
     std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
@@ -762,16 +683,25 @@
                  fstab_buf.length(), "r"), fclose);
     if (!fstab_file) {
         PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
+        return false;
+    }
+
+    if (!fs_mgr_read_fstab_file(fstab_file.get(), false, fstab)) {
+        LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
+               << std::endl << fstab_buf;
+        return false;
+    }
+
+    return true;
+}
+
+struct fstab* fs_mgr_read_fstab_dt() {
+    Fstab fstab;
+    if (!ReadFstabFromDt(&fstab)) {
         return nullptr;
     }
 
-    struct fstab* fstab = fs_mgr_read_fstab_file(fstab_file.get(), false);
-    if (!fstab) {
-        LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
-               << std::endl << fstab_buf;
-    }
-
-    return fstab;
+    return FstabToLegacyFstab(fstab);
 }
 
 /*
@@ -797,32 +727,42 @@
     return std::string();
 }
 
-/*
- * loads the fstab file and combines with fstab entries passed in from device tree.
- */
-struct fstab *fs_mgr_read_fstab_default()
-{
-    std::string default_fstab;
+// Loads the fstab file and combines with fstab entries passed in from device tree.
+bool ReadDefaultFstab(Fstab* fstab) {
+    Fstab dt_fstab;
+    ReadFstabFromDt(&dt_fstab);
 
+    *fstab = std::move(dt_fstab);
+
+    std::string default_fstab_path;
     // Use different fstab paths for normal boot and recovery boot, respectively
     if (access("/system/bin/recovery", F_OK) == 0) {
-        default_fstab = "/etc/recovery.fstab";
+        default_fstab_path = "/etc/recovery.fstab";
     } else {  // normal boot
-        default_fstab = get_fstab_path();
+        default_fstab_path = get_fstab_path();
     }
 
-    struct fstab* fstab = nullptr;
-    if (!default_fstab.empty()) {
-        fstab = fs_mgr_read_fstab(default_fstab.c_str());
+    Fstab default_fstab;
+    if (!default_fstab_path.empty()) {
+        ReadFstabFromFile(default_fstab_path, &default_fstab);
     } else {
         LINFO << __FUNCTION__ << "(): failed to find device default fstab";
     }
 
-    struct fstab* fstab_dt = fs_mgr_read_fstab_dt();
+    for (auto&& entry : default_fstab) {
+        fstab->emplace_back(std::move(entry));
+    }
 
-    // combines fstab entries passed in from device tree with
-    // the ones found from default_fstab file
-    return in_place_merge(fstab_dt, fstab);
+    return !fstab->empty();
+}
+
+struct fstab* fs_mgr_read_fstab_default() {
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        return nullptr;
+    }
+
+    return FstabToLegacyFstab(fstab);
 }
 
 void fs_mgr_free_fstab(struct fstab *fstab)
@@ -908,11 +848,83 @@
     }
 
     // Fallback to extract boot devices from fstab.
-    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
-                                                               fs_mgr_free_fstab);
-    if (fstab) return extract_boot_devices(*fstab);
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        return {};
+    }
 
-    return {};
+    return extract_boot_devices(fstab);
+}
+
+FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
+    FstabEntry entry;
+    entry.blk_device = fstab_rec->blk_device;
+    entry.logical_partition_name = fstab_rec->logical_partition_name;
+    entry.mount_point = fstab_rec->mount_point;
+    entry.fs_type = fstab_rec->fs_type;
+    entry.flags = fstab_rec->flags;
+    entry.fs_options = fstab_rec->fs_options;
+    entry.fs_mgr_flags.val = fstab_rec->fs_mgr_flags;
+    entry.key_loc = fstab_rec->key_loc;
+    entry.key_dir = fstab_rec->key_dir;
+    entry.verity_loc = fstab_rec->verity_loc;
+    entry.length = fstab_rec->length;
+    entry.label = fstab_rec->label;
+    entry.partnum = fstab_rec->partnum;
+    entry.swap_prio = fstab_rec->swap_prio;
+    entry.max_comp_streams = fstab_rec->max_comp_streams;
+    entry.zram_size = fstab_rec->zram_size;
+    entry.reserved_size = fstab_rec->reserved_size;
+    entry.file_contents_mode = fstab_rec->file_contents_mode;
+    entry.file_names_mode = fstab_rec->file_names_mode;
+    entry.erase_blk_size = fstab_rec->erase_blk_size;
+    entry.logical_blk_size = fstab_rec->logical_blk_size;
+    entry.sysfs_path = fstab_rec->sysfs_path;
+
+    return entry;
+}
+
+Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab) {
+    Fstab fstab;
+    for (int i = 0; i < legacy_fstab->num_entries; i++) {
+        fstab.emplace_back(FstabRecToFstabEntry(&legacy_fstab->recs[i]));
+    }
+
+    return fstab;
+}
+
+fstab* FstabToLegacyFstab(const Fstab& fstab) {
+    struct fstab* legacy_fstab = static_cast<struct fstab*>(calloc(1, sizeof(struct fstab)));
+    legacy_fstab->num_entries = fstab.size();
+    legacy_fstab->recs =
+            static_cast<fstab_rec*>(calloc(legacy_fstab->num_entries, sizeof(fstab_rec)));
+
+    for (int i = 0; i < legacy_fstab->num_entries; i++) {
+        legacy_fstab->recs[i].blk_device = strdup(fstab[i].blk_device.c_str());
+        legacy_fstab->recs[i].logical_partition_name =
+                strdup(fstab[i].logical_partition_name.c_str());
+        legacy_fstab->recs[i].mount_point = strdup(fstab[i].mount_point.c_str());
+        legacy_fstab->recs[i].fs_type = strdup(fstab[i].fs_type.c_str());
+        legacy_fstab->recs[i].flags = fstab[i].flags;
+        legacy_fstab->recs[i].fs_options = strdup(fstab[i].fs_options.c_str());
+        legacy_fstab->recs[i].fs_mgr_flags = fstab[i].fs_mgr_flags.val;
+        legacy_fstab->recs[i].key_loc = strdup(fstab[i].key_loc.c_str());
+        legacy_fstab->recs[i].key_dir = strdup(fstab[i].key_dir.c_str());
+        legacy_fstab->recs[i].verity_loc = strdup(fstab[i].verity_loc.c_str());
+        legacy_fstab->recs[i].length = fstab[i].length;
+        legacy_fstab->recs[i].label = strdup(fstab[i].label.c_str());
+        legacy_fstab->recs[i].partnum = fstab[i].partnum;
+        legacy_fstab->recs[i].swap_prio = fstab[i].swap_prio;
+        legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
+        legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
+        legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
+        legacy_fstab->recs[i].file_contents_mode = fstab[i].file_contents_mode;
+        legacy_fstab->recs[i].file_names_mode = fstab[i].file_names_mode;
+        legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
+        legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
+        legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
+    }
+    return legacy_fstab;
 }
 
 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 20652ad..57e984d 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -675,14 +675,26 @@
         }
         changed = true;
     }
-    // Take half of free space, minimum 512MB or free space - 256KB margin.
+    // Take half of free space, minimum 512MB or maximum free - margin.
     static constexpr auto kMinimumSize = uint64_t(512 * 1024 * 1024);
-    static constexpr auto kMarginSize = uint64_t(256 * 1024);
     if (partition->size() < kMinimumSize) {
         auto partition_size =
                 builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
         if ((partition_size > kMinimumSize) || !partition->size()) {
-            partition_size = std::max(std::min(kMinimumSize, partition_size - kMarginSize),
+            // Leave some space for free space jitter of a few erase
+            // blocks, in case they are needed for any individual updates
+            // to any other partition that needs to be flashed while
+            // overlayfs is in force.  Of course if margin_size is not
+            // enough could normally get a flash failure, so
+            // ResizePartition() will delete the scratch partition in
+            // order to fulfill.  Deleting scratch will destroy all of
+            // the adb remount overrides :-( .
+            auto margin_size = uint64_t(3 * 256 * 1024);
+            BlockDeviceInfo info;
+            if (builder->GetBlockDeviceInfo(partition_name, &info)) {
+                margin_size = 3 * info.logical_block_size;
+            }
+            partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
                                       partition_size / 2);
             if (partition_size > partition->size()) {
                 if (!builder->ResizePartition(partition, partition_size)) {
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 87c971a..711446c 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -22,6 +22,7 @@
 
 #include <android-base/logging.h>
 #include <fs_mgr.h>
+#include <fstab/fstab.h>
 
 #include "fs_mgr_priv_boot_config.h"
 
@@ -130,7 +131,7 @@
                           FileWaitMode wait_mode = FileWaitMode::Exists);
 
 int fs_mgr_set_blk_ro(const char* blockdev);
-bool fs_mgr_update_for_slotselect(fstab* fstab);
+bool fs_mgr_update_for_slotselect(Fstab* fstab);
 bool fs_mgr_is_device_unlocked();
 const std::string& get_android_dt_dir();
 bool is_dt_compatible();
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index 3b01d0e..20d60ae 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -31,36 +31,23 @@
 }
 
 // Updates |fstab| for slot_suffix. Returns true on success, false on error.
-bool fs_mgr_update_for_slotselect(struct fstab *fstab) {
+bool fs_mgr_update_for_slotselect(Fstab* fstab) {
     int n;
     std::string ab_suffix;
 
-    for (n = 0; n < fstab->num_entries; n++) {
-        fstab_rec& record = fstab->recs[n];
-        if (record.fs_mgr_flags & MF_SLOTSELECT) {
-            if (ab_suffix.empty()) {
-                ab_suffix = fs_mgr_get_slot_suffix();
-                // Return false if failed to get ab_suffix when MF_SLOTSELECT is specified.
-                if (ab_suffix.empty()) return false;
-            }
-
-            char* new_blk_device;
-            if (asprintf(&new_blk_device, "%s%s", record.blk_device, ab_suffix.c_str()) <= 0) {
-                return false;
-            }
-            free(record.blk_device);
-            record.blk_device = new_blk_device;
-
-            char* new_partition_name;
-            if (record.logical_partition_name) {
-                if (asprintf(&new_partition_name, "%s%s", record.logical_partition_name,
-                             ab_suffix.c_str()) <= 0) {
-                    return false;
-                }
-                free(record.logical_partition_name);
-                record.logical_partition_name = new_partition_name;
-            }
+    for (auto& entry : *fstab) {
+        if (!entry.fs_mgr_flags.slot_select) {
+            continue;
         }
+
+        if (ab_suffix.empty()) {
+            ab_suffix = fs_mgr_get_slot_suffix();
+            // Return false if failed to get ab_suffix when MF_SLOTSELECT is specified.
+            if (ab_suffix.empty()) return false;
+        }
+
+        entry.blk_device = entry.blk_device + ab_suffix;
+        entry.logical_partition_name = entry.logical_partition_name + ab_suffix;
     }
     return true;
 }
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 5dabe76..80f97fc 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -78,7 +78,7 @@
 void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
 bool fs_mgr_load_verity_state(int* mode);
 bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback);
-int fs_mgr_swapon_all(struct fstab *fstab);
+bool fs_mgr_swapon_all(const Fstab& fstab);
 bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
 
 int fs_mgr_do_format(fstab_rec* fstab, bool reserve_footer);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index da13899..80bdb87 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_TAB_H
-#define __CORE_FS_TAB_H
+#pragma once
 
 #include <linux/dm-ioctl.h>
 #include <stdbool.h>
@@ -25,6 +24,7 @@
 
 #include <set>
 #include <string>
+#include <vector>
 
 /*
  * The entries must be kept in the same order as they were seen in the fstab.
@@ -95,4 +95,82 @@
 std::string fs_mgr_get_slot_suffix();
 std::set<std::string> fs_mgr_get_boot_devices();
 
-#endif /* __CORE_FS_TAB_H */
+struct FstabEntry {
+    std::string blk_device;
+    std::string logical_partition_name;
+    std::string mount_point;
+    std::string fs_type;
+    unsigned long flags = 0;
+    std::string fs_options;
+    std::string key_loc;
+    std::string key_dir;
+    std::string verity_loc;
+    off64_t length = 0;
+    std::string label;
+    int partnum = -1;
+    int swap_prio = -1;
+    int max_comp_streams = 0;
+    off64_t zram_size = 0;
+    off64_t reserved_size = 0;
+    int file_contents_mode = 0;
+    int file_names_mode = 0;
+    off64_t erase_blk_size = 0;
+    off64_t logical_blk_size = 0;
+    std::string sysfs_path;
+
+    // TODO: Remove this union once fstab_rec is deprecated. It only serves as a
+    // convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
+    union {
+        int val;
+        struct {
+            bool wait : 1;
+            bool check : 1;
+            bool crypt : 1;
+            bool nonremovable : 1;
+            bool vold_managed : 1;
+            bool length : 1;
+            bool recovery_only : 1;
+            bool swap_prio : 1;
+            bool zram_size : 1;
+            bool verify : 1;
+            bool force_crypt : 1;
+            bool no_emulated_sd : 1;  // No emulated sdcard daemon; sd card is the only external
+                                      // storage.
+            bool no_trim : 1;
+            bool file_encryption : 1;
+            bool formattable : 1;
+            bool slot_select : 1;
+            bool force_fde_or_fbe : 1;
+            bool late_mount : 1;
+            bool no_fail : 1;
+            bool verify_at_boot : 1;
+            bool max_comp_streams : 1;
+            bool reserved_size : 1;
+            bool quota : 1;
+            bool erase_blk_size : 1;
+            bool logical_blk_size : 1;
+            bool avb : 1;
+            bool key_directory : 1;
+            bool sysfs : 1;
+            bool logical : 1;
+            bool checkpoint_blk : 1;
+            bool checkpoint_fs : 1;
+        };
+    } fs_mgr_flags;
+
+    bool is_encryptable() const {
+        return fs_mgr_flags.crypt || fs_mgr_flags.force_crypt || fs_mgr_flags.force_fde_or_fbe;
+    }
+};
+
+// An Fstab is a collection of FstabEntry structs.
+using Fstab = std::vector<FstabEntry>;
+
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
+bool ReadFstabFromDt(Fstab* fstab);
+bool ReadDefaultFstab(Fstab* fstab);
+
+// Temporary conversion functions.
+FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
+Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
+fstab* FstabToLegacyFstab(const Fstab& fstab);
diff --git a/init/Android.mk b/init/Android.mk
index 69f1d87..0e6ee0b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -35,7 +35,6 @@
     -Wall -Wextra \
     -Wno-unused-parameter \
     -Werror \
-    -std=gnu++1z \
 
 # --
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 6eb65b2..b382126 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -612,14 +612,15 @@
 }
 
 static Result<Success> do_swapon_all(const BuiltinArguments& args) {
-    struct fstab *fstab;
-    int ret;
+    Fstab fstab;
+    if (!ReadFstabFromFile(args[1], &fstab)) {
+        return Error() << "Could not read fstab '" << args[1] << "'";
+    }
 
-    fstab = fs_mgr_read_fstab(args[1].c_str());
-    ret = fs_mgr_swapon_all(fstab);
-    fs_mgr_free_fstab(fstab);
+    if (!fs_mgr_swapon_all(fstab)) {
+        return Error() << "fs_mgr_swapon_all() failed";
+    }
 
-    if (ret != 0) return Error() << "fs_mgr_swapon_all() failed";
     return Success();
 }
 
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 70f6faa..6637deb 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -12,5 +12,6 @@
         "-Werror",
     ],
     stl: "none",
+    system_shared_libs: [],
     export_include_dirs: ["include"],
 }
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 4576776..d10f7c1 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,6 +5,7 @@
     export ANDROID_ASSETS /system/app
     export ANDROID_DATA /data
     export ANDROID_STORAGE /storage
+    export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
     export EXTERNAL_STORAGE /sdcard
     export ASEC_MOUNTPOINT /mnt/asec
     export BOOTCLASSPATH %BOOTCLASSPATH%