Merge QP1A.190205.002

Change-Id: I84e5c133130e4d5cbcdef0ebba50c7a220bef366
diff --git a/Android.bp b/Android.bp
index f2012ef..e27f4e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,7 +132,6 @@
         "model/PublicVolume.cpp",
         "model/VolumeBase.cpp",
         "model/StubVolume.cpp",
-        "secontext.cpp",
     ],
     product_variables: {
         arc: {
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 7586a6c..a9bcbf4 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "Checkpoint"
 #include "Checkpoint.h"
+#include "VoldUtil.h"
 
 #include <fstream>
 #include <list>
@@ -39,6 +40,9 @@
 
 using android::base::SetProperty;
 using android::binder::Status;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::ReadDefaultFstab;
+using android::fs_mgr::ReadFstabFromFile;
 using android::hardware::hidl_string;
 using android::hardware::boot::V1_0::BoolResult;
 using android::hardware::boot::V1_0::IBootControl;
@@ -67,6 +71,18 @@
 
 }  // namespace
 
+Status cp_supportsCheckpoint(bool& result) {
+    result = false;
+
+    for (const auto& entry : fstab_default) {
+        if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
+            result = true;
+            return Status::ok();
+        }
+    }
+    return Status::ok();
+}
+
 Status cp_startCheckpoint(int retry) {
     if (retry < -1) return Status::fromExceptionCode(EINVAL, "Retry count must be more than -1");
     std::string content = std::to_string(retry + 1);
@@ -97,30 +113,27 @@
     // But we also need to get the matching fstab entries to see
     // the original flags
     std::string err_str;
-    auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
-        fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
-    if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
 
-    auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
-        fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
-    if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
+    Fstab mounts;
+    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
+        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
+    }
 
     // Walk mounted file systems
-    for (int i = 0; i < mounts->num_entries; ++i) {
-        const fstab_rec* mount_rec = &mounts->recs[i];
-        const fstab_rec* fstab_rec =
-            fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
+    for (const auto& mount_rec : mounts) {
+        const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
         if (!fstab_rec) continue;
 
-        if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
-            if (!strcmp(fstab_rec->fs_type, "f2fs")) {
-                if (mount(mount_rec->blk_device, mount_rec->mount_point, "none",
-                          MS_REMOUNT | fstab_rec->flags, "checkpoint=enable")) {
+        if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
+            if (fstab_rec->fs_type == "f2fs") {
+                std::string options = mount_rec.fs_options + ",checkpoint=enable";
+                if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
+                          MS_REMOUNT | fstab_rec->flags, options.c_str())) {
                     return Status::fromExceptionCode(EINVAL, "Failed to remount");
                 }
             }
-        } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
-            if (!setBowState(mount_rec->blk_device, "2"))
+        } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
+            if (!setBowState(mount_rec.blk_device, "2"))
                 return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
         }
     }
@@ -177,36 +190,31 @@
 }
 
 Status cp_prepareCheckpoint() {
-    auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
-        fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
-    if (!fstab_default) return Status::fromExceptionCode(EINVAL, "Failed to get fstab");
+    Fstab mounts;
+    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
+        return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
+    }
 
