diff --git a/init/builtins.cpp b/init/builtins.cpp index e2c033a04..d05f046f2 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -62,14 +62,8 @@ extern "C" int init_module(void *, unsigned long, const char *); static int insmod(const char *filename, char *options) { - char filename_val[PROP_VALUE_MAX]; - if (expand_props(filename_val, filename, sizeof(filename_val)) == -1) { - ERROR("insmod: cannot expand '%s'\n", filename); - return -EINVAL; - } - std::string module; - if (!read_file(filename_val, &module)) { + if (!read_file(filename, &module)) { return -1; } @@ -468,17 +462,11 @@ int do_mount_all(int nargs, char **args) int child_ret = -1; int status; struct fstab *fstab; - char fstabfile[PROP_VALUE_MAX]; if (nargs != 2) { return -1; } - - if (expand_props(fstabfile, args[1], sizeof(fstabfile)) == -1) { - ERROR("mount_all: cannot expand '%s' \n", args[1]); - return -EINVAL; - } - + const char* fstabfile = args[1]; /* * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and * do the call in the child to provide protection to the main init @@ -572,15 +560,7 @@ int do_setprop(int nargs, char **args) { const char *name = args[1]; const char *value = args[2]; - char prop_val[PROP_VALUE_MAX]; - int ret; - - ret = expand_props(prop_val, value, sizeof(prop_val)); - if (ret) { - ERROR("cannot expand '%s' while assigning to '%s'\n", value, name); - return -EINVAL; - } - property_set(name, prop_val); + property_set(name, value); return 0; } @@ -626,19 +606,12 @@ int do_restart(int nargs, char **args) int do_powerctl(int nargs, char **args) { - char command[PROP_VALUE_MAX]; - int res; + const char* command = args[1]; int len = 0; int cmd = 0; const char *reboot_target; void (*callback_on_ro_remount)(const struct mntent*) = NULL; - res = expand_props(command, args[1], sizeof(command)); - if (res) { - ERROR("powerctl: cannot expand '%s'\n", args[1]); - return -EINVAL; - } - if (strncmp(command, "shutdown", 8) == 0) { cmd = ANDROID_RB_POWEROFF; len = 8; @@ -666,13 +639,7 @@ int do_powerctl(int nargs, char **args) int do_trigger(int nargs, char **args) { - char prop_val[PROP_VALUE_MAX]; - int res = expand_props(prop_val, args[1], sizeof(prop_val)); - if (res) { - ERROR("trigger: cannot expand '%s'\n", args[1]); - return -EINVAL; - } - action_for_each_trigger(prop_val, action_add_queue_tail); + action_for_each_trigger(args[1], action_add_queue_tail); return 0; } @@ -727,13 +694,7 @@ int do_write(int nargs, char **args) { const char *path = args[1]; const char *value = args[2]; - - char expanded_value[256]; - if (expand_props(expanded_value, value, sizeof(expanded_value))) { - ERROR("cannot expand '%s' while writing to '%s'\n", value, path); - return -EINVAL; - } - return write_file(path, expanded_value); + return write_file(path, value); } int do_copy(int nargs, char **args) @@ -856,18 +817,12 @@ int do_restorecon_recursive(int nargs, char **args) { } int do_loglevel(int nargs, char **args) { - int log_level; - char log_level_str[PROP_VALUE_MAX] = ""; if (nargs != 2) { ERROR("loglevel: missing argument\n"); return -EINVAL; } - if (expand_props(log_level_str, args[1], sizeof(log_level_str))) { - ERROR("loglevel: cannot expand '%s'\n", args[1]); - return -EINVAL; - } - log_level = atoi(log_level_str); + int log_level = atoi(args[1]); if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) { ERROR("loglevel: invalid log level'%d'\n", log_level); return -EINVAL; diff --git a/init/init.cpp b/init/init.cpp index cd1964773..42eebe129 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -570,25 +570,24 @@ static int is_last_command(struct action *act, struct command *cmd) } -void build_triggers_string(char *name_str, int length, struct action *cur_action) { +std::string build_triggers_string(struct action *cur_action) { + std::string result; struct listnode *node; struct trigger *cur_trigger; list_for_each(node, &cur_action->triggers) { cur_trigger = node_to_item(node, struct trigger, nlist); if (node != cur_action->triggers.next) { - strlcat(name_str, " " , length); + result.push_back(' '); } - strlcat(name_str, cur_trigger->name , length); + result += cur_trigger->name; } + return result; } void execute_one_command() { Timer t; - char cmd_str[256] = ""; - char name_str[256] = ""; - if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) { cur_action = action_remove_queue_head(); cur_command = NULL; @@ -596,9 +595,8 @@ void execute_one_command() { return; } - build_triggers_string(name_str, sizeof(name_str), cur_action); - - INFO("processing action %p (%s)\n", cur_action, name_str); + std::string trigger_name = build_triggers_string(cur_action); + INFO("processing action %p (%s)\n", cur_action, trigger_name.c_str()); cur_command = get_first_command(cur_action); } else { cur_command = get_next_command(cur_action, cur_command); @@ -607,23 +605,40 @@ void execute_one_command() { if (!cur_command) { return; } - - int result = cur_command->func(cur_command->nargs, cur_command->args); + int result = 0; + std::vector arg_strs(cur_command->nargs); + arg_strs[0] = cur_command->args[0]; + for (int i = 1; i < cur_command->nargs; ++i) { + if (expand_props(cur_command->args[i], &arg_strs[i]) == -1) { + ERROR("%s: cannot expand '%s'\n", cur_command->args[0], cur_command->args[i]); + result = -EINVAL; + break; + } + } + if (result == 0) { + std::vector args; + for (auto& s : arg_strs) { + args.push_back(&s[0]); + } + result = cur_command->func(args.size(), &args[0]); + } if (klog_get_level() >= KLOG_INFO_LEVEL) { - for (int i = 0; i < cur_command->nargs; i++) { - strlcat(cmd_str, cur_command->args[i], sizeof(cmd_str)); - if (i < cur_command->nargs - 1) { - strlcat(cmd_str, " ", sizeof(cmd_str)); + std::string cmd_str; + for (int i = 0; i < cur_command->nargs; ++i) { + if (i > 0) { + cmd_str.push_back(' '); } + cmd_str += cur_command->args[i]; } - char source[256]; + std::string trigger_name = build_triggers_string(cur_action); + + std::string source; if (cur_command->filename) { - snprintf(source, sizeof(source), " (%s:%d)", cur_command->filename, cur_command->line); - } else { - *source = '\0'; + source = android::base::StringPrintf(" (%s:%d)", cur_command->filename, cur_command->line); } + INFO("Command '%s' action=%s%s returned %d took %.2fs\n", - cmd_str, cur_action ? name_str : "", source, result, t.duration()); + cmd_str.c_str(), trigger_name.c_str(), source.c_str(), result, t.duration()); } } diff --git a/init/init.h b/init/init.h index c1669694b..d81273322 100644 --- a/init/init.h +++ b/init/init.h @@ -138,7 +138,7 @@ extern bool waiting_for_exec; extern struct selabel_handle *sehandle; extern struct selabel_handle *sehandle_prop; -void build_triggers_string(char *name_str, int length, struct action *cur_action); +std::string build_triggers_string(struct action *cur_action); void handle_control_message(const char *msg, const char *arg); diff --git a/init/init_parser.cpp b/init/init_parser.cpp index 41b89f14c..86e9ce68f 100644 --- a/init/init_parser.cpp +++ b/init/init_parser.cpp @@ -95,9 +95,8 @@ void dump_parser_state() { list_for_each(node, &action_list) { action* act = node_to_item(node, struct action, alist); INFO("on "); - char name_str[256] = ""; - build_triggers_string(name_str, sizeof(name_str), act); - INFO("%s", name_str); + std::string trigger_name = build_triggers_string(act); + INFO("%s", trigger_name.c_str()); INFO("\n"); struct listnode* node2; @@ -216,27 +215,12 @@ static int lookup_keyword(const char *s) static void parse_line_no_op(struct parse_state*, int, char**) { } -static int push_chars(char **dst, int *len, const char *chars, int cnt) -{ - if (cnt > *len) - return -1; - - memcpy(*dst, chars, cnt); - *dst += cnt; - *len -= cnt; - - return 0; -} - -int expand_props(char *dst, const char *src, int dst_size) -{ - char *dst_ptr = dst; +int expand_props(const char *src, std::string *dst) { const char *src_ptr = src; - int ret = 0; - int left = dst_size - 1; - if (!src || !dst || dst_size == 0) + if (!src || !dst) { return -1; + } /* - variables can either be $x.y or ${x.y}, in case they are only part * of the string. @@ -244,102 +228,75 @@ int expand_props(char *dst, const char *src, int dst_size) * - no nested property expansion, i.e. ${foo.${bar}} is not supported, * bad things will happen */ - while (*src_ptr && left > 0) { - char *c; - char prop[PROP_NAME_MAX + 1]; - int prop_len = 0; + while (*src_ptr) { + const char *c; c = strchr(src_ptr, '$'); if (!c) { - while (left-- > 0 && *src_ptr) - *(dst_ptr++) = *(src_ptr++); + dst->append(src_ptr); break; } - memset(prop, 0, sizeof(prop)); - - ret = push_chars(&dst_ptr, &left, src_ptr, c - src_ptr); - if (ret < 0) - goto err_nospace; + dst->append(src_ptr, c); c++; if (*c == '$') { - *(dst_ptr++) = *(c++); + dst->push_back(*(c++)); src_ptr = c; - left--; continue; } else if (*c == '\0') { break; } + std::string prop_name; if (*c == '{') { c++; - while (*c && *c != '}' && prop_len < PROP_NAME_MAX) - prop[prop_len++] = *(c++); - if (*c != '}') { - /* failed to find closing brace, abort. */ - if (prop_len == PROP_NAME_MAX) - ERROR("prop name too long during expansion of '%s'\n", - src); - else if (*c == '\0') - ERROR("unexpected end of string in '%s', looking for }\n", - src); + const char* end = strchr(c, '}'); + if (!end) { + // failed to find closing brace, abort. + ERROR("unexpected end of string in '%s', looking for }\n", src); goto err; } - prop[prop_len] = '\0'; - c++; - } else if (*c) { - while (*c && prop_len < PROP_NAME_MAX) - prop[prop_len++] = *(c++); - if (prop_len == PROP_NAME_MAX && *c != '\0') { - ERROR("prop name too long in '%s'\n", src); - goto err; - } - prop[prop_len] = '\0'; + prop_name = std::string(c, end); + c = end + 1; + } else { + prop_name = c; ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n", - prop); + c); + c += prop_name.size(); } - if (prop_len == 0) { + if (prop_name.empty()) { ERROR("invalid zero-length prop name in '%s'\n", src); goto err; } - std::string prop_val = property_get(prop); + std::string prop_val = property_get(prop_name.c_str()); if (prop_val.empty()) { ERROR("property '%s' doesn't exist while expanding '%s'\n", - prop, src); + prop_name.c_str(), src); goto err; } - ret = push_chars(&dst_ptr, &left, prop_val.c_str(), prop_val.size()); - if (ret < 0) - goto err_nospace; + dst->append(prop_val); src_ptr = c; continue; } - *dst_ptr = '\0'; return 0; - -err_nospace: - ERROR("destination buffer overflow while expanding '%s'\n", src); err: return -1; } static void parse_import(struct parse_state *state, int nargs, char **args) { - struct listnode *import_list = (listnode*) state->priv; - char conf_file[PATH_MAX]; - int ret; - if (nargs != 2) { ERROR("single argument needed for import\n"); return; } - ret = expand_props(conf_file, args[1], sizeof(conf_file)); + std::string conf_file; + int ret = expand_props(args[1], &conf_file); if (ret) { ERROR("error while handling import on line '%d' in '%s'\n", state->line, state->filename); @@ -347,7 +304,9 @@ static void parse_import(struct parse_state *state, int nargs, char **args) } struct import* import = (struct import*) calloc(1, sizeof(struct import)); - import->filename = strdup(conf_file); + import->filename = strdup(conf_file.c_str()); + + struct listnode *import_list = (listnode*) state->priv; list_add_tail(import_list, &import->list); INFO("Added '%s' to import list\n", import->filename); } diff --git a/init/init_parser.h b/init/init_parser.h index 90f880f79..fa7e67f95 100644 --- a/init/init_parser.h +++ b/init/init_parser.h @@ -17,6 +17,8 @@ #ifndef _INIT_INIT_PARSER_H_ #define _INIT_INIT_PARSER_H_ +#include + #define INIT_PARSER_MAXARGS 64 struct action; @@ -32,7 +34,7 @@ void queue_all_property_triggers(); void queue_builtin_action(int (*func)(int nargs, char **args), const char *name); bool init_parse_config_file(const char* path); -int expand_props(char *dst, const char *src, int len); +int expand_props(const char *src, std::string *dst); service* make_exec_oneshot_service(int argc, char** argv);