diff --git a/init/README.md b/init/README.md index 2c531df60..4b21e32ea 100644 --- a/init/README.md +++ b/init/README.md @@ -275,6 +275,10 @@ runs the service. since it has some peculiarities for backwards compatibility reasons. The 'imports' section of this file has more details on the order. +`parse_apex_configs` + Parses config file(s) from the mounted APEXes. Intented to be used only once + when apexd notifies the mount event by setting apexd.status to ready. + `priority ` > Scheduling priority of the service process. This value has to be in range -20 to 19. Default priority is 0. Priority is set via setpriority(). diff --git a/init/builtins.cpp b/init/builtins.cpp index 5d62c0b92..8660d2a99 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1053,6 +1054,38 @@ static Result do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } +static Result 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 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::max(); @@ -1090,6 +1123,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { // 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}}}, diff --git a/init/init.cpp b/init/init.cpp index 90803f794..e7dbc1197 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -132,6 +132,14 @@ Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) { return parser; } +// parser that only accepts new services +Parser CreateServiceOnlyParser(ServiceList& service_list) { + Parser parser; + + parser.AddSectionParser("service", std::make_unique(&service_list, subcontexts)); + return parser; +} + static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) { Parser parser = CreateParser(action_manager, service_list); diff --git a/init/init.h b/init/init.h index f244ad7fe..65405aaeb 100644 --- a/init/init.h +++ b/init/init.h @@ -38,6 +38,7 @@ extern std::string default_console; extern std::vector late_import_paths; Parser CreateParser(ActionManager& action_manager, ServiceList& service_list); +Parser CreateServiceOnlyParser(ServiceList& service_list); void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid); diff --git a/init/parser.h b/init/parser.h index 2454b6a6f..f30bda707 100644 --- a/init/parser.h +++ b/init/parser.h @@ -72,6 +72,7 @@ class Parser { Parser(); bool ParseConfig(const std::string& path); + bool ParseConfigFile(const std::string& path); void AddSectionParser(const std::string& name, std::unique_ptr parser); void AddSingleLineParser(const std::string& prefix, LineCallback callback); @@ -82,7 +83,6 @@ class Parser { private: void ParseData(const std::string& filename, std::string* data); - bool ParseConfigFile(const std::string& path); bool ParseConfigDir(const std::string& path); std::map> section_parsers_; diff --git a/rootdir/init.rc b/rootdir/init.rc index 025e3c3e3..636daea62 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -801,3 +801,6 @@ on property:ro.debuggable=1 service flash_recovery /system/bin/install-recovery.sh class main oneshot + +on property:apexd.status=ready + parse_apex_configs