-    auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
-        fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
-    if (!mounts) return Status::fromExceptionCode(EINVAL, "Failed to get /proc/mounts");
-
-    for (int i = 0; i < mounts->num_entries; ++i) {
-        const fstab_rec* mount_rec = &mounts->recs[i];
-        const fstab_rec* fstab_rec =
-            fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
+    for (const auto& mount_rec : mounts) {
+        const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
         if (!fstab_rec) continue;
 
-        if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
+        if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
             android::base::unique_fd fd(
-                TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
+                TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
             if (!fd) {
-                PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
+                PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
                 continue;
             }
 
             struct fstrim_range range = {};
             range.len = ULLONG_MAX;
             if (ioctl(fd, FITRIM, &range)) {
-                PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
+                PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
                 continue;
             }
 
-            setBowState(mount_rec->blk_device, "1");
+            setBowState(mount_rec.blk_device, "1");
         }
     }
     return Status::ok();
diff --git a/Checkpoint.h b/Checkpoint.h
index eac2f94..64ceed3 100644
--- a/Checkpoint.h
+++ b/Checkpoint.h
@@ -23,6 +23,8 @@
 namespace android {
 namespace vold {
 
+android::binder::Status cp_supportsCheckpoint(bool& result);
+
 android::binder::Status cp_startCheckpoint(int retry);
 
 android::binder::Status cp_commitChanges();
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 9041838..8e7d8f4 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -62,6 +62,7 @@
 
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
+using android::fs_mgr::GetEntryForMountPoint;
 using android::vold::kEmptyAuthentication;
 using android::vold::KeyBuffer;
 using android::vold::Keymaster;
@@ -327,12 +328,12 @@
 }
 
 static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
-    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab_default, DATA_MNT_POINT);
-    char const* contents_mode;
-    char const* filenames_mode;
-    fs_mgr_get_file_encryption_modes(rec, &contents_mode, &filenames_mode);
-    key_ref->contents_mode = contents_mode;
-    key_ref->filenames_mode = filenames_mode;
+    auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+    if (entry == nullptr) {
+        return;
+    }
+    key_ref->contents_mode = entry->file_contents_mode;
+    key_ref->filenames_mode = entry->file_names_mode;
 }
 
 static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) {
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index d73b6d2..56fac4c 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -45,6 +45,8 @@
 using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::WriteStringToFile;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::ReadDefaultFstab;
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::health::storage::V1_0::IStorage;
@@ -102,48 +104,43 @@
 }
 
 static void addFromFstab(std::list<std::string>* paths, PathTypes path_type) {
-    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
-                                                               fs_mgr_free_fstab);
-    struct fstab_rec* prev_rec = NULL;
+    Fstab fstab;
+    ReadDefaultFstab(&fstab);
 
