diff --git a/init/action.cpp b/init/action.cpp index 671e285e1..f687074c6 100644 --- a/init/action.cpp +++ b/init/action.cpp @@ -53,19 +53,16 @@ Action::Action(bool oneshot, const std::string& filename, int line) const KeywordMap* Action::function_map_ = nullptr; -bool Action::AddCommand(const std::vector& args, int line, std::string* err) { +Result Action::AddCommand(const std::vector& args, int line) { if (!function_map_) { - *err = "no function map available"; - return false; + return Error() << "no function map available"; } - auto function = function_map_->FindFunction(args, err); - if (!function) { - return false; - } + auto function = function_map_->FindFunction(args); + if (!function) return Error() << function.error(); - AddCommand(function, args, line); - return true; + AddCommand(*function, args, line); + return Success(); } void Action::AddCommand(BuiltinFunction f, const std::vector& args, int line) { @@ -105,67 +102,60 @@ void Action::ExecuteCommand(const Command& command) const { } } -bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) { +Result Action::ParsePropertyTrigger(const std::string& trigger) { const static std::string prop_str("property:"); std::string prop_name(trigger.substr(prop_str.length())); size_t equal_pos = prop_name.find('='); if (equal_pos == std::string::npos) { - *err = "property trigger found without matching '='"; - return false; + return Error() << "property trigger found without matching '='"; } std::string prop_value(prop_name.substr(equal_pos + 1)); prop_name.erase(equal_pos); if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) { - *err = "multiple property triggers found for same property"; - return false; + return Error() << "multiple property triggers found for same property"; } - return true; + return Success(); } -bool Action::InitTriggers(const std::vector& args, std::string* err) { +Result Action::InitTriggers(const std::vector& args) { const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (args[i].empty()) { - *err = "empty trigger is not valid"; - return false; + return Error() << "empty trigger is not valid"; } if (i % 2) { if (args[i] != "&&") { - *err = "&& is the only symbol allowed to concatenate actions"; - return false; + return Error() << "&& is the only symbol allowed to concatenate actions"; } else { continue; } } if (!args[i].compare(0, prop_str.length(), prop_str)) { - if (!ParsePropertyTrigger(args[i], err)) { - return false; + if (auto result = ParsePropertyTrigger(args[i]); !result) { + return result; } } else { if (!event_trigger_.empty()) { - *err = "multiple event triggers are not allowed"; - return false; + return Error() << "multiple event triggers are not allowed"; } event_trigger_ = args[i]; } } - return true; + return Success(); } -bool Action::InitSingleTrigger(const std::string& trigger) { +Result Action::InitSingleTrigger(const std::string& trigger) { std::vector name_vector{trigger}; - std::string err; - bool ret = InitTriggers(name_vector, &err); - if (!ret) { - LOG(ERROR) << "InitSingleTrigger failed due to: " << err; + if (auto result = InitTriggers(name_vector); !result) { + return Error() << "InitTriggers() failed: " << result.error(); } - return ret; + return Success(); } // This function checks that all property triggers are satisfied, that is @@ -263,7 +253,8 @@ void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& auto action = std::make_unique(true, "", 0); std::vector name_vector{name}; - if (!action->InitSingleTrigger(name)) { + if (auto result = action->InitSingleTrigger(name); !result) { + LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error(); return; } @@ -332,25 +323,25 @@ void ActionManager::ClearQueue() { current_command_ = 0; } -bool ActionParser::ParseSection(std::vector&& args, const std::string& filename, - int line, std::string* err) { +Result ActionParser::ParseSection(std::vector&& args, + const std::string& filename, int line) { std::vector triggers(args.begin() + 1, args.end()); if (triggers.size() < 1) { - *err = "actions must have a trigger"; - return false; + return Error() << "Actions must have a trigger"; } auto action = std::make_unique(false, filename, line); - if (!action->InitTriggers(triggers, err)) { - return false; + + if (auto result = action->InitTriggers(triggers); !result) { + return Error() << "InitTriggers() failed: " << result.error(); } action_ = std::move(action); - return true; + return Success(); } -bool ActionParser::ParseLineSection(std::vector&& args, int line, std::string* err) { - return action_ ? action_->AddCommand(std::move(args), line, err) : false; +Result ActionParser::ParseLineSection(std::vector&& args, int line) { + return action_ ? action_->AddCommand(std::move(args), line) : Success(); } void ActionParser::EndSection() { diff --git a/init/action.h b/init/action.h index 44ecd237b..d977f827a 100644 --- a/init/action.h +++ b/init/action.h @@ -54,10 +54,10 @@ class Action { public: explicit Action(bool oneshot, const std::string& filename, int line); - bool AddCommand(const std::vector& args, int line, std::string* err); + Result AddCommand(const std::vector& args, int line); void AddCommand(BuiltinFunction f, const std::vector& args, int line); - bool InitTriggers(const std::vector& args, std::string* err); - bool InitSingleTrigger(const std::string& trigger); + Result InitTriggers(const std::vector& args); + Result InitSingleTrigger(const std::string& trigger); std::size_t NumCommands() const; void ExecuteOneCommand(std::size_t command) const; void ExecuteAllCommands() const; @@ -79,7 +79,7 @@ private: void ExecuteCommand(const Command& command) const; bool CheckPropertyTriggers(const std::string& name = "", const std::string& value = "") const; - bool ParsePropertyTrigger(const std::string& trigger, std::string* err); + Result ParsePropertyTrigger(const std::string& trigger); std::map property_triggers_; std::string event_trigger_; @@ -121,9 +121,9 @@ class ActionParser : public SectionParser { public: ActionParser(ActionManager* action_manager) : action_manager_(action_manager), action_(nullptr) {} - bool ParseSection(std::vector&& args, const std::string& filename, int line, - std::string* err) override; - bool ParseLineSection(std::vector&& args, int line, std::string* err) override; + Result ParseSection(std::vector&& args, const std::string& filename, + int line) override; + Result ParseLineSection(std::vector&& args, int line) override; void EndSection() override; private: diff --git a/init/import_parser.cpp b/init/import_parser.cpp index b9fa2cea7..e335fd111 100644 --- a/init/import_parser.cpp +++ b/init/import_parser.cpp @@ -23,24 +23,22 @@ namespace android { namespace init { -bool ImportParser::ParseSection(std::vector&& args, const std::string& filename, - int line, std::string* err) { +Result ImportParser::ParseSection(std::vector&& args, + const std::string& filename, int line) { if (args.size() != 2) { - *err = "single argument needed for import\n"; - return false; + return Error() << "single argument needed for import\n"; } std::string conf_file; bool ret = expand_props(args[1], &conf_file); if (!ret) { - *err = "error while expanding import"; - return false; + return Error() << "error while expanding import"; } LOG(INFO) << "Added '" << conf_file << "' to import list"; if (filename_.empty()) filename_ = filename; imports_.emplace_back(std::move(conf_file), line); - return true; + return Success(); } void ImportParser::EndFile() { diff --git a/init/import_parser.h b/init/import_parser.h index 0d04e0e27..5a2f89498 100644 --- a/init/import_parser.h +++ b/init/import_parser.h @@ -28,8 +28,8 @@ namespace init { class ImportParser : public SectionParser { public: ImportParser(Parser* parser) : parser_(parser) {} - bool ParseSection(std::vector&& args, const std::string& filename, int line, - std::string* err) override; + Result ParseSection(std::vector&& args, const std::string& filename, + int line) override; void EndFile() override; private: diff --git a/init/keyword_map.h b/init/keyword_map.h index 481d63702..c95fc7318 100644 --- a/init/keyword_map.h +++ b/init/keyword_map.h @@ -22,6 +22,8 @@ #include +#include "result.h" + namespace android { namespace init { @@ -34,20 +36,17 @@ class KeywordMap { virtual ~KeywordMap() { } - const Function FindFunction(const std::vector& args, std::string* err) const { + const Result FindFunction(const std::vector& args) const { using android::base::StringPrintf; - if (args.empty()) { - *err = "keyword needed, but not provided"; - return nullptr; - } + if (args.empty()) return Error() << "Keyword needed, but not provided"; + auto& keyword = args[0]; auto num_args = args.size() - 1; auto function_info_it = map().find(keyword); if (function_info_it == map().end()) { - *err = StringPrintf("invalid keyword '%s'", keyword.c_str()); - return nullptr; + return Error() << StringPrintf("Invalid keyword '%s'", keyword.c_str()); } auto function_info = function_info_it->second; @@ -55,22 +54,18 @@ class KeywordMap { auto min_args = std::get<0>(function_info); auto max_args = std::get<1>(function_info); if (min_args == max_args && num_args != min_args) { - *err = StringPrintf("%s requires %zu argument%s", - keyword.c_str(), min_args, - (min_args > 1 || min_args == 0) ? "s" : ""); - return nullptr; + return Error() << StringPrintf("%s requires %zu argument%s", keyword.c_str(), min_args, + (min_args > 1 || min_args == 0) ? "s" : ""); } if (num_args < min_args || num_args > max_args) { if (max_args == std::numeric_limits::max()) { - *err = StringPrintf("%s requires at least %zu argument%s", - keyword.c_str(), min_args, - min_args > 1 ? "s" : ""); + return Error() << StringPrintf("%s requires at least %zu argument%s", + keyword.c_str(), min_args, min_args > 1 ? "s" : ""); } else { - *err = StringPrintf("%s requires between %zu and %zu arguments", - keyword.c_str(), min_args, max_args); + return Error() << StringPrintf("%s requires between %zu and %zu arguments", + keyword.c_str(), min_args, max_args); } - return nullptr; } return std::get(function_info); diff --git a/init/parser.cpp b/init/parser.cpp index 4c34c265b..8a4e798d0 100644 --- a/init/parser.cpp +++ b/init/parser.cpp @@ -67,9 +67,8 @@ void Parser::ParseData(const std::string& filename, const std::string& data) { if (android::base::StartsWith(args[0], prefix.c_str())) { if (section_parser) section_parser->EndSection(); - std::string ret_err; - if (!callback(std::move(args), &ret_err)) { - LOG(ERROR) << filename << ": " << state.line << ": " << ret_err; + if (auto result = callback(std::move(args)); !result) { + LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); } section_parser = nullptr; break; @@ -78,16 +77,16 @@ void Parser::ParseData(const std::string& filename, const std::string& data) { if (section_parsers_.count(args[0])) { if (section_parser) section_parser->EndSection(); section_parser = section_parsers_[args[0]].get(); - std::string ret_err; - if (!section_parser->ParseSection(std::move(args), filename, state.line, - &ret_err)) { - LOG(ERROR) << filename << ": " << state.line << ": " << ret_err; + if (auto result = + section_parser->ParseSection(std::move(args), filename, state.line); + !result) { + LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); section_parser = nullptr; } } else if (section_parser) { - std::string ret_err; - if (!section_parser->ParseLineSection(std::move(args), state.line, &ret_err)) { - LOG(ERROR) << filename << ": " << state.line << ": " << ret_err; + if (auto result = section_parser->ParseLineSection(std::move(args), state.line); + !result) { + LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); } } args.clear(); diff --git a/init/parser.h b/init/parser.h index fd65ad6ff..4ab24a4ee 100644 --- a/init/parser.h +++ b/init/parser.h @@ -22,6 +22,8 @@ #include #include +#include "result.h" + // SectionParser is an interface that can parse a given 'section' in init. // // You can implement up to 4 functions below, with ParseSection() being mandatory. @@ -51,9 +53,9 @@ namespace init { class SectionParser { public: virtual ~SectionParser() {} - virtual bool ParseSection(std::vector&& args, const std::string& filename, - int line, std::string* err) = 0; - virtual bool ParseLineSection(std::vector&&, int, std::string*) { return true; }; + virtual Result ParseSection(std::vector&& args, + const std::string& filename, int line) = 0; + virtual Result ParseLineSection(std::vector&&, int) { return Success(); }; virtual void EndSection(){}; virtual void EndFile(){}; }; @@ -67,7 +69,7 @@ class Parser { // Similar to ParseSection() and ParseLineSection(), this function returns bool with false // indicating a failure and has an std::string* err parameter into which an error string can // be written. - using LineCallback = std::function&&, std::string*)>; + using LineCallback = std::function(std::vector&&)>; Parser(); diff --git a/init/service.cpp b/init/service.cpp index e37888bf8..1b5cc19e4 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -333,12 +333,12 @@ void Service::DumpState() const { [] (const auto& info) { LOG(INFO) << *info; }); } -bool Service::ParseCapabilities(const std::vector& args, std::string* err) { +Result Service::ParseCapabilities(const std::vector& args) { capabilities_ = 0; if (!CapAmbientSupported()) { - *err = "capabilities requested but the kernel does not support ambient capabilities"; - return false; + return Error() + << "capabilities requested but the kernel does not support ambient capabilities"; } unsigned int last_valid_cap = GetLastValidCap(); @@ -350,76 +350,71 @@ bool Service::ParseCapabilities(const std::vector& args, std::strin const std::string& arg = args[i]; int res = LookupCap(arg); if (res < 0) { - *err = StringPrintf("invalid capability '%s'", arg.c_str()); - return false; + return Error() << StringPrintf("invalid capability '%s'", arg.c_str()); } unsigned int cap = static_cast(res); // |res| is >= 0. if (cap > last_valid_cap) { - *err = StringPrintf("capability '%s' not supported by the kernel", arg.c_str()); - return false; + return Error() << StringPrintf("capability '%s' not supported by the kernel", + arg.c_str()); } capabilities_[cap] = true; } - return true; + return Success(); } -bool Service::ParseClass(const std::vector& args, std::string* err) { +Result Service::ParseClass(const std::vector& args) { classnames_ = std::set(args.begin() + 1, args.end()); - return true; + return Success(); } -bool Service::ParseConsole(const std::vector& args, std::string* err) { +Result Service::ParseConsole(const std::vector& args) { flags_ |= SVC_CONSOLE; console_ = args.size() > 1 ? "/dev/" + args[1] : ""; - return true; + return Success(); } -bool Service::ParseCritical(const std::vector& args, std::string* err) { +Result Service::ParseCritical(const std::vector& args) { flags_ |= SVC_CRITICAL; - return true; + return Success(); } -bool Service::ParseDisabled(const std::vector& args, std::string* err) { +Result Service::ParseDisabled(const std::vector& args) { flags_ |= SVC_DISABLED; flags_ |= SVC_RC_DISABLED; - return true; + return Success(); } -bool Service::ParseGroup(const std::vector& args, std::string* err) { +Result Service::ParseGroup(const std::vector& args) { auto gid = DecodeUid(args[1]); if (!gid) { - *err = "Unable to decode GID for '" + args[1] + "': " + gid.error(); - return false; + return Error() << "Unable to decode GID for '" << args[1] << "': " << gid.error(); } gid_ = *gid; for (std::size_t n = 2; n < args.size(); n++) { gid = DecodeUid(args[n]); if (!gid) { - *err = "Unable to decode GID for '" + args[n] + "': " + gid.error(); - return false; + return Error() << "Unable to decode GID for '" << args[n] << "': " << gid.error(); } supp_gids_.emplace_back(*gid); } - return true; + return Success(); } -bool Service::ParsePriority(const std::vector& args, std::string* err) { +Result Service::ParsePriority(const std::vector& args) { priority_ = 0; if (!ParseInt(args[1], &priority_, static_cast(ANDROID_PRIORITY_HIGHEST), // highest is negative static_cast(ANDROID_PRIORITY_LOWEST))) { - *err = StringPrintf("process priority value must be range %d - %d", - ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST); - return false; + return Error() << StringPrintf("process priority value must be range %d - %d", + ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST); } - return true; + return Success(); } -bool Service::ParseIoprio(const std::vector& args, std::string* err) { +Result Service::ParseIoprio(const std::vector& args) { if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { - *err = "priority value must be range 0 - 7"; - return false; + return Error() << "priority value must be range 0 - 7"; } if (args[1] == "rt") { @@ -429,14 +424,13 @@ bool Service::ParseIoprio(const std::vector& args, std::string* err } else if (args[1] == "idle") { ioprio_class_ = IoSchedClass_IDLE; } else { - *err = "ioprio option usage: ioprio <0-7>"; - return false; + return Error() << "ioprio option usage: ioprio <0-7>"; } - return true; + return Success(); } -bool Service::ParseKeycodes(const std::vector& args, std::string* err) { +Result Service::ParseKeycodes(const std::vector& args) { for (std::size_t i = 1; i < args.size(); i++) { int code; if (ParseInt(args[i], &code)) { @@ -445,22 +439,24 @@ bool Service::ParseKeycodes(const std::vector& args, std::string* e LOG(WARNING) << "ignoring invalid keycode: " << args[i]; } } - return true; + return Success(); } -bool Service::ParseOneshot(const std::vector& args, std::string* err) { +Result Service::ParseOneshot(const std::vector& args) { flags_ |= SVC_ONESHOT; - return true; + return Success(); } -bool Service::ParseOnrestart(const std::vector& args, std::string* err) { +Result Service::ParseOnrestart(const std::vector& args) { std::vector str_args(args.begin() + 1, args.end()); int line = onrestart_.NumCommands() + 1; - onrestart_.AddCommand(str_args, line, err); - return true; + if (auto result = onrestart_.AddCommand(str_args, line); !result) { + return Error() << "cannot add Onrestart command: " << result.error(); + } + return Success(); } -bool Service::ParseNamespace(const std::vector& args, std::string* err) { +Result Service::ParseNamespace(const std::vector& args) { for (size_t i = 1; i < args.size(); i++) { if (args[i] == "pid") { namespace_flags_ |= CLONE_NEWPID; @@ -469,65 +465,60 @@ bool Service::ParseNamespace(const std::vector& args, std::string* } else if (args[i] == "mnt") { namespace_flags_ |= CLONE_NEWNS; } else { - *err = "namespace must be 'pid' or 'mnt'"; - return false; + return Error() << "namespace must be 'pid' or 'mnt'"; } } - return true; + return Success(); } -bool Service::ParseOomScoreAdjust(const std::vector& args, std::string* err) { +Result Service::ParseOomScoreAdjust(const std::vector& args) { if (!ParseInt(args[1], &oom_score_adjust_, -1000, 1000)) { - *err = "oom_score_adjust value must be in range -1000 - +1000"; - return false; + return Error() << "oom_score_adjust value must be in range -1000 - +1000"; } - return true; + return Success(); } -bool Service::ParseMemcgSwappiness(const std::vector& args, std::string* err) { +Result Service::ParseMemcgSwappiness(const std::vector& args) { if (!ParseInt(args[1], &swappiness_, 0)) { - *err = "swappiness value must be equal or greater than 0"; - return false; + return Error() << "swappiness value must be equal or greater than 0"; } - return true; + return Success(); } -bool Service::ParseMemcgLimitInBytes(const std::vector& args, std::string* err) { +Result Service::ParseMemcgLimitInBytes(const std::vector& args) { if (!ParseInt(args[1], &limit_in_bytes_, 0)) { - *err = "limit_in_bytes value must be equal or greater than 0"; - return false; + return Error() << "limit_in_bytes value must be equal or greater than 0"; } - return true; + return Success(); } -bool Service::ParseMemcgSoftLimitInBytes(const std::vector& args, std::string* err) { +Result Service::ParseMemcgSoftLimitInBytes(const std::vector& args) { if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) { - *err = "soft_limit_in_bytes value must be equal or greater than 0"; - return false; + return Error() << "soft_limit_in_bytes value must be equal or greater than 0"; } - return true; + return Success(); } -bool Service::ParseSeclabel(const std::vector& args, std::string* err) { +Result Service::ParseSeclabel(const std::vector& args) { seclabel_ = args[1]; - return true; + return Success(); } -bool Service::ParseSetenv(const std::vector& args, std::string* err) { +Result Service::ParseSetenv(const std::vector& args) { envvars_.emplace_back(args[1], args[2]); - return true; + return Success(); } -bool Service::ParseShutdown(const std::vector& args, std::string* err) { +Result Service::ParseShutdown(const std::vector& args) { if (args[1] == "critical") { flags_ |= SVC_SHUTDOWN_CRITICAL; - return true; + return Success(); } - return false; + return Error() << "Invalid shutdown option"; } template -bool Service::AddDescriptor(const std::vector& args, std::string* err) { +Result Service::AddDescriptor(const std::vector& args) { int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1; Result uid = 0; Result gid = 0; @@ -536,16 +527,14 @@ bool Service::AddDescriptor(const std::vector& args, std::string* e if (args.size() > 4) { uid = DecodeUid(args[4]); if (!uid) { - *err = "Unable to find UID for '" + args[4] + "': " + uid.error(); - return false; + return Error() << "Unable to find UID for '" << args[4] << "': " << uid.error(); } } if (args.size() > 5) { gid = DecodeUid(args[5]); if (!gid) { - *err = "Unable to find GID for '" + args[5] + "': " + gid.error(); - return false; + return Error() << "Unable to find GID for '" << args[5] << "': " << gid.error(); } } @@ -556,50 +545,45 @@ bool Service::AddDescriptor(const std::vector& args, std::string* e [&descriptor] (const auto& other) { return descriptor.get() == other.get(); }); if (old != descriptors_.end()) { - *err = "duplicate descriptor " + args[1] + " " + args[2]; - return false; + return Error() << "duplicate descriptor " << args[1] << " " << args[2]; } descriptors_.emplace_back(std::move(descriptor)); - return true; + return Success(); } // name type perm [ uid gid context ] -bool Service::ParseSocket(const std::vector& args, std::string* err) { +Result Service::ParseSocket(const std::vector& args) { if (!StartsWith(args[2], "dgram") && !StartsWith(args[2], "stream") && !StartsWith(args[2], "seqpacket")) { - *err = "socket type must be 'dgram', 'stream' or 'seqpacket'"; - return false; + return Error() << "socket type must be 'dgram', 'stream' or 'seqpacket'"; } - return AddDescriptor(args, err); + return AddDescriptor(args); } // name type perm [ uid gid context ] -bool Service::ParseFile(const std::vector& args, std::string* err) { +Result Service::ParseFile(const std::vector& args) { if (args[2] != "r" && args[2] != "w" && args[2] != "rw") { - *err = "file type must be 'r', 'w' or 'rw'"; - return false; + return Error() << "file type must be 'r', 'w' or 'rw'"; } if ((args[1][0] != '/') || (args[1].find("../") != std::string::npos)) { - *err = "file name must not be relative"; - return false; + return Error() << "file name must not be relative"; } - return AddDescriptor(args, err); + return AddDescriptor(args); } -bool Service::ParseUser(const std::vector& args, std::string* err) { +Result Service::ParseUser(const std::vector& args) { auto uid = DecodeUid(args[1]); if (!uid) { - *err = "Unable to find UID for '" + args[1] + "': " + uid.error(); - return false; + return Error() << "Unable to find UID for '" << args[1] << "': " << uid.error(); } uid_ = *uid; - return true; + return Success(); } -bool Service::ParseWritepid(const std::vector& args, std::string* err) { +Result Service::ParseWritepid(const std::vector& args) { writepid_files_.assign(args.begin() + 1, args.end()); - return true; + return Success(); } class Service::OptionParserMap : public KeywordMap { @@ -647,15 +631,13 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { return option_parsers; } -bool Service::ParseLine(const std::vector& args, std::string* err) { +Result Service::ParseLine(const std::vector& args) { static const OptionParserMap parser_map; - auto parser = parser_map.FindFunction(args, err); + auto parser = parser_map.FindFunction(args); - if (!parser) { - return false; - } + if (!parser) return Error() << parser.error(); - return (this->*parser)(args, err); + return std::invoke(*parser, this, args); } bool Service::ExecStart() { @@ -1044,32 +1026,29 @@ void ServiceList::DumpState() const { } } -bool ServiceParser::ParseSection(std::vector&& args, const std::string& filename, - int line, std::string* err) { +Result ServiceParser::ParseSection(std::vector&& args, + const std::string& filename, int line) { if (args.size() < 3) { - *err = "services must have a name and a program"; - return false; + return Error() << "services must have a name and a program"; } const std::string& name = args[1]; if (!IsValidName(name)) { - *err = StringPrintf("invalid service name '%s'", name.c_str()); - return false; + return Error() << "invalid service name '" << name << "'"; } Service* old_service = service_list_->FindService(name); if (old_service) { - *err = "ignored duplicate definition of service '" + name + "'"; - return false; + return Error() << "ignored duplicate definition of service '" << name << "'"; } std::vector str_args(args.begin() + 2, args.end()); service_ = std::make_unique(name, str_args); - return true; + return Success(); } -bool ServiceParser::ParseLineSection(std::vector&& args, int line, std::string* err) { - return service_ ? service_->ParseLine(std::move(args), err) : false; +Result ServiceParser::ParseLineSection(std::vector&& args, int line) { + return service_ ? service_->ParseLine(std::move(args)) : Success(); } void ServiceParser::EndSection() { diff --git a/init/service.h b/init/service.h index 6c143cb61..fe851299e 100644 --- a/init/service.h +++ b/init/service.h @@ -76,7 +76,7 @@ class Service { static std::unique_ptr MakeTemporaryOneshotService(const std::vector& args); bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; } - bool ParseLine(const std::vector& args, std::string* err); + Result ParseLine(const std::vector& args); bool ExecStart(); bool Start(); bool StartIfNotDisabled(); @@ -119,8 +119,7 @@ class Service { const std::vector& args() const { return args_; } private: - using OptionParser = bool (Service::*) (const std::vector& args, - std::string* err); + using OptionParser = Result (Service::*)(const std::vector& args); class OptionParserMap; void NotifyStateChange(const std::string& new_state) const; @@ -130,32 +129,32 @@ class Service { void KillProcessGroup(int signal); void SetProcessAttributes(); - bool ParseCapabilities(const std::vector& args, std::string *err); - bool ParseClass(const std::vector& args, std::string* err); - bool ParseConsole(const std::vector& args, std::string* err); - bool ParseCritical(const std::vector& args, std::string* err); - bool ParseDisabled(const std::vector& args, std::string* err); - bool ParseGroup(const std::vector& args, std::string* err); - bool ParsePriority(const std::vector& args, std::string* err); - bool ParseIoprio(const std::vector& args, std::string* err); - bool ParseKeycodes(const std::vector& args, std::string* err); - bool ParseOneshot(const std::vector& args, std::string* err); - bool ParseOnrestart(const std::vector& args, std::string* err); - bool ParseOomScoreAdjust(const std::vector& args, std::string* err); - bool ParseMemcgLimitInBytes(const std::vector& args, std::string* err); - bool ParseMemcgSoftLimitInBytes(const std::vector& args, std::string* err); - bool ParseMemcgSwappiness(const std::vector& args, std::string* err); - bool ParseNamespace(const std::vector& args, std::string* err); - bool ParseSeclabel(const std::vector& args, std::string* err); - bool ParseSetenv(const std::vector& args, std::string* err); - bool ParseShutdown(const std::vector& args, std::string* err); - bool ParseSocket(const std::vector& args, std::string* err); - bool ParseFile(const std::vector& args, std::string* err); - bool ParseUser(const std::vector& args, std::string* err); - bool ParseWritepid(const std::vector& args, std::string* err); + Result ParseCapabilities(const std::vector& args); + Result ParseClass(const std::vector& args); + Result ParseConsole(const std::vector& args); + Result ParseCritical(const std::vector& args); + Result ParseDisabled(const std::vector& args); + Result ParseGroup(const std::vector& args); + Result ParsePriority(const std::vector& args); + Result ParseIoprio(const std::vector& args); + Result ParseKeycodes(const std::vector& args); + Result ParseOneshot(const std::vector& args); + Result ParseOnrestart(const std::vector& args); + Result ParseOomScoreAdjust(const std::vector& args); + Result ParseMemcgLimitInBytes(const std::vector& args); + Result ParseMemcgSoftLimitInBytes(const std::vector& args); + Result ParseMemcgSwappiness(const std::vector& args); + Result ParseNamespace(const std::vector& args); + Result ParseSeclabel(const std::vector& args); + Result ParseSetenv(const std::vector& args); + Result ParseShutdown(const std::vector& args); + Result ParseSocket(const std::vector& args); + Result ParseFile(const std::vector& args); + Result ParseUser(const std::vector& args); + Result ParseWritepid(const std::vector& args); template - bool AddDescriptor(const std::vector& args, std::string* err); + Result AddDescriptor(const std::vector& args); static unsigned long next_start_order_; static bool is_exec_service_running_; @@ -242,9 +241,9 @@ class ServiceList { class ServiceParser : public SectionParser { public: ServiceParser(ServiceList* service_list) : service_list_(service_list), service_(nullptr) {} - bool ParseSection(std::vector&& args, const std::string& filename, int line, - std::string* err) override; - bool ParseLineSection(std::vector&& args, int line, std::string* err) override; + Result ParseSection(std::vector&& args, const std::string& filename, + int line) override; + Result ParseLineSection(std::vector&& args, int line) override; void EndSection() override; private: diff --git a/init/ueventd.cpp b/init/ueventd.cpp index b71945acc..1435d82ef 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -223,10 +223,10 @@ DeviceHandler CreateDeviceHandler() { using namespace std::placeholders; std::vector sysfs_permissions; std::vector dev_permissions; - parser.AddSingleLineParser( - "/sys/", std::bind(ParsePermissionsLine, _1, _2, &sysfs_permissions, nullptr)); + parser.AddSingleLineParser("/sys/", + std::bind(ParsePermissionsLine, _1, &sysfs_permissions, nullptr)); parser.AddSingleLineParser("/dev/", - std::bind(ParsePermissionsLine, _1, _2, nullptr, &dev_permissions)); + std::bind(ParsePermissionsLine, _1, nullptr, &dev_permissions)); parser.ParseConfig("/ueventd.rc"); parser.ParseConfig("/vendor/ueventd.rc"); diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp index 02e0d42e5..e831b8b63 100644 --- a/init/ueventd_parser.cpp +++ b/init/ueventd_parser.cpp @@ -24,18 +24,16 @@ namespace android { namespace init { -bool ParsePermissionsLine(std::vector&& args, std::string* err, - std::vector* out_sysfs_permissions, - std::vector* out_dev_permissions) { +Result ParsePermissionsLine(std::vector&& args, + std::vector* out_sysfs_permissions, + std::vector* out_dev_permissions) { bool is_sysfs = out_sysfs_permissions != nullptr; if (is_sysfs && args.size() != 5) { - *err = "/sys/ lines must have 5 entries"; - return false; + return Error() << "/sys/ lines must have 5 entries"; } if (!is_sysfs && args.size() != 4) { - *err = "/dev/ lines must have 4 entries"; - return false; + return Error() << "/dev/ lines must have 4 entries"; } auto it = args.begin(); @@ -49,23 +47,20 @@ bool ParsePermissionsLine(std::vector&& args, std::string* err, char* end_pointer = 0; mode_t perm = strtol(perm_string.c_str(), &end_pointer, 8); if (end_pointer == nullptr || *end_pointer != '\0') { - *err = "invalid mode '" + perm_string + "'"; - return false; + return Error() << "invalid mode '" << perm_string << "'"; } std::string& uid_string = *it++; passwd* pwd = getpwnam(uid_string.c_str()); if (!pwd) { - *err = "invalid uid '" + uid_string + "'"; - return false; + return Error() << "invalid uid '" << uid_string << "'"; } uid_t uid = pwd->pw_uid; std::string& gid_string = *it++; struct group* grp = getgrnam(gid_string.c_str()); if (!grp) { - *err = "invalid gid '" + gid_string + "'"; - return false; + return Error() << "invalid gid '" << gid_string << "'"; } gid_t gid = grp->gr_gid; @@ -74,53 +69,49 @@ bool ParsePermissionsLine(std::vector&& args, std::string* err, } else { out_dev_permissions->emplace_back(name, perm, uid, gid); } - return true; + return Success(); } -bool SubsystemParser::ParseSection(std::vector&& args, const std::string& filename, - int line, std::string* err) { +Result SubsystemParser::ParseSection(std::vector&& args, + const std::string& filename, int line) { if (args.size() != 2) { - *err = "subsystems must have exactly one name"; - return false; + return Error() << "subsystems must have exactly one name"; } if (std::find(subsystems_->begin(), subsystems_->end(), args[1]) != subsystems_->end()) { - *err = "ignoring duplicate subsystem entry"; - return false; + return Error() << "ignoring duplicate subsystem entry"; } subsystem_.name_ = args[1]; - return true; + return Success(); } -bool SubsystemParser::ParseDevName(std::vector&& args, std::string* err) { +Result SubsystemParser::ParseDevName(std::vector&& args) { if (args[1] == "uevent_devname") { subsystem_.devname_source_ = Subsystem::DevnameSource::DEVNAME_UEVENT_DEVNAME; - return true; + return Success(); } if (args[1] == "uevent_devpath") { subsystem_.devname_source_ = Subsystem::DevnameSource::DEVNAME_UEVENT_DEVPATH; - return true; + return Success(); } - *err = "invalid devname '" + args[1] + "'"; - return false; + return Error() << "invalid devname '" << args[1] << "'"; } -bool SubsystemParser::ParseDirName(std::vector&& args, std::string* err) { +Result SubsystemParser::ParseDirName(std::vector&& args) { if (args[1].front() != '/') { - *err = "dirname '" + args[1] + " ' does not start with '/'"; - return false; + return Error() << "dirname '" << args[1] << " ' does not start with '/'"; } subsystem_.dir_name_ = args[1]; - return true; + return Success(); } -bool SubsystemParser::ParseLineSection(std::vector&& args, int line, std::string* err) { - using OptionParser = - bool (SubsystemParser::*)(std::vector && args, std::string * err); +Result SubsystemParser::ParseLineSection(std::vector&& args, int line) { + using OptionParser = Result (SubsystemParser::*)(std::vector && args); + static class OptionParserMap : public KeywordMap { private: const Map& map() const override { @@ -134,13 +125,11 @@ bool SubsystemParser::ParseLineSection(std::vector&& args, int line } } parser_map; - auto parser = parser_map.FindFunction(args, err); + auto parser = parser_map.FindFunction(args); - if (!parser) { - return false; - } + if (!parser) return Error() << parser.error(); - return (this->*parser)(std::move(args), err); + return std::invoke(*parser, this, std::move(args)); } void SubsystemParser::EndSection() { diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h index 51d83ef00..18d1027b4 100644 --- a/init/ueventd_parser.h +++ b/init/ueventd_parser.h @@ -29,22 +29,22 @@ namespace init { class SubsystemParser : public SectionParser { public: SubsystemParser(std::vector* subsystems) : subsystems_(subsystems) {} - bool ParseSection(std::vector&& args, const std::string& filename, int line, - std::string* err) override; - bool ParseLineSection(std::vector&& args, int line, std::string* err) override; + Result ParseSection(std::vector&& args, const std::string& filename, + int line) override; + Result ParseLineSection(std::vector&& args, int line) override; void EndSection() override; private: - bool ParseDevName(std::vector&& args, std::string* err); - bool ParseDirName(std::vector&& args, std::string* err); + Result ParseDevName(std::vector&& args); + Result ParseDirName(std::vector&& args); Subsystem subsystem_; std::vector* subsystems_; }; -bool ParsePermissionsLine(std::vector&& args, std::string* err, - std::vector* out_sysfs_permissions, - std::vector* out_dev_permissions); +Result ParsePermissionsLine(std::vector&& args, + std::vector* out_sysfs_permissions, + std::vector* out_dev_permissions); } // namespace init } // namespace android