host_apex_verifier: Add --fsckerofs argument

The tool invokes deapexer which relies on debugfs/fsckerofs. deapexer
complains when fsckerofs is missing and ANDROID_HOST_OUT is not set. To
satisfy deapexer, host_apex_verifier needs --fsckerofs as well.

Btw, for convenience, we search tools under ANDROID_HOST_OUT when it's
set.

Bug: 223896570
Test: host_apex_verifier --apex=<apex> runs
Change-Id: I1e7c23dff2241604e972c6b60806f769458e661d
diff --git a/tools/host_apex_verifier.cc b/tools/host_apex_verifier.cc
index f33223c..a86416c 100644
--- a/tools/host_apex_verifier.cc
+++ b/tools/host_apex_verifier.cc
@@ -65,6 +65,7 @@
 Options:
   --deapexer=PATH             Use the deapexer binary at this path when extracting APEXes.
   --debugfs=PATH              Use the debugfs binary at this path when extracting APEXes.
+  --fsckerofs=PATH            Use the fsck.erofs binary at this path when extracting APEXes.
   --sdk_version=INT           The active system SDK version used when filtering versioned
                               init.rc files.
 for checking all APEXes:
@@ -128,8 +129,8 @@
 }
 
 // Extract and validate a single APEX.
-void ScanApex(const std::string& deapexer, const std::string& debugfs,
-              int sdk_version, const std::string& apex_path) {
+void ScanApex(const std::string& deapexer, int sdk_version,
+              const std::string& apex_path) {
   LOG(INFO) << "Checking APEX " << apex_path;
 
   auto apex = OR_FATAL(ApexFile::Open(apex_path));
@@ -137,9 +138,8 @@
 
   auto extracted_apex = TemporaryDir();
   std::string extracted_apex_dir = extracted_apex.path;
-  std::string deapexer_command = deapexer + " --debugfs_path " + debugfs +
-                                 " extract " + apex_path + " " +
-                                 extracted_apex_dir;
+  std::string deapexer_command =
+      deapexer + " extract " + apex_path + " " + extracted_apex_dir;
   auto code = system(deapexer_command.c_str());
   if (code != 0) {
     LOG(FATAL) << "Error running deapexer command \"" << deapexer_command
@@ -157,8 +157,7 @@
 //     APEX may flatten to that path.
 //   - Extracted target_files archives which may not contain
 //     flattened <PARTITON>/apex/ directories.
-void ScanPartitionApexes(const std::string& deapexer,
-                         const std::string& debugfs, int sdk_version,
+void ScanPartitionApexes(const std::string& deapexer, int sdk_version,
                          const std::string& partition_dir) {
   LOG(INFO) << "Scanning partition factory APEX dir " << partition_dir;
 
@@ -173,8 +172,7 @@
   while ((entry = readdir(apex_dir.get()))) {
     if (base::EndsWith(entry->d_name, ".apex") ||
         base::EndsWith(entry->d_name, ".capex")) {
-      ScanApex(deapexer, debugfs, sdk_version,
-               partition_dir + "/" + entry->d_name);
+      ScanApex(deapexer, sdk_version, partition_dir + "/" + entry->d_name);
     }
   }
 }
@@ -184,7 +182,14 @@
 int main(int argc, char** argv) {
   android::base::InitLogging(argv, &android::base::StdioLogger);
 
-  std::string deapexer, debugfs;
+  std::string deapexer, debugfs, fsckerofs;
+  // Use ANDROID_HOST_OUT for convenience
+  const char* host_out = getenv("ANDROID_HOST_OUT");
+  if (host_out) {
+    deapexer = std::string(host_out) + "/bin/deapexer";
+    debugfs = std::string(host_out) + "/bin/debugfs_static";
+    fsckerofs = std::string(host_out) + "/bin/fsck.erofs";
+  }
   int sdk_version = INT_MAX;
   std::map<std::string, std::string> partition_map;
   std::string apex;
@@ -194,6 +199,7 @@
         {"help", no_argument, nullptr, 'h'},
         {"deapexer", required_argument, nullptr, 0},
         {"debugfs", required_argument, nullptr, 0},
+        {"fsckerofs", required_argument, nullptr, 0},
         {"sdk_version", required_argument, nullptr, 0},
         {"out_system", required_argument, nullptr, 0},
         {"out_system_ext", required_argument, nullptr, 0},
@@ -220,6 +226,9 @@
         if (name == "debugfs") {
           debugfs = optarg;
         }
+        if (name == "fsckerofs") {
+          fsckerofs = optarg;
+        }
         if (name == "sdk_version") {
           if (!base::ParseInt(optarg, &sdk_version)) {
             PrintUsage();
@@ -248,10 +257,17 @@
   argc -= optind;
   argv += optind;
 
-  if (argc != 0 || deapexer.empty() || debugfs.empty()) {
+  if (argc != 0) {
     PrintUsage();
     return EXIT_FAILURE;
   }
+  if (deapexer.empty() || debugfs.empty() || fsckerofs.empty()) {
+    PrintUsage();
+    return EXIT_FAILURE;
+  }
+  deapexer += " --debugfs_path " + debugfs;
+  deapexer += " --fsckerofs_path " + fsckerofs;
+
   if (!!apex.empty() + !!partition_map.empty() != 1) {
     PrintUsage();
     return EXIT_FAILURE;
@@ -261,10 +277,10 @@
 
   if (!partition_map.empty()) {
     for (const auto& p : partition_map) {
-      ScanPartitionApexes(deapexer, debugfs, sdk_version, p.second);
+      ScanPartitionApexes(deapexer, sdk_version, p.second);
     }
   } else {
-    ScanApex(deapexer, debugfs, sdk_version, apex);
+    ScanApex(deapexer, sdk_version, apex);
   }
   return EXIT_SUCCESS;
 }