From ffb48f64fec674c6dd923eb8b1eb3f743e05a8ba Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 18:28:14 -0800 Subject: [PATCH] auto import from //depot/cupcake/@135843 --- Android.mk | 60 - amend/Android.mk | 53 - amend/amend.c | 32 - amend/amend.h | 25 - amend/ast.c | 198 --- amend/ast.h | 165 --- amend/commands.c | 273 ---- amend/commands.h | 96 -- amend/execute.c | 315 ----- amend/execute.h | 25 - amend/lexer.h | 43 - amend/lexer.l | 299 ----- amend/main.c | 195 --- amend/parser.h | 24 - amend/parser_y.y | 430 ------ amend/permissions.c | 270 ---- amend/permissions.h | 111 -- amend/register.c | 394 ------ amend/register.h | 23 - amend/symtab.c | 132 -- amend/symtab.h | 34 - amend/test_commands.c | 538 -------- amend/test_permissions.c | 347 ----- amend/test_symtab.c | 146 --- amend/tests/001-nop/expected.txt | 1 - amend/tests/001-nop/info.txt | 2 - amend/tests/001-nop/run | 17 - amend/tests/002-lex-empty/SKIP | 0 amend/tests/002-lex-empty/expected.txt | 1 - amend/tests/002-lex-empty/info.txt | 1 - amend/tests/002-lex-empty/input | 0 amend/tests/002-lex-empty/run | 17 - amend/tests/003-lex-command/expected.txt | 13 - amend/tests/003-lex-command/info.txt | 1 - amend/tests/003-lex-command/input | 6 - amend/tests/003-lex-command/input2 | 1 - amend/tests/003-lex-command/input3 | 1 - amend/tests/003-lex-command/input4 | 1 - amend/tests/003-lex-command/run | 20 - amend/tests/004-lex-comment/expected.txt | 5 - amend/tests/004-lex-comment/info.txt | 1 - amend/tests/004-lex-comment/input | 4 - amend/tests/004-lex-comment/run | 17 - .../tests/005-lex-quoted-string/expected.txt | 13 - amend/tests/005-lex-quoted-string/info.txt | 1 - amend/tests/005-lex-quoted-string/input | 5 - amend/tests/005-lex-quoted-string/input2 | 2 - amend/tests/005-lex-quoted-string/input3 | 2 - amend/tests/005-lex-quoted-string/run | 19 - amend/tests/006-lex-words/SKIP | 0 amend/tests/006-lex-words/expected.txt | 6 - amend/tests/006-lex-words/info.txt | 1 - amend/tests/006-lex-words/input | 5 - amend/tests/006-lex-words/input2 | 2 - amend/tests/006-lex-words/input3 | 2 - amend/tests/006-lex-words/run | 17 - amend/tests/007-lex-real-script/expected.txt | 11 - amend/tests/007-lex-real-script/info.txt | 1 - amend/tests/007-lex-real-script/input | 10 - amend/tests/007-lex-real-script/run | 17 - .../tests/008-parse-real-script/expected.txt | 74 -- amend/tests/008-parse-real-script/info.txt | 1 - amend/tests/008-parse-real-script/input | 10 - amend/tests/008-parse-real-script/run | 17 - amend/tests/XXX-long-token/SKIP | 0 amend/tests/XXX-stack-overflow/SKIP | 0 amend/tests/one-test | 150 --- amend/tests/run-all-tests | 69 - bootloader.c | 267 ---- bootloader.h | 59 - commands.c | 1148 ----------------- commands.h | 28 - common.h | 94 -- etc/META-INF/com/google/android/update-script | 8 - etc/init.rc | 33 - firmware.c | 127 -- firmware.h | 32 - install.c | 186 --- install.h | 25 - minui/Android.mk | 12 - minui/events.c | 82 -- minui/font_10x18.h | 214 --- minui/graphics.c | 312 ----- minui/minui.h | 70 - minui/mkfont.c | 54 - minui/resources.c | 202 --- minzip/Android.mk | 19 - minzip/Bits.h | 357 ----- minzip/DirUtil.c | 280 ---- minzip/DirUtil.h | 51 - minzip/Hash.c | 390 ------ minzip/Hash.h | 186 --- minzip/Inlines.c | 25 - minzip/Log.h | 207 --- minzip/SysUtil.c | 212 --- minzip/SysUtil.h | 61 - minzip/Zip.c | 1098 ---------------- minzip/Zip.h | 206 --- minzip/inline_magic.h | 26 - mtdutils/Android.mk | 23 - mtdutils/flash_image.c | 140 -- mtdutils/mounts.c | 214 --- mtdutils/mounts.h | 31 - mtdutils/mtdutils.c | 510 -------- mtdutils/mtdutils.h | 54 - recovery.c | 471 ------- res/images/icon_error.bmp | Bin 91076 -> 0 bytes res/images/icon_firmware_error.bmp | Bin 91076 -> 0 bytes res/images/icon_firmware_install.bmp | Bin 91076 -> 0 bytes res/images/icon_installing.bmp | Bin 91076 -> 0 bytes res/images/icon_unpacking.bmp | Bin 91076 -> 0 bytes res/images/indeterminate1.bmp | Bin 20214 -> 0 bytes res/images/indeterminate2.bmp | Bin 20214 -> 0 bytes res/images/indeterminate3.bmp | Bin 20214 -> 0 bytes res/images/indeterminate4.bmp | Bin 20214 -> 0 bytes res/images/indeterminate5.bmp | Bin 20214 -> 0 bytes res/images/indeterminate6.bmp | Bin 20214 -> 0 bytes res/images/progress_bar_empty.bmp | Bin 136 -> 0 bytes res/images/progress_bar_empty_left_round.bmp | Bin 294 -> 0 bytes res/images/progress_bar_empty_right_round.bmp | Bin 294 -> 0 bytes res/images/progress_bar_fill.bmp | Bin 136 -> 0 bytes res/images/progress_bar_left_round.bmp | Bin 294 -> 0 bytes res/images/progress_bar_right_round.bmp | Bin 294 -> 0 bytes roots.c | 370 ------ roots.h | 63 - test_roots.c | 81 -- tools/Android.mk | 1 - tools/ota/Android.mk | 42 - tools/ota/add-data-wipe | 118 -- tools/ota/add-property-tag.c | 141 -- tools/ota/check-lost+found.c | 144 --- tools/ota/convert-to-bmp.py | 79 -- tools/ota/make-update-script.c | 228 ---- tools/ota/otatool | 225 ---- ui.c | 542 -------- verifier.c | 361 ------ verifier.h | 30 - 137 files changed, 14711 deletions(-) delete mode 100644 Android.mk delete mode 100644 amend/Android.mk delete mode 100644 amend/amend.c delete mode 100644 amend/amend.h delete mode 100644 amend/ast.c delete mode 100644 amend/ast.h delete mode 100644 amend/commands.c delete mode 100644 amend/commands.h delete mode 100644 amend/execute.c delete mode 100644 amend/execute.h delete mode 100644 amend/lexer.h delete mode 100644 amend/lexer.l delete mode 100644 amend/main.c delete mode 100644 amend/parser.h delete mode 100644 amend/parser_y.y delete mode 100644 amend/permissions.c delete mode 100644 amend/permissions.h delete mode 100644 amend/register.c delete mode 100644 amend/register.h delete mode 100644 amend/symtab.c delete mode 100644 amend/symtab.h delete mode 100644 amend/test_commands.c delete mode 100644 amend/test_permissions.c delete mode 100644 amend/test_symtab.c delete mode 100644 amend/tests/001-nop/expected.txt delete mode 100644 amend/tests/001-nop/info.txt delete mode 100644 amend/tests/001-nop/run delete mode 100644 amend/tests/002-lex-empty/SKIP delete mode 100644 amend/tests/002-lex-empty/expected.txt delete mode 100644 amend/tests/002-lex-empty/info.txt delete mode 100644 amend/tests/002-lex-empty/input delete mode 100644 amend/tests/002-lex-empty/run delete mode 100644 amend/tests/003-lex-command/expected.txt delete mode 100644 amend/tests/003-lex-command/info.txt delete mode 100644 amend/tests/003-lex-command/input delete mode 100644 amend/tests/003-lex-command/input2 delete mode 100644 amend/tests/003-lex-command/input3 delete mode 100644 amend/tests/003-lex-command/input4 delete mode 100644 amend/tests/003-lex-command/run delete mode 100644 amend/tests/004-lex-comment/expected.txt delete mode 100644 amend/tests/004-lex-comment/info.txt delete mode 100644 amend/tests/004-lex-comment/input delete mode 100644 amend/tests/004-lex-comment/run delete mode 100644 amend/tests/005-lex-quoted-string/expected.txt delete mode 100644 amend/tests/005-lex-quoted-string/info.txt delete mode 100644 amend/tests/005-lex-quoted-string/input delete mode 100644 amend/tests/005-lex-quoted-string/input2 delete mode 100644 amend/tests/005-lex-quoted-string/input3 delete mode 100644 amend/tests/005-lex-quoted-string/run delete mode 100644 amend/tests/006-lex-words/SKIP delete mode 100644 amend/tests/006-lex-words/expected.txt delete mode 100644 amend/tests/006-lex-words/info.txt delete mode 100644 amend/tests/006-lex-words/input delete mode 100644 amend/tests/006-lex-words/input2 delete mode 100644 amend/tests/006-lex-words/input3 delete mode 100644 amend/tests/006-lex-words/run delete mode 100644 amend/tests/007-lex-real-script/expected.txt delete mode 100644 amend/tests/007-lex-real-script/info.txt delete mode 100644 amend/tests/007-lex-real-script/input delete mode 100644 amend/tests/007-lex-real-script/run delete mode 100644 amend/tests/008-parse-real-script/expected.txt delete mode 100644 amend/tests/008-parse-real-script/info.txt delete mode 100644 amend/tests/008-parse-real-script/input delete mode 100644 amend/tests/008-parse-real-script/run delete mode 100644 amend/tests/XXX-long-token/SKIP delete mode 100644 amend/tests/XXX-stack-overflow/SKIP delete mode 100755 amend/tests/one-test delete mode 100755 amend/tests/run-all-tests delete mode 100644 bootloader.c delete mode 100644 bootloader.h delete mode 100644 commands.c delete mode 100644 commands.h delete mode 100644 common.h delete mode 100644 etc/META-INF/com/google/android/update-script delete mode 100644 etc/init.rc delete mode 100644 firmware.c delete mode 100644 firmware.h delete mode 100644 install.c delete mode 100644 install.h delete mode 100644 minui/Android.mk delete mode 100644 minui/events.c delete mode 100644 minui/font_10x18.h delete mode 100644 minui/graphics.c delete mode 100644 minui/minui.h delete mode 100644 minui/mkfont.c delete mode 100644 minui/resources.c delete mode 100644 minzip/Android.mk delete mode 100644 minzip/Bits.h delete mode 100644 minzip/DirUtil.c delete mode 100644 minzip/DirUtil.h delete mode 100644 minzip/Hash.c delete mode 100644 minzip/Hash.h delete mode 100644 minzip/Inlines.c delete mode 100644 minzip/Log.h delete mode 100644 minzip/SysUtil.c delete mode 100644 minzip/SysUtil.h delete mode 100644 minzip/Zip.c delete mode 100644 minzip/Zip.h delete mode 100644 minzip/inline_magic.h delete mode 100644 mtdutils/Android.mk delete mode 100644 mtdutils/flash_image.c delete mode 100644 mtdutils/mounts.c delete mode 100644 mtdutils/mounts.h delete mode 100644 mtdutils/mtdutils.c delete mode 100644 mtdutils/mtdutils.h delete mode 100644 recovery.c delete mode 100644 res/images/icon_error.bmp delete mode 100644 res/images/icon_firmware_error.bmp delete mode 100644 res/images/icon_firmware_install.bmp delete mode 100644 res/images/icon_installing.bmp delete mode 100644 res/images/icon_unpacking.bmp delete mode 100644 res/images/indeterminate1.bmp delete mode 100644 res/images/indeterminate2.bmp delete mode 100644 res/images/indeterminate3.bmp delete mode 100644 res/images/indeterminate4.bmp delete mode 100644 res/images/indeterminate5.bmp delete mode 100644 res/images/indeterminate6.bmp delete mode 100644 res/images/progress_bar_empty.bmp delete mode 100644 res/images/progress_bar_empty_left_round.bmp delete mode 100644 res/images/progress_bar_empty_right_round.bmp delete mode 100644 res/images/progress_bar_fill.bmp delete mode 100644 res/images/progress_bar_left_round.bmp delete mode 100644 res/images/progress_bar_right_round.bmp delete mode 100644 roots.c delete mode 100644 roots.h delete mode 100644 test_roots.c delete mode 100644 tools/Android.mk delete mode 100644 tools/ota/Android.mk delete mode 100755 tools/ota/add-data-wipe delete mode 100644 tools/ota/add-property-tag.c delete mode 100644 tools/ota/check-lost+found.c delete mode 100644 tools/ota/convert-to-bmp.py delete mode 100644 tools/ota/make-update-script.c delete mode 100755 tools/ota/otatool delete mode 100644 ui.c delete mode 100644 verifier.c delete mode 100644 verifier.h 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 -#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 -#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\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\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; - - -/* ::= - * | - * - */ -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; -}; - - -/* ::= - * - */ -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; - - -/* ::= - * ! | - * - */ -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; - - -/* ::= - * | - * - */ -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 -#include -#include -#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 -#include -#include -#undef NDEBUG -#include -#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 -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 - #include - #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 */ -{ - {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; - } - } - -{ - {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 */ - -\" { - /* Initial quote */ - gStr.nextc = gStr.value; - BEGIN(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; - } - } - - <> | - \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++); - } - } - } - -{ - /*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; - } - } - -{ - \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 -#include -#include -#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] []\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 - #include - #include - #include - #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 TOK_STRING TOK_IDENTIFIER TOK_WORD - -%type lines -%type command line -%type function_arguments -%type function_arguments_or_empty -%type function_call -%type function_name -%type string_value -%type boolean_expression -%type word_list -%type 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 -#include -#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 - -#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 -#include -#include -#undef NDEBUG -#include -#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 - */ -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 - */ -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 - */ -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 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() - * - * 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() - */ -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(, [, ...]) - * If matches (strcmp) any of ..., returns , - * 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(, [, ...]) - * 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 -#include -#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 -#include -#include -#undef NDEBUG -#include -#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 -#include -#include -#undef NDEBUG -#include -#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 -#undef NDEBUG -#include -#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 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 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 EOL - IDENTIFIER EOL - IDENTIFIER EOL - IDENTIFIER EOL - 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 EOL - IDENTIFIER 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 WORD EOL - IDENTIFIER WORD EOL - IDENTIFIER WORD EOL - IDENTIFIER WORD EOL - IDENTIFIER WORD EOL - EOF - EOL - IDENTIFIERline 2: unterminated string at ' -' - ??? <0> - EOL - IDENTIFIERline 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 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 WORD WORD WORD WORD WORD WORD WORD WORD EOL - IDENTIFIER WORD<12> WORD WORD WORD<)> WORD WORD WORD<\\> WORD WORD EOL - IDENTIFIER WORD WORD WORD WORD WORD WORD EOL - IDENTIFIER WORD WORD WORD EOL - IDENTIFIER WORD<"""shouldn't> WORD WORD WORD WORD 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 IDENTIFIER ( STRING ) == STRING<112345oldhashvalue1234123> EOL - IDENTIFIER WORD WORD EOL - IDENTIFIER WORD WORD EOL - IDENTIFIER IDENTIFIER ( STRING ) == STRING<667890newhashvalue6678909> EOL - IDENTIFIER WORD WORD EOL - IDENTIFIER EOL - IDENTIFIER IDENTIFIER ( STRING , STRING ) == STRING<112345oldhashvalue1234123> EOL - IDENTIFIER STRING == STRING EOL - IDENTIFIER IDENTIFIER ( STRING , IDENTIFIER ( STRING ) ) == STRING EOL - IDENTIFIER IDENTIFIER ( STRING ) == STRING<667890newhashvalue6678909> || IDENTIFIER ( STRING ) == 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 diff --git a/amend/tests/XXX-stack-overflow/SKIP b/amend/tests/XXX-stack-overflow/SKIP deleted file mode 100644 index e69de29..0000000 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 -#include -#include - -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - */ -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 - */ -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 [ ...] - * delete_recursive [ ...] - * - * 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 [] - * - * The contents of will become the contents of . - * The original contents of are preserved unless something - * in 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 [ ...] - * - * 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 [... ] - * set_perm_recursive [... ] - * - * 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 - * - * Use of the on-screen progress meter for the next operation, - * automatically advancing the meter over 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 - * - * Create a symlink, like "ln -s". The link path must not exist already. - * Note that is in root:path format, but 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 - * write_hboot_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 - */ -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 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() - * - * 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() - * - * 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() - */ -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(, [, ...]) - * If matches (strcmp) any of ..., returns , - * 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(, [, ...]) - * 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() - * 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(, ) - * 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 - -// Initialize the graphics system. -void ui_init(); - -// Use KEY_* codes from 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 -#include -#include - -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 -#include -#include -#include - -#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 -#include -#include -#include -#include - -#include - -#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 -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#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 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 -#include - -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 -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#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 -#include - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 -#include - -/* 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 - */ -int dirUnlinkHierarchy(const char *path); - -/* chown -R : - * chmod -R - * - * Sets directories to and files to . 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 -#include - -#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 -#include -#include - -/* 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 - -// --------------------------------------------------------------------- - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include - -#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 - -/* - * 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 -#include -#include -#include // for uintptr_t -#include -#include // for S_ISLNK() -#include - -#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 - -#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 -#include - -#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 -#include -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include -#include // for _IOW, _IOR, mount() -#include -#include -#undef NDEBUG -#include - -#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 // 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 deleted file mode 100644 index 7eb2bbc778f7fe98f15ffb3438ecd191196a3416..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91076 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 diff --git a/res/images/icon_firmware_error.bmp b/res/images/icon_firmware_error.bmp deleted file mode 100644 index 5b8649f17f1186edb119f2c0ce93b36567f5b4c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91076 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 IIJOG>KfFbp%m4rY diff --git a/res/images/icon_firmware_install.bmp b/res/images/icon_firmware_install.bmp deleted file mode 100644 index b0f5f959b4903d5394280589bb61055cf8933c98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91076 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 AyZ`_I diff --git a/res/images/icon_installing.bmp b/res/images/icon_installing.bmp deleted file mode 100644 index fff99fd7e58b882ba65521ea6b42c6e303215a70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91076 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 PfYgB0fYiV*Py_!DLb`NA diff --git a/res/images/indeterminate1.bmp b/res/images/indeterminate1.bmp deleted file mode 100644 index 716c92568eed57f402e594e8d7b93f2a4e009670..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20214 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 diff --git a/res/images/indeterminate4.bmp b/res/images/indeterminate4.bmp deleted file mode 100644 index 87b2640343fda36e46484bf7ed0da7640c94eb20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20214 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 G%zpsCXBAff diff --git a/res/images/indeterminate5.bmp b/res/images/indeterminate5.bmp deleted file mode 100644 index e16efb04c42464b99b83eb9f7d9e3a591c883c75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20214 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 diff --git a/res/images/indeterminate6.bmp b/res/images/indeterminate6.bmp deleted file mode 100644 index 085ad951a853ec76353e9a4ab8adf85b71310621..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20214 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 Oyty9dZ8P3CHvS7=)D;T= diff --git a/res/images/progress_bar_empty.bmp b/res/images/progress_bar_empty.bmp deleted file mode 100644 index 8e512fd9276337a51c8ac67afe44b036aba1eb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmZ?r?O=caGa#h_#Ed{J0;VN^Bm+Yb5DRfbFjxRc^mO$w6qgn=WT$2`L?uQsB*!L0 z=+tC}?96P2?A&aI;=*Ev>dI<{>e_0CmZlblDU+sv@tk>c7(jUKvb79LS1o1Ox^64b FL;$0WAW;AS diff --git a/res/images/progress_bar_empty_left_round.bmp b/res/images/progress_bar_empty_left_round.bmp deleted file mode 100644 index c4e2f44fc6f46b7e054425f58a56f5ce7d07f643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmXw!u?mAQ5Qde$LLZ=0=@aw;y7vVH2MG=$1xx54;wBwR=pdnkh(jR`LY9KBk~eX3 z_E9Z;~p- z_s^OPym`#*?6A99&*Lb>l6gTUWJ=;_#{3T%8OB1xT#P@RPX&NTA2diuihP?R&vK|t zd6g<8n*?;9qzMG+1vWgBnpRsP&J^T+@Q!;1^q%_%s+{YE|xAkKA;}49{ls*6e diff --git a/res/images/progress_bar_fill.bmp b/res/images/progress_bar_fill.bmp deleted file mode 100644 index 8d57d81174bc6798c32bccfe1f7d7a1cf965d1b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmZ?r?O=caGa#h_#Ed{J0;VN^Bm+Yb5DRfbFjxRYod3_ja2$wtLGdOiy$wlhACL{g VAayW&8psCe1>wt3d>u$L007pqC364( diff --git a/res/images/progress_bar_left_round.bmp b/res/images/progress_bar_left_round.bmp deleted file mode 100644 index 6d2df8d6a44a33706375ce94b4404a363a693379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmZ?rRbylT12Z700mRHeECR%g3<^LJ0zgWj%D@8u|Nm!jT6L^I;PCgKmh<)&aP0g3 zm*M#T|BB15U1QhDw8Yy+}kcoUEf!Z1FF2C0Sdq52s10mVQV#z&@Mav&OL zAH!iZ3=%^Yhw(x5c_2Ow!2-vDZUeD_VupvGUjxel*+KiR6>yyX|Cix1(1$?jsKfUP J1kQi|2>||Oqy+!~ diff --git a/res/images/progress_bar_right_round.bmp b/res/images/progress_bar_right_round.bmp deleted file mode 100644 index 68bb6fe3727bbbaa81390f996a9ecf4ecb770cff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmZ?rRbylT12Z700mRHeECR%g3<^LJ0zgWj%D@5whrj=HT6L`8|Ns9C49EZf=h*lC zujRbG1q{1@0zj;|?AkSkZ9p~4Z=_{3>u_w9}q+J!)bIe5FdsQ1KA)9 zv>%LNd>9QAhta2j>OlBB6a(1;$ANBx@(m9^zs7JG=-$)+{|4>5Rv>Wx`_HJu_rQJx E00 -#include -#include -#include -#include -#include - -#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 -#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 " - 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 -#include -#include -#include -#include -#include -#include - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include - -/* - * Recursively walk the directory tree at /, 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-options] " - echo " Where 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 -o|--output " - echo " Append the contents of to the install script" - echo " --replace-script -o|--output " - echo " Replace the install script with the contents of " - 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 \" or \"--output \"" - fi - shift - - OUTFILE="$1" - shift - if [ -z "$OUTFILE" ] - then - usage "$CMD requires \"-o \" or \"--output \"" - 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 diff --git a/ui.c b/ui.c deleted file mode 100644 index 5d06561..0000000 --- a/ui.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 /* required for resolv.h */ -#include /* for base64 codec */ -#include - -/* 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 */