diff --git a/init/Android.mk b/init/Android.mk
index 58bff5861..76709513c 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -45,6 +45,7 @@ include $(CLEAR_VARS)
LOCAL_CPPFLAGS := $(init_cflags)
LOCAL_SRC_FILES:= \
action.cpp \
+ import_parser.cpp \
init_parser.cpp \
log.cpp \
parser.cpp \
diff --git a/init/action.cpp b/init/action.cpp
index dd366d3ae..c6cbc2ed6 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -21,46 +21,27 @@
#include
#include
+#include "builtins.h"
#include "error.h"
#include "init_parser.h"
#include "log.h"
#include "property_service.h"
#include "util.h"
-class Action::Command
-{
-public:
- Command(int (*f)(const std::vector& args),
- const std::vector& args,
- const std::string& filename,
- int line);
+using android::base::Join;
+using android::base::StringPrintf;
- int InvokeFunc() const;
- std::string BuildCommandString() const;
- std::string BuildSourceString() const;
-
-private:
- int (*func_)(const std::vector& args);
- const std::vector args_;
- const std::string filename_;
- int line_;
-};
-
-Action::Command::Command(int (*f)(const std::vector& args),
- const std::vector& args,
- const std::string& filename,
- int line) :
- func_(f), args_(args), filename_(filename), line_(line)
-{
+Command::Command(BuiltinFunction f, const std::vector& args,
+ const std::string& filename, int line)
+ : func_(f), args_(args), filename_(filename), line_(line) {
}
-int Action::Command::InvokeFunc() const
-{
+int Command::InvokeFunc() const {
std::vector expanded_args;
expanded_args.resize(args_.size());
expanded_args[0] = args_[0];
for (std::size_t i = 1; i < args_.size(); ++i) {
- if (expand_props(args_[i], &expanded_args[i]) == -1) {
+ if (!expand_props(args_[i], &expanded_args[i])) {
ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str());
return -EINVAL;
}
@@ -69,51 +50,71 @@ int Action::Command::InvokeFunc() const
return func_(expanded_args);
}
-std::string Action::Command::BuildCommandString() const
-{
- return android::base::Join(args_, ' ');
+std::string Command::BuildCommandString() const {
+ return Join(args_, ' ');
}
-std::string Action::Command::BuildSourceString() const
-{
+std::string Command::BuildSourceString() const {
if (!filename_.empty()) {
- return android::base::StringPrintf(" (%s:%d)", filename_.c_str(), line_);
+ return StringPrintf(" (%s:%d)", filename_.c_str(), line_);
} else {
return std::string();
}
}
-Action::Action()
-{
+Action::Action(bool oneshot) : oneshot_(oneshot) {
}
-void Action::AddCommand(int (*f)(const std::vector& args),
+const KeywordMap* Action::function_map_ = nullptr;
+
+bool Action::AddCommand(const std::vector& args,
+ const std::string& filename, int line, std::string* err) {
+ if (!function_map_) {
+ *err = "no function map available";
+ return false;
+ }
+
+ if (args.empty()) {
+ *err = "command needed, but not provided";
+ return false;
+ }
+
+ auto function = function_map_->FindFunction(args[0], args.size() - 1, err);
+ if (!function) {
+ return false;
+ }
+
+ AddCommand(function, args, filename, line);
+ return true;
+}
+
+void Action::AddCommand(BuiltinFunction f,
const std::vector& args,
- const std::string& filename, int line)
-{
- Action::Command* cmd = new Action::Command(f, args, filename, line);
- commands_.push_back(cmd);
+ const std::string& filename, int line) {
+ commands_.emplace_back(f, args, filename, line);
}
-std::size_t Action::NumCommands() const
-{
- return commands_.size();
-}
-
-void Action::ExecuteOneCommand(std::size_t command) const
-{
- ExecuteCommand(*commands_[command]);
-}
-
-void Action::ExecuteAllCommands() const
-{
- for (const auto& c : commands_) {
- ExecuteCommand(*c);
+void Action::CombineAction(const Action& action) {
+ for (const auto& c : action.commands_) {
+ commands_.emplace_back(c);
}
}
-void Action::ExecuteCommand(const Command& command) const
-{
+std::size_t Action::NumCommands() const {
+ return commands_.size();
+}
+
+void Action::ExecuteOneCommand(std::size_t command) const {
+ ExecuteCommand(commands_[command]);
+}
+
+void Action::ExecuteAllCommands() const {
+ for (const auto& c : commands_) {
+ ExecuteCommand(c);
+ }
+}
+
+void Action::ExecuteCommand(const Command& command) const {
Timer t;
int result = command.InvokeFunc();
@@ -128,8 +129,7 @@ void Action::ExecuteCommand(const Command& command) const
}
}
-bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err)
-{
+bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) {
const static std::string prop_str("property:");
std::string prop_name(trigger.substr(prop_str.length()));
size_t equal_pos = prop_name.find('=');
@@ -149,8 +149,7 @@ bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err)
return true;
}
-bool Action::InitTriggers(const std::vector& args, std::string* err)
-{
+bool Action::InitTriggers(const std::vector& args, std::string* err) {
const static std::string prop_str("property:");
for (std::size_t i = 0; i < args.size(); ++i) {
if (i % 2) {
@@ -179,21 +178,26 @@ bool Action::InitTriggers(const std::vector& args, std::string* err
return true;
}
-bool Action::InitSingleTrigger(const std::string& trigger)
-{
+bool Action::InitSingleTrigger(const std::string& trigger) {
std::vector name_vector{trigger};
std::string err;
return InitTriggers(name_vector, &err);
}
+// This function checks that all property triggers are satisfied, that is
+// for each (name, value) in property_triggers_, check that the current
+// value of the property 'name' == value.
+//
+// It takes an optional (name, value) pair, which if provided must
+// be present in property_triggers_; it skips the check of the current
+// property value for this pair.
bool Action::CheckPropertyTriggers(const std::string& name,
- const std::string& value) const
-{
- bool found = name.empty();
+ const std::string& value) const {
if (property_triggers_.empty()) {
return true;
}
+ bool found = name.empty();
for (const auto& t : property_triggers_) {
const auto& trigger_name = t.first;
const auto& trigger_value = t.second;
@@ -214,27 +218,23 @@ bool Action::CheckPropertyTriggers(const std::string& name,
return found;
}
-bool Action::CheckEventTrigger(const std::string& trigger) const
-{
+bool Action::CheckEventTrigger(const std::string& trigger) const {
return !event_trigger_.empty() &&
trigger == event_trigger_ &&
CheckPropertyTriggers();
}
bool Action::CheckPropertyTrigger(const std::string& name,
- const std::string& value) const
-{
+ const std::string& value) const {
return event_trigger_.empty() && CheckPropertyTriggers(name, value);
}
-bool Action::TriggersEqual(const class Action& other) const
-{
+bool Action::TriggersEqual(const Action& other) const {
return property_triggers_ == other.property_triggers_ &&
event_trigger_ == other.event_trigger_;
}
-std::string Action::BuildTriggersString() const
-{
+std::string Action::BuildTriggersString() const {
std::string result;
for (const auto& t : property_triggers_) {
@@ -251,28 +251,26 @@ std::string Action::BuildTriggersString() const
return result;
}
-void Action::DumpState() const
-{
+void Action::DumpState() const {
std::string trigger_name = BuildTriggersString();
INFO("on %s\n", trigger_name.c_str());
for (const auto& c : commands_) {
- std::string cmd_str = c->BuildCommandString();
+ std::string cmd_str = c.BuildCommandString();
INFO(" %s\n", cmd_str.c_str());
}
INFO("\n");
}
-
class EventTrigger : public Trigger {
public:
EventTrigger(const std::string& trigger) : trigger_(trigger) {
}
- bool CheckTriggers(const Action* action) override {
- return action->CheckEventTrigger(trigger_);
+ bool CheckTriggers(const Action& action) const override {
+ return action.CheckEventTrigger(trigger_);
}
private:
- std::string trigger_;
+ const std::string trigger_;
};
class PropertyTrigger : public Trigger {
@@ -280,27 +278,26 @@ public:
PropertyTrigger(const std::string& name, const std::string& value)
: name_(name), value_(value) {
}
- bool CheckTriggers(const Action* action) override {
- return action->CheckPropertyTrigger(name_, value_);
+ bool CheckTriggers(const Action& action) const override {
+ return action.CheckPropertyTrigger(name_, value_);
}
private:
- std::string name_;
- std::string value_;
+ const std::string name_;
+ const std::string value_;
};
class BuiltinTrigger : public Trigger {
public:
BuiltinTrigger(Action* action) : action_(action) {
}
- bool CheckTriggers(const Action* action) override {
- return action == action_;
+ bool CheckTriggers(const Action& action) const override {
+ return action_ == &action;
}
private:
- Action* action_;
+ const Action* action_;
};
-ActionManager::ActionManager() : current_command_(0)
-{
+ActionManager::ActionManager() : current_command_(0) {
}
ActionManager& ActionManager::GetInstance() {
@@ -308,45 +305,56 @@ ActionManager& ActionManager::GetInstance() {
return instance;
}
-void ActionManager::QueueEventTrigger(const std::string& trigger)
-{
+void ActionManager::AddAction(std::unique_ptr action) {
+ auto old_action_it =
+ std::find_if(actions_.begin(), actions_.end(),
+ [&action] (std::unique_ptr& a) {
+ return action->TriggersEqual(*a);
+ });
+
+ if (old_action_it != actions_.end()) {
+ (*old_action_it)->CombineAction(*action);
+ } else {
+ actions_.emplace_back(std::move(action));
+ }
+}
+
+void ActionManager::QueueEventTrigger(const std::string& trigger) {
trigger_queue_.push(std::make_unique(trigger));
}
void ActionManager::QueuePropertyTrigger(const std::string& name,
- const std::string& value)
-{
+ const std::string& value) {
trigger_queue_.push(std::make_unique(name, value));
}
-void ActionManager::QueueAllPropertyTriggers()
-{
+void ActionManager::QueueAllPropertyTriggers() {
QueuePropertyTrigger("", "");
}
-void ActionManager::QueueBuiltinAction(int (*func)(const std::vector& args),
- const std::string& name)
-{
- Action* act = new Action();
+void ActionManager::QueueBuiltinAction(BuiltinFunction func,
+ const std::string& name) {
+ auto action = std::make_unique(true);
std::vector name_vector{name};
- if (!act->InitSingleTrigger(name)) {
+ if (!action->InitSingleTrigger(name)) {
return;
}
- act->AddCommand(func, name_vector);
+ action->AddCommand(func, name_vector);
- actions_.push_back(act);
- trigger_queue_.push(std::make_unique(act));
+ trigger_queue_.push(std::make_unique(action.get()));
+ actions_.emplace_back(std::move(action));
}
void ActionManager::ExecuteOneCommand() {
+ // Loop through the trigger queue until we have an action to execute
while (current_executing_actions_.empty() && !trigger_queue_.empty()) {
- std::copy_if(actions_.begin(), actions_.end(),
- std::back_inserter(current_executing_actions_),
- [this] (Action* act) {
- return trigger_queue_.front()->CheckTriggers(act);
- });
+ for (const auto& action : actions_) {
+ if (trigger_queue_.front()->CheckTriggers(*action)) {
+ current_executing_actions_.emplace(action.get());
+ }
+ }
trigger_queue_.pop();
}
@@ -354,59 +362,67 @@ void ActionManager::ExecuteOneCommand() {
return;
}
- Action* action = current_executing_actions_.back();
- if (!action->NumCommands()) {
- current_executing_actions_.pop_back();
- return;
- }
+ auto action = current_executing_actions_.front();
if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
- INFO("processing action %p (%s)\n", action, trigger_name.c_str());
+ INFO("processing action (%s)\n", trigger_name.c_str());
}
- action->ExecuteOneCommand(current_command_++);
+ action->ExecuteOneCommand(current_command_);
+
+ // If this was the last command in the current action, then remove
+ // the action from the executing list.
+ // If this action was oneshot, then also remove it from actions_.
+ ++current_command_;
if (current_command_ == action->NumCommands()) {
+ current_executing_actions_.pop();
current_command_ = 0;
- current_executing_actions_.pop_back();
+ if (action->oneshot()) {
+ auto eraser = [&action] (std::unique_ptr& a) {
+ return a.get() == action;
+ };
+ actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
+ }
}
}
-bool ActionManager::HasMoreCommands() const
-{
+bool ActionManager::HasMoreCommands() const {
return !current_executing_actions_.empty() || !trigger_queue_.empty();
}
-Action* ActionManager::AddNewAction(const std::vector& triggers,
- std::string* err)
-{
- if (triggers.size() < 1) {
- *err = "actions must have a trigger\n";
- return nullptr;
- }
-
- Action* act = new Action();
- if (!act->InitTriggers(triggers, err)) {
- return nullptr;
- }
-
- auto old_act_it =
- std::find_if(actions_.begin(), actions_.end(),
- [&act] (Action* a) { return act->TriggersEqual(*a); });
-
- if (old_act_it != actions_.end()) {
- delete act;
- return *old_act_it;
- }
-
- actions_.push_back(act);
- return act;
-}
-
-void ActionManager::DumpState() const
-{
+void ActionManager::DumpState() const {
for (const auto& a : actions_) {
a->DumpState();
}
INFO("\n");
}
+
+bool ActionParser::ParseSection(const std::vector& args,
+ std::string* err) {
+ std::vector triggers(args.begin() + 1, args.end());
+ if (triggers.size() < 1) {
+ *err = "actions must have a trigger";
+ return false;
+ }
+
+ auto action = std::make_unique(false);
+ if (!action->InitTriggers(triggers, err)) {
+ return false;
+ }
+
+ action_ = std::move(action);
+ return true;
+}
+
+bool ActionParser::ParseLineSection(const std::vector& args,
+ const std::string& filename, int line,
+ std::string* err) const {
+ return action_ ? action_->AddCommand(args, filename, line, err) : false;
+}
+
+void ActionParser::EndSection() {
+ if (action_ && action_->NumCommands() > 0) {
+ ActionManager::GetInstance().AddAction(std::move(action_));
+ }
+}
diff --git a/init/action.h b/init/action.h
index 5088c710f..6dee2d0a5 100644
--- a/init/action.h
+++ b/init/action.h
@@ -22,13 +22,36 @@
#include
#include
+#include "builtins.h"
+#include "init_parser.h"
+#include "keyword_map.h"
+
+class Command {
+public:
+ Command(BuiltinFunction f, const std::vector& args,
+ const std::string& filename, int line);
+
+ int InvokeFunc() const;
+ std::string BuildCommandString() const;
+ std::string BuildSourceString() const;
+
+private:
+ BuiltinFunction func_;
+ std::vector args_;
+ std::string filename_;
+ int line_;
+};
+
class Action {
public:
- Action();
+ Action(bool oneshot = false);
- void AddCommand(int (*f)(const std::vector& args),
+ bool AddCommand(const std::vector& args,
+ const std::string& filename, int line, std::string* err);
+ void AddCommand(BuiltinFunction f,
const std::vector& args,
const std::string& filename = "", int line = 0);
+ void CombineAction(const Action& action);
bool InitTriggers(const std::vector& args, std::string* err);
bool InitSingleTrigger(const std::string& trigger);
std::size_t NumCommands() const;
@@ -37,13 +60,17 @@ public:
bool CheckEventTrigger(const std::string& trigger) const;
bool CheckPropertyTrigger(const std::string& name,
const std::string& value) const;
- bool TriggersEqual(const class Action& other) const;
+ bool TriggersEqual(const Action& other) const;
std::string BuildTriggersString() const;
void DumpState() const;
-private:
- class Command;
+ bool oneshot() const { return oneshot_; }
+ static void set_function_map(const KeywordMap* function_map) {
+ function_map_ = function_map;
+ }
+
+private:
void ExecuteCommand(const Command& command) const;
bool CheckPropertyTriggers(const std::string& name = "",
const std::string& value = "") const;
@@ -51,27 +78,28 @@ private:
std::map property_triggers_;
std::string event_trigger_;
- std::vector commands_;
+ std::vector commands_;
+ bool oneshot_;
+ static const KeywordMap* function_map_;
};
class Trigger {
public:
virtual ~Trigger() { }
- virtual bool CheckTriggers(const Action* action) = 0;
+ virtual bool CheckTriggers(const Action& action) const = 0;
};
class ActionManager {
public:
static ActionManager& GetInstance();
+
+ void AddAction(std::unique_ptr action);
void QueueEventTrigger(const std::string& trigger);
void QueuePropertyTrigger(const std::string& name, const std::string& value);
void QueueAllPropertyTriggers();
- void QueueBuiltinAction(int (*func)(const std::vector& args),
- const std::string& name);
+ void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
void ExecuteOneCommand();
bool HasMoreCommands() const;
- Action* AddNewAction(const std::vector& triggers,
- std::string* err);
void DumpState() const;
private:
@@ -80,10 +108,26 @@ private:
ActionManager(ActionManager const&) = delete;
void operator=(ActionManager const&) = delete;
- std::vector actions_;
+ std::vector> actions_;
std::queue> trigger_queue_;
- std::vector current_executing_actions_;
+ std::queue current_executing_actions_;
std::size_t current_command_;
};
+class ActionParser : public SectionParser {
+public:
+ ActionParser() : action_(nullptr) {
+ }
+ bool ParseSection(const std::vector& args,
+ std::string* err) override;
+ bool ParseLineSection(const std::vector& args,
+ const std::string& filename, int line,
+ std::string* err) const override;
+ void EndSection() override;
+ void EndFile(const std::string&) override {
+ }
+private:
+ std::unique_ptr action_;
+};
+
#endif
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index efaee1ca8..a768762b0 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -15,7 +15,6 @@
*/
#include "bootchart.h"
-#include "keywords.h"
#include "log.h"
#include "property_service.h"
@@ -32,6 +31,7 @@
#include
#include
+#include
#include
diff --git a/init/bootchart.h b/init/bootchart.h
index cf61d8350..47eda7abe 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -17,6 +17,10 @@
#ifndef _BOOTCHART_H
#define _BOOTCHART_H
+#include
+#include
+
+int do_bootchart_init(const std::vector& args);
void bootchart_sample(int* timeout);
#endif /* _BOOTCHART_H */
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 97151c01b..3ffa2e82c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "builtins.h"
+
#include
#include
#include
@@ -44,10 +46,10 @@
#include
#include "action.h"
+#include "bootchart.h"
#include "devices.h"
#include "init.h"
#include "init_parser.h"
-#include "keywords.h"
#include "log.h"
#include "property_service.h"
#include "service.h"
@@ -60,8 +62,7 @@
// System call provided by bionic but not in any header file.
extern "C" int init_module(void *, unsigned long, const char *);
-static int insmod(const char *filename, const char *options)
-{
+static int insmod(const char *filename, const char *options) {
std::string module;
if (!read_file(filename, &module)) {
return -1;
@@ -71,8 +72,7 @@ static int insmod(const char *filename, const char *options)
return init_module(&module[0], module.size(), options);
}
-static int __ifupdown(const char *interface, int up)
-{
+static int __ifupdown(const char *interface, int up) {
struct ifreq ifr;
int s, ret;
@@ -99,8 +99,7 @@ done:
return ret;
}
-static void unmount_and_fsck(const struct mntent *entry)
-{
+static void unmount_and_fsck(const struct mntent *entry) {
if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
return;
@@ -160,8 +159,7 @@ static void unmount_and_fsck(const struct mntent *entry)
}
}
-int do_class_start(const std::vector& args)
-{
+static int do_class_start(const std::vector& args) {
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
@@ -171,27 +169,23 @@ int do_class_start(const std::vector& args)
return 0;
}
-int do_class_stop(const std::vector& args)
-{
+static int do_class_stop(const std::vector& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Stop(); });
return 0;
}
-int do_class_reset(const std::vector& args)
-{
+static int do_class_reset(const std::vector& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Reset(); });
return 0;
}
-int do_domainname(const std::vector& args)
-{
+static int do_domainname(const std::vector& args) {
return write_file("/proc/sys/kernel/domainname", args[1].c_str());
}
-int do_enable(const std::vector& args)
-{
+static int do_enable(const std::vector& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
return -1;
@@ -199,7 +193,7 @@ int do_enable(const std::vector& args)
return svc->Enable();
}
-int do_exec(const std::vector& args) {
+static int do_exec(const std::vector& args) {
Service* svc = ServiceManager::GetInstance().MakeExecOneshotService(args);
if (!svc) {
return -1;
@@ -211,23 +205,19 @@ int do_exec(const std::vector& args) {
return 0;
}
-int do_export(const std::vector& args)
-{
+static int do_export(const std::vector& args) {
return add_environment(args[1].c_str(), args[2].c_str());
}
-int do_hostname(const std::vector& args)
-{
+static int do_hostname(const std::vector& args) {
return write_file("/proc/sys/kernel/hostname", args[1].c_str());
}
-int do_ifup(const std::vector& args)
-{
+static int do_ifup(const std::vector& args) {
return __ifupdown(args[1].c_str(), 1);
}
-int do_insmod(const std::vector& args)
-{
+static int do_insmod(const std::vector& args) {
std::string options;
if (args.size() > 2) {
@@ -241,8 +231,7 @@ int do_insmod(const std::vector& args)
return insmod(args[1].c_str(), options.c_str());
}
-int do_mkdir(const std::vector& args)
-{
+static int do_mkdir(const std::vector& args) {
mode_t mode = 0755;
int ret;
@@ -310,8 +299,7 @@ static struct {
#define DATA_MNT_POINT "/data"
/* mount */
-int do_mount(const std::vector& args)
-{
+static int do_mount(const std::vector& args) {
char tmp[64];
const char *source, *target, *system;
const char *options = NULL;
@@ -411,8 +399,7 @@ exit_success:
}
-static int wipe_data_via_recovery()
-{
+static int wipe_data_via_recovery() {
mkdir("/cache/recovery", 0700);
int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0600);
if (fd >= 0) {
@@ -427,16 +414,16 @@ static int wipe_data_via_recovery()
while (1) { pause(); } // never reached
}
-void import_late()
-{
+static void import_late() {
static const std::vector init_directories = {
"/system/etc/init",
"/vendor/etc/init",
"/odm/etc/init"
};
+ Parser& parser = Parser::GetInstance();
for (const auto& dir : init_directories) {
- init_parse_config(dir.c_str());
+ parser.ParseConfig(dir.c_str());
}
}
@@ -444,17 +431,13 @@ void import_late()
* This function might request a reboot, in which case it will
* not return.
*/
-int do_mount_all(const std::vector& args)
-{
+static int do_mount_all(const std::vector& args) {
pid_t pid;
int ret = -1;
int child_ret = -1;
int status;
struct fstab *fstab;
- if (args.size() != 2) {
- return -1;
- }
const char* fstabfile = args[1].c_str();
/*
* Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
@@ -535,8 +518,7 @@ int do_mount_all(const std::vector& args)
return ret;
}
-int do_swapon_all(const std::vector& args)
-{
+static int do_swapon_all(const std::vector& args) {
struct fstab *fstab;
int ret;
@@ -547,16 +529,14 @@ int do_swapon_all(const std::vector& args)
return ret;
}
-int do_setprop(const std::vector& args)
-{
+static int do_setprop(const std::vector& args) {
const char* name = args[1].c_str();
const char* value = args[2].c_str();
property_set(name, value);
return 0;
}
-int do_setrlimit(const std::vector& args)
-{
+static int do_setrlimit(const std::vector& args) {
struct rlimit limit;
int resource;
resource = std::stoi(args[1]);
@@ -565,8 +545,7 @@ int do_setrlimit(const std::vector& args)
return setrlimit(resource, &limit);
}
-int do_start(const std::vector& args)
-{
+static int do_start(const std::vector& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_start: Service %s not found\n", args[1].c_str());
@@ -577,8 +556,7 @@ int do_start(const std::vector& args)
return 0;
}
-int do_stop(const std::vector& args)
-{
+static int do_stop(const std::vector& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_stop: Service %s not found\n", args[1].c_str());
@@ -588,8 +566,7 @@ int do_stop(const std::vector& args)
return 0;
}
-int do_restart(const std::vector& args)
-{
+static int do_restart(const std::vector& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_restart: Service %s not found\n", args[1].c_str());
@@ -599,8 +576,7 @@ int do_restart(const std::vector& args)
return 0;
}
-int do_powerctl(const std::vector& args)
-{
+static int do_powerctl(const std::vector& args) {
const char* command = args[1].c_str();
int len = 0;
unsigned int cmd = 0;
@@ -636,34 +612,26 @@ int do_powerctl(const std::vector& args)
callback_on_ro_remount);
}
-int do_trigger(const std::vector& args)
-{
+static int do_trigger(const std::vector& args) {
ActionManager::GetInstance().QueueEventTrigger(args[1]);
return 0;
}
-int do_symlink(const std::vector& args)
-{
+static int do_symlink(const std::vector& args) {
return symlink(args[1].c_str(), args[2].c_str());
}
-int do_rm(const std::vector& args)
-{
+static int do_rm(const std::vector& args) {
return unlink(args[1].c_str());
}
-int do_rmdir(const std::vector& args)
-{
+static int do_rmdir(const std::vector& args) {
return rmdir(args[1].c_str());
}
-int do_sysclktz(const std::vector& args)
-{
+static int do_sysclktz(const std::vector& args) {
struct timezone tz;
- if (args.size() != 2)
- return -1;
-
memset(&tz, 0, sizeof(tz));
tz.tz_minuteswest = std::stoi(args[1]);
if (settimeofday(NULL, &tz))
@@ -671,7 +639,7 @@ int do_sysclktz(const std::vector& args)
return 0;
}
-int do_verity_load_state(const std::vector& args) {
+static int do_verity_load_state(const std::vector& args) {
int mode = -1;
int rc = fs_mgr_load_verity_state(&mode);
if (rc == 0 && mode == VERITY_MODE_LOGGING) {
@@ -680,24 +648,23 @@ int do_verity_load_state(const std::vector& args) {
return rc;
}
-static void verity_update_property(fstab_rec *fstab, const char *mount_point, int mode, int status) {
+static void verity_update_property(fstab_rec *fstab, const char *mount_point,
+ int mode, int status) {
property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(),
android::base::StringPrintf("%d", mode).c_str());
}
-int do_verity_update_state(const std::vector& args) {
+static int do_verity_update_state(const std::vector& args) {
return fs_mgr_update_verity_state(verity_update_property);
}
-int do_write(const std::vector& args)
-{
+static int do_write(const std::vector& args) {
const char* path = args[1].c_str();
const char* value = args[2].c_str();
return write_file(path, value);
}
-int do_copy(const std::vector& args)
-{
+static int do_copy(const std::vector& args) {
char *buffer = NULL;
int rc = 0;
int fd1 = -1, fd2 = -1;
@@ -705,9 +672,6 @@ int do_copy(const std::vector& args)
int brtw, brtr;
char *p;
- if (args.size() != 3)
- return -1;
-
if (stat(args[1].c_str(), &info) < 0)
return -1;
@@ -758,7 +722,7 @@ out:
return rc;
}
-int do_chown(const std::vector& args) {
+static int do_chown(const std::vector& args) {
/* GID is optional. */
if (args.size() == 3) {
if (lchown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1)
@@ -786,7 +750,7 @@ static mode_t get_mode(const char *s) {
return mode;
}
-int do_chmod(const std::vector& args) {
+static int do_chmod(const std::vector& args) {
mode_t mode = get_mode(args[1].c_str());
if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
return -errno;
@@ -794,7 +758,7 @@ int do_chmod(const std::vector& args) {
return 0;
}
-int do_restorecon(const std::vector& args) {
+static int do_restorecon(const std::vector& args) {
int ret = 0;
for (auto it = std::next(args.begin()); it != args.end(); ++it) {
@@ -804,7 +768,7 @@ int do_restorecon(const std::vector& args) {
return ret;
}
-int do_restorecon_recursive(const std::vector& args) {
+static int do_restorecon_recursive(const std::vector& args) {
int ret = 0;
for (auto it = std::next(args.begin()); it != args.end(); ++it) {
@@ -814,12 +778,7 @@ int do_restorecon_recursive(const std::vector& args) {
return ret;
}
-int do_loglevel(const std::vector& args) {
- if (args.size() != 2) {
- ERROR("loglevel: missing argument\n");
- return -EINVAL;
- }
-
+static int do_loglevel(const std::vector& args) {
int log_level = std::stoi(args[1]);
if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
ERROR("loglevel: invalid log level'%d'\n", log_level);
@@ -830,23 +789,16 @@ int do_loglevel(const std::vector& args) {
}
int do_load_persist_props(const std::vector& args) {
- if (args.size() == 1) {
- load_persist_props();
- return 0;
- }
- return -1;
+ load_persist_props();
+ return 0;
}
-int do_load_all_props(const std::vector& args) {
- if (args.size() == 1) {
- load_all_props();
- return 0;
- }
- return -1;
+static int do_load_all_props(const std::vector& args) {
+ load_all_props();
+ return 0;
}
-int do_wait(const std::vector& args)
-{
+static int do_wait(const std::vector& args) {
if (args.size() == 2) {
return wait_for_file(args[1].c_str(), COMMAND_RETRY_TIMEOUT);
} else if (args.size() == 3) {
@@ -858,8 +810,7 @@ int do_wait(const std::vector& args)
/*
* Callback to make a directory from the ext4 code
*/
-static int do_installkeys_ensure_dir_exists(const char* dir)
-{
+static int do_installkeys_ensure_dir_exists(const char* dir) {
if (make_dir(dir, 0700) && errno != EEXIST) {
return -1;
}
@@ -867,12 +818,7 @@ static int do_installkeys_ensure_dir_exists(const char* dir)
return 0;
}
-int do_installkey(const std::vector& args)
-{
- if (args.size() != 2) {
- return -1;
- }
-
+static int do_installkey(const std::vector& args) {
std::string prop_value = property_get("ro.crypto.type");
if (prop_value != "file") {
return 0;
@@ -881,3 +827,49 @@ int do_installkey(const std::vector& args)
return e4crypt_create_device_key(args[1].c_str(),
do_installkeys_ensure_dir_exists);
}
+
+BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
+ constexpr std::size_t kMax = std::numeric_limits::max();
+ static const Map builtin_functions = {
+ {"bootchart_init", {0, 0, do_bootchart_init}},
+ {"chmod", {2, 2, do_chmod}},
+ {"chown", {2, 3, do_chown}},
+ {"class_reset", {1, 1, do_class_reset}},
+ {"class_start", {1, 1, do_class_start}},
+ {"class_stop", {1, 1, do_class_stop}},
+ {"copy", {2, 2, do_copy}},
+ {"domainname", {1, 1, do_domainname}},
+ {"enable", {1, 1, do_enable}},
+ {"exec", {1, kMax, do_exec}},
+ {"export", {2, 2, do_export}},
+ {"hostname", {1, 1, do_hostname}},
+ {"ifup", {1, 1, do_ifup}},
+ {"insmod", {1, kMax, do_insmod}},
+ {"installkey", {1, 1, do_installkey}},
+ {"load_all_props", {0, 0, do_load_all_props}},
+ {"load_persist_props", {0, 0, do_load_persist_props}},
+ {"loglevel", {1, 1, do_loglevel}},
+ {"mkdir", {1, 4, do_mkdir}},
+ {"mount_all", {1, 1, do_mount_all}},
+ {"mount", {3, kMax, do_mount}},
+ {"powerctl", {1, 1, do_powerctl}},
+ {"restart", {1, 1, do_restart}},
+ {"restorecon", {1, kMax, do_restorecon}},
+ {"restorecon_recursive", {1, kMax, do_restorecon_recursive}},
+ {"rm", {1, 1, do_rm}},
+ {"rmdir", {1, 1, do_rmdir}},
+ {"setprop", {2, 2, do_setprop}},
+ {"setrlimit", {3, 3, do_setrlimit}},
+ {"start", {1, 1, do_start}},
+ {"stop", {1, 1, do_stop}},
+ {"swapon_all", {1, 1, do_swapon_all}},
+ {"symlink", {2, 2, do_symlink}},
+ {"sysclktz", {1, 1, do_sysclktz}},
+ {"trigger", {1, 1, do_trigger}},
+ {"verity_load_state", {0, 0, do_verity_load_state}},
+ {"verity_update_state", {0, 0, do_verity_update_state}},
+ {"wait", {1, 2, do_wait}},
+ {"write", {2, 2, do_write}},
+ };
+ return builtin_functions;
+}
diff --git a/init/builtins.h b/init/builtins.h
new file mode 100644
index 000000000..53f4a714f
--- /dev/null
+++ b/init/builtins.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _INIT_BUILTINS_H
+#define _INIT_BUILTINS_H
+
+#include