-    for (int i = 0; i < fstab->num_entries; i++) {
-        auto fs_type = std::string(fstab->recs[i].fs_type);
-        /* Skip raw partitions */
-        if (fs_type == "emmc" || fs_type == "mtd") {
+    std::string previous_mount_point;
+    for (const auto& entry : fstab) {
+        // Skip raw partitions.
+        if (entry.fs_type == "emmc" || entry.fs_type == "mtd") {
             continue;
         }
-        /* Skip read-only filesystems */
-        if (fstab->recs[i].flags & MS_RDONLY) {
+        // Skip read-only filesystems
+        if (entry.flags & MS_RDONLY) {
             continue;
         }
-        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
-            continue; /* Should we trim fat32 filesystems? */
+        if (entry.fs_mgr_flags.vold_managed) {
+            continue;  // Should we trim fat32 filesystems?
         }
-        if (fs_mgr_is_notrim(&fstab->recs[i])) {
+        if (entry.fs_mgr_flags.no_trim) {
             continue;
         }
 
-        /* Skip the multi-type partitions, which are required to be following each other.
-         * See fs_mgr.c's mount_with_alternatives().
-         */
-        if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) {
+        // Skip the multi-type partitions, which are required to be following each other.
+        // See fs_mgr.c's mount_with_alternatives().
+        if (entry.mount_point == previous_mount_point) {
             continue;
         }
 
         if (path_type == PathTypes::kMountPoint) {
-            paths->push_back(fstab->recs[i].mount_point);
+            paths->push_back(entry.mount_point);
         } else if (path_type == PathTypes::kBlkDevice) {
             std::string gc_path;
-            if (std::string(fstab->recs[i].fs_type) == "f2fs" &&
-                Realpath(
-                    android::vold::BlockDeviceForPath(std::string(fstab->recs[i].mount_point) + "/"),
-                    &gc_path)) {
-                paths->push_back(std::string("/sys/fs/") + fstab->recs[i].fs_type + "/" +
-                                 Basename(gc_path));
+            if (entry.fs_type == "f2fs" &&
+                Realpath(android::vold::BlockDeviceForPath(entry.mount_point + "/"), &gc_path)) {
+                paths->push_back("/sys/fs/" + entry.fs_type + "/" + Basename(gc_path));
             }
         }
 
-        prev_rec = &fstab->recs[i];
+        previous_mount_point = entry.mount_point;
     }
 }
 
@@ -263,22 +260,21 @@
 }
 
 static void runDevGcFstab(void) {
-    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
-                                                               fs_mgr_free_fstab);
-    struct fstab_rec* rec = NULL;
+    Fstab fstab;
+    ReadDefaultFstab(&fstab);
 
-    for (int i = 0; i < fstab->num_entries; i++) {
-        if (fs_mgr_has_sysfs_path(&fstab->recs[i])) {
-            rec = &fstab->recs[i];
+    std::string path;
+    for (const auto& entry : fstab) {
+        if (!entry.sysfs_path.empty()) {
+            path = entry.sysfs_path;
             break;
         }
     }
-    if (!rec) {
+
+    if (path.empty()) {
         return;
     }
 
-    std::string path;
-    path.append(rec->sysfs_path);
     path = path + "/manual_gc";
     Timer timer;
 
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 5c8a075..deb7194 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -44,12 +44,13 @@
 #include "Keymaster.h"
 #include "Utils.h"
 #include "VoldUtil.h"
-#include "secontext.h"
 
 #define DM_CRYPT_BUF_SIZE 4096
 #define TABLE_LOAD_RETRIES 10
 #define DEFAULT_KEY_TARGET_TYPE "default-key"
 
+using android::fs_mgr::FstabEntry;
+using android::fs_mgr::GetEntryForMountPoint;
 using android::vold::KeyBuffer;
 
 static const std::string kDmNameUserdata = "userdata";
@@ -60,11 +61,11 @@
 static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
     // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
     // partitions in the fsck domain.
-    if (setexeccon(secontextFsck())) {
+    if (setexeccon(android::vold::sFsckContext)) {
         PLOG(ERROR) << "Failed to setexeccon";
         return false;
     }
-    auto mount_rc = fs_mgr_do_mount(fstab_default, const_cast<char*>(mount_point),
+    auto mount_rc = fs_mgr_do_mount(&fstab_default, const_cast<char*>(mount_point),
                                     const_cast<char*>(blk_device), nullptr,
                                     android::vold::cp_needsCheckpoint());
     if (setexeccon(nullptr)) {
@@ -107,12 +108,12 @@
     LOG(INFO) << "Old Key deleted: " << dir;
 }
 
-static bool read_key(struct fstab_rec const* data_rec, bool create_if_absent, KeyBuffer* key) {
-    if (!data_rec->key_dir) {
+static bool read_key(const FstabEntry& data_rec, bool create_if_absent, KeyBuffer* key) {
+    if (data_rec.key_dir.empty()) {
         LOG(ERROR) << "Failed to get key_dir";
         return false;
     }
-    std::string key_dir = data_rec->key_dir;
+    std::string key_dir = data_rec.key_dir;
     std::string sKey;
     auto dir = key_dir + "/key";
     LOG(DEBUG) << "key_dir/key: " << dir;
@@ -255,13 +256,14 @@
         LOG(DEBUG) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
         return false;
     }
-    auto data_rec = fs_mgr_get_entry_for_mount_point(fstab_default, mount_point);
+
+    auto data_rec = GetEntryForMountPoint(&fstab_default, mount_point);
     if (!data_rec) {
         LOG(ERROR) << "Failed to get data_rec";
         return false;
     }
     KeyBuffer key;
-    if (!read_key(data_rec, needs_encrypt, &key)) return false;
+    if (!read_key(*data_rec, needs_encrypt, &key)) return false;
     uint64_t nr_sec;
     if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false;
     std::string crypto_blkdev;
@@ -272,9 +274,8 @@
     if (needs_encrypt) {
         LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
         off64_t size_already_done = 0;
-        auto rc =
-            cryptfs_enable_inplace(const_cast<char*>(crypto_blkdev.c_str()), data_rec->blk_device,
-                                   nr_sec, &size_already_done, nr_sec, 0, false);
+        auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), data_rec->blk_device.data(), nr_sec,
+                                         &size_already_done, nr_sec, 0, false);
         if (rc != 0) {
             LOG(ERROR) << "Inplace crypto failed with code: " << rc;
             return false;
@@ -287,6 +288,6 @@
     }
 
     LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point;
-    mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str());
+    mount_via_fs_mgr(data_rec->mount_point.c_str(), crypto_blkdev.c_str());
     return true;
 }
diff --git a/Utils.cpp b/Utils.cpp
index 341c927..f9b61b6 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -377,7 +377,7 @@
         return -errno;
     }
 
-    size_t n;
+    ssize_t n;
     while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], bytes))) > 0) {
         bytes -= n;
         buf += n;
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 58fdc74..5898e59 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -1005,5 +1005,12 @@
     return cp_abortChanges();
 }
 
+binder::Status VoldNativeService::supportsCheckpoint(bool* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    ACQUIRE_LOCK;
+
+    return cp_supportsCheckpoint(*_aidl_return);
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/VoldNativeService.h b/VoldNativeService.h
index b313514..2abf19d 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -142,6 +142,7 @@
     binder::Status restoreCheckpoint(const std::string& mountPoint);
     binder::Status markBootAttempt();
     binder::Status abortChanges();
+    binder::Status supportsCheckpoint(bool* _aidl_return);
 };
 
 }  // namespace vold
