diff options
137 files changed, 0 insertions, 14711 deletions
diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 816d143..0000000 --- a/Android.mk +++ /dev/null @@ -1,60 +0,0 @@ -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 \ - ui.c \ - verifier.c - -LOCAL_SRC_FILES += test_roots.c - -LOCAL_MODULE := recovery - -LOCAL_FORCE_STATIC_EXECUTABLE := true - -# This binary is in the recovery ramdisk, which is otherwise a copy of root. -# It gets copied there in config/Makefile. LOCAL_MODULE_TAGS suppresses -# a (redundant) copy of the binary in /system/bin for user builds. -# TODO: Build the ramdisk image in a more principled way. - -LOCAL_MODULE_TAGS := eng - -LOCAL_STATIC_LIBRARIES := libminzip libunz libamend libmtdutils libmincrypt -LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libcutils -LOCAL_STATIC_LIBRARIES += libstdc++ libc - -# Specify a C-includable file containing the OTA public keys. -# This is built in config/Makefile. -# *** THIS IS A TOTAL HACK; EXECUTABLES MUST NOT CHANGE BETWEEN DIFFERENT -# PRODUCTS/BUILD TYPES. *** -# TODO: make recovery read the keys from an external file. -RECOVERY_INSTALL_OTA_KEYS_INC := \ - $(call intermediates-dir-for,PACKAGING,ota_keys_inc)/keys.inc -# Let install.c say #include "keys.inc" -LOCAL_C_INCLUDES += $(dir $(RECOVERY_INSTALL_OTA_KEYS_INC)) - -include $(BUILD_EXECUTABLE) - -# Depend on the generated keys.inc containing the OTA public keys. -$(intermediates)/install.o: $(RECOVERY_INSTALL_OTA_KEYS_INC) - -include $(commands_recovery_local_path)/minui/Android.mk - -endif # TARGET_ARCH == arm -endif # !TARGET_SIMULATOR - -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 -commands_recovery_local_path := diff --git a/amend/Android.mk b/amend/Android.mk deleted file mode 100644 index ae2d44a..0000000 --- a/amend/Android.mk +++ /dev/null @@ -1,53 +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 \ - permissions.c \ - execute.c - -amend_test_files := \ - test_symtab.c \ - test_commands.c \ - test_permissions.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 49cd64e..0000000 --- a/amend/amend.c +++ /dev/null @@ -1,32 +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" - -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 416f974..0000000 --- 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 f53efdc..0000000 --- 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 7834a2b..0000000 --- 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 75ff828..0000000 --- a/amend/commands.c +++ /dev/null @@ -1,273 +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[], - PermissionRequestList *permissions) -{ - if (entry != NULL && entry->argType == CMD_ARGS_WORDS && - (argc == 0 || (argc > 0 && argv != NULL))) - { - if (permissions == 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, permissions); -//xxx if permissions, make sure the entry has added at least one element. - } -bail: - return -1; -} - -static int -callBooleanCommandInternal(CommandEntry *entry, bool arg, - PermissionRequestList *permissions) -{ - 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, - permissions); -//xxx if permissions, make sure the entry has added at least one element. - } - return -1; -} - -int -callCommand(Command *cmd, int argc, const char *argv[]) -{ - return callCommandInternal((CommandEntry *)cmd, argc, argv, NULL); -} - -int -callBooleanCommand(Command *cmd, bool arg) -{ - return callBooleanCommandInternal((CommandEntry *)cmd, arg, NULL); -} - -int -getCommandPermissions(Command *cmd, int argc, const char *argv[], - PermissionRequestList *permissions) -{ - if (permissions != NULL) { - return callCommandInternal((CommandEntry *)cmd, argc, argv, - permissions); - } - return -1; -} - -int -getBooleanCommandPermissions(Command *cmd, bool arg, - PermissionRequestList *permissions) -{ - if (permissions != NULL) { - return callBooleanCommandInternal((CommandEntry *)cmd, arg, - permissions); - } - return -1; -} - -int -callFunctionInternal(CommandEntry *entry, int argc, const char *argv[], - char **result, size_t *resultLen, PermissionRequestList *permissions) -{ - if (entry != NULL && entry->argType == CMD_ARGS_WORDS && - (argc == 0 || (argc > 0 && argv != NULL))) - { - if ((permissions == NULL && result != NULL) || - (permissions != NULL && result == NULL)) - { - if (permissions == 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, permissions); -//xxx if permissions, make sure the entry has added at least one element. - } - } -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, NULL); -} - -int -getFunctionPermissions(Function *fn, int argc, const char *argv[], - PermissionRequestList *permissions) -{ - if (permissions != NULL) { - return callFunctionInternal((CommandEntry *)fn, argc, argv, - NULL, NULL, permissions); - } - return -1; -} diff --git a/amend/commands.h b/amend/commands.h deleted file mode 100644 index 38931c0..0000000 --- a/amend/commands.h +++ /dev/null @@ -1,96 +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_COMMANDS_H_ -#define AMEND_COMMANDS_H_ - -#include "permissions.h" - -/* Invoke or dry-run a command. If "permissions" is non-NULL, - * the hook should fill it out with the list of files and operations that - * it would need to complete its operation. If "permissions" is NULL, - * the hook should do the actual work specified by its arguments. - * - * When a command is called with non-NULL "permissions", some arguments - * may be NULL. A NULL argument indicates that the argument is actually - * the output of another function, so is not known at permissions time. - * The permissions of leaf-node functions (those that have only literal - * strings as arguments) will get appended to the permissions of the - * functions that call them. However, to be completely safe, functions - * that receive a NULL argument should request the broadest-possible - * permissions for the range of the input argument. - * - * 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[], - PermissionRequestList *permissions); - -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); - -int getCommandPermissions(Command *cmd, int argc, const char *argv[], - PermissionRequestList *permissions); -int getBooleanCommandPermissions(Command *cmd, bool arg, - PermissionRequestList *permissions); - -/* - * Function management - */ - -typedef int (*FunctionHook)(const char *name, void *cookie, - int argc, const char *argv[], - char **result, size_t *resultLen, - PermissionRequestList *permissions); - -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); - -int getFunctionPermissions(Function *fn, int argc, const char *argv[], - PermissionRequestList *permissions); - -#endif // AMEND_COMMANDS_H_ diff --git a/amend/execute.c b/amend/execute.c deleted file mode 100644 index 9162ad6..0000000 --- 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 3becb48..0000000 --- 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 fc716fd..0000000 --- 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 80896d1..0000000 --- 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 9bb0785..0000000 --- a/amend/main.c +++ /dev/null @@ -1,195 +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); - } - extern int test_permissions(void); - ret = test_permissions(); - if (ret != 0) { - fprintf(stderr, "test_permissions() 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 aeb8657..0000000 --- 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 b634016..0000000 --- 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/permissions.c b/amend/permissions.c deleted file mode 100644 index a642d0b..0000000 --- a/amend/permissions.c +++ /dev/null @@ -1,270 +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 "permissions.h" - -int -initPermissionRequestList(PermissionRequestList *list) -{ - if (list != NULL) { - list->requests = NULL; - list->numRequests = 0; - list->requestsAllocated = 0; - return 0; - } - return -1; -} - -int -addPermissionRequestToList(PermissionRequestList *list, - const char *path, bool recursive, unsigned int permissions) -{ - if (list == NULL || list->numRequests < 0 || - list->requestsAllocated < list->numRequests || path == NULL) - { - return -1; - } - - if (list->numRequests == list->requestsAllocated) { - int newSize; - PermissionRequest *newRequests; - - newSize = list->requestsAllocated * 2; - if (newSize < 16) { - newSize = 16; - } - newRequests = (PermissionRequest *)realloc(list->requests, - newSize * sizeof(PermissionRequest)); - if (newRequests == NULL) { - return -2; - } - list->requests = newRequests; - list->requestsAllocated = newSize; - } - - PermissionRequest *req; - req = &list->requests[list->numRequests++]; - req->path = strdup(path); - if (req->path == NULL) { - list->numRequests--; - return -3; - } - req->recursive = recursive; - req->requested = permissions; - req->allowed = 0; - - return 0; -} - -void -freePermissionRequestListElements(PermissionRequestList *list) -{ - if (list != NULL && list->numRequests >= 0 && - list->requestsAllocated >= list->numRequests) - { - int i; - for (i = 0; i < list->numRequests; i++) { - free((void *)list->requests[i].path); - } - free(list->requests); - initPermissionRequestList(list); - } -} - -/* - * Global permission table - */ - -static struct { - Permission *permissions; - int numPermissionEntries; - int allocatedPermissionEntries; - bool permissionStateInitialized; -} gPermissionState = { -#if 1 - NULL, 0, 0, false -#else - .permissions = NULL, - .numPermissionEntries = 0, - .allocatedPermissionEntries = 0, - .permissionStateInitialized = false -#endif -}; - -int -permissionInit() -{ - if (gPermissionState.permissionStateInitialized) { - return -1; - } - gPermissionState.permissions = NULL; - gPermissionState.numPermissionEntries = 0; - gPermissionState.allocatedPermissionEntries = 0; - gPermissionState.permissionStateInitialized = true; -//xxx maybe add an "namespace root gets no permissions" fallback by default - return 0; -} - -void -permissionCleanup() -{ - if (gPermissionState.permissionStateInitialized) { - gPermissionState.permissionStateInitialized = false; - if (gPermissionState.permissions != NULL) { - int i; - for (i = 0; i < gPermissionState.numPermissionEntries; i++) { - free((void *)gPermissionState.permissions[i].path); - } - free(gPermissionState.permissions); - } - } -} - -int -getPermissionCount() -{ - if (gPermissionState.permissionStateInitialized) { - return gPermissionState.numPermissionEntries; - } - return -1; -} - -const Permission * -getPermissionAt(int index) -{ - if (!gPermissionState.permissionStateInitialized) { - return NULL; - } - if (index < 0 || index >= gPermissionState.numPermissionEntries) { - return NULL; - } - return &gPermissionState.permissions[index]; -} - -int -getAllowedPermissions(const char *path, bool recursive, - unsigned int *outAllowed) -{ - if (!gPermissionState.permissionStateInitialized) { - return -2; - } - if (outAllowed == NULL) { - return -1; - } - *outAllowed = 0; - if (path == NULL) { - return -1; - } - //TODO: implement this for real. - recursive = false; - *outAllowed = PERMSET_ALL; - return 0; -} - -int -countPermissionConflicts(PermissionRequestList *requests, bool updateAllowed) -{ - if (!gPermissionState.permissionStateInitialized) { - return -2; - } - if (requests == NULL || requests->requests == NULL || - requests->numRequests < 0 || - requests->requestsAllocated < requests->numRequests) - { - return -1; - } - int conflicts = 0; - int i; - for (i = 0; i < requests->numRequests; i++) { - PermissionRequest *req; - unsigned int allowed; - int ret; - - req = &requests->requests[i]; - ret = getAllowedPermissions(req->path, req->recursive, &allowed); - if (ret < 0) { - return ret; - } - if ((req->requested & ~allowed) != 0) { - conflicts++; - } - if (updateAllowed) { - req->allowed = allowed; - } - } - return conflicts; -} - -int -registerPermissionSet(int count, Permission *set) -{ - if (!gPermissionState.permissionStateInitialized) { - return -2; - } - if (count < 0 || (count > 0 && set == NULL)) { - return -1; - } - if (count == 0) { - return 0; - } - - if (gPermissionState.numPermissionEntries + count >= - gPermissionState.allocatedPermissionEntries) - { - Permission *newList; - int newSize; - - newSize = (gPermissionState.allocatedPermissionEntries + count) * 2; - if (newSize < 16) { - newSize = 16; - } - newList = (Permission *)realloc(gPermissionState.permissions, - newSize * sizeof(Permission)); - if (newList == NULL) { - return -3; - } - gPermissionState.permissions = newList; - gPermissionState.allocatedPermissionEntries = newSize; - } - - Permission *p = &gPermissionState.permissions[ - gPermissionState.numPermissionEntries]; - int i; - for (i = 0; i < count; i++) { - *p = set[i]; - //TODO: cache the strlen of the path - //TODO: normalize; strip off trailing / - p->path = strdup(p->path); - if (p->path == NULL) { - /* If we can't add all of the entries, we don't - * add any of them. - */ - Permission *pp = &gPermissionState.permissions[ - gPermissionState.numPermissionEntries]; - while (pp != p) { - free((void *)pp->path); - pp++; - } - return -4; - } - p++; - } - gPermissionState.numPermissionEntries += count; - - return 0; -} diff --git a/amend/permissions.h b/amend/permissions.h deleted file mode 100644 index 5b1d14d..0000000 --- a/amend/permissions.h +++ /dev/null @@ -1,111 +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_PERMISSIONS_H_ -#define AMEND_PERMISSIONS_H_ - -#include <stdbool.h> - -#define PERM_NONE (0) -#define PERM_STAT (1<<0) -#define PERM_READ (1<<1) -#define PERM_WRITE (1<<2) // including create, delete, mkdir, rmdir -#define PERM_CHMOD (1<<3) -#define PERM_CHOWN (1<<4) -#define PERM_CHGRP (1<<5) -#define PERM_SETUID (1<<6) -#define PERM_SETGID (1<<7) - -#define PERMSET_READ (PERM_STAT | PERM_READ) -#define PERMSET_WRITE (PERMSET_READ | PERM_WRITE) - -#define PERMSET_ALL \ - (PERM_STAT | PERM_READ | PERM_WRITE | PERM_CHMOD | \ - PERM_CHOWN | PERM_CHGRP | PERM_SETUID | PERM_SETGID) - -typedef struct { - unsigned int requested; - unsigned int allowed; - const char *path; - bool recursive; -} PermissionRequest; - -typedef struct { - PermissionRequest *requests; - int numRequests; - int requestsAllocated; -} PermissionRequestList; - -/* Properly clear out a PermissionRequestList. - * - * @return 0 if list is non-NULL, negative otherwise. - */ -int initPermissionRequestList(PermissionRequestList *list); - -/* Add a permission request to the list, allocating more space - * if necessary. - * - * @return 0 on success or a negative value on failure. - */ -int addPermissionRequestToList(PermissionRequestList *list, - const char *path, bool recursive, unsigned int permissions); - -/* Free anything allocated by addPermissionRequestToList(). The caller - * is responsible for freeing the actual PermissionRequestList. - */ -void freePermissionRequestListElements(PermissionRequestList *list); - - -/* - * Global permission table - */ - -typedef struct { - const char *path; - unsigned int allowed; -} Permission; - -int permissionInit(void); -void permissionCleanup(void); - -/* Returns the allowed permissions for the path in "outAllowed". - * Returns 0 if successful, negative if a parameter or global state - * is bad. - */ -int getAllowedPermissions(const char *path, bool recursive, - unsigned int *outAllowed); - -/* More-recently-registered permissions override older permissions. - */ -int registerPermissionSet(int count, Permission *set); - -/* Check to make sure that each request is allowed. - * - * @param requests The list of permission requests - * @param updateAllowed If true, update the "allowed" field in each - * element of the list - * @return the number of requests that were denied, or negative if - * an error occurred. - */ -int countPermissionConflicts(PermissionRequestList *requests, - bool updateAllowed); - -/* Inspection/testing/debugging functions - */ -int getPermissionCount(void); -const Permission *getPermissionAt(int index); - -#endif // AMEND_PERMISSIONS_H_ diff --git a/amend/register.c b/amend/register.c deleted file mode 100644 index 167dd32..0000000 --- a/amend/register.c +++ /dev/null @@ -1,394 +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; \ - if (permissions != NULL) { \ - int CW_I_; \ - for (CW_I_ = 0; CW_I_ < argc; CW_I_++) { \ - assert(argv[CW_I_] != NULL); \ - if (argv[CW_I_] == NULL) return -1; \ - } \ - } \ - } while (false) - -#define CHECK_FN() \ - do { \ - CHECK_WORDS(); \ - if (permissions != NULL) { \ - assert(result == NULL); \ - if (result != NULL) return -1; \ - } else { \ - assert(result != NULL); \ - if (result == NULL) return -1; \ - } \ - } while (false) - -#define NO_PERMS(perms) \ - do { \ - PermissionRequestList *NP_PRL_ = (perms); \ - if (NP_PRL_ != NULL) { \ - int NP_RET_ = addPermissionRequestToList(NP_PRL_, \ - "", false, PERM_NONE); \ - if (NP_RET_ < 0) { \ - /* Returns from the calling function. \ - */ \ - return NP_RET_; \ - } \ - } \ - } while (false) - -/* - * Command definitions - */ - -/* assert <boolexpr> - */ -static int -cmd_assert(const char *name, void *cookie, int argc, const char *argv[], - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_BOOL(); - NO_PERMS(permissions); - - /* 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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; - -//xxx some way to fix permissions -//xxx could have "installperms" commands that build the fs_config list -//xxx along with a "commitperms", and any copy_dir etc. needs to see -// a commitperms before it will work - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - 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]; - } - - if (permissions != NULL) { - if (dir == NULL) { - /* The argument is the result of another function. - * Assume the worst case, where the function returns - * the root. - */ - dir = "/"; - } - ret = addPermissionRequestToList(permissions, dir, true, PERM_READ); - } else { -//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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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 1d9eacb..0000000 --- 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 835d2fc..0000000 --- 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 f83c65b..0000000 --- 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 be938ac..0000000 --- a/amend/test_commands.c +++ /dev/null @@ -1,538 +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; - PermissionRequestList *permissions; - int returnValue; - char *functionResult; -} gTestCommandState; - -static int -testCommand(const char *name, void *cookie, int argc, const char *argv[], - PermissionRequestList *permissions) -{ - gTestCommandState.called = true; - gTestCommandState.name = name; - gTestCommandState.cookie = cookie; - gTestCommandState.argc = argc; - gTestCommandState.argv = argv; - gTestCommandState.permissions = permissions; - return gTestCommandState.returnValue; -} - -static int -testFunction(const char *name, void *cookie, int argc, const char *argv[], - char **result, size_t *resultLen, PermissionRequestList *permissions) -{ - gTestCommandState.called = true; - gTestCommandState.name = name; - gTestCommandState.cookie = cookie; - gTestCommandState.argc = argc; - gTestCommandState.argv = argv; - gTestCommandState.permissions = permissions; - 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; - gTestCommandState.permissions = (PermissionRequestList *)1; - 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); - assert(gTestCommandState.permissions == NULL); - - /* 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; - gTestCommandState.permissions = (PermissionRequestList *)1; - 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); - assert(gTestCommandState.permissions == NULL); - - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 13; - gTestCommandState.permissions = (PermissionRequestList *)1; - 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); - assert(gTestCommandState.permissions == NULL); - - /* Try looking up permissions. - */ - PermissionRequestList permissions; - cmd = findCommand("one"); - assert(cmd != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 27; - gTestCommandState.permissions = (PermissionRequestList *)1; - argv[1] = NULL; // null out an arg, which should be ok - ret = getCommandPermissions(cmd, argc, argv, &permissions); - assert(ret == 27); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - assert(gTestCommandState.permissions == &permissions); - - /* Boolean command permissions - */ - cmd = findCommand("bool"); - assert(cmd != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 55; - gTestCommandState.permissions = (PermissionRequestList *)1; - // argv[1] is still NULL - ret = getBooleanCommandPermissions(cmd, true, &permissions); - assert(ret == 55); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "bool") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == 1); - assert(gTestCommandState.argv == NULL); - assert(gTestCommandState.permissions == &permissions); - - - /* 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"; - gTestCommandState.permissions = (PermissionRequestList *)1; - 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(gTestCommandState.permissions == NULL); - assert(strcmp(functionResult, "1234") == 0); - assert(functionResultLen == strlen(functionResult)); - - /* Try looking up permissions. - */ - PermissionRequestList permissions; - fn = findFunction("one"); - assert(fn != NULL); - memset(&gTestCommandState, 0, sizeof(gTestCommandState)); - gTestCommandState.called = false; - gTestCommandState.returnValue = 27; - gTestCommandState.permissions = (PermissionRequestList *)1; - argv[1] = NULL; // null out an arg, which should be ok - ret = getFunctionPermissions(fn, argc, argv, &permissions); - assert(ret == 27); - assert(gTestCommandState.called); - assert(strcmp(gTestCommandState.name, "one") == 0); - assert(gTestCommandState.cookie == &gTestCommandState); - assert(gTestCommandState.argc == argc); - assert(gTestCommandState.argv == argv); - assert(gTestCommandState.permissions == &permissions); - - /* 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; - gTestCommandState.permissions = (PermissionRequestList *)1; - 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); - assert(gTestCommandState.permissions == NULL); - - /* 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"; - gTestCommandState.permissions = (PermissionRequestList *)2; - 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(gTestCommandState.permissions == NULL); - 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_permissions.c b/amend/test_permissions.c deleted file mode 100644 index c389456..0000000 --- a/amend/test_permissions.c +++ /dev/null @@ -1,347 +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 "permissions.h" - -static int -test_permission_list() -{ - PermissionRequestList list; - int ret; - int numRequests; - - /* Bad parameter - */ - ret = initPermissionRequestList(NULL); - assert(ret < 0); - - /* Good parameter - */ - ret = initPermissionRequestList(&list); - assert(ret == 0); - - /* Bad parameters - */ - ret = addPermissionRequestToList(NULL, NULL, false, 0); - assert(ret < 0); - - ret = addPermissionRequestToList(&list, NULL, false, 0); - assert(ret < 0); - - /* Good parameters - */ - numRequests = 0; - - ret = addPermissionRequestToList(&list, "one", false, 1); - assert(ret == 0); - numRequests++; - - ret = addPermissionRequestToList(&list, "two", false, 2); - assert(ret == 0); - numRequests++; - - ret = addPermissionRequestToList(&list, "three", false, 3); - assert(ret == 0); - numRequests++; - - ret = addPermissionRequestToList(&list, "recursive", true, 55); - assert(ret == 0); - numRequests++; - - /* Validate the list - */ - assert(list.requests != NULL); - assert(list.numRequests == numRequests); - assert(list.numRequests <= list.requestsAllocated); - bool sawOne = false; - bool sawTwo = false; - bool sawThree = false; - bool sawRecursive = false; - int i; - for (i = 0; i < list.numRequests; i++) { - PermissionRequest *req = &list.requests[i]; - assert(req->allowed == 0); - - /* Order isn't guaranteed, so we have to switch every time. - */ - if (strcmp(req->path, "one") == 0) { - assert(!sawOne); - assert(req->requested == 1); - assert(!req->recursive); - sawOne = true; - } else if (strcmp(req->path, "two") == 0) { - assert(!sawTwo); - assert(req->requested == 2); - assert(!req->recursive); - sawTwo = true; - } else if (strcmp(req->path, "three") == 0) { - assert(!sawThree); - assert(req->requested == 3); - assert(!req->recursive); - sawThree = true; - } else if (strcmp(req->path, "recursive") == 0) { - assert(!sawRecursive); - assert(req->requested == 55); - assert(req->recursive); - sawRecursive = true; - } else { - assert(false); - } - } - assert(sawOne); - assert(sawTwo); - assert(sawThree); - assert(sawRecursive); - - /* Smoke test the teardown - */ - freePermissionRequestListElements(&list); - - return 0; -} - -static int -test_permission_table() -{ - int ret; - - /* Test the global permissions table. - * Try calling functions without initializing first. - */ - ret = registerPermissionSet(0, NULL); - assert(ret < 0); - - ret = countPermissionConflicts((PermissionRequestList *)16, false); - assert(ret < 0); - - ret = getPermissionCount(); - assert(ret < 0); - - const Permission *p; - p = getPermissionAt(0); - assert(p == NULL); - - /* Initialize. - */ - ret = permissionInit(); - assert(ret == 0); - - /* Make sure we can't initialize twice. - */ - ret = permissionInit(); - assert(ret < 0); - - /* Test the inspection functions. - */ - ret = getPermissionCount(); - assert(ret == 0); - - p = getPermissionAt(-1); - assert(p == NULL); - - p = getPermissionAt(0); - assert(p == NULL); - - p = getPermissionAt(1); - assert(p == NULL); - - /* Test registerPermissionSet(). - * Try some bad parameter values. - */ - ret = registerPermissionSet(-1, NULL); - assert(ret < 0); - - ret = registerPermissionSet(1, NULL); - assert(ret < 0); - - /* Register some permissions. - */ - Permission p1; - p1.path = "one"; - p1.allowed = 1; - ret = registerPermissionSet(1, &p1); - assert(ret == 0); - ret = getPermissionCount(); - assert(ret == 1); - - Permission p2[2]; - p2[0].path = "two"; - p2[0].allowed = 2; - p2[1].path = "three"; - p2[1].allowed = 3; - ret = registerPermissionSet(2, p2); - assert(ret == 0); - ret = getPermissionCount(); - assert(ret == 3); - - ret = registerPermissionSet(0, NULL); - assert(ret == 0); - ret = getPermissionCount(); - assert(ret == 3); - - p1.path = "four"; - p1.allowed = 4; - ret = registerPermissionSet(1, &p1); - assert(ret == 0); - - /* Make sure the table looks correct. - * Order is important; more-recent additions - * should appear at higher indices. - */ - ret = getPermissionCount(); - assert(ret == 4); - - int i; - for (i = 0; i < ret; i++) { - const Permission *p; - p = getPermissionAt(i); - assert(p != NULL); - assert(p->allowed == (unsigned int)(i + 1)); - switch (i) { - case 0: - assert(strcmp(p->path, "one") == 0); - break; - case 1: - assert(strcmp(p->path, "two") == 0); - break; - case 2: - assert(strcmp(p->path, "three") == 0); - break; - case 3: - assert(strcmp(p->path, "four") == 0); - break; - default: - assert(!"internal error"); - break; - } - } - p = getPermissionAt(ret); - assert(p == NULL); - - /* Smoke test the teardown - */ - permissionCleanup(); - - return 0; -} - -static int -test_allowed_permissions() -{ - int ret; - int numPerms; - - /* Make sure these fail before initialization. - */ - ret = countPermissionConflicts((PermissionRequestList *)1, false); - assert(ret < 0); - - ret = getAllowedPermissions((const char *)1, false, (unsigned int *)1); - assert(ret < 0); - - /* Initialize. - */ - ret = permissionInit(); - assert(ret == 0); - - /* Make sure countPermissionConflicts() fails with bad parameters. - */ - ret = countPermissionConflicts(NULL, false); - assert(ret < 0); - - /* Register a set of permissions. - */ - Permission perms[] = { - { "/", PERM_NONE }, - { "/stat", PERM_STAT }, - { "/read", PERMSET_READ }, - { "/write", PERMSET_WRITE }, - { "/.stat", PERM_STAT }, - { "/.stat/.read", PERMSET_READ }, - { "/.stat/.read/.write", PERMSET_WRITE }, - { "/.stat/.write", PERMSET_WRITE }, - }; - numPerms = sizeof(perms) / sizeof(perms[0]); - ret = registerPermissionSet(numPerms, perms); - assert(ret == 0); - - /* Build a permission request list. - */ - PermissionRequestList list; - ret = initPermissionRequestList(&list); - assert(ret == 0); - - ret = addPermissionRequestToList(&list, "/stat", false, PERM_STAT); - assert(ret == 0); - - ret = addPermissionRequestToList(&list, "/read", false, PERM_READ); - assert(ret == 0); - - ret = addPermissionRequestToList(&list, "/write", false, PERM_WRITE); - assert(ret == 0); - - //TODO: cover more cases once the permission stuff has been implemented - - /* All of the requests in the list should be allowed. - */ - ret = countPermissionConflicts(&list, false); - assert(ret == 0); - - /* Add a request that will be denied. - */ - ret = addPermissionRequestToList(&list, "/stat", false, 1<<31 | PERM_STAT); - assert(ret == 0); - - ret = countPermissionConflicts(&list, false); - assert(ret == 1); - - //TODO: more tests - - permissionCleanup(); - - return 0; -} - -int -test_permissions() -{ - int ret; - - ret = test_permission_list(); - if (ret != 0) { - fprintf(stderr, "test_permission_list() failed: %d\n", ret); - return ret; - } - - ret = test_permission_table(); - if (ret != 0) { - fprintf(stderr, "test_permission_table() failed: %d\n", ret); - return ret; - } - - ret = test_allowed_permissions(); - if (ret != 0) { - fprintf(stderr, "test_permission_table() 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 017d18c..0000000 --- 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 d4a85ce..0000000 --- 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 9942f10..0000000 --- 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 51637c1..0000000 --- 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 e69de29..0000000 --- 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 822a54c..0000000 --- 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 090083f..0000000 --- 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 e69de29..0000000 --- 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 35c4a4f..0000000 --- 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 e40db0c..0000000 --- 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 9296648..0000000 --- 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 b9ef231..0000000 --- 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 eb5daf7..0000000 --- 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 f1c8738..0000000 --- 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 3ad5abd..0000000 --- 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 2e21fab..0000000 --- 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 a728a5e..0000000 --- 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 0691248..0000000 --- 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 6736c95..0000000 --- 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 35c4a4f..0000000 --- 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 9bb5ac4..0000000 --- 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 be458bd..0000000 --- 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 2b34bbc..0000000 --- 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 09e6689..0000000 --- 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 02f3f85..0000000 --- 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 7b1292a..0000000 --- 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 e69de29..0000000 --- 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 a78a0b1..0000000 --- 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 dd37016..0000000 --- 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 a4de638..0000000 --- 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 09e6689..0000000 --- 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 02f3f85..0000000 --- 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 35c4a4f..0000000 --- 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 012f62c..0000000 --- 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 5e321f5..0000000 --- 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 f3f1fd9..0000000 --- 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 35c4a4f..0000000 --- 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 dabf6d4..0000000 --- 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 5e321f5..0000000 --- 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 b073306..0000000 --- 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 9544e1b..0000000 --- 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 e69de29..0000000 --- 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 e69de29..0000000 --- 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 9cebd3f..0000000 --- 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 c696bbd..0000000 --- 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/bootloader.c b/bootloader.c deleted file mode 100644 index de441e1..0000000 --- a/bootloader.c +++ /dev/null @@ -1,267 +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 "bootloader.h" -#include "common.h" -#include "mtdutils/mtdutils.h" -#include "roots.h" - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -static const char *CACHE_NAME = "CACHE:"; -static const char *MISC_NAME = "MISC:"; -static const int MISC_PAGES = 3; // number of pages to save -static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page - -#ifdef LOG_VERBOSE -static void dump_data(const char *data, int len) { - int pos; - for (pos = 0; pos < len; ) { - printf("%05x: %02x", pos, data[pos]); - for (++pos; pos < len && (pos % 24) != 0; ++pos) { - printf(" %02x", data[pos]); - } - printf("\n"); - } -} -#endif - -int get_bootloader_message(struct bootloader_message *out) { - size_t write_size; - const MtdPartition *part = get_root_mtd_partition(MISC_NAME); - if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { - LOGE("Can't find %s\n", MISC_NAME); - return -1; - } - - MtdReadContext *read = mtd_read_partition(part); - if (read == NULL) { - LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); - return -1; - } - - const ssize_t size = write_size * MISC_PAGES; - char data[size]; - ssize_t r = mtd_read_data(read, data, size); - if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); - mtd_read_close(read); - if (r != size) return -1; - -#ifdef LOG_VERBOSE - printf("\n--- get_bootloader_message ---\n"); - dump_data(data, size); - printf("\n"); -#endif - - memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); - return 0; -} - -int set_bootloader_message(const struct bootloader_message *in) { - size_t write_size; - const MtdPartition *part = get_root_mtd_partition(MISC_NAME); - if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { - LOGE("Can't find %s\n", MISC_NAME); - return -1; - } - - MtdReadContext *read = mtd_read_partition(part); - if (read == NULL) { - LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); - return -1; - } - - ssize_t size = write_size * MISC_PAGES; - char data[size]; - ssize_t r = mtd_read_data(read, data, size); - if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); - mtd_read_close(read); - if (r != size) return -1; - - memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); - -#ifdef LOG_VERBOSE - printf("\n--- set_bootloader_message ---\n"); - dump_data(data, size); - printf("\n"); -#endif - - MtdWriteContext *write = mtd_write_partition(part); - if (write == NULL) { - LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); - return -1; - } - if (mtd_write_data(write, data, size) != size) { - LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - if (mtd_write_close(write)) { - LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); - return -1; - } - - LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); - return 0; -} - -/* Update Image - * - * - will be stored in the "cache" partition - * - bad blocks will be ignored, like boot.img and recovery.img - * - the first block will be the image header (described below) - * - the size is in BYTES, inclusive of the header - * - offsets are in BYTES from the start of the update header - * - two raw bitmaps will be included, the "busy" and "fail" bitmaps - * - for dream, the bitmaps will be 320x480x16bpp RGB565 - */ - -#define UPDATE_MAGIC "MSM-RADIO-UPDATE" -#define UPDATE_MAGIC_SIZE 16 -#define UPDATE_VERSION 0x00010000 - -struct update_header { - unsigned char MAGIC[UPDATE_MAGIC_SIZE]; - - unsigned version; - unsigned size; - - unsigned image_offset; - unsigned image_length; - - unsigned bitmap_width; - unsigned bitmap_height; - unsigned bitmap_bpp; - - unsigned busy_bitmap_offset; - unsigned busy_bitmap_length; - - unsigned fail_bitmap_offset; - unsigned fail_bitmap_length; -}; - -int write_update_for_bootloader( - const char *update, int update_length, - int bitmap_width, int bitmap_height, int bitmap_bpp, - const char *busy_bitmap, const char *fail_bitmap) { - if (ensure_root_path_unmounted(CACHE_NAME)) { - LOGE("Can't unmount %s\n", CACHE_NAME); - return -1; - } - - const MtdPartition *part = get_root_mtd_partition(CACHE_NAME); - if (part == NULL) { - LOGE("Can't find %s\n", CACHE_NAME); - return -1; - } - - MtdWriteContext *write = mtd_write_partition(part); - if (write == NULL) { - LOGE("Can't open %s\n(%s)\n", CACHE_NAME, strerror(errno)); - return -1; - } - - /* Write an invalid (zero) header first, to disable any previous - * update and any other structured contents (like a filesystem), - * and as a placeholder for the amount of space required. - */ - - struct update_header header; - memset(&header, 0, sizeof(header)); - const ssize_t header_size = sizeof(header); - if (mtd_write_data(write, (char*) &header, header_size) != header_size) { - LOGE("Can't write header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - /* Write each section individually block-aligned, so we can write - * each block independently without complicated buffering. - */ - - memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE); - header.version = UPDATE_VERSION; - header.size = header_size; - - header.image_offset = mtd_erase_blocks(write, 0); - header.image_length = update_length; - if ((int) header.image_offset == -1 || - mtd_write_data(write, update, update_length) != update_length) { - LOGE("Can't write update to %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - header.bitmap_width = bitmap_width; - header.bitmap_height = bitmap_height; - header.bitmap_bpp = bitmap_bpp; - - int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height; - - header.busy_bitmap_offset = mtd_erase_blocks(write, 0); - header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0; - if ((int) header.busy_bitmap_offset == -1 || - mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) { - LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - header.fail_bitmap_offset = mtd_erase_blocks(write, 0); - header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0; - if ((int) header.fail_bitmap_offset == -1 || - mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) { - LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - /* Write the header last, after all the blocks it refers to, so that - * when the magic number is installed everything is valid. - */ - - if (mtd_write_close(write)) { - LOGE("Can't finish writing %s\n(%s)\n", CACHE_NAME, strerror(errno)); - return -1; - } - - write = mtd_write_partition(part); - if (write == NULL) { - LOGE("Can't reopen %s\n(%s)\n", CACHE_NAME, strerror(errno)); - return -1; - } - - if (mtd_write_data(write, (char*) &header, header_size) != header_size) { - LOGE("Can't rewrite header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - if (mtd_erase_blocks(write, 0) != (off_t) header.image_offset) { - LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno)); - mtd_write_close(write); - return -1; - } - - if (mtd_write_close(write)) { - LOGE("Can't finish header of %s\n(%s)\n", CACHE_NAME, strerror(errno)); - return -1; - } - - return 0; -} diff --git a/bootloader.h b/bootloader.h deleted file mode 100644 index 3d4302f..0000000 --- a/bootloader.h +++ /dev/null @@ -1,59 +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. - */ - -#ifndef _RECOVERY_BOOTLOADER_H -#define _RECOVERY_BOOTLOADER_H - -/* Bootloader Message - * - * This structure describes the content of a block in flash - * that is used for recovery and the bootloader to talk to - * each other. - * - * The command field is updated by linux when it wants to - * reboot into recovery or to update radio or bootloader firmware. - * It is also updated by the bootloader when firmware update - * is complete (to boot into recovery for any final cleanup) - * - * The status field is written by the bootloader after the - * completion of an "update-radio" or "update-hboot" command. - * - * The recovery field is only written by linux and used - * for the system to send a message to recovery or the - * other way around. - */ -struct bootloader_message { - char command[32]; - char status[32]; - char recovery[1024]; -}; - -/* Read and write the bootloader command from the "misc" partition. - * These return zero on success. - */ -int get_bootloader_message(struct bootloader_message *out); -int set_bootloader_message(const struct bootloader_message *in); - -/* Write an update to the cache partition for update-radio or update-hboot. - * Note, this destroys any filesystem on the cache partition! - * The expected bitmap format is 240x320, 16bpp (2Bpp), RGB 5:6:5. - */ -int write_update_for_bootloader( - const char *update, int update_len, - int bitmap_width, int bitmap_height, int bitmap_bpp, - const char *busy_bitmap, const char *error_bitmap); - -#endif diff --git a/commands.c b/commands.c deleted file mode 100644 index 23ad91c..0000000 --- a/commands.c +++ /dev/null @@ -1,1148 +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; \ - if (permissions != NULL) { \ - int CW_I_; \ - for (CW_I_ = 0; CW_I_ < argc; CW_I_++) { \ - assert(argv[CW_I_] != NULL); \ - if (argv[CW_I_] == NULL) return -1; \ - } \ - } \ - } while (false) - -#define CHECK_FN() \ - do { \ - CHECK_WORDS(); \ - if (permissions != NULL) { \ - assert(result == NULL); \ - if (result != NULL) return -1; \ - } else { \ - assert(result != NULL); \ - if (result == NULL) return -1; \ - } \ - } while (false) - -#define NO_PERMS(perms) \ - do { \ - PermissionRequestList *NP_PRL_ = (perms); \ - if (NP_PRL_ != NULL) { \ - int NP_RET_ = addPermissionRequestToList(NP_PRL_, \ - "", false, PERM_NONE); \ - if (NP_RET_ < 0) { \ - /* Returns from the calling function. \ - */ \ - return NP_RET_; \ - } \ - } \ - } while (false) - -/* - * Command definitions - */ - -/* assert <boolexpr> - */ -static int -cmd_assert(const char *name, void *cookie, int argc, const char *argv[], - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_BOOL(); - NO_PERMS(permissions); - - /* 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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"); -//xxx permissions - - 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[], - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_WORDS(); -//xxx permissions - - // 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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[], PermissionRequestList *permissions) -{ - 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[], PermissionRequestList *permissions) -{ - UNUSED(cookie); - CHECK_WORDS(); -//xxx permissions - - 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[], - PermissionRequestList *permissions) -{ - 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[], - PermissionRequestList *permissions) -{ - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - 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]; - } - - if (permissions != NULL) { - if (dir == NULL) { - /* The argument is the result of another function. - * Assume the worst case, where the function returns - * the root. - */ - dir = "/"; - } - ret = addPermissionRequestToList(permissions, dir, true, PERM_READ); - } else { -//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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(name); - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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, - PermissionRequestList *permissions) -{ - UNUSED(cookie); - CHECK_FN(); - NO_PERMS(permissions); - - 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 e9acea2..0000000 --- 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/common.h b/common.h deleted file mode 100644 index e17f76a..0000000 --- a/common.h +++ /dev/null @@ -1,94 +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_COMMON_H -#define RECOVERY_COMMON_H - -#include <stdio.h> - -// Initialize the graphics system. -void ui_init(); - -// Use KEY_* codes from <linux/input.h> or KEY_DREAM_* from "minui/minui.h". -int ui_wait_key(); // waits for a key/button press, returns the code -int ui_key_pressed(int key); // returns >0 if the code is currently pressed -int ui_text_visible(); // returns >0 if text log is currently visible -void ui_clear_key_queue(); - -// Write a message to the on-screen log shown with Alt-L (also to stderr). -// The screen is small, and users may need to report these messages to support, -// so keep the output short and not too cryptic. -void ui_print(const char *fmt, ...); - -// Display some header text followed by a menu of items, which appears -// at the top of the screen (in place of any scrolling ui_print() -// output, if necessary). -void ui_start_menu(char** headers, char** items); -// Set the menu highlight to the given index, and return it (capped to -// the range [0..numitems). -int ui_menu_select(int sel); -// End menu mode, resetting the text overlay so that ui_print() -// statements will be displayed. -void ui_end_menu(); - -// Set the icon (normally the only thing visible besides the progress bar). -enum { - BACKGROUND_ICON_NONE, - BACKGROUND_ICON_UNPACKING, - BACKGROUND_ICON_INSTALLING, - BACKGROUND_ICON_ERROR, - BACKGROUND_ICON_FIRMWARE_INSTALLING, - BACKGROUND_ICON_FIRMWARE_ERROR, - NUM_BACKGROUND_ICONS -}; -void ui_set_background(int icon); - -// Get a malloc'd copy of the screen image showing (only) the specified icon. -// Also returns the width, height, and bits per pixel of the returned image. -// TODO: Use some sort of "struct Bitmap" here instead of all these variables? -char *ui_copy_image(int icon, int *width, int *height, int *bpp); - -// Show a progress bar and define the scope of the next operation: -// portion - fraction of the progress bar the next operation will use -// seconds - expected time interval (progress bar moves at this minimum rate) -void ui_show_progress(float portion, int seconds); -void ui_set_progress(float fraction); // 0.0 - 1.0 within the defined scope - -// Default allocation of progress bar segments to operations -static const int VERIFICATION_PROGRESS_TIME = 60; -static const float VERIFICATION_PROGRESS_FRACTION = 0.5; -static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4; -static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1; - -// Show a rotating "barberpole" for ongoing operations. Updates automatically. -void ui_show_indeterminate_progress(); - -// Hide and reset the progress bar. -void ui_reset_progress(); - -#define LOGE(...) ui_print("E:" __VA_ARGS__) -#define LOGW(...) fprintf(stderr, "W:" __VA_ARGS__) -#define LOGI(...) fprintf(stderr, "I:" __VA_ARGS__) - -#if 0 -#define LOGV(...) fprintf(stderr, "V:" __VA_ARGS__) -#define LOGD(...) fprintf(stderr, "D:" __VA_ARGS__) -#else -#define LOGV(...) do {} while (0) -#define LOGD(...) do {} while (0) -#endif - -#endif // RECOVERY_COMMON_H diff --git a/etc/META-INF/com/google/android/update-script b/etc/META-INF/com/google/android/update-script deleted file mode 100644 index b091b19..0000000 --- a/etc/META-INF/com/google/android/update-script +++ /dev/null @@ -1,8 +0,0 @@ -assert compatible_with("0.1") == "true" -assert file_contains("SYSTEM:build.prop", "ro.product.device=dream") == "true" || file_contains("SYSTEM:build.prop", "ro.build.product=dream") == "true" -assert file_contains("RECOVERY:default.prop", "ro.product.device=dream") == "true" || file_contains("RECOVERY:default.prop", "ro.build.product=dream") == "true" -assert getprop("ro.product.device") == "dream" -format BOOT: -format SYSTEM: -copy_dir PACKAGE:system SYSTEM: -write_raw_image PACKAGE:boot.img BOOT: diff --git a/etc/init.rc b/etc/init.rc deleted file mode 100644 index d9e86d7..0000000 --- a/etc/init.rc +++ /dev/null @@ -1,33 +0,0 @@ - -on init - export PATH /sbin - export ANDROID_ROOT /system - export ANDROID_DATA /data - export EXTERNAL_STORAGE /sdcard - - symlink /system/etc /etc - - mkdir /sdcard - mkdir /system - mkdir /data - mkdir /cache - mount /tmp /tmp tmpfs - -on boot - - ifup lo - hostname localhost - domainname localdomain - - class_start default - - -service recovery /sbin/recovery - -service adbd /sbin/adbd recovery - -on property:persist.service.adb.enable=1 - start adbd - -on property:persist.service.adb.enable=0 - stop adbd diff --git a/firmware.c b/firmware.c deleted file mode 100644 index 34b2918..0000000 --- a/firmware.c +++ /dev/null @@ -1,127 +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 "bootloader.h" -#include "common.h" -#include "firmware.h" -#include "roots.h" - -#include <errno.h> -#include <string.h> -#include <sys/reboot.h> - -static const char *update_type = NULL; -static const char *update_data = NULL; -static int update_length = 0; - -int remember_firmware_update(const char *type, const char *data, int length) { - if (update_type != NULL || update_data != NULL) { - LOGE("Multiple firmware images\n"); - return -1; - } - - update_type = type; - update_data = data; - update_length = length; - return 0; -} - - -/* Bootloader / Recovery Flow - * - * On every boot, the bootloader will read the bootloader_message - * from flash and check the command field. The bootloader should - * deal with the command field not having a 0 terminator correctly - * (so as to not crash if the block is invalid or corrupt). - * - * The bootloader will have to publish the partition that contains - * the bootloader_message to the linux kernel so it can update it. - * - * if command == "boot-recovery" -> boot recovery.img - * else if command == "update-radio" -> update radio image (below) - * else if command == "update-hboot" -> update hboot image (below) - * else -> boot boot.img (normal boot) - * - * Radio/Hboot Update Flow - * 1. the bootloader will attempt to load and validate the header - * 2. if the header is invalid, status="invalid-update", goto #8 - * 3. display the busy image on-screen - * 4. if the update image is invalid, status="invalid-radio-image", goto #8 - * 5. attempt to update the firmware (depending on the command) - * 6. if successful, status="okay", goto #8 - * 7. if failed, and the old image can still boot, status="failed-update" - * 8. write the bootloader_message, leaving the recovery field - * unchanged, updating status, and setting command to - * "boot-recovery" - * 9. reboot - * - * The bootloader will not modify or erase the cache partition. - * It is recovery's responsibility to clean up the mess afterwards. - */ - -int maybe_install_firmware_update(const char *send_intent) { - if (update_data == NULL || update_length == 0) return 0; - - /* We destroy the cache partition to pass the update image to the - * bootloader, so all we can really do afterwards is wipe cache and reboot. - * Set up this instruction now, in case we're interrupted while writing. - */ - - struct bootloader_message boot; - memset(&boot, 0, sizeof(boot)); - strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); - strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command)); - if (send_intent != NULL) { - strlcat(boot.recovery, "--send_intent=", sizeof(boot.recovery)); - strlcat(boot.recovery, send_intent, sizeof(boot.recovery)); - strlcat(boot.recovery, "\n", sizeof(boot.recovery)); - } - if (set_bootloader_message(&boot)) return -1; - - int width = 0, height = 0, bpp = 0; - char *busy_image = ui_copy_image( - BACKGROUND_ICON_FIRMWARE_INSTALLING, &width, &height, &bpp); - char *fail_image = ui_copy_image( - BACKGROUND_ICON_FIRMWARE_ERROR, &width, &height, &bpp); - - ui_print("Writing %s image...\n", update_type); - if (write_update_for_bootloader( - update_data, update_length, - width, height, bpp, busy_image, fail_image)) { - LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno)); - format_root_device("CACHE:"); // Attempt to clean cache up, at least. - return -1; - } - - free(busy_image); - free(fail_image); - - /* The update image is fully written, so now we can instruct the bootloader - * to install it. (After doing so, it will come back here, and we will - * wipe the cache and reboot into the system.) - */ - snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); - if (set_bootloader_message(&boot)) { - format_root_device("CACHE:"); - return -1; - } - - reboot(RB_AUTOBOOT); - - // Can't reboot? WTF? - LOGE("Can't reboot\n"); - return -1; -} diff --git a/firmware.h b/firmware.h deleted file mode 100644 index f3f7aab..0000000 --- a/firmware.h +++ /dev/null @@ -1,32 +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. - */ - -#ifndef _RECOVERY_FIRMWARE_H -#define _RECOVERY_FIRMWARE_H - -/* Save a radio or bootloader update image for later installation. - * The type should be one of "hboot" or "radio". - * Takes ownership of type and data. Returns nonzero on error. - */ -int remember_firmware_update(const char *type, const char *data, int length); - -/* If an update was saved, reboot into the bootloader now to install it. - * Returns 0 if no radio image was defined, nonzero on error, - * doesn't return at all on success... - */ -int maybe_install_firmware_update(const char *send_intent); - -#endif diff --git a/install.c b/install.c deleted file mode 100644 index 0691120..0000000 --- a/install.c +++ /dev/null @@ -1,186 +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 <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <sys/stat.h> - -#include "amend/amend.h" -#include "common.h" -#include "install.h" -#include "mincrypt/rsa.h" -#include "minui/minui.h" -#include "minzip/SysUtil.h" -#include "minzip/Zip.h" -#include "mtdutils/mounts.h" -#include "mtdutils/mtdutils.h" -#include "roots.h" -#include "verifier.h" - -/* List of public keys */ -static const RSAPublicKey keys[] = { -#include "keys.inc" -}; - -#define ASSUMED_UPDATE_SCRIPT_NAME "META-INF/com/google/android/update-script" - -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, *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; - } - - ui_print("Installation complete.\n"); - return INSTALL_SUCCESS; -} - -static int -handle_update_package(const char *path, ZipArchive *zip) -{ - // Give verification half the progress bar... - ui_print("Verifying update package...\n"); - ui_show_progress( - VERIFICATION_PROGRESS_FRACTION, - VERIFICATION_PROGRESS_TIME); - - if (!verify_jar_signature(zip, keys, sizeof(keys) / sizeof(keys[0]))) { - LOGE("Verification failed\n"); - return INSTALL_CORRUPT; - } - - // Update should take the rest of the progress bar. - ui_print("Installing update...\n"); - - 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; -} - -int -install_package(const char *root_path) -{ - ui_set_background(BACKGROUND_ICON_INSTALLING); - ui_print("Finding update package...\n"); - ui_show_indeterminate_progress(); - LOGI("Update location: %s\n", root_path); - - if (ensure_root_path_mounted(root_path) != 0) { - LOGE("Can't mount %s\n", root_path); - return INSTALL_CORRUPT; - } - - char path[PATH_MAX] = ""; - if (translate_root_path(root_path, path, sizeof(path)) == NULL) { - LOGE("Bad path %s\n", root_path); - return INSTALL_CORRUPT; - } - - ui_print("Opening update package...\n"); - LOGI("Update file path: %s\n", path); - - /* Try to open the package. - */ - ZipArchive zip; - int err = mzOpenZipArchive(path, &zip); - if (err != 0) { - LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); - return INSTALL_CORRUPT; - } - - /* Verify and install the contents of the package. - */ - int status = handle_update_package(path, &zip); - mzCloseZipArchive(&zip); - return status; -} diff --git a/install.h b/install.h deleted file mode 100644 index a7ebc09..0000000 --- a/install.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 RECOVERY_INSTALL_H_ -#define RECOVERY_INSTALL_H_ - -#include "common.h" - -enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT }; -int install_package(const char *root_path); - -#endif // RECOVERY_INSTALL_H_ diff --git a/minui/Android.mk b/minui/Android.mk deleted file mode 100644 index 91dd939..0000000 --- a/minui/Android.mk +++ /dev/null @@ -1,12 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := graphics.c events.c resources.c - -LOCAL_C_INCLUDES +=\ - external/libpng\ - external/zlib - -LOCAL_MODULE := libminui - -include $(BUILD_STATIC_LIBRARY) diff --git a/minui/events.c b/minui/events.c deleted file mode 100644 index 3aed2a8..0000000 --- a/minui/events.c +++ /dev/null @@ -1,82 +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 <fcntl.h> -#include <dirent.h> -#include <sys/poll.h> - -#include <linux/input.h> - -#include "minui.h" - -#define MAX_DEVICES 16 - -static struct pollfd ev_fds[MAX_DEVICES]; -static unsigned ev_count = 0; - -int ev_init(void) -{ - DIR *dir; - struct dirent *de; - int fd; - - dir = opendir("/dev/input"); - if(dir != 0) { - while((de = readdir(dir))) { -// fprintf(stderr,"/dev/input/%s\n", de->d_name); - if(strncmp(de->d_name,"event",5)) continue; - fd = openat(dirfd(dir), de->d_name, O_RDONLY); - if(fd < 0) continue; - - ev_fds[ev_count].fd = fd; - ev_fds[ev_count].events = POLLIN; - ev_count++; - if(ev_count == MAX_DEVICES) break; - } - } - - return 0; -} - -void ev_exit(void) -{ - while (ev_count > 0) { - close(ev_fds[--ev_count].fd); - } -} - -int ev_get(struct input_event *ev, unsigned dont_wait) -{ - int r; - unsigned n; - - do { - r = poll(ev_fds, ev_count, dont_wait ? 0 : -1); - - if(r > 0) { - for(n = 0; n < ev_count; n++) { - if(ev_fds[n].revents & POLLIN) { - r = read(ev_fds[n].fd, ev, sizeof(*ev)); - if(r == sizeof(*ev)) return 0; - } - } - } - } while(dont_wait == 0); - - return -1; -} diff --git a/minui/font_10x18.h b/minui/font_10x18.h deleted file mode 100644 index 7f96465..0000000 --- a/minui/font_10x18.h +++ /dev/null @@ -1,214 +0,0 @@ -struct { - unsigned width; - unsigned height; - unsigned cwidth; - unsigned cheight; - unsigned char rundata[]; -} font = { - .width = 960, - .height = 18, - .cwidth = 10, - .cheight = 18, - .rundata = { -0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x55,0x82,0x06,0x82,0x02,0x82,0x10,0x82, -0x11,0x83,0x08,0x82,0x0a,0x82,0x04,0x82,0x46,0x82,0x08,0x82,0x07,0x84,0x06, -0x84,0x0a,0x81,0x03,0x88,0x04,0x84,0x04,0x88,0x04,0x84,0x06,0x84,0x1e,0x81, -0x0e,0x81,0x0a,0x84,0x06,0x84,0x07,0x82,0x05,0x85,0x07,0x84,0x04,0x86,0x04, -0x88,0x02,0x88,0x04,0x84,0x04,0x82,0x04,0x82,0x02,0x88,0x05,0x86,0x01,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x04,0x84,0x04, -0x86,0x06,0x84,0x04,0x86,0x06,0x84,0x04,0x88,0x02,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02, -0x88,0x03,0x86,0x0e,0x86,0x06,0x82,0x11,0x82,0x10,0x82,0x18,0x82,0x0f,0x84, -0x0d,0x82,0x1c,0x82,0x09,0x84,0x7f,0x16,0x84,0x05,0x82,0x05,0x84,0x07,0x83, -0x02,0x82,0x19,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x01,0x82,0x03,0x86,0x04, -0x83,0x02,0x82,0x03,0x82,0x01,0x82,0x07,0x82,0x09,0x82,0x06,0x82,0x3e,0x82, -0x04,0x84,0x06,0x83,0x06,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x03, -0x82,0x09,0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82, -0x1c,0x82,0x0e,0x82,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x05,0x84,0x04, -0x82,0x02,0x82,0x05,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82, -0x09,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x04, -0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x02, -0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x03,0x82,0x08,0x82,0x0c, -0x82,0x05,0x84,0x11,0x82,0x0f,0x82,0x18,0x82,0x0e,0x82,0x02,0x82,0x0c,0x82, -0x1c,0x82,0x0b,0x82,0x7f,0x15,0x82,0x08,0x82,0x08,0x82,0x05,0x82,0x01,0x82, -0x01,0x82,0x19,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x01,0x82,0x02,0x82,0x01, -0x82,0x01,0x82,0x02,0x82,0x01,0x82,0x01,0x82,0x03,0x82,0x01,0x82,0x07,0x82, -0x08,0x82,0x08,0x82,0x3d,0x82,0x03,0x82,0x02,0x82,0x04,0x84,0x05,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x06,0x83,0x03,0x82,0x08,0x82,0x04,0x81,0x09,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x1a,0x82,0x10,0x82,0x06,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x83, -0x02,0x83,0x02,0x83,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x08,0x82,0x0c,0x82,0x04,0x82,0x02,0x82, -0x11,0x82,0x0e,0x82,0x18,0x82,0x0e,0x82,0x02,0x82,0x0c,0x82,0x0b,0x82,0x0b, -0x82,0x02,0x82,0x0b,0x82,0x4d,0x82,0x45,0x82,0x08,0x82,0x08,0x82,0x05,0x82, -0x02,0x83,0x1a,0x82,0x07,0x81,0x02,0x81,0x07,0x82,0x01,0x82,0x02,0x82,0x01, -0x82,0x05,0x82,0x01,0x84,0x04,0x82,0x01,0x82,0x07,0x82,0x08,0x82,0x08,0x82, -0x06,0x82,0x02,0x82,0x06,0x82,0x28,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x01, -0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x84,0x03,0x82,0x08,0x82, -0x0d,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x19,0x82,0x12,0x82,0x05, -0x82,0x04,0x82,0x02,0x82,0x02,0x84,0x03,0x82,0x02,0x82,0x03,0x82,0x03,0x82, -0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x04, -0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x83,0x02,0x83, -0x02,0x84,0x02,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x0b,0x82,0x05,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08, -0x82,0x04,0x82,0x09,0x82,0x0b,0x82,0x03,0x82,0x04,0x82,0x20,0x82,0x18,0x82, -0x0e,0x82,0x10,0x82,0x0b,0x82,0x0b,0x82,0x02,0x82,0x0b,0x82,0x4d,0x82,0x45, -0x82,0x08,0x82,0x08,0x82,0x26,0x82,0x10,0x88,0x01,0x82,0x01,0x82,0x06,0x83, -0x01,0x82,0x04,0x84,0x08,0x81,0x08,0x82,0x0a,0x82,0x05,0x82,0x02,0x82,0x06, -0x82,0x28,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x08,0x82,0x04,0x82, -0x01,0x82,0x03,0x82,0x08,0x82,0x0d,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x18,0x82,0x06,0x88,0x06,0x82,0x04,0x82,0x04,0x82,0x02,0x82,0x01,0x85, -0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82, -0x02,0x82,0x04,0x82,0x08,0x88,0x02,0x84,0x02,0x82,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x0b,0x82, -0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x04,0x84,0x06, -0x84,0x08,0x82,0x05,0x82,0x09,0x82,0x0b,0x82,0x2b,0x82,0x18,0x82,0x0e,0x82, -0x10,0x82,0x1c,0x82,0x0b,0x82,0x4d,0x82,0x45,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x11,0x82,0x01,0x82,0x03,0x82,0x01,0x82,0x09,0x82,0x06,0x82,0x12,0x82, -0x0a,0x82,0x06,0x84,0x07,0x82,0x27,0x82,0x04,0x82,0x04,0x82,0x05,0x82,0x0b, -0x82,0x07,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x01,0x83,0x04,0x82,0x01,0x83, -0x08,0x82,0x05,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x05,0x83,0x07,0x83,0x05, -0x82,0x16,0x82,0x08,0x82,0x03,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08, -0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82, -0x08,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82, -0x0a,0x82,0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01, -0x82,0x04,0x84,0x06,0x84,0x08,0x82,0x05,0x82,0x0a,0x82,0x0a,0x82,0x23,0x85, -0x03,0x82,0x01,0x83,0x06,0x85,0x05,0x83,0x01,0x82,0x04,0x84,0x04,0x86,0x05, -0x85,0x01,0x81,0x02,0x82,0x01,0x83,0x05,0x84,0x09,0x84,0x02,0x82,0x03,0x82, -0x06,0x82,0x05,0x81,0x01,0x82,0x01,0x82,0x03,0x82,0x01,0x83,0x06,0x84,0x04, -0x82,0x01,0x83,0x06,0x83,0x01,0x82,0x02,0x82,0x01,0x84,0x04,0x86,0x03,0x86, -0x04,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x87,0x05,0x82,0x08,0x82,0x08,0x82,0x26,0x82, -0x11,0x82,0x01,0x82,0x04,0x86,0x07,0x82,0x05,0x83,0x12,0x82,0x0a,0x82,0x04, -0x88,0x02,0x88,0x0c,0x88,0x10,0x82,0x04,0x82,0x04,0x82,0x05,0x82,0x0a,0x82, -0x06,0x83,0x04,0x82,0x03,0x82,0x03,0x83,0x02,0x82,0x03,0x83,0x02,0x82,0x07, -0x82,0x06,0x84,0x05,0x82,0x02,0x83,0x05,0x83,0x07,0x83,0x04,0x82,0x18,0x82, -0x06,0x82,0x04,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x86,0x04, -0x82,0x08,0x82,0x04,0x82,0x02,0x86,0x04,0x86,0x04,0x82,0x02,0x84,0x02,0x88, -0x05,0x82,0x0a,0x82,0x03,0x85,0x05,0x82,0x08,0x82,0x01,0x82,0x01,0x82,0x02, -0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x02,0x82,0x03,0x82,0x05,0x84,0x07,0x82,0x05,0x82,0x04,0x82,0x03, -0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01,0x82,0x05,0x82,0x08,0x82,0x08,0x82, -0x06,0x82,0x0a,0x82,0x0a,0x82,0x22,0x82,0x03,0x82,0x02,0x83,0x02,0x82,0x04, -0x82,0x03,0x82,0x03,0x82,0x02,0x83,0x03,0x82,0x02,0x82,0x05,0x82,0x06,0x82, -0x03,0x83,0x02,0x83,0x02,0x82,0x06,0x82,0x0b,0x82,0x02,0x82,0x02,0x82,0x07, -0x82,0x05,0x88,0x02,0x83,0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02,0x82, -0x04,0x82,0x02,0x83,0x03,0x83,0x02,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x06, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x04,0x82,0x08,0x82,0x02,0x84,0x09,0x82,0x09,0x84,0x23,0x82,0x11, -0x82,0x01,0x82,0x06,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x01,0x82,0x11,0x82, -0x0a,0x82,0x06,0x84,0x07,0x82,0x26,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x08, -0x83,0x09,0x82,0x03,0x82,0x03,0x82,0x09,0x82,0x02,0x82,0x04,0x82,0x05,0x82, -0x06,0x82,0x02,0x82,0x05,0x83,0x01,0x82,0x17,0x82,0x16,0x82,0x06,0x82,0x05, -0x82,0x01,0x82,0x01,0x82,0x02,0x88,0x02,0x82,0x03,0x82,0x03,0x82,0x08,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x01,0x82,0x01,0x82, -0x02,0x82,0x02,0x84,0x02,0x82,0x04,0x82,0x02,0x86,0x04,0x82,0x04,0x82,0x02, -0x86,0x09,0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x82, -0x01,0x82,0x04,0x84,0x07,0x82,0x07,0x82,0x07,0x82,0x0b,0x82,0x09,0x82,0x27, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x04,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02, -0x82,0x01,0x82,0x08,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x07, -0x82,0x0a,0x82,0x06,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x04,0x82, -0x04,0x84,0x04,0x82,0x04,0x82,0x07,0x82,0x06,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x0f,0x88,0x05,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x02,0x82,0x01,0x82, -0x0d,0x82,0x0a,0x82,0x05,0x82,0x02,0x82,0x06,0x82,0x26,0x82,0x05,0x82,0x04, -0x82,0x05,0x82,0x07,0x82,0x0c,0x82,0x02,0x88,0x08,0x82,0x02,0x82,0x04,0x82, -0x05,0x82,0x05,0x82,0x04,0x82,0x08,0x82,0x18,0x82,0x14,0x82,0x07,0x82,0x05, -0x82,0x01,0x84,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x01,0x82,0x01,0x82, -0x02,0x82,0x02,0x84,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x02,0x82,0x0a,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x82, -0x01,0x82,0x01,0x82,0x04,0x84,0x07,0x82,0x07,0x82,0x07,0x82,0x0b,0x82,0x09, -0x82,0x22,0x87,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x88, -0x04,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02, -0x84,0x09,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x08,0x86,0x05, -0x82,0x06,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01,0x82, -0x05,0x82,0x05,0x82,0x04,0x82,0x06,0x82,0x07,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x10,0x82,0x01,0x82,0x07,0x82,0x01,0x82,0x04,0x82,0x01,0x83,0x02,0x82, -0x03,0x83,0x0f,0x82,0x08,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x25,0x82,0x07, -0x82,0x02,0x82,0x06,0x82,0x06,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x09,0x82, -0x02,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x04,0x82,0x08,0x82,0x19,0x82,0x05, -0x88,0x05,0x82,0x08,0x82,0x05,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82,0x03,0x82,0x03,0x82,0x03,0x82, -0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02,0x82,0x04,0x82,0x02, -0x82,0x08,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x03,0x82,0x09,0x82,0x05,0x82, -0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x83,0x02,0x83,0x03,0x82,0x02,0x82,0x06, -0x82,0x06,0x82,0x08,0x82,0x0c,0x82,0x08,0x82,0x21,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x0a,0x82,0x06,0x82,0x03, -0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x85,0x08,0x82,0x05,0x82, -0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x0d,0x82,0x04,0x82,0x06,0x82,0x04,0x82, -0x04,0x84,0x04,0x82,0x01,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x05, -0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x38,0x82,0x01,0x82,0x04,0x82,0x01,0x82, -0x01,0x82,0x04,0x84,0x01,0x82,0x01,0x82,0x03,0x82,0x10,0x82,0x08,0x82,0x30, -0x83,0x06,0x82,0x07,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x08,0x82,0x04,0x82, -0x07,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x04, -0x82,0x03,0x81,0x04,0x82,0x1a,0x82,0x10,0x82,0x10,0x82,0x08,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08, -0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82,0x03,0x82, -0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02, -0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x02,0x84,0x02,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x05,0x83,0x02,0x83,0x03, -0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x09,0x82,0x0c,0x82,0x08,0x82,0x21,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x0a, -0x82,0x07,0x85,0x04,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x82,0x02,0x82, -0x07,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x0d,0x82,0x04,0x82, -0x06,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x82,0x01,0x82,0x04,0x84,0x04, -0x82,0x04,0x82,0x04,0x82,0x09,0x82,0x08,0x82,0x08,0x82,0x26,0x82,0x10,0x82, -0x01,0x82,0x05,0x86,0x04,0x82,0x01,0x82,0x01,0x82,0x01,0x83,0x01,0x84,0x10, -0x82,0x06,0x82,0x1d,0x83,0x11,0x83,0x05,0x82,0x09,0x84,0x07,0x82,0x05,0x82, -0x09,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x06,0x83,0x07,0x83,0x09,0x82, -0x0e,0x82,0x0a,0x82,0x06,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x03, -0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x09,0x82, -0x02,0x83,0x02,0x82,0x04,0x82,0x05,0x82,0x06,0x82,0x01,0x82,0x04,0x82,0x04, -0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x09,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x06, -0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x05,0x82,0x05,0x82,0x09,0x82,0x0d,0x82,0x07,0x82,0x21,0x82,0x04,0x82,0x02, -0x83,0x02,0x82,0x04,0x82,0x03,0x82,0x03,0x82,0x02,0x83,0x03,0x82,0x03,0x82, -0x04,0x82,0x06,0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x82,0x03, -0x82,0x06,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x03,0x82, -0x02,0x82,0x03,0x83,0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x07,0x82,0x04, -0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x02,0x83,0x05,0x82,0x05,0x88,0x03,0x82, -0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x0a,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x1c,0x82,0x06,0x82,0x02,0x83,0x03,0x84,0x02,0x82,0x10,0x82,0x04,0x82, -0x1e,0x83,0x11,0x83,0x05,0x82,0x0a,0x82,0x05,0x88,0x02,0x88,0x04,0x84,0x09, -0x82,0x05,0x84,0x06,0x84,0x05,0x82,0x09,0x84,0x06,0x84,0x07,0x83,0x07,0x83, -0x0a,0x81,0x0e,0x81,0x0b,0x82,0x07,0x85,0x03,0x82,0x04,0x82,0x02,0x86,0x06, -0x84,0x04,0x86,0x04,0x88,0x02,0x82,0x0a,0x84,0x01,0x81,0x02,0x82,0x04,0x82, -0x02,0x88,0x04,0x83,0x05,0x82,0x04,0x82,0x02,0x88,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x0a,0x85,0x03,0x82,0x04,0x82,0x04,0x84, -0x07,0x82,0x07,0x84,0x07,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x05,0x88,0x03,0x86,0x09,0x82,0x03,0x86,0x22,0x85,0x01,0x81,0x02,0x82, -0x01,0x83,0x06,0x85,0x05,0x83,0x01,0x82,0x04,0x85,0x05,0x82,0x07,0x86,0x03, -0x82,0x04,0x82,0x02,0x88,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x88,0x02,0x82, -0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x83,0x06, -0x83,0x01,0x82,0x03,0x82,0x08,0x86,0x06,0x84,0x05,0x83,0x01,0x82,0x05,0x82, -0x06,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x04,0x83,0x01,0x82,0x03,0x87,0x06, -0x84,0x05,0x82,0x05,0x84,0x7f,0x15,0x83,0x7f,0x14,0x83,0x7f,0x5e,0x82,0x7f, -0x05,0x89,0x47,0x82,0x04,0x82,0x17,0x82,0x03,0x82,0x34,0x82,0x0e,0x82,0x4e, -0x82,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0a,0x82,0x04,0x82,0x17,0x82,0x03,0x82, -0x34,0x82,0x0e,0x82,0x48,0x82,0x04,0x82,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0a, -0x82,0x04,0x82,0x17,0x82,0x03,0x82,0x34,0x82,0x0e,0x82,0x49,0x82,0x02,0x82, -0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0c,0x86,0x19,0x85,0x35,0x82,0x0e,0x82,0x4a, -0x84,0x3f, -0x00, - } -}; diff --git a/minui/graphics.c b/minui/graphics.c deleted file mode 100644 index 06c5fdf..0000000 --- a/minui/graphics.c +++ /dev/null @@ -1,312 +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 <unistd.h> - -#include <fcntl.h> -#include <stdio.h> - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> - -#include <linux/fb.h> -#include <linux/kd.h> - -#include <pixelflinger/pixelflinger.h> - -#include "font_10x18.h" -#include "minui.h" - -typedef struct { - GGLSurface texture; - unsigned cwidth; - unsigned cheight; - unsigned ascent; -} GRFont; - -static GRFont *gr_font = 0; -static GGLContext *gr_context = 0; -static GGLSurface gr_font_texture; -static GGLSurface gr_framebuffer[2]; -static GGLSurface gr_mem_surface; -static unsigned gr_active_fb = 0; - -static int gr_fb_fd = -1; -static int gr_vt_fd = -1; - -static struct fb_var_screeninfo vi; - -static int get_framebuffer(GGLSurface *fb) -{ - int fd; - struct fb_fix_screeninfo fi; - void *bits; - - fd = open("/dev/graphics/fb0", O_RDWR); - if (fd < 0) { - perror("cannot open fb0"); - return -1; - } - - if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { - perror("failed to get fb0 info"); - close(fd); - return -1; - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { - perror("failed to get fb0 info"); - close(fd); - return -1; - } - - bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (bits == MAP_FAILED) { - perror("failed to mmap framebuffer"); - close(fd); - return -1; - } - - fb->version = sizeof(*fb); - fb->width = vi.xres; - fb->height = vi.yres; - fb->stride = vi.xres; - fb->data = bits; - fb->format = GGL_PIXEL_FORMAT_RGB_565; - - fb++; - - fb->version = sizeof(*fb); - fb->width = vi.xres; - fb->height = vi.yres; - fb->stride = vi.xres; - fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2); - fb->format = GGL_PIXEL_FORMAT_RGB_565; - - return fd; -} - -static void get_memory_surface(GGLSurface* ms) { - ms->version = sizeof(*ms); - ms->width = vi.xres; - ms->height = vi.yres; - ms->stride = vi.xres; - ms->data = malloc(vi.xres * vi.yres * 2); - ms->format = GGL_PIXEL_FORMAT_RGB_565; -} - -static void set_active_framebuffer(unsigned n) -{ - if (n > 1) return; - vi.yres_virtual = vi.yres * 2; - vi.yoffset = n * vi.yres; - if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) { - perror("active fb swap failed"); - } -} - -void gr_flip(void) -{ - GGLContext *gl = gr_context; - - /* swap front and back buffers */ - gr_active_fb = (gr_active_fb + 1) & 1; - - /* copy data from the in-memory surface to the buffer we're about - * to make active. */ - memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data, - vi.xres * vi.yres * 2); - - /* inform the display driver */ - set_active_framebuffer(gr_active_fb); -} - -void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - GGLContext *gl = gr_context; - GGLint color[4]; - color[0] = ((r << 8) | r) + 1; - color[1] = ((g << 8) | g) + 1; - color[2] = ((b << 8) | b) + 1; - color[3] = ((a << 8) | a) + 1; - gl->color4xv(gl, color); -} - -int gr_measure(const char *s) -{ - return gr_font->cwidth * strlen(s); -} - -int gr_text(int x, int y, const char *s) -{ - GGLContext *gl = gr_context; - GRFont *font = gr_font; - unsigned off; - - y -= font->ascent; - - gl->bindTexture(gl, &font->texture); - gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); - gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->enable(gl, GGL_TEXTURE_2D); - - while((off = *s++)) { - off -= 32; - if (off < 96) { - gl->texCoord2i(gl, (off * font->cwidth) - x, 0 - y); - gl->recti(gl, x, y, x + font->cwidth, y + font->cheight); - } - x += font->cwidth; - } - - return x; -} - -void gr_fill(int x, int y, int w, int h) -{ - GGLContext *gl = gr_context; - gl->disable(gl, GGL_TEXTURE_2D); - gl->recti(gl, x, y, w, h); -} - -void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) { - if (gr_context == NULL) { - return; - } - GGLContext *gl = gr_context; - - gl->bindTexture(gl, (GGLSurface*) source); - gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); - gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->enable(gl, GGL_TEXTURE_2D); - gl->texCoord2i(gl, sx - dx, sy - dy); - gl->recti(gl, dx, dy, dx + w, dy + h); -} - -unsigned int gr_get_width(gr_surface surface) { - if (surface == NULL) { - return 0; - } - return ((GGLSurface*) surface)->width; -} - -unsigned int gr_get_height(gr_surface surface) { - if (surface == NULL) { - return 0; - } - return ((GGLSurface*) surface)->height; -} - -static void gr_init_font(void) -{ - GGLSurface *ftex; - unsigned char *bits, *rle; - unsigned char *in, data; - - gr_font = calloc(sizeof(*gr_font), 1); - ftex = &gr_font->texture; - - bits = malloc(font.width * font.height); - - ftex->version = sizeof(*ftex); - ftex->width = font.width; - ftex->height = font.height; - ftex->stride = font.width; - ftex->data = (void*) bits; - ftex->format = GGL_PIXEL_FORMAT_A_8; - - in = font.rundata; - while((data = *in++)) { - memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f); - bits += (data & 0x7f); - } - - gr_font->cwidth = font.cwidth; - gr_font->cheight = font.cheight; - gr_font->ascent = font.cheight - 2; -} - -int gr_init(void) -{ - gglInit(&gr_context); - GGLContext *gl = gr_context; - - gr_init_font(); - gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC); - if (gr_vt_fd < 0) { - // This is non-fatal; post-Cupcake kernels don't have tty0. - perror("can't open /dev/tty0"); - } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) { - // However, if we do open tty0, we expect the ioctl to work. - perror("failed KDSETMODE to KD_GRAPHICS on tty0"); - gr_exit(); - return -1; - } - - gr_fb_fd = get_framebuffer(gr_framebuffer); - if (gr_fb_fd < 0) { - gr_exit(); - return -1; - } - - get_memory_surface(&gr_mem_surface); - - fprintf(stderr, "framebuffer: fd %d (%d x %d)\n", - gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height); - - /* start with 0 as front (displayed) and 1 as back (drawing) */ - gr_active_fb = 0; - set_active_framebuffer(0); - gl->colorBuffer(gl, &gr_mem_surface); - - - gl->activeTexture(gl, 0); - gl->enable(gl, GGL_BLEND); - gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA); - - return 0; -} - -void gr_exit(void) -{ - close(gr_fb_fd); - gr_fb_fd = -1; - - free(gr_mem_surface.data); - - ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT); - close(gr_vt_fd); - gr_vt_fd = -1; -} - -int gr_fb_width(void) -{ - return gr_framebuffer[0].width; -} - -int gr_fb_height(void) -{ - return gr_framebuffer[0].height; -} - -gr_pixel *gr_fb_data(void) -{ - return (unsigned short *) gr_mem_surface.data; -} diff --git a/minui/minui.h b/minui/minui.h deleted file mode 100644 index 80b47a4..0000000 --- a/minui/minui.h +++ /dev/null @@ -1,70 +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 _MINUI_H_ -#define _MINUI_H_ - -typedef void* gr_surface; -typedef unsigned short gr_pixel; - -int gr_init(void); -void gr_exit(void); - -int gr_fb_width(void); -int gr_fb_height(void); -gr_pixel *gr_fb_data(void); -void gr_flip(void); - -void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); -void gr_fill(int x, int y, int w, int h); -int gr_text(int x, int y, const char *s); -int gr_measure(const char *s); - -void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy); -unsigned int gr_get_width(gr_surface surface); -unsigned int gr_get_height(gr_surface surface); - -// input event structure, include <linux/input.h> for the definition. -// 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); - -// Resources - -// Returns 0 if no error, else negative. -int res_create_surface(const char* name, gr_surface* pSurface); -void res_free_surface(gr_surface surface); - -#endif diff --git a/minui/mkfont.c b/minui/mkfont.c deleted file mode 100644 index 61a5ede..0000000 --- a/minui/mkfont.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv) -{ - unsigned n; - unsigned char *x; - unsigned m; - unsigned run_val; - unsigned run_count; - - n = gimp_image.width * gimp_image.height; - m = 0; - x = gimp_image.pixel_data; - - printf("struct {\n"); - printf(" unsigned width;\n"); - printf(" unsigned height;\n"); - printf(" unsigned cwidth;\n"); - printf(" unsigned cheight;\n"); - printf(" unsigned char rundata[];\n"); - printf("} font = {\n"); - printf(" .width = %d,\n .height = %d,\n .cwidth = %d,\n .cheight = %d,\n", gimp_image.width, gimp_image.height, - gimp_image.width / 96, gimp_image.height); - printf(" .rundata = {\n"); - - run_val = (*x ? 0 : 255); - run_count = 1; - n--; - x+=3; - - while(n-- > 0) { - unsigned val = (*x ? 0 : 255); - x+=3; - if((val == run_val) && (run_count < 127)) { - run_count++; - } else { -eject: - printf("0x%02x,",run_count | (run_val ? 0x80 : 0x00)); - run_val = val; - run_count = 1; - m += 5; - if(m >= 75) { - printf("\n"); - m = 0; - } - } - } - printf("0x%02x,",run_count | (run_val ? 0x80 : 0x00)); - printf("\n0x00,"); - printf("\n"); - printf(" }\n};\n"); - return 0; -} diff --git a/minui/resources.c b/minui/resources.c deleted file mode 100644 index 5beb6a6..0000000 --- a/minui/resources.c +++ /dev/null @@ -1,202 +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 <unistd.h> - -#include <fcntl.h> -#include <stdio.h> - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> - -#include <linux/fb.h> -#include <linux/kd.h> - -#include <pixelflinger/pixelflinger.h> - -#include "minui.h" - -// File signature for BMP files. -// The letters 'BM' as a little-endian unsigned short. - -#define BMP_SIGNATURE 0x4d42 - -typedef struct { - // constant, value should equal BMP_SIGNATURE - unsigned short bfType; - // size of the file in bytes. - unsigned long bfSize; - // must always be set to zero. - unsigned short bfReserved1; - // must always be set to zero. - unsigned short bfReserved2; - // offset from the beginning of the file to the bitmap data. - unsigned long bfOffBits; - - // The BITMAPINFOHEADER: - // size of the BITMAPINFOHEADER structure, in bytes. - unsigned long biSize; - // width of the image, in pixels. - unsigned long biWidth; - // height of the image, in pixels. - unsigned long biHeight; - // number of planes of the target device, must be set to 1. - unsigned short biPlanes; - // number of bits per pixel. - unsigned short biBitCount; - // type of compression, zero means no compression. - unsigned long biCompression; - // size of the image data, in bytes. If there is no compression, - // it is valid to set this member to zero. - unsigned long biSizeImage; - // horizontal pixels per meter on the designated targer device, - // usually set to zero. - unsigned long biXPelsPerMeter; - // vertical pixels per meter on the designated targer device, - // usually set to zero. - unsigned long biYPelsPerMeter; - // number of colors used in the bitmap, if set to zero the - // number of colors is calculated using the biBitCount member. - unsigned long biClrUsed; - // number of color that are 'important' for the bitmap, - // if set to zero, all colors are important. - unsigned long biClrImportant; -} __attribute__((packed)) BitMapFileHeader; - -int res_create_surface(const char* name, gr_surface* pSurface) { - char resPath[256]; - BitMapFileHeader header; - GGLSurface* surface = NULL; - int result = 0; - - snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.bmp", name); - resPath[sizeof(resPath)-1] = '\0'; - int fd = open(resPath, O_RDONLY); - if (fd == -1) { - result = -1; - goto exit; - } - size_t bytesRead = read(fd, &header, sizeof(header)); - if (bytesRead != sizeof(header)) { - result = -2; - goto exit; - } - if (header.bfType != BMP_SIGNATURE) { - result = -3; // Not a legal header - goto exit; - } - if (header.biPlanes != 1) { - result = -4; - goto exit; - } - if (!(header.biBitCount == 24 || header.biBitCount == 32)) { - result = -5; - goto exit; - } - if (header.biCompression != 0) { - result = -6; - goto exit; - } - size_t width = header.biWidth; - size_t height = header.biHeight; - size_t stride = 4 * width; - size_t pixelSize = stride * height; - - surface = malloc(sizeof(GGLSurface) + pixelSize); - if (surface == NULL) { - result = -7; - goto exit; - } - unsigned char* pData = (unsigned char*) (surface + 1); - surface->version = sizeof(GGLSurface); - surface->width = width; - surface->height = height; - surface->stride = width; /* Yes, pixels, not bytes */ - surface->data = pData; - surface->format = (header.biBitCount == 24) ? - GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888; - - // Source pixel bytes are stored B G R {A} - - lseek(fd, header.bfOffBits, SEEK_SET); - size_t y; - if (header.biBitCount == 24) { // RGB - size_t inputStride = (((3 * width + 3) >> 2) << 2); - for (y = 0; y < height; y++) { - unsigned char* pRow = pData + (height - (y + 1)) * stride; - bytesRead = read(fd, pRow, inputStride); - if (bytesRead != inputStride) { - result = -8; - goto exit; - } - int x; - for(x = width - 1; x >= 0; x--) { - int sx = x * 3; - int dx = x * 4; - unsigned char b = pRow[sx]; - unsigned char g = pRow[sx + 1]; - unsigned char r = pRow[sx + 2]; - unsigned char a = 0xff; - pRow[dx ] = r; // r - pRow[dx + 1] = g; // g - pRow[dx + 2] = b; // b; - pRow[dx + 3] = a; - } - } - } else { // RGBA - for (y = 0; y < height; y++) { - unsigned char* pRow = pData + (height - (y + 1)) * stride; - bytesRead = read(fd, pRow, stride); - if (bytesRead != stride) { - result = -9; - goto exit; - } - size_t x; - for(x = 0; x < width; x++) { - size_t xx = x * 4; - unsigned char b = pRow[xx]; - unsigned char g = pRow[xx + 1]; - unsigned char r = pRow[xx + 2]; - unsigned char a = pRow[xx + 3]; - pRow[xx ] = r; - pRow[xx + 1] = g; - pRow[xx + 2] = b; - pRow[xx + 3] = a; - } - } - } - *pSurface = (gr_surface) surface; - -exit: - if (fd >= 0) { - close(fd); - } - if (result < 0) { - if (surface) { - free(surface); - } - } - return result; -} - -void res_free_surface(gr_surface surface) { - GGLSurface* pSurface = (GGLSurface*) surface; - if (pSurface) { - free(pSurface); - } -} diff --git a/minzip/Android.mk b/minzip/Android.mk deleted file mode 100644 index b1ee674..0000000 --- a/minzip/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - Hash.c \ - SysUtil.c \ - DirUtil.c \ - Inlines.c \ - Zip.c - -LOCAL_C_INCLUDES += \ - external/zlib \ - external/safe-iop/include - -LOCAL_MODULE := libminzip - -LOCAL_CFLAGS += -Wall - -include $(BUILD_STATIC_LIBRARY) diff --git a/minzip/Bits.h b/minzip/Bits.h deleted file mode 100644 index f96e6c4..0000000 --- a/minzip/Bits.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Some handy functions for manipulating bits and bytes. - */ -#ifndef _MINZIP_BITS -#define _MINZIP_BITS - -#include "inline_magic.h" - -#include <stdlib.h> -#include <string.h> - -/* - * Get 1 byte. (Included to make the code more legible.) - */ -INLINE unsigned char get1(unsigned const char* pSrc) -{ - return *pSrc; -} - -/* - * Get 2 big-endian bytes. - */ -INLINE unsigned short get2BE(unsigned char const* pSrc) -{ - unsigned short result; - - result = *pSrc++ << 8; - result |= *pSrc++; - - return result; -} - -/* - * Get 4 big-endian bytes. - */ -INLINE unsigned int get4BE(unsigned char const* pSrc) -{ - unsigned int result; - - result = *pSrc++ << 24; - result |= *pSrc++ << 16; - result |= *pSrc++ << 8; - result |= *pSrc++; - - return result; -} - -/* - * Get 8 big-endian bytes. - */ -INLINE unsigned long long get8BE(unsigned char const* pSrc) -{ - unsigned long long result; - - result = (unsigned long long) *pSrc++ << 56; - result |= (unsigned long long) *pSrc++ << 48; - result |= (unsigned long long) *pSrc++ << 40; - result |= (unsigned long long) *pSrc++ << 32; - result |= (unsigned long long) *pSrc++ << 24; - result |= (unsigned long long) *pSrc++ << 16; - result |= (unsigned long long) *pSrc++ << 8; - result |= (unsigned long long) *pSrc++; - - return result; -} - -/* - * Get 2 little-endian bytes. - */ -INLINE unsigned short get2LE(unsigned char const* pSrc) -{ - unsigned short result; - - result = *pSrc++; - result |= *pSrc++ << 8; - - return result; -} - -/* - * Get 4 little-endian bytes. - */ -INLINE unsigned int get4LE(unsigned char const* pSrc) -{ - unsigned int result; - - result = *pSrc++; - result |= *pSrc++ << 8; - result |= *pSrc++ << 16; - result |= *pSrc++ << 24; - - return result; -} - -/* - * Get 8 little-endian bytes. - */ -INLINE unsigned long long get8LE(unsigned char const* pSrc) -{ - unsigned long long result; - - result = (unsigned long long) *pSrc++; - result |= (unsigned long long) *pSrc++ << 8; - result |= (unsigned long long) *pSrc++ << 16; - result |= (unsigned long long) *pSrc++ << 24; - result |= (unsigned long long) *pSrc++ << 32; - result |= (unsigned long long) *pSrc++ << 40; - result |= (unsigned long long) *pSrc++ << 48; - result |= (unsigned long long) *pSrc++ << 56; - - return result; -} - -/* - * Grab 1 byte and advance the data pointer. - */ -INLINE unsigned char read1(unsigned const char** ppSrc) -{ - return *(*ppSrc)++; -} - -/* - * Grab 2 big-endian bytes and advance the data pointer. - */ -INLINE unsigned short read2BE(unsigned char const** ppSrc) -{ - unsigned short result; - - result = *(*ppSrc)++ << 8; - result |= *(*ppSrc)++; - - return result; -} - -/* - * Grab 4 big-endian bytes and advance the data pointer. - */ -INLINE unsigned int read4BE(unsigned char const** ppSrc) -{ - unsigned int result; - - result = *(*ppSrc)++ << 24; - result |= *(*ppSrc)++ << 16; - result |= *(*ppSrc)++ << 8; - result |= *(*ppSrc)++; - - return result; -} - -/* - * Get 8 big-endian bytes. - */ -INLINE unsigned long long read8BE(unsigned char const** ppSrc) -{ - unsigned long long result; - - result = (unsigned long long) *(*ppSrc)++ << 56; - result |= (unsigned long long) *(*ppSrc)++ << 48; - result |= (unsigned long long) *(*ppSrc)++ << 40; - result |= (unsigned long long) *(*ppSrc)++ << 32; - result |= (unsigned long long) *(*ppSrc)++ << 24; - result |= (unsigned long long) *(*ppSrc)++ << 16; - result |= (unsigned long long) *(*ppSrc)++ << 8; - result |= (unsigned long long) *(*ppSrc)++; - - return result; -} - -/* - * Grab 2 little-endian bytes and advance the data pointer. - */ -INLINE unsigned short read2LE(unsigned char const** ppSrc) -{ - unsigned short result; - - result = *(*ppSrc)++; - result |= *(*ppSrc)++ << 8; - - return result; -} - -/* - * Grab 4 little-endian bytes and advance the data pointer. - */ -INLINE unsigned int read4LE(unsigned char const** ppSrc) -{ - unsigned int result; - - result = *(*ppSrc)++; - result |= *(*ppSrc)++ << 8; - result |= *(*ppSrc)++ << 16; - result |= *(*ppSrc)++ << 24; - - return result; -} - -/* - * Get 8 little-endian bytes. - */ -INLINE unsigned long long read8LE(unsigned char const** ppSrc) -{ - unsigned long long result; - - result = (unsigned long long) *(*ppSrc)++; - result |= (unsigned long long) *(*ppSrc)++ << 8; - result |= (unsigned long long) *(*ppSrc)++ << 16; - result |= (unsigned long long) *(*ppSrc)++ << 24; - result |= (unsigned long long) *(*ppSrc)++ << 32; - result |= (unsigned long long) *(*ppSrc)++ << 40; - result |= (unsigned long long) *(*ppSrc)++ << 48; - result |= (unsigned long long) *(*ppSrc)++ << 56; - - return result; -} - -/* - * Skip over a UTF-8 string. - */ -INLINE void skipUtf8String(unsigned char const** ppSrc) -{ - unsigned int length = read4BE(ppSrc); - - (*ppSrc) += length; -} - -/* - * Read a UTF-8 string into a fixed-size buffer, and null-terminate it. - * - * Returns the length of the original string. - */ -INLINE int readUtf8String(unsigned char const** ppSrc, char* buf, size_t bufLen) -{ - unsigned int length = read4BE(ppSrc); - size_t copyLen = (length < bufLen) ? length : bufLen-1; - - memcpy(buf, *ppSrc, copyLen); - buf[copyLen] = '\0'; - - (*ppSrc) += length; - return length; -} - -/* - * Read a UTF-8 string into newly-allocated storage, and null-terminate it. - * - * Returns the string and its length. (The latter is probably unnecessary - * for the way we're using UTF8.) - */ -INLINE char* readNewUtf8String(unsigned char const** ppSrc, size_t* pLength) -{ - unsigned int length = read4BE(ppSrc); - char* buf; - - buf = (char*) malloc(length+1); - - memcpy(buf, *ppSrc, length); - buf[length] = '\0'; - - (*ppSrc) += length; - - *pLength = length; - return buf; -} - - -/* - * Set 1 byte. (Included to make the code more legible.) - */ -INLINE void set1(unsigned char* buf, unsigned char val) -{ - *buf = (unsigned char)(val); -} - -/* - * Set 2 big-endian bytes. - */ -INLINE void set2BE(unsigned char* buf, unsigned short val) -{ - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 4 big-endian bytes. - */ -INLINE void set4BE(unsigned char* buf, unsigned int val) -{ - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 8 big-endian bytes. - */ -INLINE void set8BE(unsigned char* buf, unsigned long long val) -{ - *buf++ = (unsigned char)(val >> 56); - *buf++ = (unsigned char)(val >> 48); - *buf++ = (unsigned char)(val >> 40); - *buf++ = (unsigned char)(val >> 32); - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 2 little-endian bytes. - */ -INLINE void set2LE(unsigned char* buf, unsigned short val) -{ - *buf++ = (unsigned char)(val); - *buf = (unsigned char)(val >> 8); -} - -/* - * Set 4 little-endian bytes. - */ -INLINE void set4LE(unsigned char* buf, unsigned int val) -{ - *buf++ = (unsigned char)(val); - *buf++ = (unsigned char)(val >> 8); - *buf++ = (unsigned char)(val >> 16); - *buf = (unsigned char)(val >> 24); -} - -/* - * Set 8 little-endian bytes. - */ -INLINE void set8LE(unsigned char* buf, unsigned long long val) -{ - *buf++ = (unsigned char)(val); - *buf++ = (unsigned char)(val >> 8); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 32); - *buf++ = (unsigned char)(val >> 40); - *buf++ = (unsigned char)(val >> 48); - *buf = (unsigned char)(val >> 56); -} - -/* - * Stuff a UTF-8 string into the buffer. - */ -INLINE void setUtf8String(unsigned char* buf, const unsigned char* str) -{ - unsigned int strLen = strlen((const char*)str); - - set4BE(buf, strLen); - memcpy(buf + sizeof(unsigned int), str, strLen); -} - -#endif /*_MINZIP_BITS*/ diff --git a/minzip/DirUtil.c b/minzip/DirUtil.c deleted file mode 100644 index 20c89cd..0000000 --- a/minzip/DirUtil.c +++ /dev/null @@ -1,280 +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 <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <dirent.h> -#include <limits.h> - -#include "DirUtil.h" - -typedef enum { DMISSING, DDIR, DILLEGAL } DirStatus; - -static DirStatus -getPathDirStatus(const char *path) -{ - struct stat st; - int err; - - err = stat(path, &st); - if (err == 0) { - /* Something's there; make sure it's a directory. - */ - if (S_ISDIR(st.st_mode)) { - return DDIR; - } - errno = ENOTDIR; - return DILLEGAL; - } else if (errno != ENOENT) { - /* Something went wrong, or something in the path - * is bad. Can't do anything in this situation. - */ - return DILLEGAL; - } - return DMISSING; -} - -int -dirCreateHierarchy(const char *path, int mode, - const struct utimbuf *timestamp, bool stripFileName) -{ - DirStatus ds; - - /* Check for an empty string before we bother - * making any syscalls. - */ - if (path[0] == '\0') { - errno = ENOENT; - return -1; - } - - /* Allocate a path that we can modify; stick a slash on - * the end to make things easier. - */ - size_t pathLen = strlen(path); - char *cpath = (char *)malloc(pathLen + 2); - if (cpath == NULL) { - errno = ENOMEM; - return -1; - } - memcpy(cpath, path, pathLen); - if (stripFileName) { - /* Strip everything after the last slash. - */ - char *c = cpath + pathLen - 1; - while (c != cpath && *c != '/') { - c--; - } - if (c == cpath) { -//xxx test this path - /* No directory component. Act like the path was empty. - */ - errno = ENOENT; - free(cpath); - return -1; - } - c[1] = '\0'; // Terminate after the slash we found. - } else { - /* Make sure that the path ends in a slash. - */ - cpath[pathLen] = '/'; - cpath[pathLen + 1] = '\0'; - } - - /* See if it already exists. - */ - ds = getPathDirStatus(cpath); - if (ds == DDIR) { - return 0; - } else if (ds == DILLEGAL) { - return -1; - } - - /* Walk up the path from the root and make each level. - * If a directory already exists, no big deal. - */ - char *p = cpath; - while (*p != '\0') { - /* Skip any slashes, watching out for the end of the string. - */ - while (*p != '\0' && *p == '/') { - p++; - } - if (*p == '\0') { - break; - } - - /* Find the end of the next path component. - * We know that we'll see a slash before the NUL, - * because we added it, above. - */ - while (*p != '/') { - p++; - } - *p = '\0'; - - /* Check this part of the path and make a new directory - * if necessary. - */ - ds = getPathDirStatus(cpath); - if (ds == DILLEGAL) { - /* Could happen if some other process/thread is - * messing with the filesystem. - */ - free(cpath); - return -1; - } else if (ds == DMISSING) { - int err; - - err = mkdir(cpath, mode); - if (err != 0) { - free(cpath); - return -1; - } - if (timestamp != NULL && utime(cpath, timestamp)) { - free(cpath); - return -1; - } - } - // else, this directory already exists. - - /* Repair the path and continue. - */ - *p = '/'; - } - free(cpath); - - return 0; -} - -int -dirUnlinkHierarchy(const char *path) -{ - struct stat st; - DIR *dir; - struct dirent *de; - int fail = 0; - - /* is it a file or directory? */ - if (lstat(path, &st) < 0) { - return -1; - } - - /* a file, so unlink it */ - if (!S_ISDIR(st.st_mode)) { - return unlink(path); - } - - /* a directory, so open handle */ - dir = opendir(path); - if (dir == NULL) { - return -1; - } - - /* recurse over components */ - errno = 0; - while ((de = readdir(dir)) != NULL) { -//TODO: don't blow the stack - char dn[PATH_MAX]; - if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) { - continue; - } - snprintf(dn, sizeof(dn), "%s/%s", path, de->d_name); - if (dirUnlinkHierarchy(dn) < 0) { - fail = 1; - break; - } - errno = 0; - } - /* in case readdir or unlink_recursive failed */ - if (fail || errno < 0) { - int save = errno; - closedir(dir); - errno = save; - return -1; - } - - /* close directory handle */ - if (closedir(dir) < 0) { - return -1; - } - - /* delete target directory */ - return rmdir(path); -} - -int -dirSetHierarchyPermissions(const char *path, - int uid, int gid, int dirMode, int fileMode) -{ - struct stat st; - if (lstat(path, &st)) { - return -1; - } - - /* ignore symlinks */ - if (S_ISLNK(st.st_mode)) { - return 0; - } - - /* directories and files get different permissions */ - if (chown(path, uid, gid) || - chmod(path, S_ISDIR(st.st_mode) ? dirMode : fileMode)) { - return -1; - } - - /* recurse over directory components */ - if (S_ISDIR(st.st_mode)) { - DIR *dir = opendir(path); - if (dir == NULL) { - return -1; - } - - errno = 0; - const struct dirent *de; - while (errno == 0 && (de = readdir(dir)) != NULL) { - if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) { - continue; - } - - char dn[PATH_MAX]; - snprintf(dn, sizeof(dn), "%s/%s", path, de->d_name); - if (!dirSetHierarchyPermissions(dn, uid, gid, dirMode, fileMode)) { - errno = 0; - } else if (errno == 0) { - errno = -1; - } - } - - if (errno != 0) { - int save = errno; - closedir(dir); - errno = save; - return -1; - } - - if (closedir(dir)) { - return -1; - } - } - - return 0; -} diff --git a/minzip/DirUtil.h b/minzip/DirUtil.h deleted file mode 100644 index 5d881f5..0000000 --- a/minzip/DirUtil.h +++ /dev/null @@ -1,51 +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 MINZIP_DIRUTIL_H_ -#define MINZIP_DIRUTIL_H_ - -#include <stdbool.h> -#include <utime.h> - -/* Like "mkdir -p", try to guarantee that all directories - * specified in path are present, creating as many directories - * as necessary. The specified mode is passed to all mkdir - * calls; no modifications are made to umask. - * - * If stripFileName is set, everything after the final '/' - * is stripped before creating the directory hierarchy. - * - * If timestamp is non-NULL, new directories will be timestamped accordingly. - * - * Returns 0 on success; returns -1 (and sets errno) on failure - * (usually if some element of path is not a directory). - */ -int dirCreateHierarchy(const char *path, int mode, - const struct utimbuf *timestamp, bool stripFileName); - -/* rm -rf <path> - */ -int dirUnlinkHierarchy(const char *path); - -/* chown -R <uid>:<gid> <path> - * chmod -R <mode> <path> - * - * Sets directories to <dirMode> and files to <fileMode>. Skips symlinks. - */ -int dirSetHierarchyPermissions(const char *path, - int uid, int gid, int dirMode, int fileMode); - -#endif // MINZIP_DIRUTIL_H_ diff --git a/minzip/Hash.c b/minzip/Hash.c deleted file mode 100644 index 8c6ca9b..0000000 --- a/minzip/Hash.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Hash table. The dominant calls are add and lookup, with removals - * happening very infrequently. We use probing, and don't worry much - * about tombstone removal. - */ -#include <stdlib.h> -#include <assert.h> - -#define LOG_TAG "minzip" -#include "Log.h" -#include "Hash.h" - -/* table load factor, i.e. how full can it get before we resize */ -//#define LOAD_NUMER 3 // 75% -//#define LOAD_DENOM 4 -#define LOAD_NUMER 5 // 62.5% -#define LOAD_DENOM 8 -//#define LOAD_NUMER 1 // 50% -//#define LOAD_DENOM 2 - -/* - * Compute the capacity needed for a table to hold "size" elements. - */ -size_t mzHashSize(size_t size) { - return (size * LOAD_DENOM) / LOAD_NUMER +1; -} - -/* - * Round up to the next highest power of 2. - * - * Found on http://graphics.stanford.edu/~seander/bithacks.html. - */ -unsigned int roundUpPower2(unsigned int val) -{ - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - - return val; -} - -/* - * Create and initialize a hash table. - */ -HashTable* mzHashTableCreate(size_t initialSize, HashFreeFunc freeFunc) -{ - HashTable* pHashTable; - - assert(initialSize > 0); - - pHashTable = (HashTable*) malloc(sizeof(*pHashTable)); - if (pHashTable == NULL) - return NULL; - - pHashTable->tableSize = roundUpPower2(initialSize); - pHashTable->numEntries = pHashTable->numDeadEntries = 0; - pHashTable->freeFunc = freeFunc; - pHashTable->pEntries = - (HashEntry*) calloc((size_t)pHashTable->tableSize, sizeof(HashTable)); - if (pHashTable->pEntries == NULL) { - free(pHashTable); - return NULL; - } - - return pHashTable; -} - -/* - * Clear out all entries. - */ -void mzHashTableClear(HashTable* pHashTable) -{ - HashEntry* pEnt; - int i; - - pEnt = pHashTable->pEntries; - for (i = 0; i < pHashTable->tableSize; i++, pEnt++) { - if (pEnt->data == HASH_TOMBSTONE) { - // nuke entry - pEnt->data = NULL; - } else if (pEnt->data != NULL) { - // call free func then nuke entry - if (pHashTable->freeFunc != NULL) - (*pHashTable->freeFunc)(pEnt->data); - pEnt->data = NULL; - } - } - - pHashTable->numEntries = 0; - pHashTable->numDeadEntries = 0; -} - -/* - * Free the table. - */ -void mzHashTableFree(HashTable* pHashTable) -{ - if (pHashTable == NULL) - return; - mzHashTableClear(pHashTable); - free(pHashTable->pEntries); - free(pHashTable); -} - -#ifndef NDEBUG -/* - * Count up the number of tombstone entries in the hash table. - */ -static int countTombStones(HashTable* pHashTable) -{ - int i, count; - - for (count = i = 0; i < pHashTable->tableSize; i++) { - if (pHashTable->pEntries[i].data == HASH_TOMBSTONE) - count++; - } - return count; -} -#endif - -/* - * Resize a hash table. We do this when adding an entry increased the - * size of the table beyond its comfy limit. - * - * This essentially requires re-inserting all elements into the new storage. - * - * If multiple threads can access the hash table, the table's lock should - * have been grabbed before issuing the "lookup+add" call that led to the - * resize, so we don't have a synchronization problem here. - */ -static bool resizeHash(HashTable* pHashTable, int newSize) -{ - HashEntry* pNewEntries; - int i; - - assert(countTombStones(pHashTable) == pHashTable->numDeadEntries); - //LOGI("before: dead=%d\n", pHashTable->numDeadEntries); - - pNewEntries = (HashEntry*) calloc(newSize, sizeof(HashTable)); - if (pNewEntries == NULL) - return false; - - for (i = 0; i < pHashTable->tableSize; i++) { - void* data = pHashTable->pEntries[i].data; - if (data != NULL && data != HASH_TOMBSTONE) { - int hashValue = pHashTable->pEntries[i].hashValue; - int newIdx; - - /* probe for new spot, wrapping around */ - newIdx = hashValue & (newSize-1); - while (pNewEntries[newIdx].data != NULL) - newIdx = (newIdx + 1) & (newSize-1); - - pNewEntries[newIdx].hashValue = hashValue; - pNewEntries[newIdx].data = data; - } - } - - free(pHashTable->pEntries); - pHashTable->pEntries = pNewEntries; - pHashTable->tableSize = newSize; - pHashTable->numDeadEntries = 0; - - assert(countTombStones(pHashTable) == 0); - return true; -} - -/* - * Look up an entry. - * - * We probe on collisions, wrapping around the table. - */ -void* mzHashTableLookup(HashTable* pHashTable, unsigned int itemHash, void* item, - HashCompareFunc cmpFunc, bool doAdd) -{ - HashEntry* pEntry; - HashEntry* pEnd; - void* result = NULL; - - assert(pHashTable->tableSize > 0); - assert(item != HASH_TOMBSTONE); - assert(item != NULL); - - /* jump to the first entry and probe for a match */ - pEntry = &pHashTable->pEntries[itemHash & (pHashTable->tableSize-1)]; - pEnd = &pHashTable->pEntries[pHashTable->tableSize]; - while (pEntry->data != NULL) { - if (pEntry->data != HASH_TOMBSTONE && - pEntry->hashValue == itemHash && - (*cmpFunc)(pEntry->data, item) == 0) - { - /* match */ - //LOGD("+++ match on entry %d\n", pEntry - pHashTable->pEntries); - break; - } - - pEntry++; - if (pEntry == pEnd) { /* wrap around to start */ - if (pHashTable->tableSize == 1) - break; /* edge case - single-entry table */ - pEntry = pHashTable->pEntries; - } - - //LOGI("+++ look probing %d...\n", pEntry - pHashTable->pEntries); - } - - if (pEntry->data == NULL) { - if (doAdd) { - pEntry->hashValue = itemHash; - pEntry->data = item; - pHashTable->numEntries++; - - /* - * We've added an entry. See if this brings us too close to full. - */ - if ((pHashTable->numEntries+pHashTable->numDeadEntries) * LOAD_DENOM - > pHashTable->tableSize * LOAD_NUMER) - { - if (!resizeHash(pHashTable, pHashTable->tableSize * 2)) { - /* don't really have a way to indicate failure */ - LOGE("Dalvik hash resize failure\n"); - abort(); - } - /* note "pEntry" is now invalid */ - } else { - //LOGW("okay %d/%d/%d\n", - // pHashTable->numEntries, pHashTable->tableSize, - // (pHashTable->tableSize * LOAD_NUMER) / LOAD_DENOM); - } - - /* full table is bad -- search for nonexistent never halts */ - assert(pHashTable->numEntries < pHashTable->tableSize); - result = item; - } else { - assert(result == NULL); - } - } else { - result = pEntry->data; - } - - return result; -} - -/* - * Remove an entry from the table. - * - * Does NOT invoke the "free" function on the item. - */ -bool mzHashTableRemove(HashTable* pHashTable, unsigned int itemHash, void* item) -{ - HashEntry* pEntry; - HashEntry* pEnd; - - assert(pHashTable->tableSize > 0); - - /* jump to the first entry and probe for a match */ - pEntry = &pHashTable->pEntries[itemHash & (pHashTable->tableSize-1)]; - pEnd = &pHashTable->pEntries[pHashTable->tableSize]; - while (pEntry->data != NULL) { - if (pEntry->data == item) { - //LOGI("+++ stepping on entry %d\n", pEntry - pHashTable->pEntries); - pEntry->data = HASH_TOMBSTONE; - pHashTable->numEntries--; - pHashTable->numDeadEntries++; - return true; - } - - pEntry++; - if (pEntry == pEnd) { /* wrap around to start */ - if (pHashTable->tableSize == 1) - break; /* edge case - single-entry table */ - pEntry = pHashTable->pEntries; - } - - //LOGI("+++ del probing %d...\n", pEntry - pHashTable->pEntries); - } - - return false; -} - -/* - * Execute a function on every entry in the hash table. - * - * If "func" returns a nonzero value, terminate early and return the value. - */ -int mzHashForeach(HashTable* pHashTable, HashForeachFunc func, void* arg) -{ - int i, val; - - for (i = 0; i < pHashTable->tableSize; i++) { - HashEntry* pEnt = &pHashTable->pEntries[i]; - - if (pEnt->data != NULL && pEnt->data != HASH_TOMBSTONE) { - val = (*func)(pEnt->data, arg); - if (val != 0) - return val; - } - } - - return 0; -} - - -/* - * Look up an entry, counting the number of times we have to probe. - * - * Returns -1 if the entry wasn't found. - */ -int countProbes(HashTable* pHashTable, unsigned int itemHash, const void* item, - HashCompareFunc cmpFunc) -{ - HashEntry* pEntry; - HashEntry* pEnd; - int count = 0; - - assert(pHashTable->tableSize > 0); - assert(item != HASH_TOMBSTONE); - assert(item != NULL); - - /* jump to the first entry and probe for a match */ - pEntry = &pHashTable->pEntries[itemHash & (pHashTable->tableSize-1)]; - pEnd = &pHashTable->pEntries[pHashTable->tableSize]; - while (pEntry->data != NULL) { - if (pEntry->data != HASH_TOMBSTONE && - pEntry->hashValue == itemHash && - (*cmpFunc)(pEntry->data, item) == 0) - { - /* match */ - break; - } - - pEntry++; - if (pEntry == pEnd) { /* wrap around to start */ - if (pHashTable->tableSize == 1) - break; /* edge case - single-entry table */ - pEntry = pHashTable->pEntries; - } - - count++; - } - if (pEntry->data == NULL) - return -1; - - return count; -} - -/* - * Evaluate the amount of probing required for the specified hash table. - * - * We do this by running through all entries in the hash table, computing - * the hash value and then doing a lookup. - * - * The caller should lock the table before calling here. - */ -void mzHashTableProbeCount(HashTable* pHashTable, HashCalcFunc calcFunc, - HashCompareFunc cmpFunc) -{ - int numEntries, minProbe, maxProbe, totalProbe; - HashIter iter; - - numEntries = maxProbe = totalProbe = 0; - minProbe = 65536*32767; - - for (mzHashIterBegin(pHashTable, &iter); !mzHashIterDone(&iter); - mzHashIterNext(&iter)) - { - const void* data = (const void*)mzHashIterData(&iter); - int count; - - count = countProbes(pHashTable, (*calcFunc)(data), data, cmpFunc); - - numEntries++; - - if (count < minProbe) - minProbe = count; - if (count > maxProbe) - maxProbe = count; - totalProbe += count; - } - - LOGI("Probe: min=%d max=%d, total=%d in %d (%d), avg=%.3f\n", - minProbe, maxProbe, totalProbe, numEntries, pHashTable->tableSize, - (float) totalProbe / (float) numEntries); -} diff --git a/minzip/Hash.h b/minzip/Hash.h deleted file mode 100644 index 8194537..0000000 --- a/minzip/Hash.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2007 The Android Open Source Project - * - * General purpose hash table, used for finding classes, methods, etc. - * - * When the number of elements reaches 3/4 of the table's capacity, the - * table will be resized. - */ -#ifndef _MINZIP_HASH -#define _MINZIP_HASH - -#include "inline_magic.h" - -#include <stdlib.h> -#include <stdbool.h> -#include <assert.h> - -/* compute the hash of an item with a specific type */ -typedef unsigned int (*HashCompute)(const void* item); - -/* - * Compare a hash entry with a "loose" item after their hash values match. - * Returns { <0, 0, >0 } depending on ordering of items (same semantics - * as strcmp()). - */ -typedef int (*HashCompareFunc)(const void* tableItem, const void* looseItem); - -/* - * This function will be used to free entries in the table. This can be - * NULL if no free is required, free(), or a custom function. - */ -typedef void (*HashFreeFunc)(void* ptr); - -/* - * Used by mzHashForeach(). - */ -typedef int (*HashForeachFunc)(void* data, void* arg); - -/* - * One entry in the hash table. "data" values are expected to be (or have - * the same characteristics as) valid pointers. In particular, a NULL - * value for "data" indicates an empty slot, and HASH_TOMBSTONE indicates - * a no-longer-used slot that must be stepped over during probing. - * - * Attempting to add a NULL or tombstone value is an error. - * - * When an entry is released, we will call (HashFreeFunc)(entry->data). - */ -typedef struct HashEntry { - unsigned int hashValue; - void* data; -} HashEntry; - -#define HASH_TOMBSTONE ((void*) 0xcbcacccd) // invalid ptr value - -/* - * Expandable hash table. - * - * This structure should be considered opaque. - */ -typedef struct HashTable { - int tableSize; /* must be power of 2 */ - int numEntries; /* current #of "live" entries */ - int numDeadEntries; /* current #of tombstone entries */ - HashEntry* pEntries; /* array on heap */ - HashFreeFunc freeFunc; -} HashTable; - -/* - * Create and initialize a HashTable structure, using "initialSize" as - * a basis for the initial capacity of the table. (The actual initial - * table size may be adjusted upward.) If you know exactly how many - * elements the table will hold, pass the result from mzHashSize() in.) - * - * Returns "false" if unable to allocate the table. - */ -HashTable* mzHashTableCreate(size_t initialSize, HashFreeFunc freeFunc); - -/* - * Compute the capacity needed for a table to hold "size" elements. Use - * this when you know ahead of time how many elements the table will hold. - * Pass this value into mzHashTableCreate() to ensure that you can add - * all elements without needing to reallocate the table. - */ -size_t mzHashSize(size_t size); - -/* - * Clear out a hash table, freeing the contents of any used entries. - */ -void mzHashTableClear(HashTable* pHashTable); - -/* - * Free a hash table. - */ -void mzHashTableFree(HashTable* pHashTable); - -/* - * Get #of entries in hash table. - */ -INLINE int mzHashTableNumEntries(HashTable* pHashTable) { - return pHashTable->numEntries; -} - -/* - * Get total size of hash table (for memory usage calculations). - */ -INLINE int mzHashTableMemUsage(HashTable* pHashTable) { - return sizeof(HashTable) + pHashTable->tableSize * sizeof(HashEntry); -} - -/* - * Look up an entry in the table, possibly adding it if it's not there. - * - * If "item" is not found, and "doAdd" is false, NULL is returned. - * Otherwise, a pointer to the found or added item is returned. (You can - * tell the difference by seeing if return value == item.) - * - * An "add" operation may cause the entire table to be reallocated. - */ -void* mzHashTableLookup(HashTable* pHashTable, unsigned int itemHash, void* item, - HashCompareFunc cmpFunc, bool doAdd); - -/* - * Remove an item from the hash table, given its "data" pointer. Does not - * invoke the "free" function; just detaches it from the table. - */ -bool mzHashTableRemove(HashTable* pHashTable, unsigned int hash, void* item); - -/* - * Execute "func" on every entry in the hash table. - * - * If "func" returns a nonzero value, terminate early and return the value. - */ -int mzHashForeach(HashTable* pHashTable, HashForeachFunc func, void* arg); - -/* - * An alternative to mzHashForeach(), using an iterator. - * - * Use like this: - * HashIter iter; - * for (mzHashIterBegin(hashTable, &iter); !mzHashIterDone(&iter); - * mzHashIterNext(&iter)) - * { - * MyData* data = (MyData*)mzHashIterData(&iter); - * } - */ -typedef struct HashIter { - void* data; - HashTable* pHashTable; - int idx; -} HashIter; -INLINE void mzHashIterNext(HashIter* pIter) { - int i = pIter->idx +1; - int lim = pIter->pHashTable->tableSize; - for ( ; i < lim; i++) { - void* data = pIter->pHashTable->pEntries[i].data; - if (data != NULL && data != HASH_TOMBSTONE) - break; - } - pIter->idx = i; -} -INLINE void mzHashIterBegin(HashTable* pHashTable, HashIter* pIter) { - pIter->pHashTable = pHashTable; - pIter->idx = -1; - mzHashIterNext(pIter); -} -INLINE bool mzHashIterDone(HashIter* pIter) { - return (pIter->idx >= pIter->pHashTable->tableSize); -} -INLINE void* mzHashIterData(HashIter* pIter) { - assert(pIter->idx >= 0 && pIter->idx < pIter->pHashTable->tableSize); - return pIter->pHashTable->pEntries[pIter->idx].data; -} - - -/* - * Evaluate hash table performance by examining the number of times we - * have to probe for an entry. - * - * The caller should lock the table beforehand. - */ -typedef unsigned int (*HashCalcFunc)(const void* item); -void mzHashTableProbeCount(HashTable* pHashTable, HashCalcFunc calcFunc, - HashCompareFunc cmpFunc); - -#endif /*_MINZIP_HASH*/ diff --git a/minzip/Inlines.c b/minzip/Inlines.c deleted file mode 100644 index 91f8775..0000000 --- a/minzip/Inlines.c +++ /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. - */ - -/* Make sure that non-inlined versions of INLINED-marked functions - * exist so that debug builds (which don't generally do inlining) - * don't break. - */ -#define MINZIP_GENERATE_INLINES 1 -#include "Bits.h" -#include "Hash.h" -#include "SysUtil.h" -#include "Zip.h" diff --git a/minzip/Log.h b/minzip/Log.h deleted file mode 100644 index 36e62f5..0000000 --- a/minzip/Log.h +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -// C/C++ logging functions. See the logging documentation for API details. -// -// We'd like these to be available from C code (in case we import some from -// somewhere), so this has a C interface. -// -// The output will be correct when the log file is shared between multiple -// threads and/or multiple processes so long as the operating system -// supports O_APPEND. These calls have mutex-protected data structures -// and so are NOT reentrant. Do not use LOG in a signal handler. -// -#ifndef _MINZIP_LOG_H -#define _MINZIP_LOG_H - -#include <stdio.h> - -// --------------------------------------------------------------------- - -/* - * Normally we strip LOGV (VERBOSE messages) from release builds. - * You can modify this (for example with "#define LOG_NDEBUG 0" - * at the top of your source file) to change that behavior. - */ -#ifndef LOG_NDEBUG -#ifdef NDEBUG -#define LOG_NDEBUG 1 -#else -#define LOG_NDEBUG 0 -#endif -#endif - -/* - * This is the local tag used for the following simplified - * logging macros. You can change this preprocessor definition - * before using the other macros to change the tag. - */ -#ifndef LOG_TAG -#define LOG_TAG NULL -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose log message using the current LOG_TAG. - */ -#ifndef LOGV -#if LOG_NDEBUG -#define LOGV(...) ((void)0) -#else -#define LOGV(...) ((void)LOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef LOGV_IF -#if LOG_NDEBUG -#define LOGV_IF(cond, ...) ((void)0) -#else -#define LOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -#define LOGVV LOGV -#define LOGVV_IF LOGV_IF - -/* - * Simplified macro to send a debug log message using the current LOG_TAG. - */ -#ifndef LOGD -#define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGD_IF -#define LOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info log message using the current LOG_TAG. - */ -#ifndef LOGI -#define LOGI(...) ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGI_IF -#define LOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning log message using the current LOG_TAG. - */ -#ifndef LOGW -#define LOGW(...) ((void)LOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGW_IF -#define LOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error log message using the current LOG_TAG. - */ -#ifndef LOGE -#define LOGE(...) ((void)LOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGE_IF -#define LOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * verbose priority. - */ -#ifndef IF_LOGV -#if LOG_NDEBUG -#define IF_LOGV() if (false) -#else -#define IF_LOGV() IF_LOG(LOG_VERBOSE, LOG_TAG) -#endif -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * debug priority. - */ -#ifndef IF_LOGD -#define IF_LOGD() IF_LOG(LOG_DEBUG, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * info priority. - */ -#ifndef IF_LOGI -#define IF_LOGI() IF_LOG(LOG_INFO, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * warn priority. - */ -#ifndef IF_LOGW -#define IF_LOGW() IF_LOG(LOG_WARN, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * error priority. - */ -#ifndef IF_LOGE -#define IF_LOGE() IF_LOG(LOG_ERROR, LOG_TAG) -#endif - -// --------------------------------------------------------------------- - -/* - * Basic log message macro. - * - * Example: - * LOG(LOG_WARN, NULL, "Failed with error %d", errno); - * - * The second argument may be NULL or "" to indicate the "global" tag. - * - * Non-gcc probably won't have __FUNCTION__. It's not vital. gcc also - * offers __PRETTY_FUNCTION__, which is rather more than we need. - */ -#ifndef LOG -#define LOG(priority, tag, ...) \ - LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to specify a number for the priority. - */ -#ifndef LOG_PRI -#define LOG_PRI(priority, tag, ...) \ - printf(tag ": " __VA_ARGS__) -#endif - -/* - * Conditional given a desired logging priority and tag. - */ -#ifndef IF_LOG -#define IF_LOG(priority, tag) \ - if (1) -#endif - -#endif // _MINZIP_LOG_H diff --git a/minzip/SysUtil.c b/minzip/SysUtil.c deleted file mode 100644 index 49a2522..0000000 --- a/minzip/SysUtil.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * System utilities. - */ -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <sys/mman.h> -#include <limits.h> -#include <errno.h> -#include <assert.h> - -#define LOG_TAG "minzip" -#include "Log.h" -#include "SysUtil.h" - -/* - * Having trouble finding a portable way to get this. sysconf(_SC_PAGE_SIZE) - * seems appropriate, but we don't have that on the device. Some systems - * have getpagesize(2), though the linux man page has some odd cautions. - */ -#define DEFAULT_PAGE_SIZE 4096 - - -/* - * Create an anonymous shared memory segment large enough to hold "length" - * bytes. The actual segment may be larger because mmap() operates on - * page boundaries (usually 4K). - */ -static void* sysCreateAnonShmem(size_t length) -{ - void* ptr; - - ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANON, -1, 0); - if (ptr == MAP_FAILED) { - LOGW("mmap(%d, RW, SHARED|ANON) failed: %s\n", (int) length, - strerror(errno)); - return NULL; - } - - return ptr; -} - -static int getFileStartAndLength(int fd, off_t *start_, size_t *length_) -{ - off_t start, end; - size_t length; - - assert(start_ != NULL); - assert(length_ != NULL); - - start = lseek(fd, 0L, SEEK_CUR); - end = lseek(fd, 0L, SEEK_END); - (void) lseek(fd, start, SEEK_SET); - - if (start == (off_t) -1 || end == (off_t) -1) { - LOGE("could not determine length of file\n"); - return -1; - } - - length = end - start; - if (length == 0) { - LOGE("file is empty\n"); - return -1; - } - - *start_ = start; - *length_ = length; - - return 0; -} - -/* - * Pull the contents of a file into an new shared memory segment. We grab - * everything from fd's current offset on. - * - * We need to know the length ahead of time so we can allocate a segment - * of sufficient size. - */ -int sysLoadFileInShmem(int fd, MemMapping* pMap) -{ - off_t start; - size_t length, actual; - void* memPtr; - - assert(pMap != NULL); - - if (getFileStartAndLength(fd, &start, &length) < 0) - return -1; - - memPtr = sysCreateAnonShmem(length); - if (memPtr == NULL) - return -1; - - actual = read(fd, memPtr, length); - if (actual != length) { - LOGE("only read %d of %d bytes\n", (int) actual, (int) length); - sysReleaseShmem(pMap); - return -1; - } - - pMap->baseAddr = pMap->addr = memPtr; - pMap->baseLength = pMap->length = length; - - return 0; -} - -/* - * Map a file (from fd's current offset) into a shared, read-only memory - * segment. The file offset must be a multiple of the page size. - * - * On success, returns 0 and fills out "pMap". On failure, returns a nonzero - * value and does not disturb "pMap". - */ -int sysMapFileInShmem(int fd, MemMapping* pMap) -{ - off_t start; - size_t length; - void* memPtr; - - assert(pMap != NULL); - - if (getFileStartAndLength(fd, &start, &length) < 0) - return -1; - - memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start); - if (memPtr == MAP_FAILED) { - LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", (int) length, - fd, (int) start, strerror(errno)); - return -1; - } - - pMap->baseAddr = pMap->addr = memPtr; - pMap->baseLength = pMap->length = length; - - return 0; -} - -/* - * Map part of a file (from fd's current offset) into a shared, read-only - * memory segment. - * - * On success, returns 0 and fills out "pMap". On failure, returns a nonzero - * value and does not disturb "pMap". - */ -int sysMapFileSegmentInShmem(int fd, off_t start, long length, - MemMapping* pMap) -{ - off_t dummy; - size_t fileLength, actualLength; - off_t actualStart; - int adjust; - void* memPtr; - - assert(pMap != NULL); - - if (getFileStartAndLength(fd, &dummy, &fileLength) < 0) - return -1; - - if (start + length > (long)fileLength) { - LOGW("bad segment: st=%d len=%ld flen=%d\n", - (int) start, length, (int) fileLength); - return -1; - } - - /* adjust to be page-aligned */ - adjust = start % DEFAULT_PAGE_SIZE; - actualStart = start - adjust; - actualLength = length + adjust; - - memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED, - fd, actualStart); - if (memPtr == MAP_FAILED) { - LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", - (int) actualLength, fd, (int) actualStart, strerror(errno)); - return -1; - } - - pMap->baseAddr = memPtr; - pMap->baseLength = actualLength; - pMap->addr = (char*)memPtr + adjust; - pMap->length = length; - - LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d\n", - (int) start, (int) length, - pMap->baseAddr, (int) pMap->baseLength, - pMap->addr, (int) pMap->length); - - return 0; -} - -/* - * Release a memory mapping. - */ -void sysReleaseShmem(MemMapping* pMap) -{ - if (pMap->baseAddr == NULL && pMap->baseLength == 0) - return; - - if (munmap(pMap->baseAddr, pMap->baseLength) < 0) { - LOGW("munmap(%p, %d) failed: %s\n", - pMap->baseAddr, (int)pMap->baseLength, strerror(errno)); - } else { - LOGV("munmap(%p, %d) succeeded\n", pMap->baseAddr, pMap->baseLength); - pMap->baseAddr = NULL; - pMap->baseLength = 0; - } -} - diff --git a/minzip/SysUtil.h b/minzip/SysUtil.h deleted file mode 100644 index ec3a4bc..0000000 --- a/minzip/SysUtil.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * System utilities. - */ -#ifndef _MINZIP_SYSUTIL -#define _MINZIP_SYSUTIL - -#include "inline_magic.h" - -#include <sys/types.h> - -/* - * Use this to keep track of mapped segments. - */ -typedef struct MemMapping { - void* addr; /* start of data */ - size_t length; /* length of data */ - - void* baseAddr; /* page-aligned base address */ - size_t baseLength; /* length of mapping */ -} MemMapping; - -/* copy a map */ -INLINE void sysCopyMap(MemMapping* dst, const MemMapping* src) { - *dst = *src; -} - -/* - * Load a file into a new shared memory segment. All data from the current - * offset to the end of the file is pulled in. - * - * The segment is read-write, allowing VM fixups. (It should be modified - * to support .gz/.zip compressed data.) - * - * On success, "pMap" is filled in, and zero is returned. - */ -int sysLoadFileInShmem(int fd, MemMapping* pMap); - -/* - * Map a file (from fd's current offset) into a shared, - * read-only memory segment. - * - * On success, "pMap" is filled in, and zero is returned. - */ -int sysMapFileInShmem(int fd, MemMapping* pMap); - -/* - * Like sysMapFileInShmem, but on only part of a file. - */ -int sysMapFileSegmentInShmem(int fd, off_t start, long length, - MemMapping* pMap); - -/* - * Release the pages associated with a shared memory segment. - * - * This does not free "pMap"; it just releases the memory. - */ -void sysReleaseShmem(MemMapping* pMap); - -#endif /*_MINZIP_SYSUTIL*/ diff --git a/minzip/Zip.c b/minzip/Zip.c deleted file mode 100644 index 100c833..0000000 --- a/minzip/Zip.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Simple Zip file support. - */ -#include "safe_iop.h" -#include "zlib.h" - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdint.h> // for uintptr_t -#include <stdlib.h> -#include <sys/stat.h> // for S_ISLNK() -#include <unistd.h> - -#define LOG_TAG "minzip" -#include "Zip.h" -#include "Bits.h" -#include "Log.h" -#include "DirUtil.h" - -#undef NDEBUG // do this after including Log.h -#include <assert.h> - -#define SORT_ENTRIES 1 - -/* - * Offset and length constants (java.util.zip naming convention). - */ -enum { - CENSIG = 0x02014b50, // PK12 - CENHDR = 46, - - CENVEM = 4, - CENVER = 6, - CENFLG = 8, - CENHOW = 10, - CENTIM = 12, - CENCRC = 16, - CENSIZ = 20, - CENLEN = 24, - CENNAM = 28, - CENEXT = 30, - CENCOM = 32, - CENDSK = 34, - CENATT = 36, - CENATX = 38, - CENOFF = 42, - - ENDSIG = 0x06054b50, // PK56 - ENDHDR = 22, - - ENDSUB = 8, - ENDTOT = 10, - ENDSIZ = 12, - ENDOFF = 16, - ENDCOM = 20, - - EXTSIG = 0x08074b50, // PK78 - EXTHDR = 16, - - EXTCRC = 4, - EXTSIZ = 8, - EXTLEN = 12, - - LOCSIG = 0x04034b50, // PK34 - LOCHDR = 30, - - LOCVER = 4, - LOCFLG = 6, - LOCHOW = 8, - LOCTIM = 10, - LOCCRC = 14, - LOCSIZ = 18, - LOCLEN = 22, - LOCNAM = 26, - LOCEXT = 28, - - STORED = 0, - DEFLATED = 8, - - CENVEM_UNIX = 3 << 8, // the high byte of CENVEM -}; - - -/* - * For debugging, dump the contents of a ZipEntry. - */ -#if 0 -static void dumpEntry(const ZipEntry* pEntry) -{ - LOGI(" %p '%.*s'\n", pEntry->fileName,pEntry->fileNameLen,pEntry->fileName); - LOGI(" off=%ld comp=%ld uncomp=%ld how=%d\n", pEntry->offset, - pEntry->compLen, pEntry->uncompLen, pEntry->compression); -} -#endif - -/* - * (This is a mzHashTableLookup callback.) - * - * Compare two ZipEntry structs, by name. - */ -static int hashcmpZipEntry(const void* ventry1, const void* ventry2) -{ - const ZipEntry* entry1 = (const ZipEntry*) ventry1; - const ZipEntry* entry2 = (const ZipEntry*) ventry2; - - if (entry1->fileNameLen != entry2->fileNameLen) - return entry1->fileNameLen - entry2->fileNameLen; - return memcmp(entry1->fileName, entry2->fileName, entry1->fileNameLen); -} - -/* - * (This is a mzHashTableLookup callback.) - * - * find a ZipEntry struct by name. - */ -static int hashcmpZipName(const void* ventry, const void* vname) -{ - const ZipEntry* entry = (const ZipEntry*) ventry; - const char* name = (const char*) vname; - unsigned int nameLen = strlen(name); - - if (entry->fileNameLen != nameLen) - return entry->fileNameLen - nameLen; - return memcmp(entry->fileName, name, nameLen); -} - -/* - * Compute the hash code for a ZipEntry filename. - * - * Not expected to be compatible with any other hash function, so we init - * to 2 to ensure it doesn't happen to match. - */ -static unsigned int computeHash(const char* name, int nameLen) -{ - unsigned int hash = 2; - - while (nameLen--) - hash = hash * 31 + *name++; - - return hash; -} - -static void addEntryToHashTable(HashTable* pHash, ZipEntry* pEntry) -{ - unsigned int itemHash = computeHash(pEntry->fileName, pEntry->fileNameLen); - const ZipEntry* found; - - found = (const ZipEntry*)mzHashTableLookup(pHash, - itemHash, pEntry, hashcmpZipEntry, true); - if (found != pEntry) { - LOGW("WARNING: duplicate entry '%.*s' in Zip\n", - found->fileNameLen, found->fileName); - /* keep going */ - } -} - -static int validFilename(const char *fileName, unsigned int fileNameLen) -{ - // Forbid super long filenames. - if (fileNameLen >= PATH_MAX) { - LOGW("Filename too long (%d chatacters)\n", fileNameLen); - return 0; - } - - // Require all characters to be printable ASCII (no NUL, no UTF-8, etc). - unsigned int i; - for (i = 0; i < fileNameLen; ++i) { - if (fileName[i] < 32 || fileName[i] >= 127) { - LOGW("Filename contains invalid character '\%03o'\n", fileName[i]); - return 0; - } - } - - return 1; -} - -/* - * Parse the contents of a Zip archive. After confirming that the file - * is in fact a Zip, we scan out the contents of the central directory and - * store it in a hash table. - * - * Returns "true" on success. - */ -static bool parseZipArchive(ZipArchive* pArchive, const MemMapping* pMap) -{ - bool result = false; - const unsigned char* ptr; - unsigned int i, numEntries, cdOffset; - unsigned int val; - - /* - * The first 4 bytes of the file will either be the local header - * signature for the first file (LOCSIG) or, if the archive doesn't - * have any files in it, the end-of-central-directory signature (ENDSIG). - */ - val = get4LE(pMap->addr); - if (val == ENDSIG) { - LOGI("Found Zip archive, but it looks empty\n"); - goto bail; - } else if (val != LOCSIG) { - LOGV("Not a Zip archive (found 0x%08x)\n", val); - goto bail; - } - - /* - * Find the EOCD. We'll find it immediately unless they have a file - * comment. - */ - ptr = pMap->addr + pMap->length - ENDHDR; - - while (ptr >= (const unsigned char*) pMap->addr) { - if (*ptr == (ENDSIG & 0xff) && get4LE(ptr) == ENDSIG) - break; - ptr--; - } - if (ptr < (const unsigned char*) pMap->addr) { - LOGI("Could not find end-of-central-directory in Zip\n"); - goto bail; - } - - /* - * There are two interesting items in the EOCD block: the number of - * entries in the file, and the file offset of the start of the - * central directory. - */ - numEntries = get2LE(ptr + ENDSUB); - cdOffset = get4LE(ptr + ENDOFF); - - LOGVV("numEntries=%d cdOffset=%d\n", numEntries, cdOffset); - if (numEntries == 0 || cdOffset >= pMap->length) { - LOGW("Invalid entries=%d offset=%d (len=%zd)\n", - numEntries, cdOffset, pMap->length); - goto bail; - } - - /* - * Create data structures to hold entries. - */ - pArchive->numEntries = numEntries; - pArchive->pEntries = (ZipEntry*) calloc(numEntries, sizeof(ZipEntry)); - pArchive->pHash = mzHashTableCreate(mzHashSize(numEntries), NULL); - if (pArchive->pEntries == NULL || pArchive->pHash == NULL) - goto bail; - - ptr = pMap->addr + cdOffset; - for (i = 0; i < numEntries; i++) { - ZipEntry* pEntry; - unsigned int fileNameLen, extraLen, commentLen, localHdrOffset; - const unsigned char* localHdr; - const char *fileName; - - if (ptr + CENHDR > (const unsigned char*)pMap->addr + pMap->length) { - LOGW("Ran off the end (at %d)\n", i); - goto bail; - } - if (get4LE(ptr) != CENSIG) { - LOGW("Missed a central dir sig (at %d)\n", i); - goto bail; - } - - localHdrOffset = get4LE(ptr + CENOFF); - fileNameLen = get2LE(ptr + CENNAM); - extraLen = get2LE(ptr + CENEXT); - commentLen = get2LE(ptr + CENCOM); - fileName = (const char*)ptr + CENHDR; - if (fileName + fileNameLen > (const char*)pMap->addr + pMap->length) { - LOGW("Filename ran off the end (at %d)\n", i); - goto bail; - } - if (!validFilename(fileName, fileNameLen)) { - LOGW("Invalid filename (at %d)\n", i); - goto bail; - } - -#if SORT_ENTRIES - /* Figure out where this entry should go (binary search). - */ - if (i > 0) { - int low, high; - - low = 0; - high = i - 1; - while (low <= high) { - int mid; - int diff; - int diffLen; - - mid = low + ((high - low) / 2); // avoid overflow - - if (pArchive->pEntries[mid].fileNameLen < fileNameLen) { - diffLen = pArchive->pEntries[mid].fileNameLen; - } else { - diffLen = fileNameLen; - } - diff = strncmp(pArchive->pEntries[mid].fileName, fileName, - diffLen); - if (diff == 0) { - diff = pArchive->pEntries[mid].fileNameLen - fileNameLen; - } - if (diff < 0) { - low = mid + 1; - } else if (diff > 0) { - high = mid - 1; - } else { - high = mid; - break; - } - } - - unsigned int target = high + 1; - assert(target <= i); - if (target != i) { - /* It belongs somewhere other than at the end of - * the list. Make some room at [target]. - */ - memmove(pArchive->pEntries + target + 1, - pArchive->pEntries + target, - (i - target) * sizeof(ZipEntry)); - } - pEntry = &pArchive->pEntries[target]; - } else { - pEntry = &pArchive->pEntries[0]; - } -#else - pEntry = &pArchive->pEntries[i]; -#endif - - //LOGI("%d: localHdr=%d fnl=%d el=%d cl=%d\n", - // i, localHdrOffset, fileNameLen, extraLen, commentLen); - - pEntry->fileNameLen = fileNameLen; - pEntry->fileName = fileName; - - pEntry->compLen = get4LE(ptr + CENSIZ); - pEntry->uncompLen = get4LE(ptr + CENLEN); - pEntry->compression = get2LE(ptr + CENHOW); - pEntry->modTime = get4LE(ptr + CENTIM); - pEntry->crc32 = get4LE(ptr + CENCRC); - - /* These two are necessary for finding the mode of the file. - */ - pEntry->versionMadeBy = get2LE(ptr + CENVEM); - if ((pEntry->versionMadeBy & 0xff00) != 0 && - (pEntry->versionMadeBy & 0xff00) != CENVEM_UNIX) - { - LOGW("Incompatible \"version made by\": 0x%02x (at %d)\n", - pEntry->versionMadeBy >> 8, i); - goto bail; - } - pEntry->externalFileAttributes = get4LE(ptr + CENATX); - - // Perform pMap->addr + localHdrOffset, ensuring that it won't - // overflow. This is needed because localHdrOffset is untrusted. - if (!safe_add((uintptr_t *)&localHdr, (uintptr_t)pMap->addr, - (uintptr_t)localHdrOffset)) { - LOGW("Integer overflow adding in parseZipArchive\n"); - goto bail; - } - if ((uintptr_t)localHdr + LOCHDR > - (uintptr_t)pMap->addr + pMap->length) { - LOGW("Bad offset to local header: %d (at %d)\n", localHdrOffset, i); - goto bail; - } - if (get4LE(localHdr) != LOCSIG) { - LOGW("Missed a local header sig (at %d)\n", i); - goto bail; - } - pEntry->offset = localHdrOffset + LOCHDR - + get2LE(localHdr + LOCNAM) + get2LE(localHdr + LOCEXT); - if (!safe_add(NULL, pEntry->offset, pEntry->compLen)) { - LOGW("Integer overflow adding in parseZipArchive\n"); - goto bail; - } - if ((size_t)pEntry->offset + pEntry->compLen > pMap->length) { - LOGW("Data ran off the end (at %d)\n", i); - goto bail; - } - -#if !SORT_ENTRIES - /* Add to hash table; no need to lock here. - * Can't do this now if we're sorting, because entries - * will move around. - */ - addEntryToHashTable(pArchive->pHash, pEntry); -#endif - - //dumpEntry(pEntry); - ptr += CENHDR + fileNameLen + extraLen + commentLen; - } - -#if SORT_ENTRIES - /* If we're sorting, we have to wait until all entries - * are in their final places, otherwise the pointers will - * probably point to the wrong things. - */ - for (i = 0; i < numEntries; i++) { - /* Add to hash table; no need to lock here. - */ - addEntryToHashTable(pArchive->pHash, &pArchive->pEntries[i]); - } -#endif - - result = true; - -bail: - if (!result) { - mzHashTableFree(pArchive->pHash); - pArchive->pHash = NULL; - } - return result; -} - -/* - * Open a Zip archive and scan out the contents. - * - * The easiest way to do this is to mmap() the whole thing and do the - * traditional backward scan for central directory. Since the EOCD is - * a relatively small bit at the end, we should end up only touching a - * small set of pages. - * - * This will be called on non-Zip files, especially during startup, so - * we don't want to be too noisy about failures. (Do we want a "quiet" - * flag?) - * - * On success, we fill out the contents of "pArchive". - */ -int mzOpenZipArchive(const char* fileName, ZipArchive* pArchive) -{ - MemMapping map; - int err; - - LOGV("Opening archive '%s' %p\n", fileName, pArchive); - - map.addr = NULL; - memset(pArchive, 0, sizeof(*pArchive)); - - pArchive->fd = open(fileName, O_RDONLY, 0); - if (pArchive->fd < 0) { - err = errno ? errno : -1; - LOGV("Unable to open '%s': %s\n", fileName, strerror(err)); - goto bail; - } - - if (sysMapFileInShmem(pArchive->fd, &map) != 0) { - err = -1; - LOGW("Map of '%s' failed\n", fileName); - goto bail; - } - - if (map.length < ENDHDR) { - err = -1; - LOGV("File '%s' too small to be zip (%zd)\n", fileName, map.length); - goto bail; - } - - if (!parseZipArchive(pArchive, &map)) { - err = -1; - LOGV("Parsing '%s' failed\n", fileName); - goto bail; - } - - err = 0; - sysCopyMap(&pArchive->map, &map); - map.addr = NULL; - -bail: - if (err != 0) - mzCloseZipArchive(pArchive); - if (map.addr != NULL) - sysReleaseShmem(&map); - return err; -} - -/* - * Close a ZipArchive, closing the file and freeing the contents. - * - * NOTE: the ZipArchive may not have been fully created. - */ -void mzCloseZipArchive(ZipArchive* pArchive) -{ - LOGV("Closing archive %p\n", pArchive); - - if (pArchive->fd >= 0) - close(pArchive->fd); - if (pArchive->map.addr != NULL) - sysReleaseShmem(&pArchive->map); - - free(pArchive->pEntries); - - mzHashTableFree(pArchive->pHash); - - pArchive->fd = -1; - pArchive->pHash = NULL; - pArchive->pEntries = NULL; -} - -/* - * Find a matching entry. - * - * Returns NULL if no matching entry found. - */ -const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive, - const char* entryName) -{ - unsigned int itemHash = computeHash(entryName, strlen(entryName)); - - return (const ZipEntry*)mzHashTableLookup(pArchive->pHash, - itemHash, (char*) entryName, hashcmpZipName, false); -} - -/* - * Return true if the entry is a symbolic link. - */ -bool mzIsZipEntrySymlink(const ZipEntry* pEntry) -{ - if ((pEntry->versionMadeBy & 0xff00) == CENVEM_UNIX) { - return S_ISLNK(pEntry->externalFileAttributes >> 16); - } - return false; -} - -/* Call processFunction on the uncompressed data of a STORED entry. - */ -static bool processStoredEntry(const ZipArchive *pArchive, - const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, - void *cookie) -{ - size_t bytesLeft = pEntry->compLen; - while (bytesLeft > 0) { - unsigned char buf[32 * 1024]; - ssize_t n; - size_t count; - bool ret; - - count = bytesLeft; - if (count > sizeof(buf)) { - count = sizeof(buf); - } - n = read(pArchive->fd, buf, count); - if (n < 0 || (size_t)n != count) { - LOGE("Can't read %zu bytes from zip file: %ld\n", count, n); - return false; - } - ret = processFunction(buf, n, cookie); - if (!ret) { - return false; - } - bytesLeft -= count; - } - return true; -} - -static bool processDeflatedEntry(const ZipArchive *pArchive, - const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, - void *cookie) -{ - long result = -1; - unsigned char readBuf[32 * 1024]; - unsigned char procBuf[32 * 1024]; - z_stream zstream; - int zerr; - long compRemaining; - - compRemaining = pEntry->compLen; - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = (Bytef*) procBuf; - zstream.avail_out = sizeof(procBuf); - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have data. - */ - do { - /* read as much as we can */ - if (zstream.avail_in == 0) { - long getSize = (compRemaining > (long)sizeof(readBuf)) ? - (long)sizeof(readBuf) : compRemaining; - LOGVV("+++ reading %ld bytes (%ld left)\n", - getSize, compRemaining); - - int cc = read(pArchive->fd, readBuf, getSize); - if (cc != (int) getSize) { - LOGW("inflate read failed (%d vs %ld)\n", cc, getSize); - goto z_bail; - } - - compRemaining -= getSize; - - zstream.next_in = readBuf; - zstream.avail_in = getSize; - } - - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGD("zlib inflate call failed (zerr=%d)\n", zerr); - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != sizeof(procBuf))) - { - long procSize = zstream.next_out - procBuf; - LOGVV("+++ processing %d bytes\n", (int) procSize); - bool ret = processFunction(procBuf, procSize, cookie); - if (!ret) { - LOGW("Process function elected to fail (in inflate)\n"); - goto z_bail; - } - - zstream.next_out = procBuf; - zstream.avail_out = sizeof(procBuf); - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - // success! - result = zstream.total_out; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - if (result != pEntry->uncompLen) { - if (result != -1) // error already shown? - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", - result, pEntry->uncompLen); - return false; - } - return true; -} - -/* - * Stream the uncompressed data through the supplied function, - * passing cookie to it each time it gets called. processFunction - * may be called more than once. - * - * If processFunction returns false, the operation is abandoned and - * mzProcessZipEntryContents() immediately returns false. - * - * This is useful for calculating the hash of an entry's uncompressed contents. - */ -bool mzProcessZipEntryContents(const ZipArchive *pArchive, - const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, - void *cookie) -{ - bool ret = false; - off_t oldOff; - - /* save current offset */ - oldOff = lseek(pArchive->fd, 0, SEEK_CUR); - - /* Seek to the beginning of the entry's compressed data. */ - lseek(pArchive->fd, pEntry->offset, SEEK_SET); - - switch (pEntry->compression) { - case STORED: - ret = processStoredEntry(pArchive, pEntry, processFunction, cookie); - break; - case DEFLATED: - ret = processDeflatedEntry(pArchive, pEntry, processFunction, cookie); - break; - default: - LOGE("Unsupported compression type %d for entry '%s'\n", - pEntry->compression, pEntry->fileName); - break; - } - - /* restore file offset */ - lseek(pArchive->fd, oldOff, SEEK_SET); - return ret; -} - -static bool crcProcessFunction(const unsigned char *data, int dataLen, - void *crc) -{ - *(unsigned long *)crc = crc32(*(unsigned long *)crc, data, dataLen); - return true; -} - -/* - * Check the CRC on this entry; return true if it is correct. - * May do other internal checks as well. - */ -bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry) -{ - unsigned long crc; - bool ret; - - crc = crc32(0L, Z_NULL, 0); - ret = mzProcessZipEntryContents(pArchive, pEntry, crcProcessFunction, - (void *)&crc); - if (!ret) { - LOGE("Can't calculate CRC for entry\n"); - return false; - } - if (crc != (unsigned long)pEntry->crc32) { - LOGW("CRC for entry %.*s (0x%08lx) != expected (0x%08lx)\n", - pEntry->fileNameLen, pEntry->fileName, crc, pEntry->crc32); - return false; - } - return true; -} - -typedef struct { - char *buf; - int bufLen; -} CopyProcessArgs; - -static bool copyProcessFunction(const unsigned char *data, int dataLen, - void *cookie) -{ - CopyProcessArgs *args = (CopyProcessArgs *)cookie; - if (dataLen <= args->bufLen) { - memcpy(args->buf, data, dataLen); - args->buf += dataLen; - args->bufLen -= dataLen; - return true; - } - return false; -} - -/* - * Read an entry into a buffer allocated by the caller. - */ -bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry, - char *buf, int bufLen) -{ - CopyProcessArgs args; - bool ret; - - args.buf = buf; - args.bufLen = bufLen; - ret = mzProcessZipEntryContents(pArchive, pEntry, copyProcessFunction, - (void *)&args); - if (!ret) { - LOGE("Can't extract entry to buffer.\n"); - return false; - } - return true; -} - -static bool writeProcessFunction(const unsigned char *data, int dataLen, - void *fd) -{ - ssize_t n = write((int)fd, data, dataLen); - if (n != dataLen) { - LOGE("Can't write %d bytes (only %ld) from zip file: %s\n", - dataLen, n, strerror(errno)); - return false; - } - return true; -} - -/* - * Uncompress "pEntry" in "pArchive" to "fd" at the current offset. - */ -bool mzExtractZipEntryToFile(const ZipArchive *pArchive, - const ZipEntry *pEntry, int fd) -{ - bool ret = mzProcessZipEntryContents(pArchive, pEntry, writeProcessFunction, - (void *)fd); - if (!ret) { - LOGE("Can't extract entry to file.\n"); - return false; - } - return true; -} - -/* Helper state to make path translation easier and less malloc-happy. - */ -typedef struct { - const char *targetDir; - const char *zipDir; - char *buf; - int targetDirLen; - int zipDirLen; - int bufLen; -} MzPathHelper; - -/* Given the values of targetDir and zipDir in the helper, - * return the target filename of the provided entry. - * The helper must be initialized first. - */ -static const char *targetEntryPath(MzPathHelper *helper, ZipEntry *pEntry) -{ - int needLen; - bool firstTime = (helper->buf == NULL); - - /* target file <-- targetDir + / + entry[zipDirLen:] - */ - needLen = helper->targetDirLen + 1 + - pEntry->fileNameLen - helper->zipDirLen + 1; - if (needLen > helper->bufLen) { - char *newBuf; - - needLen *= 2; - newBuf = (char *)realloc(helper->buf, needLen); - if (newBuf == NULL) { - return NULL; - } - helper->buf = newBuf; - helper->bufLen = needLen; - } - - /* Every path will start with the target path and a slash. - */ - if (firstTime) { - char *p = helper->buf; - memcpy(p, helper->targetDir, helper->targetDirLen); - p += helper->targetDirLen; - if (p == helper->buf || p[-1] != '/') { - helper->targetDirLen += 1; - *p++ = '/'; - } - } - - /* Replace the custom part of the path with the appropriate - * part of the entry's path. - */ - char *epath = helper->buf + helper->targetDirLen; - memcpy(epath, pEntry->fileName + helper->zipDirLen, - pEntry->fileNameLen - helper->zipDirLen); - epath += pEntry->fileNameLen - helper->zipDirLen; - *epath = '\0'; - - return helper->buf; -} - -/* - * Inflate all entries under zipDir to the directory specified by - * targetDir, which must exist and be a writable directory. - * - * The immediate children of zipDir will become the immediate - * children of targetDir; e.g., if the archive contains the entries - * - * a/b/c/one - * a/b/c/two - * a/b/c/d/three - * - * and mzExtractRecursive(a, "a/b/c", "/tmp") is called, the resulting - * files will be - * - * /tmp/one - * /tmp/two - * /tmp/d/three - * - * Returns true on success, false on failure. - */ -bool mzExtractRecursive(const ZipArchive *pArchive, - const char *zipDir, const char *targetDir, - int flags, const struct utimbuf *timestamp, - void (*callback)(const char *fn, void *), void *cookie) -{ - if (zipDir[0] == '/') { - LOGE("mzExtractRecursive(): zipDir must be a relative path.\n"); - return false; - } - if (targetDir[0] != '/') { - LOGE("mzExtractRecursive(): targetDir must be an absolute path.\n"); - return false; - } - - unsigned int zipDirLen; - char *zpath; - - zipDirLen = strlen(zipDir); - zpath = (char *)malloc(zipDirLen + 2); - if (zpath == NULL) { - LOGE("Can't allocate %d bytes for zip path\n", zipDirLen + 2); - return false; - } - /* If zipDir is empty, we'll extract the entire zip file. - * Otherwise, canonicalize the path. - */ - if (zipDirLen > 0) { - /* Make sure there's (hopefully, exactly one) slash at the - * end of the path. This way we don't need to worry about - * accidentally extracting "one/twothree" when a path like - * "one/two" is specified. - */ - memcpy(zpath, zipDir, zipDirLen); - if (zpath[zipDirLen-1] != '/') { - zpath[zipDirLen++] = '/'; - } - } - zpath[zipDirLen] = '\0'; - - /* Set up the helper structure that we'll use to assemble paths. - */ - MzPathHelper helper; - helper.targetDir = targetDir; - helper.targetDirLen = strlen(helper.targetDir); - helper.zipDir = zpath; - helper.zipDirLen = strlen(helper.zipDir); - helper.buf = NULL; - helper.bufLen = 0; - - /* Walk through the entries and extract anything whose path begins - * with zpath. -//TODO: since the entries are sorted, binary search for the first match -// and stop after the first non-match. - */ - unsigned int i; - bool seenMatch = false; - int ok = true; - for (i = 0; i < pArchive->numEntries; i++) { - ZipEntry *pEntry = pArchive->pEntries + i; - if (pEntry->fileNameLen < zipDirLen) { -//TODO: look out for a single empty directory entry that matches zpath, but -// missing the trailing slash. Most zip files seem to include -// the trailing slash, but I think it's legal to leave it off. -// e.g., zpath "a/b/", entry "a/b", with no children of the entry. - /* No chance of matching. - */ -#if SORT_ENTRIES - if (seenMatch) { - /* Since the entries are sorted, we can give up - * on the first mismatch after the first match. - */ - break; - } -#endif - continue; - } - /* If zpath is empty, this strncmp() will match everything, - * which is what we want. - */ - if (strncmp(pEntry->fileName, zpath, zipDirLen) != 0) { -#if SORT_ENTRIES - if (seenMatch) { - /* Since the entries are sorted, we can give up - * on the first mismatch after the first match. - */ - break; - } -#endif - continue; - } - /* This entry begins with zipDir, so we'll extract it. - */ - seenMatch = true; - - /* Find the target location of the entry. - */ - const char *targetFile = targetEntryPath(&helper, pEntry); - if (targetFile == NULL) { - LOGE("Can't assemble target path for \"%.*s\"\n", - pEntry->fileNameLen, pEntry->fileName); - ok = false; - break; - } - - /* With DRY_RUN set, invoke the callback but don't do anything else. - */ - if (flags & MZ_EXTRACT_DRY_RUN) { - if (callback != NULL) callback(targetFile, cookie); - continue; - } - - /* Create the file or directory. - */ -#define UNZIP_DIRMODE 0755 -#define UNZIP_FILEMODE 0644 - if (pEntry->fileName[pEntry->fileNameLen-1] == '/') { - if (!(flags & MZ_EXTRACT_FILES_ONLY)) { - int ret = dirCreateHierarchy( - targetFile, UNZIP_DIRMODE, timestamp, false); - if (ret != 0) { - LOGE("Can't create containing directory for \"%s\": %s\n", - targetFile, strerror(errno)); - ok = false; - break; - } - LOGD("Extracted dir \"%s\"\n", targetFile); - } - } else { - /* This is not a directory. First, make sure that - * the containing directory exists. - */ - int ret = dirCreateHierarchy( - targetFile, UNZIP_DIRMODE, timestamp, true); - if (ret != 0) { - LOGE("Can't create containing directory for \"%s\": %s\n", - targetFile, strerror(errno)); - ok = false; - break; - } - - /* With FILES_ONLY set, we need to ignore metadata entirely, - * so treat symlinks as regular files. - */ - if (!(flags & MZ_EXTRACT_FILES_ONLY) && mzIsZipEntrySymlink(pEntry)) { - /* The entry is a symbolic link. - * The relative target of the symlink is in the - * data section of this entry. - */ - if (pEntry->uncompLen == 0) { - LOGE("Symlink entry \"%s\" has no target\n", - targetFile); - ok = false; - break; - } - char *linkTarget = malloc(pEntry->uncompLen + 1); - if (linkTarget == NULL) { - ok = false; - break; - } - ok = mzReadZipEntry(pArchive, pEntry, linkTarget, - pEntry->uncompLen); - if (!ok) { - LOGE("Can't read symlink target for \"%s\"\n", - targetFile); - free(linkTarget); - break; - } - linkTarget[pEntry->uncompLen] = '\0'; - - /* Make the link. - */ - ret = symlink(linkTarget, targetFile); - if (ret != 0) { - LOGE("Can't symlink \"%s\" to \"%s\": %s\n", - targetFile, linkTarget, strerror(errno)); - free(linkTarget); - ok = false; - break; - } - LOGD("Extracted symlink \"%s\" -> \"%s\"\n", - targetFile, linkTarget); - free(linkTarget); - } else { - /* The entry is a regular file. - * Open the target for writing. - */ - int fd = creat(targetFile, UNZIP_FILEMODE); - if (fd < 0) { - LOGE("Can't create target file \"%s\": %s\n", - targetFile, strerror(errno)); - ok = false; - break; - } - - bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd); - close(fd); - if (!ok) { - LOGE("Error extracting \"%s\"\n", targetFile); - ok = false; - break; - } - - if (timestamp != NULL && utime(targetFile, timestamp)) { - LOGE("Error touching \"%s\"\n", targetFile); - ok = false; - break; - } - - LOGD("Extracted file \"%s\"\n", targetFile); - } - } - - if (callback != NULL) callback(targetFile, cookie); - } - - free(helper.buf); - free(zpath); - - return ok; -} diff --git a/minzip/Zip.h b/minzip/Zip.h deleted file mode 100644 index 1c1df2f..0000000 --- a/minzip/Zip.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Simple Zip archive support. - */ -#ifndef _MINZIP_ZIP -#define _MINZIP_ZIP - -#include "inline_magic.h" - -#include <stdlib.h> -#include <utime.h> - -#include "Hash.h" -#include "SysUtil.h" - -/* - * One entry in the Zip archive. Treat this as opaque -- use accessors below. - * - * TODO: we're now keeping the pages mapped so we don't have to copy the - * filename. We can change the accessors to retrieve the various pieces - * directly from the source file instead of copying them out, for a very - * slight speed hit and a modest reduction in memory usage. - */ -typedef struct ZipEntry { - unsigned int fileNameLen; - const char* fileName; // not null-terminated - long offset; - long compLen; - long uncompLen; - int compression; - long modTime; - long crc32; - int versionMadeBy; - long externalFileAttributes; -} ZipEntry; - -/* - * One Zip archive. Treat as opaque. - */ -typedef struct ZipArchive { - int fd; - unsigned int numEntries; - ZipEntry* pEntries; - HashTable* pHash; // maps file name to ZipEntry - MemMapping map; -} ZipArchive; - -/* - * Represents a non-NUL-terminated string, - * which is how entry names are stored. - */ -typedef struct { - const char *str; - size_t len; -} UnterminatedString; - -/* - * Open a Zip archive. - * - * On success, returns 0 and populates "pArchive". Returns nonzero errno - * value on failure. - */ -int mzOpenZipArchive(const char* fileName, ZipArchive* pArchive); - -/* - * Close archive, releasing resources associated with it. - * - * Depending on the implementation this could unmap pages used by classes - * stored in a Jar. This should only be done after unloading classes. - */ -void mzCloseZipArchive(ZipArchive* pArchive); - - -/* - * Find an entry in the Zip archive, by name. - */ -const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive, - const char* entryName); - -/* - * Get the number of entries in the Zip archive. - */ -INLINE unsigned int mzZipEntryCount(const ZipArchive* pArchive) { - return pArchive->numEntries; -} - -/* - * Get an entry by index. Returns NULL if the index is out-of-bounds. - */ -INLINE const ZipEntry* -mzGetZipEntryAt(const ZipArchive* pArchive, unsigned int index) -{ - if (index < pArchive->numEntries) { - return pArchive->pEntries + index; - } - return NULL; -} - -/* - * Get the index number of an entry in the archive. - */ -INLINE unsigned int -mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) { - return pEntry - pArchive->pEntries; -} - -/* - * Simple accessors. - */ -INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) { - UnterminatedString ret; - ret.str = pEntry->fileName; - ret.len = pEntry->fileNameLen; - return ret; -} -INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) { - return pEntry->offset; -} -INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) { - return pEntry->uncompLen; -} -INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) { - return pEntry->modTime; -} -INLINE long mzGetZipEntryCrc32(const ZipEntry* pEntry) { - return pEntry->crc32; -} -bool mzIsZipEntrySymlink(const ZipEntry* pEntry); - - -/* - * Type definition for the callback function used by - * mzProcessZipEntryContents(). - */ -typedef bool (*ProcessZipEntryContentsFunction)(const unsigned char *data, - int dataLen, void *cookie); - -/* - * Stream the uncompressed data through the supplied function, - * passing cookie to it each time it gets called. processFunction - * may be called more than once. - * - * If processFunction returns false, the operation is abandoned and - * mzProcessZipEntryContents() immediately returns false. - * - * This is useful for calculating the hash of an entry's uncompressed contents. - */ -bool mzProcessZipEntryContents(const ZipArchive *pArchive, - const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, - void *cookie); - -/* - * Read an entry into a buffer allocated by the caller. - */ -bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry, - char* buf, int bufLen); - -/* - * Check the CRC on this entry; return true if it is correct. - * May do other internal checks as well. - */ -bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry); - -/* - * Inflate and write an entry to a file. - */ -bool mzExtractZipEntryToFile(const ZipArchive *pArchive, - const ZipEntry *pEntry, int fd); - -/* - * Inflate all entries under zipDir to the directory specified by - * targetDir, which must exist and be a writable directory. - * - * The immediate children of zipDir will become the immediate - * children of targetDir; e.g., if the archive contains the entries - * - * a/b/c/one - * a/b/c/two - * a/b/c/d/three - * - * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting - * files will be - * - * /tmp/one - * /tmp/two - * /tmp/d/three - * - * flags is zero or more of the following: - * - * MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks - * MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback - * - * If timestamp is non-NULL, file timestamps will be set accordingly. - * - * If callback is non-NULL, it will be invoked with each unpacked file. - * - * Returns true on success, false on failure. - */ -enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 }; -bool mzExtractRecursive(const ZipArchive *pArchive, - const char *zipDir, const char *targetDir, - int flags, const struct utimbuf *timestamp, - void (*callback)(const char *fn, void*), void *cookie); - -#endif /*_MINZIP_ZIP*/ diff --git a/minzip/inline_magic.h b/minzip/inline_magic.h deleted file mode 100644 index 8c185e1..0000000 --- a/minzip/inline_magic.h +++ /dev/null @@ -1,26 +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 MINZIP_INLINE_MAGIC_H_ -#define MINZIP_INLINE_MAGIC_H_ - -#ifndef MINZIP_GENERATE_INLINES -#define INLINE extern __inline__ -#else -#define INLINE -#endif - -#endif // MINZIP_INLINE_MAGIC_H_ diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk deleted file mode 100644 index 1a75423..0000000 --- a/mtdutils/Android.mk +++ /dev/null @@ -1,23 +0,0 @@ -ifneq ($(TARGET_SIMULATOR),true) -ifeq ($(TARGET_ARCH),arm) - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - mtdutils.c \ - mounts.c - -LOCAL_MODULE := libmtdutils - -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := flash_image.c -LOCAL_MODULE := flash_image -LOCAL_STATIC_LIBRARIES := libmtdutils -LOCAL_SHARED_LIBRARIES := libcutils libc -include $(BUILD_EXECUTABLE) - -endif # TARGET_ARCH == arm -endif # !TARGET_SIMULATOR diff --git a/mtdutils/flash_image.c b/mtdutils/flash_image.c deleted file mode 100644 index c776876..0000000 --- a/mtdutils/flash_image.c +++ /dev/null @@ -1,140 +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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "cutils/log.h" -#include "mtdutils.h" - -#define LOG_TAG "flash_image" - -#define HEADER_SIZE 2048 // size of header to compare for equality - -void die(const char *msg, ...) { - int err = errno; - va_list args; - va_start(args, msg); - char buf[1024]; - vsnprintf(buf, sizeof(buf), msg, args); - va_end(args); - - if (err != 0) { - strlcat(buf, ": ", sizeof(buf)); - strlcat(buf, strerror(err), sizeof(buf)); - } - - fprintf(stderr, "%s\n", buf); - LOGE("%s\n", buf); - exit(1); -} - -/* Read an image file and write it to a flash partition. */ - -int main(int argc, char **argv) { - const MtdPartition *ptn; - MtdWriteContext *write; - void *data; - unsigned sz; - - if (argc != 3) { - fprintf(stderr, "usage: %s partition file.img\n", argv[0]); - return 2; - } - - if (mtd_scan_partitions() <= 0) die("error scanning partitions"); - const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); - if (partition == NULL) die("can't find %s partition", argv[1]); - - // If the first part of the file matches the partition, skip writing - - int fd = open(argv[2], O_RDONLY); - if (fd < 0) die("error opening %s", argv[2]); - - char header[HEADER_SIZE]; - int headerlen = read(fd, header, sizeof(header)); - if (headerlen <= 0) die("error reading %s header", argv[2]); - - MtdReadContext *in = mtd_read_partition(partition); - if (in == NULL) { - LOGW("error opening %s: %s\n", argv[1], strerror(errno)); - // just assume it needs re-writing - } else { - char check[HEADER_SIZE]; - int checklen = mtd_read_data(in, check, sizeof(check)); - if (checklen <= 0) { - LOGW("error reading %s: %s\n", argv[1], strerror(errno)); - // just assume it needs re-writing - } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { - LOGI("header is the same, not flashing %s\n", argv[1]); - return 0; - } - mtd_read_close(in); - } - - // Skip the header (we'll come back to it), write everything else - LOGI("flashing %s from %s\n", argv[1], argv[2]); - - MtdWriteContext *out = mtd_write_partition(partition); - if (out == NULL) die("error writing %s", argv[1]); - - char buf[HEADER_SIZE]; - memset(buf, 0, headerlen); - int wrote = mtd_write_data(out, buf, headerlen); - if (wrote != headerlen) die("error writing %s", argv[1]); - - int len; - while ((len = read(fd, buf, sizeof(buf))) > 0) { - wrote = mtd_write_data(out, buf, len); - if (wrote != len) die("error writing %s", argv[1]); - } - if (len < 0) die("error reading %s", argv[2]); - - if (mtd_write_close(out)) die("error closing %s", argv[1]); - - // Now come back and write the header last - - out = mtd_write_partition(partition); - if (out == NULL) die("error re-opening %s", argv[1]); - - wrote = mtd_write_data(out, header, headerlen); - if (wrote != headerlen) die("error re-writing %s", argv[1]); - - // Need to write a complete block, so write the rest of the first block - size_t block_size; - if (mtd_partition_info(partition, NULL, &block_size, NULL)) - die("error getting %s block size", argv[1]); - - if (lseek(fd, headerlen, SEEK_SET) != headerlen) - die("error rewinding %s", argv[2]); - - int left = block_size - headerlen; - while (left < 0) left += block_size; - while (left > 0) { - len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); - if (len <= 0) die("error reading %s", argv[2]); - if (mtd_write_data(out, buf, len) != len) - die("error writing %s", argv[1]); - left -= len; - } - - if (mtd_write_close(out)) die("error closing %s", argv[1]); - return 0; -} diff --git a/mtdutils/mounts.c b/mtdutils/mounts.c deleted file mode 100644 index 2ab3ff6..0000000 --- a/mtdutils/mounts.c +++ /dev/null @@ -1,214 +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 <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mount.h> - -#include "mounts.h" - -struct MountedVolume { - const char *device; - const char *mount_point; - const char *filesystem; - const char *flags; -}; - -typedef struct { - MountedVolume *volumes; - int volumes_allocd; - int volume_count; -} MountsState; - -static MountsState g_mounts_state = { - NULL, // volumes - 0, // volumes_allocd - 0 // volume_count -}; - -static inline void -free_volume_internals(const MountedVolume *volume, int zero) -{ - free((char *)volume->device); - free((char *)volume->mount_point); - free((char *)volume->filesystem); - free((char *)volume->flags); - if (zero) { - memset((void *)volume, 0, sizeof(*volume)); - } -} - -#define PROC_MOUNTS_FILENAME "/proc/mounts" - -int -scan_mounted_volumes() -{ - char buf[2048]; - const char *bufp; - int fd; - ssize_t nbytes; - - if (g_mounts_state.volumes == NULL) { - const int numv = 32; - MountedVolume *volumes = malloc(numv * sizeof(*volumes)); - if (volumes == NULL) { - errno = ENOMEM; - return -1; - } - g_mounts_state.volumes = volumes; - g_mounts_state.volumes_allocd = numv; - memset(volumes, 0, numv * sizeof(*volumes)); - } else { - /* Free the old volume strings. - */ - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - free_volume_internals(&g_mounts_state.volumes[i], 1); - } - } - g_mounts_state.volume_count = 0; - - /* Open and read the file contents. - */ - fd = open(PROC_MOUNTS_FILENAME, O_RDONLY); - if (fd < 0) { - goto bail; - } - nbytes = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (nbytes < 0) { - goto bail; - } - buf[nbytes] = '\0'; - - /* Parse the contents of the file, which looks like: - * - * # cat /proc/mounts - * rootfs / rootfs rw 0 0 - * /dev/pts /dev/pts devpts rw 0 0 - * /proc /proc proc rw 0 0 - * /sys /sys sysfs rw 0 0 - * /dev/block/mtdblock4 /system yaffs2 rw,nodev,noatime,nodiratime 0 0 - * /dev/block/mtdblock5 /data yaffs2 rw,nodev,noatime,nodiratime 0 0 - * /dev/block/mmcblk0p1 /sdcard vfat rw,sync,dirsync,fmask=0000,dmask=0000,codepage=cp437,iocharset=iso8859-1,utf8 0 0 - * - * The zeroes at the end are dummy placeholder fields to make the - * output match Linux's /etc/mtab, but don't represent anything here. - */ - bufp = buf; - while (nbytes > 0) { - char device[64]; - char mount_point[64]; - char filesystem[64]; - char flags[128]; - int matches; - - /* %as is a gnu extension that malloc()s a string for each field. - */ - matches = sscanf(bufp, "%63s %63s %63s %127s", - device, mount_point, filesystem, flags); - - if (matches == 4) { - device[sizeof(device)-1] = '\0'; - mount_point[sizeof(mount_point)-1] = '\0'; - filesystem[sizeof(filesystem)-1] = '\0'; - flags[sizeof(flags)-1] = '\0'; - - MountedVolume *v = - &g_mounts_state.volumes[g_mounts_state.volume_count++]; - v->device = strdup(device); - v->mount_point = strdup(mount_point); - v->filesystem = strdup(filesystem); - v->flags = strdup(flags); - } else { -printf("matches was %d on <<%.40s>>\n", matches, bufp); - } - - /* Eat the line. - */ - while (nbytes > 0 && *bufp != '\n') { - bufp++; - nbytes--; - } - if (nbytes > 0) { - bufp++; - nbytes--; - } - } - - return 0; - -bail: -//TODO: free the strings we've allocated. - g_mounts_state.volume_count = 0; - return -1; -} - -const MountedVolume * -find_mounted_volume_by_device(const char *device) -{ - if (g_mounts_state.volumes != NULL) { - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - MountedVolume *v = &g_mounts_state.volumes[i]; - /* May be null if it was unmounted and we haven't rescanned. - */ - if (v->device != NULL) { - if (strcmp(v->device, device) == 0) { - return v; - } - } - } - } - return NULL; -} - -const MountedVolume * -find_mounted_volume_by_mount_point(const char *mount_point) -{ - if (g_mounts_state.volumes != NULL) { - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - MountedVolume *v = &g_mounts_state.volumes[i]; - /* May be null if it was unmounted and we haven't rescanned. - */ - if (v->mount_point != NULL) { - if (strcmp(v->mount_point, mount_point) == 0) { - return v; - } - } - } - } - return NULL; -} - -int -unmount_mounted_volume(const MountedVolume *volume) -{ - /* Intentionally pass NULL to umount if the caller tries - * to unmount a volume they already unmounted using this - * function. - */ - int ret = umount(volume->mount_point); - if (ret == 0) { - free_volume_internals(volume, 1); - return 0; - } - return ret; -} diff --git a/mtdutils/mounts.h b/mtdutils/mounts.h deleted file mode 100644 index 2e2765a..0000000 --- a/mtdutils/mounts.h +++ /dev/null @@ -1,31 +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 MTDUTILS_MOUNTS_H_ -#define MTDUTILS_MOUNTS_H_ - -typedef struct MountedVolume MountedVolume; - -int scan_mounted_volumes(void); - -const MountedVolume *find_mounted_volume_by_device(const char *device); - -const MountedVolume * -find_mounted_volume_by_mount_point(const char *mount_point); - -int unmount_mounted_volume(const MountedVolume *volume); - -#endif // MTDUTILS_MOUNTS_H_ diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c deleted file mode 100644 index 2b0106f..0000000 --- a/mtdutils/mtdutils.c +++ /dev/null @@ -1,510 +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 <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mount.h> // for _IOW, _IOR, mount() -#include <sys/stat.h> -#include <mtd/mtd-user.h> -#undef NDEBUG -#include <assert.h> - -#include "mtdutils.h" - -struct MtdPartition { - int device_index; - unsigned int size; - unsigned int erase_size; - char *name; -}; - -struct MtdReadContext { - const MtdPartition *partition; - char *buffer; - size_t consumed; - int fd; -}; - -struct MtdWriteContext { - const MtdPartition *partition; - char *buffer; - size_t stored; - int fd; -}; - -typedef struct { - MtdPartition *partitions; - int partitions_allocd; - int partition_count; -} MtdState; - -static MtdState g_mtd_state = { - NULL, // partitions - 0, // partitions_allocd - -1 // partition_count -}; - -#define MTD_PROC_FILENAME "/proc/mtd" - -int -mtd_scan_partitions() -{ - char buf[2048]; - const char *bufp; - int fd; - int i; - ssize_t nbytes; - - if (g_mtd_state.partitions == NULL) { - const int nump = 32; - MtdPartition *partitions = malloc(nump * sizeof(*partitions)); - if (partitions == NULL) { - errno = ENOMEM; - return -1; - } - g_mtd_state.partitions = partitions; - g_mtd_state.partitions_allocd = nump; - memset(partitions, 0, nump * sizeof(*partitions)); - } - g_mtd_state.partition_count = 0; - - /* Initialize all of the entries to make things easier later. - * (Lets us handle sparsely-numbered partitions, which - * may not even be possible.) - */ - for (i = 0; i < g_mtd_state.partitions_allocd; i++) { - MtdPartition *p = &g_mtd_state.partitions[i]; - if (p->name != NULL) { - free(p->name); - p->name = NULL; - } - p->device_index = -1; - } - - /* Open and read the file contents. - */ - fd = open(MTD_PROC_FILENAME, O_RDONLY); - if (fd < 0) { - goto bail; - } - nbytes = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (nbytes < 0) { - goto bail; - } - buf[nbytes] = '\0'; - - /* Parse the contents of the file, which looks like: - * - * # cat /proc/mtd - * dev: size erasesize name - * mtd0: 00080000 00020000 "bootloader" - * mtd1: 00400000 00020000 "mfg_and_gsm" - * mtd2: 00400000 00020000 "0000000c" - * mtd3: 00200000 00020000 "0000000d" - * mtd4: 04000000 00020000 "system" - * mtd5: 03280000 00020000 "userdata" - */ - bufp = buf; - while (nbytes > 0) { - int mtdnum, mtdsize, mtderasesize; - int matches; - char mtdname[64]; - mtdname[0] = '\0'; - mtdnum = -1; - - matches = sscanf(bufp, "mtd%d: %x %x \"%63[^\"]", - &mtdnum, &mtdsize, &mtderasesize, mtdname); - /* This will fail on the first line, which just contains - * column headers. - */ - if (matches == 4) { - MtdPartition *p = &g_mtd_state.partitions[mtdnum]; - p->device_index = mtdnum; - p->size = mtdsize; - p->erase_size = mtderasesize; - p->name = strdup(mtdname); - if (p->name == NULL) { - errno = ENOMEM; - goto bail; - } - g_mtd_state.partition_count++; - } - - /* Eat the line. - */ - while (nbytes > 0 && *bufp != '\n') { - bufp++; - nbytes--; - } - if (nbytes > 0) { - bufp++; - nbytes--; - } - } - - return g_mtd_state.partition_count; - -bail: - // keep "partitions" around so we can free the names on a rescan. - g_mtd_state.partition_count = -1; - return -1; -} - -const MtdPartition * -mtd_find_partition_by_name(const char *name) -{ - if (g_mtd_state.partitions != NULL) { - int i; - for (i = 0; i < g_mtd_state.partitions_allocd; i++) { - MtdPartition *p = &g_mtd_state.partitions[i]; - if (p->device_index >= 0 && p->name != NULL) { - if (strcmp(p->name, name) == 0) { - return p; - } - } - } - } - return NULL; -} - -int -mtd_mount_partition(const MtdPartition *partition, const char *mount_point, - const char *filesystem, int read_only) -{ - const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME; - char devname[64]; - int rv = -1; - - sprintf(devname, "/dev/block/mtdblock%d", partition->device_index); - if (!read_only) { - rv = mount(devname, mount_point, filesystem, flags, NULL); - } - if (read_only || rv < 0) { - rv = mount(devname, mount_point, filesystem, flags | MS_RDONLY, 0); - if (rv < 0) { - printf("Failed to mount %s on %s: %s\n", - devname, mount_point, strerror(errno)); - } else { - printf("Mount %s on %s read-only\n", devname, mount_point); - } - } -#if 1 //TODO: figure out why this is happening; remove include of stat.h - if (rv >= 0) { - /* For some reason, the x bits sometimes aren't set on the root - * of mounted volumes. - */ - struct stat st; - rv = stat(mount_point, &st); - if (rv < 0) { - return rv; - } - mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH; - if (new_mode != st.st_mode) { -printf("Fixing execute permissions for %s\n", mount_point); - rv = chmod(mount_point, new_mode); - if (rv < 0) { - printf("Couldn't fix permissions for %s: %s\n", - mount_point, strerror(errno)); - } - } - } -#endif - return rv; -} - -int -mtd_partition_info(const MtdPartition *partition, - size_t *total_size, size_t *erase_size, size_t *write_size) -{ - char mtddevname[32]; - sprintf(mtddevname, "/dev/mtd/mtd%d", partition->device_index); - int fd = open(mtddevname, O_RDONLY); - if (fd < 0) return -1; - - struct mtd_info_user mtd_info; - int ret = ioctl(fd, MEMGETINFO, &mtd_info); - close(fd); - if (ret < 0) return -1; - - if (total_size != NULL) *total_size = mtd_info.size; - if (erase_size != NULL) *erase_size = mtd_info.erasesize; - if (write_size != NULL) *write_size = mtd_info.writesize; - return 0; -} - -MtdReadContext *mtd_read_partition(const MtdPartition *partition) -{ - MtdReadContext *ctx = (MtdReadContext*) malloc(sizeof(MtdReadContext)); - if (ctx == NULL) return NULL; - - ctx->buffer = malloc(partition->erase_size); - if (ctx->buffer == NULL) { - free(ctx); - return NULL; - } - - char mtddevname[32]; - sprintf(mtddevname, "/dev/mtd/mtd%d", partition->device_index); - ctx->fd = open(mtddevname, O_RDONLY); - if (ctx->fd < 0) { - free(ctx); - free(ctx->buffer); - return NULL; - } - - ctx->partition = partition; - ctx->consumed = partition->erase_size; - return ctx; -} - -static int read_block(const MtdPartition *partition, int fd, char *data) -{ - struct mtd_ecc_stats before, after; - if (ioctl(fd, ECCGETSTATS, &before)) { - fprintf(stderr, "mtd: ECCGETSTATS error (%s)\n", strerror(errno)); - return -1; - } - - off_t pos = lseek(fd, 0, SEEK_CUR); - ssize_t size = partition->erase_size; - while (pos + size <= (int) partition->size) { - if (lseek(fd, pos, SEEK_SET) != pos || read(fd, data, size) != size) { - fprintf(stderr, "mtd: read error at 0x%08lx (%s)\n", - pos, strerror(errno)); - } else if (ioctl(fd, ECCGETSTATS, &after)) { - fprintf(stderr, "mtd: ECCGETSTATS error (%s)\n", strerror(errno)); - return -1; - } else if (after.failed != before.failed) { - fprintf(stderr, "mtd: ECC errors (%d soft, %d hard) at 0x%08lx\n", - after.corrected - before.corrected, - after.failed - before.failed, pos); - } else { - return 0; // Success! - } - - pos += partition->erase_size; - } - - errno = ENOSPC; - return -1; -} - -ssize_t mtd_read_data(MtdReadContext *ctx, char *data, size_t len) -{ - ssize_t read = 0; - while (read < (int) len) { - if (ctx->consumed < ctx->partition->erase_size) { - size_t avail = ctx->partition->erase_size - ctx->consumed; - size_t copy = len - read < avail ? len - read : avail; - memcpy(data + read, ctx->buffer + ctx->consumed, copy); - ctx->consumed += copy; - read += copy; - } - - // Read complete blocks directly into the user's buffer - while (ctx->consumed == ctx->partition->erase_size && - len - read >= ctx->partition->erase_size) { - if (read_block(ctx->partition, ctx->fd, data + read)) return -1; - read += ctx->partition->erase_size; - } - - // Read the next block into the buffer - if (ctx->consumed == ctx->partition->erase_size && read < (int) len) { - if (read_block(ctx->partition, ctx->fd, ctx->buffer)) return -1; - ctx->consumed = 0; - } - } - - return read; -} - -void mtd_read_close(MtdReadContext *ctx) -{ - close(ctx->fd); - free(ctx->buffer); - free(ctx); -} - -MtdWriteContext *mtd_write_partition(const MtdPartition *partition) -{ - MtdWriteContext *ctx = (MtdWriteContext*) malloc(sizeof(MtdWriteContext)); - if (ctx == NULL) return NULL; - - ctx->buffer = malloc(partition->erase_size); - if (ctx->buffer == NULL) { - free(ctx); - return NULL; - } - - char mtddevname[32]; - sprintf(mtddevname, "/dev/mtd/mtd%d", partition->device_index); - ctx->fd = open(mtddevname, O_RDWR); - if (ctx->fd < 0) { - free(ctx->buffer); - free(ctx); - return NULL; - } - - ctx->partition = partition; - ctx->stored = 0; - return ctx; -} - -static int write_block(const MtdPartition *partition, int fd, const char *data) -{ - off_t pos = lseek(fd, 0, SEEK_CUR); - if (pos == (off_t) -1) return 1; - - ssize_t size = partition->erase_size; - while (pos + size <= (int) partition->size) { - loff_t bpos = pos; - if (ioctl(fd, MEMGETBADBLOCK, &bpos) > 0) { - fprintf(stderr, "mtd: not writing bad block at 0x%08lx\n", pos); - pos += partition->erase_size; - continue; // Don't try to erase known factory-bad blocks. - } - - struct erase_info_user erase_info; - erase_info.start = pos; - erase_info.length = size; - int retry; - for (retry = 0; retry < 2; ++retry) { - if (ioctl(fd, MEMERASE, &erase_info) < 0) { - fprintf(stderr, "mtd: erase failure at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - if (lseek(fd, pos, SEEK_SET) != pos || - write(fd, data, size) != size) { - fprintf(stderr, "mtd: write error at 0x%08lx (%s)\n", - pos, strerror(errno)); - } - - char verify[size]; - if (lseek(fd, pos, SEEK_SET) != pos || - read(fd, verify, size) != size) { - fprintf(stderr, "mtd: re-read error at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - if (memcmp(data, verify, size) != 0) { - fprintf(stderr, "mtd: verification error at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - - if (retry > 0) { - fprintf(stderr, "mtd: wrote block after %d retries\n", retry); - } - return 0; // Success! - } - - // Try to erase it once more as we give up on this block - fprintf(stderr, "mtd: skipping write block at 0x%08lx\n", pos); - ioctl(fd, MEMERASE, &erase_info); - pos += partition->erase_size; - } - - // Ran out of space on the device - errno = ENOSPC; - return -1; -} - -ssize_t mtd_write_data(MtdWriteContext *ctx, const char *data, size_t len) -{ - size_t wrote = 0; - while (wrote < len) { - // Coalesce partial writes into complete blocks - if (ctx->stored > 0 || len - wrote < ctx->partition->erase_size) { - size_t avail = ctx->partition->erase_size - ctx->stored; - size_t copy = len - wrote < avail ? len - wrote : avail; - memcpy(ctx->buffer + ctx->stored, data + wrote, copy); - ctx->stored += copy; - wrote += copy; - } - - // If a complete block was accumulated, write it - if (ctx->stored == ctx->partition->erase_size) { - if (write_block(ctx->partition, ctx->fd, ctx->buffer)) return -1; - ctx->stored = 0; - } - - // Write complete blocks directly from the user's buffer - while (ctx->stored == 0 && len - wrote >= ctx->partition->erase_size) { - if (write_block(ctx->partition, ctx->fd, data + wrote)) return -1; - wrote += ctx->partition->erase_size; - } - } - - return wrote; -} - -off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks) -{ - // Zero-pad and write any pending data to get us to a block boundary - if (ctx->stored > 0) { - size_t zero = ctx->partition->erase_size - ctx->stored; - memset(ctx->buffer + ctx->stored, 0, zero); - if (write_block(ctx->partition, ctx->fd, ctx->buffer)) return -1; - ctx->stored = 0; - } - - off_t pos = lseek(ctx->fd, 0, SEEK_CUR); - if ((off_t) pos == (off_t) -1) return pos; - - const int total = (ctx->partition->size - pos) / ctx->partition->erase_size; - if (blocks < 0) blocks = total; - if (blocks > total) { - errno = ENOSPC; - return -1; - } - - // Erase the specified number of blocks - while (blocks-- > 0) { - loff_t bpos = pos; - if (ioctl(ctx->fd, MEMGETBADBLOCK, &bpos) > 0) { - fprintf(stderr, "mtd: not erasing bad block at 0x%08lx\n", pos); - pos += ctx->partition->erase_size; - continue; // Don't try to erase known factory-bad blocks. - } - - struct erase_info_user erase_info; - erase_info.start = pos; - erase_info.length = ctx->partition->erase_size; - if (ioctl(ctx->fd, MEMERASE, &erase_info) < 0) { - fprintf(stderr, "mtd: erase failure at 0x%08lx\n", pos); - } - pos += ctx->partition->erase_size; - } - - return pos; -} - -int mtd_write_close(MtdWriteContext *ctx) -{ - int r = 0; - // Make sure any pending data gets written - if (mtd_erase_blocks(ctx, 0) == (off_t) -1) r = -1; - if (close(ctx->fd)) r = -1; - free(ctx->buffer); - free(ctx); - return r; -} diff --git a/mtdutils/mtdutils.h b/mtdutils/mtdutils.h deleted file mode 100644 index 8d2cb56..0000000 --- a/mtdutils/mtdutils.h +++ /dev/null @@ -1,54 +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 MTDUTILS_H_ -#define MTDUTILS_H_ - -#include <sys/types.h> // for size_t, etc. - -typedef struct MtdPartition MtdPartition; - -int mtd_scan_partitions(void); - -const MtdPartition *mtd_find_partition_by_name(const char *name); - -/* mount_point is like "/system" - * filesystem is like "yaffs2" - */ -int mtd_mount_partition(const MtdPartition *partition, const char *mount_point, - const char *filesystem, int read_only); - -/* get the partition and the minimum erase/write block size. NULL is ok. - */ -int mtd_partition_info(const MtdPartition *partition, - size_t *total_size, size_t *erase_size, size_t *write_size); - -/* read or write raw data from a partition, starting at the beginning. - * skips bad blocks as best we can. - */ -typedef struct MtdReadContext MtdReadContext; -typedef struct MtdWriteContext MtdWriteContext; - -MtdReadContext *mtd_read_partition(const MtdPartition *); -ssize_t mtd_read_data(MtdReadContext *, char *data, size_t data_len); -void mtd_read_close(MtdReadContext *); - -MtdWriteContext *mtd_write_partition(const MtdPartition *); -ssize_t mtd_write_data(MtdWriteContext *, const char *data, size_t data_len); -off_t mtd_erase_blocks(MtdWriteContext *, int blocks); /* 0 ok, -1 for all */ -int mtd_write_close(MtdWriteContext *); - -#endif // MTDUTILS_H_ diff --git a/recovery.c b/recovery.c deleted file mode 100644 index 221ee29..0000000 --- a/recovery.c +++ /dev/null @@ -1,471 +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 <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <limits.h> -#include <linux/input.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/reboot.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#include "bootloader.h" -#include "commands.h" -#include "common.h" -#include "cutils/properties.h" -#include "firmware.h" -#include "install.h" -#include "minui/minui.h" -#include "minzip/DirUtil.h" -#include "roots.h" - -static const struct option OPTIONS[] = { - { "send_intent", required_argument, NULL, 's' }, - { "update_package", required_argument, NULL, 'u' }, - { "wipe_data", no_argument, NULL, 'w' }, - { "wipe_cache", no_argument, NULL, 'c' }, -}; - -static const char *COMMAND_FILE = "CACHE:recovery/command"; -static const char *INTENT_FILE = "CACHE:recovery/intent"; -static const char *LOG_FILE = "CACHE:recovery/log"; -static const char *SDCARD_PACKAGE_FILE = "SDCARD:update.zip"; -static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log"; - -/* - * The recovery tool communicates with the main system through /cache files. - * /cache/recovery/command - INPUT - command line for tool, one arg per line - * /cache/recovery/log - OUTPUT - combined log file from recovery run(s) - * /cache/recovery/intent - OUTPUT - intent that was passed in - * - * The arguments which may be supplied in the recovery.command file: - * --send_intent=anystring - write the text out to recovery.intent - * --update_package=root:path - verify install an OTA package file - * --wipe_data - erase user data (and cache), then reboot - * --wipe_cache - wipe cache (but not user data), then reboot - * - * After completing, we remove /cache/recovery/command and reboot. - * Arguments may also be supplied in the bootloader control block (BCB). - * These important scenarios must be safely restartable at any point: - * - * FACTORY RESET - * 1. user selects "factory reset" - * 2. main system writes "--wipe_data" to /cache/recovery/command - * 3. main system reboots into recovery - * 4. get_args() writes BCB with "boot-recovery" and "--wipe_data" - * -- after this, rebooting will restart the erase -- - * 5. erase_root() reformats /data - * 6. erase_root() reformats /cache - * 7. finish_recovery() erases BCB - * -- after this, rebooting will restart the main system -- - * 8. main() calls reboot() to boot main system - * - * OTA INSTALL - * 1. main system downloads OTA package to /cache/some-filename.zip - * 2. main system writes "--update_package=CACHE:some-filename.zip" - * 3. main system reboots into recovery - * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..." - * -- after this, rebooting will attempt to reinstall the update -- - * 5. install_package() attempts to install the update - * NOTE: the package install must itself be restartable from any point - * 6. finish_recovery() erases BCB - * -- after this, rebooting will (try to) restart the main system -- - * 7. ** if install failed ** - * 7a. prompt_and_wait() shows an error icon and waits for the user - * 7b; the user reboots (pulling the battery, etc) into the main system - * 8. main() calls maybe_install_firmware_update() - * ** if the update contained radio/hboot firmware **: - * 8a. m_i_f_u() writes BCB with "boot-recovery" and "--wipe_cache" - * -- after this, rebooting will reformat cache & restart main system -- - * 8b. m_i_f_u() writes firmware image into raw cache partition - * 8c. m_i_f_u() writes BCB with "update-radio/hboot" and "--wipe_cache" - * -- after this, rebooting will attempt to reinstall firmware -- - * 8d. bootloader tries to flash firmware - * 8e. bootloader writes BCB with "boot-recovery" (keeping "--wipe_cache") - * -- after this, rebooting will reformat cache & restart main system -- - * 8f. erase_root() reformats /cache - * 8g. finish_recovery() erases BCB - * -- after this, rebooting will (try to) restart the main system -- - * 9. main() calls reboot() to boot main system - */ - -static const int MAX_ARG_LENGTH = 4096; -static const int MAX_ARGS = 100; - -// open a file given in root:path format, mounting partitions as necessary -static FILE* -fopen_root_path(const char *root_path, const char *mode) { - if (ensure_root_path_mounted(root_path) != 0) { - LOGE("Can't mount %s\n", root_path); - return NULL; - } - - char path[PATH_MAX] = ""; - if (translate_root_path(root_path, path, sizeof(path)) == NULL) { - LOGE("Bad path %s\n", root_path); - return NULL; - } - - // When writing, try to create the containing directory, if necessary. - // Use generous permissions, the system (init.rc) will reset them. - if (strchr("wa", mode[0])) dirCreateHierarchy(path, 0777, NULL, 1); - - FILE *fp = fopen(path, mode); - if (fp == NULL) LOGE("Can't open %s\n", path); - return fp; -} - -// close a file, log an error if the error indicator is set -static void -check_and_fclose(FILE *fp, const char *name) { - fflush(fp); - if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno)); - fclose(fp); -} - -// command line args come from, in decreasing precedence: -// - the actual command line -// - the bootloader control block (one per line, after "recovery") -// - the contents of COMMAND_FILE (one per line) -static void -get_args(int *argc, char ***argv) { - struct bootloader_message boot; - memset(&boot, 0, sizeof(boot)); - get_bootloader_message(&boot); // this may fail, leaving a zeroed structure - - if (boot.command[0] != 0 && boot.command[0] != 255) { - LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); - } - - if (boot.status[0] != 0 && boot.status[0] != 255) { - LOGI("Boot status: %.*s\n", sizeof(boot.status), boot.status); - } - - // --- if arguments weren't supplied, look in the bootloader control block - if (*argc <= 1) { - boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination - const char *arg = strtok(boot.recovery, "\n"); - if (arg != NULL && !strcmp(arg, "recovery")) { - *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); - (*argv)[0] = strdup(arg); - for (*argc = 1; *argc < MAX_ARGS; ++*argc) { - if ((arg = strtok(NULL, "\n")) == NULL) break; - (*argv)[*argc] = strdup(arg); - } - LOGI("Got arguments from boot message\n"); - } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) { - LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); - } - } - - // --- if that doesn't work, try the command file - if (*argc <= 1) { - FILE *fp = fopen_root_path(COMMAND_FILE, "r"); - if (fp != NULL) { - char *argv0 = (*argv)[0]; - *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); - (*argv)[0] = argv0; // use the same program name - - char buf[MAX_ARG_LENGTH]; - for (*argc = 1; *argc < MAX_ARGS; ++*argc) { - if (!fgets(buf, sizeof(buf), fp)) break; - (*argv)[*argc] = strdup(strtok(buf, "\r\n")); // Strip newline. - } - - check_and_fclose(fp, COMMAND_FILE); - LOGI("Got arguments from %s\n", COMMAND_FILE); - } - } - - // --> write the arguments we have back into the bootloader control block - // always boot into recovery after this (until finish_recovery() is called) - strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); - strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); - int i; - for (i = 1; i < *argc; ++i) { - strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); - strlcat(boot.recovery, "\n", sizeof(boot.recovery)); - } - set_bootloader_message(&boot); -} - - -// clear the recovery command and prepare to boot a (hopefully working) system, -// copy our log file to cache as well (for the system to read), and -// record any intent we were asked to communicate back to the system. -// this function is idempotent: call it as many times as you like. -static void -finish_recovery(const char *send_intent) -{ - // By this point, we're ready to return to the main system... - if (send_intent != NULL) { - FILE *fp = fopen_root_path(INTENT_FILE, "w"); - if (fp != NULL) { - fputs(send_intent, fp); - check_and_fclose(fp, INTENT_FILE); - } - } - - // Copy logs to cache so the system can find out what happened. - FILE *log = fopen_root_path(LOG_FILE, "a"); - if (log != NULL) { - FILE *tmplog = fopen(TEMPORARY_LOG_FILE, "r"); - if (tmplog == NULL) { - LOGE("Can't open %s\n", TEMPORARY_LOG_FILE); - } else { - static long tmplog_offset = 0; - fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write - char buf[4096]; - while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); - tmplog_offset = ftell(tmplog); - check_and_fclose(tmplog, TEMPORARY_LOG_FILE); - } - check_and_fclose(log, LOG_FILE); - } - - // Reset the bootloader message to revert to a normal main system boot. - struct bootloader_message boot; - memset(&boot, 0, sizeof(boot)); - set_bootloader_message(&boot); - - // Remove the command file, so recovery won't repeat indefinitely. - char path[PATH_MAX] = ""; - if (ensure_root_path_mounted(COMMAND_FILE) != 0 || - translate_root_path(COMMAND_FILE, path, sizeof(path)) == NULL || - (unlink(path) && errno != ENOENT)) { - LOGW("Can't unlink %s\n", COMMAND_FILE); - } - - 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); - extern int test_permissions(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); - LOGD("Testing permissions...\n"); - ret = test_permissions(); - LOGD(" returned %d\n", ret); -} -#endif // TEST_AMEND - -static int -erase_root(const char *root) -{ - ui_set_background(BACKGROUND_ICON_INSTALLING); - ui_show_indeterminate_progress(); - ui_print("Formatting %s...\n", root); - return format_root_device(root); -} - -static void -prompt_and_wait() -{ - char* headers[] = { "Android system recovery utility", - "", - "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 - char* items[] = { "reboot system now [Home+Back]", - "apply sdcard:update.zip [Alt+S]", - "wipe data/factory reset [Alt+W]", - NULL }; - - ui_start_menu(headers, items); - int selected = 0; - int chosen_item = -1; - - finish_recovery(NULL); - 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); - } - 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; - } - - if (chosen_item >= 0) { - // turn off the menu, letting ui_print() to scroll output - // on the screen. - ui_end_menu(); - - switch (chosen_item) { - case ITEM_REBOOT: - return; - - case ITEM_WIPE_DATA: - ui_print("\n-- Wiping data...\n"); - erase_root("DATA:"); - erase_root("CACHE:"); - ui_print("Data wipe complete.\n"); - if (!ui_text_visible()) return; - break; - - case ITEM_APPLY_SDCARD: - ui_print("\n-- Install from sdcard...\n"); - int status = install_package(SDCARD_PACKAGE_FILE); - if (status != INSTALL_SUCCESS) { - ui_set_background(BACKGROUND_ICON_ERROR); - ui_print("Installation aborted.\n"); - } else if (!ui_text_visible()) { - return; // reboot if logs aren't visible - } else { - ui_print("Install from sdcard complete.\n"); - } - break; - } - - // if we didn't return from this function to reboot, show - // the menu again. - ui_start_menu(headers, items); - selected = 0; - chosen_item = -1; - - finish_recovery(NULL); - ui_reset_progress(); - - // throw away keys pressed while the command was running, - // so user doesn't accidentally trigger menu items. - ui_clear_key_queue(); - } - } -} - -static void -print_property(const char *key, const char *name, void *cookie) -{ - fprintf(stderr, "%s=%s\n", key, name); -} - -int -main(int argc, char **argv) -{ - time_t start = time(NULL); - - // If these fail, there's not really anywhere to complain... - freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); - freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); - fprintf(stderr, "Starting recovery on %s", ctime(&start)); - - ui_init(); - get_args(&argc, &argv); - - int previous_runs = 0; - const char *send_intent = NULL; - const char *update_package = NULL; - int wipe_data = 0, wipe_cache = 0; - - int arg; - while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { - switch (arg) { - case 'p': previous_runs = atoi(optarg); break; - case 's': send_intent = optarg; break; - case 'u': update_package = optarg; break; - case 'w': wipe_data = wipe_cache = 1; break; - case 'c': wipe_cache = 1; break; - case '?': - LOGE("Invalid command argument\n"); - continue; - } - } - - fprintf(stderr, "Command:"); - for (arg = 0; arg < argc; arg++) { - fprintf(stderr, " \"%s\"", argv[arg]); - } - fprintf(stderr, "\n\n"); - - 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; - if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR; - if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); - } else { - status = INSTALL_ERROR; // No command specified - } - - if (status != INSTALL_SUCCESS) ui_set_background(BACKGROUND_ICON_ERROR); - if (status != INSTALL_SUCCESS || ui_text_visible()) prompt_and_wait(); - - // If there is a radio image pending, reboot now to install it. - maybe_install_firmware_update(send_intent); - - // Otherwise, get ready to boot the main system... - finish_recovery(send_intent); - ui_print("Rebooting...\n"); - sync(); - reboot(RB_AUTOBOOT); - return EXIT_SUCCESS; -} diff --git a/res/images/icon_error.bmp b/res/images/icon_error.bmp Binary files differdeleted file mode 100644 index 7eb2bbc..0000000 --- a/res/images/icon_error.bmp +++ /dev/null diff --git a/res/images/icon_firmware_error.bmp b/res/images/icon_firmware_error.bmp Binary files differdeleted file mode 100644 index 5b8649f..0000000 --- a/res/images/icon_firmware_error.bmp +++ /dev/null diff --git a/res/images/icon_firmware_install.bmp b/res/images/icon_firmware_install.bmp Binary files differdeleted file mode 100644 index b0f5f95..0000000 --- a/res/images/icon_firmware_install.bmp +++ /dev/null diff --git a/res/images/icon_installing.bmp b/res/images/icon_installing.bmp Binary files differdeleted file mode 100644 index fff99fd..0000000 --- a/res/images/icon_installing.bmp +++ /dev/null diff --git a/res/images/icon_unpacking.bmp b/res/images/icon_unpacking.bmp Binary files differdeleted file mode 100644 index ab6548c..0000000 --- a/res/images/icon_unpacking.bmp +++ /dev/null diff --git a/res/images/indeterminate1.bmp b/res/images/indeterminate1.bmp Binary files differdeleted file mode 100644 index 716c925..0000000 --- a/res/images/indeterminate1.bmp +++ /dev/null diff --git a/res/images/indeterminate2.bmp b/res/images/indeterminate2.bmp Binary files differdeleted file mode 100644 index 223cd3c..0000000 --- a/res/images/indeterminate2.bmp +++ /dev/null diff --git a/res/images/indeterminate3.bmp b/res/images/indeterminate3.bmp Binary files differdeleted file mode 100644 index fd9086a..0000000 --- a/res/images/indeterminate3.bmp +++ /dev/null diff --git a/res/images/indeterminate4.bmp b/res/images/indeterminate4.bmp Binary files differdeleted file mode 100644 index 87b2640..0000000 --- a/res/images/indeterminate4.bmp +++ /dev/null diff --git a/res/images/indeterminate5.bmp b/res/images/indeterminate5.bmp Binary files differdeleted file mode 100644 index e16efb0..0000000 --- a/res/images/indeterminate5.bmp +++ /dev/null diff --git a/res/images/indeterminate6.bmp b/res/images/indeterminate6.bmp Binary files differdeleted file mode 100644 index 085ad95..0000000 --- a/res/images/indeterminate6.bmp +++ /dev/null diff --git a/res/images/progress_bar_empty.bmp b/res/images/progress_bar_empty.bmp Binary files differdeleted file mode 100644 index 8e512fd..0000000 --- a/res/images/progress_bar_empty.bmp +++ /dev/null diff --git a/res/images/progress_bar_empty_left_round.bmp b/res/images/progress_bar_empty_left_round.bmp Binary files differdeleted file mode 100644 index c4e2f44..0000000 --- a/res/images/progress_bar_empty_left_round.bmp +++ /dev/null diff --git a/res/images/progress_bar_empty_right_round.bmp b/res/images/progress_bar_empty_right_round.bmp Binary files differdeleted file mode 100644 index 1906f62..0000000 --- a/res/images/progress_bar_empty_right_round.bmp +++ /dev/null diff --git a/res/images/progress_bar_fill.bmp b/res/images/progress_bar_fill.bmp Binary files differdeleted file mode 100644 index 8d57d81..0000000 --- a/res/images/progress_bar_fill.bmp +++ /dev/null diff --git a/res/images/progress_bar_left_round.bmp b/res/images/progress_bar_left_round.bmp Binary files differdeleted file mode 100644 index 6d2df8d..0000000 --- a/res/images/progress_bar_left_round.bmp +++ /dev/null diff --git a/res/images/progress_bar_right_round.bmp b/res/images/progress_bar_right_round.bmp Binary files differdeleted file mode 100644 index 68bb6fe..0000000 --- a/res/images/progress_bar_right_round.bmp +++ /dev/null diff --git a/roots.c b/roots.c deleted file mode 100644 index 6a6cf8a..0000000 --- a/roots.c +++ /dev/null @@ -1,370 +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 <errno.h> -#include <stdlib.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "mtdutils/mtdutils.h" -#include "mtdutils/mounts.h" -#include "minzip/Zip.h" -#include "roots.h" -#include "common.h" - -typedef struct { - const char *name; - const char *device; - const char *device2; // If the first one doesn't work (may be NULL) - const char *partition_name; - const char *mount_point; - const char *filesystem; -} RootInfo; - -/* Canonical pointers. -xxx may just want to use enums - */ -static const char g_mtd_device[] = "@\0g_mtd_device"; -static const char g_raw[] = "@\0g_raw"; -static const char g_package_file[] = "@\0g_package_file"; - -static RootInfo g_roots[] = { - { "BOOT:", g_mtd_device, NULL, "boot", NULL, g_raw }, - { "CACHE:", g_mtd_device, NULL, "cache", "/cache", "yaffs2" }, - { "DATA:", g_mtd_device, NULL, "userdata", "/data", "yaffs2" }, - { "MISC:", g_mtd_device, NULL, "misc", NULL, g_raw }, - { "PACKAGE:", NULL, NULL, NULL, NULL, g_package_file }, - { "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" }, - { "TMP:", NULL, NULL, NULL, "/tmp", NULL }, -}; -#define NUM_ROOTS (sizeof(g_roots) / sizeof(g_roots[0])) - -// TODO: for SDCARD:, try /dev/block/mmcblk0 if mmcblk0p1 fails - -static const RootInfo * -get_root_info_for_path(const char *root_path) -{ - const char *c; - - /* Find the first colon. - */ - c = root_path; - while (*c != '\0' && *c != ':') { - c++; - } - if (*c == '\0') { - return NULL; - } - size_t len = c - root_path + 1; - size_t i; - for (i = 0; i < NUM_ROOTS; i++) { - RootInfo *info = &g_roots[i]; - if (strncmp(info->name, root_path, len) == 0) { - return info; - } - } - return NULL; -} - -static const ZipArchive *g_package = NULL; -static char *g_package_path = NULL; - -int -register_package_root(const ZipArchive *package, const char *package_path) -{ - if (package != NULL) { - package_path = strdup(package_path); - if (package_path == NULL) { - return -1; - } - g_package_path = (char *)package_path; - } else { - free(g_package_path); - g_package_path = NULL; - } - g_package = package; - return 0; -} - -int -is_package_root_path(const char *root_path) -{ - const RootInfo *info = get_root_info_for_path(root_path); - return info != NULL && info->filesystem == g_package_file; -} - -const char * -translate_package_root_path(const char *root_path, - char *out_buf, size_t out_buf_len, const ZipArchive **out_package) -{ - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL || info->filesystem != g_package_file) { - return NULL; - } - - /* Strip the package root off of the path. - */ - size_t root_len = strlen(info->name); - root_path += root_len; - size_t root_path_len = strlen(root_path); - - if (out_buf_len < root_path_len + 1) { - return NULL; - } - strcpy(out_buf, root_path); - *out_package = g_package; - return out_buf; -} - -/* Takes a string like "SYSTEM:lib" and turns it into a string - * like "/system/lib". The translated path is put in out_buf, - * and out_buf is returned if the translation succeeded. - */ -const char * -translate_root_path(const char *root_path, char *out_buf, size_t out_buf_len) -{ - if (out_buf_len < 1) { - return NULL; - } - - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL || info->mount_point == NULL) { - return NULL; - } - - /* Find the relative part of the non-root part of the path. - */ - root_path += strlen(info->name); // strip off the "root:" - while (*root_path != '\0' && *root_path == '/') { - root_path++; - } - - size_t mp_len = strlen(info->mount_point); - size_t rp_len = strlen(root_path); - if (mp_len + 1 + rp_len + 1 > out_buf_len) { - return NULL; - } - - /* Glue the mount point to the relative part of the path. - */ - memcpy(out_buf, info->mount_point, mp_len); - if (out_buf[mp_len - 1] != '/') out_buf[mp_len++] = '/'; - - memcpy(out_buf + mp_len, root_path, rp_len); - out_buf[mp_len + rp_len] = '\0'; - - return out_buf; -} - -static int -internal_root_mounted(const RootInfo *info) -{ - if (info->mount_point == NULL) { - return -1; - } -//xxx if TMP: (or similar) just say "yes" - - /* See if this root is already mounted. - */ - int ret = scan_mounted_volumes(); - if (ret < 0) { - return ret; - } - const MountedVolume *volume; - volume = find_mounted_volume_by_mount_point(info->mount_point); - if (volume != NULL) { - /* It's already mounted. - */ - return 0; - } - return -1; -} - -int -is_root_path_mounted(const char *root_path) -{ - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL) { - return -1; - } - return internal_root_mounted(info) >= 0; -} - -int -ensure_root_path_mounted(const char *root_path) -{ - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL) { - return -1; - } - - int ret = internal_root_mounted(info); - if (ret >= 0) { - /* It's already mounted. - */ - return 0; - } - - /* It's not mounted. - */ - if (info->device == g_mtd_device) { - if (info->partition_name == NULL) { - return -1; - } -//TODO: make the mtd stuff scan once when it needs to - mtd_scan_partitions(); - const MtdPartition *partition; - partition = mtd_find_partition_by_name(info->partition_name); - if (partition == NULL) { - return -1; - } - return mtd_mount_partition(partition, info->mount_point, - info->filesystem, 0); - } - - if (info->device == NULL || info->mount_point == NULL || - info->filesystem == NULL || - info->filesystem == g_raw || - info->filesystem == g_package_file) { - return -1; - } - - mkdir(info->mount_point, 0755); // in case it doesn't already exist - if (mount(info->device, info->mount_point, info->filesystem, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - if (info->device2 == NULL) { - LOGE("Can't mount %s\n(%s)\n", info->device, strerror(errno)); - return -1; - } else if (mount(info->device2, info->mount_point, info->filesystem, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - LOGE("Can't mount %s (or %s)\n(%s)\n", - info->device, info->device2, strerror(errno)); - return -1; - } - } - return 0; -} - -int -ensure_root_path_unmounted(const char *root_path) -{ - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL) { - return -1; - } - if (info->mount_point == NULL) { - /* This root can't be mounted, so by definition it isn't. - */ - return 0; - } -//xxx if TMP: (or similar) just return error - - /* See if this root is already mounted. - */ - int ret = scan_mounted_volumes(); - if (ret < 0) { - return ret; - } - const MountedVolume *volume; - volume = find_mounted_volume_by_mount_point(info->mount_point); - if (volume == NULL) { - /* It's not mounted. - */ - return 0; - } - - return unmount_mounted_volume(volume); -} - -const MtdPartition * -get_root_mtd_partition(const char *root_path) -{ - const RootInfo *info = get_root_info_for_path(root_path); - if (info == NULL || info->device != g_mtd_device || - info->partition_name == NULL) - { - return NULL; - } - mtd_scan_partitions(); - return mtd_find_partition_by_name(info->partition_name); -} - -int -format_root_device(const char *root) -{ - /* Be a little safer here; require that "root" is just - * a device with no relative path after it. - */ - const char *c = root; - while (*c != '\0' && *c != ':') { - c++; - } - if (c[0] != ':' || c[1] != '\0') { - LOGW("format_root_device: bad root name \"%s\"\n", root); - return -1; - } - - const RootInfo *info = get_root_info_for_path(root); - if (info == NULL || info->device == NULL) { - LOGW("format_root_device: can't resolve \"%s\"\n", root); - return -1; - } - if (info->mount_point != NULL) { - /* Don't try to format a mounted device. - */ - int ret = ensure_root_path_unmounted(root); - if (ret < 0) { - LOGW("format_root_device: can't unmount \"%s\"\n", root); - return ret; - } - } - - /* Format the device. - */ - if (info->device == g_mtd_device) { - mtd_scan_partitions(); - const MtdPartition *partition; - partition = mtd_find_partition_by_name(info->partition_name); - if (partition == NULL) { - LOGW("format_root_device: can't find mtd partition \"%s\"\n", - info->partition_name); - return -1; - } - if (info->filesystem == g_raw || !strcmp(info->filesystem, "yaffs2")) { - MtdWriteContext *write = mtd_write_partition(partition); - if (write == NULL) { - LOGW("format_root_device: can't open \"%s\"\n", root); - return -1; - } else if (mtd_erase_blocks(write, -1) == (off_t) -1) { - LOGW("format_root_device: can't erase \"%s\"\n", root); - mtd_write_close(write); - return -1; - } else if (mtd_write_close(write)) { - LOGW("format_root_device: can't close \"%s\"\n", root); - return -1; - } else { - return 0; - } - } - } -//TODO: handle other device types (sdcard, etc.) - LOGW("format_root_device: can't handle non-mtd device \"%s\"\n", root); - return -1; -} diff --git a/roots.h b/roots.h deleted file mode 100644 index bc847ea..0000000 --- a/roots.h +++ /dev/null @@ -1,63 +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_ROOTS_H_ -#define RECOVERY_ROOTS_H_ - -#include "minzip/Zip.h" -#include "mtdutils/mtdutils.h" - -/* Any of the "root_path" arguments can be paths with relative - * components, like "SYSTEM:a/b/c". - */ - -/* Associate this package with the package root "PKG:". - */ -int register_package_root(const ZipArchive *package, const char *package_path); - -/* Returns non-zero iff root_path points inside a package. - */ -int is_package_root_path(const char *root_path); - -/* Takes a string like "SYSTEM:lib" and turns it into a string - * like "/system/lib". The translated path is put in out_buf, - * and out_buf is returned if the translation succeeded. - */ -const char *translate_root_path(const char *root_path, - char *out_buf, size_t out_buf_len); - -/* Takes a string like "PKG:lib/libc.so" and returns a pointer to - * the containing zip file and a path like "lib/libc.so". - */ -const char *translate_package_root_path(const char *root_path, - char *out_buf, size_t out_buf_len, const ZipArchive **out_package); - -/* Returns negative on error, positive if it's mounted, zero if it isn't. - */ -int is_root_path_mounted(const char *root_path); - -int ensure_root_path_mounted(const char *root_path); - -int ensure_root_path_unmounted(const char *root_path); - -const MtdPartition *get_root_mtd_partition(const char *root_path); - -/* "root" must be the exact name of the root; no relative path is permitted. - * If the named root is mounted, this will attempt to unmount it first. - */ -int format_root_device(const char *root); - -#endif // RECOVERY_ROOTS_H_ diff --git a/test_roots.c b/test_roots.c deleted file mode 100644 index f49f55e..0000000 --- a/test_roots.c +++ /dev/null @@ -1,81 +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 <sys/stat.h> -#include "roots.h" -#include "common.h" - -#define CANARY_FILE "/system/build.prop" -#define CANARY_FILE_ROOT_PATH "SYSTEM:build.prop" - -int -file_exists(const char *path) -{ - struct stat st; - int ret; - ret = stat(path, &st); - if (ret == 0) { - return S_ISREG(st.st_mode); - } - return 0; -} - -int -test_roots() -{ - int ret; - - /* Make sure that /system isn't mounted yet. - */ - if (file_exists(CANARY_FILE)) return -__LINE__; - if (is_root_path_mounted(CANARY_FILE_ROOT_PATH)) return -__LINE__; - - /* Try to mount the root. - */ - ret = ensure_root_path_mounted(CANARY_FILE_ROOT_PATH); - if (ret < 0) return -__LINE__; - - /* Make sure we can see the file now and that we know the root is mounted. - */ - if (!file_exists(CANARY_FILE)) return -__LINE__; - if (!is_root_path_mounted(CANARY_FILE_ROOT_PATH)) return -__LINE__; - - /* Make sure that the root path corresponds to the regular path. - */ - struct stat st1, st2; - char buf[128]; - const char *path = translate_root_path(CANARY_FILE_ROOT_PATH, - buf, sizeof(buf)); - if (path == NULL) return -__LINE__; - ret = stat(CANARY_FILE, &st1); - if (ret != 0) return -__LINE__; - ret = stat(path, &st2); - if (ret != 0) return -__LINE__; - if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) return -__LINE__; - - /* Try to unmount the root. - */ - ret = ensure_root_path_unmounted(CANARY_FILE_ROOT_PATH); - if (ret < 0) return -__LINE__; - - /* Make sure that we can't see the file anymore and that - * we don't think the root is mounted. - */ - if (file_exists(CANARY_FILE)) return -__LINE__; - if (is_root_path_mounted(CANARY_FILE_ROOT_PATH)) return -__LINE__; - - return 0; -} diff --git a/tools/Android.mk b/tools/Android.mk deleted file mode 100644 index 6571161..0000000 --- a/tools/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(all-subdir-makefiles) diff --git a/tools/ota/Android.mk b/tools/ota/Android.mk deleted file mode 100644 index b7a57d6..0000000 --- a/tools/ota/Android.mk +++ /dev/null @@ -1,42 +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. - -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) -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_MODULE := add-property-tag -LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) -LOCAL_MODULE_TAGS := debug -LOCAL_SRC_FILES := add-property-tag.c -LOCAL_STATIC_LIBRARIES := libc -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_MODULE := check-lost+found -LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) -LOCAL_MODULE_TAGS := debug -LOCAL_SRC_FILES := check-lost+found.c -LOCAL_STATIC_LIBRARIES := libcutils libc -include $(BUILD_EXECUTABLE) - -endif # !TARGET_SIMULATOR diff --git a/tools/ota/add-data-wipe b/tools/ota/add-data-wipe deleted file mode 100755 index 8d2626f..0000000 --- a/tools/ota/add-data-wipe +++ /dev/null @@ -1,118 +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. -# - -PROGNAME=`basename $0` - -function cleantmp -{ - if [ ! -z "$TMPDIR" ] - then - rm -rf "$TMPDIR" - TMPDIR= - fi -} - -function println -{ - if [ $# -gt 0 ] - then - echo "$PROGNAME: $@" - fi -} - -function fail -{ - println "$@" - cleantmp - exit 1 -} - -function usage -{ - println "$@" - echo "Usage: $PROGNAME <input file> <output file>" - fail -} - -OTATOOL=`which otatool` -if [ -z "$OTATOOL" ] -then - OTATOOL="`dirname $0`/otatool" - if [ ! -x "$OTATOOL" ] - then - fail "Can't find otatool" - fi -fi - - -if [ $# -ne 2 ] -then - usage -fi - -INFILE="$1" -OUTFILE="$2" - -if [ ! -f "$INFILE" ] -then - fail "$INFILE doesn't exist or isn't a file" -fi - -if [ -z "$OUTFILE" ] -then - usage "Output file not specified" -fi - -if [ -d "$OUTFILE" ] -then - usage "Output file may not be a directory" -fi - -if [ "$INFILE" -ef "$OUTFILE" ] -then - fail "Refusing to use the input file as the output file" -fi - -TMPDIR=`mktemp -d "/tmp/$PROGNAME.XXXXXX"` -if [ $? -ne 0 ] -then - TMPDIR= - fail "Can't create temporary directory" -fi - -ORIGSCRIPT="$TMPDIR/orig" -NEWSCRIPT="$TMPDIR/new" - -"$OTATOOL" --dump-script "$INFILE" | -awk ' - { print } - /^format SYSTEM:$/ { - print "delete_recursive DATA:" - } -' > "$NEWSCRIPT" -if [ $? -ne 0 ] -then - fail "Couldn't modify script" -fi - -"$OTATOOL" --replace-script "$NEWSCRIPT" -o "$OUTFILE" "$INFILE" -if [ $? -ne 0 ] -then - fail "Couldn't replace script" -fi - -cleantmp diff --git a/tools/ota/add-property-tag.c b/tools/ota/add-property-tag.c deleted file mode 100644 index 5277edd..0000000 --- a/tools/ota/add-property-tag.c +++ /dev/null @@ -1,141 +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 <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* - * Append a tag to a property value in a .prop file if it isn't already there. - * Normally used to modify build properties to record incremental updates. - */ - -// Return nonzero if the tag should be added to this line. -int should_tag(const char *line, const char *propname) { - const char *prop = strstr(line, propname); - if (prop == NULL) return 0; - - // Make sure this is actually the property name (not an accidental hit) - const char *ptr; - for (ptr = line; ptr < prop && isspace(*ptr); ++ptr) ; - if (ptr != prop) return 0; // Must be at the beginning of the line - - for (ptr += strlen(propname); *ptr != '\0' && isspace(*ptr); ++ptr) ; - return (*ptr == '='); // Must be followed by a '=' -} - -// Remove existing tags from the line, return the following number (if any) -int remove_tag(char *line, const char *tag) { - char *pos = strstr(line, tag); - if (pos == NULL) return 0; - - char *end; - int num = strtoul(pos + strlen(tag), &end, 10); - strcpy(pos, end); - return num; -} - -// Write line to output with the tag added, adding a number (if >0) -void write_tagged(FILE *out, const char *line, const char *tag, int number) { - const char *end = line + strlen(line); - while (end > line && isspace(end[-1])) --end; - if (number > 0) { - fprintf(out, "%.*s%s%d%s", end - line, line, tag, number, end); - } else { - fprintf(out, "%.*s%s%s", end - line, line, tag, end); - } -} - -int main(int argc, char **argv) { - const char *filename = "/system/build.prop"; - const char *propname = "ro.build.fingerprint"; - const char *tag = NULL; - int do_remove = 0, do_number = 0; - - int opt; - while ((opt = getopt(argc, argv, "f:p:rn")) != -1) { - switch (opt) { - case 'f': filename = optarg; break; - case 'p': propname = optarg; break; - case 'r': do_remove = 1; break; - case 'n': do_number = 1; break; - case '?': return 2; - } - } - - if (argc != optind + 1) { - fprintf(stderr, - "usage: add-property-tag [flags] tag-to-add\n" - "flags: -f /dir/file.prop (default /system/build.prop)\n" - " -p prop.name (default ro.build.fingerprint)\n" - " -r (if set, remove the tag rather than adding it)\n" - " -n (if set, add and increment a number after the tag)\n"); - return 2; - } - - tag = argv[optind]; - FILE *input = fopen(filename, "r"); - if (input == NULL) { - fprintf(stderr, "can't read %s: %s\n", filename, strerror(errno)); - return 1; - } - - char tmpname[PATH_MAX]; - snprintf(tmpname, sizeof(tmpname), "%s.tmp", filename); - FILE *output = fopen(tmpname, "w"); - if (output == NULL) { - fprintf(stderr, "can't write %s: %s\n", tmpname, strerror(errno)); - return 1; - } - - int found = 0; - char line[4096]; - while (fgets(line, sizeof(line), input)) { - if (!should_tag(line, propname)) { - fputs(line, output); // Pass through unmodified - } else { - found = 1; - int number = remove_tag(line, tag); - if (do_remove) { - fputs(line, output); // Remove the tag but don't re-add it - } else { - write_tagged(output, line, tag, number + do_number); - } - } - } - - fclose(input); - fclose(output); - - if (!found) { - fprintf(stderr, "property %s not found in %s\n", propname, filename); - remove(tmpname); - return 1; - } - - if (rename(tmpname, filename)) { - fprintf(stderr, "can't rename %s to %s: %s\n", - tmpname, filename, strerror(errno)); - remove(tmpname); - return 1; - } - - return 0; -} diff --git a/tools/ota/check-lost+found.c b/tools/ota/check-lost+found.c deleted file mode 100644 index f856275..0000000 --- a/tools/ota/check-lost+found.c +++ /dev/null @@ -1,144 +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 <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/klog.h> -#include <sys/reboot.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <time.h> - -#include "private/android_filesystem_config.h" - -// Sentinel file used to track whether we've forced a reboot -static const char *kMarkerFile = "/data/misc/check-lost+found-rebooted-2"; - -// Output file in tombstones directory (first 8K will be uploaded) -static const char *kOutputDir = "/data/tombstones"; -static const char *kOutputFile = "/data/tombstones/check-lost+found-log"; - -// Partitions to check -static const char *kPartitions[] = { "/system", "/data", "/cache", NULL }; - -/* - * 1. If /data/misc/forced-reboot is missing, touch it & force "unclean" boot. - * 2. Write a log entry with the number of files in lost+found directories. - */ - -int main(int argc, char **argv) { - mkdir(kOutputDir, 0755); - chown(kOutputDir, AID_SYSTEM, AID_SYSTEM); - FILE *out = fopen(kOutputFile, "a"); - if (out == NULL) { - fprintf(stderr, "Can't write %s: %s\n", kOutputFile, strerror(errno)); - return 1; - } - - // Note: only the first 8K of log will be uploaded, so be terse. - time_t start = time(NULL); - fprintf(out, "*** check-lost+found ***\nStarted: %s", ctime(&start)); - - struct stat st; - if (stat(kMarkerFile, &st)) { - // No reboot marker -- need to force an unclean reboot. - // But first, try to create the marker file. If that fails, - // skip the reboot, so we don't get caught in an infinite loop. - - int fd = open(kMarkerFile, O_WRONLY|O_CREAT, 0444); - if (fd >= 0 && close(fd) == 0) { - fprintf(out, "Wrote %s, rebooting\n", kMarkerFile); - fflush(out); - sync(); // Make sure the marker file is committed to disk - - // If possible, dirty each of these partitions before rebooting, - // to make sure the filesystem has to do a scan on mount. - int i; - for (i = 0; kPartitions[i] != NULL; ++i) { - char fn[PATH_MAX]; - snprintf(fn, sizeof(fn), "%s/%s", kPartitions[i], "dirty"); - fd = open(fn, O_WRONLY|O_CREAT, 0444); - if (fd >= 0) { // Don't sweat it if we can't write the file. - write(fd, fn, sizeof(fn)); // write, you know, some data - close(fd); - unlink(fn); - } - } - - reboot(RB_AUTOBOOT); // reboot immediately, with dirty filesystems - fprintf(out, "Reboot failed?!\n"); - exit(1); - } else { - fprintf(out, "Can't write %s: %s\n", kMarkerFile, strerror(errno)); - } - } else { - fprintf(out, "Found %s\n", kMarkerFile); - } - - int i; - for (i = 0; kPartitions[i] != NULL; ++i) { - char fn[PATH_MAX]; - snprintf(fn, sizeof(fn), "%s/%s", kPartitions[i], "lost+found"); - DIR *dir = opendir(fn); - if (dir == NULL) { - fprintf(out, "Can't open %s: %s\n", fn, strerror(errno)); - } else { - int count = 0; - struct dirent *ent; - while ((ent = readdir(dir))) { - if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) - ++count; - } - closedir(dir); - if (count > 0) { - fprintf(out, "OMGZ FOUND %d FILES IN %s\n", count, fn); - } else { - fprintf(out, "%s is clean\n", fn); - } - } - } - - char dmesg[131073]; - int len = klogctl(KLOG_READ_ALL, dmesg, sizeof(dmesg) - 1); - if (len < 0) { - fprintf(out, "Can't read kernel log: %s\n", strerror(errno)); - } else { // To conserve space, only write lines with certain keywords - fprintf(out, "--- Kernel log ---\n"); - dmesg[len] = '\0'; - char *saveptr, *line; - int in_yaffs = 0; - for (line = strtok_r(dmesg, "\n", &saveptr); line != NULL; - line = strtok_r(NULL, "\n", &saveptr)) { - if (strstr(line, "yaffs: dev is")) in_yaffs = 1; - - if (in_yaffs || - strstr(line, "yaffs") || - strstr(line, "mtd") || - strstr(line, "msm_nand")) { - fprintf(out, "%s\n", line); - } - - if (strstr(line, "yaffs_read_super: isCheckpointed")) in_yaffs = 0; - } - } - - return 0; -} diff --git a/tools/ota/convert-to-bmp.py b/tools/ota/convert-to-bmp.py deleted file mode 100644 index 446c09d..0000000 --- a/tools/ota/convert-to-bmp.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/python2.4 - -"""A simple script to convert asset images to BMP files, that supports -RGBA image.""" - -import struct -import Image -import sys - -infile = sys.argv[1] -outfile = sys.argv[2] - -if not outfile.endswith(".bmp"): - print >> sys.stderr, "Warning: I'm expecting to write BMP files." - -im = Image.open(infile) -if im.mode == 'RGB': - im.save(outfile) -elif im.mode == 'RGBA': - # Python Imaging Library doesn't write RGBA BMP files, so we roll - # our own. - - BMP_HEADER_FMT = ("<" # little-endian - "H" # signature - "L" # file size - "HH" # reserved (set to 0) - "L" # offset to start of bitmap data) - ) - - BITMAPINFO_HEADER_FMT= ("<" # little-endian - "L" # size of this struct - "L" # width - "L" # height - "H" # planes (set to 1) - "H" # bit count - "L" # compression (set to 0 for minui) - "L" # size of image data (0 if uncompressed) - "L" # x pixels per meter (1) - "L" # y pixels per meter (1) - "L" # colors used (0) - "L" # important colors (0) - ) - - fileheadersize = struct.calcsize(BMP_HEADER_FMT) - infoheadersize = struct.calcsize(BITMAPINFO_HEADER_FMT) - - header = struct.pack(BMP_HEADER_FMT, - 0x4d42, # "BM" in little-endian - (fileheadersize + infoheadersize + - im.size[0] * im.size[1] * 4), - 0, 0, - fileheadersize + infoheadersize) - - info = struct.pack(BITMAPINFO_HEADER_FMT, - infoheadersize, - im.size[0], - im.size[1], - 1, - 32, - 0, - 0, - 1, - 1, - 0, - 0) - - f = open(outfile, "wb") - f.write(header) - f.write(info) - data = im.tostring() - for j in range(im.size[1]-1, -1, -1): # rows bottom-to-top - for i in range(j*im.size[0]*4, (j+1)*im.size[0]*4, 4): - f.write(data[i+2]) # B - f.write(data[i+1]) # G - f.write(data[i+0]) # R - f.write(data[i+3]) # A - f.close() -else: - print >> sys.stderr, "Don't know how to handle image mode '%s'." % (im.mode,) diff --git a/tools/ota/make-update-script.c b/tools/ota/make-update-script.c deleted file mode 100644 index 225dc52..0000000 --- a/tools/ota/make-update-script.c +++ /dev/null @@ -1,228 +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 - // or: - // require version-bootloader=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\"\n", value); - } - // 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; -} diff --git a/tools/ota/otatool b/tools/ota/otatool deleted file mode 100755 index 4b02629..0000000 --- a/tools/ota/otatool +++ /dev/null @@ -1,225 +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. -# - -PROGNAME=`basename "$0"` - -INSTALL_SCRIPT_NAME=META-INF/com/android/update-script - -function cleantmp -{ - if [ ! -z "$TMPDIR" ] - then - rm -rf "$TMPDIR" - TMPDIR= - fi -} - -function println -{ - if [ $# -gt 0 ] - then - echo "$PROGNAME: $@" - fi -} - -function fail -{ - println "$@" - cleantmp - exit 1 -} - -function usage -{ - println "$@" - echo "Usage: $PROGNAME <command> [command-options] <ota-file>" - echo " Where <command> is one of:" - echo " --dump" - echo " Dump a description of the ota file" - echo " --dump-script" - echo " Dumps the install script to standard out" - echo " --append-script <file> -o|--output <outfile>" - echo " Append the contents of <file> to the install script" - echo " --replace-script <file> -o|--output <outfile>" - echo " Replace the install script with the contents of <file>" - fail -} - -if [ $# -lt 2 ] -then - usage -fi -CMD="$1" -shift -if [ "$CMD" = --dump ] -then - CMD_DUMP=1 - UNPACK_FILE=1 -elif [ "$CMD" = --dump-script ] -then - CMD_DUMP_SCRIPT=1 -elif [ "$CMD" = --append-script ] -then - CMD_APPEND_SCRIPT=1 - SCRIPT_FILE=$1 - shift - NEEDS_SCRIPT_FILE=1 - NEEDS_OUTPUT=1 -elif [ "$CMD" = --replace-script ] -then - CMD_REPLACE_SCRIPT=1 - SCRIPT_FILE=$1 - shift - NEEDS_SCRIPT_FILE=1 - NEEDS_OUTPUT=1 -else - usage "Unknown command $CMD" -fi - -if [ ! -z "$NEED_SCRIPT_FILE" ] -then - if [ -z "$SCRIPT_FILE" -o ! -f "$SCRIPT_FILE" ] - then - usage "$CMD requires a valid script file" - fi -fi - -if [ ! -z "$NEEDS_OUTPUT" ] -then - if [ "x$1" != "x-o" -a "x$1" != "x--output" ] - then - usage "$CMD requires \"-o <file>\" or \"--output <file>\"" - fi - shift - - OUTFILE="$1" - shift - if [ -z "$OUTFILE" ] - then - usage "$CMD requires \"-o <file>\" or \"--output <file>\"" - fi - if [ -d "$OUTFILE" ] - then - fail "Output file \"$OUTFILE\" is a directory" - fi -fi - -FILE="$1" -if [ ! -f "$FILE" ] -then - fail "$FILE doesn't exist or isn't a file" -fi -if [ ! -z "$OUTFILE" -a "$FILE" -ef "$OUTFILE" ] -then - fail "Refusing to use the input file as the output file" -fi - -if [ $CMD_DUMP_SCRIPT ] -then - unzip -p "$FILE" "$INSTALL_SCRIPT_NAME" - exit 0 -fi - -# Create a temporary directory for scratch files. -# -TMPDIR=`mktemp -d /tmp/$PROGNAME.XXXXXX` -if [ $? -ne 0 ] -then - TMPDIR= - fail "Can't create temporary directory" -fi - - -if [ $UNPACK_FILE ] -then - ROOTDIR="$TMPDIR/root" - mkdir -p "$ROOTDIR" - - println "Unpacking `basename $FILE`..." - - unzip -q -d "$ROOTDIR" "$FILE" - if [ $? -ne 0 ] - then - fail "Couldn't unpack $FILE" - fi -fi - - -if [ $CMD_DUMP ] -then - function dumpfile - { - echo "BEGIN `basename $1`" - cat "$1" | sed -e 's/^/ /' - echo "END `basename $1`" - } - - echo Contents of root: - ls -1 "$ROOTDIR" | sed -e 's/^/ /' - echo - echo Contents of META-INF: - (cd "$ROOTDIR" && find META-INF -type f) | sed -e 's/^/ /' - - echo - dumpfile "$ROOTDIR/META-INF/MANIFEST.MF" - echo - dumpfile "$ROOTDIR/$INSTALL_SCRIPT_NAME" - echo - dumpfile "$ROOTDIR/android-product.txt" - echo - dumpfile "$ROOTDIR/system/build.prop" -fi - -if [ $CMD_APPEND_SCRIPT ] -then - TMPSCRIPT="$TMPDIR/script" - NEWSCRIPT="$TMPDIR/$INSTALL_SCRIPT_NAME" - unzip -p "$FILE" "$INSTALL_SCRIPT_NAME" > "$TMPSCRIPT" - if [ $? -ne 0 ] - then - fail "Couldn't extract $INSTALL_SCRIPT_NAME from $FILE" - fi - mkdir -p `dirname "$NEWSCRIPT"` - cat "$TMPSCRIPT" "$SCRIPT_FILE" > "$NEWSCRIPT" - - OVERWRITE_SCRIPT=1 -fi - -if [ $CMD_REPLACE_SCRIPT ] -then - NEWSCRIPT="$TMPDIR/$INSTALL_SCRIPT_NAME" - mkdir -p `dirname "$NEWSCRIPT"` - cp "$SCRIPT_FILE" "$NEWSCRIPT" - - OVERWRITE_SCRIPT=1 -fi - -if [ $OVERWRITE_SCRIPT ] -then - cp "$FILE" "$TMPDIR/outfile.zip" - (cd "$TMPDIR" && zip -qu outfile.zip "$INSTALL_SCRIPT_NAME") - if [ $? -ne 0 ] - then - fail "Couldn't add new $INSTALL_SCRIPT_NAME to output file" - fi - - rm -f "$OUTFILE" - mkdir -p `dirname "$OUTFILE"` - mv "$TMPDIR/outfile.zip" "$OUTFILE" -fi - -cleantmp @@ -1,542 +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 <linux/input.h> -#include <pthread.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/reboot.h> -#include <sys/time.h> -#include <time.h> -#include <unistd.h> - -#include "common.h" -#include "minui/minui.h" - -#define MAX_COLS 64 -#define MAX_ROWS 32 - -#define CHAR_WIDTH 10 -#define CHAR_HEIGHT 18 - -#define PROGRESSBAR_INDETERMINATE_STATES 6 -#define PROGRESSBAR_INDETERMINATE_FPS 15 - -enum { LEFT_SIDE, CENTER_TILE, RIGHT_SIDE, NUM_SIDES }; - -static pthread_mutex_t gUpdateMutex = PTHREAD_MUTEX_INITIALIZER; -static gr_surface gBackgroundIcon[NUM_BACKGROUND_ICONS]; -static gr_surface gProgressBarIndeterminate[PROGRESSBAR_INDETERMINATE_STATES]; -static gr_surface gProgressBarEmpty[NUM_SIDES]; -static gr_surface gProgressBarFill[NUM_SIDES]; - -static const struct { gr_surface* surface; const char *name; } BITMAPS[] = { - { &gBackgroundIcon[BACKGROUND_ICON_UNPACKING], "icon_unpacking" }, - { &gBackgroundIcon[BACKGROUND_ICON_INSTALLING], "icon_installing" }, - { &gBackgroundIcon[BACKGROUND_ICON_ERROR], "icon_error" }, - { &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_INSTALLING], - "icon_firmware_install" }, - { &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_ERROR], - "icon_firmware_error" }, - { &gProgressBarIndeterminate[0], "indeterminate1" }, - { &gProgressBarIndeterminate[1], "indeterminate2" }, - { &gProgressBarIndeterminate[2], "indeterminate3" }, - { &gProgressBarIndeterminate[3], "indeterminate4" }, - { &gProgressBarIndeterminate[4], "indeterminate5" }, - { &gProgressBarIndeterminate[5], "indeterminate6" }, - { &gProgressBarEmpty[LEFT_SIDE], "progress_bar_empty_left_round" }, - { &gProgressBarEmpty[CENTER_TILE], "progress_bar_empty" }, - { &gProgressBarEmpty[RIGHT_SIDE], "progress_bar_empty_right_round" }, - { &gProgressBarFill[LEFT_SIDE], "progress_bar_left_round" }, - { &gProgressBarFill[CENTER_TILE], "progress_bar_fill" }, - { &gProgressBarFill[RIGHT_SIDE], "progress_bar_right_round" }, - { NULL, NULL }, -}; - -static gr_surface gCurrentIcon = NULL; - -static enum ProgressBarType { - PROGRESSBAR_TYPE_NONE, - PROGRESSBAR_TYPE_INDETERMINATE, - PROGRESSBAR_TYPE_NORMAL, -} gProgressBarType = PROGRESSBAR_TYPE_NONE; - -// Progress bar scope of current operation -static float gProgressScopeStart = 0, gProgressScopeSize = 0, gProgress = 0; -static time_t gProgressScopeTime, gProgressScopeDuration; - -// Set to 1 when both graphics pages are the same (except for the progress bar) -static int gPagesIdentical = 0; - -// Log text overlay, displayed when a magic key is pressed -static char text[MAX_ROWS][MAX_COLS]; -static int text_cols = 0, text_rows = 0; -static int text_col = 0, text_row = 0, text_top = 0; -static int show_text = 0; - -static char menu[MAX_ROWS][MAX_COLS]; -static int show_menu = 0; -static int menu_top = 0, menu_items = 0, menu_sel = 0; - -// Key event input queue -static pthread_mutex_t key_queue_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t key_queue_cond = PTHREAD_COND_INITIALIZER; -static int key_queue[256], key_queue_len = 0; -static volatile char key_pressed[KEY_MAX + 1]; - -// Clear the screen and draw the currently selected background icon (if any). -// Should only be called with gUpdateMutex locked. -static void draw_background_locked(gr_surface icon) -{ - gPagesIdentical = 0; - gr_color(0, 0, 0, 255); - gr_fill(0, 0, gr_fb_width(), gr_fb_height()); - - if (icon) { - int iconWidth = gr_get_width(icon); - int iconHeight = gr_get_height(icon); - int iconX = (gr_fb_width() - iconWidth) / 2; - int iconY = (gr_fb_height() - iconHeight) / 2; - gr_blit(icon, 0, 0, iconWidth, iconHeight, iconX, iconY); - } -} - -// Draw the progress bar (if any) on the screen. Does not flip pages. -// Should only be called with gUpdateMutex locked. -static void draw_progress_locked() -{ - if (gProgressBarType == PROGRESSBAR_TYPE_NONE) return; - - int iconHeight = gr_get_height(gBackgroundIcon[BACKGROUND_ICON_INSTALLING]); - int width = gr_get_width(gProgressBarIndeterminate[0]); - int height = gr_get_height(gProgressBarIndeterminate[0]); - - int dx = (gr_fb_width() - width)/2; - int dy = (3*gr_fb_height() + iconHeight - 2*height)/4; - - // Erase behind the progress bar (in case this was a progress-only update) - gr_color(0, 0, 0, 255); - gr_fill(dx, dy, width, height); - - if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL) { - float progress = gProgressScopeStart + gProgress * gProgressScopeSize; - int pos = (int) (progress * width); - - gr_surface s = (pos ? gProgressBarFill : gProgressBarEmpty)[LEFT_SIDE]; - gr_blit(s, 0, 0, gr_get_width(s), gr_get_height(s), dx, dy); - - int x = gr_get_width(s); - while (x + (int) gr_get_width(gProgressBarEmpty[RIGHT_SIDE]) < width) { - s = (pos > x ? gProgressBarFill : gProgressBarEmpty)[CENTER_TILE]; - gr_blit(s, 0, 0, gr_get_width(s), gr_get_height(s), dx + x, dy); - x += gr_get_width(s); - } - - s = (pos > x ? gProgressBarFill : gProgressBarEmpty)[RIGHT_SIDE]; - gr_blit(s, 0, 0, gr_get_width(s), gr_get_height(s), dx + x, dy); - } - - if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE) { - static int frame = 0; - gr_blit(gProgressBarIndeterminate[frame], 0, 0, width, height, dx, dy); - frame = (frame + 1) % PROGRESSBAR_INDETERMINATE_STATES; - } -} - -static void draw_text_line(int row, const char* t) { - if (t[0] != '\0') { - gr_text(0, (row+1)*CHAR_HEIGHT-1, t); - } -} - -// Redraw everything on the screen. Does not flip pages. -// Should only be called with gUpdateMutex locked. -static void draw_screen_locked(void) -{ - draw_background_locked(gCurrentIcon); - draw_progress_locked(); - - if (show_text) { - gr_color(0, 0, 0, 160); - gr_fill(0, 0, gr_fb_width(), gr_fb_height()); - - int i = 0; - if (show_menu) { - gr_color(64, 96, 255, 255); - gr_fill(0, (menu_top+menu_sel) * CHAR_HEIGHT, - gr_fb_width(), (menu_top+menu_sel+1)*CHAR_HEIGHT+1); - - for (; i < menu_top + menu_items; ++i) { - if (i == menu_top + menu_sel) { - gr_color(255, 255, 255, 255); - draw_text_line(i, menu[i]); - gr_color(64, 96, 255, 255); - } else { - draw_text_line(i, menu[i]); - } - } - gr_fill(0, i*CHAR_HEIGHT+CHAR_HEIGHT/2-1, - gr_fb_width(), i*CHAR_HEIGHT+CHAR_HEIGHT/2+1); - ++i; - } - - gr_color(255, 255, 0, 255); - - for (; i < text_rows; ++i) { - draw_text_line(i, text[(i+text_top) % text_rows]); - } - } -} - -// Redraw everything on the screen and flip the screen (make it visible). -// Should only be called with gUpdateMutex locked. -static void update_screen_locked(void) -{ - draw_screen_locked(); - gr_flip(); -} - -// Updates only the progress bar, if possible, otherwise redraws the screen. -// Should only be called with gUpdateMutex locked. -static void update_progress_locked(void) -{ - if (show_text || !gPagesIdentical) { - draw_screen_locked(); // Must redraw the whole screen - gPagesIdentical = 1; - } else { - draw_progress_locked(); // Draw only the progress bar - } - gr_flip(); -} - -// Keeps the progress bar updated, even when the process is otherwise busy. -static void *progress_thread(void *cookie) -{ - for (;;) { - usleep(1000000 / PROGRESSBAR_INDETERMINATE_FPS); - pthread_mutex_lock(&gUpdateMutex); - - // update the progress bar animation, if active - // skip this if we have a text overlay (too expensive to update) - if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE && !show_text) { - update_progress_locked(); - } - - // move the progress bar forward on timed intervals, if configured - int duration = gProgressScopeDuration; - if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL && duration > 0) { - int elapsed = time(NULL) - gProgressScopeTime; - float progress = 1.0 * elapsed / duration; - if (progress > 1.0) progress = 1.0; - if (progress > gProgress) { - gProgress = progress; - update_progress_locked(); - } - } - - pthread_mutex_unlock(&gUpdateMutex); - } - return NULL; -} - -// Reads input events, handles special hot keys, and adds to the key queue. -static void *input_thread(void *cookie) -{ - int rel_sum = 0; - int fake_key = 0; - for (;;) { - // wait for the next key event - struct input_event ev; - do { - ev_get(&ev, 0); - - if (ev.type == EV_SYN) { - continue; - } else if (ev.type == EV_REL) { - if (ev.code == REL_Y) { - // accumulate the up or down motion reported by - // the trackball. When it exceeds a threshold - // (positive or negative), fake an up/down - // key event. - rel_sum += ev.value; - if (rel_sum > 3) { - fake_key = 1; - ev.type = EV_KEY; - ev.code = KEY_DOWN; - ev.value = 1; - rel_sum = 0; - } else if (rel_sum < -3) { - fake_key = 1; - ev.type = EV_KEY; - ev.code = KEY_UP; - ev.value = 1; - rel_sum = 0; - } - } - } else { - rel_sum = 0; - } - } while (ev.type != EV_KEY || ev.code > KEY_MAX); - - pthread_mutex_lock(&key_queue_mutex); - if (!fake_key) { - // our "fake" keys only report a key-down event (no - // key-up), so don't record them in the key_pressed - // table. - key_pressed[ev.code] = ev.value; - } - fake_key = 0; - const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]); - if (ev.value > 0 && key_queue_len < queue_max) { - key_queue[key_queue_len++] = ev.code; - pthread_cond_signal(&key_queue_cond); - } - 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)) { - 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]) { - reboot(RB_AUTOBOOT); - } - } - return NULL; -} - -void ui_init(void) -{ - gr_init(); - ev_init(); - - text_col = text_row = 0; - text_rows = gr_fb_height() / CHAR_HEIGHT; - if (text_rows > MAX_ROWS) text_rows = MAX_ROWS; - text_top = 1; - - text_cols = gr_fb_width() / CHAR_WIDTH; - if (text_cols > MAX_COLS - 1) text_cols = MAX_COLS - 1; - - int i; - for (i = 0; BITMAPS[i].name != NULL; ++i) { - int result = res_create_surface(BITMAPS[i].name, BITMAPS[i].surface); - if (result < 0) { - LOGE("Missing bitmap %s\n(Code %d)\n", BITMAPS[i].name, result); - *BITMAPS[i].surface = NULL; - } - } - - pthread_t t; - pthread_create(&t, NULL, progress_thread, NULL); - pthread_create(&t, NULL, input_thread, NULL); -} - -char *ui_copy_image(int icon, int *width, int *height, int *bpp) { - pthread_mutex_lock(&gUpdateMutex); - draw_background_locked(gBackgroundIcon[icon]); - *width = gr_fb_width(); - *height = gr_fb_height(); - *bpp = sizeof(gr_pixel) * 8; - int size = *width * *height * sizeof(gr_pixel); - char *ret = malloc(size); - if (ret == NULL) { - LOGE("Can't allocate %d bytes for image\n", size); - } else { - memcpy(ret, gr_fb_data(), size); - } - pthread_mutex_unlock(&gUpdateMutex); - return ret; -} - -void ui_set_background(int icon) -{ - pthread_mutex_lock(&gUpdateMutex); - gCurrentIcon = gBackgroundIcon[icon]; - update_screen_locked(); - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_show_indeterminate_progress() -{ - pthread_mutex_lock(&gUpdateMutex); - if (gProgressBarType != PROGRESSBAR_TYPE_INDETERMINATE) { - gProgressBarType = PROGRESSBAR_TYPE_INDETERMINATE; - update_progress_locked(); - } - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_show_progress(float portion, int seconds) -{ - pthread_mutex_lock(&gUpdateMutex); - gProgressBarType = PROGRESSBAR_TYPE_NORMAL; - gProgressScopeStart += gProgressScopeSize; - gProgressScopeSize = portion; - gProgressScopeTime = time(NULL); - gProgressScopeDuration = seconds; - gProgress = 0; - update_progress_locked(); - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_set_progress(float fraction) -{ - pthread_mutex_lock(&gUpdateMutex); - if (fraction < 0.0) fraction = 0.0; - if (fraction > 1.0) fraction = 1.0; - if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL && fraction > gProgress) { - // Skip updates that aren't visibly different. - int width = gr_get_width(gProgressBarIndeterminate[0]); - float scale = width * gProgressScopeSize; - if ((int) (gProgress * scale) != (int) (fraction * scale)) { - gProgress = fraction; - update_progress_locked(); - } - } - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_reset_progress() -{ - pthread_mutex_lock(&gUpdateMutex); - gProgressBarType = PROGRESSBAR_TYPE_NONE; - gProgressScopeStart = gProgressScopeSize = 0; - gProgressScopeTime = gProgressScopeDuration = 0; - gProgress = 0; - update_screen_locked(); - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_print(const char *fmt, ...) -{ - char buf[256]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, 256, fmt, ap); - va_end(ap); - - fputs(buf, stderr); - - // This can get called before ui_init(), so be careful. - pthread_mutex_lock(&gUpdateMutex); - if (text_rows > 0 && text_cols > 0) { - char *ptr; - for (ptr = buf; *ptr != '\0'; ++ptr) { - if (*ptr == '\n' || text_col >= text_cols) { - text[text_row][text_col] = '\0'; - text_col = 0; - text_row = (text_row + 1) % text_rows; - if (text_row == text_top) text_top = (text_top + 1) % text_rows; - } - if (*ptr != '\n') text[text_row][text_col++] = *ptr; - } - text[text_row][text_col] = '\0'; - update_screen_locked(); - } - pthread_mutex_unlock(&gUpdateMutex); -} - -void ui_start_menu(char** headers, char** items) { - int i; - pthread_mutex_lock(&gUpdateMutex); - if (text_rows > 0 && text_cols > 0) { - for (i = 0; i < text_rows; ++i) { - if (headers[i] == NULL) break; - strncpy(menu[i], headers[i], text_cols-1); - menu[i][text_cols-1] = '\0'; - } - menu_top = i; - for (; i < text_rows; ++i) { - if (items[i-menu_top] == NULL) break; - strncpy(menu[i], items[i-menu_top], text_cols-1); - menu[i][text_cols-1] = '\0'; - } - menu_items = i - menu_top; - show_menu = 1; - menu_sel = 0; - update_screen_locked(); - } - pthread_mutex_unlock(&gUpdateMutex); -} - -int ui_menu_select(int sel) { - int old_sel; - pthread_mutex_lock(&gUpdateMutex); - if (show_menu > 0) { - old_sel = menu_sel; - menu_sel = sel; - if (menu_sel < 0) menu_sel = 0; - if (menu_sel >= menu_items) menu_sel = menu_items-1; - sel = menu_sel; - if (menu_sel != old_sel) update_screen_locked(); - } - pthread_mutex_unlock(&gUpdateMutex); - return sel; -} - -void ui_end_menu() { - int i; - pthread_mutex_lock(&gUpdateMutex); - if (show_menu > 0 && text_rows > 0 && text_cols > 0) { - show_menu = 0; - update_screen_locked(); - } - pthread_mutex_unlock(&gUpdateMutex); -} - -int ui_text_visible() -{ - pthread_mutex_lock(&gUpdateMutex); - int visible = show_text; - pthread_mutex_unlock(&gUpdateMutex); - return visible; -} - -int ui_wait_key() -{ - pthread_mutex_lock(&key_queue_mutex); - while (key_queue_len == 0) { - pthread_cond_wait(&key_queue_cond, &key_queue_mutex); - } - - int key = key_queue[0]; - memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); - pthread_mutex_unlock(&key_queue_mutex); - return key; -} - -int ui_key_pressed(int key) -{ - // This is a volatile static array, don't bother locking - return key_pressed[key]; -} - -void ui_clear_key_queue() { - pthread_mutex_lock(&key_queue_mutex); - key_queue_len = 0; - pthread_mutex_unlock(&key_queue_mutex); -} diff --git a/verifier.c b/verifier.c deleted file mode 100644 index 1180ae8..0000000 --- a/verifier.c +++ /dev/null @@ -1,361 +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 "common.h" -#include "verifier.h" - -#include "minzip/Zip.h" -#include "mincrypt/rsa.h" -#include "mincrypt/sha.h" - -#include <netinet/in.h> /* required for resolv.h */ -#include <resolv.h> /* for base64 codec */ -#include <string.h> - -/* Return an allocated buffer with the contents of a zip file entry. */ -static char *slurpEntry(const ZipArchive *pArchive, const ZipEntry *pEntry) { - if (!mzIsZipEntryIntact(pArchive, pEntry)) { - UnterminatedString fn = mzGetZipEntryFileName(pEntry); - LOGE("Invalid %.*s\n", fn.len, fn.str); - return NULL; - } - - int len = mzGetZipEntryUncompLen(pEntry); - char *buf = malloc(len + 1); - if (buf == NULL) { - UnterminatedString fn = mzGetZipEntryFileName(pEntry); - LOGE("Can't allocate %d bytes for %.*s\n", len, fn.len, fn.str); - return NULL; - } - - if (!mzReadZipEntry(pArchive, pEntry, buf, len)) { - UnterminatedString fn = mzGetZipEntryFileName(pEntry); - LOGE("Can't read %.*s\n", fn.len, fn.str); - free(buf); - return NULL; - } - - buf[len] = '\0'; - return buf; -} - - -struct DigestContext { - SHA_CTX digest; - unsigned *doneBytes; - unsigned totalBytes; -}; - - -/* mzProcessZipEntryContents callback to update an SHA-1 hash context. */ -static bool updateHash(const unsigned char *data, int dataLen, void *cookie) { - struct DigestContext *context = (struct DigestContext *) cookie; - SHA_update(&context->digest, data, dataLen); - if (context->doneBytes != NULL) { - *context->doneBytes += dataLen; - if (context->totalBytes > 0) { - ui_set_progress(*context->doneBytes * 1.0 / context->totalBytes); - } - } - return true; -} - - -/* Get the SHA-1 digest of a zip file entry. */ -static bool digestEntry(const ZipArchive *pArchive, const ZipEntry *pEntry, - unsigned *doneBytes, unsigned totalBytes, - uint8_t digest[SHA_DIGEST_SIZE]) { - struct DigestContext context; - SHA_init(&context.digest); - context.doneBytes = doneBytes; - context.totalBytes = totalBytes; - if (!mzProcessZipEntryContents(pArchive, pEntry, updateHash, &context)) { - UnterminatedString fn = mzGetZipEntryFileName(pEntry); - LOGE("Can't digest %.*s\n", fn.len, fn.str); - return false; - } - - memcpy(digest, SHA_final(&context.digest), SHA_DIGEST_SIZE); - -#ifdef LOG_VERBOSE - UnterminatedString fn = mzGetZipEntryFileName(pEntry); - char base64[SHA_DIGEST_SIZE * 3]; - b64_ntop(digest, SHA_DIGEST_SIZE, base64, sizeof(base64)); - LOGV("sha1(%.*s) = %s\n", fn.len, fn.str, base64); -#endif - - return true; -} - - -/* Find a /META-INF/xxx.SF signature file signed by a matching xxx.RSA file. */ -static const ZipEntry *verifySignature(const ZipArchive *pArchive, - const RSAPublicKey *pKeys, unsigned int numKeys) { - static const char prefix[] = "META-INF/"; - static const char rsa[] = ".RSA", sf[] = ".SF"; - - unsigned int i, j; - for (i = 0; i < mzZipEntryCount(pArchive); ++i) { - const ZipEntry *rsaEntry = mzGetZipEntryAt(pArchive, i); - UnterminatedString rsaName = mzGetZipEntryFileName(rsaEntry); - int rsaLen = mzGetZipEntryUncompLen(rsaEntry); - if (rsaLen >= RSANUMBYTES && rsaName.len > sizeof(prefix) && - !strncmp(rsaName.str, prefix, sizeof(prefix) - 1) && - !strncmp(rsaName.str + rsaName.len - sizeof(rsa) + 1, - rsa, sizeof(rsa) - 1)) { - char *sfName = malloc(rsaName.len - sizeof(rsa) + sizeof(sf) + 1); - if (sfName == NULL) { - LOGE("Can't allocate %d bytes for filename\n", rsaName.len); - continue; - } - - /* Replace .RSA with .SF */ - strncpy(sfName, rsaName.str, rsaName.len - sizeof(rsa) + 1); - strcpy(sfName + rsaName.len - sizeof(rsa) + 1, sf); - const ZipEntry *sfEntry = mzFindZipEntry(pArchive, sfName); - - if (sfEntry == NULL) { - LOGW("Missing signature file %s\n", sfName); - free(sfName); - continue; - } - - free(sfName); - - uint8_t sfDigest[SHA_DIGEST_SIZE]; - if (!digestEntry(pArchive, sfEntry, NULL, 0, sfDigest)) continue; - - char *rsaBuf = slurpEntry(pArchive, rsaEntry); - if (rsaBuf == NULL) continue; - - /* Try to verify the signature with all the keys. */ - uint8_t *sig = (uint8_t *) rsaBuf + rsaLen - RSANUMBYTES; - for (j = 0; j < numKeys; ++j) { - if (RSA_verify(&pKeys[j], sig, RSANUMBYTES, sfDigest)) { - free(rsaBuf); - LOGI("Verified %.*s\n", rsaName.len, rsaName.str); - return sfEntry; - } - } - - free(rsaBuf); - LOGW("Can't verify %.*s\n", rsaName.len, rsaName.str); - } - } - - LOGE("No signature (%d files)\n", mzZipEntryCount(pArchive)); - return NULL; -} - - -/* Verify /META-INF/MANIFEST.MF against the digest in a signature file. */ -static const ZipEntry *verifyManifest(const ZipArchive *pArchive, - const ZipEntry *sfEntry) { - static const char prefix[] = "SHA1-Digest-Manifest: ", eol[] = "\r\n"; - uint8_t expected[SHA_DIGEST_SIZE + 3], actual[SHA_DIGEST_SIZE]; - - char *sfBuf = slurpEntry(pArchive, sfEntry); - if (sfBuf == NULL) return NULL; - - char *line, *save; - for (line = strtok_r(sfBuf, eol, &save); line != NULL; - line = strtok_r(NULL, eol, &save)) { - if (!strncasecmp(prefix, line, sizeof(prefix) - 1)) { - UnterminatedString fn = mzGetZipEntryFileName(sfEntry); - const char *digest = line + sizeof(prefix) - 1; - int n = b64_pton(digest, expected, sizeof(expected)); - if (n != SHA_DIGEST_SIZE) { - LOGE("Invalid base64 in %.*s: %s (%d)\n", - fn.len, fn.str, digest, n); - line = NULL; - } - break; - } - } - - free(sfBuf); - - if (line == NULL) { - LOGE("No digest manifest in signature file\n"); - return false; - } - - const char *mfName = "META-INF/MANIFEST.MF"; - const ZipEntry *mfEntry = mzFindZipEntry(pArchive, mfName); - if (mfEntry == NULL) { - LOGE("No manifest file %s\n", mfName); - return NULL; - } - - if (!digestEntry(pArchive, mfEntry, NULL, 0, actual)) return NULL; - if (memcmp(expected, actual, SHA_DIGEST_SIZE)) { - UnterminatedString fn = mzGetZipEntryFileName(sfEntry); - LOGE("Wrong digest for %s in %.*s\n", mfName, fn.len, fn.str); - return NULL; - } - - LOGI("Verified %s\n", mfName); - return mfEntry; -} - - -/* Verify all the files in a Zip archive against the manifest. */ -static bool verifyArchive(const ZipArchive *pArchive, const ZipEntry *mfEntry) { - static const char namePrefix[] = "Name: "; - static const char contPrefix[] = " "; // Continuation of the filename - static const char digestPrefix[] = "SHA1-Digest: "; - static const char eol[] = "\r\n"; - - char *mfBuf = slurpEntry(pArchive, mfEntry); - if (mfBuf == NULL) return false; - - /* we're using calloc() here, so the initial state of the array is false */ - bool *unverified = (bool *) calloc(mzZipEntryCount(pArchive), sizeof(bool)); - if (unverified == NULL) { - LOGE("Can't allocate valid flags\n"); - free(mfBuf); - return false; - } - - /* Mark all the files in the archive that need to be verified. - * As we scan the manifest and check signatures, we'll unset these flags. - * At the end, we'll make sure that all the flags are unset. - */ - - unsigned i, totalBytes = 0; - for (i = 0; i < mzZipEntryCount(pArchive); ++i) { - const ZipEntry *entry = mzGetZipEntryAt(pArchive, i); - UnterminatedString fn = mzGetZipEntryFileName(entry); - int len = mzGetZipEntryUncompLen(entry); - - // Don't validate: directories, the manifest, *.RSA, and *.SF. - - if (entry == mfEntry) { - LOGV("Skipping manifest %.*s\n", fn.len, fn.str); - } else if (fn.len > 0 && fn.str[fn.len-1] == '/' && len == 0) { - LOGV("Skipping directory %.*s\n", fn.len, fn.str); - } else if (!strncasecmp(fn.str, "META-INF/", 9) && ( - !strncasecmp(fn.str + fn.len - 4, ".RSA", 4) || - !strncasecmp(fn.str + fn.len - 3, ".SF", 3))) { - LOGV("Skipping signature %.*s\n", fn.len, fn.str); - } else { - unverified[i] = true; - totalBytes += len; - } - } - - unsigned doneBytes = 0; - char *line, *save, *name = NULL; - for (line = strtok_r(mfBuf, eol, &save); line != NULL; - line = strtok_r(NULL, eol, &save)) { - if (!strncasecmp(line, namePrefix, sizeof(namePrefix) - 1)) { - // "Name:" introducing a new stanza - if (name != NULL) { - LOGE("No digest:\n %s\n", name); - break; - } - - name = strdup(line + sizeof(namePrefix) - 1); - if (name == NULL) { - LOGE("Can't copy filename in %s\n", line); - break; - } - } else if (!strncasecmp(line, contPrefix, sizeof(contPrefix) - 1)) { - // Continuing a long name (nothing else should be continued) - const char *tail = line + sizeof(contPrefix) - 1; - if (name == NULL) { - LOGE("Unexpected continuation:\n %s\n", tail); - } - - char *concat; - if (asprintf(&concat, "%s%s", name, tail) < 0) { - LOGE("Can't append continuation %s\n", tail); - break; - } - free(name); - name = concat; - } else if (!strncasecmp(line, digestPrefix, sizeof(digestPrefix) - 1)) { - // "Digest:" supplying a hash code for the current stanza - const char *base64 = line + sizeof(digestPrefix) - 1; - if (name == NULL) { - LOGE("Unexpected digest:\n %s\n", base64); - break; - } - - const ZipEntry *entry = mzFindZipEntry(pArchive, name); - if (entry == NULL) { - LOGE("Missing file:\n %s\n", name); - break; - } - if (!mzIsZipEntryIntact(pArchive, entry)) { - LOGE("Corrupt file:\n %s\n", name); - break; - } - if (!unverified[mzGetZipEntryIndex(pArchive, entry)]) { - LOGE("Unexpected file:\n %s\n", name); - break; - } - - uint8_t expected[SHA_DIGEST_SIZE + 3], actual[SHA_DIGEST_SIZE]; - int n = b64_pton(base64, expected, sizeof(expected)); - if (n != SHA_DIGEST_SIZE) { - LOGE("Invalid base64:\n %s\n %s\n", name, base64); - break; - } - - if (!digestEntry(pArchive, entry, &doneBytes, totalBytes, actual) || - memcmp(expected, actual, SHA_DIGEST_SIZE) != 0) { - LOGE("Wrong digest:\n %s\n", name); - break; - } - - LOGI("Verified %s\n", name); - unverified[mzGetZipEntryIndex(pArchive, entry)] = false; - free(name); - name = NULL; - } - } - - if (name != NULL) free(name); - free(mfBuf); - - for (i = 0; i < mzZipEntryCount(pArchive) && !unverified[i]; ++i) ; - free(unverified); - - // This means we didn't get to the end of the manifest successfully. - if (line != NULL) return false; - - if (i < mzZipEntryCount(pArchive)) { - const ZipEntry *entry = mzGetZipEntryAt(pArchive, i); - UnterminatedString fn = mzGetZipEntryFileName(entry); - LOGE("No digest for %.*s\n", fn.len, fn.str); - return false; - } - - return true; -} - - -bool verify_jar_signature(const ZipArchive *pArchive, - const RSAPublicKey *pKeys, int numKeys) { - const ZipEntry *sfEntry = verifySignature(pArchive, pKeys, numKeys); - if (sfEntry == NULL) return false; - - const ZipEntry *mfEntry = verifyManifest(pArchive, sfEntry); - if (mfEntry == NULL) return false; - - return verifyArchive(pArchive, mfEntry); -} diff --git a/verifier.h b/verifier.h deleted file mode 100644 index d784dce..0000000 --- a/verifier.h +++ /dev/null @@ -1,30 +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. - */ - -#ifndef _RECOVERY_VERIFIER_H -#define _RECOVERY_VERIFIER_H - -#include "minzip/Zip.h" -#include "mincrypt/rsa.h" - -/* - * Check the digital signature (as applied by jarsigner) on a Zip archive. - * Every file in the archive must be signed by one of the supplied RSA keys. - */ -bool verify_jar_signature(const ZipArchive *pArchive, - const RSAPublicKey *pKeys, int numKeys); - -#endif /* _RECOVERY_VERIFIER_H */ |