init parses *.rc files from APEXes
Init now parses *.rc files from the APEXs when the apexd notifies the
mount event via apexd.status sysprop.
Bug: 117403679
Test: m apex.test; adb root; adb push <builtfile> /data/apex; adb reboot
adb root; adb shell setprop ctl.start apex.test; dmesg shows that init
tries to start the service which doesn't exist.
[ 47.979657] init: Could not ctl.start for 'apex.test': Cannot find '/apex/com.android.example.apex/bin/test': No such file or directory
Change-Id: I3f12355346eeb212eca4de85b6b73257283fa054
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 5d62c0b..8660d2a 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
+#include <glob.h>
#include <linux/loop.h>
#include <linux/module.h>
#include <mntent.h>
@@ -1053,6 +1054,38 @@
{{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
}
+static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
+ glob_t glob_result;
+ // @ is added to filter out the later paths, which are bind mounts of the places
+ // where the APEXes are really mounted at. Otherwise, we will parse the
+ // same file twice.
+ static constexpr char glob_pattern[] = "/apex/*@*/etc/*.rc";
+ if (glob(glob_pattern, GLOB_MARK, nullptr, &glob_result) != 0) {
+ globfree(&glob_result);
+ return Error() << "glob pattern '" << glob_pattern << "' failed";
+ }
+ std::vector<std::string> configs;
+ Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance());
+ for (size_t i = 0; i < glob_result.gl_pathc; i++) {
+ configs.emplace_back(glob_result.gl_pathv[i]);
+ }
+ globfree(&glob_result);
+
+ bool success = true;
+ for (const auto& c : configs) {
+ if (c.back() == '/') {
+ // skip if directory
+ continue;
+ }
+ success &= parser.ParseConfigFile(c);
+ }
+ if (success) {
+ return Success();
+ } else {
+ return Error() << "Could not parse apex configs";
+ }
+}
+
// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
@@ -1090,6 +1123,7 @@
// mount and umount are run in the same context as mount_all for symmetry.
{"mount_all", {1, kMax, {false, do_mount_all}}},
{"mount", {3, kMax, {false, do_mount}}},
+ {"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
{"umount", {1, 1, {false, do_umount}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"restart", {1, 1, {false, do_restart}}},