diff --git a/VoldUtil.cpp b/VoldUtil.cpp
index 4b980be..082f743 100644
--- a/VoldUtil.cpp
+++ b/VoldUtil.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <linux/fs.h>
-#include <sys/ioctl.h>
+#include "VoldUtil.h"
 
-struct fstab* fstab_default;
+android::fs_mgr::Fstab fstab_default;
diff --git a/VoldUtil.h b/VoldUtil.h
index 569a801..181506e 100644
--- a/VoldUtil.h
+++ b/VoldUtil.h
@@ -14,17 +14,15 @@
  * limitations under the License.
  */
 
-#ifndef _VOLDUTIL_H
-#define _VOLDUTIL_H
+#pragma once
 
 #include <fstab/fstab.h>
 #include <sys/cdefs.h>
 
-extern struct fstab* fstab_default;
+extern android::fs_mgr::Fstab fstab_default;
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
 #ifdef CONFIG_HW_DISK_ENCRYPT_PERF
 void get_blkdev_start_sector(int fd, unsigned long* st_sec);
 #endif
-#endif
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index b9181bd..191fbd6 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -114,6 +114,7 @@
     void prepareCheckpoint();
     void restoreCheckpoint(@utf8InCpp String device);
     void markBootAttempt();
+    boolean supportsCheckpoint();
 
     @utf8InCpp String createStubVolume(@utf8InCpp String sourcePath,
             @utf8InCpp String mountPath, @utf8InCpp String fsType,
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 08bcaba..97447cd 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -33,8 +33,8 @@
 #include "Utils.h"
 #include "VoldUtil.h"
 #include "VolumeManager.h"
-#include "secontext.h"
 
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <bootloader_message/bootloader_message.h>
@@ -78,7 +78,9 @@
 #include <crypto_scrypt.h>
 }
 
+using android::base::ParseUint;
 using android::base::StringPrintf;
+using android::fs_mgr::GetEntryForMountPoint;
 using namespace std::chrono_literals;
 
 #define UNUSED __attribute__((unused))
@@ -553,7 +555,7 @@
     return get_crypto_type().get_crypto_name();
 }
 
