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
This commit is contained in:
Jiyong Park 2018-11-08 17:14:35 +09:00
parent 9e04f62895
commit c240440eec
6 changed files with 51 additions and 1 deletions

View file

@ -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 <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().

View file

@ -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 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) {
{{"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 @@ 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}}},

View file

@ -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<ServiceParser>(&service_list, subcontexts));
return parser;
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);

View file

@ -38,6 +38,7 @@ extern std::string default_console;
extern std::vector<std::string> 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);

View file

@ -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<SectionParser> 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<std::string, std::unique_ptr<SectionParser>> section_parsers_;

View file

@ -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