diff options
-rw-r--r-- | edify/edify_parser.cpp | 9 | ||||
-rw-r--r-- | edify/expr.cpp | 119 | ||||
-rw-r--r-- | edify/expr.h | 83 | ||||
-rw-r--r-- | edify/parser.yy | 71 | ||||
-rw-r--r-- | tests/component/edify_test.cpp | 5 | ||||
-rw-r--r-- | tests/component/updater_test.cpp | 3 | ||||
-rw-r--r-- | updater/blockimg.cpp | 54 | ||||
-rw-r--r-- | updater/install.cpp | 242 | ||||
-rw-r--r-- | updater/updater.cpp | 2 |
9 files changed, 331 insertions, 257 deletions
diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp index 908fcf13b..f1b56284c 100644 --- a/edify/edify_parser.cpp +++ b/edify/edify_parser.cpp @@ -27,18 +27,19 @@ #include <errno.h> #include <stdio.h> +#include <memory> #include <string> #include <android-base/file.h> #include "expr.h" -static void ExprDump(int depth, const Expr* n, const std::string& script) { +static void ExprDump(int depth, const std::unique_ptr<Expr>& n, const std::string& script) { printf("%*s", depth*2, ""); printf("%s %p (%d-%d) \"%s\"\n", - n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, + n->name.c_str(), n->fn, n->start, n->end, script.substr(n->start, n->end - n->start).c_str()); - for (int i = 0; i < n->argc; ++i) { + for (size_t i = 0; i < n->argv.size(); ++i) { ExprDump(depth+1, n->argv[i], script); } } @@ -57,7 +58,7 @@ int main(int argc, char** argv) { return 1; } - Expr* root; + std::unique_ptr<Expr> root; int error_count = 0; int error = parse_string(buffer.data(), &root, &error_count); printf("parse returned %d; %d errors encountered\n", error, error_count); diff --git a/edify/expr.cpp b/edify/expr.cpp index 329cf3acd..2b7fd7a6a 100644 --- a/edify/expr.cpp +++ b/edify/expr.cpp @@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) { return !s.empty(); } -bool Evaluate(State* state, Expr* expr, std::string* result) { +bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) { if (result == nullptr) { return false; } - std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv)); + std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv)); if (!v) { return false; } @@ -58,8 +58,8 @@ bool Evaluate(State* state, Expr* expr, std::string* result) { return true; } -Value* EvaluateValue(State* state, Expr* expr) { - return expr->fn(expr->name, state, expr->argc, expr->argv); +Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) { + return expr->fn(expr->name.c_str(), state, expr->argv); } Value* StringValue(const char* str) { @@ -73,12 +73,12 @@ Value* StringValue(const std::string& str) { return StringValue(str.c_str()); } -Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { +Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.empty()) { return StringValue(""); } std::string result; - for (int i = 0; i < argc; ++i) { + for (size_t i = 0; i < argv.size(); ++i) { std::string str; if (!Evaluate(state, argv[i], &str)) { return nullptr; @@ -89,8 +89,8 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2 && argc != 3) { +Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2 && argv.size() != 3) { state->errmsg = "ifelse expects 2 or 3 arguments"; return nullptr; } @@ -102,16 +102,16 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (!cond.empty()) { return EvaluateValue(state, argv[1]); - } else if (argc == 3) { + } else if (argv.size() == 3) { return EvaluateValue(state, argv[2]); } return StringValue(""); } -Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string msg; - if (argc > 0 && Evaluate(state, argv[0], &msg)) { + if (!argv.empty() && Evaluate(state, argv[0], &msg)) { state->errmsg = msg; } else { state->errmsg = "called abort()"; @@ -119,8 +119,8 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { - for (int i = 0; i < argc; ++i) { +Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + for (size_t i = 0; i < argv.size(); ++i) { std::string result; if (!Evaluate(state, argv[i], &result)) { return nullptr; @@ -134,7 +134,7 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(""); } -Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; @@ -149,8 +149,8 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(val); } -Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { - for (int i = 0; i < argc; ++i) { +Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + for (size_t i = 0; i < argv.size(); ++i) { std::string v; if (!Evaluate(state, argv[i], &v)) { return nullptr; @@ -161,7 +161,7 @@ Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* LogicalAndFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -174,7 +174,7 @@ Value* LogicalAndFn(const char* name, State* state, } Value* LogicalOrFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -187,7 +187,7 @@ Value* LogicalOrFn(const char* name, State* state, } Value* LogicalNotFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; @@ -197,7 +197,7 @@ Value* LogicalNotFn(const char* name, State* state, } Value* SubstringFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector<std::unique_ptr<Expr>>& argv) { std::string needle; if (!Evaluate(state, argv[0], &needle)) { return nullptr; @@ -212,7 +212,7 @@ Value* SubstringFn(const char* name, State* state, return StringValue(result); } -Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -226,7 +226,8 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* InequalityFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -240,7 +241,7 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::unique_ptr<Value> left(EvaluateValue(state, argv[0])); if (!left) { return nullptr; @@ -248,14 +249,15 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { return EvaluateValue(state, argv[1]); } -Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { +Value* LessThanIntFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { state->errmsg = "less_than_int expects 2 arguments"; return nullptr; } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return nullptr; } @@ -276,20 +278,34 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* GreaterThanIntFn(const char* name, State* state, - int argc, Expr* argv[]) { - if (argc != 2) { + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { state->errmsg = "greater_than_int expects 2 arguments"; return nullptr; } - Expr* temp[2]; - temp[0] = argv[1]; - temp[1] = argv[0]; + std::vector<std::string> args; + if (!ReadArgs(state, argv, &args)) { + return nullptr; + } + + // Parse up to at least long long or 64-bit integers. + int64_t l_int; + if (!android::base::ParseInt(args[0].c_str(), &l_int)) { + state->errmsg = "failed to parse int in " + args[0]; + return nullptr; + } + + int64_t r_int; + if (!android::base::ParseInt(args[1].c_str(), &r_int)) { + state->errmsg = "failed to parse int in " + args[1]; + return nullptr; + } - return LessThanIntFn(name, state, 2, temp); + return StringValue(l_int > r_int ? "t" : ""); } -Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { +Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { return StringValue(name); } @@ -329,14 +345,22 @@ void RegisterBuiltins() { // convenience methods for functions // ----------------------------------------------------------------- -// Evaluate the expressions in argv, and put the results of strings in -// args. If any expression evaluates to nullptr, free the rest and return -// false. Return true on success. -bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) { +// Evaluate the expressions in argv, and put the results of strings in args. If any expression +// evaluates to nullptr, return false. Return true on success. +bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::string>* args) { + return ReadArgs(state, argv, args, 0, argv.size()); +} + +bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::string>* args, size_t start, size_t len) { if (args == nullptr) { return false; } - for (int i = 0; i < argc; ++i) { + if (len == 0 || start + len > argv.size()) { + return false; + } + for (size_t i = start; i < start + len; ++i) { std::string var; if (!Evaluate(state, argv[i], &var)) { args->clear(); @@ -347,15 +371,22 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* ar return true; } -// Evaluate the expressions in argv, and put the results of Value* in -// args. If any expression evaluate to nullptr, free the rest and return -// false. Return true on success. -bool ReadValueArgs(State* state, int argc, Expr* argv[], +// Evaluate the expressions in argv, and put the results of Value* in args. If any expression +// evaluate to nullptr, return false. Return true on success. +bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args) { + return ReadValueArgs(state, argv, args, 0, argv.size()); +} + +bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) { if (args == nullptr) { return false; } - for (int i = 0; i < argc; ++i) { + if (len == 0 || start + len > argv.size()) { + return false; + } + for (size_t i = start; i < start + len; ++i) { std::unique_ptr<Value> v(EvaluateValue(state, argv[i])); if (!v) { args->clear(); diff --git a/edify/expr.h b/edify/expr.h index 911adbc82..4838d20c0 100644 --- a/edify/expr.h +++ b/edify/expr.h @@ -18,7 +18,10 @@ #define _EXPRESSION_H #include <unistd.h> + +#include <memory> #include <string> +#include <vector> #include "error_code.h" @@ -65,47 +68,49 @@ struct Value { struct Expr; -using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); +using Function = Value* (*)(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv); struct Expr { - Function fn; - const char* name; - int argc; - Expr** argv; - int start, end; + Function fn; + std::string name; + std::vector<std::unique_ptr<Expr>> argv; + int start, end; + + Expr(Function fn, const std::string& name, int start, int end) : + fn(fn), + name(name), + start(start), + end(end) {} }; -// Take one of the Expr*s passed to the function as an argument, -// evaluate it, return the resulting Value. The caller takes -// ownership of the returned Value. -Value* EvaluateValue(State* state, Expr* expr); +// Evaluate the input expr, return the resulting Value. +Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr); -// Take one of the Expr*s passed to the function as an argument, -// evaluate it, assert that it is a string, and update the result -// parameter. This function returns true if the evaluation succeeds. -// This is a convenience function for older functions that want to -// deal only with strings. -bool Evaluate(State* state, Expr* expr, std::string* result); +// Evaluate the input expr, assert that it is a string, and update the result parameter. This +// function returns true if the evaluation succeeds. This is a convenience function for older +// functions that want to deal only with strings. +bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result); // Glue to make an Expr out of a literal. -Value* Literal(const char* name, State* state, int argc, Expr* argv[]); +Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Functions corresponding to various syntactic sugar operators. // ("concat" is also available as a builtin function, to concatenate // more than two strings.) -Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]); -Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]); -Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); -Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); -Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); +Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* LogicalAndFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* LogicalOrFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* LogicalNotFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* SubstringFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Global builtins, registered by RegisterBuiltins(). -Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); -Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); -Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); +Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); +Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Register a new function. The same Function may be registered under // multiple names, but a given name should only be used once. @@ -120,15 +125,19 @@ Function FindFunction(const std::string& name); // --- convenience functions for use in functions --- -// Evaluate the expressions in argv, and put the results of strings in -// args. If any expression evaluates to nullptr, free the rest and return -// false. Return true on success. -bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args); +// Evaluate the expressions in argv, and put the results of strings in args. If any expression +// evaluates to nullptr, return false. Return true on success. +bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::string>* args); +bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::string>* args, size_t start, size_t len); -// Evaluate the expressions in argv, and put the results of Value* in -// args. If any expression evaluate to nullptr, free the rest and return -// false. Return true on success. -bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector<std::unique_ptr<Value>>* args); +// Evaluate the expressions in argv, and put the results of Value* in args. If any +// expression evaluate to nullptr, return false. Return true on success. +bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::unique_ptr<Value>>* args); +bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, + std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len); // Use printf-style arguments to compose an error message to put into // *state. Returns NULL. @@ -145,6 +154,6 @@ Value* StringValue(const char* str); Value* StringValue(const std::string& str); -int parse_string(const char* str, Expr** root, int* error_count); +int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count); #endif // _EXPRESSION_H diff --git a/edify/parser.yy b/edify/parser.yy index 58a8dec65..97205fe3b 100644 --- a/edify/parser.yy +++ b/edify/parser.yy @@ -19,6 +19,10 @@ #include <stdlib.h> #include <string.h> +#include <memory> +#include <string> +#include <vector> + #include "expr.h" #include "yydefs.h" #include "parser.h" @@ -26,8 +30,8 @@ extern int gLine; extern int gColumn; -void yyerror(Expr** root, int* error_count, const char* s); -int yyparse(Expr** root, int* error_count); +void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s); +int yyparse(std::unique_ptr<Expr>* root, int* error_count); struct yy_buffer_state; void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); @@ -38,17 +42,11 @@ struct yy_buffer_state* yy_scan_string(const char* yystr); static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { va_list v; va_start(v, count); - Expr* e = static_cast<Expr*>(malloc(sizeof(Expr))); - e->fn = fn; - e->name = "(operator)"; - e->argc = count; - e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*))); + Expr* e = new Expr(fn, "(operator)", loc.start, loc.end); for (size_t i = 0; i < count; ++i) { - e->argv[i] = va_arg(v, Expr*); + e->argv.emplace_back(va_arg(v, Expr*)); } va_end(v); - e->start = loc.start; - e->end = loc.end; return e; } @@ -59,10 +57,7 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %union { char* str; Expr* expr; - struct { - int argc; - Expr** argv; - } args; + std::vector<std::unique_ptr<Expr>>* args; } %token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF @@ -70,7 +65,10 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %type <expr> expr %type <args> arglist -%parse-param {Expr** root} +%destructor { delete $$; } expr +%destructor { delete $$; } arglist + +%parse-param {std::unique_ptr<Expr>* root} %parse-param {int* error_count} %error-verbose @@ -85,17 +83,11 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %% -input: expr { *root = $1; } +input: expr { root->reset($1); } ; expr: STRING { - $$ = static_cast<Expr*>(malloc(sizeof(Expr))); - $$->fn = Literal; - $$->name = $1; - $$->argc = 0; - $$->argv = NULL; - $$->start = @$.start; - $$->end = @$.end; + $$ = new Expr(Literal, $1, @$.start, @$.end); } | '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } | expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } @@ -110,41 +102,32 @@ expr: STRING { | IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } | IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | STRING '(' arglist ')' { - $$ = static_cast<Expr*>(malloc(sizeof(Expr))); - $$->fn = FindFunction($1); - if ($$->fn == nullptr) { - char buffer[256]; - snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); - yyerror(root, error_count, buffer); + Function fn = FindFunction($1); + if (fn == nullptr) { + std::string msg = "unknown function \"" + std::string($1) + "\""; + yyerror(root, error_count, msg.c_str()); YYERROR; } - $$->name = $1; - $$->argc = $3.argc; - $$->argv = $3.argv; - $$->start = @$.start; - $$->end = @$.end; + $$ = new Expr(fn, $1, @$.start, @$.end); + $$->argv = std::move(*$3); } ; arglist: /* empty */ { - $$.argc = 0; - $$.argv = NULL; + $$ = new std::vector<std::unique_ptr<Expr>>; } | expr { - $$.argc = 1; - $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*))); - $$.argv[0] = $1; + $$ = new std::vector<std::unique_ptr<Expr>>; + $$->emplace_back($1); } | arglist ',' expr { - $$.argc = $1.argc + 1; - $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*))); - $$.argv[$$.argc-1] = $3; + $$->push_back(std::unique_ptr<Expr>($3)); } ; %% -void yyerror(Expr** root, int* error_count, const char* s) { +void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) { if (strlen(s) == 0) { s = "syntax error"; } @@ -152,7 +135,7 @@ void yyerror(Expr** root, int* error_count, const char* s) { ++*error_count; } -int parse_string(const char* str, Expr** root, int* error_count) { +int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) { yy_switch_to_buffer(yy_scan_string(str)); return yyparse(root, error_count); } diff --git a/tests/component/edify_test.cpp b/tests/component/edify_test.cpp index 287e40cc6..61a1e6b64 100644 --- a/tests/component/edify_test.cpp +++ b/tests/component/edify_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <memory> #include <string> #include <gtest/gtest.h> @@ -21,7 +22,7 @@ #include "edify/expr.h" static void expect(const char* expr_str, const char* expected) { - Expr* e; + std::unique_ptr<Expr> e; int error_count = 0; EXPECT_EQ(0, parse_string(expr_str, &e, &error_count)); EXPECT_EQ(0, error_count); @@ -152,7 +153,7 @@ TEST_F(EdifyTest, big_string) { TEST_F(EdifyTest, unknown_function) { // unknown function const char* script1 = "unknown_function()"; - Expr* expr; + std::unique_ptr<Expr> expr; int error_count = 0; EXPECT_EQ(1, parse_string(script1, &expr, &error_count)); EXPECT_EQ(1, error_count); diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 4f8349e2f..ef121a973 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -19,6 +19,7 @@ #include <sys/types.h> #include <unistd.h> +#include <memory> #include <string> #include <vector> @@ -46,7 +47,7 @@ struct selabel_handle *sehandle = nullptr; static void expect(const char* expected, const char* expr_str, CauseCode cause_code, UpdaterInfo* info = nullptr) { - Expr* e; + std::unique_ptr<Expr> e; int error_count = 0; ASSERT_EQ(0, parse_string(expr_str, &e, &error_count)); ASSERT_EQ(0, error_count); diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 8dbd8c7d1..efdfec19a 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -1470,8 +1470,9 @@ struct Command { // - new data stream (filename within package.zip) // - patch stream (filename within package.zip, must be uncompressed) -static Value* PerformBlockImageUpdate(const char* name, State* state, int /* argc */, Expr* argv[], - const Command* commands, size_t cmdcount, bool dryrun) { +static Value* PerformBlockImageUpdate(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv, + const Command* commands, size_t cmdcount, bool dryrun) { CommandParameters params = {}; params.canwrite = !dryrun; @@ -1480,9 +1481,14 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg is_retry = true; LOG(INFO) << "This update is a retry."; } + if (argv.size() != 4) { + ErrorAbort(state, kArgsParsingFailure, "block_image_update expects 4 arguments, got %zu", + argv.size()); + return StringValue(""); + } std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 4, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1762,7 +1768,8 @@ pbiudone: // command has already been completed and verify the integrity of // the source data. -Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageVerifyFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { // Commands which are not tested are set to nullptr to skip them completely const Command commands[] = { { "bsdiff", PerformCommandDiff }, @@ -1776,11 +1783,12 @@ Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[] }; // Perform a dry run without writing to test if an update can proceed - return PerformBlockImageUpdate(name, state, argc, argv, commands, + return PerformBlockImageUpdate(name, state, argv, commands, sizeof(commands) / sizeof(commands[0]), true); } -Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageUpdateFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { const Command commands[] = { { "bsdiff", PerformCommandDiff }, { "erase", PerformCommandErase }, @@ -1792,13 +1800,19 @@ Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[] { "zero", PerformCommandZero } }; - return PerformBlockImageUpdate(name, state, argc, argv, commands, + return PerformBlockImageUpdate(name, state, argv, commands, sizeof(commands) / sizeof(commands[0]), false); } -Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) { +Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + ErrorAbort(state, kArgsParsingFailure, "range_sha1 expects 2 arguments, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 2, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1856,9 +1870,16 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) // 1st block of each partition and check for mounting time/count. It return string "t" // if executes successfully and an empty string otherwise. -Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* CheckFirstBlockFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + ErrorAbort(state, kArgsParsingFailure, "check_first_block expects 1 argument, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 1, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1904,9 +1925,16 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) } -Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageRecoverFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + ErrorAbort(state, kArgsParsingFailure, "block_image_recover expects 2 arguments, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 2, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } diff --git a/updater/install.cpp b/updater/install.cpp index 0963333fc..c9a0270ec 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -126,15 +126,16 @@ static bool make_parents(const std::string& name) { // mount(fs_type, partition_type, location, mount_point) // mount(fs_type, partition_type, location, mount_point, mount_options) -// + // fs_type="ext4" partition_type="EMMC" location=device -Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 4 && argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); +Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 4 && argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -143,7 +144,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { const std::string& mount_point = args[3]; std::string mount_options; - if (argc == 5) { + if (argv.size() == 5) { mount_options = args[4]; } @@ -188,15 +189,14 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } - // is_mounted(mount_point) -Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -214,12 +214,12 @@ Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } -Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -265,13 +265,14 @@ static int exec_cmd(const char* path, char* const argv[]) { // if fs_size == 0, then make fs uses the entire partition. // if fs_size > 0, that is the size to use // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") -Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); +Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -332,13 +333,15 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* ShowProgressFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -361,13 +364,13 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(frac_str); } -Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* SetProgressFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -390,13 +393,15 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { // Example: package_extract_dir("system", "/system") // // Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path. -Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* PackageExtractDirFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>&argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& zip_path = args[0]; @@ -416,17 +421,20 @@ Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[ // Extracts a single package_file from the update package and writes it to dest_file, // overwriting existing files if necessary. Without the dest_file argument, returns the // contents of the package file as a binary blob. -Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1 || argc > 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc); +Value* PackageExtractFileFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1 || argv.size() > 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, + argv.size()); } - if (argc == 2) { + if (argv.size() == 2) { // The two-argument version extracts to a file. std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; const std::string& dest_path = args[1]; @@ -468,8 +476,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv // The one-argument version returns the contents of the file as the result. std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; @@ -495,9 +504,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv } } -Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::string key; if (!Evaluate(state, argv[0], &key)) { @@ -513,13 +522,14 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // interprets 'file' as a getprop-style file (key=value pairs, one // per line. # comment lines, blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). -Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* FileGetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -578,9 +588,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } // apply_patch_space(bytes) -Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, + argv.size()); + } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& bytes_str = args[0]; @@ -606,14 +620,14 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) // state. If the process is interrupted during patching, the target file may be in an intermediate // state; a copy exists in the cache partition so restarting the update can successfully update // the file. -Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 6 || (argc % 2) == 1) { +Value* ApplyPatchFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 6 || (argv.size() % 2) == 1) { return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " - "even number, got %d", name, argc); + "even number, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 4, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 4)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& source_filename = args[0]; @@ -627,9 +641,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { name, target_size_str.c_str()); } - int patchcount = (argc-4) / 2; + int patchcount = (argv.size()-4) / 2; std::vector<std::unique_ptr<Value>> arg_values; - if (!ReadValueArgs(state, argc-4, argv+4, &arg_values)) { + if (!ReadValueArgs(state, argv, &arg_values, 4, argv.size() - 4)) { return nullptr; } @@ -664,20 +678,20 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { // specified as 40 hex digits. This function differs from sha1_check(read_file(filename), // sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will // succeed even if the file was corrupted by an interrupted apply_patch() update. -Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", name, - argc); +Value* ApplyPatchCheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; std::vector<std::string> sha1s; - if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { + if (!ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } int result = applypatch_check(filename.c_str(), sha1s); @@ -687,9 +701,9 @@ Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) // This is the updater side handler for ui_print() in edify script. Contents // will be sent over to the recovery side for on-screen display. -Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } @@ -698,31 +712,32 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(buffer); } -Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n"); return StringValue("t"); } -Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - char* args2[argc + 1]; - for (int i = 0; i < argc; i++) { + char* args2[argv.size() + 1]; + for (size_t i = 0; i < argv.size(); i++) { args2[i] = &args[i][0]; } - args2[argc] = nullptr; + args2[argv.size()] = nullptr; - LOG(INFO) << "about to run program [" << args2[0] << "] with " << argc << " args"; + LOG(INFO) << "about to run program [" << args2[0] << "] with " << argv.size() << " args"; pid_t child = fork(); if (child == 0) { @@ -752,13 +767,13 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { // returns the sha1 of the file if it matches any of the hex // strings passed, or "" if it does not equal any of them. // -Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* Sha1CheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, argc, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -768,11 +783,11 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { uint8_t digest[SHA_DIGEST_LENGTH]; SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest); - if (argc == 1) { + if (argv.size() == 1) { return StringValue(print_sha1(digest)); } - for (int i = 1; i < argc; ++i) { + for (size_t i = 1; i < argv.size(); ++i) { uint8_t arg_digest[SHA_DIGEST_LENGTH]; if (args[i]->type != VAL_STRING) { LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; @@ -791,13 +806,13 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { // Read a local file and return its contents (the Value* returned // is actually a FileContents*). -Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -815,13 +830,14 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { // write_value(value, filename) // Writes 'value' to 'filename'. // Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") -Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } @@ -848,13 +864,14 @@ Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { // property. It can be "recovery" to boot from the recovery // partition, or "" (empty string) to boot from the regular boot // partition. -Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -890,13 +907,14 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // ("/misc" in the fstab), which is where this value is stored. The // second argument is the string to store; it should not exceed 31 // bytes. -Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -923,13 +941,13 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. -Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -944,13 +962,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(boot.stage); } -Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -967,38 +986,39 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) return StringValue((status == 0) ? "t" : ""); } -Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie); fprintf(ui->cmd_pipe, "enable_reboot\n"); return StringValue("t"); } -Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); +Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); } - char* args2[argc + 1]; + char* args2[argv.size() + 1]; // Tune2fs expects the program name as its args[0] args2[0] = const_cast<char*>(name); if (args2[0] == nullptr) { return nullptr; } - for (int i = 0; i < argc; ++i) { + for (size_t i = 0; i < argv.size(); ++i) { args2[i + 1] = &args[i][0]; } // tune2fs changes the file system parameters on an ext2 file system; it // returns 0 on success. - int result = tune2fs_main(argc + 1, args2); + int result = tune2fs_main(argv.size() + 1, args2); if (result != 0) { return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); } diff --git a/updater/updater.cpp b/updater/updater.cpp index 22c060fcb..0693cbd98 100644 --- a/updater/updater.cpp +++ b/updater/updater.cpp @@ -130,7 +130,7 @@ int main(int argc, char** argv) { // Parse the script. - Expr* root; + std::unique_ptr<Expr> root; int error_count = 0; int error = parse_string(script.c_str(), &root, &error_count); if (error != 0 || error_count > 0) { |