diff options
82 files changed, 253 insertions, 5327 deletions
diff --git a/Android.mk b/Android.mk index 0367fef70..deec80ae4 100644 --- a/Android.mk +++ b/Android.mk @@ -1,15 +1,14 @@ +ifneq ($(TARGET_SIMULATOR),true) +ifeq ($(TARGET_ARCH),arm) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) commands_recovery_local_path := $(LOCAL_PATH) -ifneq ($(TARGET_SIMULATOR),true) -ifeq ($(TARGET_ARCH),arm) - LOCAL_SRC_FILES := \ recovery.c \ bootloader.c \ - commands.c \ firmware.c \ install.c \ roots.c \ @@ -32,14 +31,19 @@ LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) LOCAL_MODULE_TAGS := eng -LOCAL_STATIC_LIBRARIES := libminzip libunz libamend libmtdutils libmincrypt +LOCAL_STATIC_LIBRARIES := +ifeq ($(TARGET_RECOVERY_UI_LIB),) + LOCAL_SRC_FILES += default_recovery_ui.c +else + LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) +endif +LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmincrypt LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils LOCAL_STATIC_LIBRARIES += libstdc++ libc include $(BUILD_EXECUTABLE) include $(commands_recovery_local_path)/minui/Android.mk -include $(commands_recovery_local_path)/amend/Android.mk include $(commands_recovery_local_path)/minzip/Android.mk include $(commands_recovery_local_path)/mtdutils/Android.mk include $(commands_recovery_local_path)/tools/Android.mk diff --git a/amend/Android.mk b/amend/Android.mk deleted file mode 100644 index c3b7c3277..000000000 --- a/amend/Android.mk +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2007 The Android Open Source Project -# - -LOCAL_PATH := $(call my-dir) - -amend_src_files := \ - amend.c \ - lexer.l \ - parser_y.y \ - ast.c \ - symtab.c \ - commands.c \ - execute.c - -amend_test_files := \ - test_symtab.c \ - test_commands.c - -# "-x c" forces the lex/yacc files to be compiled as c; -# the build system otherwise forces them to be c++. -amend_cflags := -Wall -x c - -# -# Build the host-side command line tool -# -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - $(amend_src_files) \ - $(amend_test_files) \ - register.c \ - main.c - -LOCAL_CFLAGS := $(amend_cflags) -g -O0 -LOCAL_MODULE := amend -LOCAL_YACCFLAGS := -v - -include $(BUILD_HOST_EXECUTABLE) - -# -# Build the device-side library -# -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(amend_src_files) -LOCAL_SRC_FILES += $(amend_test_files) - -LOCAL_CFLAGS := $(amend_cflags) -LOCAL_MODULE := libamend - -include $(BUILD_STATIC_LIBRARY) diff --git a/amend/amend.c b/amend/amend.c deleted file mode 100644 index 6f706d021..000000000 --- a/amend/amend.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include "amend.h" -#include "lexer.h" -#include "parser.h" - -extern const AmCommandList *gCommands; - -const AmCommandList * -parseAmendScript(const char *buf, size_t bufLen) -{ - setLexerInputBuffer(buf, bufLen); - int ret = yyparse(); - if (ret != 0) { - return NULL; - } - return gCommands; -} diff --git a/amend/amend.h b/amend/amend.h deleted file mode 100644 index 416f974e9..000000000 --- a/amend/amend.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_H_ -#define AMEND_H_ - -#include "ast.h" -#include "execute.h" - -const AmCommandList *parseAmendScript(const char *buf, size_t bufLen); - -#endif // AMEND_H_ diff --git a/amend/ast.c b/amend/ast.c deleted file mode 100644 index f53efdc9c..000000000 --- a/amend/ast.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdio.h> -#include "ast.h" - -static const char gSpaces[] = - " " - " " - " " - " " - " " - " " - " "; -const int gSpacesMax = sizeof(gSpaces) - 1; - -static const char * -pad(int level) -{ - level *= 4; - if (level > gSpacesMax) { - level = gSpacesMax; - } - return gSpaces + gSpacesMax - level; -} - -void dumpBooleanValue(int level, const AmBooleanValue *booleanValue); -void dumpStringValue(int level, const AmStringValue *stringValue); - -void -dumpBooleanExpression(int level, const AmBooleanExpression *booleanExpression) -{ - const char *op; - bool unary = false; - - switch (booleanExpression->op) { - case AM_BOP_NOT: - op = "NOT"; - unary = true; - break; - case AM_BOP_EQ: - op = "EQ"; - break; - case AM_BOP_NE: - op = "NE"; - break; - case AM_BOP_AND: - op = "AND"; - break; - case AM_BOP_OR: - op = "OR"; - break; - default: - op = "??"; - break; - } - - printf("%sBOOLEAN %s {\n", pad(level), op); - dumpBooleanValue(level + 1, booleanExpression->arg1); - if (!unary) { - dumpBooleanValue(level + 1, booleanExpression->arg2); - } - printf("%s}\n", pad(level)); -} - -void -dumpFunctionArguments(int level, const AmFunctionArguments *functionArguments) -{ - int i; - for (i = 0; i < functionArguments->argc; i++) { - dumpStringValue(level, &functionArguments->argv[i]); - } -} - -void -dumpFunctionCall(int level, const AmFunctionCall *functionCall) -{ - printf("%sFUNCTION %s (\n", pad(level), functionCall->name); - dumpFunctionArguments(level + 1, functionCall->args); - printf("%s)\n", pad(level)); -} - -void -dumpStringValue(int level, const AmStringValue *stringValue) -{ - switch (stringValue->type) { - case AM_SVAL_LITERAL: - printf("%s\"%s\"\n", pad(level), stringValue->u.literal); - break; - case AM_SVAL_FUNCTION: - dumpFunctionCall(level, stringValue->u.function); - break; - default: - printf("%s<UNKNOWN SVAL TYPE %d>\n", pad(level), stringValue->type); - break; - } -} - -void -dumpStringComparisonExpression(int level, - const AmStringComparisonExpression *stringComparisonExpression) -{ - const char *op; - - switch (stringComparisonExpression->op) { - case AM_SOP_LT: - op = "LT"; - break; - case AM_SOP_LE: - op = "LE"; - break; - case AM_SOP_GT: - op = "GT"; - break; - case AM_SOP_GE: - op = "GE"; - break; - case AM_SOP_EQ: - op = "EQ"; - break; - case AM_SOP_NE: - op = "NE"; - break; - default: - op = "??"; - break; - } - printf("%sSTRING %s {\n", pad(level), op); - dumpStringValue(level + 1, stringComparisonExpression->arg1); - dumpStringValue(level + 1, stringComparisonExpression->arg2); - printf("%s}\n", pad(level)); -} - -void -dumpBooleanValue(int level, const AmBooleanValue *booleanValue) -{ - switch (booleanValue->type) { - case AM_BVAL_EXPRESSION: - dumpBooleanExpression(level, &booleanValue->u.expression); - break; - case AM_BVAL_STRING_COMPARISON: - dumpStringComparisonExpression(level, - &booleanValue->u.stringComparison); - break; - default: - printf("%s<UNKNOWN BVAL TYPE %d>\n", pad(1), booleanValue->type); - break; - } -} - -void -dumpWordList(const AmWordList *wordList) -{ - int i; - for (i = 0; i < wordList->argc; i++) { - printf("%s\"%s\"\n", pad(1), wordList->argv[i]); - } -} - -void -dumpCommandArguments(const AmCommandArguments *commandArguments) -{ - if (commandArguments->booleanArgs) { - dumpBooleanValue(1, commandArguments->u.b); - } else { - dumpWordList(commandArguments->u.w); - } -} - -void -dumpCommand(const AmCommand *command) -{ - printf("command \"%s\" {\n", command->name); - dumpCommandArguments(command->args); - printf("}\n"); -} - -void -dumpCommandList(const AmCommandList *commandList) -{ - int i; - for (i = 0; i < commandList->commandCount; i++) { - dumpCommand(commandList->commands[i]); - } -} diff --git a/amend/ast.h b/amend/ast.h deleted file mode 100644 index 7834a2bdd..000000000 --- a/amend/ast.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_AST_H_ -#define AMEND_AST_H_ - -#include "commands.h" - -typedef struct AmStringValue AmStringValue; - -typedef struct { - int argc; - AmStringValue *argv; -} AmFunctionArguments; - -/* An internal structure used only by the parser; - * will not appear in the output AST. -xxx try to move this into parser.h - */ -typedef struct AmFunctionArgumentBuilder AmFunctionArgumentBuilder; -struct AmFunctionArgumentBuilder { - AmFunctionArgumentBuilder *next; - AmStringValue *arg; - int argCount; -}; - -typedef struct AmWordListBuilder AmWordListBuilder; -struct AmWordListBuilder { - AmWordListBuilder *next; - const char *word; - int wordCount; -}; - -typedef struct { - const char *name; - Function *fn; - AmFunctionArguments *args; -} AmFunctionCall; - - -/* <string-value> ::= - * <literal-string> | - * <function-call> - */ -struct AmStringValue { - unsigned int line; - - enum { - AM_SVAL_LITERAL, - AM_SVAL_FUNCTION, - } type; - union { - const char *literal; -//xxx inline instead of using pointers - AmFunctionCall *function; - } u; -}; - - -/* <string-comparison-expression> ::= - * <string-value> <string-comparison-operator> <string-value> - */ -typedef struct { - unsigned int line; - - enum { - AM_SOP_LT, - AM_SOP_LE, - AM_SOP_GT, - AM_SOP_GE, - AM_SOP_EQ, - AM_SOP_NE, - } op; - AmStringValue *arg1; - AmStringValue *arg2; -} AmStringComparisonExpression; - - -/* <boolean-expression> ::= - * ! <boolean-value> | - * <boolean-value> <binary-boolean-operator> <boolean-value> - */ -typedef struct AmBooleanValue AmBooleanValue; -typedef struct { - unsigned int line; - - enum { - AM_BOP_NOT, - - AM_BOP_EQ, - AM_BOP_NE, - - AM_BOP_AND, - - AM_BOP_OR, - } op; - AmBooleanValue *arg1; - AmBooleanValue *arg2; -} AmBooleanExpression; - - -/* <boolean-value> ::= - * <boolean-expression> | - * <string-comparison-expression> - */ -struct AmBooleanValue { - unsigned int line; - - enum { - AM_BVAL_EXPRESSION, - AM_BVAL_STRING_COMPARISON, - } type; - union { - AmBooleanExpression expression; - AmStringComparisonExpression stringComparison; - } u; -}; - - -typedef struct { - unsigned int line; - - int argc; - const char **argv; -} AmWordList; - - -typedef struct { - bool booleanArgs; - union { - AmWordList *w; - AmBooleanValue *b; - } u; -} AmCommandArguments; - -typedef struct { - unsigned int line; - - const char *name; - Command *cmd; - AmCommandArguments *args; -} AmCommand; - -typedef struct { - AmCommand **commands; - int commandCount; - int arraySize; -} AmCommandList; - -void dumpCommandList(const AmCommandList *commandList); - -#endif // AMEND_AST_H_ diff --git a/amend/commands.c b/amend/commands.c deleted file mode 100644 index 78121adf1..000000000 --- a/amend/commands.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include "symtab.h" -#include "commands.h" - -#if 1 -#define TRACE(...) printf(__VA_ARGS__) -#else -#define TRACE(...) /**/ -#endif - -typedef enum { - CMD_TYPE_UNKNOWN = -1, - CMD_TYPE_COMMAND = 0, - CMD_TYPE_FUNCTION -} CommandType; - -typedef struct { - const char *name; - void *cookie; - CommandType type; - CommandArgumentType argType; - CommandHook hook; -} CommandEntry; - -static struct { - SymbolTable *symbolTable; - bool commandStateInitialized; -} gCommandState; - -int -commandInit() -{ - if (gCommandState.commandStateInitialized) { - return -1; - } - gCommandState.symbolTable = createSymbolTable(); - if (gCommandState.symbolTable == NULL) { - return -1; - } - gCommandState.commandStateInitialized = true; - return 0; -} - -void -commandCleanup() -{ - if (gCommandState.commandStateInitialized) { - gCommandState.commandStateInitialized = false; - deleteSymbolTable(gCommandState.symbolTable); - gCommandState.symbolTable = NULL; -//xxx need to free the entries and names in the symbol table - } -} - -static int -registerCommandInternal(const char *name, CommandType type, - CommandArgumentType argType, CommandHook hook, void *cookie) -{ - CommandEntry *entry; - - if (!gCommandState.commandStateInitialized) { - return -1; - } - if (name == NULL || hook == NULL) { - return -1; - } - if (type != CMD_TYPE_COMMAND && type != CMD_TYPE_FUNCTION) { - return -1; - } - if (argType != CMD_ARGS_BOOLEAN && argType != CMD_ARGS_WORDS) { - return -1; - } - - entry = (CommandEntry *)malloc(sizeof(CommandEntry)); - if (entry != NULL) { - entry->name = strdup(name); - if (entry->name != NULL) { - int ret; - - entry->cookie = cookie; - entry->type = type; - entry->argType = argType; - entry->hook = hook; - ret = addToSymbolTable(gCommandState.symbolTable, - entry->name, entry->type, entry); - if (ret == 0) { - return 0; - } - } - free(entry); - } - - return -1; -} - -int -registerCommand(const char *name, - CommandArgumentType argType, CommandHook hook, void *cookie) -{ - return registerCommandInternal(name, - CMD_TYPE_COMMAND, argType, hook, cookie); -} - -int -registerFunction(const char *name, FunctionHook hook, void *cookie) -{ - return registerCommandInternal(name, - CMD_TYPE_FUNCTION, CMD_ARGS_WORDS, (CommandHook)hook, cookie); -} - -Command * -findCommand(const char *name) -{ - return (Command *)findInSymbolTable(gCommandState.symbolTable, - name, CMD_TYPE_COMMAND); -} - -Function * -findFunction(const char *name) -{ - return (Function *)findInSymbolTable(gCommandState.symbolTable, - name, CMD_TYPE_FUNCTION); -} - -CommandArgumentType -getCommandArgumentType(Command *cmd) -{ - CommandEntry *entry = (CommandEntry *)cmd; - - if (entry != NULL) { - return entry->argType; - } - return CMD_ARGS_UNKNOWN; -} - -static int -callCommandInternal(CommandEntry *entry, int argc, const char *argv[]) -{ - if (entry != NULL && entry->argType == CMD_ARGS_WORDS && - (argc == 0 || (argc > 0 && argv != NULL))) - { - int i; - for (i = 0; i < argc; i++) { - if (argv[i] == NULL) { - goto bail; - } - } - TRACE("calling command %s\n", entry->name); - return entry->hook(entry->name, entry->cookie, argc, argv); - } -bail: - return -1; -} - -static int -callBooleanCommandInternal(CommandEntry *entry, bool arg) -{ - if (entry != NULL && entry->argType == CMD_ARGS_BOOLEAN) { - TRACE("calling boolean command %s\n", entry->name); - return entry->hook(entry->name, entry->cookie, arg ? 1 : 0, NULL); - } - return -1; -} - -int -callCommand(Command *cmd, int argc, const char *argv[]) -{ - return callCommandInternal((CommandEntry *)cmd, argc, argv); -} - -int -callBooleanCommand(Command *cmd, bool arg) -{ - return callBooleanCommandInternal((CommandEntry *)cmd, arg); -} - -int -callFunctionInternal(CommandEntry *entry, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - if (entry != NULL && entry->argType == CMD_ARGS_WORDS && - (argc == 0 || (argc > 0 && argv != NULL))) - { - if (result != NULL) - { - /* This is the actual invocation of the function, - * which means that none of the arguments are allowed - * to be NULL. - */ - int i; - for (i = 0; i < argc; i++) { - if (argv[i] == NULL) { - goto bail; - } - } - TRACE("calling function %s\n", entry->name); - return ((FunctionHook)entry->hook)(entry->name, entry->cookie, - argc, argv, result, resultLen); - } - } -bail: - return -1; -} - -int -callFunction(Function *fn, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - return callFunctionInternal((CommandEntry *)fn, argc, argv, - result, resultLen); -} diff --git a/amend/commands.h b/amend/commands.h deleted file mode 100644 index 6c97e5587..000000000 --- a/amend/commands.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdbool.h> - -#ifndef AMEND_COMMANDS_H_ -#define AMEND_COMMANDS_H_ - -/* Invoke a command. - * - * When a boolean command is called, "argc" is the boolean value and - * "argv" is NULL. - */ -typedef int (*CommandHook)(const char *name, void *cookie, - int argc, const char *argv[]); - -int commandInit(void); -void commandCleanup(void); - -/* - * Command management - */ - -struct Command; -typedef struct Command Command; - -typedef enum { - CMD_ARGS_UNKNOWN = -1, - CMD_ARGS_BOOLEAN = 0, - CMD_ARGS_WORDS -} CommandArgumentType; - -int registerCommand(const char *name, - CommandArgumentType argType, CommandHook hook, void *cookie); - -Command *findCommand(const char *name); - -CommandArgumentType getCommandArgumentType(Command *cmd); - -int callCommand(Command *cmd, int argc, const char *argv[]); -int callBooleanCommand(Command *cmd, bool arg); - -/* - * Function management - */ - -typedef int (*FunctionHook)(const char *name, void *cookie, - int argc, const char *argv[], - char **result, size_t *resultLen); - -struct Function; -typedef struct Function Function; - -int registerFunction(const char *name, FunctionHook hook, void *cookie); - -Function *findFunction(const char *name); - -int callFunction(Function *fn, int argc, const char *argv[], - char **result, size_t *resultLen); - -#endif // AMEND_COMMANDS_H_ diff --git a/amend/execute.c b/amend/execute.c deleted file mode 100644 index 9162ad647..000000000 --- a/amend/execute.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#undef NDEBUG -#include <assert.h> -#include "ast.h" -#include "execute.h" - -typedef struct { - int c; - const char **v; -} StringList; - -static int execBooleanValue(ExecContext *ctx, - const AmBooleanValue *booleanValue, bool *result); -static int execStringValue(ExecContext *ctx, const AmStringValue *stringValue, - const char **result); - -static int -execBooleanExpression(ExecContext *ctx, - const AmBooleanExpression *booleanExpression, bool *result) -{ - int ret; - bool arg1, arg2; - bool unary; - - assert(ctx != NULL); - assert(booleanExpression != NULL); - assert(result != NULL); - if (ctx == NULL || booleanExpression == NULL || result == NULL) { - return -__LINE__; - } - - if (booleanExpression->op == AM_BOP_NOT) { - unary = true; - } else { - unary = false; - } - - ret = execBooleanValue(ctx, booleanExpression->arg1, &arg1); - if (ret != 0) return ret; - - if (!unary) { - ret = execBooleanValue(ctx, booleanExpression->arg2, &arg2); - if (ret != 0) return ret; - } else { - arg2 = false; - } - - switch (booleanExpression->op) { - case AM_BOP_NOT: - *result = !arg1; - break; - case AM_BOP_EQ: - *result = (arg1 == arg2); - break; - case AM_BOP_NE: - *result = (arg1 != arg2); - break; - case AM_BOP_AND: - *result = (arg1 && arg2); - break; - case AM_BOP_OR: - *result = (arg1 || arg2); - break; - default: - return -__LINE__; - } - - return 0; -} - -static int -execFunctionArguments(ExecContext *ctx, - const AmFunctionArguments *functionArguments, StringList *result) -{ - int ret; - - assert(ctx != NULL); - assert(functionArguments != NULL); - assert(result != NULL); - if (ctx == NULL || functionArguments == NULL || result == NULL) { - return -__LINE__; - } - - result->c = functionArguments->argc; - result->v = (const char **)malloc(result->c * sizeof(const char *)); - if (result->v == NULL) { - result->c = 0; - return -__LINE__; - } - - int i; - for (i = 0; i < functionArguments->argc; i++) { - ret = execStringValue(ctx, &functionArguments->argv[i], &result->v[i]); - if (ret != 0) { - result->c = 0; - free(result->v); - //TODO: free the individual args, if we're responsible for them. - result->v = NULL; - return ret; - } - } - - return 0; -} - -static int -execFunctionCall(ExecContext *ctx, const AmFunctionCall *functionCall, - const char **result) -{ - int ret; - - assert(ctx != NULL); - assert(functionCall != NULL); - assert(result != NULL); - if (ctx == NULL || functionCall == NULL || result == NULL) { - return -__LINE__; - } - - StringList args; - ret = execFunctionArguments(ctx, functionCall->args, &args); - if (ret != 0) { - return ret; - } - - ret = callFunction(functionCall->fn, args.c, args.v, (char **)result, NULL); - if (ret != 0) { - return ret; - } - - //TODO: clean up args - - return 0; -} - -static int -execStringValue(ExecContext *ctx, const AmStringValue *stringValue, - const char **result) -{ - int ret; - - assert(ctx != NULL); - assert(stringValue != NULL); - assert(result != NULL); - if (ctx == NULL || stringValue == NULL || result == NULL) { - return -__LINE__; - } - - switch (stringValue->type) { - case AM_SVAL_LITERAL: - *result = strdup(stringValue->u.literal); - break; - case AM_SVAL_FUNCTION: - ret = execFunctionCall(ctx, stringValue->u.function, result); - if (ret != 0) { - return ret; - } - break; - default: - return -__LINE__; - } - - return 0; -} - -static int -execStringComparisonExpression(ExecContext *ctx, - const AmStringComparisonExpression *stringComparisonExpression, - bool *result) -{ - int ret; - - assert(ctx != NULL); - assert(stringComparisonExpression != NULL); - assert(result != NULL); - if (ctx == NULL || stringComparisonExpression == NULL || result == NULL) { - return -__LINE__; - } - - const char *arg1, *arg2; - ret = execStringValue(ctx, stringComparisonExpression->arg1, &arg1); - if (ret != 0) { - return ret; - } - ret = execStringValue(ctx, stringComparisonExpression->arg2, &arg2); - if (ret != 0) { - return ret; - } - - int cmp = strcmp(arg1, arg2); - - switch (stringComparisonExpression->op) { - case AM_SOP_LT: - *result = (cmp < 0); - break; - case AM_SOP_LE: - *result = (cmp <= 0); - break; - case AM_SOP_GT: - *result = (cmp > 0); - break; - case AM_SOP_GE: - *result = (cmp >= 0); - break; - case AM_SOP_EQ: - *result = (cmp == 0); - break; - case AM_SOP_NE: - *result = (cmp != 0); - break; - default: - return -__LINE__; - break; - } - - return 0; -} - -static int -execBooleanValue(ExecContext *ctx, const AmBooleanValue *booleanValue, - bool *result) -{ - int ret; - - assert(ctx != NULL); - assert(booleanValue != NULL); - assert(result != NULL); - if (ctx == NULL || booleanValue == NULL || result == NULL) { - return -__LINE__; - } - - switch (booleanValue->type) { - case AM_BVAL_EXPRESSION: - ret = execBooleanExpression(ctx, &booleanValue->u.expression, result); - break; - case AM_BVAL_STRING_COMPARISON: - ret = execStringComparisonExpression(ctx, - &booleanValue->u.stringComparison, result); - break; - default: - ret = -__LINE__; - break; - } - - return ret; -} - -static int -execCommand(ExecContext *ctx, const AmCommand *command) -{ - int ret; - - assert(ctx != NULL); - assert(command != NULL); - if (ctx == NULL || command == NULL) { - return -__LINE__; - } - - CommandArgumentType argType; - argType = getCommandArgumentType(command->cmd); - switch (argType) { - case CMD_ARGS_BOOLEAN: - { - bool bVal; - ret = execBooleanValue(ctx, command->args->u.b, &bVal); - if (ret == 0) { - ret = callBooleanCommand(command->cmd, bVal); - } - } - break; - case CMD_ARGS_WORDS: - { - AmWordList *words = command->args->u.w; - ret = callCommand(command->cmd, words->argc, words->argv); - } - break; - default: - ret = -__LINE__; - break; - } - - return ret; -} - -int -execCommandList(ExecContext *ctx, const AmCommandList *commandList) -{ - int i; - for (i = 0; i < commandList->commandCount; i++) { - int ret = execCommand(ctx, commandList->commands[i]); - if (ret != 0) { - int line = commandList->commands[i]->line; - return line > 0 ? line : ret; - } - } - - return 0; -} diff --git a/amend/execute.h b/amend/execute.h deleted file mode 100644 index 3becb484d..000000000 --- a/amend/execute.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_EXECUTE_H_ -#define AMEND_EXECUTE_H_ - -typedef struct ExecContext ExecContext; - -/* Returns 0 on success, otherwise the line number that failed. */ -int execCommandList(ExecContext *ctx, const AmCommandList *commandList); - -#endif // AMEND_EXECUTE_H_ diff --git a/amend/lexer.h b/amend/lexer.h deleted file mode 100644 index fc716fdcd..000000000 --- a/amend/lexer.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_LEXER_H_ -#define AMEND_LEXER_H_ - -#define AMEND_LEXER_BUFFER_INPUT 1 - -void yyerror(const char *msg); -int yylex(void); - -#if AMEND_LEXER_BUFFER_INPUT -void setLexerInputBuffer(const char *buf, size_t buflen); -#else -#include <stdio.h> -void yyset_in(FILE *in_str); -#endif - -const char *tokenToString(int token); - -typedef enum { - AM_UNKNOWN_ARGS, - AM_WORD_ARGS, - AM_BOOLEAN_ARGS, -} AmArgumentType; - -void setLexerArgumentType(AmArgumentType type); -int getLexerLineNumber(void); - -#endif // AMEND_LEXER_H_ diff --git a/amend/lexer.l b/amend/lexer.l deleted file mode 100644 index 80896d11f..000000000 --- a/amend/lexer.l +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -%{ - #include <stdio.h> - #include <stdlib.h> - #include "ast.h" - #include "lexer.h" - #include "parser.h" - - const char *tokenToString(int token) - { - static char scratch[128]; - - switch (token) { - case TOK_AND: - return "&&"; - case TOK_OR: - return "||"; - case TOK_EQ: - return "=="; - case TOK_NE: - return "!="; - case TOK_GE: - return ">="; - case TOK_LE: - return "<="; - case TOK_EOF: - return "EOF"; - case TOK_EOL: - return "EOL\n"; - case TOK_STRING: - snprintf(scratch, sizeof(scratch), - "STRING<%s>", yylval.literalString); - return scratch; - case TOK_IDENTIFIER: - snprintf(scratch, sizeof(scratch), "IDENTIFIER<%s>", - yylval.literalString); - return scratch; - case TOK_WORD: - snprintf(scratch, sizeof(scratch), "WORD<%s>", - yylval.literalString); - return scratch; - default: - if (token > ' ' && token <= '~') { - scratch[0] = (char)token; - scratch[1] = '\0'; - } else { - snprintf(scratch, sizeof(scratch), "??? <%d>", token); - } - return scratch; - } - } - - typedef struct { - char *value; - char *nextc; - unsigned int alloc_size; - } AmString; - - static int addCharToString(AmString *str, char c) - { - if ((unsigned int)(str->nextc - str->value) >= str->alloc_size) { - char *new_value; - unsigned int new_size; - - new_size = (str->alloc_size + 1) * 2; - if (new_size < 64) { - new_size = 64; - } - - new_value = (char *)realloc(str->value, new_size); - if (new_value == NULL) { - yyerror("out of memory"); - return -1; - } - str->nextc = str->nextc - str->value + new_value; - str->value = new_value; - str->alloc_size = new_size; - } - *str->nextc++ = c; - return 0; - } - - static int setString(AmString *str, const char *p) - { - str->nextc = str->value; - while (*p != '\0') { -//TODO: add the whole string at once - addCharToString(str, *p++); - } - return addCharToString(str, '\0'); - } - - static AmString gStr = { NULL, NULL, 0 }; - static int gLineNumber = 1; - static AmArgumentType gArgumentType = AM_UNKNOWN_ARGS; - static const char *gErrorMessage = NULL; - -#if AMEND_LEXER_BUFFER_INPUT - static const char *gInputBuffer; - static const char *gInputBufferNext; - static const char *gInputBufferEnd; - -# define YY_INPUT(buf, result, max_size) \ - do { \ - int nbytes = gInputBufferEnd - gInputBufferNext; \ - if (nbytes > 0) { \ - if (nbytes > max_size) { \ - nbytes = max_size; \ - } \ - memcpy(buf, gInputBufferNext, nbytes); \ - gInputBufferNext += nbytes; \ - result = nbytes; \ - } else { \ - result = YY_NULL; \ - } \ - } while (false) -#endif // AMEND_LEXER_BUFFER_INPUT - -%} - -%option noyywrap - -%x QUOTED_STRING BOOLEAN WORDS - -ident [a-zA-Z_][a-zA-Z_0-9]* -word [^ \t\r\n"]+ - -%% - /* This happens at the beginning of each call to yylex(). - */ - if (gArgumentType == AM_WORD_ARGS) { - BEGIN(WORDS); - } else if (gArgumentType == AM_BOOLEAN_ARGS) { - BEGIN(BOOLEAN); - } - - /*xxx require everything to be 7-bit-clean, printable characters */ -<INITIAL>{ - {ident}/[ \t\r\n] { - /* The only token we recognize in the initial - * state is an identifier followed by whitespace. - */ - setString(&gStr, yytext); - yylval.literalString = gStr.value; - return TOK_IDENTIFIER; - } - } - -<BOOLEAN>{ - {ident} { - /* Non-quoted identifier-style string */ - setString(&gStr, yytext); - yylval.literalString = gStr.value; - return TOK_IDENTIFIER; - } - "&&" return TOK_AND; - "||" return TOK_OR; - "==" return TOK_EQ; - "!=" return TOK_NE; - ">=" return TOK_GE; - "<=" return TOK_LE; - [<>()!,] return yytext[0]; - } - - /* Double-quoted string handling */ - -<WORDS,BOOLEAN>\" { - /* Initial quote */ - gStr.nextc = gStr.value; - BEGIN(QUOTED_STRING); - } - -<QUOTED_STRING>{ - \" { - /* Closing quote */ - BEGIN(INITIAL); - addCharToString(&gStr, '\0'); - yylval.literalString = gStr.value; - if (gArgumentType == AM_WORD_ARGS) { - return TOK_WORD; - } else { - return TOK_STRING; - } - } - - <<EOF>> | - \n { - /* Unterminated string */ - yyerror("unterminated string"); - return TOK_ERROR; - } - - \\\" { - /* Escaped quote */ - addCharToString(&gStr, '"'); - } - - \\\\ { - /* Escaped backslash */ - addCharToString(&gStr, '\\'); - } - - \\. { - /* No other escapes allowed. */ - gErrorMessage = "illegal escape"; - return TOK_ERROR; - } - - [^\\\n\"]+ { - /* String contents */ - char *p = yytext; - while (*p != '\0') { - /* TODO: add the whole string at once */ - addCharToString(&gStr, *p++); - } - } - } - -<WORDS>{ - /*xxx look out for backslashes; escape backslashes and quotes */ - /*xxx if a quote is right against a char, we should append */ - {word} { - /* Whitespace-separated word */ - setString(&gStr, yytext); - yylval.literalString = gStr.value; - return TOK_WORD; - } - } - -<INITIAL,WORDS,BOOLEAN>{ - \n { - /* Count lines */ - gLineNumber++; - gArgumentType = AM_UNKNOWN_ARGS; - BEGIN(INITIAL); - return TOK_EOL; - } - - /*xxx backslashes to extend lines? */ - /* Skip whitespace and comments. - */ - [ \t\r]+ ; - #.* ; - - . { - /* Fail on anything we didn't expect. */ - gErrorMessage = "unexpected character"; - return TOK_ERROR; - } - } -%% - -void -yyerror(const char *msg) -{ - if (!strcmp(msg, "syntax error") && gErrorMessage != NULL) { - msg = gErrorMessage; - gErrorMessage = NULL; - } - fprintf(stderr, "line %d: %s at '%s'\n", gLineNumber, msg, yytext); -} - -#if AMEND_LEXER_BUFFER_INPUT -void -setLexerInputBuffer(const char *buf, size_t buflen) -{ - gLineNumber = 1; - gInputBuffer = buf; - gInputBufferNext = gInputBuffer; - gInputBufferEnd = gInputBuffer + buflen; -} -#endif // AMEND_LEXER_BUFFER_INPUT - -void -setLexerArgumentType(AmArgumentType type) -{ - gArgumentType = type; -} - -int -getLexerLineNumber(void) -{ - return gLineNumber; -} diff --git a/amend/main.c b/amend/main.c deleted file mode 100644 index bc9e58778..000000000 --- a/amend/main.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "ast.h" -#include "lexer.h" -#include "parser.h" -#include "register.h" -#include "execute.h" - -void -lexTest() -{ - int token; - do { - token = yylex(); - if (token == 0) { - printf(" EOF"); - fflush(stdout); - break; - } else { - printf(" %s", tokenToString(token)); - fflush(stdout); - if (token == TOK_IDENTIFIER) { - if (strcmp(yylval.literalString, "assert") == 0) { - setLexerArgumentType(AM_BOOLEAN_ARGS); - } else { - setLexerArgumentType(AM_WORD_ARGS); - } - do { - token = yylex(); - printf(" %s", tokenToString(token)); - fflush(stdout); - } while (token != TOK_EOL && token != TOK_EOF && token != 0); - } else if (token != TOK_EOL) { - fprintf(stderr, "syntax error: expected identifier\n"); - break; - } - } - } while (token != 0); - printf("\n"); -} - -void -usage() -{ - printf("usage: amend [--debug-lex|--debug-ast] [<filename>]\n"); - exit(1); -} - -extern const AmCommandList *gCommands; -int -main(int argc, char *argv[]) -{ - FILE *inputFile = NULL; - bool debugLex = false; - bool debugAst = false; - const char *fileName = NULL; - int err; - -#if 1 - extern int test_symtab(void); - int ret = test_symtab(); - if (ret != 0) { - fprintf(stderr, "test_symtab() failed: %d\n", ret); - exit(ret); - } - extern int test_cmd_fn(void); - ret = test_cmd_fn(); - if (ret != 0) { - fprintf(stderr, "test_cmd_fn() failed: %d\n", ret); - exit(ret); - } -#endif - - argc--; - argv++; - while (argc > 0) { - if (strcmp("--debug-lex", argv[0]) == 0) { - debugLex = true; - } else if (strcmp("--debug-ast", argv[0]) == 0) { - debugAst = true; - } else if (argv[0][0] == '-') { - fprintf(stderr, "amend: Unknown option \"%s\"\n", argv[0]); - usage(); - } else { - fileName = argv[0]; - } - argc--; - argv++; - } - - if (fileName != NULL) { - inputFile = fopen(fileName, "r"); - if (inputFile == NULL) { - fprintf(stderr, "amend: Can't open input file '%s'\n", fileName); - usage(); - } - } - - commandInit(); -//xxx clean up - - err = registerUpdateCommands(); - if (err < 0) { - fprintf(stderr, "amend: Error registering commands: %d\n", err); - exit(-err); - } - err = registerUpdateFunctions(); - if (err < 0) { - fprintf(stderr, "amend: Error registering functions: %d\n", err); - exit(-err); - } - -#if AMEND_LEXER_BUFFER_INPUT - if (inputFile == NULL) { - fprintf(stderr, "amend: No input file\n"); - usage(); - } - char *fileData; - int fileDataLen; - fseek(inputFile, 0, SEEK_END); - fileDataLen = ftell(inputFile); - rewind(inputFile); - if (fileDataLen < 0) { - fprintf(stderr, "amend: Can't get file length\n"); - exit(2); - } else if (fileDataLen == 0) { - printf("amend: Empty input file\n"); - exit(0); - } - fileData = (char *)malloc(fileDataLen + 1); - if (fileData == NULL) { - fprintf(stderr, "amend: Can't allocate %d bytes\n", fileDataLen + 1); - exit(2); - } - size_t nread = fread(fileData, 1, fileDataLen, inputFile); - if (nread != (size_t)fileDataLen) { - fprintf(stderr, "amend: Didn't read %d bytes, only %zd\n", fileDataLen, - nread); - exit(2); - } - fileData[fileDataLen] = '\0'; - setLexerInputBuffer(fileData, fileDataLen); -#else - if (inputFile == NULL) { - inputFile = stdin; - } - yyset_in(inputFile); -#endif - - if (debugLex) { - lexTest(); - } else { - int ret = yyparse(); - if (ret != 0) { - fprintf(stderr, "amend: Parse failed (%d)\n", ret); - exit(2); - } else { - if (debugAst) { - dumpCommandList(gCommands); - } -printf("amend: Parse successful.\n"); - ret = execCommandList((ExecContext *)1, gCommands); - if (ret != 0) { - fprintf(stderr, "amend: Execution failed (%d)\n", ret); - exit(3); - } -printf("amend: Execution successful.\n"); - } - } - - return 0; -} diff --git a/amend/parser.h b/amend/parser.h deleted file mode 100644 index aeb865737..000000000 --- a/amend/parser.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_PARSER_H_ -#define AMEND_PARSER_H_ - -#include "parser_y.h" - -int yyparse(void); - -#endif // AMEND_PARSER_H_ diff --git a/amend/parser_y.y b/amend/parser_y.y deleted file mode 100644 index b634016e2..000000000 --- a/amend/parser_y.y +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -%{ -#undef NDEBUG - #include <stdlib.h> - #include <string.h> - #include <assert.h> - #include <stdio.h> - #include "ast.h" - #include "lexer.h" - #include "commands.h" - - void yyerror(const char *msg); - int yylex(void); - -#define STRING_COMPARISON(out, a1, sop, a2) \ - do { \ - out = (AmBooleanValue *)malloc(sizeof(AmBooleanValue)); \ - if (out == NULL) { \ - YYABORT; \ - } \ - out->type = AM_BVAL_STRING_COMPARISON; \ - out->u.stringComparison.op = sop; \ - out->u.stringComparison.arg1 = a1; \ - out->u.stringComparison.arg2 = a2; \ - } while (false) - -#define BOOLEAN_EXPRESSION(out, a1, bop, a2) \ - do { \ - out = (AmBooleanValue *)malloc(sizeof(AmBooleanValue)); \ - if (out == NULL) { \ - YYABORT; \ - } \ - out->type = AM_BVAL_EXPRESSION; \ - out->u.expression.op = bop; \ - out->u.expression.arg1 = a1; \ - out->u.expression.arg2 = a2; \ - } while (false) - -AmCommandList *gCommands = NULL; -%} - -%start lines - -%union { - char *literalString; - AmFunctionArgumentBuilder *functionArgumentBuilder; - AmFunctionArguments *functionArguments; - AmFunctionCall *functionCall; - AmStringValue *stringValue; - AmBooleanValue *booleanValue; - AmWordListBuilder *wordListBuilder; - AmCommandArguments *commandArguments; - AmCommand *command; - AmCommandList *commandList; - } - -%token TOK_AND TOK_OR TOK_EQ TOK_NE TOK_GE TOK_LE TOK_EOF TOK_EOL TOK_ERROR -%token <literalString> TOK_STRING TOK_IDENTIFIER TOK_WORD - -%type <commandList> lines -%type <command> command line -%type <functionArgumentBuilder> function_arguments -%type <functionArguments> function_arguments_or_empty -%type <functionCall> function_call -%type <literalString> function_name -%type <stringValue> string_value -%type <booleanValue> boolean_expression -%type <wordListBuilder> word_list -%type <commandArguments> arguments - -/* Operator precedence, weakest to strongest. - * Same as C/Java precedence. - */ - -%left TOK_OR -%left TOK_AND -%left TOK_EQ TOK_NE -%left '<' '>' TOK_LE TOK_GE -%right '!' - -%% - -lines : /* empty */ - { - $$ = (AmCommandList *)malloc(sizeof(AmCommandList)); - if ($$ == NULL) { - YYABORT; - } -gCommands = $$; - $$->arraySize = 64; - $$->commandCount = 0; - $$->commands = (AmCommand **)malloc( - sizeof(AmCommand *) * $$->arraySize); - if ($$->commands == NULL) { - YYABORT; - } - } - | lines line - { - if ($2 != NULL) { - if ($1->commandCount >= $1->arraySize) { - AmCommand **newArray; - newArray = (AmCommand **)realloc($$->commands, - sizeof(AmCommand *) * $$->arraySize * 2); - if (newArray == NULL) { - YYABORT; - } - $$->commands = newArray; - $$->arraySize *= 2; - } - $1->commands[$1->commandCount++] = $2; - } - } - ; - -line : line_ending - { - $$ = NULL; /* ignore blank lines */ - } - | command arguments line_ending - { - $$ = $1; - $$->args = $2; - setLexerArgumentType(AM_UNKNOWN_ARGS); - } - ; - -command : TOK_IDENTIFIER - { - Command *cmd = findCommand($1); - if (cmd == NULL) { - fprintf(stderr, "Unknown command \"%s\"\n", $1); - YYABORT; - } - $$ = (AmCommand *)malloc(sizeof(AmCommand)); - if ($$ == NULL) { - YYABORT; - } - $$->line = getLexerLineNumber(); - $$->name = strdup($1); - if ($$->name == NULL) { - YYABORT; - } - $$->args = NULL; - CommandArgumentType argType = getCommandArgumentType(cmd); - if (argType == CMD_ARGS_BOOLEAN) { - setLexerArgumentType(AM_BOOLEAN_ARGS); - } else { - setLexerArgumentType(AM_WORD_ARGS); - } - $$->cmd = cmd; - } - ; - -line_ending : - TOK_EOL - | TOK_EOF - ; - -arguments : boolean_expression - { - $$ = (AmCommandArguments *)malloc( - sizeof(AmCommandArguments)); - if ($$ == NULL) { - YYABORT; - } - $$->booleanArgs = true; - $$->u.b = $1; - } - | word_list - { - /* Convert the builder list into an array. - * Do it in reverse order; the words were pushed - * onto the list in LIFO order. - */ - AmWordList *w = (AmWordList *)malloc(sizeof(AmWordList)); - if (w == NULL) { - YYABORT; - } - if ($1 != NULL) { - AmWordListBuilder *words = $1; - - w->argc = words->wordCount; - w->argv = (const char **)malloc(w->argc * - sizeof(char *)); - if (w->argv == NULL) { - YYABORT; - } - int i; - for (i = w->argc; words != NULL && i > 0; --i) { - AmWordListBuilder *f = words; - w->argv[i-1] = words->word; - words = words->next; - free(f); - } - assert(i == 0); - assert(words == NULL); - } else { - w->argc = 0; - w->argv = NULL; - } - $$ = (AmCommandArguments *)malloc( - sizeof(AmCommandArguments)); - if ($$ == NULL) { - YYABORT; - } - $$->booleanArgs = false; - $$->u.w = w; - } - ; - -word_list : /* empty */ - { $$ = NULL; } - | word_list TOK_WORD - { - if ($1 == NULL) { - $$ = (AmWordListBuilder *)malloc( - sizeof(AmWordListBuilder)); - if ($$ == NULL) { - YYABORT; - } - $$->next = NULL; - $$->wordCount = 1; - } else { - $$ = (AmWordListBuilder *)malloc( - sizeof(AmWordListBuilder)); - if ($$ == NULL) { - YYABORT; - } - $$->next = $1; - $$->wordCount = $$->next->wordCount + 1; - } - $$->word = strdup($2); - if ($$->word == NULL) { - YYABORT; - } - } - ; - -boolean_expression : - '!' boolean_expression - { - $$ = (AmBooleanValue *)malloc(sizeof(AmBooleanValue)); - if ($$ == NULL) { - YYABORT; - } - $$->type = AM_BVAL_EXPRESSION; - $$->u.expression.op = AM_BOP_NOT; - $$->u.expression.arg1 = $2; - $$->u.expression.arg2 = NULL; - } - /* TODO: if both expressions are literals, evaluate now */ - | boolean_expression TOK_AND boolean_expression - { BOOLEAN_EXPRESSION($$, $1, AM_BOP_AND, $3); } - | boolean_expression TOK_OR boolean_expression - { BOOLEAN_EXPRESSION($$, $1, AM_BOP_OR, $3); } - | boolean_expression TOK_EQ boolean_expression - { BOOLEAN_EXPRESSION($$, $1, AM_BOP_EQ, $3); } - | boolean_expression TOK_NE boolean_expression - { BOOLEAN_EXPRESSION($$, $1, AM_BOP_NE, $3); } - | '(' boolean_expression ')' - { $$ = $2; } - /* TODO: if both strings are literals, evaluate now */ - | string_value '<' string_value - { STRING_COMPARISON($$, $1, AM_SOP_LT, $3); } - | string_value '>' string_value - { STRING_COMPARISON($$, $1, AM_SOP_GT, $3); } - | string_value TOK_EQ string_value - { STRING_COMPARISON($$, $1, AM_SOP_EQ, $3); } - | string_value TOK_NE string_value - { STRING_COMPARISON($$, $1, AM_SOP_NE, $3); } - | string_value TOK_LE string_value - { STRING_COMPARISON($$, $1, AM_SOP_LE, $3); } - | string_value TOK_GE string_value - { STRING_COMPARISON($$, $1, AM_SOP_GE, $3); } - ; - -string_value : - TOK_IDENTIFIER - { - $$ = (AmStringValue *)malloc(sizeof(AmStringValue)); - if ($$ == NULL) { - YYABORT; - } - $$->type = AM_SVAL_LITERAL; - $$->u.literal = strdup($1); - if ($$->u.literal == NULL) { - YYABORT; - } - } - | TOK_STRING - { - $$ = (AmStringValue *)malloc(sizeof(AmStringValue)); - if ($$ == NULL) { - YYABORT; - } - $$->type = AM_SVAL_LITERAL; - $$->u.literal = strdup($1); - if ($$->u.literal == NULL) { - YYABORT; - } - } - | function_call - { - $$ = (AmStringValue *)malloc(sizeof(AmStringValue)); - if ($$ == NULL) { - YYABORT; - } - $$->type = AM_SVAL_FUNCTION; - $$->u.function = $1; - } - ; - - /* We can't just say - * TOK_IDENTIFIER '(' function_arguments_or_empty ')' - * because parsing function_arguments_or_empty will clobber - * the underlying string that yylval.literalString points to. - */ -function_call : - function_name '(' function_arguments_or_empty ')' - { - Function *fn = findFunction($1); - if (fn == NULL) { - fprintf(stderr, "Unknown function \"%s\"\n", $1); - YYABORT; - } - $$ = (AmFunctionCall *)malloc(sizeof(AmFunctionCall)); - if ($$ == NULL) { - YYABORT; - } - $$->name = $1; - if ($$->name == NULL) { - YYABORT; - } - $$->fn = fn; - $$->args = $3; - } - ; - -function_name : - TOK_IDENTIFIER - { - $$ = strdup($1); - } - ; - -function_arguments_or_empty : - /* empty */ - { - $$ = (AmFunctionArguments *)malloc( - sizeof(AmFunctionArguments)); - if ($$ == NULL) { - YYABORT; - } - $$->argc = 0; - $$->argv = NULL; - } - | function_arguments - { - AmFunctionArgumentBuilder *args = $1; - assert(args != NULL); - - /* Convert the builder list into an array. - * Do it in reverse order; the args were pushed - * onto the list in LIFO order. - */ - $$ = (AmFunctionArguments *)malloc( - sizeof(AmFunctionArguments)); - if ($$ == NULL) { - YYABORT; - } - $$->argc = args->argCount; - $$->argv = (AmStringValue *)malloc( - $$->argc * sizeof(AmStringValue)); - if ($$->argv == NULL) { - YYABORT; - } - int i; - for (i = $$->argc; args != NULL && i > 0; --i) { - AmFunctionArgumentBuilder *f = args; - $$->argv[i-1] = *args->arg; - args = args->next; - free(f->arg); - free(f); - } - assert(i == 0); - assert(args == NULL); - } - ; - -function_arguments : - string_value - { - $$ = (AmFunctionArgumentBuilder *)malloc( - sizeof(AmFunctionArgumentBuilder)); - if ($$ == NULL) { - YYABORT; - } - $$->next = NULL; - $$->argCount = 1; - $$->arg = $1; - } - | function_arguments ',' string_value - { - $$ = (AmFunctionArgumentBuilder *)malloc( - sizeof(AmFunctionArgumentBuilder)); - if ($$ == NULL) { - YYABORT; - } - $$->next = $1; - $$->argCount = $$->next->argCount + 1; - $$->arg = $3; - } - ; - /* xxx this whole tool needs to be hardened */ diff --git a/amend/register.c b/amend/register.c deleted file mode 100644 index 0f44b7478..000000000 --- a/amend/register.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#undef NDEBUG -#include <assert.h> -#include "commands.h" - -#include "register.h" - -#define UNUSED(p) ((void)(p)) - -#define CHECK_BOOL() \ - do { \ - assert(argv == NULL); \ - if (argv != NULL) return -1; \ - assert(argc == true || argc == false); \ - if (argc != true && argc != false) return -1; \ - } while (false) - -#define CHECK_WORDS() \ - do { \ - assert(argc >= 0); \ - if (argc < 0) return -1; \ - assert(argc == 0 || argv != NULL); \ - if (argc != 0 && argv == NULL) return -1; \ - } while (false) - -#define CHECK_FN() \ - do { \ - CHECK_WORDS(); \ - assert(result != NULL); \ - if (result == NULL) return -1; \ - } while (false) - - -/* - * Command definitions - */ - -/* assert <boolexpr> - */ -static int -cmd_assert(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_BOOL(); - - /* If our argument is false, return non-zero (failure) - * If our argument is true, return zero (success) - */ - if (argc) { - return 0; - } else { - return 1; - } -} - -/* format <root> - */ -static int -cmd_format(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx - return -1; -} - -/* copy_dir <srcdir> <dstdir> - */ -static int -cmd_copy_dir(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx - return -1; -} - -/* mark <resource> dirty|clean - */ -static int -cmd_mark(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx when marking, save the top-level hash at the mark point -// so we can retry on failure. Otherwise the hashes won't match, -// or someone could intentionally dirty the FS to force a downgrade -//xxx - return -1; -} - -/* done - */ -static int -cmd_done(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx - return -1; -} - -int -registerUpdateCommands() -{ - int ret; - - ret = registerCommand("assert", CMD_ARGS_BOOLEAN, cmd_assert, NULL); - if (ret < 0) return ret; - - ret = registerCommand("copy_dir", CMD_ARGS_WORDS, cmd_copy_dir, NULL); - if (ret < 0) return ret; - - ret = registerCommand("format", CMD_ARGS_WORDS, cmd_format, NULL); - if (ret < 0) return ret; - - ret = registerCommand("mark", CMD_ARGS_WORDS, cmd_mark, NULL); - if (ret < 0) return ret; - - ret = registerCommand("done", CMD_ARGS_WORDS, cmd_done, NULL); - if (ret < 0) return ret; - - return 0; -} - - -/* - * Function definitions - */ - -/* update_forced() - * - * Returns "true" if some system setting has determined that - * the update should happen no matter what. - */ -static int -fn_update_forced(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc != 0) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } - - //xxx check some global or property - bool force = true; - if (force) { - *result = strdup("true"); - } else { - *result = strdup(""); - } - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - - return 0; -} - -/* get_mark(<resource>) - * - * Returns the current mark associated with the provided resource. - */ -static int -fn_get_mark(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc != 1) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } - - //xxx look up the value - *result = strdup(""); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - - return 0; -} - -/* hash_dir(<path-to-directory>) - */ -static int -fn_hash_dir(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - int ret = -1; - - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - const char *dir; - if (argc != 1) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } else { - dir = argv[0]; - } - -//xxx build and return the string - *result = strdup("hashvalue"); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - ret = 0; - - return ret; -} - -/* matches(<str>, <str1> [, <strN>...]) - * If <str> matches (strcmp) any of <str1>...<strN>, returns <str>, - * otherwise returns "". - * - * E.g., assert matches(hash_dir("/path"), "hash1", "hash2") - */ -static int -fn_matches(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc < 2) { - fprintf(stderr, "%s: not enough arguments (%d < 2)\n", - name, argc); - return 1; - } - - int i; - for (i = 1; i < argc; i++) { - if (strcmp(argv[0], argv[i]) == 0) { - *result = strdup(argv[0]); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - return 0; - } - } - - *result = strdup(""); - if (resultLen != NULL) { - *resultLen = 1; - } - return 0; -} - -/* concat(<str>, <str1> [, <strN>...]) - * Returns the concatenation of all strings. - */ -static int -fn_concat(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - size_t totalLen = 0; - int i; - for (i = 0; i < argc; i++) { - totalLen += strlen(argv[i]); - } - - char *s = (char *)malloc(totalLen + 1); - if (s == NULL) { - return -1; - } - s[totalLen] = '\0'; - for (i = 0; i < argc; i++) { - //TODO: keep track of the end to avoid walking the string each time - strcat(s, argv[i]); - } - *result = s; - if (resultLen != NULL) { - *resultLen = strlen(s); - } - - return 0; -} - -int -registerUpdateFunctions() -{ - int ret; - - ret = registerFunction("update_forced", fn_update_forced, NULL); - if (ret < 0) return ret; - - ret = registerFunction("get_mark", fn_get_mark, NULL); - if (ret < 0) return ret; - - ret = registerFunction("hash_dir", fn_hash_dir, NULL); - if (ret < 0) return ret; - - ret = registerFunction("matches", fn_matches, NULL); - if (ret < 0) return ret; - - ret = registerFunction("concat", fn_concat, NULL); - if (ret < 0) return ret; - - return 0; -} diff --git a/amend/register.h b/amend/register.h deleted file mode 100644 index 1d9eacbfe..000000000 --- a/amend/register.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_REGISTER_H_ -#define AMEND_REGISTER_H_ - -int registerUpdateCommands(void); -int registerUpdateFunctions(void); - -#endif // AMEND_REGISTER_H_ diff --git a/amend/symtab.c b/amend/symtab.c deleted file mode 100644 index 835d2fc40..000000000 --- a/amend/symtab.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <string.h> -#include "symtab.h" - -#define DEFAULT_TABLE_SIZE 16 - -typedef struct { - char *symbol; - const void *cookie; - unsigned int flags; -} SymbolTableEntry; - -struct SymbolTable { - SymbolTableEntry *table; - int numEntries; - int maxSize; -}; - -SymbolTable * -createSymbolTable() -{ - SymbolTable *tab; - - tab = (SymbolTable *)malloc(sizeof(SymbolTable)); - if (tab != NULL) { - tab->numEntries = 0; - tab->maxSize = DEFAULT_TABLE_SIZE; - tab->table = (SymbolTableEntry *)malloc( - tab->maxSize * sizeof(SymbolTableEntry)); - if (tab->table == NULL) { - free(tab); - tab = NULL; - } - } - return tab; -} - -void -deleteSymbolTable(SymbolTable *tab) -{ - if (tab != NULL) { - while (tab->numEntries > 0) { - free(tab->table[--tab->numEntries].symbol); - } - free(tab->table); - } -} - -void * -findInSymbolTable(SymbolTable *tab, const char *symbol, unsigned int flags) -{ - int i; - - if (tab == NULL || symbol == NULL) { - return NULL; - } - - // TODO: Sort the table and binary search - for (i = 0; i < tab->numEntries; i++) { - if (strcmp(tab->table[i].symbol, symbol) == 0 && - tab->table[i].flags == flags) - { - return (void *)tab->table[i].cookie; - } - } - - return NULL; -} - -int -addToSymbolTable(SymbolTable *tab, const char *symbol, unsigned int flags, - const void *cookie) -{ - if (tab == NULL || symbol == NULL || cookie == NULL) { - return -1; - } - - /* Make sure that this symbol isn't already in the table. - */ - if (findInSymbolTable(tab, symbol, flags) != NULL) { - return -2; - } - - /* Make sure there's enough space for the new entry. - */ - if (tab->numEntries == tab->maxSize) { - SymbolTableEntry *newTable; - int newSize; - - newSize = tab->numEntries * 2; - if (newSize < DEFAULT_TABLE_SIZE) { - newSize = DEFAULT_TABLE_SIZE; - } - newTable = (SymbolTableEntry *)realloc(tab->table, - newSize * sizeof(SymbolTableEntry)); - if (newTable == NULL) { - return -1; - } - tab->maxSize = newSize; - tab->table = newTable; - } - - /* Insert the new entry. - */ - symbol = strdup(symbol); - if (symbol == NULL) { - return -1; - } - // TODO: Sort the table - tab->table[tab->numEntries].symbol = (char *)symbol; - tab->table[tab->numEntries].cookie = cookie; - tab->table[tab->numEntries].flags = flags; - tab->numEntries++; - - return 0; -} diff --git a/amend/symtab.h b/amend/symtab.h deleted file mode 100644 index f83c65b3f..000000000 --- a/amend/symtab.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007 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 AMEND_SYMTAB_H_ -#define AMEND_SYMTAB_H_ - -typedef struct SymbolTable SymbolTable; - -SymbolTable *createSymbolTable(void); - -void deleteSymbolTable(SymbolTable *tab); - -/* symbol and cookie must be non-NULL. - */ -int addToSymbolTable(SymbolTable *tab, const char *symbol, unsigned int flags, - const void *cookie); - -void *findInSymbolTable(SymbolTable *tab, const char *symbol, - unsigned int flags); - -#endif // AMEND_SYMTAB_H_ diff --git a/amend/test_commands.c b/amend/test_commands.c deleted file mode 100644 index 452f808b0..000000000 --- a/amend/test_commands.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#undef NDEBUG -#include <assert.h> -#include "commands.h" - -static struct { - bool called; - const char *name; - void *cookie; - int argc; - const char **argv; - int returnValue; - char *functionResult; -} gTestCommandState; - -static int -testCommand(const char *name, void *cookie, int argc, const char *argv[]) -{ - gTestCommandState.called = true; - gTestCommandState.name = name; - gTestCommandState.cookie = cookie; - gTestCommandState.argc = argc; - gTestCommandState.argv = argv; - return gTestCommandState.returnValue; -} - -static int -testFunction(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - gTestCommandState.called = true; - gTestCommandState.name = name; - gTestCommandState.cookie = cookie; - gTestCommandState.argc = argc; - gTestCommandState.argv = argv; - if (result != NULL) { - *result = gTestCommandState.functionResult; - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - } - return gTestCommandState.returnValue; -} - -static int -test_commands() -{ - Command *cmd; - int ret; - CommandArgumentType argType; - - ret = commandInit(); - assert(ret == 0); - - /* Make sure we can't initialize twice. - */ - ret = commandInit(); - assert(ret < 0); - - /* Try calling with some bad values. - */ - ret = registerCommand(NULL, CMD_ARGS_UNKNOWN, NULL, NULL); - assert(ret < 0); - - ret = registerCommand("hello", CMD_ARGS_UNKNOWN, NULL, NULL); - assert(ret < 0); - - ret = registerCommand("hello", CMD_ARGS_WORDS, NULL, NULL); - assert(ret < 0); - - cmd = findCommand(NULL); - assert(cmd == NULL); - - argType = getCommandArgumentType(NULL); - assert((int)argType < 0); - - ret = callCommand(NULL, -1, NULL); - assert(ret < 0); - - ret = callBooleanCommand(NULL, false); - assert(ret < 0); - - /* Register some commands. - */ - ret = registerCommand("one", CMD_ARGS_WORDS, testCommand, - &gTestCommandState); - assert(ret == 0); - - ret = registerCommand("two", CMD_ARGS_WORDS, testCommand, - &gTestCommandState); - assert(ret == 0); - - ret = registerCommand("bool", CMD_ARGS_BOOLEAN, testCommand, - &gTestCommandState); - assert(ret == 0); - - /* Make sure that all of those commands exist and that their - * argument types are correct. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - argType = getCommandArgumentType(cmd); - assert(argType == CMD_ARGS_WORDS); - - cmd = findCommand("two"); - assert(cmd != NULL); - argType = getCommandArgumentType(cmd); - assert(argType == CMD_ARGS_WORDS); - - cmd = findCommand("bool"); - assert(cmd != NULL); - argType = getCommandArgumentType(cmd); - assert(argType == CMD_ARGS_BOOLEAN); - - /* Make sure that no similar commands exist. - */ - cmd = findCommand("on"); - assert(cmd == NULL); - - cmd = findCommand("onee"); - assert(cmd == NULL); - - /* Make sure that a double insertion fails. - */ - ret = registerCommand("one", CMD_ARGS_WORDS, testCommand, - &gTestCommandState); - assert(ret < 0); - - /* Make sure that bad args fail. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - - ret = callCommand(cmd, -1, NULL); // argc must be non-negative - assert(ret < 0); - - ret = callCommand(cmd, 1, NULL); // argv can't be NULL if argc > 0 - assert(ret < 0); - - /* Make sure that you can't make a boolean call on a regular command. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - - ret = callBooleanCommand(cmd, false); - assert(ret < 0); - - /* Make sure that you can't make a regular call on a boolean command. - */ - cmd = findCommand("bool"); - assert(cmd != NULL); - - ret = callCommand(cmd, 0, NULL); - assert(ret < 0); - - /* Set up some arguments. - */ - int argc = 4; - const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" }; - - /* Make a call and make sure that it occurred. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 25; - ret = callCommand(cmd, argc, argv); -//xxx also try calling with a null argv element (should fail) - assert(ret == 25); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - - /* Make a boolean call and make sure that it occurred. - */ - cmd = findCommand("bool"); - assert(cmd != NULL); - - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 12; - ret = callBooleanCommand(cmd, false); - assert(ret == 12); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "bool") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == 0); - assert(gTestCommandState.argv == NULL); - - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 13; - ret = callBooleanCommand(cmd, true); - assert(ret == 13); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "bool") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == 1); - assert(gTestCommandState.argv == NULL); - - /* Smoke test commandCleanup(). - */ - commandCleanup(); - - return 0; -} - -static int -test_functions() -{ - Function *fn; - int ret; - - ret = commandInit(); - assert(ret == 0); - - /* Try calling with some bad values. - */ - ret = registerFunction(NULL, NULL, NULL); - assert(ret < 0); - - ret = registerFunction("hello", NULL, NULL); - assert(ret < 0); - - fn = findFunction(NULL); - assert(fn == NULL); - - ret = callFunction(NULL, -1, NULL, NULL, NULL); - assert(ret < 0); - - /* Register some functions. - */ - ret = registerFunction("one", testFunction, &gTestCommandState); - assert(ret == 0); - - ret = registerFunction("two", testFunction, &gTestCommandState); - assert(ret == 0); - - ret = registerFunction("three", testFunction, &gTestCommandState); - assert(ret == 0); - - /* Make sure that all of those functions exist. - * argument types are correct. - */ - fn = findFunction("one"); - assert(fn != NULL); - - fn = findFunction("two"); - assert(fn != NULL); - - fn = findFunction("three"); - assert(fn != NULL); - - /* Make sure that no similar functions exist. - */ - fn = findFunction("on"); - assert(fn == NULL); - - fn = findFunction("onee"); - assert(fn == NULL); - - /* Make sure that a double insertion fails. - */ - ret = registerFunction("one", testFunction, &gTestCommandState); - assert(ret < 0); - - /* Make sure that bad args fail. - */ - fn = findFunction("one"); - assert(fn != NULL); - - // argc must be non-negative - ret = callFunction(fn, -1, NULL, (char **)1, NULL); - assert(ret < 0); - - // argv can't be NULL if argc > 0 - ret = callFunction(fn, 1, NULL, (char **)1, NULL); - assert(ret < 0); - - // result can't be NULL - ret = callFunction(fn, 0, NULL, NULL, NULL); - assert(ret < 0); - - /* Set up some arguments. - */ - int argc = 4; - const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" }; - - /* Make a call and make sure that it occurred. - */ - char *functionResult; - size_t functionResultLen; - fn = findFunction("one"); - assert(fn != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 25; - gTestCommandState.functionResult = "1234"; - functionResult = NULL; - functionResultLen = 55; - ret = callFunction(fn, argc, argv, - &functionResult, &functionResultLen); -//xxx also try calling with a null resultLen arg (should succeed) -//xxx also try calling with a null argv element (should fail) - assert(ret == 25); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - assert(strcmp(functionResult, "1234") == 0); - assert(functionResultLen == strlen(functionResult)); - - /* Smoke test commandCleanup(). - */ - commandCleanup(); - - return 0; -} - -static int -test_interaction() -{ - Command *cmd; - Function *fn; - int ret; - - ret = commandInit(); - assert(ret == 0); - - /* Register some commands. - */ - ret = registerCommand("one", CMD_ARGS_WORDS, testCommand, (void *)0xc1); - assert(ret == 0); - - ret = registerCommand("two", CMD_ARGS_WORDS, testCommand, (void *)0xc2); - assert(ret == 0); - - /* Register some functions, one of which shares a name with a command. - */ - ret = registerFunction("one", testFunction, (void *)0xf1); - assert(ret == 0); - - ret = registerFunction("three", testFunction, (void *)0xf3); - assert(ret == 0); - - /* Look up each of the commands, and make sure no command exists - * with the name used only by our function. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - - cmd = findCommand("two"); - assert(cmd != NULL); - - cmd = findCommand("three"); - assert(cmd == NULL); - - /* Look up each of the functions, and make sure no function exists - * with the name used only by our command. - */ - fn = findFunction("one"); - assert(fn != NULL); - - fn = findFunction("two"); - assert(fn == NULL); - - fn = findFunction("three"); - assert(fn != NULL); - - /* Set up some arguments. - */ - int argc = 4; - const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" }; - - /* Call the overlapping command and make sure that the cookie is correct. - */ - cmd = findCommand("one"); - assert(cmd != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 123; - ret = callCommand(cmd, argc, argv); - assert(ret == 123); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert((int)gTestCommandState.cookie == 0xc1); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - - /* Call the overlapping function and make sure that the cookie is correct. - */ - char *functionResult; - size_t functionResultLen; - fn = findFunction("one"); - assert(fn != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 125; - gTestCommandState.functionResult = "5678"; - functionResult = NULL; - functionResultLen = 66; - ret = callFunction(fn, argc, argv, &functionResult, &functionResultLen); - assert(ret == 125); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert((int)gTestCommandState.cookie == 0xf1); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - assert(strcmp(functionResult, "5678") == 0); - assert(functionResultLen == strlen(functionResult)); - - /* Clean up. - */ - commandCleanup(); - - return 0; -} - -int -test_cmd_fn() -{ - int ret; - - ret = test_commands(); - if (ret != 0) { - fprintf(stderr, "test_commands() failed: %d\n", ret); - return ret; - } - - ret = test_functions(); - if (ret != 0) { - fprintf(stderr, "test_functions() failed: %d\n", ret); - return ret; - } - - ret = test_interaction(); - if (ret != 0) { - fprintf(stderr, "test_interaction() failed: %d\n", ret); - return ret; - } - - return 0; -} diff --git a/amend/test_symtab.c b/amend/test_symtab.c deleted file mode 100644 index 017d18ccd..000000000 --- a/amend/test_symtab.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdlib.h> -#undef NDEBUG -#include <assert.h> -#include "symtab.h" - -int -test_symtab() -{ - SymbolTable *tab; - void *cookie; - int ret; - - /* Test creation */ - tab = createSymbolTable(); - assert(tab != NULL); - - /* Smoke-test deletion */ - deleteSymbolTable(tab); - - - tab = createSymbolTable(); - assert(tab != NULL); - - - /* table parameter must be non-NULL. */ - ret = addToSymbolTable(NULL, NULL, 0, NULL); - assert(ret < 0); - - /* symbol parameter must be non-NULL. */ - ret = addToSymbolTable(tab, NULL, 0, NULL); - assert(ret < 0); - - /* cookie parameter must be non-NULL. */ - ret = addToSymbolTable(tab, "null", 0, NULL); - assert(ret < 0); - - - /* table parameter must be non-NULL. */ - cookie = findInSymbolTable(NULL, NULL, 0); - assert(cookie == NULL); - - /* symbol parameter must be non-NULL. */ - cookie = findInSymbolTable(tab, NULL, 0); - assert(cookie == NULL); - - - /* Try some actual inserts. - */ - ret = addToSymbolTable(tab, "one", 0, (void *)1); - assert(ret == 0); - - ret = addToSymbolTable(tab, "two", 0, (void *)2); - assert(ret == 0); - - ret = addToSymbolTable(tab, "three", 0, (void *)3); - assert(ret == 0); - - /* Try some lookups. - */ - cookie = findInSymbolTable(tab, "one", 0); - assert((int)cookie == 1); - - cookie = findInSymbolTable(tab, "two", 0); - assert((int)cookie == 2); - - cookie = findInSymbolTable(tab, "three", 0); - assert((int)cookie == 3); - - /* Try to insert something that's already there. - */ - ret = addToSymbolTable(tab, "one", 0, (void *)1111); - assert(ret < 0); - - /* Make sure that the failed duplicate insert didn't - * clobber the original cookie value. - */ - cookie = findInSymbolTable(tab, "one", 0); - assert((int)cookie == 1); - - /* Try looking up something that isn't there. - */ - cookie = findInSymbolTable(tab, "FOUR", 0); - assert(cookie == NULL); - - /* Try looking up something that's similar to an existing entry. - */ - cookie = findInSymbolTable(tab, "on", 0); - assert(cookie == NULL); - - cookie = findInSymbolTable(tab, "onee", 0); - assert(cookie == NULL); - - /* Test flags. - * Try inserting something with a different flag. - */ - ret = addToSymbolTable(tab, "ten", 333, (void *)10); - assert(ret == 0); - - /* Make sure it's there. - */ - cookie = findInSymbolTable(tab, "ten", 333); - assert((int)cookie == 10); - - /* Make sure it's not there when looked up with a different flag. - */ - cookie = findInSymbolTable(tab, "ten", 0); - assert(cookie == NULL); - - /* Try inserting something that has the same name as something - * with a different flag. - */ - ret = addToSymbolTable(tab, "one", 333, (void *)11); - assert(ret == 0); - - /* Make sure the new entry exists. - */ - cookie = findInSymbolTable(tab, "one", 333); - assert((int)cookie == 11); - - /* Make sure the old entry still has the right value. - */ - cookie = findInSymbolTable(tab, "one", 0); - assert((int)cookie == 1); - - /* Try deleting again, now that there's stuff in the table. - */ - deleteSymbolTable(tab); - - return 0; -} diff --git a/amend/tests/001-nop/expected.txt b/amend/tests/001-nop/expected.txt deleted file mode 100644 index d4a85ceab..000000000 --- a/amend/tests/001-nop/expected.txt +++ /dev/null @@ -1 +0,0 @@ -I am a jelly donut. diff --git a/amend/tests/001-nop/info.txt b/amend/tests/001-nop/info.txt deleted file mode 100644 index 9942f10da..000000000 --- a/amend/tests/001-nop/info.txt +++ /dev/null @@ -1,2 +0,0 @@ -This is a sample no-op test, which does at least serve to verify that the -test harness is working. diff --git a/amend/tests/001-nop/run b/amend/tests/001-nop/run deleted file mode 100644 index 51637c147..000000000 --- a/amend/tests/001-nop/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -echo 'I am a jelly donut.' diff --git a/amend/tests/002-lex-empty/SKIP b/amend/tests/002-lex-empty/SKIP deleted file mode 100644 index e69de29bb..000000000 --- a/amend/tests/002-lex-empty/SKIP +++ /dev/null diff --git a/amend/tests/002-lex-empty/expected.txt b/amend/tests/002-lex-empty/expected.txt deleted file mode 100644 index 822a54c23..000000000 --- a/amend/tests/002-lex-empty/expected.txt +++ /dev/null @@ -1 +0,0 @@ - EOF diff --git a/amend/tests/002-lex-empty/info.txt b/amend/tests/002-lex-empty/info.txt deleted file mode 100644 index 090083fc6..000000000 --- a/amend/tests/002-lex-empty/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test to make sure that an empty file is accepted properly. diff --git a/amend/tests/002-lex-empty/input b/amend/tests/002-lex-empty/input deleted file mode 100644 index e69de29bb..000000000 --- a/amend/tests/002-lex-empty/input +++ /dev/null diff --git a/amend/tests/002-lex-empty/run b/amend/tests/002-lex-empty/run deleted file mode 100644 index 35c4a4fa3..000000000 --- a/amend/tests/002-lex-empty/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input diff --git a/amend/tests/003-lex-command/expected.txt b/amend/tests/003-lex-command/expected.txt deleted file mode 100644 index e40db0c7c..000000000 --- a/amend/tests/003-lex-command/expected.txt +++ /dev/null @@ -1,13 +0,0 @@ - IDENTIFIER<this_identifier_is_not_assert> EOL - IDENTIFIER<NEITHER_IS_THIS_123> EOL - IDENTIFIER<but_the_next_one_is> EOL - IDENTIFIER<assert> EOL - IDENTIFIER<next_one_is_not_an_identifier> EOL -line 6: unexpected character at '1' - EOF -line 1: unexpected character at '"' - EOF -line 1: unexpected character at '=' - EOF -line 1: unexpected character at '9' - EOF diff --git a/amend/tests/003-lex-command/info.txt b/amend/tests/003-lex-command/info.txt deleted file mode 100644 index 929664855..000000000 --- a/amend/tests/003-lex-command/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test to make sure that simple command names are tokenized properly. diff --git a/amend/tests/003-lex-command/input b/amend/tests/003-lex-command/input deleted file mode 100644 index b9ef231b0..000000000 --- a/amend/tests/003-lex-command/input +++ /dev/null @@ -1,6 +0,0 @@ -this_identifier_is_not_assert -NEITHER_IS_THIS_123 -but_the_next_one_is -assert -next_one_is_not_an_identifier -12not_an_identifier diff --git a/amend/tests/003-lex-command/input2 b/amend/tests/003-lex-command/input2 deleted file mode 100644 index eb5daf761..000000000 --- a/amend/tests/003-lex-command/input2 +++ /dev/null @@ -1 +0,0 @@ -"quoted" diff --git a/amend/tests/003-lex-command/input3 b/amend/tests/003-lex-command/input3 deleted file mode 100644 index f1c873878..000000000 --- a/amend/tests/003-lex-command/input3 +++ /dev/null @@ -1 +0,0 @@ -== diff --git a/amend/tests/003-lex-command/input4 b/amend/tests/003-lex-command/input4 deleted file mode 100644 index 3ad5abd03..000000000 --- a/amend/tests/003-lex-command/input4 +++ /dev/null @@ -1 +0,0 @@ -99 diff --git a/amend/tests/003-lex-command/run b/amend/tests/003-lex-command/run deleted file mode 100644 index 2e21fab03..000000000 --- a/amend/tests/003-lex-command/run +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input -amend --debug-lex input2 -amend --debug-lex input3 -amend --debug-lex input4 diff --git a/amend/tests/004-lex-comment/expected.txt b/amend/tests/004-lex-comment/expected.txt deleted file mode 100644 index a728a5e70..000000000 --- a/amend/tests/004-lex-comment/expected.txt +++ /dev/null @@ -1,5 +0,0 @@ - IDENTIFIER<comment_on_this_line> EOL - IDENTIFIER<none_on_this_one> EOL - EOL - EOL - EOF diff --git a/amend/tests/004-lex-comment/info.txt b/amend/tests/004-lex-comment/info.txt deleted file mode 100644 index 06912483b..000000000 --- a/amend/tests/004-lex-comment/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test to make sure that comments are stripped out. diff --git a/amend/tests/004-lex-comment/input b/amend/tests/004-lex-comment/input deleted file mode 100644 index 6736c954c..000000000 --- a/amend/tests/004-lex-comment/input +++ /dev/null @@ -1,4 +0,0 @@ -comment_on_this_line # this is a "comment" (with / a bunch) # \\ of stuff \ -none_on_this_one -# beginning of line - # preceded by whitespace diff --git a/amend/tests/004-lex-comment/run b/amend/tests/004-lex-comment/run deleted file mode 100644 index 35c4a4fa3..000000000 --- a/amend/tests/004-lex-comment/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input diff --git a/amend/tests/005-lex-quoted-string/expected.txt b/amend/tests/005-lex-quoted-string/expected.txt deleted file mode 100644 index 9bb5ac485..000000000 --- a/amend/tests/005-lex-quoted-string/expected.txt +++ /dev/null @@ -1,13 +0,0 @@ - IDENTIFIER<test> WORD<string> EOL - IDENTIFIER<test> WORD<string with spaces> EOL - IDENTIFIER<test> WORD<string with "escaped" quotes> EOL - IDENTIFIER<test> WORD<string with \escaped\ backslashes> EOL - IDENTIFIER<test> WORD<string with # a comment character> EOL - EOF - EOL - IDENTIFIER<test1>line 2: unterminated string at ' -' - ??? <0> - EOL - IDENTIFIER<test1>line 2: illegal escape at '\n' - ??? <0> diff --git a/amend/tests/005-lex-quoted-string/info.txt b/amend/tests/005-lex-quoted-string/info.txt deleted file mode 100644 index be458bd36..000000000 --- a/amend/tests/005-lex-quoted-string/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test to make sure that quoted strings are tokenized properly. diff --git a/amend/tests/005-lex-quoted-string/input b/amend/tests/005-lex-quoted-string/input deleted file mode 100644 index 2b34bbcfa..000000000 --- a/amend/tests/005-lex-quoted-string/input +++ /dev/null @@ -1,5 +0,0 @@ -test "string" -test "string with spaces" -test "string with \"escaped\" quotes" -test "string with \\escaped\\ backslashes" -test "string with # a comment character" diff --git a/amend/tests/005-lex-quoted-string/input2 b/amend/tests/005-lex-quoted-string/input2 deleted file mode 100644 index 09e668957..000000000 --- a/amend/tests/005-lex-quoted-string/input2 +++ /dev/null @@ -1,2 +0,0 @@ -# This should fail -test1 "unterminated string diff --git a/amend/tests/005-lex-quoted-string/input3 b/amend/tests/005-lex-quoted-string/input3 deleted file mode 100644 index 02f3f8530..000000000 --- a/amend/tests/005-lex-quoted-string/input3 +++ /dev/null @@ -1,2 +0,0 @@ -# This should fail -test1 "string with illegal escape \n in the middle" diff --git a/amend/tests/005-lex-quoted-string/run b/amend/tests/005-lex-quoted-string/run deleted file mode 100644 index 7b1292a75..000000000 --- a/amend/tests/005-lex-quoted-string/run +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input -amend --debug-lex input2 -amend --debug-lex input3 diff --git a/amend/tests/006-lex-words/SKIP b/amend/tests/006-lex-words/SKIP deleted file mode 100644 index e69de29bb..000000000 --- a/amend/tests/006-lex-words/SKIP +++ /dev/null diff --git a/amend/tests/006-lex-words/expected.txt b/amend/tests/006-lex-words/expected.txt deleted file mode 100644 index a78a0b177..000000000 --- a/amend/tests/006-lex-words/expected.txt +++ /dev/null @@ -1,6 +0,0 @@ - IDENTIFIER<test> WORD<this> WORD<has> WORD<a> WORD<bunch> WORD<of> WORD<BARE> WORD<ALPHA> WORD<WORDS> EOL - IDENTIFIER<test> WORD<12> WORD<this> WORD<has(some> WORD<)> WORD<ALPHANUMER1C> WORD<and> WORD<\\> WORD<whatever> WORD<characters> EOL - IDENTIFIER<test> WORD<this> WORD<has> WORD<mixed> WORD<bare> WORD<and quoted> WORD<words> EOL - IDENTIFIER<test> WORD<what> WORD<about> WORD<quotesin the middle?> EOL - IDENTIFIER<test> WORD<"""shouldn't> WORD<be> WORD<a> WORD<quoted> WORD<string> EOL - EOF diff --git a/amend/tests/006-lex-words/info.txt b/amend/tests/006-lex-words/info.txt deleted file mode 100644 index dd3701607..000000000 --- a/amend/tests/006-lex-words/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test to make sure that argument words are tokenized properly. diff --git a/amend/tests/006-lex-words/input b/amend/tests/006-lex-words/input deleted file mode 100644 index a4de63821..000000000 --- a/amend/tests/006-lex-words/input +++ /dev/null @@ -1,5 +0,0 @@ -test this has a bunch of BARE ALPHA WORDS -test 12 this has(some ) ALPHANUMER1C and \\ whatever characters -test this has mixed bare "and quoted" words -test what about quotes"in the middle?" -test \"\"\"shouldn't be a quoted string diff --git a/amend/tests/006-lex-words/input2 b/amend/tests/006-lex-words/input2 deleted file mode 100644 index 09e668957..000000000 --- a/amend/tests/006-lex-words/input2 +++ /dev/null @@ -1,2 +0,0 @@ -# This should fail -test1 "unterminated string diff --git a/amend/tests/006-lex-words/input3 b/amend/tests/006-lex-words/input3 deleted file mode 100644 index 02f3f8530..000000000 --- a/amend/tests/006-lex-words/input3 +++ /dev/null @@ -1,2 +0,0 @@ -# This should fail -test1 "string with illegal escape \n in the middle" diff --git a/amend/tests/006-lex-words/run b/amend/tests/006-lex-words/run deleted file mode 100644 index 35c4a4fa3..000000000 --- a/amend/tests/006-lex-words/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input diff --git a/amend/tests/007-lex-real-script/expected.txt b/amend/tests/007-lex-real-script/expected.txt deleted file mode 100644 index 012f62c8d..000000000 --- a/amend/tests/007-lex-real-script/expected.txt +++ /dev/null @@ -1,11 +0,0 @@ - IDENTIFIER<assert> IDENTIFIER<hash_dir> ( STRING<SYS:> ) == STRING<112345oldhashvalue1234123> EOL - IDENTIFIER<mark> WORD<SYS:> WORD<dirty> EOL - IDENTIFIER<copy_dir> WORD<PKG:android-files> WORD<SYS:> EOL - IDENTIFIER<assert> IDENTIFIER<hash_dir> ( STRING<SYS:> ) == STRING<667890newhashvalue6678909> EOL - IDENTIFIER<mark> WORD<SYS:> WORD<clean> EOL - IDENTIFIER<done> EOL - IDENTIFIER<assert> IDENTIFIER<hash_dir> ( STRING<SYS:> , STRING<blah> ) == STRING<112345oldhashvalue1234123> EOL - IDENTIFIER<assert> STRING<true> == STRING<false> EOL - IDENTIFIER<assert> IDENTIFIER<one> ( STRING<abc> , IDENTIFIER<two> ( STRING<def> ) ) == STRING<five> EOL - IDENTIFIER<assert> IDENTIFIER<hash_dir> ( STRING<SYS:> ) == STRING<667890newhashvalue6678909> || IDENTIFIER<hash_dir> ( STRING<SYS:> ) == STRING<667890newhashvalue6678909> EOL - EOF diff --git a/amend/tests/007-lex-real-script/info.txt b/amend/tests/007-lex-real-script/info.txt deleted file mode 100644 index 5e321f552..000000000 --- a/amend/tests/007-lex-real-script/info.txt +++ /dev/null @@ -1 +0,0 @@ -An input script similar to one that will actually be used in practice. diff --git a/amend/tests/007-lex-real-script/input b/amend/tests/007-lex-real-script/input deleted file mode 100644 index f3f1fd986..000000000 --- a/amend/tests/007-lex-real-script/input +++ /dev/null @@ -1,10 +0,0 @@ -assert hash_dir("SYS:") == "112345oldhashvalue1234123" -mark SYS: dirty -copy_dir "PKG:android-files" SYS: -assert hash_dir("SYS:") == "667890newhashvalue6678909" -mark SYS: clean -done -assert hash_dir("SYS:", "blah") == "112345oldhashvalue1234123" -assert "true" == "false" -assert one("abc", two("def")) == "five" -assert hash_dir("SYS:") == "667890newhashvalue6678909" || hash_dir("SYS:") == "667890newhashvalue6678909" diff --git a/amend/tests/007-lex-real-script/run b/amend/tests/007-lex-real-script/run deleted file mode 100644 index 35c4a4fa3..000000000 --- a/amend/tests/007-lex-real-script/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-lex input diff --git a/amend/tests/008-parse-real-script/expected.txt b/amend/tests/008-parse-real-script/expected.txt deleted file mode 100644 index dabf6d4e2..000000000 --- a/amend/tests/008-parse-real-script/expected.txt +++ /dev/null @@ -1,74 +0,0 @@ -command "assert" { - STRING EQ { - FUNCTION hash_dir ( - "SYS:" - ) - "112345oldhashvalue1234123" - } -} -command "mark" { - "SYS:" - "dirty" -} -command "copy_dir" { - "PKG:android-files" - "SYS:" -} -command "assert" { - STRING EQ { - FUNCTION hash_dir ( - "SYS:" - ) - "667890newhashvalue6678909" - } -} -command "mark" { - "SYS:" - "clean" -} -command "done" { -} -command "assert" { - STRING EQ { - FUNCTION hash_dir ( - "SYS:" - "blah" - ) - "112345oldhashvalue1234123" - } -} -command "assert" { - STRING EQ { - "true" - "false" - } -} -command "assert" { - STRING NE { - FUNCTION matches ( - FUNCTION hash_dir ( - "SYS:" - ) - "667890newhashvalue6678909" - "999999newhashvalue6678909" - ) - "" - } -} -command "assert" { - BOOLEAN OR { - STRING EQ { - FUNCTION hash_dir ( - "SYS:" - ) - "667890newhashvalue6678909" - } - STRING EQ { - FUNCTION hash_dir ( - "SYS:" - ) - "999999newhashvalue6678909" - } - } -} -amend: Parse successful. diff --git a/amend/tests/008-parse-real-script/info.txt b/amend/tests/008-parse-real-script/info.txt deleted file mode 100644 index 5e321f552..000000000 --- a/amend/tests/008-parse-real-script/info.txt +++ /dev/null @@ -1 +0,0 @@ -An input script similar to one that will actually be used in practice. diff --git a/amend/tests/008-parse-real-script/input b/amend/tests/008-parse-real-script/input deleted file mode 100644 index b07330695..000000000 --- a/amend/tests/008-parse-real-script/input +++ /dev/null @@ -1,10 +0,0 @@ -assert hash_dir("SYS:") == "112345oldhashvalue1234123" -mark SYS: dirty -copy_dir "PKG:android-files" SYS: -assert hash_dir("SYS:") == "667890newhashvalue6678909" -mark SYS: clean -done -assert hash_dir("SYS:", "blah") == "112345oldhashvalue1234123" -assert "true" == "false" -assert matches(hash_dir("SYS:"), "667890newhashvalue6678909", "999999newhashvalue6678909") != "" -assert hash_dir("SYS:") == "667890newhashvalue6678909" || hash_dir("SYS:") == "999999newhashvalue6678909" diff --git a/amend/tests/008-parse-real-script/run b/amend/tests/008-parse-real-script/run deleted file mode 100644 index 9544e1b9b..000000000 --- a/amend/tests/008-parse-real-script/run +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -amend --debug-ast input diff --git a/amend/tests/XXX-long-token/SKIP b/amend/tests/XXX-long-token/SKIP deleted file mode 100644 index e69de29bb..000000000 --- a/amend/tests/XXX-long-token/SKIP +++ /dev/null diff --git a/amend/tests/XXX-stack-overflow/SKIP b/amend/tests/XXX-stack-overflow/SKIP deleted file mode 100644 index e69de29bb..000000000 --- a/amend/tests/XXX-stack-overflow/SKIP +++ /dev/null diff --git a/amend/tests/one-test b/amend/tests/one-test deleted file mode 100755 index 9cebd3f47..000000000 --- a/amend/tests/one-test +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. -prog="$0" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/`basename "${prog}"` - -info="info.txt" -run="run" -expected="expected.txt" -output="out.txt" -skip="SKIP" - -dev_mode="no" -if [ "x$1" = "x--dev" ]; then - dev_mode="yes" - shift -fi - -update_mode="no" -if [ "x$1" = "x--update" ]; then - update_mode="yes" - shift -fi - -usage="no" -if [ "x$1" = "x--help" ]; then - usage="yes" -else - if [ "x$1" = "x" ]; then - testdir=`basename "$oldwd"` - else - testdir="$1" - fi - - if [ '!' -d "$testdir" ]; then - td2=`echo ${testdir}-*` - if [ '!' -d "$td2" ]; then - echo "${testdir}: no such test directory" 1>&2 - usage="yes" - fi - testdir="$td2" - fi -fi - -if [ "$usage" = "yes" ]; then - prog=`basename $prog` - ( - echo "usage:" - echo " $prog --help Print this message." - echo " $prog testname Run test normally." - echo " $prog --dev testname Development mode (dump to stdout)." - echo " $prog --update testname Update mode (replace expected.txt)." - echo " Omitting the test name uses the current directory as the test." - ) 1>&2 - exit 1 -fi - -td_info="$testdir"/"$info" -td_run="$testdir"/"$run" -td_expected="$testdir"/"$expected" -td_skip="$testdir"/"$skip" - -if [ -r "$td_skip" ]; then - exit 2 -fi - -tmpdir=/tmp/test-$$ - -if [ '!' '(' -r "$td_info" -a -r "$td_run" -a -r "$td_expected" ')' ]; then - echo "${testdir}: missing files" 1>&2 - exit 1 -fi - -# copy the test to a temp dir and run it - -echo "${testdir}: running..." 1>&2 - -rm -rf "$tmpdir" -cp -Rp "$testdir" "$tmpdir" -cd "$tmpdir" -chmod 755 "$run" - -#PATH="${progdir}/../build/bin:${PATH}" - -good="no" -if [ "$dev_mode" = "yes" ]; then - "./$run" 2>&1 - echo "exit status: $?" 1>&2 - good="yes" -elif [ "$update_mode" = "yes" ]; then - "./$run" >"${progdir}/$td_expected" 2>&1 - good="yes" -else - "./$run" >"$output" 2>&1 - cmp -s "$expected" "$output" - if [ "$?" = "0" ]; then - # output == expected - good="yes" - echo "$testdir"': succeeded!' 1>&2 - fi -fi - -if [ "$good" = "yes" ]; then - cd "$oldwd" - rm -rf "$tmpdir" - exit 0 -fi - -( - echo "${testdir}: FAILED!" - echo ' ' - echo '#################### info' - cat "$info" | sed 's/^/# /g' - echo '#################### diffs' - diff -u "$expected" "$output" - echo '####################' - echo ' ' - echo "files left in $tmpdir" -) 1>&2 - -exit 1 diff --git a/amend/tests/run-all-tests b/amend/tests/run-all-tests deleted file mode 100755 index c696bbd6c..000000000 --- a/amend/tests/run-all-tests +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2007 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. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. -prog="$0" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/`basename "${prog}"` - -passed=0 -skipped=0 -skipNames="" -failed=0 -failNames="" - -for i in *; do - if [ -d "$i" -a -r "$i" ]; then - ./one-test "$i" - status=$? - if [ "$status" = "0" ]; then - ((passed += 1)) - elif [ "$status" = "2" ]; then - ((skipped += 1)) - skipNames="$skipNames $i" - else - ((failed += 1)) - failNames="$failNames $i" - fi - fi -done - -echo "passed: $passed test(s)" -echo "skipped: $skipped test(s)" - -for i in $skipNames; do - echo "skipped: $i" -done - -echo "failed: $failed test(s)" - -for i in $failNames; do - echo "failed: $i" -done diff --git a/commands.c b/commands.c deleted file mode 100644 index b4678ba6f..000000000 --- a/commands.c +++ /dev/null @@ -1,1075 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#undef NDEBUG - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <unistd.h> - -#include "amend/commands.h" -#include "commands.h" -#include "common.h" -#include "cutils/misc.h" -#include "cutils/properties.h" -#include "firmware.h" -#include "minzip/DirUtil.h" -#include "minzip/Zip.h" -#include "roots.h" - -static int gDidShowProgress = 0; - -#define UNUSED(p) ((void)(p)) - -#define CHECK_BOOL() \ - do { \ - assert(argv == NULL); \ - if (argv != NULL) return -1; \ - assert(argc == true || argc == false); \ - if (argc != true && argc != false) return -1; \ - } while (false) - -#define CHECK_WORDS() \ - do { \ - assert(argc >= 0); \ - if (argc < 0) return -1; \ - assert(argc == 0 || argv != NULL); \ - if (argc != 0 && argv == NULL) return -1; \ - } while (false) - -#define CHECK_FN() \ - do { \ - CHECK_WORDS(); \ - assert(result != NULL); \ - if (result == NULL) return -1; \ - } while (false) - -/* - * Command definitions - */ - -/* assert <boolexpr> - */ -static int -cmd_assert(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_BOOL(); - - /* If our argument is false, return non-zero (failure) - * If our argument is true, return zero (success) - */ - if (argc) { - return 0; - } else { - return 1; - } -} - -/* format <root> - */ -static int -cmd_format(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); - - if (argc != 1) { - LOGE("Command %s requires exactly one argument\n", name); - return 1; - } - const char *root = argv[0]; - ui_print("Formatting %s...\n", root); - - int ret = format_root_device(root); - if (ret != 0) { - LOGE("Can't format %s\n", root); - return 1; - } - - return 0; -} - -/* delete <file1> [<fileN> ...] - * delete_recursive <file-or-dir1> [<file-or-dirN> ...] - * - * Like "rm -f", will try to delete every named file/dir, even if - * earlier ones fail. Recursive deletes that fail halfway through - * give up early. - */ -static int -cmd_delete(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - int nerr = 0; - bool recurse; - - if (argc < 1) { - LOGE("Command %s requires at least one argument\n", name); - return 1; - } - - recurse = (strcmp(name, "delete_recursive") == 0); - ui_print("Deleting files...\n"); - - int i; - for (i = 0; i < argc; i++) { - const char *root_path = argv[i]; - char pathbuf[PATH_MAX]; - const char *path; - - /* This guarantees that all paths use "SYSTEM:"-style roots; - * plain paths won't make it through translate_root_path(). - */ - path = translate_root_path(root_path, pathbuf, sizeof(pathbuf)); - if (path != NULL) { - int ret = ensure_root_path_mounted(root_path); - if (ret < 0) { - LOGW("Can't mount volume to delete \"%s\"\n", root_path); - nerr++; - continue; - } - if (recurse) { - ret = dirUnlinkHierarchy(path); - } else { - ret = unlink(path); - } - if (ret != 0 && errno != ENOENT) { - LOGW("Can't delete %s\n(%s)\n", path, strerror(errno)); - nerr++; - } - } else { - nerr++; - } - } -//TODO: add a way to fail if a delete didn't work - - return 0; -} - -typedef struct { - int num_done; - int num_total; -} ExtractContext; - -static void extract_count_cb(const char *fn, void *cookie) -{ - ++((ExtractContext*) cookie)->num_total; -} - -static void extract_cb(const char *fn, void *cookie) -{ - // minzip writes the filename to the log, so we don't need to - ExtractContext *ctx = (ExtractContext*) cookie; - ui_set_progress((float) ++ctx->num_done / ctx->num_total); -} - -/* copy_dir <src-dir> <dst-dir> [<timestamp>] - * - * The contents of <src-dir> will become the contents of <dst-dir>. - * The original contents of <dst-dir> are preserved unless something - * in <src-dir> overwrote them. - * - * e.g., for "copy_dir PKG:system SYSTEM:", the file "PKG:system/a" - * would be copied to "SYSTEM:a". - * - * The specified timestamp (in decimal seconds since 1970) will be used, - * or a fixed default timestamp will be supplied otherwise. - */ -static int -cmd_copy_dir(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); - - // To create a consistent system image, never use the clock for timestamps. - struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default - if (argc == 3) { - char *end; - time_t value = strtoul(argv[2], &end, 0); - if (value == 0 || end[0] != '\0') { - LOGE("Command %s: invalid timestamp \"%s\"\n", name, argv[2]); - return 1; - } else if (value < timestamp.modtime) { - LOGE("Command %s: timestamp \"%s\" too early\n", name, argv[2]); - return 1; - } - timestamp.modtime = timestamp.actime = value; - } else if (argc != 2) { - LOGE("Command %s requires exactly two arguments\n", name); - return 1; - } - - // Use 40% of the progress bar (80% post-verification) by default - ui_print("Copying files...\n"); - if (!gDidShowProgress) ui_show_progress(DEFAULT_FILES_PROGRESS_FRACTION, 0); - - /* Mount the destination volume if it isn't already. - */ - const char *dst_root_path = argv[1]; - int ret = ensure_root_path_mounted(dst_root_path); - if (ret < 0) { - LOGE("Can't mount %s\n", dst_root_path); - return 1; - } - - /* Get the real target path. - */ - char dstpathbuf[PATH_MAX]; - const char *dst_path; - dst_path = translate_root_path(dst_root_path, - dstpathbuf, sizeof(dstpathbuf)); - if (dst_path == NULL) { - LOGE("Command %s: bad destination path \"%s\"\n", name, dst_root_path); - return 1; - } - - /* Try to copy the directory. The source may be inside a package. - */ - const char *src_root_path = argv[0]; - char srcpathbuf[PATH_MAX]; - const char *src_path; - if (is_package_root_path(src_root_path)) { - const ZipArchive *package; - src_path = translate_package_root_path(src_root_path, - srcpathbuf, sizeof(srcpathbuf), &package); - if (src_path == NULL) { - LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); - return 1; - } - - /* Extract the files. Set MZ_EXTRACT_FILES_ONLY, because only files - * are validated by the signature. Do a dry run first to count how - * many there are (and find some errors early). - */ - ExtractContext ctx; - ctx.num_done = 0; - ctx.num_total = 0; - - if (!mzExtractRecursive(package, src_path, dst_path, - MZ_EXTRACT_FILES_ONLY | MZ_EXTRACT_DRY_RUN, - ×tamp, extract_count_cb, (void *) &ctx) || - !mzExtractRecursive(package, src_path, dst_path, - MZ_EXTRACT_FILES_ONLY, - ×tamp, extract_cb, (void *) &ctx)) { - LOGW("Command %s: couldn't extract \"%s\" to \"%s\"\n", - name, src_root_path, dst_root_path); - return 1; - } - } else { - LOGE("Command %s: non-package source path \"%s\" not yet supported\n", - name, src_root_path); -//xxx mount the src volume -//xxx - return 255; - } - - return 0; -} - -/* run_program <program-file> [<args> ...] - * - * Run an external program included in the update package. - */ -static int -cmd_run_program(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - - if (argc < 1) { - LOGE("Command %s requires at least one argument\n", name); - return 1; - } - - // Copy the program file to temporary storage. - if (!is_package_root_path(argv[0])) { - LOGE("Command %s: non-package program file \"%s\" not supported\n", - name, argv[0]); - return 1; - } - - char path[PATH_MAX]; - const ZipArchive *package; - if (!translate_package_root_path(argv[0], path, sizeof(path), &package)) { - LOGE("Command %s: bad source path \"%s\"\n", name, argv[0]); - return 1; - } - - const ZipEntry *entry = mzFindZipEntry(package, path); - if (entry == NULL) { - LOGE("Can't find %s\n", path); - return 1; - } - - static const char *binary = "/tmp/run_program_binary"; - unlink(binary); // just to be sure - int fd = creat(binary, 0755); - if (fd < 0) { - LOGE("Can't make %s\n", binary); - return 1; - } - bool ok = mzExtractZipEntryToFile(package, entry, fd); - close(fd); - - if (!ok) { - LOGE("Can't copy %s\n", path); - return 1; - } - - // Create a copy of argv to NULL-terminate it, as execv requires - char **args = (char **) malloc(sizeof(char*) * (argc + 1)); - memcpy(args, argv, sizeof(char*) * argc); - args[argc] = NULL; - - pid_t pid = fork(); - if (pid == 0) { - execv(binary, args); - fprintf(stderr, "E:Can't run %s\n(%s)\n", binary, strerror(errno)); - _exit(-1); - } - - int status; - waitpid(pid, &status, 0); - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - return 0; - } else { - LOGE("Error in %s\n(Status %d)\n", path, status); - return 1; - } -} - -/* set_perm <uid> <gid> <mode> <path> [... <pathN>] - * set_perm_recursive <uid> <gid> <dir-mode> <file-mode> <path> [... <pathN>] - * - * Like "chmod", "chown" and "chgrp" all in one, set ownership and permissions - * of single files or entire directory trees. Any error causes failure. - * User, group, and modes must all be integer values (hex or octal OK). - */ -static int -cmd_set_perm(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - bool recurse = !strcmp(name, "set_perm_recursive"); - - int min_args = 4 + (recurse ? 1 : 0); - if (argc < min_args) { - LOGE("Command %s requires at least %d args\n", name, min_args); - return 1; - } - - // All the arguments except the path(s) are numeric. - int i, n[min_args - 1]; - for (i = 0; i < min_args - 1; ++i) { - char *end; - n[i] = strtoul(argv[i], &end, 0); - if (end[0] != '\0' || argv[i][0] == '\0') { - LOGE("Command %s: invalid argument \"%s\"\n", name, argv[i]); - return 1; - } - } - - for (i = min_args - 1; i < min_args; ++i) { - char path[PATH_MAX]; - if (translate_root_path(argv[i], path, sizeof(path)) == NULL) { - LOGE("Command %s: bad path \"%s\"\n", name, argv[i]); - return 1; - } - - if (ensure_root_path_mounted(argv[i])) { - LOGE("Can't mount %s\n", argv[i]); - return 1; - } - - if (recurse - ? dirSetHierarchyPermissions(path, n[0], n[1], n[2], n[3]) - : (chown(path, n[0], n[1]) || chmod(path, n[2]))) { - LOGE("Can't chown/mod %s\n(%s)\n", path, strerror(errno)); - return 1; - } - } - - return 0; -} - -/* show_progress <fraction> <duration> - * - * Use <fraction> of the on-screen progress meter for the next operation, - * automatically advancing the meter over <duration> seconds (or more rapidly - * if the actual rate of progress can be determined). - */ -static int -cmd_show_progress(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - - if (argc != 2) { - LOGE("Command %s requires exactly two arguments\n", name); - return 1; - } - - char *end; - double fraction = strtod(argv[0], &end); - if (end[0] != '\0' || argv[0][0] == '\0' || fraction < 0 || fraction > 1) { - LOGE("Command %s: invalid fraction \"%s\"\n", name, argv[0]); - return 1; - } - - int duration = strtoul(argv[1], &end, 0); - if (end[0] != '\0' || argv[0][0] == '\0') { - LOGE("Command %s: invalid duration \"%s\"\n", name, argv[1]); - return 1; - } - - // Half of the progress bar is taken by verification, - // so everything that happens during installation is scaled. - ui_show_progress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), duration); - gDidShowProgress = 1; - return 0; -} - -/* symlink <link-target> <link-path> - * - * Create a symlink, like "ln -s". The link path must not exist already. - * Note that <link-path> is in root:path format, but <link-target> is - * for the target filesystem (and may be relative). - */ -static int -cmd_symlink(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - - if (argc != 2) { - LOGE("Command %s requires exactly two arguments\n", name); - return 1; - } - - char path[PATH_MAX]; - if (translate_root_path(argv[1], path, sizeof(path)) == NULL) { - LOGE("Command %s: bad path \"%s\"\n", name, argv[1]); - return 1; - } - - if (ensure_root_path_mounted(argv[1])) { - LOGE("Can't mount %s\n", argv[1]); - return 1; - } - - if (symlink(argv[0], path)) { - LOGE("Can't symlink %s\n", path); - return 1; - } - - return 0; -} - -struct FirmwareContext { - size_t total_bytes, done_bytes; - char *data; -}; - -static bool firmware_fn(const unsigned char *data, int data_len, void *cookie) -{ - struct FirmwareContext *context = (struct FirmwareContext*) cookie; - if (context->done_bytes + data_len > context->total_bytes) { - LOGE("Data overrun in firmware\n"); - return false; // Should not happen, but let's be safe. - } - - memcpy(context->data + context->done_bytes, data, data_len); - context->done_bytes += data_len; - ui_set_progress(context->done_bytes * 1.0 / context->total_bytes); - return true; -} - -/* write_radio_image <src-image> - * write_hboot_image <src-image> - * Doesn't actually take effect until the rest of installation finishes. - */ -static int -cmd_write_firmware_image(const char *name, void *cookie, - int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - - if (argc != 1) { - LOGE("Command %s requires exactly one argument\n", name); - return 1; - } - - const char *type; - if (!strcmp(name, "write_radio_image")) { - type = "radio"; - } else if (!strcmp(name, "write_hboot_image")) { - type = "hboot"; - } else { - LOGE("Unknown firmware update command %s\n", name); - return 1; - } - - if (!is_package_root_path(argv[0])) { - LOGE("Command %s: non-package image file \"%s\" not supported\n", - name, argv[0]); - return 1; - } - - ui_print("Extracting %s image...\n", type); - char path[PATH_MAX]; - const ZipArchive *package; - if (!translate_package_root_path(argv[0], path, sizeof(path), &package)) { - LOGE("Command %s: bad source path \"%s\"\n", name, argv[0]); - return 1; - } - - const ZipEntry *entry = mzFindZipEntry(package, path); - if (entry == NULL) { - LOGE("Can't find %s\n", path); - return 1; - } - - // Load the update image into RAM. - struct FirmwareContext context; - context.total_bytes = mzGetZipEntryUncompLen(entry); - context.done_bytes = 0; - context.data = malloc(context.total_bytes); - if (context.data == NULL) { - LOGE("Can't allocate %d bytes for %s\n", context.total_bytes, argv[0]); - return 1; - } - - if (!mzProcessZipEntryContents(package, entry, firmware_fn, &context) || - context.done_bytes != context.total_bytes) { - LOGE("Can't read %s\n", argv[0]); - free(context.data); - return 1; - } - - if (remember_firmware_update(type, context.data, context.total_bytes)) { - LOGE("Can't store %s image\n", type); - free(context.data); - return 1; - } - - return 0; -} - -static bool write_raw_image_process_fn( - const unsigned char *data, - int data_len, void *ctx) -{ - int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len); - if (r == data_len) return true; - LOGE("%s\n", strerror(errno)); - return false; -} - -/* write_raw_image <src-image> <dest-root> - */ -static int -cmd_write_raw_image(const char *name, void *cookie, - int argc, const char *argv[]) -{ - UNUSED(cookie); - CHECK_WORDS(); - - if (argc != 2) { - LOGE("Command %s requires exactly two arguments\n", name); - return 1; - } - - // Use 10% of the progress bar (20% post-verification) by default - const char *src_root_path = argv[0]; - const char *dst_root_path = argv[1]; - ui_print("Writing %s...\n", dst_root_path); - if (!gDidShowProgress) ui_show_progress(DEFAULT_IMAGE_PROGRESS_FRACTION, 0); - - /* Find the source image, which is probably in a package. - */ - if (!is_package_root_path(src_root_path)) { - LOGE("Command %s: non-package source path \"%s\" not yet supported\n", - name, src_root_path); - return 255; - } - - /* Get the package. - */ - char srcpathbuf[PATH_MAX]; - const char *src_path; - const ZipArchive *package; - src_path = translate_package_root_path(src_root_path, - srcpathbuf, sizeof(srcpathbuf), &package); - if (src_path == NULL) { - LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); - return 1; - } - - /* Get the entry. - */ - const ZipEntry *entry = mzFindZipEntry(package, src_path); - if (entry == NULL) { - LOGE("Missing file %s\n", src_path); - return 1; - } - - /* Unmount the destination root if it isn't already. - */ - int ret = ensure_root_path_unmounted(dst_root_path); - if (ret < 0) { - LOGE("Can't unmount %s\n", dst_root_path); - return 1; - } - - /* Open the partition for writing. - */ - const MtdPartition *partition = get_root_mtd_partition(dst_root_path); - if (partition == NULL) { - LOGE("Can't find %s\n", dst_root_path); - return 1; - } - MtdWriteContext *context = mtd_write_partition(partition); - if (context == NULL) { - LOGE("Can't open %s\n", dst_root_path); - return 1; - } - - /* Extract and write the image. - */ - bool ok = mzProcessZipEntryContents(package, entry, - write_raw_image_process_fn, context); - if (!ok) { - LOGE("Error writing %s\n", dst_root_path); - mtd_write_close(context); - return 1; - } - - if (mtd_erase_blocks(context, -1) == (off_t) -1) { - LOGE("Error finishing %s\n", dst_root_path); - mtd_write_close(context); - return -1; - } - - if (mtd_write_close(context)) { - LOGE("Error closing %s\n", dst_root_path); - return -1; - } - return 0; -} - -/* mark <resource> dirty|clean - */ -static int -cmd_mark(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx when marking, save the top-level hash at the mark point -// so we can retry on failure. Otherwise the hashes won't match, -// or someone could intentionally dirty the FS to force a downgrade -//xxx - return -1; -} - -/* done - */ -static int -cmd_done(const char *name, void *cookie, int argc, const char *argv[]) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx - return -1; -} - - -/* - * Function definitions - */ - -/* compatible_with(<version>) - * - * Returns "true" if this version of the script parser and command - * set supports the named version. - */ -static int -fn_compatible_with(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc != 1) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } - - if (!strcmp(argv[0], "0.1") || !strcmp(argv[0], "0.2")) { - *result = strdup("true"); - } else { - *result = strdup(""); - } - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - return 0; -} - -/* update_forced() - * - * Returns "true" if some system setting has determined that - * the update should happen no matter what. - */ -static int -fn_update_forced(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc != 0) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } - - //xxx check some global or property - bool force = true; - if (force) { - *result = strdup("true"); - } else { - *result = strdup(""); - } - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - - return 0; -} - -/* get_mark(<resource>) - * - * Returns the current mark associated with the provided resource. - */ -static int -fn_get_mark(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc != 1) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } - - //xxx look up the value - *result = strdup(""); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - - return 0; -} - -/* hash_dir(<path-to-directory>) - */ -static int -fn_hash_dir(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - int ret = -1; - - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - const char *dir; - if (argc != 1) { - fprintf(stderr, "%s: wrong number of arguments (%d)\n", - name, argc); - return 1; - } else { - dir = argv[0]; - } - - return ret; -} - -/* matches(<str>, <str1> [, <strN>...]) - * If <str> matches (strcmp) any of <str1>...<strN>, returns <str>, - * otherwise returns "". - * - * E.g., assert matches(hash_dir("/path"), "hash1", "hash2") - */ -static int -fn_matches(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - if (argc < 2) { - fprintf(stderr, "%s: not enough arguments (%d < 2)\n", - name, argc); - return 1; - } - - int i; - for (i = 1; i < argc; i++) { - if (strcmp(argv[0], argv[i]) == 0) { - *result = strdup(argv[0]); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - return 0; - } - } - - *result = strdup(""); - if (resultLen != NULL) { - *resultLen = 1; - } - return 0; -} - -/* concat(<str>, <str1> [, <strN>...]) - * Returns the concatenation of all strings. - */ -static int -fn_concat(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - - size_t totalLen = 0; - int i; - for (i = 0; i < argc; i++) { - totalLen += strlen(argv[i]); - } - - char *s = (char *)malloc(totalLen + 1); - if (s == NULL) { - return -1; - } - s[totalLen] = '\0'; - for (i = 0; i < argc; i++) { - //TODO: keep track of the end to avoid walking the string each time - strcat(s, argv[i]); - } - *result = s; - if (resultLen != NULL) { - *resultLen = strlen(s); - } - - return 0; -} - -/* getprop(<property>) - * Returns the named Android system property value, or "" if not set. - */ -static int -fn_getprop(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(cookie); - CHECK_FN(); - - if (argc != 1) { - LOGE("Command %s requires exactly one argument\n", name); - return 1; - } - - char value[PROPERTY_VALUE_MAX]; - property_get(argv[0], value, ""); - - *result = strdup(value); - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - - return 0; -} - -/* file_contains(<filename>, <substring>) - * Returns "true" if the file exists and contains the specified substring. - */ -static int -fn_file_contains(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen) -{ - UNUSED(cookie); - CHECK_FN(); - - if (argc != 2) { - LOGE("Command %s requires exactly two arguments\n", name); - return 1; - } - - char pathbuf[PATH_MAX]; - const char *root_path = argv[0]; - const char *path = translate_root_path(root_path, pathbuf, sizeof(pathbuf)); - if (path == NULL) { - LOGE("Command %s: bad path \"%s\"\n", name, root_path); - return 1; - } - - if (ensure_root_path_mounted(root_path)) { - LOGE("Can't mount %s\n", root_path); - return 1; - } - - const char *needle = argv[1]; - char *haystack = (char*) load_file(path, NULL); - if (haystack == NULL) { - LOGI("%s: Can't read \"%s\" (%s)\n", name, path, strerror(errno)); - *result = ""; /* File not found is not an error. */ - } else if (strstr(haystack, needle) == NULL) { - LOGI("%s: Can't find \"%s\" in \"%s\"\n", name, needle, path); - *result = strdup(""); - free(haystack); - } else { - *result = strdup("true"); - free(haystack); - } - - if (resultLen != NULL) { - *resultLen = strlen(*result); - } - return 0; -} - -int -register_update_commands(RecoveryCommandContext *ctx) -{ - int ret; - - ret = commandInit(); - if (ret < 0) return ret; - - /* - * Commands - */ - - ret = registerCommand("assert", CMD_ARGS_BOOLEAN, cmd_assert, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("delete", CMD_ARGS_WORDS, cmd_delete, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("delete_recursive", CMD_ARGS_WORDS, cmd_delete, - (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("copy_dir", CMD_ARGS_WORDS, - cmd_copy_dir, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("run_program", CMD_ARGS_WORDS, - cmd_run_program, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("set_perm", CMD_ARGS_WORDS, - cmd_set_perm, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("set_perm_recursive", CMD_ARGS_WORDS, - cmd_set_perm, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("show_progress", CMD_ARGS_WORDS, - cmd_show_progress, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("symlink", CMD_ARGS_WORDS, cmd_symlink, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("format", CMD_ARGS_WORDS, cmd_format, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("write_radio_image", CMD_ARGS_WORDS, - cmd_write_firmware_image, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("write_hboot_image", CMD_ARGS_WORDS, - cmd_write_firmware_image, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("write_raw_image", CMD_ARGS_WORDS, - cmd_write_raw_image, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("mark", CMD_ARGS_WORDS, cmd_mark, (void *)ctx); - if (ret < 0) return ret; - - ret = registerCommand("done", CMD_ARGS_WORDS, cmd_done, (void *)ctx); - if (ret < 0) return ret; - - /* - * Functions - */ - - ret = registerFunction("compatible_with", fn_compatible_with, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("update_forced", fn_update_forced, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("get_mark", fn_get_mark, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("hash_dir", fn_hash_dir, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("matches", fn_matches, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("concat", fn_concat, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("getprop", fn_getprop, (void *)ctx); - if (ret < 0) return ret; - - ret = registerFunction("file_contains", fn_file_contains, (void *)ctx); - if (ret < 0) return ret; - - return 0; -} diff --git a/commands.h b/commands.h deleted file mode 100644 index e9acea2ce..000000000 --- a/commands.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2007 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 RECOVERY_COMMANDS_H_ -#define RECOVERY_COMMANDS_H_ - -#include "minzip/Zip.h" - -typedef struct { - ZipArchive *package; -} RecoveryCommandContext; - -int register_update_commands(RecoveryCommandContext *ctx); - -#endif // RECOVERY_COMMANDS_H_ diff --git a/default_recovery_ui.c b/default_recovery_ui.c new file mode 100644 index 000000000..d4e620403 --- /dev/null +++ b/default_recovery_ui.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 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. + */ + +#include <linux/input.h> + +#include "recovery_ui.h" +#include "common.h" + +char* MENU_HEADERS[] = { "Android system recovery utility", + "", + NULL }; + +char* MENU_ITEMS[] = { "reboot system now", + "apply sdcard:update.zip", + "wipe data/factory reset", + "wipe cache partition", + NULL }; + +int device_toggle_display(volatile char* key_pressed, int key_code) { + return key_code == KEY_HOME; +} + +int device_reboot_now(volatile char* key_pressed, int key_code) { + return 0; +} + +int device_handle_key(int key_code, int visible) { + if (visible) { + switch (key_code) { + case KEY_DOWN: + case KEY_VOLUMEDOWN: + return HIGHLIGHT_DOWN; + + case KEY_UP: + case KEY_VOLUMEUP: + return HIGHLIGHT_UP; + + case KEY_ENTER: + return SELECT_ITEM; + } + } + + return NO_ACTION; +} + +int device_perform_action(int which) { + return which; +} + +int device_wipe_data() { + return 0; +} @@ -22,7 +22,6 @@ #include <sys/wait.h> #include <unistd.h> -#include "amend/amend.h" #include "common.h" #include "install.h" #include "mincrypt/rsa.h" @@ -35,85 +34,9 @@ #include "verifier.h" #include "firmware.h" -#define ASSUMED_UPDATE_SCRIPT_NAME "META-INF/com/google/android/update-script" #define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary" #define PUBLIC_KEYS_FILE "/res/keys" -static const ZipEntry * -find_update_script(ZipArchive *zip) -{ -//TODO: Get the location of this script from the MANIFEST.MF file - return mzFindZipEntry(zip, ASSUMED_UPDATE_SCRIPT_NAME); -} - -static int read_data(ZipArchive *zip, const ZipEntry *entry, - char** ppData, int* pLength) { - int len = (int)mzGetZipEntryUncompLen(entry); - if (len <= 0) { - LOGE("Bad data length %d\n", len); - return -1; - } - char *data = malloc(len + 1); - if (data == NULL) { - LOGE("Can't allocate %d bytes for data\n", len + 1); - return -2; - } - bool ok = mzReadZipEntry(zip, entry, data, len); - if (!ok) { - LOGE("Error while reading data\n"); - free(data); - return -3; - } - data[len] = '\0'; // not necessary, but just to be safe - *ppData = data; - if (pLength) { - *pLength = len; - } - return 0; -} - -static int -handle_update_script(ZipArchive *zip, const ZipEntry *update_script_entry) -{ - /* Read the entire script into a buffer. - */ - int script_len; - char* script_data; - if (read_data(zip, update_script_entry, &script_data, &script_len) < 0) { - LOGE("Can't read update script\n"); - return INSTALL_ERROR; - } - - /* Parse the script. Note that the script and parse tree are never freed. - */ - const AmCommandList *commands = parseAmendScript(script_data, script_len); - if (commands == NULL) { - LOGE("Syntax error in update script\n"); - return INSTALL_ERROR; - } else { - UnterminatedString name = mzGetZipEntryFileName(update_script_entry); - LOGI("Parsed %.*s\n", name.len, name.str); - } - - /* Execute the script. - */ - int ret = execCommandList((ExecContext *)1, commands); - if (ret != 0) { - int num = ret; - char *line = NULL, *next = script_data; - while (next != NULL && ret-- > 0) { - line = next; - next = memchr(line, '\n', script_data + script_len - line); - if (next != NULL) *next++ = '\0'; - } - LOGE("Failure at line %d:\n%s\n", num, next ? line : "(not found)"); - return INSTALL_ERROR; - } - - LOGI("Installation complete.\n"); - return INSTALL_SUCCESS; -} - // The update binary ask us to install a firmware file on reboot. Set // that up. Takes ownership of type and filename. static int @@ -252,11 +175,9 @@ try_update_binary(const char *path, ZipArchive *zip) { char* firmware_type = NULL; char* firmware_filename = NULL; - char buffer[81]; + char buffer[1024]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { - LOGI("read: %s", buffer); - char* command = strtok(buffer, " \n"); if (command == NULL) { continue; @@ -331,30 +252,8 @@ handle_update_package(const char *path, ZipArchive *zip, ui_print("Installing update...\n"); int result = try_update_binary(path, zip); - if (result == INSTALL_SUCCESS || result == INSTALL_ERROR) { - register_package_root(NULL, NULL); // Unregister package root - return result; - } - - // if INSTALL_CORRUPT is returned, this package doesn't have an - // update binary. Fall back to the older mechanism of looking for - // an update script. - - const ZipEntry *script_entry; - script_entry = find_update_script(zip); - if (script_entry == NULL) { - LOGE("Can't find update script\n"); - return INSTALL_CORRUPT; - } - - if (register_package_root(zip, path) < 0) { - LOGE("Can't register package root\n"); - return INSTALL_ERROR; - } - - int ret = handle_update_script(zip, script_entry); register_package_root(NULL, NULL); // Unregister package root - return ret; + return result; } // Reads a file containing one or more public keys as produced by diff --git a/minui/graphics.c b/minui/graphics.c index 06c5fdfcd..adbfc09da 100644 --- a/minui/graphics.c +++ b/minui/graphics.c @@ -115,6 +115,7 @@ static void set_active_framebuffer(unsigned n) if (n > 1) return; vi.yres_virtual = vi.yres * 2; vi.yoffset = n * vi.yres; + vi.bits_per_pixel = 16; if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) { perror("active fb swap failed"); } diff --git a/minui/minui.h b/minui/minui.h index 80b47a47f..567d42157 100644 --- a/minui/minui.h +++ b/minui/minui.h @@ -41,22 +41,6 @@ unsigned int gr_get_height(gr_surface surface); // see http://www.mjmwired.net/kernel/Documentation/input/ for info. struct input_event; -// Dream-specific key codes -#define KEY_DREAM_HOME 102 // = KEY_HOME -#define KEY_DREAM_RED 107 // = KEY_END -#define KEY_DREAM_VOLUMEDOWN 114 // = KEY_VOLUMEDOWN -#define KEY_DREAM_VOLUMEUP 115 // = KEY_VOLUMEUP -#define KEY_DREAM_SYM 127 // = KEY_COMPOSE -#define KEY_DREAM_MENU 139 // = KEY_MENU -#define KEY_DREAM_BACK 158 // = KEY_BACK -#define KEY_DREAM_FOCUS 211 // = KEY_HP (light touch on camera) -#define KEY_DREAM_CAMERA 212 // = KEY_CAMERA -#define KEY_DREAM_AT 215 // = KEY_EMAIL -#define KEY_DREAM_GREEN 231 -#define KEY_DREAM_FATTOUCH 258 // = BTN_2 ??? -#define KEY_DREAM_BALL 272 // = BTN_MOUSE -#define KEY_DREAM_TOUCH 330 // = BTN_TOUCH - int ev_init(void); void ev_exit(void); int ev_get(struct input_event *ev, unsigned dont_wait); diff --git a/recovery.c b/recovery.c index 5ccd38f2c..ed6a9c888 100644 --- a/recovery.c +++ b/recovery.c @@ -29,7 +29,6 @@ #include <unistd.h> #include "bootloader.h" -#include "commands.h" #include "common.h" #include "cutils/properties.h" #include "firmware.h" @@ -37,6 +36,7 @@ #include "minui/minui.h" #include "minzip/DirUtil.h" #include "roots.h" +#include "recovery_ui.h" static const struct option OPTIONS[] = { { "send_intent", required_argument, NULL, 's' }, @@ -258,23 +258,6 @@ finish_recovery(const char *send_intent) sync(); // For good measure. } -#define TEST_AMEND 0 -#if TEST_AMEND -static void -test_amend() -{ - extern int test_symtab(void); - extern int test_cmd_fn(void); - int ret; - LOGD("Testing symtab...\n"); - ret = test_symtab(); - LOGD(" returned %d\n", ret); - LOGD("Testing cmd_fn...\n"); - ret = test_cmd_fn(); - LOGD(" returned %d\n", ret); -} -#endif // TEST_AMEND - static int erase_root(const char *root) { @@ -287,26 +270,25 @@ erase_root(const char *root) static void prompt_and_wait() { - char* headers[] = { "Android system recovery <" - EXPAND(RECOVERY_API_VERSION) ">", - "", - "Use trackball to highlight;", - "click to select.", - "", - NULL }; - - // these constants correspond to elements of the items[] list. -#define ITEM_REBOOT 0 -#define ITEM_APPLY_SDCARD 1 -#define ITEM_WIPE_DATA 2 -#define ITEM_WIPE_CACHE 3 - char* items[] = { "reboot system now [Home+Back]", - "apply sdcard:update.zip [Alt+S]", - "wipe data/factory reset [Alt+W]", - "wipe cache partition", + char* title[] = { "Android system recovery <" + EXPAND(RECOVERY_API_VERSION) "e>", + "", NULL }; - ui_start_menu(headers, items); + // count the number of lines in our title, plus the + // product-provided headers. + int count = 0; + char** p; + for (p = title; *p; ++p, ++count); + for (p = MENU_HEADERS; *p; ++p, ++count); + + char** headers = malloc((count+1) * sizeof(char*)); + char** h = headers; + for (p = title; *p; ++p, ++h) *h = *p; + for (p = MENU_HEADERS; *p; ++p, ++h) *h = *p; + *h = NULL; + + ui_start_menu(headers, MENU_ITEMS); int selected = 0; int chosen_item = -1; @@ -314,29 +296,28 @@ prompt_and_wait() ui_reset_progress(); for (;;) { int key = ui_wait_key(); - int alt = ui_key_pressed(KEY_LEFTALT) || ui_key_pressed(KEY_RIGHTALT); int visible = ui_text_visible(); - if (key == KEY_DREAM_BACK && ui_key_pressed(KEY_DREAM_HOME)) { - // Wait for the keys to be released, to avoid triggering - // special boot modes (like coming back into recovery!). - while (ui_key_pressed(KEY_DREAM_BACK) || - ui_key_pressed(KEY_DREAM_HOME)) { - usleep(1000); + int action = device_handle_key(key, visible); + + if (action < 0) { + switch (action) { + case HIGHLIGHT_UP: + --selected; + selected = ui_menu_select(selected); + break; + case HIGHLIGHT_DOWN: + ++selected; + selected = ui_menu_select(selected); + break; + case SELECT_ITEM: + chosen_item = selected; + break; + case NO_ACTION: + break; } - chosen_item = ITEM_REBOOT; - } else if (alt && key == KEY_W) { - chosen_item = ITEM_WIPE_DATA; - } else if (alt && key == KEY_S) { - chosen_item = ITEM_APPLY_SDCARD; - } else if ((key == KEY_DOWN || key == KEY_VOLUMEDOWN) && visible) { - ++selected; - selected = ui_menu_select(selected); - } else if ((key == KEY_UP || key == KEY_VOLUMEUP) && visible) { - --selected; - selected = ui_menu_select(selected); - } else if (key == BTN_MOUSE && visible) { - chosen_item = selected; + } else { + chosen_item = action; } if (chosen_item >= 0) { @@ -344,12 +325,18 @@ prompt_and_wait() // on the screen. ui_end_menu(); + // device-specific code may take some action here. It may + // return one of the core actions handled in the switch + // statement below. + chosen_item = device_perform_action(chosen_item); + switch (chosen_item) { case ITEM_REBOOT: return; case ITEM_WIPE_DATA: ui_print("\n-- Wiping data...\n"); + device_wipe_data(); erase_root("DATA:"); erase_root("CACHE:"); ui_print("Data wipe complete.\n"); @@ -373,8 +360,8 @@ prompt_and_wait() return; // reboot if logs aren't visible } else { if (firmware_update_pending()) { - ui_print("\nReboot via home+back or menu\n" - "to complete installation.\n"); + ui_print("\nReboot via menu to complete\n" + "installation.\n"); } else { ui_print("\nInstall from sdcard complete.\n"); } @@ -384,7 +371,7 @@ prompt_and_wait() // if we didn't return from this function to reboot, show // the menu again. - ui_start_menu(headers, items); + ui_start_menu(headers, MENU_ITEMS); selected = 0; chosen_item = -1; @@ -445,24 +432,19 @@ main(int argc, char **argv) property_list(print_property, NULL); fprintf(stderr, "\n"); -#if TEST_AMEND - test_amend(); -#endif - - RecoveryCommandContext ctx = { NULL }; - if (register_update_commands(&ctx)) { - LOGE("Can't install update commands\n"); - } - int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package); if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n"); - } else if (wipe_data || wipe_cache) { - if (wipe_data && erase_root("DATA:")) status = INSTALL_ERROR; + } else if (wipe_data) { + if (device_wipe_data()) status = INSTALL_ERROR; + if (erase_root("DATA:")) status = INSTALL_ERROR; if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); + } else if (wipe_cache) { + if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR; + if (status != INSTALL_SUCCESS) ui_print("Cache wipe failed.\n"); } else { status = INSTALL_ERROR; // No command specified } diff --git a/recovery_ui.h b/recovery_ui.h new file mode 100644 index 000000000..8818ef303 --- /dev/null +++ b/recovery_ui.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 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 _RECOVERY_UI_H +#define _RECOVERY_UI_H + +// Called in the input thread when a new key (key_code) is pressed. +// *key_pressed is an array of KEY_MAX+1 bytes indicating which other +// keys are already pressed. Return true if the text display should +// be toggled. +extern int device_toggle_display(volatile char* key_pressed, int key_code); + +// Called in the input thread when a new key (key_code) is pressed. +// *key_pressed is an array of KEY_MAX+1 bytes indicating which other +// keys are already pressed. Return true if the device should reboot +// immediately. +extern int device_reboot_now(volatile char* key_pressed, int key_code); + +// Called from the main thread when recovery is waiting for input and +// a key is pressed. key is the code of the key pressed; visible is +// true if the recovery menu is being shown. Implementations can call +// ui_key_pressed() to discover if other keys are being held down. +// Return one of the defined constants below in order to: +// +// - move the menu highlight (HIGHLIGHT_*) +// - invoke the highlighted item (SELECT_ITEM) +// - do nothing (NO_ACTION) +// - invoke a specific action (a menu position: any non-negative number) +extern int device_handle_key(int key, int visible); + +// Perform a recovery action selected from the menu. 'which' will be +// the item number of the selected menu item, or a non-negative number +// returned from device_handle_key(). The menu will be hidden when +// this is called; implementations can call ui_print() to print +// information to the screen. +extern int device_perform_action(int which); + +// Called when we do a wipe data/factory reset operation (either via a +// reboot from the main system with the --wipe_data flag, or when the +// user boots into recovery manually and selects the option from the +// menu.) Can perform whatever device-specific wiping actions are +// needed. Return 0 on success. The userdata and cache partitions +// are erased after this returns (whether it returns success or not). +int device_wipe_data(); + +#define NO_ACTION -1 + +#define HIGHLIGHT_UP -2 +#define HIGHLIGHT_DOWN -3 +#define SELECT_ITEM -4 + +#define ITEM_REBOOT 0 +#define ITEM_APPLY_SDCARD 1 +#define ITEM_WIPE_DATA 2 +#define ITEM_WIPE_CACHE 3 + +// Header text to display above the main menu. +extern char* MENU_HEADERS[]; + +// Text of menu items. +extern char* MENU_ITEMS[]; + +#endif diff --git a/res/images/icon_error.png b/res/images/icon_error.png Binary files differindex 7064c2e23..6cb71c0b3 100644 --- a/res/images/icon_error.png +++ b/res/images/icon_error.png diff --git a/res/images/icon_firmware_install.png b/res/images/icon_firmware_install.png Binary files differindex ee2afac5d..8bfe77589 100644 --- a/res/images/icon_firmware_install.png +++ b/res/images/icon_firmware_install.png diff --git a/res/images/icon_installing.png b/res/images/icon_installing.png Binary files differindex f24f2e33f..1aeb9d959 100644 --- a/res/images/icon_installing.png +++ b/res/images/icon_installing.png @@ -52,6 +52,7 @@ static RootInfo g_roots[] = { { "RECOVERY:", g_mtd_device, NULL, "recovery", "/", g_raw }, { "SDCARD:", "/dev/block/mmcblk0p1", "/dev/block/mmcblk0", NULL, "/sdcard", "vfat" }, { "SYSTEM:", g_mtd_device, NULL, "system", "/system", "yaffs2" }, + { "MBM:", g_mtd_device, NULL, "mbm", NULL, g_raw }, { "TMP:", NULL, NULL, NULL, "/tmp", NULL }, }; #define NUM_ROOTS (sizeof(g_roots) / sizeof(g_roots[0])) diff --git a/tools/ota/Android.mk b/tools/ota/Android.mk index b7a57d6ac..0bde7ee72 100644 --- a/tools/ota/Android.mk +++ b/tools/ota/Android.mk @@ -14,11 +14,6 @@ LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) -LOCAL_MODULE := make-update-script -LOCAL_SRC_FILES := make-update-script.c -include $(BUILD_HOST_EXECUTABLE) - ifneq ($(TARGET_SIMULATOR),true) include $(CLEAR_VARS) diff --git a/tools/ota/make-update-script.c b/tools/ota/make-update-script.c deleted file mode 100644 index 1e1148bba..000000000 --- a/tools/ota/make-update-script.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "private/android_filesystem_config.h" - -#include <dirent.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <unistd.h> - -/* - * Recursively walk the directory tree at <sysdir>/<subdir>, writing - * script commands to set permissions and create symlinks. - * Assume the contents already have the specified default permissions, - * so only output commands if they need to be changed from the defaults. - * - * Note that permissions are set by fs_config(), which uses a lookup table of - * Android permissions. They are not drawn from the build host filesystem. - */ -static void walk_files( - const char *sysdir, const char *subdir, - unsigned default_uid, unsigned default_gid, - unsigned default_dir_mode, unsigned default_file_mode) { - const char *sep = strcmp(subdir, "") ? "/" : ""; - - char fn[PATH_MAX]; - unsigned dir_uid = 0, dir_gid = 0, dir_mode = 0; - snprintf(fn, PATH_MAX, "system%s%s", sep, subdir); - fs_config(fn, 1, &dir_uid, &dir_gid, &dir_mode); - - snprintf(fn, PATH_MAX, "%s%s%s", sysdir, sep, subdir); - DIR *dir = opendir(fn); - if (dir == NULL) { - perror(fn); - exit(1); - } - - /* - * We can use "set_perm" and "set_perm_recursive" to set file permissions - * (owner, group, and file mode) for individual files and entire subtrees. - * We want to use set_perm_recursive efficiently to avoid setting the - * permissions of every single file in the system image individually. - * - * What we do is recursively set our entire subtree to the permissions - * used by the first file we encounter, and then use "set_perm" to adjust - * the permissions of subsequent files which don't match the first one. - * This is bad if the first file is an outlier, but it generally works. - * Subdirectories can do the same thing recursively if they're different. - */ - - int is_first = 1; - const struct dirent *e; - while ((e = readdir(dir))) { - // Skip over "." and ".." entries - if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) continue; - - if (e->d_type == DT_LNK) { // Symlink - - // Symlinks don't really have permissions, so this is orthogonal. - snprintf(fn, PATH_MAX, "%s/%s%s%s", sysdir, subdir, sep, e->d_name); - int len = readlink(fn, fn, PATH_MAX - 1); - if (len <= 0) { - perror(fn); - exit(1); - } - fn[len] = '\0'; - printf("symlink %s SYSTEM:%s%s%s\n", fn, subdir, sep, e->d_name); - - } else if (e->d_type == DT_DIR) { // Subdirectory - - // Use the parent directory as the model for default permissions. - // We haven't seen a file, so just make up some file defaults. - if (is_first && ( - dir_mode != default_dir_mode || - dir_uid != default_uid || dir_gid != default_gid)) { - default_uid = dir_uid; - default_gid = dir_gid; - default_dir_mode = dir_mode; - default_file_mode = dir_mode & default_file_mode & 0666; - printf("set_perm_recursive %d %d 0%o 0%o SYSTEM:%s\n", - default_uid, default_gid, - default_dir_mode, default_file_mode, - subdir); - } - - is_first = 0; - - // Recursively handle the subdirectory. - // Note, the recursive call handles the directory's own permissions. - snprintf(fn, PATH_MAX, "%s%s%s", subdir, sep, e->d_name); - walk_files(sysdir, fn, - default_uid, default_gid, - default_dir_mode, default_file_mode); - - } else { // Ordinary file - - // Get the file's desired permissions. - unsigned file_uid = 0, file_gid = 0, file_mode = 0; - snprintf(fn, PATH_MAX, "system/%s%s%s", subdir, sep, e->d_name); - fs_config(fn, 0, &file_uid, &file_gid, &file_mode); - - // If this is the first file, its mode gets to become the default. - if (is_first && ( - dir_mode != default_dir_mode || - file_mode != default_file_mode || - dir_uid != default_uid || file_uid != default_uid || - dir_gid != default_gid || file_gid != default_gid)) { - default_uid = dir_uid; - default_gid = dir_gid; - default_dir_mode = dir_mode; - default_file_mode = file_mode; - printf("set_perm_recursive %d %d 0%o 0%o SYSTEM:%s\n", - default_uid, default_gid, - default_dir_mode, default_file_mode, - subdir); - } - - is_first = 0; - - // Otherwise, override this file if it doesn't match the defaults. - if (file_mode != default_file_mode || - file_uid != default_uid || file_gid != default_gid) { - printf("set_perm %d %d 0%o SYSTEM:%s%s%s\n", - file_uid, file_gid, file_mode, - subdir, sep, e->d_name); - } - - } - } - - // Set the directory's permissions directly, if they never got set. - if (dir_mode != default_dir_mode || - dir_uid != default_uid || dir_gid != default_gid) { - printf("set_perm %d %d 0%o SYSTEM:%s\n", - dir_uid, dir_gid, dir_mode, subdir); - } - - closedir(dir); -} - -/* - * Generate the update script (in "Amend", see commands/recovery/commands.c) - * for the complete-reinstall OTA update packages the build system makes. - * - * The generated script makes a variety of sanity checks about the device, - * erases and reinstalls system files, and sets file permissions appropriately. - */ -int main(int argc, char *argv[]) { - if (argc != 3) { - fprintf(stderr, "usage: %s systemdir android-info.txt >update-script\n", - argv[0]); - return 2; - } - - // ensure basic recovery script language compatibility - printf("assert compatible_with(\"0.2\") == \"true\"\n"); - - // if known, make sure the device name is correct - const char *device = getenv("TARGET_DEVICE"); - if (device != NULL) { - printf("assert getprop(\"ro.product.device\") == \"%s\" || " - "getprop(\"ro.build.product\") == \"%s\"\n", device, device); - } - - // scan android-info.txt to enforce compatibility with the target system - FILE *fp = fopen(argv[2], "r"); - if (fp == NULL) { - perror(argv[2]); - return 1; - } - - // The lines we're looking for look like: - // version-bootloader=x.yy.zzzz|x.yy.zzzz|... - // or: - // require version-bootloader=x.yy.zzzz|x.yy.zzzz|... - char line[256]; - while (fgets(line, sizeof(line), fp)) { - const char *name = strtok(line, "="), *value = strtok(NULL, "|\n"); - if (value != NULL && - (!strcmp(name, "version-bootloader") || - !strcmp(name, "require version-bootloader"))) { - printf("assert getprop(\"ro.bootloader\") == \"%s\"", value); - - while ((value = strtok(NULL, "|\n")) != NULL) { - printf(" || getprop(\"ro.bootloader\") == \"%s\"", value); - } - printf("\n"); - } - // We also used to check version-baseband, but we update radio.img - // ourselves, so there's no need. - } - - // erase the boot sector first, so if the update gets interrupted, - // the system will reboot into the recovery partition and start over. - printf("format BOOT:\n"); - - // write the radio image (actually just loads it into RAM for now) - printf("show_progress 0.1 0\n"); - printf("write_radio_image PACKAGE:radio.img\n"); - - // erase and reinstall the system image - printf("show_progress 0.5 0\n"); - printf("format SYSTEM:\n"); - printf("copy_dir PACKAGE:system SYSTEM:\n"); - - // walk the files in the system image, set their permissions, etc. - // use -1 for default values to force permissions to be set explicitly. - walk_files(argv[1], "", -1, -1, -1, -1); - - // as the last step, write the boot sector. - printf("show_progress 0.2 0\n"); - printf("write_raw_image PACKAGE:boot.img BOOT:\n"); - - // after the end of the script, the radio will be written to cache - // leave some space in the progress bar for this operation - printf("show_progress 0.2 10\n"); - return 0; -} @@ -27,6 +27,7 @@ #include "common.h" #include "minui/minui.h" +#include "recovery_ui.h" #define MAX_COLS 64 #define MAX_ROWS 32 @@ -307,20 +308,14 @@ static void *input_thread(void *cookie) } pthread_mutex_unlock(&key_queue_mutex); - // Alt+L or Home+End: toggle log display - int alt = key_pressed[KEY_LEFTALT] || key_pressed[KEY_RIGHTALT]; - if ((alt && ev.code == KEY_L && ev.value > 0) || - (key_pressed[KEY_HOME] && ev.code == KEY_END && ev.value > 0)) { + if (ev.value > 0 && device_toggle_display(key_pressed, ev.code)) { pthread_mutex_lock(&gUpdateMutex); show_text = !show_text; update_screen_locked(); pthread_mutex_unlock(&gUpdateMutex); } - // Green+Menu+Red: reboot immediately - if (ev.code == KEY_DREAM_RED && - key_pressed[KEY_DREAM_MENU] && - key_pressed[KEY_DREAM_GREEN]) { + if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) { reboot(RB_AUTOBOOT); } } diff --git a/updater/Android.mk b/updater/Android.mk index 897b9d74c..d4a4e332d 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -18,11 +18,47 @@ LOCAL_MODULE_TAGS := eng LOCAL_SRC_FILES := $(updater_src_files) -LOCAL_STATIC_LIBRARIES := libapplypatch libedify libmtdutils libminzip libz +LOCAL_STATIC_LIBRARIES := $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS) +LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz LOCAL_STATIC_LIBRARIES += libmincrypt libbz LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. +# Each library in TARGET_RECOVERY_UPDATER_LIBS should have a function +# named "Register_<libname>()". Here we emit a little C function that +# gets #included by updater.c. It calls all those registration +# functions. + +# Devices can also add libraries to TARGET_RECOVERY_UPDATER_EXTRA_LIBS. +# These libs are also linked in with updater, but we don't try to call +# any sort of registration function for these. Use this variable for +# any subsidiary static libraries required for your registered +# extension libs. + +inc := $(call intermediates-dir-for,PACKAGING,updater_extensions)/register.inc + +# During the first pass of reading the makefiles, we dump the list of +# extension libs to a temp file, then copy that to the ".list" file if +# it is different than the existing .list (if any). The register.inc +# file then uses the .list as a prerequisite, so it is only rebuilt +# (and updater.o recompiled) when the list of extension libs changes. + +junk := $(shell mkdir -p $(dir $(inc));\ + echo $(TARGET_RECOVERY_UPDATER_LIBS) > $(inc).temp;\ + diff -q $(inc).temp $(inc).list || cp -f $(inc).temp $(inc).list) + +$(inc) : libs := $(TARGET_RECOVERY_UPDATER_LIBS) +$(inc) : $(inc).list + $(hide) mkdir -p $(dir $@) + $(hide) echo "" > $@ + $(hide) $(foreach lib,$(libs),echo "extern void Register_$(lib)(void);" >> $@) + $(hide) echo "void RegisterDeviceExtensions() {" >> $@ + $(hide) $(foreach lib,$(libs),echo " Register_$(lib)();" >> $@) + $(hide) echo "}" >> $@ + +$(call intermediates-dir-for,EXECUTABLES,updater)/updater.o : $(inc) +LOCAL_C_INCLUDES += $(dir $(inc)) + LOCAL_MODULE := updater LOCAL_FORCE_STATIC_EXECUTABLE := true diff --git a/updater/updater.c b/updater/updater.c index 31d93ae96..1aa277c7f 100644 --- a/updater/updater.c +++ b/updater/updater.c @@ -23,6 +23,11 @@ #include "install.h" #include "minzip/Zip.h" +// Generated by the makefile, this function defines the +// RegisterDeviceExtensions() function, which calls all the +// registration functions for device-specific extensions. +#include "register.inc" + // Where in the package we expect to find the edify script to execute. // (Note it's "updateR-script", not the older "update-script".) #define SCRIPT_NAME "META-INF/com/google/android/updater-script" @@ -76,6 +81,7 @@ int main(int argc, char** argv) { RegisterBuiltins(); RegisterInstallFunctions(); + RegisterDeviceExtensions(); FinishRegistration(); // Parse the script. |