Dedup apex-scanning

create_apex_data_dirs() now uses GetApexListFrom(dir) in
apex_init_util.cpp.

This is essentially a refactoring, but there are a few behavioral
changes, which I think make more sense.
- Emits no error when opendir(/apex) fails.
- Emits errors when mkdir fails for each apex.
- Does not abort `perform_apex_config` even though create_apex_data_dirs
  fails.

Bug: 293546778
Test: check /data/misc/apexdata/ after boot
Change-Id: I9d1a9710a6a626eec087c8c0fb1768667ffb036e
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d88da39..6d17f36 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -82,7 +82,7 @@
     return configs;
 }
 
-static std::set<std::string> GetApexListFrom(const std::string& apex_dir) {
+std::set<std::string> GetApexListFrom(const std::string& apex_dir) {
     std::set<std::string> apex_list;
     auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(apex_dir.c_str()), closedir);
     if (!dirp) {
diff --git a/init/apex_init_util.h b/init/apex_init_util.h
index e55b3c0..75dfee1 100644
--- a/init/apex_init_util.h
+++ b/init/apex_init_util.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -24,6 +25,9 @@
 namespace android {
 namespace init {
 
+// Scans apex_dir (/apex) to get the list of active APEXes.
+std::set<std::string> GetApexListFrom(const std::string& apex_dir);
+
 // Parse all RC scripts for a given apex.
 Result<void> ParseRcScriptsFromApex(const std::string& apex_name);
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 2ced66d..a5b762c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1269,26 +1269,15 @@
 /*
  * Creates a directory under /data/misc/apexdata/ for each APEX.
  */
-static Result<void> create_apex_data_dirs() {
-    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
-    if (!dirp) {
-        return ErrnoError() << "Unable to open apex directory";
-    }
-    struct dirent* entry;
-    while ((entry = readdir(dirp.get())) != nullptr) {
-        if (entry->d_type != DT_DIR) continue;
-
-        const char* name = entry->d_name;
-        // skip any starting with "."
-        if (name[0] == '.') continue;
-
-        if (strchr(name, '@') != nullptr) continue;
-
-        auto path = "/data/misc/apexdata/" + std::string(name);
+static void create_apex_data_dirs() {
+    for (const auto& name : GetApexListFrom("/apex")) {
+        auto path = "/data/misc/apexdata/" + name;
         auto options = MkdirOptions{path, 0771, AID_ROOT, AID_SYSTEM, FscryptAction::kNone, "ref"};
-        make_dir_with_options(options);
+        auto result = make_dir_with_options(options);
+        if (!result.ok()) {
+            LOG(ERROR) << result.error();
+        }
     }
-    return {};
 }
 
 static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
@@ -1301,10 +1290,7 @@
     }
 
     if (!bootstrap) {
-        auto create_dirs = create_apex_data_dirs();
-        if (!create_dirs.ok()) {
-            return create_dirs.error();
-        }
+        create_apex_data_dirs();
     }
 
     auto parse_result = ParseRcScriptsFromAllApexes(bootstrap);