-static uint64_t get_fs_size(char* dev) {
+static uint64_t get_fs_size(const char* dev) {
     int fd, block_size;
     struct ext4_super_block sb;
     uint64_t len;
@@ -587,6 +589,22 @@
     return len / 512;
 }
 
+static void get_crypt_info(std::string* key_loc, std::string* real_blk_device) {
+    for (const auto& entry : fstab_default) {
+        if (!entry.fs_mgr_flags.vold_managed &&
+            (entry.fs_mgr_flags.crypt || entry.fs_mgr_flags.force_crypt ||
+             entry.fs_mgr_flags.force_fde_or_fbe || entry.fs_mgr_flags.file_encryption)) {
+            if (key_loc != nullptr) {
+                *key_loc = entry.key_loc;
+            }
+            if (real_blk_device != nullptr) {
+                *real_blk_device = entry.blk_device;
+            }
+            return;
+        }
+    }
+}
+
 static int get_crypt_ftr_info(char** metadata_fname, off64_t* off) {
     static int cached_data = 0;
     static uint64_t cached_off = 0;
@@ -596,22 +614,24 @@
     int rc = -1;
 
     if (!cached_data) {
-        fs_mgr_get_crypt_info(fstab_default, key_loc, real_blkdev, sizeof(key_loc));
+        std::string key_loc;
+        std::string real_blkdev;
+        get_crypt_info(&key_loc, &real_blkdev);
 
-        if (!strcmp(key_loc, KEY_IN_FOOTER)) {
+        if (key_loc == KEY_IN_FOOTER) {
             if (android::vold::GetBlockDevSize(real_blkdev, &cached_off) == android::OK) {
                 /* If it's an encrypted Android partition, the last 16 Kbytes contain the
                  * encryption info footer and key, and plenty of bytes to spare for future
                  * growth.
                  */
-                strlcpy(cached_metadata_fname, real_blkdev, sizeof(cached_metadata_fname));
+                strlcpy(cached_metadata_fname, real_blkdev.c_str(), sizeof(cached_metadata_fname));
                 cached_off -= CRYPT_FOOTER_OFFSET;
                 cached_data = 1;
             } else {
-                SLOGE("Cannot get size of block device %s\n", real_blkdev);
+                SLOGE("Cannot get size of block device %s\n", real_blkdev.c_str());
             }
         } else {
-            strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname));
+            strlcpy(cached_metadata_fname, key_loc.c_str(), sizeof(cached_metadata_fname));
             cached_off = 0;
             cached_data = 1;
         }
@@ -1128,8 +1148,10 @@
     tgt->length = crypt_ftr->fs_size;
     crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
     buff_offset = crypt_params - buffer;
-    SLOGI("Extra parameters for dm_crypt: %s\n", extra_params);
-
+    SLOGI(
+        "Creating crypto dev \"%s\"; cipher=%s, keysize=%u, real_dev=%s, len=%llu, params=\"%s\"\n",
+        name, crypt_ftr->crypto_type_name, crypt_ftr->keysize, real_blk_name, tgt->length * 512,
+        extra_params);
 #ifdef CONFIG_HW_DISK_ENCRYPTION
     if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
         strlcpy(tgt->target_type, "req-crypt",DM_MAX_TYPE_NAME);
@@ -1221,19 +1243,37 @@
     return extra_params;
 }
 
-// Only adds parameters if the property is set.
-static void add_sector_size_param(std::vector<std::string>* extra_params_vec) {
+/*
+ * If the ro.crypto.fde_sector_size system property is set, append the
+ * parameters to make dm-crypt use the specified crypto sector size and round
+ * the crypto device size down to a crypto sector boundary.
+ */
+static int add_sector_size_param(std::vector<std::string>* extra_params_vec,
+                                 struct crypt_mnt_ftr* ftr) {
     constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size";
-    char sector_size[PROPERTY_VALUE_MAX];
+    char value[PROPERTY_VALUE_MAX];
 
-    if (property_get(DM_CRYPT_SECTOR_SIZE, sector_size, "") > 0) {
-        std::string param = StringPrintf("sector_size:%s", sector_size);
+    if (property_get(DM_CRYPT_SECTOR_SIZE, value, "") > 0) {
+        unsigned int sector_size;
+
+        if (!ParseUint(value, &sector_size) || sector_size < 512 || sector_size > 4096 ||
+            (sector_size & (sector_size - 1)) != 0) {
+            SLOGE("Invalid value for %s: %s.  Must be >= 512, <= 4096, and a power of 2\n",
+                  DM_CRYPT_SECTOR_SIZE, value);
+            return -1;
+        }
+
+        std::string param = StringPrintf("sector_size:%u", sector_size);
         extra_params_vec->push_back(std::move(param));
 
         // With this option, IVs will match the sector numbering, instead
         // of being hard-coded to being based on 512-byte sectors.
         extra_params_vec->emplace_back("iv_large_sectors");
+
+        // Round the crypto device size down to a crypto sector boundary.
+        ftr->fs_size &= ~((sector_size / 512) - 1);
     }
+    return 0;
 }
 #endif
 
@@ -1327,7 +1367,10 @@
     if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) {
         extra_params_vec.emplace_back("allow_encrypt_override");
     }
-    add_sector_size_param(&extra_params_vec);
+    if (add_sector_size_param(&extra_params_vec, crypt_ftr)) {
+        SLOGE("Error processing dm-crypt sector size param\n");
+        goto errout;
+    }
     load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, fd,
                                            extra_params_as_string(extra_params_vec).c_str());
 #endif
@@ -1621,14 +1664,15 @@
 
 static int create_encrypted_random_key(const char* passwd, unsigned char* master_key,
                                        unsigned char* salt, struct crypt_mnt_ftr* crypt_ftr) {
-    int fd;
     unsigned char key_buf[MAX_KEY_LEN];
 
-    /* Get some random bits for a key */
-    fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
-    read(fd, key_buf, sizeof(key_buf));
-    read(fd, salt, SALT_LEN);
-    close(fd);
+    /* Get some random bits for a key and salt */
+    if (android::vold::ReadRandomBytes(sizeof(key_buf), reinterpret_cast<char*>(key_buf)) != 0) {
+        return -1;
+    }
+    if (android::vold::ReadRandomBytes(SALT_LEN, reinterpret_cast<char*>(salt)) != 0) {
+        return -1;
+    }
 
     /* Now encrypt it with the password */
     return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr, true);
@@ -1814,9 +1858,9 @@
         char ro_prop[PROPERTY_VALUE_MAX];
         property_get("ro.crypto.readonly", ro_prop, "");
         if (strlen(ro_prop) > 0 && std::stoi(ro_prop)) {
-            struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab_default, DATA_MNT_POINT);
-            if (rec) {
-                rec->flags |= MS_RDONLY;
+            auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+            if (entry != nullptr) {
+                entry->flags |= MS_RDONLY;
             }
         }
 
@@ -1828,16 +1872,16 @@
          * fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
          * partitions in the fsck domain.
          */
-        if (setexeccon(secontextFsck())) {
+        if (setexeccon(android::vold::sFsckContext)) {
             SLOGE("Failed to setexeccon");
             return -1;
         }
         bool needs_cp = android::vold::cp_needsCheckpoint();
 #ifdef CONFIG_HW_DISK_ENCRYPTION
-        while ((mount_rc = fs_mgr_do_mount(fstab_default, DATA_MNT_POINT, blkdev, 0,
+        while ((mount_rc = fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT, blkdev, 0,
                                            needs_cp)) != 0) {
 #else
-        while ((mount_rc = fs_mgr_do_mount(fstab_default, DATA_MNT_POINT, crypto_blkdev, 0,
+        while ((mount_rc = fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT, crypto_blkdev, 0,
                                            needs_cp)) != 0) {
 #endif
             if (mount_rc == FS_MGR_DOMNT_BUSY) {
@@ -1919,7 +1963,6 @@
 static int do_crypto_complete(const char* mount_point) {
     struct crypt_mnt_ftr crypt_ftr;
     char encrypted_state[PROPERTY_VALUE_MAX];
-    char key_loc[PROPERTY_VALUE_MAX];
 
     property_get("ro.crypto.state", encrypted_state, "");
     if (strcmp(encrypted_state, "encrypted")) {
@@ -1933,7 +1976,8 @@
     }
 
     if (get_crypt_ftr_and_key(&crypt_ftr)) {
-        fs_mgr_get_crypt_info(fstab_default, key_loc, 0, sizeof(key_loc));
+        std::string key_loc;
+        get_crypt_info(&key_loc, nullptr);
 
         /*
          * Only report this error if key_loc is a file and it exists.
@@ -1942,7 +1986,7 @@
          * a "enter password" screen, or worse, a "press button to wipe the
          * device" screen.
          */
-        if ((key_loc[0] == '/') && (access("key_loc", F_OK) == -1)) {
+        if (!key_loc.empty() && key_loc[0] == '/' && (access("key_loc", F_OK) == -1)) {
             SLOGE("master key file does not exist, aborting");
             return CRYPTO_COMPLETE_NOT_ENCRYPTED;
         } else {
@@ -2039,7 +2083,7 @@
                                    const char* mount_point, const char* label) {
     unsigned char decrypted_master_key[MAX_KEY_LEN];
     char crypto_blkdev[MAXPATHLEN];
-    char real_blkdev[MAXPATHLEN];
+    std::string real_blkdev;
     char tmp_mount_point[64];
     unsigned int orig_failed_decrypt_count;
     int rc;
@@ -2063,12 +2107,12 @@
         }
     }
 
-    fs_mgr_get_crypt_info(fstab_default, 0, real_blkdev, sizeof(real_blkdev));
+    get_crypt_info(nullptr, &real_blkdev);
 
     // Create crypto block device - all (non fatal) code paths
     // need it
-    if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev, label,
-                              0)) {
+    if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
+                              label, 0)) {
         SLOGE("Error creating decrypted block device\n");
         rc = -1;
         goto errout;
@@ -2091,7 +2135,7 @@
          * the footer, not the key. */
         snprintf(tmp_mount_point, sizeof(tmp_mount_point), "%s/tmp_mnt", mount_point);
         mkdir(tmp_mount_point, 0755);
-        if (fs_mgr_do_mount(fstab_default, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
+        if (fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
             SLOGE("Error temp mounting decrypted block device\n");
             delete_crypto_blk_dev(label);
 
@@ -2512,14 +2556,15 @@
 }
 
 int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
-    char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN];
+    char crypto_blkdev[MAXPATHLEN];
+    std::string real_blkdev;
     unsigned char decrypted_master_key[MAX_KEY_LEN];
     int rc = -1, i;
     struct crypt_mnt_ftr crypt_ftr;
     struct crypt_persist_data* pdata;
     char encrypted_state[PROPERTY_VALUE_MAX];
     char lockid[32] = {0};
-    char key_loc[PROPERTY_VALUE_MAX];
+    std::string key_loc;
     int num_vols;
     off64_t previously_encrypted_upto = 0;
     bool rebootEncryption = false;
@@ -2567,22 +2612,20 @@
         goto error_unencrypted;
     }
 
-    // TODO refactor fs_mgr_get_crypt_info to get both in one call
-    fs_mgr_get_crypt_info(fstab_default, key_loc, 0, sizeof(key_loc));
-    fs_mgr_get_crypt_info(fstab_default, 0, real_blkdev, sizeof(real_blkdev));
+    get_crypt_info(&key_loc, &real_blkdev);
 
     /* Get the size of the real block device */
     uint64_t nr_sec;
     if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
-        SLOGE("Cannot get size of block device %s\n", real_blkdev);
+        SLOGE("Cannot get size of block device %s\n", real_blkdev.c_str());
         goto error_unencrypted;
     }
 
     /* If doing inplace encryption, make sure the orig fs doesn't include the crypto footer */
-    if (!strcmp(key_loc, KEY_IN_FOOTER)) {
+    if (key_loc == KEY_IN_FOOTER) {
         uint64_t fs_size_sec, max_fs_size_sec;
-        fs_size_sec = get_fs_size(real_blkdev);
-        if (fs_size_sec == 0) fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev);
+        fs_size_sec = get_fs_size(real_blkdev.c_str());
+        if (fs_size_sec == 0) fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev.data());
 
         max_fs_size_sec = nr_sec - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE);
 
@@ -2631,7 +2674,7 @@
             goto error_shutting_down;
         }
 
-        if (!strcmp(key_loc, KEY_IN_FOOTER)) {
+        if (key_loc == KEY_IN_FOOTER) {
             crypt_ftr.fs_size = nr_sec - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE);
         } else {
             crypt_ftr.fs_size = nr_sec;
@@ -2756,14 +2799,14 @@
 #ifdef CONFIG_HW_DISK_ENCRYPT_PERF
       strlcpy(crypto_blkdev, real_blkdev, sizeof(crypto_blkdev));
 #else
-      create_crypto_blk_dev(&crypt_ftr, (unsigned char*)&key_index, real_blkdev, crypto_blkdev,
+      create_crypto_blk_dev(&crypt_ftr, (unsigned char*)&key_index, real_blkdev.c_str(), crypto_blkdev,
                           CRYPTO_BLOCK_DEVICE, 0);
 #endif
     else
-      create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
+      create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
                           CRYPTO_BLOCK_DEVICE, 0);
 #else
-    create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
+    create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
                           CRYPTO_BLOCK_DEVICE, 0);
 #endif
 
@@ -2793,7 +2836,7 @@
     }
 #endif
     if (!rc) {
-        rc = cryptfs_enable_all_volumes(&crypt_ftr, crypto_blkdev, real_blkdev,
+        rc = cryptfs_enable_all_volumes(&crypt_ftr, crypto_blkdev, real_blkdev.data(),
                                         previously_encrypted_upto);
     }
 
@@ -3422,8 +3465,8 @@
 }
 
 int cryptfs_isConvertibleToFBE() {
-    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab_default, DATA_MNT_POINT);
-    return (rec && fs_mgr_is_convertible_to_fbe(rec)) ? 1 : 0;
+    auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+    return entry && entry->fs_mgr_flags.force_fde_or_fbe;
 }
 
 int cryptfs_create_default_ftr(struct crypt_mnt_ftr* crypt_ftr, __attribute__((unused))int key_length)
diff --git a/hash.h b/hash.h
deleted file mode 100644
index cd81805..0000000
--- a/hash.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 1999 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 3. Neither the name of KTH 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 KTH AND ITS CONTRIBUTORS ``AS IS'' AND 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 KTH OR ITS 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. */
-
-/* $Heimdal: hash.h,v 1.1 1999/03/22 19:16:25 joda Exp $
-   $NetBSD: hash.h,v 1.1.1.3 2002/09/12 12:41:42 joda Exp $ */
-
-/* stuff in common between md4, md5, and sha1 */
-
-#ifndef __hash_h__
-#define __hash_h__
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef min
-#define min(a, b) (((a) > (b)) ? (b) : (a))
-#endif
-
-/* Vector Crays doesn't have a good 32-bit type, or more precisely,
-   int32_t as defined by <bind/bitypes.h> isn't 32 bits, and we don't
-   want to depend in being able to redefine this type.  To cope with
-   this we have to clamp the result in some places to [0,2^32); no
-   need to do this on other machines.  Did I say this was a mess?
-   */
-
-#ifdef _CRAY
-#define CRAYFIX(X) ((X)&0xffffffff)
-#else
-#define CRAYFIX(X) (X)
-#endif
-
-static inline u_int32_t cshift(u_int32_t x, unsigned int n) {
-    x = CRAYFIX(x);
-    return CRAYFIX((x << n) | (x >> (32 - n)));
-}
-
-#endif /* __hash_h__ */
diff --git a/main.cpp b/main.cpp
index 347c945..d4b1c38 100644
--- a/main.cpp
+++ b/main.cpp
@@ -50,6 +50,7 @@
 struct selabel_handle* sehandle;
 
 using android::base::StringPrintf;
+using android::fs_mgr::ReadDefaultFstab;
 
 int main(int argc, char** argv) {
     atrace_set_tracing_enabled(false);
@@ -216,8 +217,7 @@
                           bool* has_reserved) {
     ATRACE_NAME("process_config");
 
-    fstab_default = fs_mgr_read_fstab_default();
-    if (!fstab_default) {
+    if (!ReadDefaultFstab(&fstab_default)) {
         PLOG(ERROR) << "Failed to open default fstab";
         return -1;
     }
@@ -226,30 +226,29 @@
     *has_adoptable = false;
     *has_quota = false;
     *has_reserved = false;
-    for (int i = 0; i < fstab_default->num_entries; i++) {
-        auto rec = &fstab_default->recs[i];
-        if (fs_mgr_is_quota(rec)) {
+    for (const auto& entry : fstab_default) {
+        if (entry.fs_mgr_flags.quota) {
             *has_quota = true;
         }
-        if (rec->reserved_size > 0) {
+        if (entry.reserved_size > 0) {
             *has_reserved = true;
         }
 
-        if (fs_mgr_is_voldmanaged(rec)) {
-            if (fs_mgr_is_nonremovable(rec)) {
+        if (entry.fs_mgr_flags.vold_managed) {
+            if (entry.fs_mgr_flags.nonremovable) {
                 LOG(WARNING) << "nonremovable no longer supported; ignoring volume";
                 continue;
             }
 
-            std::string sysPattern(rec->blk_device);
-            std::string nickname(rec->label);
+            std::string sysPattern(entry.blk_device);
+            std::string nickname(entry.label);
             int flags = 0;
 
-            if (fs_mgr_is_encryptable(rec)) {
+            if (entry.is_encryptable()) {
                 flags |= android::vold::Disk::Flags::kAdoptable;
                 *has_adoptable = true;
             }
-            if (fs_mgr_is_noemulatedsd(rec) ||
+            if (entry.fs_mgr_flags.no_emulated_sd ||
                 android::base::GetBoolProperty("vold.debug.default_primary", false)) {
                 flags |= android::vold::Disk::Flags::kDefaultPrimary;
             }
diff --git a/secontext.cpp b/secontext.cpp
deleted file mode 100644
index bc21fc2..0000000
--- a/secontext.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "secontext.h"
-#include <Utils.h>
-
-security_context_t secontextFsck() {
-    return android::vold::sFsckContext;
-}
diff --git a/secontext.h b/secontext.h
deleted file mode 100644
index f5339c8..0000000
--- a/secontext.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _SECONTEXT_H_
-#define _SECONTEXT_H_
-
-#include <selinux/selinux.h>
-
-security_context_t secontextFsck();
-
-#endif
diff --git a/vdc.cpp b/vdc.cpp
index e971d52..35775a7 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -105,6 +105,10 @@
         checkStatus(vold->mountFstab(args[2]));
     } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 3) {
         checkStatus(vold->encryptFstab(args[2]));
+    } else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) {
+        bool supported = false;
+        checkStatus(vold->supportsCheckpoint(&supported));
+        return supported ? 1 : 0;
     } else if (args[0] == "checkpoint" && args[1] == "startCheckpoint" && args.size() == 3) {
         int retry;
         if (!android::base::ParseInt(args[2], &retry)) exit(EINVAL);