Merge "Move e2fsck into /first_stage_ramdisk." am: 8b4a9a9a61

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1478507

Change-Id: I1ff6a9cf72259e8227e1fe657e6228c354655c5e
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 554f301..d2a952f 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -99,6 +99,34 @@
     return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
 }
 
+// Move e2fsck before switching root, so that it is available at the same path
+// after switching root.
+void PrepareSwitchRoot() {
+    constexpr const char* src = "/system/bin/e2fsck";
+    constexpr const char* dst = "/first_stage_ramdisk/system/bin/e2fsck";
+
+    if (access(dst, X_OK) == 0) {
+        LOG(INFO) << dst << " already exists and it can be executed";
+        return;
+    }
+
+    if (access(src, F_OK) != 0) {
+        PLOG(INFO) << "Not moving " << src << " because it cannot be accessed";
+        return;
+    }
+
+    auto dst_dir = android::base::Dirname(dst);
+    std::error_code ec;
+    if (!fs::create_directories(dst_dir, ec)) {
+        LOG(FATAL) << "Cannot create " << dst_dir << ": " << ec.message();
+    }
+    if (rename(src, dst) != 0) {
+        PLOG(FATAL) << "Cannot move " << src << " to " << dst
+                    << ". Either install e2fsck.ramdisk so that it is at the correct place (" << dst
+                    << "), or make ramdisk writable";
+    }
+}
+
 }  // namespace
 
 std::string GetModuleLoadList(bool recovery, const std::string& dir_path) {
@@ -298,6 +326,7 @@
 
     if (ForceNormalBoot(cmdline)) {
         mkdir("/first_stage_ramdisk", 0755);
+        PrepareSwitchRoot();
         // SwitchRoot() must be called with a mount point as the target, so we bind mount the
         // target directory to itself here.
         if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {