diff options
233 files changed, 3350 insertions, 6969 deletions
diff --git a/Android.mk b/Android.mk index 589bff41f..dbc5603d8 100644 --- a/Android.mk +++ b/Android.mk @@ -14,18 +14,28 @@ LOCAL_PATH := $(call my-dir) +# libfusesideload (static library) +# =============================== include $(CLEAR_VARS) - LOCAL_SRC_FILES := fuse_sideload.cpp LOCAL_CLANG := true -LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter +LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -Werror LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE - LOCAL_MODULE := libfusesideload +LOCAL_STATIC_LIBRARIES := libcutils libc libcrypto +include $(BUILD_STATIC_LIBRARY) -LOCAL_STATIC_LIBRARIES := libcutils libc libcrypto_static +# libmounts (static library) +# =============================== +include $(CLEAR_VARS) +LOCAL_SRC_FILES := mounts.cpp +LOCAL_CLANG := true +LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror +LOCAL_MODULE := libmounts include $(BUILD_STATIC_LIBRARY) +# recovery (static executable) +# =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ @@ -55,12 +65,11 @@ endif RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) -LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_CFLAGS += -Wno-unused-parameter -Werror LOCAL_CLANG := true LOCAL_C_INCLUDES += \ system/vold \ - system/extras/ext4_utils \ system/core/adb \ LOCAL_STATIC_LIBRARIES := \ @@ -68,15 +77,17 @@ LOCAL_STATIC_LIBRARIES := \ libbootloader_message \ libext4_utils_static \ libsparse_static \ - libminzip \ + libziparchive \ + libotautil \ + libmounts \ libz \ - libmtdutils \ libminadbd \ libfusesideload \ libminui \ libpng \ libfs_mgr \ - libcrypto_static \ + libcrypto_utils \ + libcrypto \ libbase \ libcutils \ libutils \ @@ -87,12 +98,6 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_HAL_STATIC_LIBRARIES := libhealthd -ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) - LOCAL_CFLAGS += -DUSE_EXT4 - LOCAL_C_INCLUDES += system/extras/ext4_utils - LOCAL_STATIC_LIBRARIES += libext4_utils_static libz -endif - ifeq ($(AB_OTA_UPDATER),true) LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 endif @@ -131,7 +136,8 @@ LOCAL_CFLAGS := -Werror LOCAL_INIT_RC := recovery-refresh.rc include $(BUILD_EXECUTABLE) -# All the APIs for testing +# libverifier (static library) +# =============================== include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_MODULE := libverifier @@ -140,18 +146,18 @@ LOCAL_SRC_FILES := \ asn1_decoder.cpp \ verifier.cpp \ ui.cpp -LOCAL_STATIC_LIBRARIES := libcrypto_static +LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase +LOCAL_CFLAGS := -Werror include $(BUILD_STATIC_LIBRARY) include \ $(LOCAL_PATH)/applypatch/Android.mk \ $(LOCAL_PATH)/bootloader_message/Android.mk \ $(LOCAL_PATH)/edify/Android.mk \ - $(LOCAL_PATH)/minui/Android.mk \ - $(LOCAL_PATH)/minzip/Android.mk \ $(LOCAL_PATH)/minadbd/Android.mk \ - $(LOCAL_PATH)/mtdutils/Android.mk \ + $(LOCAL_PATH)/minui/Android.mk \ $(LOCAL_PATH)/otafault/Android.mk \ + $(LOCAL_PATH)/otautil/Android.mk \ $(LOCAL_PATH)/tests/Android.mk \ $(LOCAL_PATH)/tools/Android.mk \ $(LOCAL_PATH)/uncrypt/Android.mk \ diff --git a/adb_install.cpp b/adb_install.cpp index 4aed9d4b1..fab72f8a4 100644 --- a/adb_install.cpp +++ b/adb_install.cpp @@ -26,17 +26,15 @@ #include <fcntl.h> #include "ui.h" -#include "cutils/properties.h" #include "install.h" #include "common.h" #include "adb_install.h" #include "minadbd/fuse_adb_provider.h" #include "fuse_sideload.h" -static RecoveryUI* ui = NULL; +#include <android-base/properties.h> -static void -set_usb_driver(bool enabled) { +static void set_usb_driver(RecoveryUI* ui, bool enabled) { int fd = open("/sys/class/android_usb/android0/enable", O_WRONLY); if (fd < 0) { ui->Print("failed to open driver control: %s\n", strerror(errno)); @@ -50,19 +48,17 @@ set_usb_driver(bool enabled) { } } -static void -stop_adbd() { - property_set("ctl.stop", "adbd"); - set_usb_driver(false); +static void stop_adbd(RecoveryUI* ui) { + ui->Print("Stopping adbd...\n"); + android::base::SetProperty("ctl.stop", "adbd"); + set_usb_driver(ui, false); } - -static void -maybe_restart_adbd() { +static void maybe_restart_adbd(RecoveryUI* ui) { if (is_ro_debuggable()) { ui->Print("Restarting adbd...\n"); - set_usb_driver(true); - property_set("ctl.start", "adbd"); + set_usb_driver(ui, true); + android::base::SetProperty("ctl.start", "adbd"); } } @@ -70,14 +66,11 @@ maybe_restart_adbd() { // package, before timing out. #define ADB_INSTALL_TIMEOUT 300 -int -apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) { +int apply_from_adb(RecoveryUI* ui, bool* wipe_cache, const char* install_file) { modified_flash = true; - ui = ui_; - - stop_adbd(); - set_usb_driver(true); + stop_adbd(ui); + set_usb_driver(ui, true); ui->Print("\n\nNow send the package you want to apply\n" "to the device with \"adb sideload <filename>\"...\n"); @@ -137,8 +130,8 @@ apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) { } } - set_usb_driver(false); - maybe_restart_adbd(); + set_usb_driver(ui, false); + maybe_restart_adbd(ui); return result; } diff --git a/applypatch/Android.mk b/applypatch/Android.mk index 887a570db..9bbac4410 100644 --- a/applypatch/Android.mk +++ b/applypatch/Android.mk @@ -14,61 +14,90 @@ LOCAL_PATH := $(call my-dir) +# libapplypatch (static library) +# =============================== include $(CLEAR_VARS) - LOCAL_CLANG := true -LOCAL_SRC_FILES := applypatch.cpp bspatch.cpp freecache.cpp imgpatch.cpp utils.cpp +LOCAL_SRC_FILES := \ + applypatch.cpp \ + bspatch.cpp \ + freecache.cpp \ + imgpatch.cpp \ + utils.cpp LOCAL_MODULE := libapplypatch LOCAL_MODULE_TAGS := eng -LOCAL_C_INCLUDES += bootable/recovery -LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libcrypto_static libbz libz - +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/include \ + bootable/recovery +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_STATIC_LIBRARIES += \ + libotafault \ + libbase \ + libcrypto \ + libbz \ + libz +LOCAL_CFLAGS := -Werror include $(BUILD_STATIC_LIBRARY) +# libimgpatch (static library) +# =============================== include $(CLEAR_VARS) - LOCAL_CLANG := true LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp LOCAL_MODULE := libimgpatch -LOCAL_C_INCLUDES += bootable/recovery +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/include \ + bootable/recovery LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz - +LOCAL_STATIC_LIBRARIES += libcrypto libbz libz +LOCAL_CFLAGS := -Werror include $(BUILD_STATIC_LIBRARY) -ifeq ($(HOST_OS),linux) +# libimgpatch (host static library) +# =============================== include $(CLEAR_VARS) - LOCAL_CLANG := true LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp LOCAL_MODULE := libimgpatch -LOCAL_C_INCLUDES += bootable/recovery +LOCAL_MODULE_HOST_OS := linux +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/include \ + bootable/recovery LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz - +LOCAL_STATIC_LIBRARIES += libcrypto libbz libz +LOCAL_CFLAGS := -Werror include $(BUILD_HOST_STATIC_LIBRARY) -endif # HOST_OS == linux +# applypatch (executable) +# =============================== include $(CLEAR_VARS) - LOCAL_CLANG := true LOCAL_SRC_FILES := main.cpp LOCAL_MODULE := applypatch LOCAL_C_INCLUDES += bootable/recovery -LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz \ - libedify \ - -LOCAL_SHARED_LIBRARIES += libz libcutils libc - +LOCAL_STATIC_LIBRARIES += \ + libapplypatch \ + libbase \ + libedify \ + libotafault \ + libcrypto \ + libbz +LOCAL_SHARED_LIBRARIES += libbase libz libcutils libc +LOCAL_CFLAGS := -Werror include $(BUILD_EXECUTABLE) +# imgdiff (host static executable) +# =============================== include $(CLEAR_VARS) - LOCAL_CLANG := true -LOCAL_SRC_FILES := imgdiff.cpp utils.cpp bsdiff.cpp +LOCAL_SRC_FILES := imgdiff.cpp utils.cpp LOCAL_MODULE := imgdiff +LOCAL_STATIC_LIBRARIES += \ + libbsdiff \ + libbz \ + libdivsufsort64 \ + libdivsufsort \ + libz +LOCAL_CFLAGS := -Werror LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_C_INCLUDES += external/zlib external/bzip2 -LOCAL_STATIC_LIBRARIES += libz libbz - include $(BUILD_HOST_EXECUTABLE) diff --git a/applypatch/Makefile b/applypatch/Makefile new file mode 100644 index 000000000..fb4984303 --- /dev/null +++ b/applypatch/Makefile @@ -0,0 +1,33 @@ +# Copyright (C) 2016 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. + +# This file is for building imgdiff in Chrome OS. + +CPPFLAGS += -iquote.. -Iinclude +CXXFLAGS += -std=c++11 -O3 -Wall -Werror +LDLIBS += -lbz2 -lz + +.PHONY: all clean + +all: imgdiff libimgpatch.a + +clean: + rm -f *.o imgdiff libimgpatch.a + +imgdiff: imgdiff.o bsdiff.o utils.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDLIBS) -o $@ $^ + +libimgpatch.a utils.o: CXXFLAGS += -fPIC +libimgpatch.a: imgpatch.o bspatch.o utils.o + ${AR} rcs $@ $^ diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index 7985fc0c6..48e4c8386 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -31,8 +31,7 @@ #include <android-base/strings.h> #include "openssl/sha.h" -#include "applypatch.h" -#include "mtdutils/mtdutils.h" +#include "applypatch/applypatch.h" #include "edify/expr.h" #include "ota_io.h" #include "print_sha1.h" @@ -49,17 +48,14 @@ static int GenerateTarget(FileContents* source_file, size_t target_size, const Value* bonus_data); -static bool mtd_partitions_scanned = false; - // Read a file into memory; store the file contents and associated // metadata in *file. // // Return 0 on success. int LoadFileContents(const char* filename, FileContents* file) { - // A special 'filename' beginning with "MTD:" or "EMMC:" means to + // A special 'filename' beginning with "EMMC:" means to // load the contents of a partition. - if (strncmp(filename, "MTD:", 4) == 0 || - strncmp(filename, "EMMC:", 5) == 0) { + if (strncmp(filename, "EMMC:", 5) == 0) { return LoadPartitionContents(filename, file); } @@ -77,7 +73,7 @@ int LoadFileContents(const char* filename, FileContents* file) { size_t bytes_read = ota_fread(data.data(), 1, data.size(), f); if (bytes_read != data.size()) { - printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, data.size()); + printf("short read of \"%s\" (%zu bytes of %zu)\n", filename, bytes_read, data.size()); ota_fclose(f); return -1; } @@ -87,10 +83,9 @@ int LoadFileContents(const char* filename, FileContents* file) { return 0; } -// Load the contents of an MTD or EMMC partition into the provided +// Load the contents of an EMMC partition into the provided // FileContents. filename should be a string of the form -// "MTD:<partition_name>:<size_1>:<sha1_1>:<size_2>:<sha1_2>:..." (or -// "EMMC:<partition_device>:..."). The smallest size_n bytes for +// "EMMC:<partition_device>:...". The smallest size_n bytes for // which that prefix of the partition contents has the corresponding // sha1 hash will be loaded. It is acceptable for a size value to be // repeated with different sha1s. Will return 0 on success. @@ -102,8 +97,6 @@ int LoadFileContents(const char* filename, FileContents* file) { // "end-of-file" marker), so the caller must specify the possible // lengths and the hash of the data, and we'll do the load expecting // to find one of those hashes. -enum PartitionType { MTD, EMMC }; - static int LoadPartitionContents(const char* filename, FileContents* file) { std::string copy(filename); std::vector<std::string> pieces = android::base::Split(copy, ":"); @@ -112,12 +105,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) { return -1; } - enum PartitionType type; - if (pieces[0] == "MTD") { - type = MTD; - } else if (pieces[0] == "EMMC") { - type = EMMC; - } else { + if (pieces[0] != "EMMC") { printf("LoadPartitionContents called with bad filename (%s)\n", filename); return -1; } @@ -145,36 +133,10 @@ static int LoadPartitionContents(const char* filename, FileContents* file) { } ); - MtdReadContext* ctx = NULL; - FILE* dev = NULL; - - switch (type) { - case MTD: { - if (!mtd_partitions_scanned) { - mtd_scan_partitions(); - mtd_partitions_scanned = true; - } - - const MtdPartition* mtd = mtd_find_partition_by_name(partition); - if (mtd == NULL) { - printf("mtd partition \"%s\" not found (loading %s)\n", partition, filename); - return -1; - } - - ctx = mtd_read_partition(mtd); - if (ctx == NULL) { - printf("failed to initialize read of mtd partition \"%s\"\n", partition); - return -1; - } - break; - } - - case EMMC: - dev = ota_fopen(partition, "rb"); - if (dev == NULL) { - printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); - return -1; - } + FILE* dev = ota_fopen(partition, "rb"); + if (dev == NULL) { + printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); + return -1; } SHA_CTX sha_ctx; @@ -192,16 +154,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) { // we're trying the possibilities in order of increasing size). size_t next = size[index[i]] - data_size; if (next > 0) { - size_t read = 0; - switch (type) { - case MTD: - read = mtd_read_data(ctx, p, next); - break; - - case EMMC: - read = ota_fread(p, 1, next, dev); - break; - } + size_t read = ota_fread(p, 1, next, dev); if (next != read) { printf("short read (%zu bytes of %zu) for partition \"%s\"\n", read, next, partition); @@ -234,16 +187,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) { } } - switch (type) { - case MTD: - mtd_read_close(ctx); - break; - - case EMMC: - ota_fclose(dev); - break; - } - + ota_fclose(dev); if (!found) { // Ran off the end of the list of (size,sha1) pairs without finding a match. @@ -302,7 +246,7 @@ int SaveFileContents(const char* filename, const FileContents* file) { } // Write a memory buffer to 'target' partition, a string of the form -// "MTD:<partition>[:...]" or "EMMC:<partition_device>[:...]". The target name +// "EMMC:<partition_device>[:...]". The target name // might contain multiple colons, but WriteToPartition() only uses the first // two and ignores the rest. Return 0 on success. int WriteToPartition(const unsigned char* data, size_t len, const char* target) { @@ -314,165 +258,120 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target) return -1; } - enum PartitionType type; - if (pieces[0] == "MTD") { - type = MTD; - } else if (pieces[0] == "EMMC") { - type = EMMC; - } else { + if (pieces[0] != "EMMC") { printf("WriteToPartition called with bad target (%s)\n", target); return -1; } const char* partition = pieces[1].c_str(); - switch (type) { - case MTD: { - if (!mtd_partitions_scanned) { - mtd_scan_partitions(); - mtd_partitions_scanned = true; - } - - const MtdPartition* mtd = mtd_find_partition_by_name(partition); - if (mtd == NULL) { - printf("mtd partition \"%s\" not found for writing\n", partition); - return -1; - } - - MtdWriteContext* ctx = mtd_write_partition(mtd); - if (ctx == NULL) { - printf("failed to init mtd partition \"%s\" for writing\n", partition); - return -1; - } + size_t start = 0; + bool success = false; + int fd = ota_open(partition, O_RDWR | O_SYNC); + if (fd < 0) { + printf("failed to open %s: %s\n", partition, strerror(errno)); + return -1; + } - size_t written = mtd_write_data(ctx, reinterpret_cast<const char*>(data), len); - if (written != len) { - printf("only wrote %zu of %zu bytes to MTD %s\n", written, len, partition); - mtd_write_close(ctx); - return -1; - } + for (size_t attempt = 0; attempt < 2; ++attempt) { + if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { + printf("failed seek on %s: %s\n", partition, strerror(errno)); + return -1; + } + while (start < len) { + size_t to_write = len - start; + if (to_write > 1<<20) to_write = 1<<20; - if (mtd_erase_blocks(ctx, -1) < 0) { - printf("error finishing mtd write of %s\n", partition); - mtd_write_close(ctx); + ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write)); + if (written == -1) { + printf("failed write writing to %s: %s\n", partition, strerror(errno)); return -1; } + start += written; + } + if (ota_fsync(fd) != 0) { + printf("failed to sync to %s (%s)\n", partition, strerror(errno)); + return -1; + } + if (ota_close(fd) != 0) { + printf("failed to close %s (%s)\n", partition, strerror(errno)); + return -1; + } + fd = ota_open(partition, O_RDONLY); + if (fd < 0) { + printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno)); + return -1; + } - if (mtd_write_close(ctx)) { - printf("error closing mtd write of %s\n", partition); - return -1; - } - break; + // Drop caches so our subsequent verification read + // won't just be reading the cache. + sync(); + int dc = ota_open("/proc/sys/vm/drop_caches", O_WRONLY); + if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) { + printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno)); + } else { + printf(" caches dropped\n"); } + ota_close(dc); + sleep(1); - case EMMC: { - size_t start = 0; - bool success = false; - int fd = ota_open(partition, O_RDWR | O_SYNC); - if (fd < 0) { - printf("failed to open %s: %s\n", partition, strerror(errno)); - return -1; + // verify + if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) { + printf("failed to seek back to beginning of %s: %s\n", + partition, strerror(errno)); + return -1; + } + unsigned char buffer[4096]; + start = len; + for (size_t p = 0; p < len; p += sizeof(buffer)) { + size_t to_read = len - p; + if (to_read > sizeof(buffer)) { + to_read = sizeof(buffer); } - for (size_t attempt = 0; attempt < 2; ++attempt) { - if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { - printf("failed seek on %s: %s\n", partition, strerror(errno)); + size_t so_far = 0; + while (so_far < to_read) { + ssize_t read_count = + TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far)); + if (read_count == -1) { + printf("verify read error %s at %zu: %s\n", + partition, p, strerror(errno)); return -1; - } - while (start < len) { - size_t to_write = len - start; - if (to_write > 1<<20) to_write = 1<<20; - - ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write)); - if (written == -1) { - printf("failed write writing to %s: %s\n", partition, strerror(errno)); - return -1; - } - start += written; - } - if (ota_fsync(fd) != 0) { - printf("failed to sync to %s (%s)\n", partition, strerror(errno)); - return -1; - } - if (ota_close(fd) != 0) { - printf("failed to close %s (%s)\n", partition, strerror(errno)); - return -1; - } - fd = ota_open(partition, O_RDONLY); - if (fd < 0) { - printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno)); - return -1; - } - - // Drop caches so our subsequent verification read - // won't just be reading the cache. - sync(); - int dc = ota_open("/proc/sys/vm/drop_caches", O_WRONLY); - if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) { - printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno)); - } else { - printf(" caches dropped\n"); - } - ota_close(dc); - sleep(1); - - // verify - if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) { - printf("failed to seek back to beginning of %s: %s\n", - partition, strerror(errno)); + } else if (read_count == 0) { + printf("verify read reached unexpected EOF, %s at %zu\n", partition, p); return -1; } - unsigned char buffer[4096]; - start = len; - for (size_t p = 0; p < len; p += sizeof(buffer)) { - size_t to_read = len - p; - if (to_read > sizeof(buffer)) { - to_read = sizeof(buffer); - } - - size_t so_far = 0; - while (so_far < to_read) { - ssize_t read_count = - TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far)); - if (read_count == -1) { - printf("verify read error %s at %zu: %s\n", - partition, p, strerror(errno)); - return -1; - } - if (static_cast<size_t>(read_count) < to_read) { - printf("short verify read %s at %zu: %zd %zu %s\n", - partition, p, read_count, to_read, strerror(errno)); - } - so_far += read_count; - } - - if (memcmp(buffer, data+p, to_read) != 0) { - printf("verification failed starting at %zu\n", p); - start = p; - break; - } - } - - if (start == len) { - printf("verification read succeeded (attempt %zu)\n", attempt+1); - success = true; - break; + if (static_cast<size_t>(read_count) < to_read) { + printf("short verify read %s at %zu: %zd %zu %s\n", + partition, p, read_count, to_read, strerror(errno)); } + so_far += read_count; } - if (!success) { - printf("failed to verify after all attempts\n"); - return -1; + if (memcmp(buffer, data+p, to_read) != 0) { + printf("verification failed starting at %zu\n", p); + start = p; + break; } + } - if (ota_close(fd) != 0) { - printf("error closing %s (%s)\n", partition, strerror(errno)); - return -1; - } - sync(); + if (start == len) { + printf("verification read succeeded (attempt %zu)\n", attempt+1); + success = true; break; } } + if (!success) { + printf("failed to verify after all attempts\n"); + return -1; + } + + if (ota_close(fd) != 0) { + printf("error closing %s (%s)\n", partition, strerror(errno)); + return -1; + } + sync(); + return 0; } @@ -509,11 +408,10 @@ int ParseSha1(const char* str, uint8_t* digest) { // Search an array of sha1 strings for one matching the given sha1. // Return the index of the match on success, or -1 if no match is // found. -int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, - int num_patches) { - uint8_t patch_sha1[SHA_DIGEST_LENGTH]; - for (int i = 0; i < num_patches; ++i) { - if (ParseSha1(patch_sha1_str[i], patch_sha1) == 0 && +int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) { + for (size_t i = 0; i < patch_sha1_str.size(); ++i) { + uint8_t patch_sha1[SHA_DIGEST_LENGTH]; + if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 && memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { return i; } @@ -524,8 +422,7 @@ int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, // Returns 0 if the contents of the file (argv[2]) or the cached file // match any of the sha1's on the command line (argv[3:]). Returns // nonzero otherwise. -int applypatch_check(const char* filename, int num_patches, - char** const patch_sha1_str) { +int applypatch_check(const char* filename, const std::vector<std::string>& patch_sha1_str) { FileContents file; // It's okay to specify no sha1s; the check will pass if the @@ -533,8 +430,7 @@ int applypatch_check(const char* filename, int num_patches, // partitions, where the filename encodes the sha1s; no need to // check them twice.) if (LoadFileContents(filename, &file) != 0 || - (num_patches > 0 && - FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0)) { + (patch_sha1_str.size() > 0 && FindMatchingPatch(file.sha1, patch_sha1_str) < 0)) { printf("file \"%s\" doesn't have any of expected " "sha1 sums; checking cache\n", filename); @@ -549,7 +445,7 @@ int applypatch_check(const char* filename, int num_patches, return 1; } - if (FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0) { + if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) { printf("cache bits don't match any sha1 for \"%s\"\n", filename); return 1; } @@ -596,7 +492,7 @@ size_t FreeSpaceForFile(const char* filename) { int CacheSizeCheck(size_t bytes) { if (MakeFreeSpaceOnCache(bytes) < 0) { - printf("unable to make %ld bytes available on /cache\n", (long)bytes); + printf("unable to make %zu bytes available on /cache\n", bytes); return 1; } else { return 0; @@ -633,8 +529,7 @@ int applypatch(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t target_size, - int num_patches, - char** const patch_sha1_str, + const std::vector<std::string>& patch_sha1_str, Value** patch_data, Value* bonus_data) { printf("patch %s: ", source_filename); @@ -674,7 +569,7 @@ int applypatch(const char* source_filename, } if (!source_file.data.empty()) { - int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str, num_patches); + int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str); if (to_use >= 0) { source_patch_value = patch_data[to_use]; } @@ -690,7 +585,7 @@ int applypatch(const char* source_filename, return 1; } - int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str, num_patches); + int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str); if (to_use >= 0) { copy_patch_value = patch_data[to_use]; } @@ -729,7 +624,7 @@ int applypatch_flash(const char* source_filename, const char* target_filename, std::string target_str(target_filename); std::vector<std::string> pieces = android::base::Split(target_str, ":"); - if (pieces.size() != 2 || (pieces[0] != "MTD" && pieces[0] != "EMMC")) { + if (pieces.size() != 2 || pieces[0] != "EMMC") { printf("invalid target name \"%s\"", target_filename); return 1; } @@ -778,8 +673,7 @@ static int GenerateTarget(FileContents* source_file, FileContents* source_to_use; int made_copy = 0; - bool target_is_partition = (strncmp(target_filename, "MTD:", 4) == 0 || - strncmp(target_filename, "EMMC:", 5) == 0); + bool target_is_partition = (strncmp(target_filename, "EMMC:", 5) == 0); const std::string tmp_target_filename = std::string(target_filename) + ".patch"; // assume that target_filename (eg "/system/app/Foo.apk") is located @@ -803,8 +697,8 @@ static int GenerateTarget(FileContents* source_file, printf("patch is not a blob\n"); return 1; } - char* header = patch->data; - ssize_t header_bytes_read = patch->size; + const char* header = &patch->data[0]; + size_t header_bytes_read = patch->data.size(); bool use_bsdiff = false; if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { use_bsdiff = true; @@ -860,8 +754,7 @@ static int GenerateTarget(FileContents* source_file, // copy the source file to cache, then delete it from the original // location. - if (strncmp(source_filename, "MTD:", 4) == 0 || - strncmp(source_filename, "EMMC:", 5) == 0) { + if (strncmp(source_filename, "EMMC:", 5) == 0) { // It's impossible to free space on the target filesystem by // deleting the source if the source is a partition. If // we're ever in a state where we need to do this, fail. @@ -897,7 +790,7 @@ static int GenerateTarget(FileContents* source_file, } else { // We write the decoded output to "<tgt-file>.patch". output_fd = ota_open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, - S_IRUSR | S_IWUSR); + S_IRUSR | S_IWUSR); if (output_fd < 0) { printf("failed to open output file %s: %s\n", tmp_target_filename.c_str(), strerror(errno)); diff --git a/applypatch/bsdiff.cpp b/applypatch/bsdiff.cpp deleted file mode 100644 index 55dbe5cf1..000000000 --- a/applypatch/bsdiff.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Most of this code comes from bsdiff.c from the bsdiff-4.3 - * distribution, which is: - */ - -/*- - * Copyright 2003-2005 Colin Percival - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted providing that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> - -#include <bzlib.h> -#include <err.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define MIN(x,y) (((x)<(y)) ? (x) : (y)) - -static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h) -{ - off_t i,j,k,x,tmp,jj,kk; - - if(len<16) { - for(k=start;k<start+len;k+=j) { - j=1;x=V[I[k]+h]; - for(i=1;k+i<start+len;i++) { - if(V[I[k+i]+h]<x) { - x=V[I[k+i]+h]; - j=0; - }; - if(V[I[k+i]+h]==x) { - tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp; - j++; - }; - }; - for(i=0;i<j;i++) V[I[k+i]]=k+j-1; - if(j==1) I[k]=-1; - }; - return; - }; - - x=V[I[start+len/2]+h]; - jj=0;kk=0; - for(i=start;i<start+len;i++) { - if(V[I[i]+h]<x) jj++; - if(V[I[i]+h]==x) kk++; - }; - jj+=start;kk+=jj; - - i=start;j=0;k=0; - while(i<jj) { - if(V[I[i]+h]<x) { - i++; - } else if(V[I[i]+h]==x) { - tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp; - j++; - } else { - tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp; - k++; - }; - }; - - while(jj+j<kk) { - if(V[I[jj+j]+h]==x) { - j++; - } else { - tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp; - k++; - }; - }; - - if(jj>start) split(I,V,start,jj-start,h); - - for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1; - if(jj==kk-1) I[jj]=-1; - - if(start+len>kk) split(I,V,kk,start+len-kk,h); -} - -static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize) -{ - off_t buckets[256]; - off_t i,h,len; - - for(i=0;i<256;i++) buckets[i]=0; - for(i=0;i<oldsize;i++) buckets[old[i]]++; - for(i=1;i<256;i++) buckets[i]+=buckets[i-1]; - for(i=255;i>0;i--) buckets[i]=buckets[i-1]; - buckets[0]=0; - - for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i; - I[0]=oldsize; - for(i=0;i<oldsize;i++) V[i]=buckets[old[i]]; - V[oldsize]=0; - for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1; - I[0]=-1; - - for(h=1;I[0]!=-(oldsize+1);h+=h) { - len=0; - for(i=0;i<oldsize+1;) { - if(I[i]<0) { - len-=I[i]; - i-=I[i]; - } else { - if(len) I[i-len]=-len; - len=V[I[i]]+1-i; - split(I,V,i,len,h); - i+=len; - len=0; - }; - }; - if(len) I[i-len]=-len; - }; - - for(i=0;i<oldsize+1;i++) I[V[i]]=i; -} - -static off_t matchlen(u_char *olddata,off_t oldsize,u_char *newdata,off_t newsize) -{ - off_t i; - - for(i=0;(i<oldsize)&&(i<newsize);i++) - if(olddata[i]!=newdata[i]) break; - - return i; -} - -static off_t search(off_t *I,u_char *old,off_t oldsize, - u_char *newdata,off_t newsize,off_t st,off_t en,off_t *pos) -{ - off_t x,y; - - if(en-st<2) { - x=matchlen(old+I[st],oldsize-I[st],newdata,newsize); - y=matchlen(old+I[en],oldsize-I[en],newdata,newsize); - - if(x>y) { - *pos=I[st]; - return x; - } else { - *pos=I[en]; - return y; - } - }; - - x=st+(en-st)/2; - if(memcmp(old+I[x],newdata,MIN(oldsize-I[x],newsize))<0) { - return search(I,old,oldsize,newdata,newsize,x,en,pos); - } else { - return search(I,old,oldsize,newdata,newsize,st,x,pos); - }; -} - -static void offtout(off_t x,u_char *buf) -{ - off_t y; - - if(x<0) y=-x; else y=x; - - buf[0]=y%256;y-=buf[0]; - y=y/256;buf[1]=y%256;y-=buf[1]; - y=y/256;buf[2]=y%256;y-=buf[2]; - y=y/256;buf[3]=y%256;y-=buf[3]; - y=y/256;buf[4]=y%256;y-=buf[4]; - y=y/256;buf[5]=y%256;y-=buf[5]; - y=y/256;buf[6]=y%256;y-=buf[6]; - y=y/256;buf[7]=y%256; - - if(x<0) buf[7]|=0x80; -} - -// This is main() from bsdiff.c, with the following changes: -// -// - old, oldsize, newdata, newsize are arguments; we don't load this -// data from files. old and newdata are owned by the caller; we -// don't free them at the end. -// -// - the "I" block of memory is owned by the caller, who passes a -// pointer to *I, which can be NULL. This way if we call -// bsdiff() multiple times with the same 'old' data, we only do -// the qsufsort() step the first time. -// -int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* newdata, off_t newsize, - const char* patch_filename) -{ - int fd; - off_t *I; - off_t scan,pos,len; - off_t lastscan,lastpos,lastoffset; - off_t oldscore,scsc; - off_t s,Sf,lenf,Sb,lenb; - off_t overlap,Ss,lens; - off_t i; - off_t dblen,eblen; - u_char *db,*eb; - u_char buf[8]; - u_char header[32]; - FILE * pf; - BZFILE * pfbz2; - int bz2err; - - if (*IP == NULL) { - off_t* V; - *IP = reinterpret_cast<off_t*>(malloc((oldsize+1) * sizeof(off_t))); - V = reinterpret_cast<off_t*>(malloc((oldsize+1) * sizeof(off_t))); - qsufsort(*IP, V, old, oldsize); - free(V); - } - I = *IP; - - if(((db=reinterpret_cast<u_char*>(malloc(newsize+1)))==NULL) || - ((eb=reinterpret_cast<u_char*>(malloc(newsize+1)))==NULL)) err(1,NULL); - dblen=0; - eblen=0; - - /* Create the patch file */ - if ((pf = fopen(patch_filename, "w")) == NULL) - err(1, "%s", patch_filename); - - /* Header is - 0 8 "BSDIFF40" - 8 8 length of bzip2ed ctrl block - 16 8 length of bzip2ed diff block - 24 8 length of new file */ - /* File is - 0 32 Header - 32 ?? Bzip2ed ctrl block - ?? ?? Bzip2ed diff block - ?? ?? Bzip2ed extra block */ - memcpy(header,"BSDIFF40",8); - offtout(0, header + 8); - offtout(0, header + 16); - offtout(newsize, header + 24); - if (fwrite(header, 32, 1, pf) != 1) - err(1, "fwrite(%s)", patch_filename); - - /* Compute the differences, writing ctrl as we go */ - if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) - errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); - scan=0;len=0; - lastscan=0;lastpos=0;lastoffset=0; - while(scan<newsize) { - oldscore=0; - - for(scsc=scan+=len;scan<newsize;scan++) { - len=search(I,old,oldsize,newdata+scan,newsize-scan, - 0,oldsize,&pos); - - for(;scsc<scan+len;scsc++) - if((scsc+lastoffset<oldsize) && - (old[scsc+lastoffset] == newdata[scsc])) - oldscore++; - - if(((len==oldscore) && (len!=0)) || - (len>oldscore+8)) break; - - if((scan+lastoffset<oldsize) && - (old[scan+lastoffset] == newdata[scan])) - oldscore--; - }; - - if((len!=oldscore) || (scan==newsize)) { - s=0;Sf=0;lenf=0; - for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) { - if(old[lastpos+i]==newdata[lastscan+i]) s++; - i++; - if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; }; - }; - - lenb=0; - if(scan<newsize) { - s=0;Sb=0; - for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) { - if(old[pos-i]==newdata[scan-i]) s++; - if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; - }; - }; - - if(lastscan+lenf>scan-lenb) { - overlap=(lastscan+lenf)-(scan-lenb); - s=0;Ss=0;lens=0; - for(i=0;i<overlap;i++) { - if(newdata[lastscan+lenf-overlap+i]== - old[lastpos+lenf-overlap+i]) s++; - if(newdata[scan-lenb+i]== - old[pos-lenb+i]) s--; - if(s>Ss) { Ss=s; lens=i+1; }; - }; - - lenf+=lens-overlap; - lenb-=lens; - }; - - for(i=0;i<lenf;i++) - db[dblen+i]=newdata[lastscan+i]-old[lastpos+i]; - for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) - eb[eblen+i]=newdata[lastscan+lenf+i]; - - dblen+=lenf; - eblen+=(scan-lenb)-(lastscan+lenf); - - offtout(lenf,buf); - BZ2_bzWrite(&bz2err, pfbz2, buf, 8); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); - - offtout((scan-lenb)-(lastscan+lenf),buf); - BZ2_bzWrite(&bz2err, pfbz2, buf, 8); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); - - offtout((pos-lenb)-(lastpos+lenf),buf); - BZ2_bzWrite(&bz2err, pfbz2, buf, 8); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); - - lastscan=scan-lenb; - lastpos=pos-lenb; - lastoffset=pos-scan; - }; - }; - BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); - - /* Compute size of compressed ctrl data */ - if ((len = ftello(pf)) == -1) - err(1, "ftello"); - offtout(len-32, header + 8); - - /* Write compressed diff data */ - if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) - errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); - BZ2_bzWrite(&bz2err, pfbz2, db, dblen); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); - BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); - - /* Compute size of compressed diff data */ - if ((newsize = ftello(pf)) == -1) - err(1, "ftello"); - offtout(newsize - len, header + 16); - - /* Write compressed extra data */ - if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) - errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); - BZ2_bzWrite(&bz2err, pfbz2, eb, eblen); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); - BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); - if (bz2err != BZ_OK) - errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); - - /* Seek to the beginning, write the header, and close the file */ - if (fseeko(pf, 0, SEEK_SET)) - err(1, "fseeko"); - if (fwrite(header, 32, 1, pf) != 1) - err(1, "fwrite(%s)", patch_filename); - if (fclose(pf)) - err(1, "fclose"); - - /* Free the memory we used */ - free(db); - free(eb); - - return 0; -} diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp index ebb55f1d1..eb45e9ce9 100644 --- a/applypatch/bspatch.cpp +++ b/applypatch/bspatch.cpp @@ -30,7 +30,7 @@ #include <bzlib.h> #include "openssl/sha.h" -#include "applypatch.h" +#include "applypatch/applypatch.h" void ShowBSDiffLicense() { puts("The bsdiff library used herein is:\n" @@ -64,7 +64,7 @@ void ShowBSDiffLicense() { ); } -static off_t offtin(u_char *buf) +static off_t offtin(const u_char *buf) { off_t y; @@ -130,7 +130,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, // from oldfile to x bytes from the diff block; copy y bytes from the // extra block; seek forwards in oldfile by z bytes". - unsigned char* header = (unsigned char*) patch->data + patch_offset; + const unsigned char* header = reinterpret_cast<const unsigned char*>(&patch->data[patch_offset]); if (memcmp(header, "BSDIFF40", 8) != 0) { printf("corrupt bsdiff patch file header (magic number)\n"); return 1; @@ -149,7 +149,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, int bzerr; bz_stream cstream; - cstream.next_in = patch->data + patch_offset + 32; + cstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32]); cstream.avail_in = ctrl_len; cstream.bzalloc = NULL; cstream.bzfree = NULL; @@ -159,7 +159,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, } bz_stream dstream; - dstream.next_in = patch->data + patch_offset + 32 + ctrl_len; + dstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len]); dstream.avail_in = data_len; dstream.bzalloc = NULL; dstream.bzfree = NULL; @@ -169,8 +169,8 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, } bz_stream estream; - estream.next_in = patch->data + patch_offset + 32 + ctrl_len + data_len; - estream.avail_in = patch->size - (patch_offset + 32 + ctrl_len + data_len); + estream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len + data_len]); + estream.avail_in = patch->data.size() - (patch_offset + 32 + ctrl_len + data_len); estream.bzalloc = NULL; estream.bzfree = NULL; estream.opaque = NULL; @@ -182,7 +182,6 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, off_t oldpos = 0, newpos = 0; off_t ctrl[3]; - off_t len_read; int i; unsigned char buf[24]; while (newpos < new_size) { diff --git a/applypatch/freecache.cpp b/applypatch/freecache.cpp index c84f42797..331cae265 100644 --- a/applypatch/freecache.cpp +++ b/applypatch/freecache.cpp @@ -32,7 +32,7 @@ #include <android-base/parseint.h> #include <android-base/stringprintf.h> -#include "applypatch.h" +#include "applypatch/applypatch.h" static int EliminateOpenFiles(std::set<std::string>* files) { std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir); diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp index f22502e38..7c5bb866d 100644 --- a/applypatch/imgdiff.cpp +++ b/applypatch/imgdiff.cpp @@ -130,6 +130,8 @@ #include <unistd.h> #include <sys/types.h> +#include <bsdiff.h> + #include "zlib.h" #include "imgdiff.h" #include "utils.h" @@ -144,8 +146,6 @@ typedef struct { size_t source_start; size_t source_len; - off_t* I; // used by bsdiff - // --- for CHUNK_DEFLATE chunks only: --- // original (compressed) deflate data @@ -179,10 +179,6 @@ static int fileentry_compare(const void* a, const void* b) { } } -// from bsdiff.c -int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* newdata, off_t newsize, - const char* patch_filename); - unsigned char* ReadZip(const char* filename, int* num_chunks, ImageChunk** chunks, int include_pseudo_chunk) { @@ -296,7 +292,6 @@ unsigned char* ReadZip(const char* filename, curr->len = st.st_size; curr->data = img; curr->filename = NULL; - curr->I = NULL; ++curr; ++*num_chunks; } @@ -311,7 +306,6 @@ unsigned char* ReadZip(const char* filename, curr->deflate_len = temp_entries[nextentry].deflate_len; curr->deflate_data = img + pos; curr->filename = temp_entries[nextentry].filename; - curr->I = NULL; curr->len = temp_entries[nextentry].uncomp_len; curr->data = reinterpret_cast<unsigned char*>(malloc(curr->len)); @@ -356,7 +350,6 @@ unsigned char* ReadZip(const char* filename, } curr->data = img + pos; curr->filename = NULL; - curr->I = NULL; pos += curr->len; ++*num_chunks; @@ -407,7 +400,6 @@ unsigned char* ReadImage(const char* filename, while (pos < sz) { unsigned char* p = img+pos; - bool processed_deflate = false; if (sz - pos >= 4 && p[0] == 0x1f && p[1] == 0x8b && p[2] == 0x08 && // deflate compression @@ -425,7 +417,6 @@ unsigned char* ReadImage(const char* filename, curr->type = CHUNK_NORMAL; curr->len = GZIP_HEADER_LEN; curr->data = p; - curr->I = NULL; pos += curr->len; p += curr->len; @@ -433,7 +424,6 @@ unsigned char* ReadImage(const char* filename, curr->type = CHUNK_DEFLATE; curr->filename = NULL; - curr->I = NULL; // We must decompress this chunk in order to discover where it // ends, and so we can put the uncompressed data and its length @@ -461,28 +451,27 @@ unsigned char* ReadImage(const char* filename, strm.next_out = curr->data + curr->len; ret = inflate(&strm, Z_NO_FLUSH); if (ret < 0) { - if (!processed_deflate) { - // This is the first chunk, assume that it's just a spurious - // gzip header instead of a real one. - break; - } - printf("Error: inflate failed [%s] at file offset [%zu]\n" - "imgdiff only supports gzip kernel compression," - " did you try CONFIG_KERNEL_LZO?\n", + printf("Warning: inflate failed [%s] at offset [%zu]," + " treating as a normal chunk\n", strm.msg, chunk_offset); - free(img); - return NULL; + break; } curr->len = allocated - strm.avail_out; if (strm.avail_out == 0) { allocated *= 2; curr->data = reinterpret_cast<unsigned char*>(realloc(curr->data, allocated)); } - processed_deflate = true; } while (ret != Z_STREAM_END); curr->deflate_len = sz - strm.avail_in - pos; inflateEnd(&strm); + + if (ret < 0) { + free(curr->data); + *num_chunks -= 2; + continue; + } + pos += curr->deflate_len; p += curr->deflate_len; ++curr; @@ -493,7 +482,6 @@ unsigned char* ReadImage(const char* filename, curr->start = pos; curr->len = GZIP_FOOTER_LEN; curr->data = img+pos; - curr->I = NULL; pos += curr->len; p += curr->len; @@ -517,7 +505,6 @@ unsigned char* ReadImage(const char* filename, *chunks = reinterpret_cast<ImageChunk*>(realloc(*chunks, *num_chunks * sizeof(ImageChunk))); ImageChunk* curr = *chunks + (*num_chunks-1); curr->start = pos; - curr->I = NULL; // 'pos' is not the offset of the start of a gzip chunk, so scan // forward until we find a gzip header. @@ -598,7 +585,6 @@ int ReconstructDeflateChunk(ImageChunk* chunk) { return -1; } - size_t p = 0; unsigned char* out = reinterpret_cast<unsigned char*>(malloc(BUFFER_SIZE)); // We only check two combinations of encoder parameters: level 6 @@ -645,7 +631,7 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) { close(fd); // temporary file is created and we don't need its file // descriptor - int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp); + int r = bsdiff::bsdiff(src->data, src->len, tgt->data, tgt->len, ptemp); if (r != 0) { printf("bsdiff() failed: %d\n", r); return NULL; @@ -844,7 +830,6 @@ int main(int argc, char** argv) { } if (argc != 4) { - usage: printf("usage: %s [-z] [-b <bonus-file>] <src-img> <tgt-img> <patch-file>\n", argv[0]); return 2; diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp index d175d6385..1c4409e36 100644 --- a/applypatch/imgpatch.cpp +++ b/applypatch/imgpatch.cpp @@ -24,21 +24,22 @@ #include <unistd.h> #include <string.h> +#include <string> #include <vector> #include "zlib.h" #include "openssl/sha.h" -#include "applypatch.h" +#include "applypatch/applypatch.h" #include "imgdiff.h" #include "utils.h" int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const unsigned char* patch_data, ssize_t patch_size, SinkFn sink, void* token) { - Value patch = {VAL_BLOB, patch_size, - reinterpret_cast<char*>(const_cast<unsigned char*>(patch_data))}; - return ApplyImagePatch( - old_data, old_size, &patch, sink, token, nullptr, nullptr); + Value patch(VAL_BLOB, std::string( + reinterpret_cast<const char*>(patch_data), patch_size)); + + return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr); } /* @@ -51,9 +52,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value* patch, SinkFn sink, void* token, SHA_CTX* ctx, const Value* bonus_data) { - ssize_t pos = 12; - char* header = patch->data; - if (patch->size < 12) { + if (patch->data.size() < 12) { printf("patch too short to contain header\n"); return -1; } @@ -61,6 +60,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW. // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and // CHUNK_GZIP.) + size_t pos = 12; + const char* header = &patch->data[0]; if (memcmp(header, "IMGDIFF2", 8) != 0) { printf("corrupt patch file header (magic number)\n"); return -1; @@ -68,20 +69,19 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, int num_chunks = Read4(header+8); - int i; - for (i = 0; i < num_chunks; ++i) { + for (int i = 0; i < num_chunks; ++i) { // each chunk's header record starts with 4 bytes. - if (pos + 4 > patch->size) { + if (pos + 4 > patch->data.size()) { printf("failed to read chunk %d record\n", i); return -1; } - int type = Read4(patch->data + pos); + int type = Read4(&patch->data[pos]); pos += 4; if (type == CHUNK_NORMAL) { - char* normal_header = patch->data + pos; + const char* normal_header = &patch->data[pos]; pos += 24; - if (pos > patch->size) { + if (pos > patch->data.size()) { printf("failed to read chunk %d normal header data\n", i); return -1; } @@ -97,21 +97,21 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, token, ctx); } else if (type == CHUNK_RAW) { - char* raw_header = patch->data + pos; + const char* raw_header = &patch->data[pos]; pos += 4; - if (pos > patch->size) { + if (pos > patch->data.size()) { printf("failed to read chunk %d raw header data\n", i); return -1; } ssize_t data_len = Read4(raw_header); - if (pos + data_len > patch->size) { + if (pos + data_len > patch->data.size()) { printf("failed to read chunk %d raw data\n", i); return -1; } - if (ctx) SHA1_Update(ctx, patch->data + pos, data_len); - if (sink((unsigned char*)patch->data + pos, + if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len); + if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len, token) != data_len) { printf("failed to write chunk %d raw data\n", i); return -1; @@ -119,9 +119,9 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, pos += data_len; } else if (type == CHUNK_DEFLATE) { // deflate chunks have an additional 60 bytes in their chunk header. - char* deflate_header = patch->data + pos; + const char* deflate_header = &patch->data[pos]; pos += 60; - if (pos > patch->size) { + if (pos > patch->data.size()) { printf("failed to read chunk %d deflate header data\n", i); return -1; } @@ -130,6 +130,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, size_t src_len = Read8(deflate_header+8); size_t patch_offset = Read8(deflate_header+16); size_t expanded_len = Read8(deflate_header+24); + size_t target_len = Read8(deflate_header+32); int level = Read4(deflate_header+40); int method = Read4(deflate_header+44); int windowBits = Read4(deflate_header+48); @@ -148,7 +149,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, // the patch was constructed with bonus data. The // deflation will come up 'bonus_size' bytes short; these // must be appended from the bonus_data value. - size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0; + size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->data.size() : 0; std::vector<unsigned char> expanded_source(expanded_len); @@ -188,7 +189,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, if (bonus_size) { memcpy(expanded_source.data() + (expanded_len - bonus_size), - bonus_data->data, bonus_size); + &bonus_data->data[0], bonus_size); } } @@ -200,6 +201,11 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, &uncompressed_target_data) != 0) { return -1; } + if (uncompressed_target_data.size() != target_len) { + printf("expected target len to be %zu, but it's %zu\n", + target_len, uncompressed_target_data.size()); + return -1; + } // Now compress the target data and append it to the output. @@ -231,8 +237,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, ssize_t have = temp_data.size() - strm.avail_out; if (sink(temp_data.data(), have, token) != have) { - printf("failed to write %ld compressed bytes to output\n", - (long)have); + printf("failed to write %zd compressed bytes to output\n", + have); return -1; } if (ctx) SHA1_Update(ctx, temp_data.data(), have); diff --git a/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h index f392c5534..80d681638 100644 --- a/applypatch/applypatch.h +++ b/applypatch/include/applypatch/applypatch.h @@ -17,8 +17,10 @@ #ifndef _APPLYPATCH_H #define _APPLYPATCH_H +#include <stdint.h> #include <sys/stat.h> +#include <string> #include <vector> #include "openssl/sha.h" @@ -51,19 +53,16 @@ int applypatch(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t target_size, - int num_patches, - char** const patch_sha1_str, + const std::vector<std::string>& patch_sha1_str, Value** patch_data, Value* bonus_data); int applypatch_check(const char* filename, - int num_patches, - char** const patch_sha1_str); + const std::vector<std::string>& patch_sha1_str); int LoadFileContents(const char* filename, FileContents* file); int SaveFileContents(const char* filename, const FileContents* file); void FreeFileContents(FileContents* file); -int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, - int num_patches); +int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str); // bsdiff.cpp void ShowBSDiffLicense(); diff --git a/applypatch/libimgpatch.pc b/applypatch/libimgpatch.pc new file mode 100644 index 000000000..e5002934f --- /dev/null +++ b/applypatch/libimgpatch.pc @@ -0,0 +1,6 @@ +# This file is for libimgpatch in Chrome OS. + +Name: libimgpatch +Description: Apply imgdiff patch +Version: 0.0.1 +Libs: -limgpatch -lbz2 -lz diff --git a/applypatch/main.cpp b/applypatch/main.cpp index 9013760c4..294f7ee21 100644 --- a/applypatch/main.cpp +++ b/applypatch/main.cpp @@ -20,9 +20,10 @@ #include <unistd.h> #include <memory> +#include <string> #include <vector> -#include "applypatch.h" +#include "applypatch/applypatch.h" #include "edify/expr.h" #include "openssl/sha.h" @@ -30,7 +31,12 @@ static int CheckMode(int argc, char** argv) { if (argc < 3) { return 2; } - return applypatch_check(argv[2], argc-3, argv+3); + std::vector<std::string> sha1; + for (int i = 3; i < argc; i++) { + sha1.push_back(argv[i]); + } + + return applypatch_check(argv[2], sha1); } static int SpaceMode(int argc, char** argv) { @@ -49,11 +55,13 @@ static int SpaceMode(int argc, char** argv) { // Parse arguments (which should be of the form "<sha1>:<filename>" // into the new parallel arrays *sha1s and *files.Returns true on // success. -static bool ParsePatchArgs(int argc, char** argv, std::vector<char*>* sha1s, +static bool ParsePatchArgs(int argc, char** argv, std::vector<std::string>* sha1s, std::vector<FileContents>* files) { - uint8_t digest[SHA_DIGEST_LENGTH]; - + if (sha1s == nullptr) { + return false; + } for (int i = 0; i < argc; ++i) { + uint8_t digest[SHA_DIGEST_LENGTH]; char* colon = strchr(argv[i], ':'); if (colon == nullptr) { printf("no ':' in patch argument \"%s\"\n", argv[i]); @@ -83,18 +91,15 @@ static int FlashMode(const char* src_filename, const char* tgt_filename, static int PatchMode(int argc, char** argv) { FileContents bonusFc; - Value bonusValue; - Value* bonus = nullptr; + Value bonus(VAL_INVALID, ""); if (argc >= 3 && strcmp(argv[1], "-b") == 0) { if (LoadFileContents(argv[2], &bonusFc) != 0) { printf("failed to load bonus file %s\n", argv[2]); return 1; } - bonus = &bonusValue; - bonus->type = VAL_BLOB; - bonus->size = bonusFc.data.size(); - bonus->data = reinterpret_cast<char*>(bonusFc.data.data()); + bonus.type = VAL_BLOB; + bonus.data = std::string(bonusFc.data.cbegin(), bonusFc.data.cend()); argc -= 2; argv += 2; } @@ -112,29 +117,27 @@ static int PatchMode(int argc, char** argv) { // If no <src-sha1>:<patch> is provided, it is in flash mode. if (argc == 5) { - if (bonus != nullptr) { + if (bonus.type != VAL_INVALID) { printf("bonus file not supported in flash mode\n"); return 1; } return FlashMode(argv[1], argv[2], argv[3], target_size); } - std::vector<char*> sha1s; + std::vector<std::string> sha1s; std::vector<FileContents> files; if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) { printf("failed to parse patch args\n"); return 1; } - std::vector<Value> patches(files.size()); - std::vector<Value*> patch_ptrs(files.size()); + std::vector<Value> patches; + std::vector<Value*> patch_ptrs; for (size_t i = 0; i < files.size(); ++i) { - patches[i].type = VAL_BLOB; - patches[i].size = files[i].data.size(); - patches[i].data = reinterpret_cast<char*>(files[i].data.data()); - patch_ptrs[i] = &patches[i]; + patches.push_back(Value(VAL_BLOB, + std::string(files[i].data.cbegin(), files[i].data.cend()))); + patch_ptrs.push_back(&patches[i]); } return applypatch(argv[1], argv[2], argv[3], target_size, - patch_ptrs.size(), sha1s.data(), - patch_ptrs.data(), bonus); + sha1s, patch_ptrs.data(), &bonus); } // This program applies binary patches to files in a way that is safe @@ -160,9 +163,9 @@ static int PatchMode(int argc, char** argv) { // - otherwise, or if any error is encountered, exits with non-zero // status. // -// <src-file> (or <file> in check mode) may refer to an MTD partition +// <src-file> (or <file> in check mode) may refer to an EMMC partition // to read the source data. See the comments for the -// LoadMTDContents() function above for the format of such a filename. +// LoadPartitionContents() function for the format of such a filename. int main(int argc, char** argv) { if (argc < 2) { @@ -175,8 +178,8 @@ int main(int argc, char** argv) { " or %s -l\n" "\n" "Filenames may be of the form\n" - " MTD:<partition>:<len_1>:<sha1_1>:<len_2>:<sha1_2>:...\n" - "to specify reading from or writing to an MTD partition.\n\n", + " EMMC:<partition>:<len_1>:<sha1_1>:<len_2>:<sha1_2>:...\n" + "to specify reading from or writing to an EMMC partition.\n\n", argv[0], argv[0], argv[0], argv[0]); return 2; } diff --git a/applypatch/utils.cpp b/applypatch/utils.cpp index 4a80be75f..450dc8d76 100644 --- a/applypatch/utils.cpp +++ b/applypatch/utils.cpp @@ -27,7 +27,7 @@ void Write4(int value, FILE* f) { } /** Write an 8-byte value to f in little-endian order. */ -void Write8(long long value, FILE* f) { +void Write8(int64_t value, FILE* f) { fputc(value & 0xff, f); fputc((value >> 8) & 0xff, f); fputc((value >> 16) & 0xff, f); @@ -38,28 +38,28 @@ void Write8(long long value, FILE* f) { fputc((value >> 56) & 0xff, f); } -int Read2(void* pv) { - unsigned char* p = reinterpret_cast<unsigned char*>(pv); +int Read2(const void* pv) { + const unsigned char* p = reinterpret_cast<const unsigned char*>(pv); return (int)(((unsigned int)p[1] << 8) | (unsigned int)p[0]); } -int Read4(void* pv) { - unsigned char* p = reinterpret_cast<unsigned char*>(pv); +int Read4(const void* pv) { + const unsigned char* p = reinterpret_cast<const unsigned char*>(pv); return (int)(((unsigned int)p[3] << 24) | ((unsigned int)p[2] << 16) | ((unsigned int)p[1] << 8) | (unsigned int)p[0]); } -long long Read8(void* pv) { - unsigned char* p = reinterpret_cast<unsigned char*>(pv); - return (long long)(((unsigned long long)p[7] << 56) | - ((unsigned long long)p[6] << 48) | - ((unsigned long long)p[5] << 40) | - ((unsigned long long)p[4] << 32) | - ((unsigned long long)p[3] << 24) | - ((unsigned long long)p[2] << 16) | - ((unsigned long long)p[1] << 8) | - (unsigned long long)p[0]); +int64_t Read8(const void* pv) { + const unsigned char* p = reinterpret_cast<const unsigned char*>(pv); + return (int64_t)(((uint64_t)p[7] << 56) | + ((uint64_t)p[6] << 48) | + ((uint64_t)p[5] << 40) | + ((uint64_t)p[4] << 32) | + ((uint64_t)p[3] << 24) | + ((uint64_t)p[2] << 16) | + ((uint64_t)p[1] << 8) | + (uint64_t)p[0]); } diff --git a/applypatch/utils.h b/applypatch/utils.h index bc97f1720..c7c8e90e2 100644 --- a/applypatch/utils.h +++ b/applypatch/utils.h @@ -17,14 +17,15 @@ #ifndef _BUILD_TOOLS_APPLYPATCH_UTILS_H #define _BUILD_TOOLS_APPLYPATCH_UTILS_H +#include <inttypes.h> #include <stdio.h> // Read and write little-endian values of various sizes. void Write4(int value, FILE* f); -void Write8(long long value, FILE* f); -int Read2(void* p); -int Read4(void* p); -long long Read8(void* p); +void Write8(int64_t value, FILE* f); +int Read2(const void* p); +int Read4(const void* p); +int64_t Read8(const void* p); #endif // _BUILD_TOOLS_APPLYPATCH_UTILS_H diff --git a/bootloader_message/Android.mk b/bootloader_message/Android.mk index 815ac67d7..a8c50819b 100644 --- a/bootloader_message/Android.mk +++ b/bootloader_message/Android.mk @@ -19,6 +19,7 @@ LOCAL_CLANG := true LOCAL_SRC_FILES := bootloader_message.cpp LOCAL_MODULE := libbootloader_message LOCAL_STATIC_LIBRARIES := libbase libfs_mgr +LOCAL_CFLAGS := -Werror LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include include $(BUILD_STATIC_LIBRARY) diff --git a/bootloader_message/bootloader_message.cpp b/bootloader_message/bootloader_message.cpp index 9de7dff40..e0c95d223 100644 --- a/bootloader_message/bootloader_message.cpp +++ b/bootloader_message/bootloader_message.cpp @@ -19,25 +19,24 @@ #include <errno.h> #include <fcntl.h> #include <string.h> -#include <sys/system_properties.h> #include <string> #include <vector> #include <android-base/file.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> #include <fs_mgr.h> static struct fstab* read_fstab(std::string* err) { - // The fstab path is always "/fstab.${ro.hardware}". - std::string fstab_path = "/fstab."; - char value[PROP_VALUE_MAX]; - if (__system_property_get("ro.hardware", value) == 0) { + std::string ro_hardware = android::base::GetProperty("ro.hardware", ""); + if (ro_hardware.empty()) { *err = "failed to get ro.hardware"; return nullptr; } - fstab_path += value; + // The fstab path is always "/fstab.${ro.hardware}". + std::string fstab_path = "/fstab." + ro_hardware; struct fstab* fstab = fs_mgr_read_fstab(fstab_path.c_str()); if (fstab == nullptr) { *err = "failed to read " + fstab_path; diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h index c63aeca6f..f343c64ac 100644 --- a/bootloader_message/include/bootloader_message/bootloader_message.h +++ b/bootloader_message/include/bootloader_message/bootloader_message.h @@ -17,18 +17,21 @@ #ifndef _BOOTLOADER_MESSAGE_H #define _BOOTLOADER_MESSAGE_H +#include <assert.h> #include <stddef.h> +#include <stdint.h> // Spaces used by misc partition are as below: -// 0 - 2K Bootloader Message -// 2K - 16K Used by Vendor's bootloader +// 0 - 2K For bootloader_message +// 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used +// as bootloader_message_ab struct) // 16K - 64K Used by uncrypt and recovery to store wipe_package for A/B devices // Note that these offsets are admitted by bootloader,recovery and uncrypt, so they // are not configurable without changing all of them. static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = 0; static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024; -/* Bootloader Message +/* Bootloader Message (2-KiB) * * This structure describes the content of a block in flash * that is used for recovery and the bootloader to talk to @@ -51,12 +54,10 @@ static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024; * package it is. If the value is of the format "#/#" (eg, "1/3"), * the UI will add a simple indicator of that status. * - * The slot_suffix field is used for A/B implementations where the - * bootloader does not set the androidboot.ro.boot.slot_suffix kernel - * commandline parameter. This is used by fs_mgr to mount /system and - * other partitions with the slotselect flag set in fstab. A/B - * implementations are free to use all 32 bytes and may store private - * data past the first NUL-byte in this field. + * We used to have slot_suffix field for A/B boot control metadata in + * this struct, which gets unintentionally cleared by recovery or + * uncrypt. Move it into struct bootloader_message_ab to avoid the + * issue. */ struct bootloader_message { char command[32]; @@ -69,10 +70,110 @@ struct bootloader_message { // stage string (for multistage packages) and possible future // expansion. char stage[32]; + + // The 'reserved' field used to be 224 bytes when it was initially + // carved off from the 1024-byte recovery field. Bump it up to + // 1184-byte so that the entire bootloader_message struct rounds up + // to 2048-byte. + char reserved[1184]; +}; + +/** + * We must be cautious when changing the bootloader_message struct size, + * because A/B-specific fields may end up with different offsets. + */ +#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) +static_assert(sizeof(struct bootloader_message) == 2048, + "struct bootloader_message size changes, which may break A/B devices"); +#endif + +/** + * The A/B-specific bootloader message structure (4-KiB). + * + * We separate A/B boot control metadata from the regular bootloader + * message struct and keep it here. Everything that's A/B-specific + * stays after struct bootloader_message, which should be managed by + * the A/B-bootloader or boot control HAL. + * + * The slot_suffix field is used for A/B implementations where the + * bootloader does not set the androidboot.ro.boot.slot_suffix kernel + * commandline parameter. This is used by fs_mgr to mount /system and + * other partitions with the slotselect flag set in fstab. A/B + * implementations are free to use all 32 bytes and may store private + * data past the first NUL-byte in this field. It is encouraged, but + * not mandatory, to use 'struct bootloader_control' described below. + */ +struct bootloader_message_ab { + struct bootloader_message message; char slot_suffix[32]; - char reserved[192]; + + // Round up the entire struct to 4096-byte. + char reserved[2016]; }; +/** + * Be cautious about the struct size change, in case we put anything post + * bootloader_message_ab struct (b/29159185). + */ +#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) +static_assert(sizeof(struct bootloader_message_ab) == 4096, + "struct bootloader_message_ab size changes"); +#endif + +#define BOOT_CTRL_MAGIC 0x42414342 /* Bootloader Control AB */ +#define BOOT_CTRL_VERSION 1 + +struct slot_metadata { + // Slot priority with 15 meaning highest priority, 1 lowest + // priority and 0 the slot is unbootable. + uint8_t priority : 4; + // Number of times left attempting to boot this slot. + uint8_t tries_remaining : 3; + // 1 if this slot has booted successfully, 0 otherwise. + uint8_t successful_boot : 1; + // 1 if this slot is corrupted from a dm-verity corruption, 0 + // otherwise. + uint8_t verity_corrupted : 1; + // Reserved for further use. + uint8_t reserved : 7; +} __attribute__((packed)); + +/* Bootloader Control AB + * + * This struct can be used to manage A/B metadata. It is designed to + * be put in the 'slot_suffix' field of the 'bootloader_message' + * structure described above. It is encouraged to use the + * 'bootloader_control' structure to store the A/B metadata, but not + * mandatory. + */ +struct bootloader_control { + // NUL terminated active slot suffix. + char slot_suffix[4]; + // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC). + uint32_t magic; + // Version of struct being used (see BOOT_CTRL_VERSION). + uint8_t version; + // Number of slots being managed. + uint8_t nb_slot : 3; + // Number of times left attempting to boot recovery. + uint8_t recovery_tries_remaining : 3; + // Ensure 4-bytes alignment for slot_info field. + uint8_t reserved0[2]; + // Per-slot information. Up to 4 slots. + struct slot_metadata slot_info[4]; + // Reserved for further use. + uint8_t reserved1[8]; + // CRC32 of all 28 bytes preceding this field (little endian + // format). + uint32_t crc32_le; +} __attribute__((packed)); + +#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) +static_assert(sizeof(struct bootloader_control) == + sizeof(((struct bootloader_message_ab *)0)->slot_suffix), + "struct bootloader_control has wrong size"); +#endif + #ifdef __cplusplus #include <string> @@ -86,7 +187,6 @@ bool clear_bootloader_message(std::string* err); bool read_wipe_package(std::string* package_data, size_t size, std::string* err); bool write_wipe_package(const std::string& package_data, std::string* err); - #else #include <stdbool.h> @@ -21,18 +21,6 @@ #include <stdio.h> #include <stdarg.h> -#define LOGE(...) ui_print("E:" __VA_ARGS__) -#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__) -#define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__) - -#if 0 -#define LOGV(...) fprintf(stdout, "V:" __VA_ARGS__) -#define LOGD(...) fprintf(stdout, "D:" __VA_ARGS__) -#else -#define LOGV(...) do {} while (0) -#define LOGD(...) do {} while (0) -#endif - #define STRINGIFY(x) #x #define EXPAND(x) STRINGIFY(x) @@ -21,7 +21,7 @@ class Device { public: - Device(RecoveryUI* ui) : ui_(ui) { } + explicit Device(RecoveryUI* ui) : ui_(ui) { } virtual ~Device() { } // Called to obtain the UI object that should be used to display diff --git a/edify/Android.mk b/edify/Android.mk index 71cf7652a..d8058c16f 100644 --- a/edify/Android.mk +++ b/edify/Android.mk @@ -1,23 +1,36 @@ # Copyright 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. LOCAL_PATH := $(call my-dir) edify_src_files := \ - lexer.ll \ - parser.yy \ - expr.cpp + lexer.ll \ + parser.yy \ + expr.cpp # -# Build the host-side command line tool +# Build the host-side command line tool (host executable) # include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - $(edify_src_files) \ - main.cpp + $(edify_src_files) \ + edify_parser.cpp +LOCAL_CFLAGS := -Werror LOCAL_CPPFLAGS := -g -O0 -LOCAL_MODULE := edify +LOCAL_MODULE := edify_parser LOCAL_YACCFLAGS := -v LOCAL_CPPFLAGS += -Wno-unused-parameter LOCAL_CPPFLAGS += -Wno-deprecated-register @@ -28,12 +41,13 @@ LOCAL_STATIC_LIBRARIES += libbase include $(BUILD_HOST_EXECUTABLE) # -# Build the device-side library +# Build the device-side library (static library) # include $(CLEAR_VARS) LOCAL_SRC_FILES := $(edify_src_files) +LOCAL_CFLAGS := -Werror LOCAL_CPPFLAGS := -Wno-unused-parameter LOCAL_CPPFLAGS += -Wno-deprecated-register LOCAL_MODULE := libedify diff --git a/edify/README b/edify/README.md index 810455cca..b3330e23a 100644 --- a/edify/README +++ b/edify/README.md @@ -1,3 +1,6 @@ +edify +===== + Update scripts (from donut onwards) are written in a new little scripting language ("edify") that is superficially somewhat similar to the old one ("amend"). This is a brief overview of the new language. diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp new file mode 100644 index 000000000..908fcf13b --- /dev/null +++ b/edify/edify_parser.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This is a host-side tool for validating a given edify script file. + * + * We used to have edify test cases here, which have been moved to + * tests/component/edify_test.cpp. + * + * Caveat: It doesn't recognize functions defined through updater, which + * makes the tool less useful. We should either extend the tool or remove it. + */ + +#include <errno.h> +#include <stdio.h> + +#include <string> + +#include <android-base/file.h> + +#include "expr.h" + +static void ExprDump(int depth, const Expr* n, const std::string& script) { + printf("%*s", depth*2, ""); + printf("%s %p (%d-%d) \"%s\"\n", + n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, + script.substr(n->start, n->end - n->start).c_str()); + for (int i = 0; i < n->argc; ++i) { + ExprDump(depth+1, n->argv[i], script); + } +} + +int main(int argc, char** argv) { + RegisterBuiltins(); + + if (argc != 2) { + printf("Usage: %s <edify script>\n", argv[0]); + return 1; + } + + std::string buffer; + if (!android::base::ReadFileToString(argv[1], &buffer)) { + printf("%s: failed to read %s: %s\n", argv[0], argv[1], strerror(errno)); + return 1; + } + + Expr* root; + int error_count = 0; + int error = parse_string(buffer.data(), &root, &error_count); + printf("parse returned %d; %d errors encountered\n", error, error_count); + if (error == 0 || error_count > 0) { + + ExprDump(0, root, buffer); + + State state(buffer, nullptr); + std::string result; + if (!Evaluate(&state, root, &result)) { + printf("result was NULL, message is: %s\n", + (state.errmsg.empty() ? "(NULL)" : state.errmsg.c_str())); + } else { + printf("result is [%s]\n", result.c_str()); + } + } + return 0; +} diff --git a/edify/expr.cpp b/edify/expr.cpp index cc14fbe93..ec2409752 100644 --- a/edify/expr.cpp +++ b/edify/expr.cpp @@ -14,201 +14,172 @@ * limitations under the License. */ -#include <string.h> -#include <stdbool.h> +#include "expr.h" + +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <stdarg.h> +#include <string.h> #include <unistd.h> +#include <memory> #include <string> +#include <unordered_map> +#include <vector> +#include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> -#include "expr.h" - // Functions should: // // - return a malloc()'d string -// - if Evaluate() on any argument returns NULL, return NULL. +// - if Evaluate() on any argument returns nullptr, return nullptr. -int BooleanString(const char* s) { - return s[0] != '\0'; +static bool BooleanString(const std::string& s) { + return !s.empty(); } -char* Evaluate(State* state, Expr* expr) { - Value* v = expr->fn(expr->name, state, expr->argc, expr->argv); - if (v == NULL) return NULL; +bool Evaluate(State* state, Expr* expr, std::string* result) { + if (result == nullptr) { + return false; + } + + std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv)); + if (!v) { + return false; + } if (v->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type); - FreeValue(v); - return NULL; + return false; } - char* result = v->data; - free(v); - return result; + + *result = v->data; + return true; } Value* EvaluateValue(State* state, Expr* expr) { return expr->fn(expr->name, state, expr->argc, expr->argv); } -Value* StringValue(char* str) { - if (str == NULL) return NULL; - Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); - v->type = VAL_STRING; - v->size = strlen(str); - v->data = str; - return v; +Value* StringValue(const char* str) { + if (str == nullptr) { + return nullptr; + } + return new Value(VAL_STRING, str); } -void FreeValue(Value* v) { - if (v == NULL) return; - free(v->data); - free(v); +Value* StringValue(const std::string& str) { + return StringValue(str.c_str()); } Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc == 0) { - return StringValue(strdup("")); - } - char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); - int i; - for (i = 0; i < argc; ++i) { - strings[i] = NULL; + return StringValue(""); } - char* result = NULL; - int length = 0; - for (i = 0; i < argc; ++i) { - strings[i] = Evaluate(state, argv[i]); - if (strings[i] == NULL) { - goto done; + std::string result; + for (int i = 0; i < argc; ++i) { + std::string str; + if (!Evaluate(state, argv[i], &str)) { + return nullptr; } - length += strlen(strings[i]); - } - - result = reinterpret_cast<char*>(malloc(length+1)); - int p; - p = 0; - for (i = 0; i < argc; ++i) { - strcpy(result+p, strings[i]); - p += strlen(strings[i]); + result += str; } - result[p] = '\0'; - done: - for (i = 0; i < argc; ++i) { - free(strings[i]); - } - free(strings); return StringValue(result); } Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2 && argc != 3) { - free(state->errmsg); - state->errmsg = strdup("ifelse expects 2 or 3 arguments"); - return NULL; + state->errmsg = "ifelse expects 2 or 3 arguments"; + return nullptr; } - char* cond = Evaluate(state, argv[0]); - if (cond == NULL) { - return NULL; + + std::string cond; + if (!Evaluate(state, argv[0], &cond)) { + return nullptr; } - if (BooleanString(cond) == true) { - free(cond); + if (!cond.empty()) { return EvaluateValue(state, argv[1]); - } else { - if (argc == 3) { - free(cond); - return EvaluateValue(state, argv[2]); - } else { - return StringValue(cond); - } + } else if (argc == 3) { + return EvaluateValue(state, argv[2]); } + + return StringValue(""); } Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { - char* msg = NULL; - if (argc > 0) { - msg = Evaluate(state, argv[0]); - } - free(state->errmsg); - if (msg) { + std::string msg; + if (argc > 0 && Evaluate(state, argv[0], &msg)) { state->errmsg = msg; } else { - state->errmsg = strdup("called abort()"); + state->errmsg = "called abort()"; } - return NULL; + return nullptr; } Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { - int i; - for (i = 0; i < argc; ++i) { - char* v = Evaluate(state, argv[i]); - if (v == NULL) { - return NULL; + for (int i = 0; i < argc; ++i) { + std::string result; + if (!Evaluate(state, argv[i], &result)) { + return nullptr; } - int b = BooleanString(v); - free(v); - if (!b) { - int prefix_len; + if (result.empty()) { int len = argv[i]->end - argv[i]->start; - char* err_src = reinterpret_cast<char*>(malloc(len + 20)); - strcpy(err_src, "assert failed: "); - prefix_len = strlen(err_src); - memcpy(err_src + prefix_len, state->script + argv[i]->start, len); - err_src[prefix_len + len] = '\0'; - free(state->errmsg); - state->errmsg = err_src; - return NULL; + state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len); + return nullptr; } } - return StringValue(strdup("")); + return StringValue(""); } Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { - char* val = Evaluate(state, argv[0]); - if (val == NULL) { - return NULL; + std::string val; + if (!Evaluate(state, argv[0], &val)) { + return nullptr; + } + + int v; + if (!android::base::ParseInt(val.c_str(), &v, 0)) { + return nullptr; } - int v = strtol(val, NULL, 10); sleep(v); + return StringValue(val); } Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { - int i; - for (i = 0; i < argc; ++i) { - char* v = Evaluate(state, argv[i]); - if (v == NULL) { - return NULL; + for (int i = 0; i < argc; ++i) { + std::string v; + if (!Evaluate(state, argv[i], &v)) { + return nullptr; } - fputs(v, stdout); - free(v); + fputs(v.c_str(), stdout); } - return StringValue(strdup("")); + return StringValue(""); } Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]) { - char* left = Evaluate(state, argv[0]); - if (left == NULL) return NULL; - if (BooleanString(left) == true) { - free(left); + std::string left; + if (!Evaluate(state, argv[0], &left)) { + return nullptr; + } + if (BooleanString(left)) { return EvaluateValue(state, argv[1]); } else { - return StringValue(left); + return StringValue(""); } } Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]) { - char* left = Evaluate(state, argv[0]); - if (left == NULL) return NULL; - if (BooleanString(left) == false) { - free(left); + std::string left; + if (!Evaluate(state, argv[0], &left)) { + return nullptr; + } + if (!BooleanString(left)) { return EvaluateValue(state, argv[1]); } else { return StringValue(left); @@ -217,87 +188,87 @@ Value* LogicalOrFn(const char* name, State* state, Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]) { - char* val = Evaluate(state, argv[0]); - if (val == NULL) return NULL; - bool bv = BooleanString(val); - free(val); - return StringValue(strdup(bv ? "" : "t")); + std::string val; + if (!Evaluate(state, argv[0], &val)) { + return nullptr; + } + + return StringValue(BooleanString(val) ? "" : "t"); } Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]) { - char* needle = Evaluate(state, argv[0]); - if (needle == NULL) return NULL; - char* haystack = Evaluate(state, argv[1]); - if (haystack == NULL) { - free(needle); - return NULL; + std::string needle; + if (!Evaluate(state, argv[0], &needle)) { + return nullptr; } - char* result = strdup(strstr(haystack, needle) ? "t" : ""); - free(needle); - free(haystack); + std::string haystack; + if (!Evaluate(state, argv[1], &haystack)) { + return nullptr; + } + + std::string result = (haystack.find(needle) != std::string::npos) ? "t" : ""; return StringValue(result); } Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { - char* left = Evaluate(state, argv[0]); - if (left == NULL) return NULL; - char* right = Evaluate(state, argv[1]); - if (right == NULL) { - free(left); - return NULL; + std::string left; + if (!Evaluate(state, argv[0], &left)) { + return nullptr; + } + std::string right; + if (!Evaluate(state, argv[1], &right)) { + return nullptr; } - char* result = strdup(strcmp(left, right) == 0 ? "t" : ""); - free(left); - free(right); + const char* result = (left == right) ? "t" : ""; return StringValue(result); } Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { - char* left = Evaluate(state, argv[0]); - if (left == NULL) return NULL; - char* right = Evaluate(state, argv[1]); - if (right == NULL) { - free(left); - return NULL; + std::string left; + if (!Evaluate(state, argv[0], &left)) { + return nullptr; + } + std::string right; + if (!Evaluate(state, argv[1], &right)) { + return nullptr; } - char* result = strdup(strcmp(left, right) != 0 ? "t" : ""); - free(left); - free(right); + const char* result = (left != right) ? "t" : ""; return StringValue(result); } Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { - Value* left = EvaluateValue(state, argv[0]); - if (left == NULL) return NULL; - FreeValue(left); + std::unique_ptr<Value> left(EvaluateValue(state, argv[0])); + if (!left) { + return nullptr; + } return EvaluateValue(state, argv[1]); } Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { - free(state->errmsg); - state->errmsg = strdup("less_than_int expects 2 arguments"); - return NULL; + state->errmsg = "less_than_int expects 2 arguments"; + return nullptr; } char* left; char* right; - if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL; + if (ReadArgs(state, argv, 2, &left, &right) < 0) return nullptr; bool result = false; char* end; - long l_int = strtol(left, &end, 10); + // Parse up to at least long long or 64-bit integers. + int64_t l_int = static_cast<int64_t>(strtoll(left, &end, 10)); if (left[0] == '\0' || *end != '\0') { goto done; } - long r_int; - r_int = strtol(right, &end, 10); + int64_t r_int; + r_int = static_cast<int64_t>(strtoll(right, &end, 10)); if (right[0] == '\0' || *end != '\0') { goto done; } @@ -307,15 +278,14 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { done: free(left); free(right); - return StringValue(strdup(result ? "t" : "")); + return StringValue(result ? "t" : ""); } Value* GreaterThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { - free(state->errmsg); - state->errmsg = strdup("greater_than_int expects 2 arguments"); - return NULL; + state->errmsg = "greater_than_int expects 2 arguments"; + return nullptr; } Expr* temp[2]; @@ -326,64 +296,25 @@ Value* GreaterThanIntFn(const char* name, State* state, } Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { - return StringValue(strdup(name)); -} - -Expr* Build(Function fn, YYLTYPE loc, int count, ...) { - va_list v; - va_start(v, count); - Expr* e = reinterpret_cast<Expr*>(malloc(sizeof(Expr))); - e->fn = fn; - e->name = "(operator)"; - e->argc = count; - e->argv = reinterpret_cast<Expr**>(malloc(count * sizeof(Expr*))); - int i; - for (i = 0; i < count; ++i) { - e->argv[i] = va_arg(v, Expr*); - } - va_end(v); - e->start = loc.start; - e->end = loc.end; - return e; + return StringValue(name); } // ----------------------------------------------------------------- // the function table // ----------------------------------------------------------------- -static int fn_entries = 0; -static int fn_size = 0; -NamedFunction* fn_table = NULL; - -void RegisterFunction(const char* name, Function fn) { - if (fn_entries >= fn_size) { - fn_size = fn_size*2 + 1; - fn_table = reinterpret_cast<NamedFunction*>(realloc(fn_table, fn_size * sizeof(NamedFunction))); - } - fn_table[fn_entries].name = name; - fn_table[fn_entries].fn = fn; - ++fn_entries; -} +static std::unordered_map<std::string, Function> fn_table; -static int fn_entry_compare(const void* a, const void* b) { - const char* na = ((const NamedFunction*)a)->name; - const char* nb = ((const NamedFunction*)b)->name; - return strcmp(na, nb); +void RegisterFunction(const std::string& name, Function fn) { + fn_table[name] = fn; } -void FinishRegistration() { - qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare); -} - -Function FindFunction(const char* name) { - NamedFunction key; - key.name = name; - NamedFunction* nf = reinterpret_cast<NamedFunction*>(bsearch(&key, fn_table, fn_entries, - sizeof(NamedFunction), fn_entry_compare)); - if (nf == NULL) { - return NULL; +Function FindFunction(const std::string& name) { + if (fn_table.find(name) == fn_table.end()) { + return nullptr; + } else { + return fn_table[name]; } - return nf->fn; } void RegisterBuiltins() { @@ -404,6 +335,43 @@ void RegisterBuiltins() { // convenience methods for functions // ----------------------------------------------------------------- +// Evaluate the expressions in argv, and put the results of strings in +// args. If any expression evaluates to nullptr, free the rest and return +// false. Return true on success. +bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) { + if (args == nullptr) { + return false; + } + for (int i = 0; i < argc; ++i) { + std::string var; + if (!Evaluate(state, argv[i], &var)) { + args->clear(); + return false; + } + args->push_back(var); + } + return true; +} + +// Evaluate the expressions in argv, and put the results of Value* in +// args. If any expression evaluate to nullptr, free the rest and return +// false. Return true on success. +bool ReadValueArgs(State* state, int argc, Expr* argv[], + std::vector<std::unique_ptr<Value>>* args) { + if (args == nullptr) { + return false; + } + for (int i = 0; i < argc; ++i) { + std::unique_ptr<Value> v(EvaluateValue(state, argv[i])); + if (!v) { + args->clear(); + return false; + } + args->push_back(std::move(v)); + } + return true; +} + // Evaluate the expressions in argv, giving 'count' char* (the ... is // zero or more char** to put them in). If any expression evaluates // to NULL, free the rest and return -1. Return 0 on success. @@ -413,8 +381,9 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) { va_start(v, count); int i; for (i = 0; i < count; ++i) { - args[i] = Evaluate(state, argv[i]); - if (args[i] == NULL) { + std::string str; + if (!Evaluate(state, argv[i], &str) || + (args[i] = strdup(str.c_str())) == nullptr) { va_end(v); int j; for (j = 0; j < i; ++j) { @@ -434,25 +403,24 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) { // zero or more Value** to put them in). If any expression evaluates // to NULL, free the rest and return -1. Return 0 on success. int ReadValueArgs(State* state, Expr* argv[], int count, ...) { - Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*))); + Value** args = new Value*[count]; va_list v; va_start(v, count); - int i; - for (i = 0; i < count; ++i) { + for (int i = 0; i < count; ++i) { args[i] = EvaluateValue(state, argv[i]); if (args[i] == NULL) { va_end(v); int j; for (j = 0; j < i; ++j) { - FreeValue(args[j]); + delete args[j]; } - free(args); + delete[] args; return -1; } *(va_arg(v, Value**)) = args[i]; } va_end(v); - free(args); + delete[] args; return 0; } @@ -462,12 +430,11 @@ int ReadValueArgs(State* state, Expr* argv[], int count, ...) { // strings it contains. char** ReadVarArgs(State* state, int argc, Expr* argv[]) { char** args = (char**)malloc(argc * sizeof(char*)); - int i = 0; - for (i = 0; i < argc; ++i) { - args[i] = Evaluate(state, argv[i]); - if (args[i] == NULL) { - int j; - for (j = 0; j < i; ++j) { + for (int i = 0; i < argc; ++i) { + std::string str; + if (!Evaluate(state, argv[i], &str) || + (args[i] = strdup(str.c_str())) == nullptr) { + for (int j = 0; j < i; ++j) { free(args[j]); } free(args); @@ -482,36 +449,28 @@ char** ReadVarArgs(State* state, int argc, Expr* argv[]) { // The caller is responsible for freeing the returned array and the // Values it contains. Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) { - Value** args = (Value**)malloc(argc * sizeof(Value*)); + Value** args = new Value*[argc]; int i = 0; for (i = 0; i < argc; ++i) { args[i] = EvaluateValue(state, argv[i]); if (args[i] == NULL) { int j; for (j = 0; j < i; ++j) { - FreeValue(args[j]); + delete args[j]; } - free(args); + delete[] args; return NULL; } } return args; } -static void ErrorAbortV(State* state, const char* format, va_list ap) { - std::string buffer; - android::base::StringAppendV(&buffer, format, ap); - free(state->errmsg); - state->errmsg = strdup(buffer.c_str()); - return; -} - // Use printf-style arguments to compose an error message to put into // *state. Returns nullptr. Value* ErrorAbort(State* state, const char* format, ...) { va_list ap; va_start(ap, format); - ErrorAbortV(state, format, ap); + android::base::StringAppendV(&state->errmsg, format, ap); va_end(ap); return nullptr; } @@ -519,8 +478,14 @@ Value* ErrorAbort(State* state, const char* format, ...) { Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) { va_list ap; va_start(ap, format); - ErrorAbortV(state, format, ap); + android::base::StringAppendV(&state->errmsg, format, ap); va_end(ap); state->cause_code = cause_code; return nullptr; } + +State::State(const std::string& script, void* cookie) : + script(script), + cookie(cookie) { +} + diff --git a/edify/expr.h b/edify/expr.h index 886347991..85306542d 100644 --- a/edify/expr.h +++ b/edify/expr.h @@ -18,28 +18,24 @@ #define _EXPRESSION_H #include <unistd.h> +#include <string> #include "error_code.h" -#include "yydefs.h" -#define MAX_STRING_LEN 1024 +struct State { + State(const std::string& script, void* cookie); -typedef struct Expr Expr; + // The source of the original script. + const std::string& script; -typedef struct { // Optional pointer to app-specific data; the core of edify never // uses this value. void* cookie; - // The source of the original script. Must be NULL-terminated, - // and in writable memory (Evaluate may make temporary changes to - // it but will restore it when done). - char* script; - // The error message (if any) returned if the evaluation aborts. - // Should be NULL initially, will be either NULL or a malloc'd - // pointer after Evaluate() returns. - char* errmsg; + // Should be empty initially, will be either empty or a string that + // Evaluate() returns. + std::string errmsg; // error code indicates the type of failure (e.g. failure to update system image) // during the OTA process. @@ -50,20 +46,26 @@ typedef struct { CauseCode cause_code = kNoCause; bool is_retry = false; +}; -} State; +enum ValueType { + VAL_INVALID = -1, + VAL_STRING = 1, + VAL_BLOB = 2, +}; -#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null -#define VAL_BLOB 2 +struct Value { + ValueType type; + std::string data; -typedef struct { - int type; - ssize_t size; - char* data; -} Value; + Value(ValueType type, const std::string& str) : + type(type), + data(str) {} +}; -typedef Value* (*Function)(const char* name, State* state, - int argc, Expr* argv[]); +struct Expr; + +using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); struct Expr { Function fn; @@ -79,11 +81,11 @@ struct Expr { Value* EvaluateValue(State* state, Expr* expr); // Take one of the Expr*s passed to the function as an argument, -// evaluate it, assert that it is a string, and return the resulting -// char*. The caller takes ownership of the returned char*. This is -// a convenience function for older functions that want to deal only -// with strings. -char* Evaluate(State* state, Expr* expr); +// evaluate it, assert that it is a string, and update the result +// parameter. This function returns true if the evaluation succeeds. +// This is a convenience function for older functions that want to +// deal only with strings. +bool Evaluate(State* state, Expr* expr, std::string* result); // Glue to make an Expr out of a literal. Value* Literal(const char* name, State* state, int argc, Expr* argv[]); @@ -100,46 +102,35 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); -// Convenience function for building expressions with a fixed number -// of arguments. -Expr* Build(Function fn, YYLTYPE loc, int count, ...); - // Global builtins, registered by RegisterBuiltins(). Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); - -// For setting and getting the global error string (when returning -// NULL from a function). -void SetError(const char* message); // makes a copy -const char* GetError(); // retains ownership -void ClearError(); - - -typedef struct { - const char* name; - Function fn; -} NamedFunction; - // Register a new function. The same Function may be registered under // multiple names, but a given name should only be used once. -void RegisterFunction(const char* name, Function fn); +void RegisterFunction(const std::string& name, Function fn); // Register all the builtins. void RegisterBuiltins(); -// Call this after all calls to RegisterFunction() but before parsing -// any scripts to finish building the function table. -void FinishRegistration(); - // Find the Function for a given name; return NULL if no such function // exists. -Function FindFunction(const char* name); - +Function FindFunction(const std::string& name); // --- convenience functions for use in functions --- +// Evaluate the expressions in argv, and put the results of strings in +// args. If any expression evaluates to nullptr, free the rest and return +// false. Return true on success. +bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args); + +// Evaluate the expressions in argv, and put the results of Value* in +// args. If any expression evaluate to nullptr, free the rest and return +// false. Return true on success. +bool ReadValueArgs(State* state, int argc, Expr* argv[], + std::vector<std::unique_ptr<Value>>* args); + // Evaluate the expressions in argv, giving 'count' char* (the ... is // zero or more char** to put them in). If any expression evaluates // to NULL, free the rest and return -1. Return 0 on success. @@ -172,11 +163,10 @@ Value* ErrorAbort(State* state, const char* format, ...) Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) __attribute__((format(printf, 3, 4))); -// Wrap a string into a Value, taking ownership of the string. -Value* StringValue(char* str); +// Copying the string into a Value. +Value* StringValue(const char* str); -// Free a Value object. -void FreeValue(Value* v); +Value* StringValue(const std::string& str); int parse_string(const char* str, Expr** root, int* error_count); diff --git a/edify/main.cpp b/edify/main.cpp deleted file mode 100644 index 6007a3d58..000000000 --- a/edify/main.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <string> - -#include "expr.h" -#include "parser.h" - -extern int yyparse(Expr** root, int* error_count); - -int expect(const char* expr_str, const char* expected, int* errors) { - Expr* e; - char* result; - - printf("."); - - int error_count = parse_string(expr_str, &e, &error_count); - if (error_count > 0) { - printf("error parsing \"%s\" (%d errors)\n", - expr_str, error_count); - ++*errors; - return 0; - } - - State state; - state.cookie = NULL; - state.script = strdup(expr_str); - state.errmsg = NULL; - - result = Evaluate(&state, e); - free(state.errmsg); - free(state.script); - if (result == NULL && expected != NULL) { - printf("error evaluating \"%s\"\n", expr_str); - ++*errors; - return 0; - } - - if (result == NULL && expected == NULL) { - return 1; - } - - if (strcmp(result, expected) != 0) { - printf("evaluating \"%s\": expected \"%s\", got \"%s\"\n", - expr_str, expected, result); - ++*errors; - free(result); - return 0; - } - - free(result); - return 1; -} - -int test() { - int errors = 0; - - expect("a", "a", &errors); - expect("\"a\"", "a", &errors); - expect("\"\\x61\"", "a", &errors); - expect("# this is a comment\n" - " a\n" - " \n", - "a", &errors); - - - // sequence operator - expect("a; b; c", "c", &errors); - - // string concat operator - expect("a + b", "ab", &errors); - expect("a + \n \"b\"", "ab", &errors); - expect("a + b +\nc\n", "abc", &errors); - - // string concat function - expect("concat(a, b)", "ab", &errors); - expect("concat(a,\n \"b\")", "ab", &errors); - expect("concat(a + b,\nc,\"d\")", "abcd", &errors); - expect("\"concat\"(a + b,\nc,\"d\")", "abcd", &errors); - - // logical and - expect("a && b", "b", &errors); - expect("a && \"\"", "", &errors); - expect("\"\" && b", "", &errors); - expect("\"\" && \"\"", "", &errors); - expect("\"\" && abort()", "", &errors); // test short-circuiting - expect("t && abort()", NULL, &errors); - - // logical or - expect("a || b", "a", &errors); - expect("a || \"\"", "a", &errors); - expect("\"\" || b", "b", &errors); - expect("\"\" || \"\"", "", &errors); - expect("a || abort()", "a", &errors); // test short-circuiting - expect("\"\" || abort()", NULL, &errors); - - // logical not - expect("!a", "", &errors); - expect("! \"\"", "t", &errors); - expect("!!a", "t", &errors); - - // precedence - expect("\"\" == \"\" && b", "b", &errors); - expect("a + b == ab", "t", &errors); - expect("ab == a + b", "t", &errors); - expect("a + (b == ab)", "a", &errors); - expect("(ab == a) + b", "b", &errors); - - // substring function - expect("is_substring(cad, abracadabra)", "t", &errors); - expect("is_substring(abrac, abracadabra)", "t", &errors); - expect("is_substring(dabra, abracadabra)", "t", &errors); - expect("is_substring(cad, abracxadabra)", "", &errors); - expect("is_substring(abrac, axbracadabra)", "", &errors); - expect("is_substring(dabra, abracadabrxa)", "", &errors); - - // ifelse function - expect("ifelse(t, yes, no)", "yes", &errors); - expect("ifelse(!t, yes, no)", "no", &errors); - expect("ifelse(t, yes, abort())", "yes", &errors); - expect("ifelse(!t, abort(), no)", "no", &errors); - - // if "statements" - expect("if t then yes else no endif", "yes", &errors); - expect("if \"\" then yes else no endif", "no", &errors); - expect("if \"\" then yes endif", "", &errors); - expect("if \"\"; t then yes endif", "yes", &errors); - - // numeric comparisons - expect("less_than_int(3, 14)", "t", &errors); - expect("less_than_int(14, 3)", "", &errors); - expect("less_than_int(x, 3)", "", &errors); - expect("less_than_int(3, x)", "", &errors); - expect("greater_than_int(3, 14)", "", &errors); - expect("greater_than_int(14, 3)", "t", &errors); - expect("greater_than_int(x, 3)", "", &errors); - expect("greater_than_int(3, x)", "", &errors); - - // big string - expect(std::string(8192, 's').c_str(), std::string(8192, 's').c_str(), &errors); - - printf("\n"); - - return errors; -} - -void ExprDump(int depth, Expr* n, char* script) { - printf("%*s", depth*2, ""); - char temp = script[n->end]; - script[n->end] = '\0'; - printf("%s %p (%d-%d) \"%s\"\n", - n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, - script+n->start); - script[n->end] = temp; - int i; - for (i = 0; i < n->argc; ++i) { - ExprDump(depth+1, n->argv[i], script); - } -} - -int main(int argc, char** argv) { - RegisterBuiltins(); - FinishRegistration(); - - if (argc == 1) { - return test() != 0; - } - - FILE* f = fopen(argv[1], "r"); - if (f == NULL) { - printf("%s: %s: No such file or directory\n", argv[0], argv[1]); - return 1; - } - char buffer[8192]; - int size = fread(buffer, 1, 8191, f); - fclose(f); - buffer[size] = '\0'; - - Expr* root; - int error_count = 0; - int error = parse_string(buffer, &root, &error_count); - printf("parse returned %d; %d errors encountered\n", error, error_count); - if (error == 0 || error_count > 0) { - - ExprDump(0, root, buffer); - - State state; - state.cookie = NULL; - state.script = buffer; - state.errmsg = NULL; - - char* result = Evaluate(&state, root); - if (result == NULL) { - printf("result was NULL, message is: %s\n", - (state.errmsg == NULL ? "(NULL)" : state.errmsg)); - free(state.errmsg); - } else { - printf("result is [%s]\n", result); - } - } - return 0; -} diff --git a/edify/parser.yy b/edify/parser.yy index 098a6370a..58a8dec65 100644 --- a/edify/parser.yy +++ b/edify/parser.yy @@ -33,6 +33,25 @@ struct yy_buffer_state; void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); struct yy_buffer_state* yy_scan_string(const char* yystr); +// Convenience function for building expressions with a fixed number +// of arguments. +static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { + va_list v; + va_start(v, count); + Expr* e = static_cast<Expr*>(malloc(sizeof(Expr))); + e->fn = fn; + e->name = "(operator)"; + e->argc = count; + e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*))); + for (size_t i = 0; i < count; ++i) { + e->argv[i] = va_arg(v, Expr*); + } + va_end(v); + e->start = loc.start; + e->end = loc.end; + return e; +} + %} %locations @@ -70,7 +89,7 @@ input: expr { *root = $1; } ; expr: STRING { - $$ = reinterpret_cast<Expr*>(malloc(sizeof(Expr))); + $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = Literal; $$->name = $1; $$->argc = 0; @@ -91,9 +110,9 @@ expr: STRING { | IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } | IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | STRING '(' arglist ')' { - $$ = reinterpret_cast<Expr*>(malloc(sizeof(Expr))); + $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = FindFunction($1); - if ($$->fn == NULL) { + if ($$->fn == nullptr) { char buffer[256]; snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); yyerror(root, error_count, buffer); @@ -113,12 +132,12 @@ arglist: /* empty */ { } | expr { $$.argc = 1; - $$.argv = reinterpret_cast<Expr**>(malloc(sizeof(Expr*))); + $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*))); $$.argv[0] = $1; } | arglist ',' expr { $$.argc = $1.argc + 1; - $$.argv = reinterpret_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*))); + $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*))); $$.argv[$$.argc-1] = $3; } ; 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 b091b1927..000000000 --- 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 index 5915b8d80..b1473ba4b 100644 --- a/etc/init.rc +++ b/etc/init.rc @@ -5,7 +5,6 @@ on early-init restorecon /postinstall start ueventd - start healthd on init export ANDROID_ROOT /system @@ -14,6 +13,9 @@ on init symlink /system/etc /etc + mount cgroup none /acct cpuacct + mkdir /acct/uid + mkdir /sdcard mkdir /system mkdir /data diff --git a/fuse_sdcard_provider.cpp b/fuse_sdcard_provider.cpp index df9631272..b0ecf96be 100644 --- a/fuse_sdcard_provider.cpp +++ b/fuse_sdcard_provider.cpp @@ -23,6 +23,8 @@ #include <unistd.h> #include <fcntl.h> +#include <android-base/file.h> + #include "fuse_sideload.h" struct file_data { @@ -41,14 +43,9 @@ static int read_block_file(void* cookie, uint32_t block, uint8_t* buffer, uint32 return -EIO; } - while (fetch_size > 0) { - ssize_t r = TEMP_FAILURE_RETRY(read(fd->fd, buffer, fetch_size)); - if (r == -1) { - fprintf(stderr, "read on sdcard failed: %s\n", strerror(errno)); - return -EIO; - } - fetch_size -= r; - buffer += r; + if (!android::base::ReadFully(fd->fd, buffer, fetch_size)) { + fprintf(stderr, "read on sdcard failed: %s\n", strerror(errno)); + return -EIO; } return 0; diff --git a/install.cpp b/install.cpp index e144d9b29..919f241a2 100644 --- a/install.cpp +++ b/install.cpp @@ -31,19 +31,18 @@ #include <vector> #include <android-base/file.h> +#include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <cutils/properties.h> +#include <ziparchive/zip_archive.h> #include "common.h" #include "error_code.h" #include "install.h" #include "minui/minui.h" -#include "minzip/SysUtil.h" -#include "minzip/Zip.h" -#include "mtdutils/mounts.h" -#include "mtdutils/mtdutils.h" +#include "otautil/SysUtil.h" #include "roots.h" #include "ui.h" #include "verifier.h" @@ -64,8 +63,8 @@ static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4; static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1; // This function parses and returns the build.version.incremental -static int parse_build_number(std::string str) { - size_t pos = str.find("="); +static int parse_build_number(const std::string& str) { + size_t pos = str.find('='); if (pos != std::string::npos) { std::string num_string = android::base::Trim(str.substr(pos+1)); int build_number; @@ -74,27 +73,33 @@ static int parse_build_number(std::string str) { } } - LOGE("Failed to parse build number in %s.\n", str.c_str()); + LOG(ERROR) << "Failed to parse build number in " << str; return -1; } -bool read_metadata_from_package(ZipArchive* zip, std::string* meta_data) { - const ZipEntry* meta_entry = mzFindZipEntry(zip, METADATA_PATH); - if (meta_entry == nullptr) { - LOGE("Failed to find %s in update package.\n", METADATA_PATH); +bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data) { + ZipString metadata_path(METADATA_PATH); + ZipEntry meta_entry; + if (meta_data == nullptr) { + LOG(ERROR) << "string* meta_data can't be nullptr"; + return false; + } + if (FindEntry(zip, metadata_path, &meta_entry) != 0) { + LOG(ERROR) << "Failed to find " << METADATA_PATH << " in update package"; return false; } - meta_data->resize(meta_entry->uncompLen, '\0'); - if (!mzReadZipEntry(zip, meta_entry, &(*meta_data)[0], meta_entry->uncompLen)) { - LOGE("Failed to read metadata in update package.\n"); + meta_data->resize(meta_entry.uncompressed_length, '\0'); + if (ExtractToMemory(zip, &meta_entry, reinterpret_cast<uint8_t*>(&(*meta_data)[0]), + meta_entry.uncompressed_length) != 0) { + LOG(ERROR) << "Failed to read metadata in update package"; return false; } return true; } // Read the build.version.incremental of src/tgt from the metadata and log it to last_install. -static void read_source_target_build(ZipArchive* zip, std::vector<std::string>& log_buffer) { +static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::string>& log_buffer) { std::string meta_data; if (!read_metadata_from_package(zip, &meta_data)) { return; @@ -126,7 +131,7 @@ static void read_source_target_build(ZipArchive* zip, std::vector<std::string>& // is the file descriptor the child process should use to report back the // progress of the update. static int -update_binary_command(const char* path, ZipArchive* zip, int retry_count, +update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count, int status_fd, std::vector<std::string>* cmd); #ifdef AB_OTA_UPDATER @@ -134,7 +139,7 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, // Parses the metadata of the OTA package in |zip| and checks whether we are // allowed to accept this A/B package. Downgrading is not allowed unless // explicitly enabled in the package and only for incremental packages. -static int check_newer_ab_build(ZipArchive* zip) +static int check_newer_ab_build(ZipArchiveHandle zip) { std::string metadata_str; if (!read_metadata_from_package(zip, &metadata_str)) { @@ -152,8 +157,7 @@ static int check_newer_ab_build(ZipArchive* zip) property_get("ro.product.device", value, ""); const std::string& pkg_device = metadata["pre-device"]; if (pkg_device != value || pkg_device.empty()) { - LOGE("Package is for product %s but expected %s\n", - pkg_device.c_str(), value); + LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << value; return INSTALL_ERROR; } @@ -162,12 +166,12 @@ static int check_newer_ab_build(ZipArchive* zip) property_get("ro.serialno", value, ""); const std::string& pkg_serial_no = metadata["serialno"]; if (!pkg_serial_no.empty() && pkg_serial_no != value) { - LOGE("Package is for serial %s\n", pkg_serial_no.c_str()); + LOG(ERROR) << "Package is for serial " << pkg_serial_no; return INSTALL_ERROR; } if (metadata["ota-type"] != "AB") { - LOGE("Package is not A/B\n"); + LOG(ERROR) << "Package is not A/B"; return INSTALL_ERROR; } @@ -175,39 +179,36 @@ static int check_newer_ab_build(ZipArchive* zip) property_get("ro.build.version.incremental", value, ""); const std::string& pkg_pre_build = metadata["pre-build-incremental"]; if (!pkg_pre_build.empty() && pkg_pre_build != value) { - LOGE("Package is for source build %s but expected %s\n", - pkg_pre_build.c_str(), value); + LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected " << value; return INSTALL_ERROR; } property_get("ro.build.fingerprint", value, ""); const std::string& pkg_pre_build_fingerprint = metadata["pre-build"]; if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != value) { - LOGE("Package is for source build %s but expected %s\n", - pkg_pre_build_fingerprint.c_str(), value); + LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint + << " but expected " << value; return INSTALL_ERROR; } // Check for downgrade version. - int64_t build_timestampt = property_get_int64( + int64_t build_timestamp = property_get_int64( "ro.build.date.utc", std::numeric_limits<int64_t>::max()); - int64_t pkg_post_timespampt = 0; + int64_t pkg_post_timestamp = 0; // We allow to full update to the same version we are running, in case there // is a problem with the current copy of that version. if (metadata["post-timestamp"].empty() || !android::base::ParseInt(metadata["post-timestamp"].c_str(), - &pkg_post_timespampt) || - pkg_post_timespampt < build_timestampt) { + &pkg_post_timestamp) || + pkg_post_timestamp < build_timestamp) { if (metadata["ota-downgrade"] != "yes") { - LOGE("Update package is older than the current build, expected a " - "build newer than timestamp %" PRIu64 " but package has " - "timestamp %" PRIu64 " and downgrade not allowed.\n", - build_timestampt, pkg_post_timespampt); + LOG(ERROR) << "Update package is older than the current build, expected a build " + "newer than timestamp " << build_timestamp << " but package has " + "timestamp " << pkg_post_timestamp << " and downgrade not allowed."; return INSTALL_ERROR; } if (pkg_pre_build_fingerprint.empty()) { - LOGE("Downgrade package must have a pre-build version set, not " - "allowed.\n"); + LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed."; return INSTALL_ERROR; } } @@ -216,7 +217,7 @@ static int check_newer_ab_build(ZipArchive* zip) } static int -update_binary_command(const char* path, ZipArchive* zip, int retry_count, +update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count, int status_fd, std::vector<std::string>* cmd) { int ret = check_newer_ab_build(zip); @@ -226,26 +227,27 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, // For A/B updates we extract the payload properties to a buffer and obtain // the RAW payload offset in the zip file. - const ZipEntry* properties_entry = - mzFindZipEntry(zip, AB_OTA_PAYLOAD_PROPERTIES); - if (!properties_entry) { - LOGE("Can't find %s\n", AB_OTA_PAYLOAD_PROPERTIES); + ZipString property_name(AB_OTA_PAYLOAD_PROPERTIES); + ZipEntry properties_entry; + if (FindEntry(zip, property_name, &properties_entry) != 0) { + LOG(ERROR) << "Can't find " << AB_OTA_PAYLOAD_PROPERTIES; return INSTALL_CORRUPT; } - std::vector<unsigned char> payload_properties( - mzGetZipEntryUncompLen(properties_entry)); - if (!mzExtractZipEntryToBuffer(zip, properties_entry, - payload_properties.data())) { - LOGE("Can't extract %s\n", AB_OTA_PAYLOAD_PROPERTIES); + std::vector<uint8_t> payload_properties( + properties_entry.uncompressed_length); + if (ExtractToMemory(zip, &properties_entry, payload_properties.data(), + properties_entry.uncompressed_length) != 0) { + LOG(ERROR) << "Can't extract " << AB_OTA_PAYLOAD_PROPERTIES; return INSTALL_CORRUPT; } - const ZipEntry* payload_entry = mzFindZipEntry(zip, AB_OTA_PAYLOAD); - if (!payload_entry) { - LOGE("Can't find %s\n", AB_OTA_PAYLOAD); + ZipString payload_name(AB_OTA_PAYLOAD); + ZipEntry payload_entry; + if (FindEntry(zip, payload_name, &payload_entry) != 0) { + LOG(ERROR) << "Can't find " << AB_OTA_PAYLOAD; return INSTALL_CORRUPT; } - long payload_offset = mzGetZipEntryOffset(payload_entry); + long payload_offset = payload_entry.offset; *cmd = { "/sbin/update_engine_sideload", android::base::StringPrintf("--payload=file://%s", path), @@ -260,13 +262,13 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, #else // !AB_OTA_UPDATER static int -update_binary_command(const char* path, ZipArchive* zip, int retry_count, +update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count, int status_fd, std::vector<std::string>* cmd) { // On traditional updates we extract the update binary from the package. - const ZipEntry* binary_entry = - mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); - if (binary_entry == NULL) { + ZipString binary_name(ASSUMED_UPDATE_BINARY_NAME); + ZipEntry binary_entry; + if (FindEntry(zip, binary_name, &binary_entry) != 0) { return INSTALL_CORRUPT; } @@ -274,14 +276,15 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, unlink(binary); int fd = creat(binary, 0755); if (fd < 0) { - LOGE("Can't make %s\n", binary); + PLOG(ERROR) << "Can't make " << binary; return INSTALL_ERROR; } - bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); + int error = ExtractEntryToFile(zip, &binary_entry, fd); close(fd); - if (!ok) { - LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); + if (error != 0) { + LOG(ERROR) << "Can't copy " << ASSUMED_UPDATE_BINARY_NAME + << " : " << ErrorCodeString(error); return INSTALL_ERROR; } @@ -299,7 +302,7 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, // If the package contains an update binary, extract it and run it. static int -try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, +try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache, std::vector<std::string>& log_buffer, int retry_count) { read_source_target_build(zip, log_buffer); @@ -309,7 +312,6 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, std::vector<std::string> args; int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args); - mzCloseZipArchive(zip); if (ret) { close(pipefd[0]); close(pipefd[1]); @@ -377,7 +379,7 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, if (pid == -1) { close(pipefd[0]); close(pipefd[1]); - LOGE("Failed to fork update binary: %s\n", strerror(errno)); + PLOG(ERROR) << "Failed to fork update binary"; return INSTALL_ERROR; } @@ -435,7 +437,7 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, // last_install later. log_buffer.push_back(std::string(strtok(NULL, "\n"))); } else { - LOGE("unknown command [%s]\n", command); + LOG(ERROR) << "unknown command [" << command << "]"; } } fclose(from_child); @@ -446,7 +448,7 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, return INSTALL_RETRY; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); + LOG(ERROR) << "Error in " << path << " (Status " << WEXITSTATUS(status) << ")"; return INSTALL_ERROR; } @@ -462,7 +464,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, // Give verification half the progress bar... ui->SetProgressType(RecoveryUI::DETERMINATE); ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); - LOGI("Update location: %s\n", path); + LOG(INFO) << "Update location: " << path; // Map the update package into memory. ui->Print("Opening update package...\n"); @@ -477,7 +479,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, MemMapping map; if (sysMapFile(path, &map) != 0) { - LOGE("failed to map file\n"); + LOG(ERROR) << "failed to map file"; return INSTALL_CORRUPT; } @@ -489,13 +491,14 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, } // Try to open the package. - ZipArchive zip; - int err = mzOpenZipArchive(map.addr, map.length, &zip); + ZipArchiveHandle zip; + int err = OpenArchiveFromMemory(map.addr, map.length, path, &zip); if (err != 0) { - LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); + LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err); log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure)); sysReleaseMap(&map); + CloseArchive(zip); return INSTALL_CORRUPT; } @@ -505,12 +508,12 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, ui->Print("Retry attempt: %d\n", retry_count); } ui->SetEnableReboot(false); - int result = try_update_binary(path, &zip, wipe_cache, log_buffer, retry_count); + int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count); ui->SetEnableReboot(true); ui->Print("\n"); sysReleaseMap(&map); - + CloseArchive(zip); return result; } @@ -524,7 +527,7 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, int result; std::vector<std::string> log_buffer; if (setup_install_mounts() != 0) { - LOGE("failed to set up expected mounts for install; aborting\n"); + LOG(ERROR) << "failed to set up expected mounts for install; aborting"; result = INSTALL_ERROR; } else { result = really_install_package(path, wipe_cache, needs_mount, log_buffer, retry_count); @@ -535,13 +538,13 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, int time_total = static_cast<int>(duration.count()); if (ensure_path_mounted(UNCRYPT_STATUS) != 0) { - LOGW("Can't mount %s\n", UNCRYPT_STATUS); + LOG(WARNING) << "Can't mount " << UNCRYPT_STATUS; } else { std::string uncrypt_status; if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) { - LOGW("failed to read uncrypt status: %s\n", strerror(errno)); + PLOG(WARNING) << "failed to read uncrypt status"; } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) { - LOGW("corrupted uncrypt_status: %s: %s\n", uncrypt_status.c_str(), strerror(errno)); + LOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status; } else { log_buffer.push_back(android::base::Trim(uncrypt_status)); } @@ -557,11 +560,11 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, std::string log_content = android::base::Join(log_header, "\n") + "\n" + android::base::Join(log_buffer, "\n"); if (!android::base::WriteStringToFile(log_content, install_file)) { - LOGE("failed to write %s: %s\n", install_file, strerror(errno)); + PLOG(ERROR) << "failed to write " << install_file; } // Write a copy into last_log. - LOGI("%s\n", log_content.c_str()); + LOG(INFO) << log_content; return result; } @@ -569,10 +572,10 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, bool verify_package(const unsigned char* package_data, size_t package_size) { std::vector<Certificate> loadedKeys; if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) { - LOGE("Failed to load keys\n"); + LOG(ERROR) << "Failed to load keys"; return false; } - LOGI("%zu key(s) loaded from %s\n", loadedKeys.size(), PUBLIC_KEYS_FILE); + LOG(INFO) << loadedKeys.size() << " key(s) loaded from " << PUBLIC_KEYS_FILE; // Verify package. ui->Print("Verifying update package...\n"); @@ -581,8 +584,8 @@ bool verify_package(const unsigned char* package_data, size_t package_size) { std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0; ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err); if (err != VERIFY_SUCCESS) { - LOGE("Signature verification failed\n"); - LOGE("error: %d\n", kZipVerificationFailure); + LOG(ERROR) << "Signature verification failed"; + LOG(ERROR) << "error: " << kZipVerificationFailure; return false; } return true; @@ -18,9 +18,9 @@ #define RECOVERY_INSTALL_H_ #include <string> +#include <ziparchive/zip_archive.h> #include "common.h" -#include "minzip/Zip.h" enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SKIPPED, INSTALL_RETRY }; @@ -36,6 +36,6 @@ bool verify_package(const unsigned char* package_data, size_t package_size); // Read meta data file of the package, write its content in the string pointed by meta_data. // Return true if succeed, otherwise return false. -bool read_metadata_from_package(ZipArchive* zip, std::string* meta_data); +bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data); #endif // RECOVERY_INSTALL_H_ diff --git a/minadbd/Android.mk b/minadbd/Android.mk index 3db3b4114..7eef13ee0 100644 --- a/minadbd/Android.mk +++ b/minadbd/Android.mk @@ -11,9 +11,9 @@ minadbd_cflags := \ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - adb_main.cpp \ fuse_adb_provider.cpp \ - services.cpp \ + minadbd.cpp \ + minadbd_services.cpp \ LOCAL_CLANG := true LOCAL_MODULE := libminadbd @@ -21,7 +21,7 @@ LOCAL_CFLAGS := $(minadbd_cflags) LOCAL_CONLY_FLAGS := -Wimplicit-function-declaration LOCAL_C_INCLUDES := bootable/recovery system/core/adb LOCAL_WHOLE_STATIC_LIBRARIES := libadbd -LOCAL_STATIC_LIBRARIES := libbase +LOCAL_STATIC_LIBRARIES := libcrypto libbase include $(BUILD_STATIC_LIBRARY) diff --git a/minadbd/fuse_adb_provider.cpp b/minadbd/fuse_adb_provider.cpp index d71807dfb..0f4c2563d 100644 --- a/minadbd/fuse_adb_provider.cpp +++ b/minadbd/fuse_adb_provider.cpp @@ -19,8 +19,6 @@ #include <string.h> #include <errno.h> -#include "sysdeps.h" - #include "adb.h" #include "adb_io.h" #include "fuse_adb_provider.h" diff --git a/minadbd/adb_main.cpp b/minadbd/minadbd.cpp index 0694280cb..349189cc7 100644 --- a/minadbd/adb_main.cpp +++ b/minadbd/minadbd.cpp @@ -14,18 +14,18 @@ * limitations under the License. */ +#include "minadbd.h" + #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> -#include "sysdeps.h" - #include "adb.h" #include "adb_auth.h" #include "transport.h" -int adb_server_main(int is_daemon, int server_port, int /* reply_fd */) { +int minadbd_main() { adb_device_banner = "sideload"; signal(SIGPIPE, SIG_IGN); diff --git a/minzip/inline_magic.h b/minadbd/minadbd.h index 59c659f77..3570a5da5 100644 --- a/minzip/inline_magic.h +++ b/minadbd/minadbd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 The Android Open Source Project + * Copyright (C) 2016 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. @@ -14,13 +14,9 @@ * limitations under the License. */ -#ifndef MINZIP_INLINE_MAGIC_H_ -#define MINZIP_INLINE_MAGIC_H_ +#ifndef MINADBD_H__ +#define MINADBD_H__ -#ifndef MINZIP_GENERATE_INLINES -#define INLINE extern inline __attribute((__gnu_inline__)) -#else -#define INLINE -#endif +int minadbd_main(); -#endif // MINZIP_INLINE_MAGIC_H_ +#endif diff --git a/minadbd/services.cpp b/minadbd/minadbd_services.cpp index 658a43f36..003b51913 100644 --- a/minadbd/services.cpp +++ b/minadbd/minadbd_services.cpp @@ -21,11 +21,10 @@ #include <string.h> #include <unistd.h> -#include "sysdeps.h" - #include "adb.h" #include "fdevent.h" #include "fuse_adb_provider.h" +#include "sysdeps.h" typedef struct stinfo stinfo; @@ -62,7 +61,7 @@ static void sideload_host_service(int sfd, void* data) { static int create_service_thread(void (*func)(int, void *), void *cookie) { int s[2]; - if(adb_socketpair(s)) { + if (adb_socketpair(s)) { printf("cannot create service socket pair\n"); return -1; } diff --git a/minui/Android.mk b/minui/Android.mk index 3057f452c..67b81fc6d 100644 --- a/minui/Android.mk +++ b/minui/Android.mk @@ -11,7 +11,9 @@ LOCAL_SRC_FILES := \ LOCAL_WHOLE_STATIC_LIBRARIES += libadf LOCAL_WHOLE_STATIC_LIBRARIES += libdrm +LOCAL_WHOLE_STATIC_LIBRARIES += libsync_recovery LOCAL_STATIC_LIBRARIES += libpng +LOCAL_CFLAGS := -Werror LOCAL_MODULE := libminui @@ -45,4 +47,5 @@ LOCAL_CLANG := true LOCAL_MODULE := libminui LOCAL_WHOLE_STATIC_LIBRARIES += libminui LOCAL_SHARED_LIBRARIES := libpng +LOCAL_CFLAGS := -Werror include $(BUILD_SHARED_LIBRARY) diff --git a/minui/events.cpp b/minui/events.cpp index 3b2262a4b..e6e7bd28c 100644 --- a/minui/events.cpp +++ b/minui/events.cpp @@ -49,7 +49,7 @@ static unsigned ev_count = 0; static unsigned ev_dev_count = 0; static unsigned ev_misc_count = 0; -static bool test_bit(size_t bit, unsigned long* array) { +static bool test_bit(size_t bit, unsigned long* array) { // NOLINT return (array[bit/BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))) != 0; } @@ -65,7 +65,8 @@ int ev_init(ev_callback input_cb, void* data) { if (dir != NULL) { dirent* de; while ((de = readdir(dir))) { - unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT // fprintf(stderr,"/dev/input/%s\n", de->d_name); if (strncmp(de->d_name, "event", 5)) continue; @@ -175,8 +176,9 @@ int ev_get_input(int fd, uint32_t epevents, input_event* ev) { } int ev_sync_key_state(ev_set_key_callback set_key_cb, void* data) { - unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; - unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT + unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT for (size_t i = 0; i < ev_dev_count; ++i) { memset(ev_bits, 0, sizeof(ev_bits)); @@ -202,9 +204,10 @@ int ev_sync_key_state(ev_set_key_callback set_key_cb, void* data) { return 0; } -void ev_iterate_available_keys(std::function<void(int)> f) { - unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; - unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; +void ev_iterate_available_keys(const std::function<void(int)>& f) { + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT + unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT for (size_t i = 0; i < ev_dev_count; ++i) { memset(ev_bits, 0, sizeof(ev_bits)); diff --git a/minui/graphics_adf.cpp b/minui/graphics_adf.cpp index 5d0867f58..3c3541094 100644 --- a/minui/graphics_adf.cpp +++ b/minui/graphics_adf.cpp @@ -26,11 +26,13 @@ #include <sys/mman.h> #include <adf/adf.h> +#include <sync/sync.h> #include "graphics.h" struct adf_surface_pdata { GRSurface base; + int fence_fd; int fd; __u32 offset; __u32 pitch; @@ -42,6 +44,8 @@ struct adf_pdata { adf_id_t eng_id; __u32 format; + adf_device dev; + unsigned int current_surface; unsigned int n_surfaces; adf_surface_pdata surfaces[2]; @@ -53,6 +57,7 @@ static void adf_blank(minui_backend *backend, bool blank); static int adf_surface_init(adf_pdata *pdata, drm_mode_modeinfo *mode, adf_surface_pdata *surf) { memset(surf, 0, sizeof(*surf)); + surf->fence_fd = -1; surf->fd = adf_interface_simple_buffer_alloc(pdata->intf_fd, mode->hdisplay, mode->vdisplay, pdata->format, &surf->offset, &surf->pitch); if (surf->fd < 0) @@ -163,21 +168,20 @@ static GRSurface* adf_init(minui_backend *backend) pdata->intf_fd = -1; for (i = 0; i < n_dev_ids && pdata->intf_fd < 0; i++) { - adf_device dev; - int err = adf_device_open(dev_ids[i], O_RDWR, &dev); + int err = adf_device_open(dev_ids[i], O_RDWR, &pdata->dev); if (err < 0) { fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i], strerror(-err)); continue; } - err = adf_device_init(pdata, &dev); - if (err < 0) + err = adf_device_init(pdata, &pdata->dev); + if (err < 0) { fprintf(stderr, "initializing adf device %u failed: %s\n", dev_ids[i], strerror(-err)); - - adf_device_close(&dev); + adf_device_close(&pdata->dev); + } } free(dev_ids); @@ -193,6 +197,23 @@ static GRSurface* adf_init(minui_backend *backend) return ret; } +static void adf_sync(adf_surface_pdata *surf) +{ + unsigned int warningTimeout = 3000; + + if (surf == NULL) + return; + + if (surf->fence_fd >= 0){ + int err = sync_wait(surf->fence_fd, warningTimeout); + if (err < 0) + perror("adf sync fence wait error\n"); + + close(surf->fence_fd); + surf->fence_fd = -1; + } +} + static GRSurface* adf_flip(minui_backend *backend) { adf_pdata *pdata = (adf_pdata *)backend; @@ -202,9 +223,10 @@ static GRSurface* adf_flip(minui_backend *backend) surf->base.width, surf->base.height, pdata->format, surf->fd, surf->offset, surf->pitch, -1); if (fence_fd >= 0) - close(fence_fd); + surf->fence_fd = fence_fd; pdata->current_surface = (pdata->current_surface + 1) % pdata->n_surfaces; + adf_sync(&pdata->surfaces[pdata->current_surface]); return &pdata->surfaces[pdata->current_surface].base; } @@ -218,6 +240,7 @@ static void adf_blank(minui_backend *backend, bool blank) static void adf_surface_destroy(adf_surface_pdata *surf) { munmap(surf->base.data, surf->pitch * surf->base.height); + close(surf->fence_fd); close(surf->fd); } @@ -226,6 +249,7 @@ static void adf_exit(minui_backend *backend) adf_pdata *pdata = (adf_pdata *)backend; unsigned int i; + adf_device_close(&pdata->dev); for (i = 0; i < pdata->n_surfaces; i++) adf_surface_destroy(&pdata->surfaces[i]); if (pdata->intf_fd >= 0) diff --git a/minui/minui.h b/minui/minui.h index d30426dc8..78890b84b 100644 --- a/minui/minui.h +++ b/minui/minui.h @@ -77,7 +77,7 @@ typedef int (*ev_set_key_callback)(int code, int value, void* data); int ev_init(ev_callback input_cb, void* data); void ev_exit(); int ev_add_fd(int fd, ev_callback cb, void* data); -void ev_iterate_available_keys(std::function<void(int)> f); +void ev_iterate_available_keys(const std::function<void(int)>& f); int ev_sync_key_state(ev_set_key_callback set_key_cb, void* data); // 'timeout' has the same semantics as poll(2). @@ -123,8 +123,8 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface); // given locale. The image is expected to be a composite of multiple // translations of the same text, with special added rows that encode // the subimages' size and intended locale in the pixel data. See -// development/tools/recovery_l10n for an app that will generate these -// specialized images from Android resources. +// bootable/recovery/tools/recovery_l10n for an app that will generate +// these specialized images from Android resources. int res_create_localized_alpha_surface(const char* name, const char* locale, GRSurface** pSurface); diff --git a/minui/resources.cpp b/minui/resources.cpp index 40d3c2c88..730b05f13 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -28,6 +28,7 @@ #include <linux/fb.h> #include <linux/kd.h> +#include <vector> #include <png.h> #include "minui.h" @@ -280,7 +281,7 @@ int res_create_multi_display_surface(const char* name, int* frames, int* fps, goto exit; } - surface = reinterpret_cast<GRSurface**>(malloc(*frames * sizeof(GRSurface*))); + surface = reinterpret_cast<GRSurface**>(calloc(*frames, sizeof(GRSurface*))); if (surface == NULL) { result = -8; goto exit; @@ -315,7 +316,7 @@ exit: if (result < 0) { if (surface) { for (int i = 0; i < *frames; ++i) { - if (surface[i]) free(surface[i]); + free(surface[i]); } free(surface); } @@ -391,18 +392,13 @@ int res_create_localized_alpha_surface(const char* name, png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; - unsigned char* row; png_uint_32 y; + std::vector<unsigned char> row; *pSurface = NULL; if (locale == NULL) { - surface = malloc_surface(0); - surface->width = 0; - surface->height = 0; - surface->row_bytes = 0; - surface->pixel_bytes = 1; - goto exit; + return result; } result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); @@ -413,13 +409,13 @@ int res_create_localized_alpha_surface(const char* name, goto exit; } - row = reinterpret_cast<unsigned char*>(malloc(width)); + row.resize(width); for (y = 0; y < height; ++y) { - png_read_row(png_ptr, row, NULL); + png_read_row(png_ptr, row.data(), NULL); int w = (row[1] << 8) | row[0]; int h = (row[3] << 8) | row[2]; - int len = row[4]; - char* loc = (char*)row+5; + __unused int len = row[4]; + char* loc = reinterpret_cast<char*>(&row[5]); if (y+1+h >= height || matches_locale(loc, locale)) { printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y); @@ -436,8 +432,8 @@ int res_create_localized_alpha_surface(const char* name, int i; for (i = 0; i < h; ++i, ++y) { - png_read_row(png_ptr, row, NULL); - memcpy(surface->data + i*w, row, w); + png_read_row(png_ptr, row.data(), NULL); + memcpy(surface->data + i*w, row.data(), w); } *pSurface = reinterpret_cast<GRSurface*>(surface); @@ -445,7 +441,7 @@ int res_create_localized_alpha_surface(const char* name, } else { int i; for (i = 0; i < h; ++i, ++y) { - png_read_row(png_ptr, row, NULL); + png_read_row(png_ptr, row.data(), NULL); } } } diff --git a/minzip/Android.mk b/minzip/Android.mk deleted file mode 100644 index 22eabfbb1..000000000 --- a/minzip/Android.mk +++ /dev/null @@ -1,23 +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_STATIC_LIBRARIES := libselinux - -LOCAL_MODULE := libminzip - -LOCAL_CLANG := true - -LOCAL_CFLAGS += -Werror -Wall - -include $(BUILD_STATIC_LIBRARY) diff --git a/minzip/Bits.h b/minzip/Bits.h deleted file mode 100644 index f96e6c443..000000000 --- a/minzip/Bits.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Some handy functions for manipulating bits and bytes. - */ -#ifndef _MINZIP_BITS -#define _MINZIP_BITS - -#include "inline_magic.h" - -#include <stdlib.h> -#include <string.h> - -/* - * Get 1 byte. (Included to make the code more legible.) - */ -INLINE unsigned char get1(unsigned const char* pSrc) -{ - return *pSrc; -} - -/* - * Get 2 big-endian bytes. - */ -INLINE unsigned short get2BE(unsigned char const* pSrc) -{ - unsigned short result; - - result = *pSrc++ << 8; - result |= *pSrc++; - - return result; -} - -/* - * Get 4 big-endian bytes. - */ -INLINE unsigned int get4BE(unsigned char const* pSrc) -{ - unsigned int result; - - result = *pSrc++ << 24; - result |= *pSrc++ << 16; - result |= *pSrc++ << 8; - result |= *pSrc++; - - return result; -} - -/* - * Get 8 big-endian bytes. - */ -INLINE unsigned long long get8BE(unsigned char const* pSrc) -{ - unsigned long long result; - - result = (unsigned long long) *pSrc++ << 56; - result |= (unsigned long long) *pSrc++ << 48; - result |= (unsigned long long) *pSrc++ << 40; - result |= (unsigned long long) *pSrc++ << 32; - result |= (unsigned long long) *pSrc++ << 24; - result |= (unsigned long long) *pSrc++ << 16; - result |= (unsigned long long) *pSrc++ << 8; - result |= (unsigned long long) *pSrc++; - - return result; -} - -/* - * Get 2 little-endian bytes. - */ -INLINE unsigned short get2LE(unsigned char const* pSrc) -{ - unsigned short result; - - result = *pSrc++; - result |= *pSrc++ << 8; - - return result; -} - -/* - * Get 4 little-endian bytes. - */ -INLINE unsigned int get4LE(unsigned char const* pSrc) -{ - unsigned int result; - - result = *pSrc++; - result |= *pSrc++ << 8; - result |= *pSrc++ << 16; - result |= *pSrc++ << 24; - - return result; -} - -/* - * Get 8 little-endian bytes. - */ -INLINE unsigned long long get8LE(unsigned char const* pSrc) -{ - unsigned long long result; - - result = (unsigned long long) *pSrc++; - result |= (unsigned long long) *pSrc++ << 8; - result |= (unsigned long long) *pSrc++ << 16; - result |= (unsigned long long) *pSrc++ << 24; - result |= (unsigned long long) *pSrc++ << 32; - result |= (unsigned long long) *pSrc++ << 40; - result |= (unsigned long long) *pSrc++ << 48; - result |= (unsigned long long) *pSrc++ << 56; - - return result; -} - -/* - * Grab 1 byte and advance the data pointer. - */ -INLINE unsigned char read1(unsigned const char** ppSrc) -{ - return *(*ppSrc)++; -} - -/* - * Grab 2 big-endian bytes and advance the data pointer. - */ -INLINE unsigned short read2BE(unsigned char const** ppSrc) -{ - unsigned short result; - - result = *(*ppSrc)++ << 8; - result |= *(*ppSrc)++; - - return result; -} - -/* - * Grab 4 big-endian bytes and advance the data pointer. - */ -INLINE unsigned int read4BE(unsigned char const** ppSrc) -{ - unsigned int result; - - result = *(*ppSrc)++ << 24; - result |= *(*ppSrc)++ << 16; - result |= *(*ppSrc)++ << 8; - result |= *(*ppSrc)++; - - return result; -} - -/* - * Get 8 big-endian bytes. - */ -INLINE unsigned long long read8BE(unsigned char const** ppSrc) -{ - unsigned long long result; - - result = (unsigned long long) *(*ppSrc)++ << 56; - result |= (unsigned long long) *(*ppSrc)++ << 48; - result |= (unsigned long long) *(*ppSrc)++ << 40; - result |= (unsigned long long) *(*ppSrc)++ << 32; - result |= (unsigned long long) *(*ppSrc)++ << 24; - result |= (unsigned long long) *(*ppSrc)++ << 16; - result |= (unsigned long long) *(*ppSrc)++ << 8; - result |= (unsigned long long) *(*ppSrc)++; - - return result; -} - -/* - * Grab 2 little-endian bytes and advance the data pointer. - */ -INLINE unsigned short read2LE(unsigned char const** ppSrc) -{ - unsigned short result; - - result = *(*ppSrc)++; - result |= *(*ppSrc)++ << 8; - - return result; -} - -/* - * Grab 4 little-endian bytes and advance the data pointer. - */ -INLINE unsigned int read4LE(unsigned char const** ppSrc) -{ - unsigned int result; - - result = *(*ppSrc)++; - result |= *(*ppSrc)++ << 8; - result |= *(*ppSrc)++ << 16; - result |= *(*ppSrc)++ << 24; - - return result; -} - -/* - * Get 8 little-endian bytes. - */ -INLINE unsigned long long read8LE(unsigned char const** ppSrc) -{ - unsigned long long result; - - result = (unsigned long long) *(*ppSrc)++; - result |= (unsigned long long) *(*ppSrc)++ << 8; - result |= (unsigned long long) *(*ppSrc)++ << 16; - result |= (unsigned long long) *(*ppSrc)++ << 24; - result |= (unsigned long long) *(*ppSrc)++ << 32; - result |= (unsigned long long) *(*ppSrc)++ << 40; - result |= (unsigned long long) *(*ppSrc)++ << 48; - result |= (unsigned long long) *(*ppSrc)++ << 56; - - return result; -} - -/* - * Skip over a UTF-8 string. - */ -INLINE void skipUtf8String(unsigned char const** ppSrc) -{ - unsigned int length = read4BE(ppSrc); - - (*ppSrc) += length; -} - -/* - * Read a UTF-8 string into a fixed-size buffer, and null-terminate it. - * - * Returns the length of the original string. - */ -INLINE int readUtf8String(unsigned char const** ppSrc, char* buf, size_t bufLen) -{ - unsigned int length = read4BE(ppSrc); - size_t copyLen = (length < bufLen) ? length : bufLen-1; - - memcpy(buf, *ppSrc, copyLen); - buf[copyLen] = '\0'; - - (*ppSrc) += length; - return length; -} - -/* - * Read a UTF-8 string into newly-allocated storage, and null-terminate it. - * - * Returns the string and its length. (The latter is probably unnecessary - * for the way we're using UTF8.) - */ -INLINE char* readNewUtf8String(unsigned char const** ppSrc, size_t* pLength) -{ - unsigned int length = read4BE(ppSrc); - char* buf; - - buf = (char*) malloc(length+1); - - memcpy(buf, *ppSrc, length); - buf[length] = '\0'; - - (*ppSrc) += length; - - *pLength = length; - return buf; -} - - -/* - * Set 1 byte. (Included to make the code more legible.) - */ -INLINE void set1(unsigned char* buf, unsigned char val) -{ - *buf = (unsigned char)(val); -} - -/* - * Set 2 big-endian bytes. - */ -INLINE void set2BE(unsigned char* buf, unsigned short val) -{ - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 4 big-endian bytes. - */ -INLINE void set4BE(unsigned char* buf, unsigned int val) -{ - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 8 big-endian bytes. - */ -INLINE void set8BE(unsigned char* buf, unsigned long long val) -{ - *buf++ = (unsigned char)(val >> 56); - *buf++ = (unsigned char)(val >> 48); - *buf++ = (unsigned char)(val >> 40); - *buf++ = (unsigned char)(val >> 32); - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 8); - *buf = (unsigned char)(val); -} - -/* - * Set 2 little-endian bytes. - */ -INLINE void set2LE(unsigned char* buf, unsigned short val) -{ - *buf++ = (unsigned char)(val); - *buf = (unsigned char)(val >> 8); -} - -/* - * Set 4 little-endian bytes. - */ -INLINE void set4LE(unsigned char* buf, unsigned int val) -{ - *buf++ = (unsigned char)(val); - *buf++ = (unsigned char)(val >> 8); - *buf++ = (unsigned char)(val >> 16); - *buf = (unsigned char)(val >> 24); -} - -/* - * Set 8 little-endian bytes. - */ -INLINE void set8LE(unsigned char* buf, unsigned long long val) -{ - *buf++ = (unsigned char)(val); - *buf++ = (unsigned char)(val >> 8); - *buf++ = (unsigned char)(val >> 16); - *buf++ = (unsigned char)(val >> 24); - *buf++ = (unsigned char)(val >> 32); - *buf++ = (unsigned char)(val >> 40); - *buf++ = (unsigned char)(val >> 48); - *buf = (unsigned char)(val >> 56); -} - -/* - * Stuff a UTF-8 string into the buffer. - */ -INLINE void setUtf8String(unsigned char* buf, const unsigned char* str) -{ - unsigned int strLen = strlen((const char*)str); - - set4BE(buf, strLen); - memcpy(buf + sizeof(unsigned int), str, strLen); -} - -#endif /*_MINZIP_BITS*/ diff --git a/minzip/Hash.c b/minzip/Hash.c deleted file mode 100644 index 49bcb3161..000000000 --- a/minzip/Hash.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Hash table. The dominant calls are add and lookup, with removals - * happening very infrequently. We use probing, and don't worry much - * about tombstone removal. - */ -#include <stdlib.h> -#include <assert.h> - -#define LOG_TAG "minzip" -#include "Log.h" -#include "Hash.h" - -/* table load factor, i.e. how full can it get before we resize */ -//#define LOAD_NUMER 3 // 75% -//#define LOAD_DENOM 4 -#define LOAD_NUMER 5 // 62.5% -#define LOAD_DENOM 8 -//#define LOAD_NUMER 1 // 50% -//#define LOAD_DENOM 2 - -/* - * Compute the capacity needed for a table to hold "size" elements. - */ -size_t mzHashSize(size_t size) { - return (size * LOAD_DENOM) / LOAD_NUMER +1; -} - -/* - * Round up to the next highest power of 2. - * - * Found on http://graphics.stanford.edu/~seander/bithacks.html. - */ -unsigned int roundUpPower2(unsigned int val) -{ - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - - return val; -} - -/* - * Create and initialize a hash table. - */ -HashTable* mzHashTableCreate(size_t initialSize, HashFreeFunc freeFunc) -{ - HashTable* pHashTable; - - assert(initialSize > 0); - - pHashTable = (HashTable*) malloc(sizeof(*pHashTable)); - if (pHashTable == NULL) - return NULL; - - pHashTable->tableSize = roundUpPower2(initialSize); - pHashTable->numEntries = pHashTable->numDeadEntries = 0; - pHashTable->freeFunc = freeFunc; - pHashTable->pEntries = - (HashEntry*) calloc((size_t)pHashTable->tableSize, sizeof(HashTable)); - if (pHashTable->pEntries == NULL) { - free(pHashTable); - return NULL; - } - - return pHashTable; -} - -/* - * Clear out all entries. - */ -void mzHashTableClear(HashTable* pHashTable) -{ - HashEntry* pEnt; - int i; - - pEnt = pHashTable->pEntries; - for (i = 0; i < pHashTable->tableSize; i++, pEnt++) { - if (pEnt->data == HASH_TOMBSTONE) { - // nuke entry - pEnt->data = NULL; - } else if (pEnt->data != NULL) { - // call free func then nuke entry - if (pHashTable->freeFunc != NULL) - (*pHashTable->freeFunc)(pEnt->data); - pEnt->data = NULL; - } - } - - pHashTable->numEntries = 0; - pHashTable->numDeadEntries = 0; -} - -/* - * Free the table. - */ -void mzHashTableFree(HashTable* pHashTable) -{ - if (pHashTable == NULL) - return; - mzHashTableClear(pHashTable); - free(pHashTable->pEntries); - free(pHashTable); -} - -#ifndef NDEBUG -/* - * Count up the number of tombstone entries in the hash table. - */ -static int countTombStones(HashTable* pHashTable) -{ - int i, count; - - for (count = i = 0; i < pHashTable->tableSize; i++) { - if (pHashTable->pEntries[i].data == HASH_TOMBSTONE) - count++; - } - return count; -} -#endif - -/* - * Resize a hash table. We do this when adding an entry increased the - * size of the table beyond its comfy limit. - * - * This essentially requires re-inserting all elements into the new storage. - * - * If multiple threads can access the hash table, the table's lock should - * have been grabbed before issuing the "lookup+add" call that led to the - * resize, so we don't have a synchronization problem here. - */ -static bool resizeHash(HashTable* pHashTable, int newSize) -{ - HashEntry* pNewEntries; - int i; - - assert(countTombStones(pHashTable) == pHashTable->numDeadEntries); - - 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 */ - break; - } - - pEntry++; - if (pEntry == pEnd) { /* wrap around to start */ - if (pHashTable->tableSize == 1) - break; /* edge case - single-entry table */ - 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 */ - } - - /* 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) { - 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; - } - } - - 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; - } - - LOGV("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 e83eac414..000000000 --- a/minzip/Hash.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2007 The Android Open Source Project - * - * General purpose hash table, used for finding classes, methods, etc. - * - * When the number of elements reaches 3/4 of the table's capacity, the - * table will be resized. - */ -#ifndef _MINZIP_HASH -#define _MINZIP_HASH - -#include "inline_magic.h" - -#include <stdlib.h> -#include <stdbool.h> -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* 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); - -#ifdef __cplusplus -} -#endif - -#endif /*_MINZIP_HASH*/ diff --git a/minzip/Log.h b/minzip/Log.h deleted file mode 100644 index 36e62f594..000000000 --- a/minzip/Log.h +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// -// C/C++ logging functions. See the logging documentation for API details. -// -// We'd like these to be available from C code (in case we import some from -// somewhere), so this has a C interface. -// -// The output will be correct when the log file is shared between multiple -// threads and/or multiple processes so long as the operating system -// supports O_APPEND. These calls have mutex-protected data structures -// and so are NOT reentrant. Do not use LOG in a signal handler. -// -#ifndef _MINZIP_LOG_H -#define _MINZIP_LOG_H - -#include <stdio.h> - -// --------------------------------------------------------------------- - -/* - * Normally we strip LOGV (VERBOSE messages) from release builds. - * You can modify this (for example with "#define LOG_NDEBUG 0" - * at the top of your source file) to change that behavior. - */ -#ifndef LOG_NDEBUG -#ifdef NDEBUG -#define LOG_NDEBUG 1 -#else -#define LOG_NDEBUG 0 -#endif -#endif - -/* - * This is the local tag used for the following simplified - * logging macros. You can change this preprocessor definition - * before using the other macros to change the tag. - */ -#ifndef LOG_TAG -#define LOG_TAG NULL -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose log message using the current LOG_TAG. - */ -#ifndef LOGV -#if LOG_NDEBUG -#define LOGV(...) ((void)0) -#else -#define LOGV(...) ((void)LOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef LOGV_IF -#if LOG_NDEBUG -#define LOGV_IF(cond, ...) ((void)0) -#else -#define LOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -#define LOGVV LOGV -#define LOGVV_IF LOGV_IF - -/* - * Simplified macro to send a debug log message using the current LOG_TAG. - */ -#ifndef LOGD -#define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGD_IF -#define LOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info log message using the current LOG_TAG. - */ -#ifndef LOGI -#define LOGI(...) ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGI_IF -#define LOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning log message using the current LOG_TAG. - */ -#ifndef LOGW -#define LOGW(...) ((void)LOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGW_IF -#define LOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error log message using the current LOG_TAG. - */ -#ifndef LOGE -#define LOGE(...) ((void)LOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef LOGE_IF -#define LOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)LOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * verbose priority. - */ -#ifndef IF_LOGV -#if LOG_NDEBUG -#define IF_LOGV() if (false) -#else -#define IF_LOGV() IF_LOG(LOG_VERBOSE, LOG_TAG) -#endif -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * debug priority. - */ -#ifndef IF_LOGD -#define IF_LOGD() IF_LOG(LOG_DEBUG, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * info priority. - */ -#ifndef IF_LOGI -#define IF_LOGI() IF_LOG(LOG_INFO, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * warn priority. - */ -#ifndef IF_LOGW -#define IF_LOGW() IF_LOG(LOG_WARN, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * error priority. - */ -#ifndef IF_LOGE -#define IF_LOGE() IF_LOG(LOG_ERROR, LOG_TAG) -#endif - -// --------------------------------------------------------------------- - -/* - * Basic log message macro. - * - * Example: - * LOG(LOG_WARN, NULL, "Failed with error %d", errno); - * - * The second argument may be NULL or "" to indicate the "global" tag. - * - * Non-gcc probably won't have __FUNCTION__. It's not vital. gcc also - * offers __PRETTY_FUNCTION__, which is rather more than we need. - */ -#ifndef LOG -#define LOG(priority, tag, ...) \ - LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to specify a number for the priority. - */ -#ifndef LOG_PRI -#define LOG_PRI(priority, tag, ...) \ - printf(tag ": " __VA_ARGS__) -#endif - -/* - * Conditional given a desired logging priority and tag. - */ -#ifndef IF_LOG -#define IF_LOG(priority, tag) \ - if (1) -#endif - -#endif // _MINZIP_LOG_H diff --git a/minzip/Zip.c b/minzip/Zip.c deleted file mode 100644 index bdb565c64..000000000 --- a/minzip/Zip.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Simple Zip file support. - */ -#include "safe_iop.h" -#include "zlib.h" - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdint.h> // for uintptr_t -#include <stdlib.h> -#include <sys/stat.h> // for S_ISLNK() -#include <unistd.h> - -#define LOG_TAG "minzip" -#include "Zip.h" -#include "Bits.h" -#include "Log.h" -#include "DirUtil.h" - -#undef NDEBUG // do this after including Log.h -#include <assert.h> - -#define SORT_ENTRIES 1 - -/* - * Offset and length constants (java.util.zip naming convention). - */ -enum { - CENSIG = 0x02014b50, // PK12 - CENHDR = 46, - - CENVEM = 4, - CENVER = 6, - CENFLG = 8, - CENHOW = 10, - CENTIM = 12, - CENCRC = 16, - CENSIZ = 20, - CENLEN = 24, - CENNAM = 28, - CENEXT = 30, - CENCOM = 32, - CENDSK = 34, - CENATT = 36, - CENATX = 38, - CENOFF = 42, - - ENDSIG = 0x06054b50, // PK56 - ENDHDR = 22, - - ENDSUB = 8, - ENDTOT = 10, - ENDSIZ = 12, - ENDOFF = 16, - ENDCOM = 20, - - EXTSIG = 0x08074b50, // PK78 - EXTHDR = 16, - - EXTCRC = 4, - EXTSIZ = 8, - EXTLEN = 12, - - LOCSIG = 0x04034b50, // PK34 - LOCHDR = 30, - - LOCVER = 4, - LOCFLG = 6, - LOCHOW = 8, - LOCTIM = 10, - LOCCRC = 14, - LOCSIZ = 18, - LOCLEN = 22, - LOCNAM = 26, - LOCEXT = 28, - - STORED = 0, - DEFLATED = 8, - - CENVEM_UNIX = 3 << 8, // the high byte of CENVEM -}; - - -/* - * For debugging, dump the contents of a ZipEntry. - */ -#if 0 -static void dumpEntry(const ZipEntry* pEntry) -{ - LOGI(" %p '%.*s'\n", pEntry->fileName,pEntry->fileNameLen,pEntry->fileName); - LOGI(" off=%ld comp=%ld uncomp=%ld how=%d\n", pEntry->offset, - pEntry->compLen, pEntry->uncompLen, pEntry->compression); -} -#endif - -/* - * (This is a mzHashTableLookup callback.) - * - * Compare two ZipEntry structs, by name. - */ -static int hashcmpZipEntry(const void* ventry1, const void* ventry2) -{ - const ZipEntry* entry1 = (const ZipEntry*) ventry1; - const ZipEntry* entry2 = (const ZipEntry*) ventry2; - - if (entry1->fileNameLen != entry2->fileNameLen) - return entry1->fileNameLen - entry2->fileNameLen; - return memcmp(entry1->fileName, entry2->fileName, entry1->fileNameLen); -} - -/* - * (This is a mzHashTableLookup callback.) - * - * find a ZipEntry struct by name. - */ -static int hashcmpZipName(const void* ventry, const void* vname) -{ - const ZipEntry* entry = (const ZipEntry*) ventry; - const char* name = (const char*) vname; - unsigned int nameLen = strlen(name); - - if (entry->fileNameLen != nameLen) - return entry->fileNameLen - nameLen; - return memcmp(entry->fileName, name, nameLen); -} - -/* - * Compute the hash code for a ZipEntry filename. - * - * Not expected to be compatible with any other hash function, so we init - * to 2 to ensure it doesn't happen to match. - */ -static unsigned int computeHash(const char* name, int nameLen) -{ - unsigned int hash = 2; - - while (nameLen--) - hash = hash * 31 + *name++; - - return hash; -} - -static void addEntryToHashTable(HashTable* pHash, ZipEntry* pEntry) -{ - unsigned int itemHash = computeHash(pEntry->fileName, pEntry->fileNameLen); - const ZipEntry* found; - - found = (const ZipEntry*)mzHashTableLookup(pHash, - itemHash, pEntry, hashcmpZipEntry, true); - if (found != pEntry) { - LOGW("WARNING: duplicate entry '%.*s' in Zip\n", - found->fileNameLen, found->fileName); - /* keep going */ - } -} - -static int validFilename(const char *fileName, unsigned int fileNameLen) -{ - // Forbid super long filenames. - if (fileNameLen >= PATH_MAX) { - LOGW("Filename too long (%d chatacters)\n", fileNameLen); - return 0; - } - - // Require all characters to be printable ASCII (no NUL, no UTF-8, etc). - unsigned int i; - for (i = 0; i < fileNameLen; ++i) { - if (fileName[i] < 32 || fileName[i] >= 127) { - LOGW("Filename contains invalid character '\%03o'\n", fileName[i]); - return 0; - } - } - - return 1; -} - -/* - * Parse the contents of a Zip archive. After confirming that the file - * is in fact a Zip, we scan out the contents of the central directory and - * store it in a hash table. - * - * Returns "true" on success. - */ -static bool parseZipArchive(ZipArchive* pArchive) -{ - 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(pArchive->addr); - if (val == ENDSIG) { - LOGW("Found Zip archive, but it looks empty\n"); - goto bail; - } else if (val != LOCSIG) { - LOGW("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 = pArchive->addr + pArchive->length - ENDHDR; - - while (ptr >= (const unsigned char*) pArchive->addr) { - if (*ptr == (ENDSIG & 0xff) && get4LE(ptr) == ENDSIG) - break; - ptr--; - } - if (ptr < (const unsigned char*) pArchive->addr) { - LOGW("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 >= pArchive->length) { - LOGW("Invalid entries=%d offset=%d (len=%zd)\n", - numEntries, cdOffset, pArchive->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 = pArchive->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*)pArchive->addr + pArchive->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*)pArchive->addr + pArchive->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 - 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 pArchive->addr + localHdrOffset, ensuring that it won't - // overflow. This is needed because localHdrOffset is untrusted. - if (!safe_add((uintptr_t *)&localHdr, (uintptr_t)pArchive->addr, - (uintptr_t)localHdrOffset)) { - LOGW("Integer overflow adding in parseZipArchive\n"); - goto bail; - } - if ((uintptr_t)localHdr + LOCHDR > - (uintptr_t)pArchive->addr + pArchive->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 > pArchive->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(unsigned char* addr, size_t length, ZipArchive* pArchive) -{ - int err; - - if (length < ENDHDR) { - err = -1; - LOGW("Archive %p is too small to be zip (%zd)\n", pArchive, length); - goto bail; - } - - pArchive->addr = addr; - pArchive->length = length; - - if (!parseZipArchive(pArchive)) { - err = -1; - LOGW("Parsing archive %p failed\n", pArchive); - goto bail; - } - - err = 0; - -bail: - if (err != 0) - mzCloseZipArchive(pArchive); - 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); - - free(pArchive->pEntries); - - mzHashTableFree(pArchive->pHash); - - 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. - */ -static 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) -{ - return processFunction(pArchive->addr + pEntry->offset, pEntry->uncompLen, cookie); -} - -static bool processDeflatedEntry(const ZipArchive *pArchive, - const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, - void *cookie) -{ - long result = -1; - 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 = pArchive->addr + pEntry->offset; - zstream.avail_in = pEntry->compLen; - 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 { - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGW("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; - - 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; - } - - return ret; -} - -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 *cookie) -{ - int fd = (int)(intptr_t)cookie; - if (dataLen == 0) { - return true; - } - ssize_t soFar = 0; - while (true) { - ssize_t n = TEMP_FAILURE_RETRY(write(fd, data+soFar, dataLen-soFar)); - if (n <= 0) { - LOGE("Error writing %zd bytes from zip file from %p: %s\n", - dataLen-soFar, data+soFar, strerror(errno)); - return false; - } else if (n > 0) { - soFar += n; - if (soFar == dataLen) return true; - if (soFar > dataLen) { - LOGE("write overrun? (%zd bytes instead of %d)\n", - soFar, dataLen); - return false; - } - } - } -} - -/* - * 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*)(intptr_t)fd); - if (!ret) { - LOGE("Can't extract entry to file.\n"); - return false; - } - return true; -} - -typedef struct { - unsigned char* buffer; - long len; -} BufferExtractCookie; - -static bool bufferProcessFunction(const unsigned char *data, int dataLen, - void *cookie) { - BufferExtractCookie *bec = (BufferExtractCookie*)cookie; - - memmove(bec->buffer, data, dataLen); - bec->buffer += dataLen; - bec->len -= dataLen; - - return true; -} - -/* - * Uncompress "pEntry" in "pArchive" to buffer, which must be large - * enough to hold mzGetZipEntryUncomplen(pEntry) bytes. - */ -bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive, - const ZipEntry *pEntry, unsigned char *buffer) -{ - BufferExtractCookie bec; - bec.buffer = buffer; - bec.len = mzGetZipEntryUncompLen(pEntry); - - bool ret = mzProcessZipEntryContents(pArchive, pEntry, - bufferProcessFunction, (void*)&bec); - if (!ret || bec.len != 0) { - LOGE("Can't extract entry to memory buffer.\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, - const struct utimbuf *timestamp, - void (*callback)(const char *fn, void *), void *cookie, - struct selabel_handle *sehnd) -{ - 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; - int extractCount = 0; - 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; - } - -#define UNZIP_DIRMODE 0755 -#define UNZIP_FILEMODE 0644 - /* - * Create the file or directory. We ignore directory entries - * because we recursively create paths to each file entry we encounter - * in the zip archive anyway. - * - * NOTE: A "directory entry" in a zip archive is just a zero length - * entry that ends in a "/". They're not mandatory and many tools get - * rid of them. We need to process them only if we want to preserve - * empty directories from the archive. - */ - if (pEntry->fileName[pEntry->fileNameLen-1] != '/') { - /* This is not a directory. First, make sure that - * the containing directory exists. - */ - int ret = dirCreateHierarchy( - targetFile, UNZIP_DIRMODE, timestamp, true, sehnd); - if (ret != 0) { - LOGE("Can't create containing directory for \"%s\": %s\n", - targetFile, strerror(errno)); - ok = false; - break; - } - - /* - * The entry is a regular file or a symlink. Open the target for writing. - * - * TODO: This behavior for symlinks seems rather bizarre. For a - * symlink foo/bar/baz -> foo/tar/taz, we will create a file called - * "foo/bar/baz" whose contents are the literal "foo/tar/taz". We - * warn about this for now and preserve older behavior. - */ - if (mzIsZipEntrySymlink(pEntry)) { - LOGE("Symlink entry \"%.*s\" will be output as a regular file.", - pEntry->fileNameLen, pEntry->fileName); - } - - char *secontext = NULL; - - if (sehnd) { - selabel_lookup(sehnd, &secontext, targetFile, UNZIP_FILEMODE); - setfscreatecon(secontext); - } - - int fd = open(targetFile, O_CREAT|O_WRONLY|O_TRUNC|O_SYNC, - UNZIP_FILEMODE); - - if (secontext) { - freecon(secontext); - setfscreatecon(NULL); - } - - if (fd < 0) { - LOGE("Can't create target file \"%s\": %s\n", - targetFile, strerror(errno)); - ok = false; - break; - } - - bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd); - if (ok) { - ok = (fsync(fd) == 0); - } - if (close(fd) != 0) { - ok = false; - } - 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; - } - - LOGV("Extracted file \"%s\"\n", targetFile); - ++extractCount; - } - - if (callback != NULL) callback(targetFile, cookie); - } - - LOGV("Extracted %d file(s)\n", extractCount); - - free(helper.buf); - free(zpath); - - return ok; -} diff --git a/minzip/Zip.h b/minzip/Zip.h deleted file mode 100644 index 86d8db597..000000000 --- a/minzip/Zip.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Simple Zip archive support. - */ -#ifndef _MINZIP_ZIP -#define _MINZIP_ZIP - -#include "inline_magic.h" - -#include <stdlib.h> -#include <utime.h> - -#include "Hash.h" -#include "SysUtil.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <selinux/selinux.h> -#include <selinux/label.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 { - unsigned int numEntries; - ZipEntry* pEntries; - HashTable* pHash; // maps file name to ZipEntry - unsigned char* addr; - size_t length; -} 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(unsigned char* addr, size_t length, 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); - -INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) { - return pEntry->offset; -} -INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) { - return pEntry->uncompLen; -} - -/* - * 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); - -/* - * Inflate and write an entry to a file. - */ -bool mzExtractZipEntryToFile(const ZipArchive *pArchive, - const ZipEntry *pEntry, int fd); - -/* - * Inflate and write an entry to a memory buffer, which must be long - * enough to hold mzGetZipEntryUncomplen(pEntry) bytes. - */ -bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive, - const ZipEntry *pEntry, unsigned char* buffer); - -/* - * Inflate all files under zipDir to the directory specified by - * targetDir, which must exist and be a writable directory. - * - * Directory entries and symlinks are not extracted. - * - * - * 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 - * - * 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. - */ -bool mzExtractRecursive(const ZipArchive *pArchive, - const char *zipDir, const char *targetDir, - const struct utimbuf *timestamp, - void (*callback)(const char *fn, void*), void *cookie, - struct selabel_handle *sehnd); - -#ifdef __cplusplus -} -#endif - -#endif /*_MINZIP_ZIP*/ diff --git a/mounts.cpp b/mounts.cpp new file mode 100644 index 000000000..f23376b06 --- /dev/null +++ b/mounts.cpp @@ -0,0 +1,89 @@ +/* + * 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 "mounts.h" + +#include <errno.h> +#include <fcntl.h> +#include <mntent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mount.h> + +#include <string> +#include <vector> + +struct MountedVolume { + std::string device; + std::string mount_point; + std::string filesystem; + std::string flags; +}; + +std::vector<MountedVolume*> g_mounts_state; + +bool scan_mounted_volumes() { + for (size_t i = 0; i < g_mounts_state.size(); ++i) { + delete g_mounts_state[i]; + } + g_mounts_state.clear(); + + // Open and read mount table entries. + FILE* fp = setmntent("/proc/mounts", "re"); + if (fp == NULL) { + return false; + } + mntent* e; + while ((e = getmntent(fp)) != NULL) { + MountedVolume* v = new MountedVolume; + v->device = e->mnt_fsname; + v->mount_point = e->mnt_dir; + v->filesystem = e->mnt_type; + v->flags = e->mnt_opts; + g_mounts_state.push_back(v); + } + endmntent(fp); + return true; +} + +MountedVolume* find_mounted_volume_by_device(const char* device) { + for (size_t i = 0; i < g_mounts_state.size(); ++i) { + if (g_mounts_state[i]->device == device) return g_mounts_state[i]; + } + return nullptr; +} + +MountedVolume* find_mounted_volume_by_mount_point(const char* mount_point) { + for (size_t i = 0; i < g_mounts_state.size(); ++i) { + if (g_mounts_state[i]->mount_point == mount_point) return g_mounts_state[i]; + } + return nullptr; +} + +int unmount_mounted_volume(MountedVolume* volume) { + // Intentionally pass the empty string to umount if the caller tries + // to unmount a volume they already unmounted using this + // function. + std::string mount_point = volume->mount_point; + volume->mount_point.clear(); + return umount(mount_point.c_str()); +} + +int remount_read_only(MountedVolume* volume) { + return mount(volume->device.c_str(), volume->mount_point.c_str(), volume->filesystem.c_str(), + MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY | MS_REMOUNT, 0); +} diff --git a/minzip/Inlines.c b/mounts.h index 91f87751d..1b7670329 100644 --- a/minzip/Inlines.c +++ b/mounts.h @@ -14,12 +14,19 @@ * 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" +#ifndef MOUNTS_H_ +#define MOUNTS_H_ + +struct MountedVolume; + +bool scan_mounted_volumes(); + +MountedVolume* find_mounted_volume_by_device(const char* device); + +MountedVolume* find_mounted_volume_by_mount_point(const char* mount_point); + +int unmount_mounted_volume(MountedVolume* volume); + +int remount_read_only(MountedVolume* volume); + +#endif diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk deleted file mode 100644 index b7d35c27a..000000000 --- a/mtdutils/Android.mk +++ /dev/null @@ -1,20 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - mtdutils.c \ - mounts.c - -LOCAL_MODULE := libmtdutils -LOCAL_CLANG := true - -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_CLANG := true -LOCAL_SRC_FILES := flash_image.c -LOCAL_MODULE := flash_image -LOCAL_MODULE_TAGS := eng -LOCAL_STATIC_LIBRARIES := libmtdutils -LOCAL_SHARED_LIBRARIES := libcutils liblog libc -include $(BUILD_EXECUTABLE) diff --git a/mtdutils/flash_image.c b/mtdutils/flash_image.c deleted file mode 100644 index 36ffa1314..000000000 --- a/mtdutils/flash_image.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "cutils/log.h" -#include "mtdutils.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#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); - ALOGE("%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 = TEMP_FAILURE_RETRY(read(fd, header, sizeof(header))); - if (headerlen <= 0) die("error reading %s header", argv[2]); - - MtdReadContext *in = mtd_read_partition(partition); - if (in == NULL) { - ALOGW("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) { - ALOGW("error reading %s: %s\n", argv[1], strerror(errno)); - // just assume it needs re-writing - } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { - ALOGI("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 - ALOGI("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 = TEMP_FAILURE_RETRY(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 (TEMP_FAILURE_RETRY(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 = TEMP_FAILURE_RETRY(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 6a9b03d30..000000000 --- a/mtdutils/mounts.c +++ /dev/null @@ -1,161 +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 <mntent.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mount.h> - -#include "mounts.h" - -struct MountedVolume { - const char *device; - const char *mount_point; - const char *filesystem; - const char *flags; -}; - -typedef struct { - MountedVolume *volumes; - int volumes_allocd; - int volume_count; -} MountsState; - -static MountsState g_mounts_state = { - NULL, // volumes - 0, // volumes_allocd - 0 // volume_count -}; - -static inline void -free_volume_internals(const MountedVolume *volume, int zero) -{ - free((char *)volume->device); - free((char *)volume->mount_point); - free((char *)volume->filesystem); - free((char *)volume->flags); - if (zero) { - memset((void *)volume, 0, sizeof(*volume)); - } -} - -#define PROC_MOUNTS_FILENAME "/proc/mounts" - -int -scan_mounted_volumes() -{ - FILE* fp; - struct mntent* mentry; - - 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 mount table entries. */ - fp = setmntent(PROC_MOUNTS_FILENAME, "r"); - if (fp == NULL) { - return -1; - } - while ((mentry = getmntent(fp)) != NULL) { - MountedVolume* v = &g_mounts_state.volumes[g_mounts_state.volume_count++]; - v->device = strdup(mentry->mnt_fsname); - v->mount_point = strdup(mentry->mnt_dir); - v->filesystem = strdup(mentry->mnt_type); - v->flags = strdup(mentry->mnt_opts); - } - endmntent(fp); - return 0; -} - -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; -} - -int -remount_read_only(const MountedVolume* volume) -{ - return mount(volume->device, volume->mount_point, volume->filesystem, - MS_NOATIME | MS_NODEV | MS_NODIRATIME | - MS_RDONLY | MS_REMOUNT, 0); -} diff --git a/mtdutils/mounts.h b/mtdutils/mounts.h deleted file mode 100644 index d721355b8..000000000 --- a/mtdutils/mounts.h +++ /dev/null @@ -1,41 +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_ - -#ifdef __cplusplus -extern "C" { -#endif - -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); - -int remount_read_only(const MountedVolume* volume); - -#ifdef __cplusplus -} -#endif - -#endif // MTDUTILS_MOUNTS_H_ diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c deleted file mode 100644 index cd4f52cd5..000000000 --- a/mtdutils/mtdutils.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mount.h> // for _IOW, _IOR, mount() -#include <sys/stat.h> -#include <mtd/mtd-user.h> -#undef NDEBUG -#include <assert.h> - -#include "mtdutils.h" - -struct MtdPartition { - int device_index; - unsigned int size; - unsigned int erase_size; - char *name; -}; - -struct MtdReadContext { - const MtdPartition *partition; - char *buffer; - size_t consumed; - int fd; -}; - -struct MtdWriteContext { - const MtdPartition *partition; - char *buffer; - size_t stored; - int fd; - - off_t* bad_block_offsets; - int bad_block_alloc; - int bad_block_count; -}; - -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 = TEMP_FAILURE_RETRY(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->buffer); - free(ctx); - 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)) { - printf("mtd: ECCGETSTATS error (%s)\n", strerror(errno)); - return -1; - } - - loff_t pos = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); - if (pos == -1) { - printf("mtd: read_block: couldn't SEEK_CUR: %s\n", strerror(errno)); - return -1; - } - - ssize_t size = partition->erase_size; - int mgbb; - - while (pos + size <= (int) partition->size) { - if (TEMP_FAILURE_RETRY(lseek64(fd, pos, SEEK_SET)) != pos || - TEMP_FAILURE_RETRY(read(fd, data, size)) != size) { - printf("mtd: read error at 0x%08llx (%s)\n", - (long long)pos, strerror(errno)); - } else if (ioctl(fd, ECCGETSTATS, &after)) { - printf("mtd: ECCGETSTATS error (%s)\n", strerror(errno)); - return -1; - } else if (after.failed != before.failed) { - printf("mtd: ECC errors (%d soft, %d hard) at 0x%08llx\n", - after.corrected - before.corrected, - after.failed - before.failed, (long long)pos); - // copy the comparison baseline for the next read. - memcpy(&before, &after, sizeof(struct mtd_ecc_stats)); - } else if ((mgbb = ioctl(fd, MEMGETBADBLOCK, &pos))) { - fprintf(stderr, - "mtd: MEMGETBADBLOCK returned %d at 0x%08llx: %s\n", - mgbb, (long long)pos, strerror(errno)); - } else { - return 0; // Success! - } - - pos += partition->erase_size; - } - - errno = ENOSPC; - return -1; -} - -ssize_t mtd_read_data(MtdReadContext *ctx, char *data, size_t len) -{ - size_t read = 0; - while (read < 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; - } - - if (read >= len) { - return read; - } - - // Read the next block into the buffer - if (ctx->consumed == ctx->partition->erase_size && read < 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->bad_block_offsets = NULL; - ctx->bad_block_alloc = 0; - ctx->bad_block_count = 0; - - 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 void add_bad_block_offset(MtdWriteContext *ctx, off_t pos) { - if (ctx->bad_block_count + 1 > ctx->bad_block_alloc) { - ctx->bad_block_alloc = (ctx->bad_block_alloc*2) + 1; - ctx->bad_block_offsets = realloc(ctx->bad_block_offsets, - ctx->bad_block_alloc * sizeof(off_t)); - } - ctx->bad_block_offsets[ctx->bad_block_count++] = pos; -} - -static int write_block(MtdWriteContext *ctx, const char *data) -{ - const MtdPartition *partition = ctx->partition; - int fd = ctx->fd; - - off_t pos = TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_CUR)); - if (pos == (off_t) -1) { - printf("mtd: write_block: couldn't SEEK_CUR: %s\n", strerror(errno)); - return -1; - } - - ssize_t size = partition->erase_size; - while (pos + size <= (int) partition->size) { - loff_t bpos = pos; - int ret = ioctl(fd, MEMGETBADBLOCK, &bpos); - if (ret != 0 && !(ret == -1 && errno == EOPNOTSUPP)) { - add_bad_block_offset(ctx, pos); - fprintf(stderr, - "mtd: not writing bad block at 0x%08lx (ret %d): %s\n", - pos, ret, strerror(errno)); - 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) { - printf("mtd: erase failure at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - if (TEMP_FAILURE_RETRY(lseek(fd, pos, SEEK_SET)) != pos || - TEMP_FAILURE_RETRY(write(fd, data, size)) != size) { - printf("mtd: write error at 0x%08lx (%s)\n", - pos, strerror(errno)); - } - - char verify[size]; - if (TEMP_FAILURE_RETRY(lseek(fd, pos, SEEK_SET)) != pos || - TEMP_FAILURE_RETRY(read(fd, verify, size)) != size) { - printf("mtd: re-read error at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - if (memcmp(data, verify, size) != 0) { - printf("mtd: verification error at 0x%08lx (%s)\n", - pos, strerror(errno)); - continue; - } - - if (retry > 0) { - printf("mtd: wrote block after %d retries\n", retry); - } - printf("mtd: successfully wrote block at %lx\n", pos); - return 0; // Success! - } - - // Try to erase it once more as we give up on this block - add_bad_block_offset(ctx, pos); - printf("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, 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, 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, ctx->buffer)) return -1; - ctx->stored = 0; - } - - off_t pos = TEMP_FAILURE_RETRY(lseek(ctx->fd, 0, SEEK_CUR)); - if ((off_t) pos == (off_t) -1) { - printf("mtd_erase_blocks: couldn't SEEK_CUR: %s\n", strerror(errno)); - return -1; - } - - 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) { - printf("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) { - printf("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->bad_block_offsets); - free(ctx->buffer); - free(ctx); - return r; -} diff --git a/mtdutils/mtdutils.h b/mtdutils/mtdutils.h deleted file mode 100644 index 8059d6a4d..000000000 --- a/mtdutils/mtdutils.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MTDUTILS_H_ -#define MTDUTILS_H_ - -#include <sys/types.h> // for size_t, etc. - -#ifdef __cplusplus -extern "C" { -#endif - -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 *); - -#ifdef __cplusplus -} -#endif - -#endif // MTDUTILS_H_ diff --git a/otafault/Android.mk b/otafault/Android.mk index ba7add855..71c2c62f6 100644 --- a/otafault/Android.mk +++ b/otafault/Android.mk @@ -17,11 +17,13 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) otafault_static_libs := \ - libbase \ - libminzip \ + libziparchive \ libz \ - libselinux + libselinux \ + libbase \ + liblog +LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := config.cpp ota_io.cpp LOCAL_MODULE_TAGS := eng LOCAL_MODULE := libotafault @@ -32,12 +34,15 @@ LOCAL_WHOLE_STATIC_LIBRARIES := $(otafault_static_libs) include $(BUILD_STATIC_LIBRARY) +# otafault_test (static executable) +# =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := config.cpp ota_io.cpp test.cpp LOCAL_MODULE_TAGS := tests LOCAL_MODULE := otafault_test LOCAL_STATIC_LIBRARIES := $(otafault_static_libs) +LOCAL_CFLAGS := -Werror LOCAL_C_INCLUDES := bootable/recovery LOCAL_FORCE_STATIC_EXECUTABLE := true diff --git a/otafault/config.cpp b/otafault/config.cpp index b4567392d..ee4ef8911 100644 --- a/otafault/config.cpp +++ b/otafault/config.cpp @@ -21,21 +21,21 @@ #include <unistd.h> #include <android-base/stringprintf.h> +#include <ziparchive/zip_archive.h> -#include "minzip/Zip.h" #include "config.h" #include "ota_io.h" #define OTAIO_MAX_FNAME_SIZE 128 -static ZipArchive* archive; +static ZipArchiveHandle archive; static std::map<std::string, bool> should_inject_cache; static std::string get_type_path(const char* io_type) { return android::base::StringPrintf("%s/%s", OTAIO_BASE_DIR, io_type); } -void ota_io_init(ZipArchive* za) { +void ota_io_init(ZipArchiveHandle za) { archive = za; ota_set_fault_files(); } @@ -50,9 +50,11 @@ bool should_fault_inject(const char* io_type) { if (should_inject_cache.find(type_path) != should_inject_cache.end()) { return should_inject_cache[type_path]; } - const ZipEntry* entry = mzFindZipEntry(archive, type_path.c_str()); - should_inject_cache[type_path] = entry != nullptr; - return entry != NULL; + ZipString zip_type_path(type_path.c_str()); + ZipEntry entry; + int status = FindEntry(archive, zip_type_path, &entry); + should_inject_cache[type_path] = (status == 0); + return (status == 0); } bool should_hit_cache() { @@ -63,7 +65,9 @@ std::string fault_fname(const char* io_type) { std::string type_path = get_type_path(io_type); std::string fname; fname.resize(OTAIO_MAX_FNAME_SIZE); - const ZipEntry* entry = mzFindZipEntry(archive, type_path.c_str()); - mzReadZipEntry(archive, entry, &fname[0], OTAIO_MAX_FNAME_SIZE); + ZipString zip_type_path(type_path.c_str()); + ZipEntry entry; + int status = FindEntry(archive, zip_type_path, &entry); + ExtractToMemory(archive, &entry, reinterpret_cast<uint8_t*>(&fname[0]), OTAIO_MAX_FNAME_SIZE); return fname; } diff --git a/otafault/config.h b/otafault/config.h index 4430be3fb..c048617c2 100644 --- a/otafault/config.h +++ b/otafault/config.h @@ -41,7 +41,7 @@ #include <stdbool.h> -#include "minzip/Zip.h" +#include <ziparchive/zip_archive.h> #define OTAIO_BASE_DIR ".libotafault" #define OTAIO_READ "READ" @@ -52,7 +52,7 @@ /* * Initialize libotafault by providing a reference to the OTA package. */ -void ota_io_init(ZipArchive* za); +void ota_io_init(ZipArchiveHandle zip); /* * Return true if a config file is present for the given IO type. diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp index 04458537b..2efd3004a 100644 --- a/otafault/ota_io.cpp +++ b/otafault/ota_io.cpp @@ -30,7 +30,7 @@ static std::string read_fault_file_name = ""; static std::string write_fault_file_name = ""; static std::string fsync_fault_file_name = ""; -static bool get_hit_file(const char* cached_path, std::string ffn) { +static bool get_hit_file(const char* cached_path, const std::string& ffn) { return should_hit_cache() ? !strncmp(cached_path, OTAIO_CACHE_FNAME, strlen(cached_path)) : !strncmp(cached_path, ffn.c_str(), strlen(cached_path)); @@ -92,6 +92,7 @@ size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) { } } size_t status = fread(ptr, size, nitems, stream); + // If I/O error occurs, set the retry-update flag. if (status != nitems && errno == EIO) { have_eio_error = true; } diff --git a/otautil/Android.mk b/otautil/Android.mk new file mode 100644 index 000000000..3acfa533e --- /dev/null +++ b/otautil/Android.mk @@ -0,0 +1,35 @@ +# Copyright (C) 2016 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_SRC_FILES := \ + SysUtil.cpp \ + DirUtil.cpp \ + ZipUtil.cpp + +LOCAL_C_INCLUDES := \ + external/zlib \ + external/safe-iop/include + +LOCAL_STATIC_LIBRARIES := libselinux libbase + +LOCAL_MODULE := libotautil + +LOCAL_CLANG := true + +LOCAL_CFLAGS += -Werror -Wall + +include $(BUILD_STATIC_LIBRARY) diff --git a/minzip/DirUtil.c b/otautil/DirUtil.cpp index 97cb2e0ee..e08e360c0 100644 --- a/minzip/DirUtil.c +++ b/otautil/DirUtil.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "DirUtil.h" + #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -24,7 +26,10 @@ #include <dirent.h> #include <limits.h> -#include "DirUtil.h" +#include <string> + +#include <selinux/label.h> +#include <selinux/selinux.h> typedef enum { DMISSING, DDIR, DILLEGAL } DirStatus; @@ -66,43 +71,25 @@ dirCreateHierarchy(const char *path, int mode, 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); + // Allocate a path that we can modify; stick a slash on + // the end to make things easier. + std::string cpath = path; 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. - */ + // Strip everything after the last slash. + size_t pos = cpath.rfind('/'); + if (pos == std::string::npos) { errno = ENOENT; - free(cpath); return -1; } - c[1] = '\0'; // Terminate after the slash we found. + cpath.resize(pos + 1); } else { - /* Make sure that the path ends in a slash. - */ - cpath[pathLen] = '/'; - cpath[pathLen + 1] = '\0'; + // Make sure that the path ends in a slash. + cpath.push_back('/'); } /* See if it already exists. */ - ds = getPathDirStatus(cpath); + ds = getPathDirStatus(cpath.c_str()); if (ds == DDIR) { return 0; } else if (ds == DILLEGAL) { @@ -112,7 +99,8 @@ dirCreateHierarchy(const char *path, int mode, /* Walk up the path from the root and make each level. * If a directory already exists, no big deal. */ - char *p = cpath; + const char *path_start = &cpath[0]; + char *p = &cpath[0]; while (*p != '\0') { /* Skip any slashes, watching out for the end of the string. */ @@ -135,12 +123,11 @@ dirCreateHierarchy(const char *path, int mode, /* Check this part of the path and make a new directory * if necessary. */ - ds = getPathDirStatus(cpath); + ds = getPathDirStatus(path_start); 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; @@ -148,11 +135,11 @@ dirCreateHierarchy(const char *path, int mode, char *secontext = NULL; if (sehnd) { - selabel_lookup(sehnd, &secontext, cpath, mode); + selabel_lookup(sehnd, &secontext, path_start, mode); setfscreatecon(secontext); } - err = mkdir(cpath, mode); + err = mkdir(path_start, mode); if (secontext) { freecon(secontext); @@ -160,22 +147,17 @@ dirCreateHierarchy(const char *path, int mode, } if (err != 0) { - free(cpath); return -1; } - if (timestamp != NULL && utime(cpath, timestamp)) { - free(cpath); + if (timestamp != NULL && utime(path_start, timestamp)) { return -1; } } // else, this directory already exists. - - /* Repair the path and continue. - */ + + // Repair the path and continue. *p = '/'; } - free(cpath); - return 0; } diff --git a/minzip/DirUtil.h b/otautil/DirUtil.h index 85a00128b..85b83c387 100644 --- a/minzip/DirUtil.h +++ b/otautil/DirUtil.h @@ -24,8 +24,7 @@ extern "C" { #endif -#include <selinux/selinux.h> -#include <selinux/label.h> +struct selabel_handle; /* Like "mkdir -p", try to guarantee that all directories * specified in path are present, creating as many directories diff --git a/minzip/SysUtil.c b/otautil/SysUtil.cpp index e7dd17b51..4cdd60d9f 100644 --- a/minzip/SysUtil.c +++ b/otautil/SysUtil.cpp @@ -16,8 +16,8 @@ #include <sys/types.h> #include <unistd.h> -#define LOG_TAG "sysutil" -#include "Log.h" +#include <android-base/logging.h> + #include "SysUtil.h" static bool sysMapFD(int fd, MemMapping* pMap) { @@ -25,22 +25,22 @@ static bool sysMapFD(int fd, MemMapping* pMap) { struct stat sb; if (fstat(fd, &sb) == -1) { - LOGE("fstat(%d) failed: %s\n", fd, strerror(errno)); + PLOG(ERROR) << "fstat(" << fd << ") failed"; return false; } void* memPtr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (memPtr == MAP_FAILED) { - LOGE("mmap(%d, R, PRIVATE, %d, 0) failed: %s\n", (int) sb.st_size, fd, strerror(errno)); + PLOG(ERROR) << "mmap(" << sb.st_size << ", R, PRIVATE, " << fd << ", 0) failed"; return false; } - pMap->addr = memPtr; + pMap->addr = reinterpret_cast<unsigned char*>(memPtr); pMap->length = sb.st_size; pMap->range_count = 1; - pMap->ranges = malloc(sizeof(MappedRange)); + pMap->ranges = reinterpret_cast<MappedRange*>(malloc(sizeof(MappedRange))); if (pMap->ranges == NULL) { - LOGE("malloc failed: %s\n", strerror(errno)); + PLOG(ERROR) << "malloc failed"; munmap(memPtr, sb.st_size); return false; } @@ -60,7 +60,7 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) unsigned int i; if (fgets(block_dev, sizeof(block_dev), mapf) == NULL) { - LOGE("failed to read block device from header\n"); + PLOG(ERROR) << "failed to read block device from header"; return -1; } for (i = 0; i < sizeof(block_dev); ++i) { @@ -71,37 +71,37 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) } if (fscanf(mapf, "%zu %u\n%u\n", &size, &blksize, &range_count) != 3) { - LOGE("failed to parse block map header\n"); + LOG(ERROR) << "failed to parse block map header"; return -1; } if (blksize != 0) { blocks = ((size-1) / blksize) + 1; } if (size == 0 || blksize == 0 || blocks > SIZE_MAX / blksize || range_count == 0) { - LOGE("invalid data in block map file: size %zu, blksize %u, range_count %u\n", - size, blksize, range_count); + LOG(ERROR) << "invalid data in block map file: size " << size << ", blksize " << blksize + << ", range_count " << range_count; return -1; } pMap->range_count = range_count; - pMap->ranges = calloc(range_count, sizeof(MappedRange)); + pMap->ranges = reinterpret_cast<MappedRange*>(calloc(range_count, sizeof(MappedRange))); if (pMap->ranges == NULL) { - LOGE("calloc(%u, %zu) failed: %s\n", range_count, sizeof(MappedRange), strerror(errno)); + PLOG(ERROR) << "calloc(" << range_count << ", " << sizeof(MappedRange) << ") failed"; return -1; } // Reserve enough contiguous address space for the whole file. - unsigned char* reserve; - reserve = mmap64(NULL, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); + unsigned char* reserve = reinterpret_cast<unsigned char*>(mmap64(NULL, blocks * blksize, + PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0)); if (reserve == MAP_FAILED) { - LOGE("failed to reserve address space: %s\n", strerror(errno)); + PLOG(ERROR) << "failed to reserve address space"; free(pMap->ranges); return -1; } int fd = open(block_dev, O_RDONLY); if (fd < 0) { - LOGE("failed to open block device %s: %s\n", block_dev, strerror(errno)); + PLOG(ERROR) << "failed to open block device " << block_dev; munmap(reserve, blocks * blksize); free(pMap->ranges); return -1; @@ -113,20 +113,20 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) for (i = 0; i < range_count; ++i) { size_t start, end; if (fscanf(mapf, "%zu %zu\n", &start, &end) != 2) { - LOGE("failed to parse range %d in block map\n", i); + LOG(ERROR) << "failed to parse range " << i << " in block map"; success = false; break; } size_t length = (end - start) * blksize; - if (end <= start || (end - start) > SIZE_MAX / blksize || length > remaining_size) { - LOGE("unexpected range in block map: %zu %zu\n", start, end); - success = false; - break; + if (end <= start || ((end - start) > SIZE_MAX / blksize) || length > remaining_size) { + LOG(ERROR) << "unexpected range in block map: " << start << " " << end; + success = false; + break; } void* addr = mmap64(next, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize); if (addr == MAP_FAILED) { - LOGE("failed to map block %d: %s\n", i, strerror(errno)); + PLOG(ERROR) << "failed to map block " << i; success = false; break; } @@ -137,8 +137,8 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) remaining_size -= length; } if (success && remaining_size != 0) { - LOGE("ranges in block map are invalid: remaining_size = %zu\n", remaining_size); - success = false; + LOG(ERROR) << "ranges in block map are invalid: remaining_size = " << remaining_size; + success = false; } if (!success) { close(fd); @@ -151,7 +151,7 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) pMap->addr = reserve; pMap->length = size; - LOGI("mmapped %d ranges\n", range_count); + LOG(INFO) << "mmapped " << range_count << " ranges"; return 0; } @@ -164,12 +164,12 @@ int sysMapFile(const char* fn, MemMapping* pMap) // A map of blocks FILE* mapf = fopen(fn+1, "r"); if (mapf == NULL) { - LOGE("Unable to open '%s': %s\n", fn+1, strerror(errno)); + PLOG(ERROR) << "Unable to open '" << (fn+1) << "'"; return -1; } if (sysMapBlockFile(mapf, pMap) != 0) { - LOGE("Map of '%s' failed\n", fn); + LOG(ERROR) << "Map of '" << fn << "' failed"; fclose(mapf); return -1; } @@ -179,12 +179,12 @@ int sysMapFile(const char* fn, MemMapping* pMap) // This is a regular file. int fd = open(fn, O_RDONLY); if (fd == -1) { - LOGE("Unable to open '%s': %s\n", fn, strerror(errno)); + PLOG(ERROR) << "Unable to open '" << fn << "'"; return -1; } if (!sysMapFD(fd, pMap)) { - LOGE("Map of '%s' failed\n", fn); + LOG(ERROR) << "Map of '" << fn << "' failed"; close(fd); return -1; } @@ -202,8 +202,8 @@ void sysReleaseMap(MemMapping* pMap) int i; for (i = 0; i < pMap->range_count; ++i) { if (munmap(pMap->ranges[i].addr, pMap->ranges[i].length) < 0) { - LOGE("munmap(%p, %d) failed: %s\n", - pMap->ranges[i].addr, (int)pMap->ranges[i].length, strerror(errno)); + PLOG(ERROR) << "munmap(" << pMap->ranges[i].addr << ", " << pMap->ranges[i].length + << ") failed"; } } free(pMap->ranges); diff --git a/minzip/SysUtil.h b/otautil/SysUtil.h index 7adff1e54..7adff1e54 100644 --- a/minzip/SysUtil.h +++ b/otautil/SysUtil.h diff --git a/otautil/ZipUtil.cpp b/otautil/ZipUtil.cpp new file mode 100644 index 000000000..714c956ed --- /dev/null +++ b/otautil/ZipUtil.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2016 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 "ZipUtil.h" + +#include <errno.h> +#include <fcntl.h> +#include <utime.h> + +#include <string> + +#include <android-base/logging.h> +#include <android-base/unique_fd.h> +#include <selinux/label.h> +#include <selinux/selinux.h> +#include <ziparchive/zip_archive.h> + +#include "DirUtil.h" + +static constexpr mode_t UNZIP_DIRMODE = 0755; +static constexpr mode_t UNZIP_FILEMODE = 0644; + +bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path, + const std::string& dest_path, const struct utimbuf* timestamp, + struct selabel_handle* sehnd) { + if (!zip_path.empty() && zip_path[0] == '/') { + LOG(ERROR) << "ExtractPackageRecursive(): zip_path must be a relative path " << zip_path; + return false; + } + if (dest_path.empty() || dest_path[0] != '/') { + LOG(ERROR) << "ExtractPackageRecursive(): dest_path must be an absolute path " << dest_path; + return false; + } + + void* cookie; + std::string target_dir(dest_path); + if (dest_path.back() != '/') { + target_dir += '/'; + } + std::string prefix_path(zip_path); + if (!zip_path.empty() && zip_path.back() != '/') { + prefix_path += '/'; + } + const ZipString zip_prefix(prefix_path.c_str()); + + int ret = StartIteration(zip, &cookie, &zip_prefix, nullptr); + if (ret != 0) { + LOG(ERROR) << "failed to start iterating zip entries."; + return false; + } + + std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration); + ZipEntry entry; + ZipString name; + int extractCount = 0; + while (Next(cookie, &entry, &name) == 0) { + std::string entry_name(name.name, name.name + name.name_length); + CHECK_LE(prefix_path.size(), entry_name.size()); + std::string path = target_dir + entry_name.substr(prefix_path.size()); + // Skip dir. + if (path.back() == '/') { + continue; + } + //TODO(b/31917448) handle the symlink. + + if (dirCreateHierarchy(path.c_str(), UNZIP_DIRMODE, timestamp, true, sehnd) != 0) { + LOG(ERROR) << "failed to create dir for " << path; + return false; + } + + char *secontext = NULL; + if (sehnd) { + selabel_lookup(sehnd, &secontext, path.c_str(), UNZIP_FILEMODE); + setfscreatecon(secontext); + } + android::base::unique_fd fd(open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, UNZIP_FILEMODE)); + if (fd == -1) { + PLOG(ERROR) << "Can't create target file \"" << path << "\""; + return false; + } + if (secontext) { + freecon(secontext); + setfscreatecon(NULL); + } + + int err = ExtractEntryToFile(zip, &entry, fd); + if (err != 0) { + LOG(ERROR) << "Error extracting \"" << path << "\" : " << ErrorCodeString(err); + return false; + } + + if (fsync(fd) != 0) { + PLOG(ERROR) << "Error syncing file descriptor when extracting \"" << path << "\""; + return false; + } + + if (timestamp != nullptr && utime(path.c_str(), timestamp)) { + PLOG(ERROR) << "Error touching \"" << path << "\""; + return false; + } + + LOG(INFO) << "Extracted file \"" << path << "\""; + ++extractCount; + } + + LOG(INFO) << "Extracted " << extractCount << " file(s)"; + return true; +} diff --git a/otautil/ZipUtil.h b/otautil/ZipUtil.h new file mode 100644 index 000000000..cda405c2a --- /dev/null +++ b/otautil/ZipUtil.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 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 _OTAUTIL_ZIPUTIL_H +#define _OTAUTIL_ZIPUTIL_H + +#include <utime.h> + +#include <string> + +#include <selinux/label.h> +#include <ziparchive/zip_archive.h> + +/* + * Inflate all files under zip_path to the directory specified by + * dest_path, which must exist and be a writable directory. The zip_path + * is allowed to be an empty string, in which case the whole package + * will be extracted. + * + * Directory entries are not extracted. + * + * The immediate children of zip_path will become the immediate + * children of dest_path; e.g., if the archive contains the entries + * + * a/b/c/one + * a/b/c/two + * a/b/c/d/three + * + * and ExtractPackageRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting + * files will be + * + * /tmp/one + * /tmp/two + * /tmp/d/three + * + * If timestamp is non-NULL, file timestamps will be set accordingly. + * + * Returns true on success, false on failure. + */ +bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path, + const std::string& dest_path, const struct utimbuf* timestamp, + struct selabel_handle* sehnd); + +#endif // _OTAUTIL_ZIPUTIL_H diff --git a/recovery-persist.cpp b/recovery-persist.cpp index 25df03f47..b0ec141cb 100644 --- a/recovery-persist.cpp +++ b/recovery-persist.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "recovery-persist" - // // Strictly to deal with reboot into system after OTA after /data // mounts to pull the last pmsg file data and place it @@ -40,10 +38,9 @@ #include <string> -#include <android/log.h> /* Android Log Priority Tags */ #include <android-base/file.h> -#include <log/log.h> -#include <log/logger.h> /* Android Log packet format */ +#include <android-base/logging.h> + #include <private/android_logger.h> /* private pmsg functions */ static const char *LAST_LOG_FILE = "/data/misc/recovery/last_log"; @@ -57,14 +54,16 @@ static const int KEEP_LOG_COUNT = 10; // 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)) SLOGE("%s %s", name, strerror(errno)); + if (ferror(fp)) { + PLOG(ERROR) << "Error in " << name; + } fclose(fp); } static void copy_file(const char* source, const char* destination) { FILE* dest_fp = fopen(destination, "w"); if (dest_fp == nullptr) { - SLOGE("%s %s", destination, strerror(errno)); + PLOG(ERROR) << "Can't open " << destination; } else { FILE* source_fp = fopen(source, "r"); if (source_fp != nullptr) { @@ -157,7 +156,7 @@ int main(int argc, char **argv) { static const char mounts_file[] = "/proc/mounts"; FILE *fp = fopen(mounts_file, "r"); if (!fp) { - SLOGV("%s %s", mounts_file, strerror(errno)); + PLOG(ERROR) << "failed to open " << mounts_file; } else { char *line = NULL; size_t len = 0; diff --git a/recovery-refresh.cpp b/recovery-refresh.cpp index 70adc70ee..b2ab52f7e 100644 --- a/recovery-refresh.cpp +++ b/recovery-refresh.cpp @@ -44,7 +44,6 @@ #include <string> #include <android/log.h> /* Android Log Priority Tags */ -#include <log/logger.h> /* Android Log packet format */ #include <private/android_logger.h> /* private pmsg functions */ static const char LAST_KMSG_FILE[] = "recovery/last_kmsg"; @@ -76,7 +75,7 @@ static ssize_t logrotate( } std::string name(filename); - size_t dot = name.find_last_of("."); + size_t dot = name.find_last_of('.'); std::string sub = name.substr(0, dot); if (!strstr(LAST_KMSG_FILE, sub.c_str()) && @@ -92,7 +91,7 @@ static ssize_t logrotate( if (!isdigit(number.data()[0])) { name += ".1"; } else { - unsigned long long i = std::stoull(number); + auto i = std::stoull(number); name = sub + "." + std::to_string(i + 1); } } diff --git a/recovery.cpp b/recovery.cpp index 0f0b978e7..4d1ad1df2 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -39,18 +39,21 @@ #include <vector> #include <adb.h> -#include <android/log.h> /* Android Log Priority Tags */ #include <android-base/file.h> +#include <android-base/logging.h> #include <android-base/parseint.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> #include <bootloader_message/bootloader_message.h> #include <cutils/android_reboot.h> -#include <cutils/properties.h> -#include <log/logger.h> /* Android Log packet format */ -#include <private/android_logger.h> /* private pmsg functions */ - +#include <cutils/properties.h> /* for property_list */ #include <healthd/BatteryMonitor.h> +#include <private/android_logger.h> /* private pmsg functions */ +#include <selinux/label.h> +#include <selinux/selinux.h> +#include <ziparchive/zip_archive.h> #include "adb_install.h" #include "common.h" @@ -59,18 +62,16 @@ #include "fuse_sdcard_provider.h" #include "fuse_sideload.h" #include "install.h" +#include "minadbd/minadbd.h" #include "minui/minui.h" -#include "minzip/DirUtil.h" -#include "minzip/Zip.h" +#include "otautil/DirUtil.h" #include "roots.h" #include "ui.h" -#include "unique_fd.h" #include "screen_ui.h" struct selabel_handle *sehandle; static const struct option OPTIONS[] = { - { "send_intent", required_argument, NULL, 'i' }, { "update_package", required_argument, NULL, 'u' }, { "retry_count", required_argument, NULL, 'n' }, { "wipe_data", no_argument, NULL, 'w' }, @@ -97,7 +98,6 @@ static const std::vector<std::string> bootreason_blacklist { static const char *CACHE_LOG_DIR = "/cache/recovery"; 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 *LAST_INSTALL_FILE = "/cache/recovery/last_install"; static const char *LOCALE_FILE = "/cache/recovery/last_locale"; @@ -132,10 +132,8 @@ static bool has_cache = false; * 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=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 @@ -193,7 +191,7 @@ static const int MAX_ARGS = 100; // open a given path, mounting partitions as necessary FILE* fopen_path(const char *path, const char *mode) { if (ensure_path_mounted(path) != 0) { - LOGE("Can't mount %s\n", path); + LOG(ERROR) << "Can't mount " << path; return NULL; } @@ -208,19 +206,20 @@ FILE* fopen_path(const char *path, const char *mode) { // 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)); + if (ferror(fp)) { + PLOG(ERROR) << "Error in " << name; + } fclose(fp); } bool is_ro_debuggable() { - char value[PROPERTY_VALUE_MAX+1]; - return (property_get("ro.debuggable", value, NULL) == 1 && value[0] == '1'); + return android::base::GetBoolProperty("ro.debuggable", false); } static void redirect_stdio(const char* filename) { int pipefd[2]; if (pipe(pipefd) == -1) { - LOGE("pipe failed: %s\n", strerror(errno)); + PLOG(ERROR) << "pipe failed"; // Fall back to traditional logging mode without timestamps. // If these fail, there's not really anywhere to complain... @@ -232,7 +231,7 @@ static void redirect_stdio(const char* filename) { pid_t pid = fork(); if (pid == -1) { - LOGE("fork failed: %s\n", strerror(errno)); + PLOG(ERROR) << "fork failed"; // Fall back to traditional logging mode without timestamps. // If these fail, there's not really anywhere to complain... @@ -251,14 +250,14 @@ static void redirect_stdio(const char* filename) { // Child logger to actually write to the log file. FILE* log_fp = fopen(filename, "a"); if (log_fp == nullptr) { - LOGE("fopen \"%s\" failed: %s\n", filename, strerror(errno)); + PLOG(ERROR) << "fopen \"" << filename << "\" failed"; close(pipefd[0]); _exit(1); } FILE* pipe_fp = fdopen(pipefd[0], "r"); if (pipe_fp == nullptr) { - LOGE("fdopen failed: %s\n", strerror(errno)); + PLOG(ERROR) << "fdopen failed"; check_and_fclose(log_fp, filename); close(pipefd[0]); _exit(1); @@ -278,7 +277,7 @@ static void redirect_stdio(const char* filename) { fflush(log_fp); } - LOGE("getline failed: %s\n", strerror(errno)); + PLOG(ERROR) << "getline failed"; free(line); check_and_fclose(log_fp, filename); @@ -293,10 +292,10 @@ static void redirect_stdio(const char* filename) { setbuf(stderr, nullptr); if (dup2(pipefd[1], STDOUT_FILENO) == -1) { - LOGE("dup2 stdout failed: %s\n", strerror(errno)); + PLOG(ERROR) << "dup2 stdout failed"; } if (dup2(pipefd[1], STDERR_FILENO) == -1) { - LOGE("dup2 stderr failed: %s\n", strerror(errno)); + PLOG(ERROR) << "dup2 stderr failed"; } close(pipefd[1]); @@ -312,18 +311,20 @@ get_args(int *argc, char ***argv) { bootloader_message boot = {}; std::string err; if (!read_bootloader_message(&boot, &err)) { - LOGE("%s\n", err.c_str()); + LOG(ERROR) << err; // If fails, leave a zeroed bootloader_message. memset(&boot, 0, sizeof(boot)); } stage = strndup(boot.stage, sizeof(boot.stage)); - if (boot.command[0] != 0 && boot.command[0] != 255) { - LOGI("Boot command: %.*s\n", (int)sizeof(boot.command), boot.command); + if (boot.command[0] != 0) { + std::string boot_command = std::string(boot.command, sizeof(boot.command)); + LOG(INFO) << "Boot command: " << boot_command; } - if (boot.status[0] != 0 && boot.status[0] != 255) { - LOGI("Boot status: %.*s\n", (int)sizeof(boot.status), boot.status); + if (boot.status[0] != 0) { + std::string boot_status = std::string(boot.status, sizeof(boot.status)); + LOG(INFO) << "Boot status: " << boot_status; } // --- if arguments weren't supplied, look in the bootloader control block @@ -337,9 +338,10 @@ get_args(int *argc, char ***argv) { 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); + LOG(INFO) << "Got arguments from boot message"; + } else if (boot.recovery[0] != 0) { + std::string boot_recovery = std::string(boot.recovery, 20); + LOG(ERROR) << "Bad boot message\n" << "\"" <<boot_recovery << "\""; } } @@ -364,32 +366,27 @@ get_args(int *argc, char ***argv) { } check_and_fclose(fp, COMMAND_FILE); - LOGI("Got arguments from %s\n", COMMAND_FILE); + LOG(INFO) << "Got arguments from " << 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)); + std::vector<std::string> options; + for (int i = 1; i < *argc; ++i) { + options.push_back((*argv)[i]); } - if (!write_bootloader_message(boot, &err)) { - LOGE("%s\n", err.c_str()); + if (!write_bootloader_message(options, &err)) { + LOG(ERROR) << err; } } static void set_sdcard_update_bootloader_message() { - bootloader_message boot = {}; - strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); - strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); + std::vector<std::string> options; std::string err; - if (!write_bootloader_message(boot, &err)) { - LOGE("%s\n", err.c_str()); + if (!write_bootloader_message(options, &err)) { + LOG(ERROR) << err; } } @@ -397,14 +394,14 @@ set_sdcard_update_bootloader_message() { static void save_kernel_log(const char* destination) { int klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0); if (klog_buf_len <= 0) { - LOGE("Error getting klog size: %s\n", strerror(errno)); + PLOG(ERROR) << "Error getting klog size"; return; } std::string buffer(klog_buf_len, 0); int n = klogctl(KLOG_READ_ALL, &buffer[0], klog_buf_len); if (n == -1) { - LOGE("Error in reading klog: %s\n", strerror(errno)); + PLOG(ERROR) << "Error in reading klog"; return; } buffer.resize(n); @@ -424,17 +421,17 @@ static void copy_log_file_to_pmsg(const char* source, const char* destination) { } // How much of the temp log we have copied to the copy in cache. -static long tmplog_offset = 0; +static off_t tmplog_offset = 0; static void copy_log_file(const char* source, const char* destination, bool append) { FILE* dest_fp = fopen_path(destination, append ? "a" : "w"); if (dest_fp == nullptr) { - LOGE("Can't open %s\n", destination); + PLOG(ERROR) << "Can't open " << destination; } else { FILE* source_fp = fopen(source, "r"); if (source_fp != nullptr) { if (append) { - fseek(source_fp, tmplog_offset, SEEK_SET); // Since last write + fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write } char buf[4096]; size_t bytes; @@ -442,7 +439,7 @@ static void copy_log_file(const char* source, const char* destination, bool appe fwrite(buf, 1, bytes, dest_fp); } if (append) { - tmplog_offset = ftell(source_fp); + tmplog_offset = ftello(source_fp); } check_and_fclose(source_fp, source); } @@ -516,22 +513,10 @@ static void copy_logs() { } // 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. +// copy our log file to cache as well (for the system to read). 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 && has_cache) { - FILE *fp = fopen_path(INTENT_FILE, "w"); - if (fp == NULL) { - LOGE("Can't open %s\n", INTENT_FILE); - } else { - fputs(send_intent, fp); - check_and_fclose(fp, INTENT_FILE); - } - } - +finish_recovery() { // Save the locale to cache, so if recovery is next started up // without a --locale argument (eg, directly from the bootloader) // it will use the last-known locale. @@ -539,28 +524,29 @@ finish_recovery(const char *send_intent) { size_t len = strlen(locale); __pmsg_write(LOCALE_FILE, locale, len); if (has_cache) { - LOGI("Saving locale \"%s\"\n", locale); + LOG(INFO) << "Saving locale \"" << locale << "\""; FILE* fp = fopen_path(LOCALE_FILE, "w"); - fwrite(locale, 1, len, fp); - fflush(fp); - fsync(fileno(fp)); - check_and_fclose(fp, LOCALE_FILE); + if (fp != NULL) { + fwrite(locale, 1, len, fp); + fflush(fp); + fsync(fileno(fp)); + check_and_fclose(fp, LOCALE_FILE); + } } } copy_logs(); // Reset to normal system boot so recovery won't cycle indefinitely. - bootloader_message boot = {}; std::string err; - if (!write_bootloader_message(boot, &err)) { - LOGE("%s\n", err.c_str()); + if (!clear_bootloader_message(&err)) { + LOG(ERROR) << err; } // Remove the command file, so recovery won't repeat indefinitely. if (has_cache) { if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { - LOGW("Can't unlink %s\n", COMMAND_FILE); + LOG(WARNING) << "Can't unlink " << COMMAND_FILE; } ensure_path_unmounted(CACHE_ROOT); } @@ -700,7 +686,7 @@ get_menu_selection(const char* const * headers, const char* const * items, if (ui->WasTextEverVisible()) { continue; } else { - LOGI("timed out waiting for key input; rebooting.\n"); + LOG(INFO) << "timed out waiting for key input; rebooting."; ui->EndMenu(); return 0; // XXX fixme } @@ -741,7 +727,7 @@ static char* browse_directory(const char* path, Device* device) { DIR* d = opendir(path); if (d == NULL) { - LOGE("error opening %s: %s\n", path, strerror(errno)); + PLOG(ERROR) << "error opening " << path; return NULL; } @@ -884,35 +870,35 @@ static bool wipe_cache(bool should_confirm, Device* device) { // Otherwise, it goes with BLKDISCARD (if device supports BLKDISCARDZEROES) or // BLKZEROOUT. static bool secure_wipe_partition(const std::string& partition) { - unique_fd fd(TEMP_FAILURE_RETRY(open(partition.c_str(), O_WRONLY))); - if (fd.get() == -1) { - LOGE("failed to open \"%s\": %s\n", partition.c_str(), strerror(errno)); + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(partition.c_str(), O_WRONLY))); + if (fd == -1) { + PLOG(ERROR) << "failed to open \"" << partition << "\""; return false; } uint64_t range[2] = {0, 0}; - if (ioctl(fd.get(), BLKGETSIZE64, &range[1]) == -1 || range[1] == 0) { - LOGE("failed to get partition size: %s\n", strerror(errno)); + if (ioctl(fd, BLKGETSIZE64, &range[1]) == -1 || range[1] == 0) { + PLOG(ERROR) << "failed to get partition size"; return false; } printf("Secure-wiping \"%s\" from %" PRIu64 " to %" PRIu64 ".\n", partition.c_str(), range[0], range[1]); printf("Trying BLKSECDISCARD...\t"); - if (ioctl(fd.get(), BLKSECDISCARD, &range) == -1) { + if (ioctl(fd, BLKSECDISCARD, &range) == -1) { printf("failed: %s\n", strerror(errno)); // Use BLKDISCARD if it zeroes out blocks, otherwise use BLKZEROOUT. unsigned int zeroes; - if (ioctl(fd.get(), BLKDISCARDZEROES, &zeroes) == 0 && zeroes != 0) { + if (ioctl(fd, BLKDISCARDZEROES, &zeroes) == 0 && zeroes != 0) { printf("Trying BLKDISCARD...\t"); - if (ioctl(fd.get(), BLKDISCARD, &range) == -1) { + if (ioctl(fd, BLKDISCARD, &range) == -1) { printf("failed: %s\n", strerror(errno)); return false; } } else { printf("Trying BLKZEROOUT...\t"); - if (ioctl(fd.get(), BLKZEROOUT, &range) == -1) { + if (ioctl(fd, BLKZEROOUT, &range) == -1) { printf("failed: %s\n", strerror(errno)); return false; } @@ -928,35 +914,35 @@ static bool secure_wipe_partition(const std::string& partition) { // 2. check metadata (ota-type, pre-device and serial number if having one). static bool check_wipe_package(size_t wipe_package_size) { if (wipe_package_size == 0) { - LOGE("wipe_package_size is zero.\n"); + LOG(ERROR) << "wipe_package_size is zero"; return false; } std::string wipe_package; std::string err_str; if (!read_wipe_package(&wipe_package, wipe_package_size, &err_str)) { - LOGE("Failed to read wipe package: %s\n", err_str.c_str()); + PLOG(ERROR) << "Failed to read wipe package"; return false; } if (!verify_package(reinterpret_cast<const unsigned char*>(wipe_package.data()), wipe_package.size())) { - LOGE("Failed to verify package.\n"); + LOG(ERROR) << "Failed to verify package"; return false; } // Extract metadata - ZipArchive zip; - int err = mzOpenZipArchive(reinterpret_cast<unsigned char*>(&wipe_package[0]), - wipe_package.size(), &zip); + ZipArchiveHandle zip; + int err = OpenArchiveFromMemory(reinterpret_cast<void*>(&wipe_package[0]), + wipe_package.size(), "wipe_package", &zip); if (err != 0) { - LOGE("Can't open wipe package: %s\n", err != -1 ? strerror(err) : "bad"); + LOG(ERROR) << "Can't open wipe package : " << ErrorCodeString(err); return false; } std::string metadata; if (!read_metadata_from_package(&zip, &metadata)) { - mzCloseZipArchive(&zip); + CloseArchive(zip); return false; } - mzCloseZipArchive(&zip); + CloseArchive(zip); // Check metadata std::vector<std::string> lines = android::base::Split(metadata, "\n"); @@ -990,12 +976,12 @@ static bool wipe_ab_device(size_t wipe_package_size) { ui->SetProgressType(RecoveryUI::INDETERMINATE); if (!check_wipe_package(wipe_package_size)) { - LOGE("Failed to verify wipe package\n"); + LOG(ERROR) << "Failed to verify wipe package"; return false; } std::string partition_list; if (!android::base::ReadFileToString(RECOVERY_WIPE, &partition_list)) { - LOGE("failed to read \"%s\".\n", RECOVERY_WIPE); + LOG(ERROR) << "failed to read \"" << RECOVERY_WIPE << "\""; return false; } @@ -1158,7 +1144,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { sleep(1); continue; } else { - LOGE("Timed out waiting for the fuse-provided package.\n"); + LOG(ERROR) << "Timed out waiting for the fuse-provided package."; result = INSTALL_ERROR; kill(child, SIGKILL); break; @@ -1180,7 +1166,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOGE("Error exit from the fuse process: %d\n", WEXITSTATUS(status)); + LOG(ERROR) << "Error exit from the fuse process: " << WEXITSTATUS(status); } ensure_path_unmounted(SDCARD_ROOT); @@ -1193,7 +1179,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { static Device::BuiltinAction prompt_and_wait(Device* device, int status) { for (;;) { - finish_recovery(NULL); + finish_recovery(); switch (status) { case INSTALL_SUCCESS: case INSTALL_NONE: @@ -1271,15 +1257,12 @@ prompt_and_wait(Device* device, int status) { break; case Device::MOUNT_SYSTEM: - char system_root_image[PROPERTY_VALUE_MAX]; - property_get("ro.build.system_root_image", system_root_image, ""); - // For a system image built with the root directory (i.e. // system_root_image == "true"), we mount it to /system_root, and symlink /system // to /system_root/system to make adb shell work (the symlink is created through // the build system). // Bug: 22855115 - if (strcmp(system_root_image, "true") == 0) { + if (android::base::GetBoolProperty("ro.build.system_root_image", false)) { if (ensure_path_mounted_at("/", "/system_root") != -1) { ui->Print("Mounted /system.\n"); } @@ -1336,6 +1319,18 @@ ui_print(const char* format, ...) { } } +static constexpr char log_characters[] = "VDIWEF"; + +void UiLogger(android::base::LogId id, android::base::LogSeverity severity, + const char* tag, const char* file, unsigned int line, + const char* message) { + if (severity >= android::base::ERROR && gCurrentUI != NULL) { + gCurrentUI->Print("E:%s\n", message); + } else { + fprintf(stdout, "%c:%s\n", log_characters[severity], message); + } +} + static bool is_battery_ok() { struct healthd_config healthd_config = { .batteryStatusPath = android::String8(android::String8::kEmptyString), @@ -1391,28 +1386,18 @@ static bool is_battery_ok() { } static void set_retry_bootloader_message(int retry_count, int argc, char** argv) { - bootloader_message boot = {}; - strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); - strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); - + std::vector<std::string> options; for (int i = 1; i < argc; ++i) { if (strstr(argv[i], "retry_count") == nullptr) { - strlcat(boot.recovery, argv[i], sizeof(boot.recovery)); - strlcat(boot.recovery, "\n", sizeof(boot.recovery)); + options.push_back(argv[i]); } } - // Initialize counter to 1 if it's not in BCB, otherwise increment it by 1. - if (retry_count == 0) { - strlcat(boot.recovery, "--retry_count=1\n", sizeof(boot.recovery)); - } else { - char buffer[20]; - snprintf(buffer, sizeof(buffer), "--retry_count=%d\n", retry_count+1); - strlcat(boot.recovery, buffer, sizeof(boot.recovery)); - } + // Increment the retry counter by 1. + options.push_back(android::base::StringPrintf("--retry_count=%d", retry_count+1)); std::string err; - if (!write_bootloader_message(boot, &err)) { - LOGE("%s\n", err.c_str()); + if (!write_bootloader_message(options, &err)) { + LOG(ERROR) << err; } } @@ -1436,11 +1421,11 @@ static void log_failure_code(ErrorCode code, const char *update_package) { }; std::string log_content = android::base::Join(log_buffer, "\n"); if (!android::base::WriteStringToFile(log_content, TEMPORARY_INSTALL_FILE)) { - LOGE("failed to write %s: %s\n", TEMPORARY_INSTALL_FILE, strerror(errno)); + PLOG(ERROR) << "failed to write " << TEMPORARY_INSTALL_FILE; } // Also write the info into last_log. - LOGI("%s\n", log_content.c_str()); + LOG(INFO) << log_content; } static ssize_t logbasename( @@ -1469,7 +1454,7 @@ static ssize_t logrotate( } std::string name(filename); - size_t dot = name.find_last_of("."); + size_t dot = name.find_last_of('.'); std::string sub = name.substr(0, dot); if (!strstr(LAST_KMSG_FILE, sub.c_str()) && @@ -1485,7 +1470,7 @@ static ssize_t logrotate( if (!isdigit(number.data()[0])) { name += ".1"; } else { - unsigned long long i = std::stoull(number); + auto i = std::stoull(number); name = sub + "." + std::to_string(i + 1); } } @@ -1494,6 +1479,10 @@ static ssize_t logrotate( } int main(int argc, char **argv) { + // We don't have logcat yet under recovery; so we'll print error on screen and + // log to stdout (which is redirected to recovery.log) as we used to do. + android::base::InitLogging(argv, &UiLogger); + // Take last pmsg contents and rewrite it to the current pmsg session. static const char filter[] = "recovery/"; // Do we need to rotate? @@ -1514,7 +1503,7 @@ int main(int argc, char **argv) { // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { - adb_server_main(0, DEFAULT_ADB_PORT, -1); + minadbd_main(); return 0; } @@ -1531,7 +1520,6 @@ int main(int argc, char **argv) { get_args(&argc, &argv); - const char *send_intent = NULL; const char *update_package = NULL; bool should_wipe_data = false; bool should_wipe_cache = false; @@ -1549,7 +1537,6 @@ int main(int argc, char **argv) { int option_index; while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) { switch (arg) { - case 'i': send_intent = optarg; break; case 'n': android::base::ParseInt(optarg, &retry_count, 0); break; case 'u': update_package = optarg; break; case 'w': should_wipe_data = true; break; @@ -1581,7 +1568,7 @@ int main(int argc, char **argv) { break; } case '?': - LOGE("Invalid command argument\n"); + LOG(ERROR) << "Invalid command argument"; continue; } } @@ -1690,8 +1677,7 @@ int main(int argc, char **argv) { ui->Print("Retry attempt %d\n", retry_count); // Reboot and retry the update - int ret = property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); - if (ret < 0) { + if (!android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,recovery")) { ui->Print("Reboot failed\n"); } else { while (true) { @@ -1766,22 +1752,22 @@ int main(int argc, char **argv) { } // Save logs and clean up before rebooting or shutting down. - finish_recovery(send_intent); + finish_recovery(); switch (after) { case Device::SHUTDOWN: ui->Print("Shutting down...\n"); - property_set(ANDROID_RB_PROPERTY, "shutdown,"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); break; case Device::REBOOT_BOOTLOADER: ui->Print("Rebooting to bootloader...\n"); - property_set(ANDROID_RB_PROPERTY, "reboot,bootloader"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); break; default: ui->Print("Rebooting...\n"); - property_set(ANDROID_RB_PROPERTY, "reboot,"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,"); break; } while (true) { diff --git a/res-hdpi/images/erasing_text.png b/res-hdpi/images/erasing_text.png Binary files differindex e500d0268..2186c1950 100644 --- a/res-hdpi/images/erasing_text.png +++ b/res-hdpi/images/erasing_text.png diff --git a/res-hdpi/images/error_text.png b/res-hdpi/images/error_text.png Binary files differindex 9a3597b82..9700f459f 100644 --- a/res-hdpi/images/error_text.png +++ b/res-hdpi/images/error_text.png diff --git a/res-hdpi/images/installing_security_text.png b/res-hdpi/images/installing_security_text.png Binary files differindex 76e747410..0f605952c 100644 --- a/res-hdpi/images/installing_security_text.png +++ b/res-hdpi/images/installing_security_text.png diff --git a/res-hdpi/images/installing_text.png b/res-hdpi/images/installing_text.png Binary files differindex 5d2a5fa0c..ec8b875a5 100644 --- a/res-hdpi/images/installing_text.png +++ b/res-hdpi/images/installing_text.png diff --git a/res-hdpi/images/no_command_text.png b/res-hdpi/images/no_command_text.png Binary files differindex a567ad141..3eddcbbed 100644 --- a/res-hdpi/images/no_command_text.png +++ b/res-hdpi/images/no_command_text.png diff --git a/res-mdpi/images/erasing_text.png b/res-mdpi/images/erasing_text.png Binary files differindex ad68a1941..b0dd3c6d3 100644 --- a/res-mdpi/images/erasing_text.png +++ b/res-mdpi/images/erasing_text.png diff --git a/res-mdpi/images/error_text.png b/res-mdpi/images/error_text.png Binary files differindex 8ea5acb20..6a47a5956 100644 --- a/res-mdpi/images/error_text.png +++ b/res-mdpi/images/error_text.png diff --git a/res-mdpi/images/installing_security_text.png b/res-mdpi/images/installing_security_text.png Binary files differindex 615b9b73f..149939862 100644 --- a/res-mdpi/images/installing_security_text.png +++ b/res-mdpi/images/installing_security_text.png diff --git a/res-mdpi/images/installing_text.png b/res-mdpi/images/installing_text.png Binary files differindex 6cf8716b5..01e9bfefb 100644 --- a/res-mdpi/images/installing_text.png +++ b/res-mdpi/images/installing_text.png diff --git a/res-mdpi/images/no_command_text.png b/res-mdpi/images/no_command_text.png Binary files differindex 5cc6b3715..d340df518 100644 --- a/res-mdpi/images/no_command_text.png +++ b/res-mdpi/images/no_command_text.png diff --git a/res-xhdpi/images/erasing_text.png b/res-xhdpi/images/erasing_text.png Binary files differindex 01176e8cc..2f8b46918 100644 --- a/res-xhdpi/images/erasing_text.png +++ b/res-xhdpi/images/erasing_text.png diff --git a/res-xhdpi/images/error_text.png b/res-xhdpi/images/error_text.png Binary files differindex 4f890fa59..ad18851c5 100644 --- a/res-xhdpi/images/error_text.png +++ b/res-xhdpi/images/error_text.png diff --git a/res-xhdpi/images/installing_security_text.png b/res-xhdpi/images/installing_security_text.png Binary files differindex 6192832e8..acc6a7c2b 100644 --- a/res-xhdpi/images/installing_security_text.png +++ b/res-xhdpi/images/installing_security_text.png diff --git a/res-xhdpi/images/installing_text.png b/res-xhdpi/images/installing_text.png Binary files differindex 441352949..32897d0f0 100644 --- a/res-xhdpi/images/installing_text.png +++ b/res-xhdpi/images/installing_text.png diff --git a/res-xhdpi/images/no_command_text.png b/res-xhdpi/images/no_command_text.png Binary files differindex 9f7403753..eb43c59c5 100644 --- a/res-xhdpi/images/no_command_text.png +++ b/res-xhdpi/images/no_command_text.png diff --git a/res-xxhdpi/images/erasing_text.png b/res-xxhdpi/images/erasing_text.png Binary files differindex b8653eb95..8ff2b2fcf 100644 --- a/res-xxhdpi/images/erasing_text.png +++ b/res-xxhdpi/images/erasing_text.png diff --git a/res-xxhdpi/images/error_text.png b/res-xxhdpi/images/error_text.png Binary files differindex d77ee5085..658d4ea56 100644 --- a/res-xxhdpi/images/error_text.png +++ b/res-xxhdpi/images/error_text.png diff --git a/res-xxhdpi/images/installing_security_text.png b/res-xxhdpi/images/installing_security_text.png Binary files differindex ca0c191d4..23fcaa441 100644 --- a/res-xxhdpi/images/installing_security_text.png +++ b/res-xxhdpi/images/installing_security_text.png diff --git a/res-xxhdpi/images/installing_text.png b/res-xxhdpi/images/installing_text.png Binary files differindex a76a174f0..fd8e58464 100644 --- a/res-xxhdpi/images/installing_text.png +++ b/res-xxhdpi/images/installing_text.png diff --git a/res-xxhdpi/images/no_command_text.png b/res-xxhdpi/images/no_command_text.png Binary files differindex 5e363e3a5..23932d6b7 100644 --- a/res-xxhdpi/images/no_command_text.png +++ b/res-xxhdpi/images/no_command_text.png diff --git a/res-xxxhdpi/images/erasing_text.png b/res-xxxhdpi/images/erasing_text.png Binary files differindex f4a466118..031529371 100644 --- a/res-xxxhdpi/images/erasing_text.png +++ b/res-xxxhdpi/images/erasing_text.png diff --git a/res-xxxhdpi/images/error_text.png b/res-xxxhdpi/images/error_text.png Binary files differindex 317a7716f..dba127f02 100644 --- a/res-xxxhdpi/images/error_text.png +++ b/res-xxxhdpi/images/error_text.png diff --git a/res-xxxhdpi/images/installing_security_text.png b/res-xxxhdpi/images/installing_security_text.png Binary files differindex c99c9072a..6cdbef48e 100644 --- a/res-xxxhdpi/images/installing_security_text.png +++ b/res-xxxhdpi/images/installing_security_text.png diff --git a/res-xxxhdpi/images/installing_text.png b/res-xxxhdpi/images/installing_text.png Binary files differindex 91d833017..32511a9c5 100644 --- a/res-xxxhdpi/images/installing_text.png +++ b/res-xxxhdpi/images/installing_text.png diff --git a/res-xxxhdpi/images/no_command_text.png b/res-xxxhdpi/images/no_command_text.png Binary files differindex b6eb964ba..b6cdd7718 100644 --- a/res-xxxhdpi/images/no_command_text.png +++ b/res-xxxhdpi/images/no_command_text.png @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "roots.h" + #include <errno.h> #include <stdlib.h> #include <sys/mount.h> @@ -24,13 +26,13 @@ #include <ctype.h> #include <fcntl.h> +#include <android-base/logging.h> +#include <ext4_utils/make_ext4fs.h> +#include <ext4_utils/wipe.h> #include <fs_mgr.h> -#include "mtdutils/mtdutils.h" -#include "mtdutils/mounts.h" -#include "roots.h" + #include "common.h" -#include "make_ext4fs.h" -#include "wipe.h" +#include "mounts.h" #include "cryptfs.h" static struct fstab *fstab = NULL; @@ -44,13 +46,13 @@ void load_volume_table() fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); if (!fstab) { - LOGE("failed to read /etc/recovery.fstab\n"); + LOG(ERROR) << "failed to read /etc/recovery.fstab"; return; } ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk"); if (ret < 0 ) { - LOGE("failed to add /tmp entry to fstab\n"); + LOG(ERROR) << "failed to add /tmp entry to fstab"; fs_mgr_free_fstab(fstab); fstab = NULL; return; @@ -74,7 +76,7 @@ Volume* volume_for_path(const char* path) { int ensure_path_mounted_at(const char* path, const char* mount_point) { Volume* v = volume_for_path(path); if (v == NULL) { - LOGE("unknown volume for path [%s]\n", path); + LOG(ERROR) << "unknown volume for path [" << path << "]"; return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { @@ -82,10 +84,8 @@ int ensure_path_mounted_at(const char* path, const char* mount_point) { return 0; } - int result; - result = scan_mounted_volumes(); - if (result < 0) { - LOGE("failed to scan mounted volumes\n"); + if (!scan_mounted_volumes()) { + LOG(ERROR) << "failed to scan mounted volumes"; return -1; } @@ -93,8 +93,7 @@ int ensure_path_mounted_at(const char* path, const char* mount_point) { mount_point = v->mount_point; } - const MountedVolume* mv = - find_mounted_volume_by_mount_point(mount_point); + MountedVolume* mv = find_mounted_volume_by_mount_point(mount_point); if (mv) { // volume is already mounted return 0; @@ -102,29 +101,30 @@ int ensure_path_mounted_at(const char* path, const char* mount_point) { mkdir(mount_point, 0755); // in case it doesn't already exist - if (strcmp(v->fs_type, "yaffs2") == 0) { - // mount an MTD partition as a YAFFS2 filesystem. - mtd_scan_partitions(); - const MtdPartition* partition; - partition = mtd_find_partition_by_name(v->blk_device); - if (partition == NULL) { - LOGE("failed to find \"%s\" partition to mount at \"%s\"\n", - v->blk_device, mount_point); - return -1; - } - return mtd_mount_partition(partition, mount_point, v->fs_type, 0); - } else if (strcmp(v->fs_type, "ext4") == 0 || + if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "squashfs") == 0 || strcmp(v->fs_type, "vfat") == 0) { - result = mount(v->blk_device, mount_point, v->fs_type, - v->flags, v->fs_options); - if (result == 0) return 0; + int result = mount(v->blk_device, mount_point, v->fs_type, v->flags, v->fs_options); + if (result == -1 && fs_mgr_is_formattable(v)) { + LOG(ERROR) << "failed to mount " << mount_point << " (" << strerror(errno) + << ") , formatting....."; + bool crypt_footer = fs_mgr_is_encryptable(v) && !strcmp(v->key_loc, "footer"); + if (fs_mgr_do_format(v, crypt_footer) == 0) { + result = mount(v->blk_device, mount_point, v->fs_type, v->flags, v->fs_options); + } else { + PLOG(ERROR) << "failed to format " << mount_point; + return -1; + } + } - LOGE("failed to mount %s (%s)\n", mount_point, strerror(errno)); - return -1; + if (result == -1) { + PLOG(ERROR) << "failed to mount " << mount_point; + return -1; + } + return 0; } - LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, mount_point); + LOG(ERROR) << "unknown fs_type \"" << v->fs_type << "\" for " << mount_point; return -1; } @@ -136,7 +136,7 @@ int ensure_path_mounted(const char* path) { int ensure_path_unmounted(const char* path) { Volume* v = volume_for_path(path); if (v == NULL) { - LOGE("unknown volume for path [%s]\n", path); + LOG(ERROR) << "unknown volume for path [" << path << "]"; return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { @@ -144,15 +144,12 @@ int ensure_path_unmounted(const char* path) { return -1; } - int result; - result = scan_mounted_volumes(); - if (result < 0) { - LOGE("failed to scan mounted volumes\n"); + if (!scan_mounted_volumes()) { + LOG(ERROR) << "failed to scan mounted volumes"; return -1; } - const MountedVolume* mv = - find_mounted_volume_by_mount_point(v->mount_point); + MountedVolume* mv = find_mounted_volume_by_mount_point(v->mount_point); if (mv == NULL) { // volume is already unmounted return 0; @@ -170,7 +167,7 @@ static int exec_cmd(const char* path, char* const argv[]) { } waitpid(child, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOGE("%s failed with status %d\n", path, WEXITSTATUS(status)); + LOG(ERROR) << path << " failed with status " << WEXITSTATUS(status); } return WEXITSTATUS(status); } @@ -178,55 +175,32 @@ static int exec_cmd(const char* path, char* const argv[]) { int format_volume(const char* volume, const char* directory) { Volume* v = volume_for_path(volume); if (v == NULL) { - LOGE("unknown volume \"%s\"\n", volume); + LOG(ERROR) << "unknown volume \"" << volume << "\""; return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { // you can't format the ramdisk. - LOGE("can't format_volume \"%s\"", volume); + LOG(ERROR) << "can't format_volume \"" << volume << "\""; return -1; } if (strcmp(v->mount_point, volume) != 0) { - LOGE("can't give path \"%s\" to format_volume\n", volume); + LOG(ERROR) << "can't give path \"" << volume << "\" to format_volume"; return -1; } if (ensure_path_unmounted(volume) != 0) { - LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point); + LOG(ERROR) << "format_volume failed to unmount \"" << v->mount_point << "\""; return -1; } - if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) { - mtd_scan_partitions(); - const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device); - if (partition == NULL) { - LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device); - return -1; - } - - MtdWriteContext *write = mtd_write_partition(partition); - if (write == NULL) { - LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device); - return -1; - } else if (mtd_erase_blocks(write, -1) == (off_t) -1) { - LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device); - mtd_write_close(write); - return -1; - } else if (mtd_write_close(write)) { - LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device); - return -1; - } - return 0; - } - if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "f2fs") == 0) { // if there's a key_loc that looks like a path, it should be a // block device for storing encryption metadata. wipe it too. if (v->key_loc != NULL && v->key_loc[0] == '/') { - LOGI("wiping %s\n", v->key_loc); + LOG(INFO) << "wiping " << v->key_loc; int fd = open(v->key_loc, O_WRONLY | O_CREAT, 0644); if (fd < 0) { - LOGE("format_volume: failed to open %s\n", v->key_loc); + LOG(ERROR) << "format_volume: failed to open " << v->key_loc; return -1; } wipe_block_device(fd, get_file_size(fd)); @@ -244,16 +218,19 @@ int format_volume(const char* volume, const char* directory) { result = make_ext4fs_directory(v->blk_device, length, volume, sehandle, directory); } else { /* Has to be f2fs because we checked earlier. */ if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) { - LOGE("format_volume: crypt footer + negative length (%zd) not supported on %s\n", length, v->fs_type); + LOG(ERROR) << "format_volume: crypt footer + negative length (" << length + << ") not supported on " << v->fs_type; return -1; } if (length < 0) { - LOGE("format_volume: negative length (%zd) not supported on %s\n", length, v->fs_type); + LOG(ERROR) << "format_volume: negative length (" << length + << ") not supported on " << v->fs_type; return -1; } char *num_sectors; if (asprintf(&num_sectors, "%zd", length / 512) <= 0) { - LOGE("format_volume: failed to create %s command for %s\n", v->fs_type, v->blk_device); + LOG(ERROR) << "format_volume: failed to create " << v->fs_type + << " command for " << v->blk_device; return -1; } const char *f2fs_path = "/sbin/mkfs.f2fs"; @@ -263,13 +240,13 @@ int format_volume(const char* volume, const char* directory) { free(num_sectors); } if (result != 0) { - LOGE("format_volume: make %s failed on %s with %d(%s)\n", v->fs_type, v->blk_device, result, strerror(errno)); + PLOG(ERROR) << "format_volume: make " << v->fs_type << " failed on " << v->blk_device; return -1; } return 0; } - LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type); + LOG(ERROR) << "format_volume: fs_type \"" << v->fs_type << "\" unsupported"; return -1; } @@ -279,7 +256,7 @@ int format_volume(const char* volume) { int setup_install_mounts() { if (fstab == NULL) { - LOGE("can't set up install mounts: no fstab loaded\n"); + LOG(ERROR) << "can't set up install mounts: no fstab loaded"; return -1; } for (int i = 0; i < fstab->num_entries; ++i) { @@ -288,13 +265,13 @@ int setup_install_mounts() { if (strcmp(v->mount_point, "/tmp") == 0 || strcmp(v->mount_point, "/cache") == 0) { if (ensure_path_mounted(v->mount_point) != 0) { - LOGE("failed to mount %s\n", v->mount_point); + LOG(ERROR) << "failed to mount " << v->mount_point; return -1; } } else { if (ensure_path_unmounted(v->mount_point) != 0) { - LOGE("failed to unmount %s\n", v->mount_point); + LOG(ERROR) << "failed to unmount " << v->mount_point; return -1; } } diff --git a/screen_ui.cpp b/screen_ui.cpp index 95b97d15c..a7b03c50d 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -31,9 +31,10 @@ #include <vector> +#include <android-base/logging.h> +#include <android-base/properties.h> #include <android-base/strings.h> #include <android-base/stringprintf.h> -#include <cutils/properties.h> #include "common.h" #include "device.h" @@ -292,8 +293,8 @@ void ScreenRecoveryUI::draw_screen_locked() { int y = 0; if (show_menu) { - char recovery_fingerprint[PROPERTY_VALUE_MAX]; - property_get("ro.bootimage.build.fingerprint", recovery_fingerprint, ""); + std::string recovery_fingerprint = + android::base::GetProperty("ro.bootimage.build.fingerprint", ""); SetColor(INFO); DrawTextLine(TEXT_INDENT, &y, "Android Recovery", true); @@ -410,21 +411,21 @@ void ScreenRecoveryUI::ProgressThreadLoop() { // minimum of 20ms delay between frames double delay = interval - (end-start); if (delay < 0.02) delay = 0.02; - usleep((long)(delay * 1000000)); + usleep(static_cast<useconds_t>(delay * 1000000)); } } void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) { int result = res_create_display_surface(filename, surface); if (result < 0) { - LOGE("couldn't load bitmap %s (error %d)\n", filename, result); + LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")"; } } void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) { int result = res_create_localized_alpha_surface(filename, locale, surface); if (result < 0) { - LOGE("couldn't load bitmap %s (error %d)\n", filename, result); + LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")"; } } @@ -459,7 +460,7 @@ void ScreenRecoveryUI::Init() { RecoveryUI::Init(); InitTextParams(); - density_ = static_cast<float>(property_get_int32("ro.sf.lcd_density", 160)) / 160.f; + density_ = static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f; // Are we portrait or landscape? layout_ = (gr_fb_width() > gr_fb_height()) ? LANDSCAPE : PORTRAIT; @@ -675,8 +676,8 @@ void ScreenRecoveryUI::ClearText() { } void ScreenRecoveryUI::ShowFile(FILE* fp) { - std::vector<long> offsets; - offsets.push_back(ftell(fp)); + std::vector<off_t> offsets; + offsets.push_back(ftello(fp)); ClearText(); struct stat sb; @@ -686,7 +687,7 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) { while (true) { if (show_prompt) { PrintOnScreenOnly("--(%d%% of %d bytes)--", - static_cast<int>(100 * (double(ftell(fp)) / double(sb.st_size))), + static_cast<int>(100 * (double(ftello(fp)) / double(sb.st_size))), static_cast<int>(sb.st_size)); Redraw(); while (show_prompt) { @@ -705,7 +706,7 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) { if (feof(fp)) { return; } - offsets.push_back(ftell(fp)); + offsets.push_back(ftello(fp)); } } ClearText(); diff --git a/tests/Android.mk b/tests/Android.mk index a66991b21..3d05386b0 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -19,15 +19,23 @@ LOCAL_PATH := $(call my-dir) # Unit tests include $(CLEAR_VARS) LOCAL_CLANG := true +LOCAL_CFLAGS := -Werror LOCAL_MODULE := recovery_unit_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := \ libverifier \ - libminui + libminui \ + libotautil \ + libziparchive \ + libutils \ + libz \ + libselinux \ + libbase LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp LOCAL_SRC_FILES += unit/recovery_test.cpp LOCAL_SRC_FILES += unit/locale_test.cpp +LOCAL_SRC_FILES += unit/zip_test.cpp LOCAL_C_INCLUDES := bootable/recovery LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) @@ -35,35 +43,65 @@ include $(BUILD_NATIVE_TEST) # Component tests include $(CLEAR_VARS) LOCAL_CLANG := true -LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_CFLAGS += -Wno-unused-parameter -Werror LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_MODULE := recovery_component_test LOCAL_C_INCLUDES := bootable/recovery LOCAL_SRC_FILES := \ - component/verifier_test.cpp \ - component/applypatch_test.cpp + component/applypatch_test.cpp \ + component/edify_test.cpp \ + component/updater_test.cpp \ + component/verifier_test.cpp LOCAL_FORCE_STATIC_EXECUTABLE := true + +tune2fs_static_libraries := \ + libext2_com_err \ + libext2_blkid \ + libext2_quota \ + libext2_uuid_static \ + libext2_e2p \ + libext2fs + LOCAL_STATIC_LIBRARIES := \ libapplypatch \ + libedify \ libotafault \ - libmtdutils \ - libbase \ + libupdater \ libverifier \ - libcrypto_static \ libminui \ - libminzip \ + libotautil \ + libmounts \ + liblog \ + libselinux \ + libext4_utils_static \ + libsparse_static \ + libcrypto_utils \ + libcrypto \ libcutils \ libbz \ libz \ - libc + libbase \ + libtune2fs \ + $(tune2fs_static_libraries) -testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/recovery testdata_files := $(call find-subdir-files, testdata/*) +testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/recovery GEN := $(addprefix $(testdata_out_path)/, $(testdata_files)) $(GEN): PRIVATE_PATH := $(LOCAL_PATH) $(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ $(GEN): $(testdata_out_path)/% : $(LOCAL_PATH)/% $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN) + +ifdef TARGET_2ND_ARCH +testdata_out_path_2nd_arch := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/recovery +GEN_2ND_ARCH := $(addprefix $(testdata_out_path_2nd_arch)/, $(testdata_files)) +$(GEN_2ND_ARCH): PRIVATE_PATH := $(LOCAL_PATH) +$(GEN_2ND_ARCH): PRIVATE_CUSTOM_TOOL = cp $< $@ +$(GEN_2ND_ARCH): $(testdata_out_path_2nd_arch)/% : $(LOCAL_PATH)/% + $(transform-generated-source) +LOCAL_GENERATED_SOURCES += $(GEN_2ND_ARCH) +endif # TARGET_2ND_ARCH + include $(BUILD_NATIVE_TEST) diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index b44ddd17c..908a9f5f5 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -65,7 +65,7 @@ static bool file_cmp(std::string& f1, std::string& f2) { return c1 == c2; } -static std::string from_testdata_base(const std::string fname) { +static std::string from_testdata_base(const std::string& fname) { return android::base::StringPrintf("%s%s%s/%s", &DATA_PATH[0], &NATIVE_TEST_PATH[0], @@ -153,25 +153,16 @@ class ApplyPatchFullTest : public ApplyPatchCacheTest { struct FileContents fc; ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); - Value* patch1 = new Value(); - patch1->type = VAL_BLOB; - patch1->size = fc.data.size(); - patch1->data = static_cast<char*>(malloc(fc.data.size())); - memcpy(patch1->data, fc.data.data(), fc.data.size()); + Value* patch1 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end())); patches.push_back(patch1); ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); - Value* patch2 = new Value(); - patch2->type = VAL_BLOB; - patch2->size = fc.st.st_size; - patch2->data = static_cast<char*>(malloc(fc.data.size())); - memcpy(patch2->data, fc.data.data(), fc.data.size()); + Value* patch2 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end())); patches.push_back(patch2); } static void TearDownTestCase() { delete output_f; for (auto it = patches.begin(); it != patches.end(); ++it) { - free((*it)->data); delete *it; } patches.clear(); @@ -209,89 +200,93 @@ std::vector<Value*> ApplyPatchFullTest::patches; TemporaryFile* ApplyPatchFullTest::output_f; std::string ApplyPatchFullTest::output_loc; +TEST_F(ApplyPatchTest, CheckModeSkip) { + std::vector<std::string> sha1s; + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); +} + TEST_F(ApplyPatchTest, CheckModeSingle) { - char* s = &old_sha1[0]; - ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); + std::vector<std::string> sha1s = { old_sha1 }; + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchTest, CheckModeMultiple) { - char* argv[3] = { - &bad_sha1_a[0], - &old_sha1[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1, + bad_sha1_b }; - ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchTest, CheckModeFailure) { - char* argv[2] = { - &bad_sha1_a[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + bad_sha1_b }; - ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); + ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) { mangle_file(old_file); - char* s = &old_sha1[0]; - ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); + std::vector<std::string> sha1s = { old_sha1 }; + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) { mangle_file(old_file); - char* argv[3] = { - &bad_sha1_a[0], - &old_sha1[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1, + bad_sha1_b }; - ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) { mangle_file(old_file); - char* argv[2] = { - &bad_sha1_a[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + bad_sha1_b }; - ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); + ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) { unlink(&old_file[0]); - char* s = &old_sha1[0]; - ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); + std::vector<std::string> sha1s = { old_sha1 }; + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) { unlink(&old_file[0]); - char* argv[3] = { - &bad_sha1_a[0], - &old_sha1[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1, + bad_sha1_b }; - ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); + ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) { unlink(&old_file[0]); - char* argv[2] = { - &bad_sha1_a[0], - &bad_sha1_b[0] + std::vector<std::string> sha1s = { + bad_sha1_a, + bad_sha1_b }; - ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); + ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); } TEST_F(ApplyPatchFullTest, ApplyInPlace) { - std::vector<char*> sha1s; - sha1s.push_back(&bad_sha1_a[0]); - sha1s.push_back(&old_sha1[0]); - + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1 + }; int ap_result = applypatch(&old_file[0], "-", &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -301,8 +296,7 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) { "-", &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -310,15 +304,15 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) { } TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { - std::vector<char*> sha1s; - sha1s.push_back(&bad_sha1_a[0]); - sha1s.push_back(&old_sha1[0]); + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1 + }; int ap_result = applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -327,8 +321,7 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -337,15 +330,15 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { mangle_file(old_file); - std::vector<char*> sha1s; - sha1s.push_back(&bad_sha1_a[0]); - sha1s.push_back(&old_sha1[0]); + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1 + }; int ap_result = applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -354,8 +347,7 @@ TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_EQ(0, ap_result); @@ -366,15 +358,15 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) { mangle_file(old_file); mangle_file(cache_file); - std::vector<char*> sha1s; - sha1s.push_back(&bad_sha1_a[0]); - sha1s.push_back(&old_sha1[0]); + std::vector<std::string> sha1s = { + bad_sha1_a, + old_sha1 + }; int ap_result = applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_NE(0, ap_result); @@ -383,8 +375,7 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) { &output_loc[0], &new_sha1[0], new_size, - 2, - sha1s.data(), + sha1s, patches.data(), nullptr); ASSERT_NE(0, ap_result); diff --git a/tests/component/edify_test.cpp b/tests/component/edify_test.cpp new file mode 100644 index 000000000..287e40cc6 --- /dev/null +++ b/tests/component/edify_test.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> + +#include <gtest/gtest.h> + +#include "edify/expr.h" + +static void expect(const char* expr_str, const char* expected) { + Expr* e; + int error_count = 0; + EXPECT_EQ(0, parse_string(expr_str, &e, &error_count)); + EXPECT_EQ(0, error_count); + + State state(expr_str, nullptr); + + std::string result; + bool status = Evaluate(&state, e, &result); + + if (expected == nullptr) { + EXPECT_FALSE(status); + } else { + EXPECT_STREQ(expected, result.c_str()); + } + +} + +class EdifyTest : public ::testing::Test { + protected: + virtual void SetUp() { + RegisterBuiltins(); + } +}; + +TEST_F(EdifyTest, parsing) { + expect("a", "a"); + expect("\"a\"", "a"); + expect("\"\\x61\"", "a"); + expect("# this is a comment\n" + " a\n" + " \n", + "a"); +} + +TEST_F(EdifyTest, sequence) { + // sequence operator + expect("a; b; c", "c"); +} + +TEST_F(EdifyTest, concat) { + // string concat operator + expect("a + b", "ab"); + expect("a + \n \"b\"", "ab"); + expect("a + b +\nc\n", "abc"); + + // string concat function + expect("concat(a, b)", "ab"); + expect("concat(a,\n \"b\")", "ab"); + expect("concat(a + b,\nc,\"d\")", "abcd"); + expect("\"concat\"(a + b,\nc,\"d\")", "abcd"); +} + +TEST_F(EdifyTest, logical) { + // logical and + expect("a && b", "b"); + expect("a && \"\"", ""); + expect("\"\" && b", ""); + expect("\"\" && \"\"", ""); + expect("\"\" && abort()", ""); // test short-circuiting + expect("t && abort()", nullptr); + + // logical or + expect("a || b", "a"); + expect("a || \"\"", "a"); + expect("\"\" || b", "b"); + expect("\"\" || \"\"", ""); + expect("a || abort()", "a"); // test short-circuiting + expect("\"\" || abort()", NULL); + + // logical not + expect("!a", ""); + expect("! \"\"", "t"); + expect("!!a", "t"); +} + +TEST_F(EdifyTest, precedence) { + // precedence + expect("\"\" == \"\" && b", "b"); + expect("a + b == ab", "t"); + expect("ab == a + b", "t"); + expect("a + (b == ab)", "a"); + expect("(ab == a) + b", "b"); +} + +TEST_F(EdifyTest, substring) { + // substring function + expect("is_substring(cad, abracadabra)", "t"); + expect("is_substring(abrac, abracadabra)", "t"); + expect("is_substring(dabra, abracadabra)", "t"); + expect("is_substring(cad, abracxadabra)", ""); + expect("is_substring(abrac, axbracadabra)", ""); + expect("is_substring(dabra, abracadabrxa)", ""); +} + +TEST_F(EdifyTest, ifelse) { + // ifelse function + expect("ifelse(t, yes, no)", "yes"); + expect("ifelse(!t, yes, no)", "no"); + expect("ifelse(t, yes, abort())", "yes"); + expect("ifelse(!t, abort(), no)", "no"); +} + +TEST_F(EdifyTest, if_statement) { + // if "statements" + expect("if t then yes else no endif", "yes"); + expect("if \"\" then yes else no endif", "no"); + expect("if \"\" then yes endif", ""); + expect("if \"\"; t then yes endif", "yes"); +} + +TEST_F(EdifyTest, comparison) { + // numeric comparisons + expect("less_than_int(3, 14)", "t"); + expect("less_than_int(14, 3)", ""); + expect("less_than_int(x, 3)", ""); + expect("less_than_int(3, x)", ""); + expect("greater_than_int(3, 14)", ""); + expect("greater_than_int(14, 3)", "t"); + expect("greater_than_int(x, 3)", ""); + expect("greater_than_int(3, x)", ""); +} + +TEST_F(EdifyTest, big_string) { + // big string + expect(std::string(8192, 's').c_str(), std::string(8192, 's').c_str()); +} + +TEST_F(EdifyTest, unknown_function) { + // unknown function + const char* script1 = "unknown_function()"; + Expr* expr; + int error_count = 0; + EXPECT_EQ(1, parse_string(script1, &expr, &error_count)); + EXPECT_EQ(1, error_count); + + const char* script2 = "abc; unknown_function()"; + error_count = 0; + EXPECT_EQ(1, parse_string(script2, &expr, &error_count)); + EXPECT_EQ(1, error_count); + + const char* script3 = "unknown_function1() || yes"; + error_count = 0; + EXPECT_EQ(1, parse_string(script3, &expr, &error_count)); + EXPECT_EQ(1, error_count); +} diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp new file mode 100644 index 000000000..a859f11c1 --- /dev/null +++ b/tests/component/updater_test.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 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 <string> + +#include <android-base/properties.h> +#include <gtest/gtest.h> + +#include "edify/expr.h" +#include "error_code.h" +#include "updater/install.h" + +struct selabel_handle *sehandle = nullptr; + +static void expect(const char* expected, const char* expr_str, CauseCode cause_code) { + Expr* e; + int error_count; + EXPECT_EQ(parse_string(expr_str, &e, &error_count), 0); + + State state(expr_str, nullptr); + + std::string result; + bool status = Evaluate(&state, e, &result); + + if (expected == nullptr) { + EXPECT_FALSE(status); + } else { + EXPECT_STREQ(expected, result.c_str()); + } + + // Error code is set in updater/updater.cpp only, by parsing State.errmsg. + EXPECT_EQ(kNoError, state.error_code); + + // Cause code should always be available. + EXPECT_EQ(cause_code, state.cause_code); + +} + +class UpdaterTest : public ::testing::Test { + protected: + virtual void SetUp() { + RegisterBuiltins(); + RegisterInstallFunctions(); + } +}; + +TEST_F(UpdaterTest, getprop) { + expect(android::base::GetProperty("ro.product.device", "").c_str(), + "getprop(\"ro.product.device\")", + kNoCause); + + expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(), + "getprop(\"ro.build.fingerprint\")", + kNoCause); + + // getprop() accepts only one parameter. + expect(nullptr, "getprop()", kArgsParsingFailure); + expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure); +} + +TEST_F(UpdaterTest, sha1_check) { + // sha1_check(data) returns the SHA-1 of the data. + expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause); + expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause); + + // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1. + expect("81fe8bfe87576c3ecb22426f8e57847382917acf", + "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")", + kNoCause); + + expect("81fe8bfe87576c3ecb22426f8e57847382917acf", + "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")", + kNoCause); + + // Or "" if there's no match. + expect("", + "sha1_check(\"abcd\", \"wrong_sha1\")", + kNoCause); + + expect("", + "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")", + kNoCause); + + // sha1_check() expects at least one argument. + expect(nullptr, "sha1_check()", kArgsParsingFailure); +} diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index 780ff2816..7f9a71408 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -29,10 +29,11 @@ #include <openssl/sha.h> #include <android-base/stringprintf.h> +#include <ziparchive/zip_archive.h> #include "common.h" #include "common/test_constants.h" -#include "minzip/SysUtil.h" +#include "otautil/SysUtil.h" #include "ui.h" #include "verifier.h" @@ -45,14 +46,14 @@ class MockUI : public RecoveryUI { void Init() { } void SetStage(int, int) { } void SetLocale(const char*) { } - void SetBackground(Icon icon) { } - void SetSystemUpdateText(bool security_update) { } + void SetBackground(Icon /*icon*/) { } + void SetSystemUpdateText(bool /*security_update*/) { } - void SetProgressType(ProgressType determinate) { } - void ShowProgress(float portion, float seconds) { } - void SetProgress(float fraction) { } + void SetProgressType(ProgressType /*determinate*/) { } + void ShowProgress(float /*portion*/, float /*seconds*/) { } + void SetProgress(float /*fraction*/) { } - void ShowText(bool visible) { } + void ShowText(bool /*visible*/) { } bool IsTextVisible() { return false; } bool WasTextEverVisible() { return false; } void Print(const char* fmt, ...) { @@ -69,9 +70,10 @@ class MockUI : public RecoveryUI { } void ShowFile(const char*) { } - void StartMenu(const char* const * headers, const char* const * items, - int initial_selection) { } - int SelectMenu(int sel) { return 0; } + void StartMenu(const char* const* /*headers*/, + const char* const* /*items*/, + int /*initial_selection*/) { } + int SelectMenu(int /*sel*/) { return 0; } void EndMenu() { } }; @@ -94,30 +96,14 @@ class VerifierTest : public testing::TestWithParam<std::vector<std::string>> { android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH, TESTDATA_PATH, args[0].c_str()); if (sysMapFile(package.c_str(), &memmap) != 0) { - FAIL() << "Failed to mmap " << package << ": " << strerror(errno) - << "\n"; + FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n"; } for (auto it = ++(args.cbegin()); it != args.cend(); ++it) { - if (it->substr(it->length() - 3, it->length()) == "256") { - if (certs.empty()) { - FAIL() << "May only specify -sha256 after key type\n"; - } - certs.back().hash_len = SHA256_DIGEST_LENGTH; - } else { - std::string public_key_file = android::base::StringPrintf( - "%s%s%stest_key_%s.txt", DATA_PATH, NATIVE_TEST_PATH, - TESTDATA_PATH, it->c_str()); - ASSERT_TRUE(load_keys(public_key_file.c_str(), certs)); - certs.back().hash_len = SHA_DIGEST_LENGTH; - } - } - if (certs.empty()) { std::string public_key_file = android::base::StringPrintf( - "%s%s%stest_key_e3.txt", DATA_PATH, NATIVE_TEST_PATH, - TESTDATA_PATH); + "%s%s%stestkey_%s.txt", DATA_PATH, NATIVE_TEST_PATH, + TESTDATA_PATH, it->c_str()); ASSERT_TRUE(load_keys(public_key_file.c_str(), certs)); - certs.back().hash_len = SHA_DIGEST_LENGTH; } } @@ -142,37 +128,38 @@ TEST_P(VerifierFailureTest, VerifyFailure) { INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest, ::testing::Values( - std::vector<std::string>({"otasigned.zip", "e3"}), - std::vector<std::string>({"otasigned_f4.zip", "f4"}), - std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}), - std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}), - std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"}))); + std::vector<std::string>({"otasigned_v1.zip", "v1"}), + std::vector<std::string>({"otasigned_v2.zip", "v2"}), + std::vector<std::string>({"otasigned_v3.zip", "v3"}), + std::vector<std::string>({"otasigned_v4.zip", "v4"}), + std::vector<std::string>({"otasigned_v5.zip", "v5"}))); INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest, ::testing::Values( - std::vector<std::string>({"otasigned.zip", "f4", "e3"}), - std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}), - std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}), - std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}), - std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"}))); + std::vector<std::string>({"otasigned_v1.zip", "v1", "v2"}), + std::vector<std::string>({"otasigned_v2.zip", "v5", "v2"}), + std::vector<std::string>({"otasigned_v3.zip", "v5", "v1", "v3"}), + std::vector<std::string>({"otasigned_v4.zip", "v5", "v1", "v4"}), + std::vector<std::string>({"otasigned_v5.zip", "v4", "v1", "v5"}))); INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest, ::testing::Values( - std::vector<std::string>({"otasigned.zip", "f4"}), - std::vector<std::string>({"otasigned_f4.zip", "e3"}), - std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"}))); + std::vector<std::string>({"otasigned_v1.zip", "v2"}), + std::vector<std::string>({"otasigned_v2.zip", "v1"}), + std::vector<std::string>({"otasigned_v3.zip", "v5"}), + std::vector<std::string>({"otasigned_v4.zip", "v5"}), + std::vector<std::string>({"otasigned_v5.zip", "v3"}))); INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, ::testing::Values( - std::vector<std::string>({"otasigned.zip", "e3", "sha256"}), - std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}), - std::vector<std::string>({"otasigned_sha256.zip"}), - std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}), - std::vector<std::string>({"otasigned_ecdsa_sha256.zip"}))); + std::vector<std::string>({"otasigned_v1.zip", "v3"}), + std::vector<std::string>({"otasigned_v2.zip", "v4"}), + std::vector<std::string>({"otasigned_v3.zip", "v1"}), + std::vector<std::string>({"otasigned_v4.zip", "v2"}))); INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, ::testing::Values( - std::vector<std::string>({"random.zip"}), - std::vector<std::string>({"fake-eocd.zip"}), - std::vector<std::string>({"alter-metadata.zip"}), - std::vector<std::string>({"alter-footer.zip"}))); + std::vector<std::string>({"random.zip", "v1"}), + std::vector<std::string>({"fake-eocd.zip", "v1"}), + std::vector<std::string>({"alter-metadata.zip", "v1"}), + std::vector<std::string>({"alter-footer.zip", "v1"}))); diff --git a/tests/testdata/otasigned.zip b/tests/testdata/otasigned_v1.zip Binary files differindex a6bc53e41..a6bc53e41 100644 --- a/tests/testdata/otasigned.zip +++ b/tests/testdata/otasigned_v1.zip diff --git a/tests/testdata/otasigned_f4.zip b/tests/testdata/otasigned_v2.zip Binary files differindex dd1e4dd40..dd1e4dd40 100644 --- a/tests/testdata/otasigned_f4.zip +++ b/tests/testdata/otasigned_v2.zip diff --git a/tests/testdata/otasigned_sha256.zip b/tests/testdata/otasigned_v3.zip Binary files differindex 0ed4409b3..0ed4409b3 100644 --- a/tests/testdata/otasigned_sha256.zip +++ b/tests/testdata/otasigned_v3.zip diff --git a/tests/testdata/otasigned_f4_sha256.zip b/tests/testdata/otasigned_v4.zip Binary files differindex 3af408c40..3af408c40 100644 --- a/tests/testdata/otasigned_f4_sha256.zip +++ b/tests/testdata/otasigned_v4.zip diff --git a/tests/testdata/otasigned_ecdsa_sha256.zip b/tests/testdata/otasigned_v5.zip Binary files differindex 999fcdd0f..999fcdd0f 100644 --- a/tests/testdata/otasigned_ecdsa_sha256.zip +++ b/tests/testdata/otasigned_v5.zip diff --git a/tests/testdata/testkey.pk8 b/tests/testdata/testkey_v1.pk8 Binary files differindex 586c1bd5c..586c1bd5c 100644 --- a/tests/testdata/testkey.pk8 +++ b/tests/testdata/testkey_v1.pk8 diff --git a/tests/testdata/test_key_e3.txt b/tests/testdata/testkey_v1.txt index 53f5297bd..53f5297bd 100644 --- a/tests/testdata/test_key_e3.txt +++ b/tests/testdata/testkey_v1.txt diff --git a/tests/testdata/testkey.x509.pem b/tests/testdata/testkey_v1.x509.pem index e242d83e2..e242d83e2 100644 --- a/tests/testdata/testkey.x509.pem +++ b/tests/testdata/testkey_v1.x509.pem diff --git a/tests/testdata/test_f4.pk8 b/tests/testdata/testkey_v2.pk8 Binary files differindex 3052613c5..3052613c5 100644 --- a/tests/testdata/test_f4.pk8 +++ b/tests/testdata/testkey_v2.pk8 diff --git a/tests/testdata/test_key_f4.txt b/tests/testdata/testkey_v2.txt index 54ddbbad1..54ddbbad1 100644 --- a/tests/testdata/test_key_f4.txt +++ b/tests/testdata/testkey_v2.txt diff --git a/tests/testdata/test_f4.x509.pem b/tests/testdata/testkey_v2.x509.pem index 814abcf99..814abcf99 100644 --- a/tests/testdata/test_f4.x509.pem +++ b/tests/testdata/testkey_v2.x509.pem diff --git a/tests/testdata/testkey_v3.pk8 b/tests/testdata/testkey_v3.pk8 new file mode 120000 index 000000000..18ecf9815 --- /dev/null +++ b/tests/testdata/testkey_v3.pk8 @@ -0,0 +1 @@ +testkey_v1.pk8
\ No newline at end of file diff --git a/tests/testdata/testkey_v3.txt b/tests/testdata/testkey_v3.txt new file mode 100644 index 000000000..3208571a5 --- /dev/null +++ b/tests/testdata/testkey_v3.txt @@ -0,0 +1 @@ +v3 {64,0xc926ad21,{1795090719,2141396315,950055447,2581568430,4268923165,1920809988,546586521,3498997798,1776797858,3740060814,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,2563319927,323993566,28517732,609753416,1826472888,215237850,4261642700,4049082591,3228462402,774857746,154822455,2497198897,2758199418,3019015328,2794777644,87251430,2534927978,120774784,571297800,3695899472,2479925187,3811625450,3401832990,2394869647,3267246207,950095497,555058928,414729973,1136544882,3044590084,465547824,4058146728,2731796054,1689838846,3890756939,1048029507,895090649,247140249,178744550,3547885223,3165179243,109881576,3944604415,1044303212,3772373029,2985150306,3737520932,3599964420},{3437017481,3784475129,2800224972,3086222688,251333580,2131931323,512774938,325948880,2657486437,2102694287,3820568226,792812816,1026422502,2053275343,2800889200,3113586810,165549746,4273519969,4065247892,1902789247,772932719,3941848426,3652744109,216871947,3164400649,1942378755,3996765851,1055777370,964047799,629391717,2232744317,3910558992,191868569,2758883837,3682816752,2997714732,2702529250,3570700455,3776873832,3924067546,3555689545,2758825434,1323144535,61311905,1997411085,376844204,213777604,4077323584,9135381,1625809335,2804742137,2952293945,1117190829,4237312782,1825108855,3013147971,1111251351,2568837572,1684324211,2520978805,367251975,810756730,2353784344,1175080310}} diff --git a/tests/testdata/testkey_sha256.x509.pem b/tests/testdata/testkey_v3.x509.pem index 002ce8968..002ce8968 100644 --- a/tests/testdata/testkey_sha256.x509.pem +++ b/tests/testdata/testkey_v3.x509.pem diff --git a/tests/testdata/testkey_v4.pk8 b/tests/testdata/testkey_v4.pk8 new file mode 120000 index 000000000..683b9a3f1 --- /dev/null +++ b/tests/testdata/testkey_v4.pk8 @@ -0,0 +1 @@ +testkey_v2.pk8
\ No newline at end of file diff --git a/tests/testdata/testkey_v4.txt b/tests/testdata/testkey_v4.txt new file mode 100644 index 000000000..532cbd51a --- /dev/null +++ b/tests/testdata/testkey_v4.txt @@ -0,0 +1 @@ +v4 {64,0xc9bd1f21,{293133087,3210546773,865313125,250921607,3158780490,943703457,1242806226,2986289859,2942743769,2457906415,2719374299,1783459420,149579627,3081531591,3440738617,2788543742,2758457512,1146764939,3699497403,2446203424,1744968926,1159130537,2370028300,3978231572,3392699980,1487782451,1180150567,2841334302,3753960204,961373345,3333628321,748825784,2978557276,1566596926,1613056060,2600292737,1847226629,50398611,1890374404,2878700735,2286201787,1401186359,619285059,731930817,2340993166,1156490245,2992241729,151498140,318782170,3480838990,2100383433,4223552555,3628927011,4247846280,1759029513,4215632601,2719154626,3490334597,1751299340,3487864726,3668753795,4217506054,3748782284,3150295088},{1772626313,445326068,3477676155,1758201194,2986784722,491035581,3922936562,702212696,2979856666,3324974564,2488428922,3056318590,1626954946,664714029,398585816,3964097931,3356701905,2298377729,2040082097,3025491477,539143308,3348777868,2995302452,3602465520,212480763,2691021393,1307177300,704008044,2031136606,1054106474,3838318865,2441343869,1477566916,700949900,2534790355,3353533667,336163563,4106790558,2701448228,1571536379,1103842411,3623110423,1635278839,1577828979,910322800,715583630,138128831,1017877531,2289162787,447994798,1897243165,4121561445,4150719842,2131821093,2262395396,3305771534,980753571,3256525190,3128121808,1072869975,3507939515,4229109952,118381341,2209831334}} diff --git a/tests/testdata/test_f4_sha256.x509.pem b/tests/testdata/testkey_v4.x509.pem index 9d5376b45..9d5376b45 100644 --- a/tests/testdata/test_f4_sha256.x509.pem +++ b/tests/testdata/testkey_v4.x509.pem diff --git a/tests/testdata/testkey_ecdsa.pk8 b/tests/testdata/testkey_v5.pk8 Binary files differindex 9a521c8cf..9a521c8cf 100644 --- a/tests/testdata/testkey_ecdsa.pk8 +++ b/tests/testdata/testkey_v5.pk8 diff --git a/tests/testdata/test_key_ec.txt b/tests/testdata/testkey_v5.txt index 72b4395d9..72b4395d9 100644 --- a/tests/testdata/test_key_ec.txt +++ b/tests/testdata/testkey_v5.txt diff --git a/tests/testdata/testkey_ecdsa.x509.pem b/tests/testdata/testkey_v5.x509.pem index b12283645..b12283645 100644 --- a/tests/testdata/testkey_ecdsa.x509.pem +++ b/tests/testdata/testkey_v5.x509.pem diff --git a/tests/testdata/ziptest_dummy-update.zip b/tests/testdata/ziptest_dummy-update.zip Binary files differnew file mode 100644 index 000000000..6976bf155 --- /dev/null +++ b/tests/testdata/ziptest_dummy-update.zip diff --git a/tests/testdata/ziptest_valid.zip b/tests/testdata/ziptest_valid.zip Binary files differnew file mode 100644 index 000000000..9e7cb7800 --- /dev/null +++ b/tests/testdata/ziptest_valid.zip diff --git a/tests/unit/recovery_test.cpp b/tests/unit/recovery_test.cpp index f397f258e..28b845fb9 100644 --- a/tests/unit/recovery_test.cpp +++ b/tests/unit/recovery_test.cpp @@ -21,7 +21,6 @@ #include <android/log.h> #include <gtest/gtest.h> -#include <log/logger.h> #include <private/android_logger.h> static const char myFilename[] = "/data/misc/recovery/inject.txt"; diff --git a/tests/unit/zip_test.cpp b/tests/unit/zip_test.cpp new file mode 100644 index 000000000..b617446b8 --- /dev/null +++ b/tests/unit/zip_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <unistd.h> + +#include <memory> +#include <vector> + +#include <android-base/file.h> +#include <android-base/stringprintf.h> +#include <android-base/unique_fd.h> +#include <android-base/test_utils.h> +#include <gtest/gtest.h> +#include <otautil/SysUtil.h> +#include <otautil/ZipUtil.h> +#include <ziparchive/zip_archive.h> + +static const std::string DATA_PATH(getenv("ANDROID_DATA")); +static const std::string TESTDATA_PATH("/recovery/testdata/"); + +static const std::vector<uint8_t> kATxtContents { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + '\n' +}; + +static const std::vector<uint8_t> kBTxtContents { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + '\n' +}; + +TEST(otazip, ExtractPackageRecursive) { + TemporaryDir td; + ASSERT_NE(td.path, nullptr); + ZipArchiveHandle handle; + std::string zip_path = DATA_PATH + TESTDATA_PATH + "/ziptest_valid.zip"; + ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle)); + // Extract the whole package into a temp directory. + ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr); + // Make sure all the files are extracted correctly. + std::string path(td.path); + android::base::unique_fd fd(open((path + "/a.txt").c_str(), O_RDONLY)); + ASSERT_NE(fd, -1); + std::vector<uint8_t> read_data; + read_data.resize(kATxtContents.size()); + // The content of the file is the same as expected. + ASSERT_TRUE(android::base::ReadFully(fd.get(), read_data.data(), read_data.size())); + ASSERT_EQ(0, memcmp(read_data.data(), kATxtContents.data(), kATxtContents.size())); + + fd.reset(open((path + "/b.txt").c_str(), O_RDONLY)); + ASSERT_NE(fd, -1); + fd.reset(open((path + "/b/c.txt").c_str(), O_RDONLY)); + ASSERT_NE(fd, -1); + fd.reset(open((path + "/b/d.txt").c_str(), O_RDONLY)); + ASSERT_NE(fd, -1); + read_data.resize(kBTxtContents.size()); + ASSERT_TRUE(android::base::ReadFully(fd.get(), read_data.data(), read_data.size())); + ASSERT_EQ(0, memcmp(read_data.data(), kBTxtContents.data(), kBTxtContents.size())); +} + +TEST(otazip, OpenFromMemory) { + MemMapping map; + std::string zip_path = DATA_PATH + TESTDATA_PATH + "/ziptest_dummy-update.zip"; + ASSERT_EQ(0, sysMapFile(zip_path.c_str(), &map)); + // Map an update package into memory and open the archive from there. + ZipArchiveHandle handle; + ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_path.c_str(), &handle)); + static constexpr const char* BINARY_PATH = "META-INF/com/google/android/update-binary"; + ZipString binary_path(BINARY_PATH); + ZipEntry binary_entry; + // Make sure the package opens correctly and its entry can be read. + ASSERT_EQ(0, FindEntry(handle, binary_path, &binary_entry)); + TemporaryFile tmp_binary; + ASSERT_NE(-1, tmp_binary.fd); + ASSERT_EQ(0, ExtractEntryToFile(handle, &binary_entry, tmp_binary.fd)); +} + diff --git a/tools/ota/Android.mk b/tools/dumpkey/Android.mk index 142c3b257..31549146d 100644 --- a/tools/ota/Android.mk +++ b/tools/dumpkey/Android.mk @@ -15,19 +15,8 @@ LOCAL_PATH := $(call my-dir) 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) +LOCAL_MODULE := dumpkey +LOCAL_SRC_FILES := DumpPublicKey.java +LOCAL_JAR_MANIFEST := DumpPublicKey.mf +LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host +include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/tools/dumpkey/DumpPublicKey.java b/tools/dumpkey/DumpPublicKey.java new file mode 100644 index 000000000..3eb139842 --- /dev/null +++ b/tools/dumpkey/DumpPublicKey.java @@ -0,0 +1,270 @@ +/* + * 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. + */ + +package com.android.dumpkey; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.io.FileInputStream; +import java.math.BigInteger; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.KeyStore; +import java.security.Key; +import java.security.PublicKey; +import java.security.Security; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.ECPoint; + +/** + * Command line tool to extract RSA public keys from X.509 certificates + * and output source code with data initializers for the keys. + * @hide + */ +class DumpPublicKey { + /** + * @param key to perform sanity checks on + * @return version number of key. Supported versions are: + * 1: 2048-bit RSA key with e=3 and SHA-1 hash + * 2: 2048-bit RSA key with e=65537 and SHA-1 hash + * 3: 2048-bit RSA key with e=3 and SHA-256 hash + * 4: 2048-bit RSA key with e=65537 and SHA-256 hash + * @throws Exception if the key has the wrong size or public exponent + */ + static int checkRSA(RSAPublicKey key, boolean useSHA256) throws Exception { + BigInteger pubexp = key.getPublicExponent(); + BigInteger modulus = key.getModulus(); + int version; + + if (pubexp.equals(BigInteger.valueOf(3))) { + version = useSHA256 ? 3 : 1; + } else if (pubexp.equals(BigInteger.valueOf(65537))) { + version = useSHA256 ? 4 : 2; + } else { + throw new Exception("Public exponent should be 3 or 65537 but is " + + pubexp.toString(10) + "."); + } + + if (modulus.bitLength() != 2048) { + throw new Exception("Modulus should be 2048 bits long but is " + + modulus.bitLength() + " bits."); + } + + return version; + } + + /** + * @param key to perform sanity checks on + * @return version number of key. Supported versions are: + * 5: 256-bit EC key with curve NIST P-256 + * @throws Exception if the key has the wrong size or public exponent + */ + static int checkEC(ECPublicKey key) throws Exception { + if (key.getParams().getCurve().getField().getFieldSize() != 256) { + throw new Exception("Curve must be NIST P-256"); + } + + return 5; + } + + /** + * Perform sanity check on public key. + */ + static int check(PublicKey key, boolean useSHA256) throws Exception { + if (key instanceof RSAPublicKey) { + return checkRSA((RSAPublicKey) key, useSHA256); + } else if (key instanceof ECPublicKey) { + if (!useSHA256) { + throw new Exception("Must use SHA-256 with EC keys!"); + } + return checkEC((ECPublicKey) key); + } else { + throw new Exception("Unsupported key class: " + key.getClass().getName()); + } + } + + /** + * @param key to output + * @return a String representing this public key. If the key is a + * version 1 key, the string will be a C initializer; this is + * not true for newer key versions. + */ + static String printRSA(RSAPublicKey key, boolean useSHA256) throws Exception { + int version = check(key, useSHA256); + + BigInteger N = key.getModulus(); + + StringBuilder result = new StringBuilder(); + + int nwords = N.bitLength() / 32; // # of 32 bit integers in modulus + + if (version > 1) { + result.append("v"); + result.append(Integer.toString(version)); + result.append(" "); + } + + result.append("{"); + result.append(nwords); + + BigInteger B = BigInteger.valueOf(0x100000000L); // 2^32 + BigInteger N0inv = B.subtract(N.modInverse(B)); // -1 / N[0] mod 2^32 + + result.append(",0x"); + result.append(N0inv.toString(16)); + + BigInteger R = BigInteger.valueOf(2).pow(N.bitLength()); + BigInteger RR = R.multiply(R).mod(N); // 2^4096 mod N + + // Write out modulus as little endian array of integers. + result.append(",{"); + for (int i = 0; i < nwords; ++i) { + long n = N.mod(B).longValue(); + result.append(n); + + if (i != nwords - 1) { + result.append(","); + } + + N = N.divide(B); + } + result.append("}"); + + // Write R^2 as little endian array of integers. + result.append(",{"); + for (int i = 0; i < nwords; ++i) { + long rr = RR.mod(B).longValue(); + result.append(rr); + + if (i != nwords - 1) { + result.append(","); + } + + RR = RR.divide(B); + } + result.append("}"); + + result.append("}"); + return result.toString(); + } + + /** + * @param key to output + * @return a String representing this public key. If the key is a + * version 1 key, the string will be a C initializer; this is + * not true for newer key versions. + */ + static String printEC(ECPublicKey key) throws Exception { + int version = checkEC(key); + + StringBuilder result = new StringBuilder(); + + result.append("v"); + result.append(Integer.toString(version)); + result.append(" "); + + BigInteger X = key.getW().getAffineX(); + BigInteger Y = key.getW().getAffineY(); + int nbytes = key.getParams().getCurve().getField().getFieldSize() / 8; // # of 32 bit integers in X coordinate + + result.append("{"); + result.append(nbytes); + + BigInteger B = BigInteger.valueOf(0x100L); // 2^8 + + // Write out Y coordinate as array of characters. + result.append(",{"); + for (int i = 0; i < nbytes; ++i) { + long n = X.mod(B).longValue(); + result.append(n); + + if (i != nbytes - 1) { + result.append(","); + } + + X = X.divide(B); + } + result.append("}"); + + // Write out Y coordinate as array of characters. + result.append(",{"); + for (int i = 0; i < nbytes; ++i) { + long n = Y.mod(B).longValue(); + result.append(n); + + if (i != nbytes - 1) { + result.append(","); + } + + Y = Y.divide(B); + } + result.append("}"); + + result.append("}"); + return result.toString(); + } + + static String print(PublicKey key, boolean useSHA256) throws Exception { + if (key instanceof RSAPublicKey) { + return printRSA((RSAPublicKey) key, useSHA256); + } else if (key instanceof ECPublicKey) { + return printEC((ECPublicKey) key); + } else { + throw new Exception("Unsupported key class: " + key.getClass().getName()); + } + } + + public static void main(String[] args) { + if (args.length < 1) { + System.err.println("Usage: DumpPublicKey certfile ... > source.c"); + System.exit(1); + } + Security.addProvider(new BouncyCastleProvider()); + try { + for (int i = 0; i < args.length; i++) { + FileInputStream input = new FileInputStream(args[i]); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate) cf.generateCertificate(input); + + boolean useSHA256 = false; + String sigAlg = cert.getSigAlgName(); + if ("SHA1withRSA".equals(sigAlg) || "MD5withRSA".equals(sigAlg)) { + // SignApk has historically accepted "MD5withRSA" + // certificates, but treated them as "SHA1withRSA" + // anyway. Continue to do so for backwards + // compatibility. + useSHA256 = false; + } else if ("SHA256withRSA".equals(sigAlg) || "SHA256withECDSA".equals(sigAlg)) { + useSHA256 = true; + } else { + System.err.println(args[i] + ": unsupported signature algorithm \"" + + sigAlg + "\""); + System.exit(1); + } + + PublicKey key = cert.getPublicKey(); + check(key, useSHA256); + System.out.print(print(key, useSHA256)); + System.out.println(i < args.length - 1 ? "," : ""); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + System.exit(0); + } +} diff --git a/tools/dumpkey/DumpPublicKey.mf b/tools/dumpkey/DumpPublicKey.mf new file mode 100644 index 000000000..7bb3bc88d --- /dev/null +++ b/tools/dumpkey/DumpPublicKey.mf @@ -0,0 +1 @@ +Main-Class: com.android.dumpkey.DumpPublicKey diff --git a/tools/ota/add-property-tag.c b/tools/ota/add-property-tag.c deleted file mode 100644 index aab30b2d0..000000000 --- a/tools/ota/add-property-tag.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* - * Append a tag to a property value in a .prop file if it isn't already there. - * Normally used to modify build properties to record incremental updates. - */ - -// Return nonzero if the tag should be added to this line. -int should_tag(const char *line, const char *propname) { - const char *prop = strstr(line, propname); - if (prop == NULL) return 0; - - // Make sure this is actually the property name (not an accidental hit) - const char *ptr; - for (ptr = line; ptr < prop && isspace(*ptr); ++ptr) ; - if (ptr != prop) return 0; // Must be at the beginning of the line - - for (ptr += strlen(propname); *ptr != '\0' && isspace(*ptr); ++ptr) ; - return (*ptr == '='); // Must be followed by a '=' -} - -// Remove existing tags from the line, return the following number (if any) -int remove_tag(char *line, const char *tag) { - char *pos = strstr(line, tag); - if (pos == NULL) return 0; - - char *end; - int num = strtoul(pos + strlen(tag), &end, 10); - strcpy(pos, end); - return num; -} - -// Write line to output with the tag added, adding a number (if >0) -void write_tagged(FILE *out, const char *line, const char *tag, int number) { - const char *end = line + strlen(line); - while (end > line && isspace(end[-1])) --end; - if (number > 0) { - fprintf(out, "%.*s%s%d%s", (int)(end - line), line, tag, number, end); - } else { - fprintf(out, "%.*s%s%s", (int)(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 8ce12d39f..000000000 --- a/tools/ota/check-lost+found.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/klog.h> -#include <sys/reboot.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#include "private/android_filesystem_config.h" - -// Sentinel file used to track whether we've forced a reboot -static const char *kMarkerFile = "/data/misc/check-lost+found-rebooted-2"; - -// Output file in tombstones directory (first 8K will be uploaded) -static const char *kOutputDir = "/data/tombstones"; -static const char *kOutputFile = "/data/tombstones/check-lost+found-log"; - -// Partitions to check -static const char *kPartitions[] = { "/system", "/data", "/cache", NULL }; - -/* - * 1. If /data/misc/forced-reboot is missing, touch it & force "unclean" boot. - * 2. Write a log entry with the number of files in lost+found directories. - */ - -int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) { - 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. - TEMP_FAILURE_RETRY(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 446c09da8..000000000 --- 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/recovery_l10n/README.md b/tools/recovery_l10n/README.md new file mode 100644 index 000000000..1554f6618 --- /dev/null +++ b/tools/recovery_l10n/README.md @@ -0,0 +1,33 @@ +# Steps to regenerate background text images under res-*dpi/images/ + +1. Build the recovery_l10n app: + + cd bootable/recovery && mma -j32 + +2. Install the app on the device (or emulator) with the intended dpi. + + * For example, we can use Nexus 5 to generate the text images under + res-xxhdpi. + * When using the emulator, make sure the NDK version matches the current + repository. Otherwise, the app may not work properly. + + adb install $PATH_TO_APP + +3. Run the app, select the string to translate and press the 'go' button. + +4. After the app goes through the strings for all locales, pull the output png + file from the device. + + adb root && adb pull /data/data/com.android.recovery_l10n/files/text-out.png + +5. Compress the output file put it under the corresponding directory. + + * "pngcrush -c 0 ..." converts "text-out.png" into a 1-channel image, + which is accepted by Recovery. This also compresses the image file by + ~60%. + * zopflipng could further compress the png files by ~10%, more details + in https://github.com/google/zopfli/blob/master/README.zopflipng + * If you're using other png compression tools, make sure the final text + image works by running graphic tests under the recovery mode. + + pngcrush -c 0 text-out.png $OUTPUT_PNG diff --git a/tools/recovery_l10n/res/values-af/strings.xml b/tools/recovery_l10n/res/values-af/strings.xml index b1974da20..d5264184a 100644 --- a/tools/recovery_l10n/res/values-af/strings.xml +++ b/tools/recovery_l10n/res/values-af/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installeer tans stelselopdatering"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Vee tans uit"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Geen opdrag nie"</string> - <string name="recovery_error" msgid="5748178989622716736">"Fout!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installeer tans sekuriteitopdatering"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installeer tans stelselopdatering..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Vee tans uit..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Geen bevel."</string> + <string name="recovery_error" msgid="4550265746256727080">"Fout!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-am/strings.xml b/tools/recovery_l10n/res/values-am/strings.xml index 75c17fbad..cddb099bc 100644 --- a/tools/recovery_l10n/res/values-am/strings.xml +++ b/tools/recovery_l10n/res/values-am/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"የሥርዓት ዝማኔን በመጫን ላይ…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"በመደምሰስ ላይ"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ምንም ትዕዛዝ የለም"</string> - <string name="recovery_error" msgid="5748178989622716736">"ስህተት!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"የደህንነት ዝማኔ በመጫን ላይ"</string> + <string name="recovery_installing" msgid="7864047928003865598">"የስርዓት ዝማኔ በመጫን ላይ…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"በመደምሰስ ላይ…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ምንም ትዕዛዝ የለም።"</string> + <string name="recovery_error" msgid="4550265746256727080">"ስህተት!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ar/strings.xml b/tools/recovery_l10n/res/values-ar/strings.xml index 601b5832b..d06b96644 100644 --- a/tools/recovery_l10n/res/values-ar/strings.xml +++ b/tools/recovery_l10n/res/values-ar/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"جارٍ تثبيت تحديث النظام"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"جارٍ محو البيانات"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ليس هناك أي أمر"</string> - <string name="recovery_error" msgid="5748178989622716736">"خطأ!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"جارٍ تثبيت تحديث الأمان"</string> + <string name="recovery_installing" msgid="7864047928003865598">"جارٍ تثبيت تحديث النظام…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"جارٍ المسح…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ليس هناك أي أمر."</string> + <string name="recovery_error" msgid="4550265746256727080">"خطأ!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-az-rAZ/strings.xml b/tools/recovery_l10n/res/values-az-rAZ/strings.xml index c6765a9ea..3435573dc 100644 --- a/tools/recovery_l10n/res/values-az-rAZ/strings.xml +++ b/tools/recovery_l10n/res/values-az-rAZ/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Sistem güncəlləməsi quraşdırılır..."</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Silinir"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Əmr yoxdur"</string> - <string name="recovery_error" msgid="5748178989622716736">"Xəta!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Təhlükəsizlik güncəlləməsi yüklənir"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Sistem güncəlləməsi quraşdırılır..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Silinir..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Əmr yoxdur."</string> + <string name="recovery_error" msgid="4550265746256727080">"Xəta!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index c2d8f2239..000000000 --- a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Ažuriranje sistema se instalira"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Briše se"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nema komande"</string> - <string name="recovery_error" msgid="5748178989622716736">"Greška!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalira se bezbednosno ažuriranje"</string> -</resources> diff --git a/tools/recovery_l10n/res/values-be-rBY/strings.xml b/tools/recovery_l10n/res/values-be-rBY/strings.xml deleted file mode 100644 index 7c0954d31..000000000 --- a/tools/recovery_l10n/res/values-be-rBY/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Усталёўка абнаўлення сістэмы"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Сціранне"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Няма каманды"</string> - <string name="recovery_error" msgid="5748178989622716736">"Памылка"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Усталёўка абнаўлення сістэмы бяспекі"</string> -</resources> diff --git a/tools/recovery_l10n/res/values-bg/strings.xml b/tools/recovery_l10n/res/values-bg/strings.xml index 9e628a2af..004f3b93e 100644 --- a/tools/recovery_l10n/res/values-bg/strings.xml +++ b/tools/recovery_l10n/res/values-bg/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Системната актуализация се инсталира"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Изтрива се"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Без команда"</string> - <string name="recovery_error" msgid="5748178989622716736">"Грешка!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Актуализацията на сигурносттa се инсталира"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Системната актуализация се инсталира…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Изтрива се…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Без команда."</string> + <string name="recovery_error" msgid="4550265746256727080">"Грешка!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-bn-rBD/strings.xml b/tools/recovery_l10n/res/values-bn-rBD/strings.xml index 0a481faf1..4d2e590f4 100644 --- a/tools/recovery_l10n/res/values-bn-rBD/strings.xml +++ b/tools/recovery_l10n/res/values-bn-rBD/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"সিস্টেম আপডেট ইনস্টল করা হচ্ছে"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"মোছা হচ্ছে"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"কোনো আদেশ নেই"</string> - <string name="recovery_error" msgid="5748178989622716736">"ত্রুটি!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"নিরাপত্তার আপডেট ইনস্টল করা হচ্ছে"</string> + <string name="recovery_installing" msgid="7864047928003865598">"সিস্টেম আপডেট ইনস্টল করা হচ্ছে…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"মোছা হচ্ছে…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"কোনো নির্দেশ নেই।"</string> + <string name="recovery_error" msgid="4550265746256727080">"ত্রুটি!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-bs-rBA/strings.xml b/tools/recovery_l10n/res/values-bs-rBA/strings.xml deleted file mode 100644 index 412cf0276..000000000 --- a/tools/recovery_l10n/res/values-bs-rBA/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Ažuriranje sistema…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Brisanje u toku"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nema komande"</string> - <string name="recovery_error" msgid="5748178989622716736">"Greška!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instaliranje sigurnosnog ažuriranja…"</string> -</resources> diff --git a/tools/recovery_l10n/res/values-ca/strings.xml b/tools/recovery_l10n/res/values-ca/strings.xml index 3f266d2df..5d7b652c5 100644 --- a/tools/recovery_l10n/res/values-ca/strings.xml +++ b/tools/recovery_l10n/res/values-ca/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"S\'està instal·lant una actualització del sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"S\'està esborrant"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"No hi ha cap ordre"</string> - <string name="recovery_error" msgid="5748178989622716736">"S\'ha produït un error"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"S\'està instal·lant una actualització de seguretat"</string> + <string name="recovery_installing" msgid="7864047928003865598">"S\'està instal·lant l\'actualització del sistema..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"S\'està esborrant..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Cap ordre."</string> + <string name="recovery_error" msgid="4550265746256727080">"Error!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-cs/strings.xml b/tools/recovery_l10n/res/values-cs/strings.xml index eb436a810..771235d04 100644 --- a/tools/recovery_l10n/res/values-cs/strings.xml +++ b/tools/recovery_l10n/res/values-cs/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalace aktualizace systému"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Mazání"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Žádný příkaz"</string> - <string name="recovery_error" msgid="5748178989622716736">"Chyba!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalace aktualizace zabezpečení"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalace aktualizace systému..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Mazání…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Žádný příkaz."</string> + <string name="recovery_error" msgid="4550265746256727080">"Chyba!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-da/strings.xml b/tools/recovery_l10n/res/values-da/strings.xml index c6e64a245..c28a76fbd 100644 --- a/tools/recovery_l10n/res/values-da/strings.xml +++ b/tools/recovery_l10n/res/values-da/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installerer systemopdateringen"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Sletter"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ingen kommando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Fejl!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installerer sikkerhedsopdateringen"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Systemopdateringen installeres…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Sletter…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ingen kommando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Fejl!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-de/strings.xml b/tools/recovery_l10n/res/values-de/strings.xml index 6b6726a23..02d259059 100644 --- a/tools/recovery_l10n/res/values-de/strings.xml +++ b/tools/recovery_l10n/res/values-de/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Systemupdate wird installiert"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Wird gelöscht"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Kein Befehl"</string> - <string name="recovery_error" msgid="5748178989622716736">"Fehler"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Sicherheitsupdate wird installiert"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Systemupdate wird installiert…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Wird gelöscht…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Kein Befehl"</string> + <string name="recovery_error" msgid="4550265746256727080">"Fehler"</string> </resources> diff --git a/tools/recovery_l10n/res/values-el/strings.xml b/tools/recovery_l10n/res/values-el/strings.xml index 4cb2da5f9..aa2626b4b 100644 --- a/tools/recovery_l10n/res/values-el/strings.xml +++ b/tools/recovery_l10n/res/values-el/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Εγκατάσταση ενημέρωσης συστήματος"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Διαγραφή"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Καμία εντολή"</string> - <string name="recovery_error" msgid="5748178989622716736">"Σφάλμα!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Εγκατάσταση ενημέρωσης ασφαλείας"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Εγκατάσταση ενημέρωσης συστήματος…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Διαγραφή…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Καμία εντολή."</string> + <string name="recovery_error" msgid="4550265746256727080">"Σφάλμα!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-en-rAU/strings.xml b/tools/recovery_l10n/res/values-en-rAU/strings.xml index dc75c2374..b70d678c1 100644 --- a/tools/recovery_l10n/res/values-en-rAU/strings.xml +++ b/tools/recovery_l10n/res/values-en-rAU/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installing system update"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installing system update…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Erasing…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"No command."</string> + <string name="recovery_error" msgid="4550265746256727080">"Error!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-en-rGB/strings.xml b/tools/recovery_l10n/res/values-en-rGB/strings.xml index dc75c2374..b70d678c1 100644 --- a/tools/recovery_l10n/res/values-en-rGB/strings.xml +++ b/tools/recovery_l10n/res/values-en-rGB/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installing system update"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installing system update…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Erasing…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"No command."</string> + <string name="recovery_error" msgid="4550265746256727080">"Error!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-en-rIN/strings.xml b/tools/recovery_l10n/res/values-en-rIN/strings.xml index dc75c2374..b70d678c1 100644 --- a/tools/recovery_l10n/res/values-en-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-en-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installing system update"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installing system update…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Erasing…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"No command."</string> + <string name="recovery_error" msgid="4550265746256727080">"Error!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-es-rUS/strings.xml b/tools/recovery_l10n/res/values-es-rUS/strings.xml index 06b86069b..256272ac7 100644 --- a/tools/recovery_l10n/res/values-es-rUS/strings.xml +++ b/tools/recovery_l10n/res/values-es-rUS/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalando actualización del sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Borrando"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ningún comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando actualización de seguridad"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalando actualización del sistema…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Borrando…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ningún comando"</string> + <string name="recovery_error" msgid="4550265746256727080">"Error"</string> </resources> diff --git a/tools/recovery_l10n/res/values-es/strings.xml b/tools/recovery_l10n/res/values-es/strings.xml index d8618f2f4..323f05505 100644 --- a/tools/recovery_l10n/res/values-es/strings.xml +++ b/tools/recovery_l10n/res/values-es/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalando actualización del sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Borrando"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Sin comandos"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando actualización de seguridad"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalando actualización del sistema…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Borrando…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Sin comandos"</string> + <string name="recovery_error" msgid="4550265746256727080">"Error"</string> </resources> diff --git a/tools/recovery_l10n/res/values-et-rEE/strings.xml b/tools/recovery_l10n/res/values-et-rEE/strings.xml index 072a9ef80..407a53d67 100644 --- a/tools/recovery_l10n/res/values-et-rEE/strings.xml +++ b/tools/recovery_l10n/res/values-et-rEE/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Süsteemivärskenduse installimine"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Kustutamine"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Käsk puudub"</string> - <string name="recovery_error" msgid="5748178989622716736">"Viga!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Turvavärskenduse installimine"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Süsteemivärskenduste installimine ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Kustutamine ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Käsk puudub."</string> + <string name="recovery_error" msgid="4550265746256727080">"Viga!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-eu-rES/strings.xml b/tools/recovery_l10n/res/values-eu-rES/strings.xml index 5540469d0..08d9c0672 100644 --- a/tools/recovery_l10n/res/values-eu-rES/strings.xml +++ b/tools/recovery_l10n/res/values-eu-rES/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Sistemaren eguneratzea instalatzen"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Eduki guztia ezabatzen"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ez dago agindurik"</string> - <string name="recovery_error" msgid="5748178989622716736">"Errorea"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Segurtasun-eguneratzea instalatzen"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Sistemaren eguneratzea instalatzen…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Ezabatzen…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ez dago agindurik."</string> + <string name="recovery_error" msgid="4550265746256727080">"Errorea!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-fa/strings.xml b/tools/recovery_l10n/res/values-fa/strings.xml index cc390ae84..dd002face 100644 --- a/tools/recovery_l10n/res/values-fa/strings.xml +++ b/tools/recovery_l10n/res/values-fa/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"در حال نصب بهروزرسانی سیستم"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"در حال پاک کردن"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"فرمانی وجود ندارد"</string> - <string name="recovery_error" msgid="5748178989622716736">"خطا!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"در حال نصب بهروزرسانی امنیتی"</string> + <string name="recovery_installing" msgid="7864047928003865598">"در حال نصب بهروزرسانی سیستم ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"پاک کردن..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"فرمانی موجود نیست."</string> + <string name="recovery_error" msgid="4550265746256727080">"خطا!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-fi/strings.xml b/tools/recovery_l10n/res/values-fi/strings.xml index 5141642c8..b77417a98 100644 --- a/tools/recovery_l10n/res/values-fi/strings.xml +++ b/tools/recovery_l10n/res/values-fi/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Asennetaan järjestelmäpäivitystä"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Tyhjennetään"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ei komentoa"</string> - <string name="recovery_error" msgid="5748178989622716736">"Virhe!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Asennetaan tietoturvapäivitystä"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Asennetaan järjestelmäpäivitystä..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Tyhjennetään..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ei komentoa."</string> + <string name="recovery_error" msgid="4550265746256727080">"Virhe!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-fr-rCA/strings.xml b/tools/recovery_l10n/res/values-fr-rCA/strings.xml index b2415290b..f2a85d86a 100644 --- a/tools/recovery_l10n/res/values-fr-rCA/strings.xml +++ b/tools/recovery_l10n/res/values-fr-rCA/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installation de la mise à jour du système en cours…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Suppression en cours..."</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Aucune commande"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erreur!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installation de la mise à jour de sécurité en cours..."</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installation de la mise à jour du système en cours…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Effacement en cours…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Aucune commande."</string> + <string name="recovery_error" msgid="4550265746256727080">"Erreur!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-fr/strings.xml b/tools/recovery_l10n/res/values-fr/strings.xml index f0472b5ac..cdb4a2668 100644 --- a/tools/recovery_l10n/res/values-fr/strings.xml +++ b/tools/recovery_l10n/res/values-fr/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installation de la mise à jour du système…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Suppression…"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Aucune commande"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erreur !"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installation de la mise à jour de sécurité…"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installation de la mise à jour du système en cours…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Effacement en cours…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Aucune commande."</string> + <string name="recovery_error" msgid="4550265746256727080">"Erreur !"</string> </resources> diff --git a/tools/recovery_l10n/res/values-gl-rES/strings.xml b/tools/recovery_l10n/res/values-gl-rES/strings.xml index 42b2016c2..7546fbda4 100644 --- a/tools/recovery_l10n/res/values-gl-rES/strings.xml +++ b/tools/recovery_l10n/res/values-gl-rES/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalando actualización do sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Borrando"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Non hai ningún comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erro"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando actualización de seguranza"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalando actualización do sistema..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Borrando..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ningún comando"</string> + <string name="recovery_error" msgid="4550265746256727080">"Erro"</string> </resources> diff --git a/tools/recovery_l10n/res/values-gu-rIN/strings.xml b/tools/recovery_l10n/res/values-gu-rIN/strings.xml index 2355a0f4f..a364b523c 100644 --- a/tools/recovery_l10n/res/values-gu-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-gu-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"સિસ્ટમ અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"કાઢી નાખી રહ્યું છે"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"કોઈ આદેશ નથી"</string> - <string name="recovery_error" msgid="5748178989622716736">"ભૂલ!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"સુરક્ષા અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે"</string> + <string name="recovery_installing" msgid="7864047928003865598">"સિસ્ટમ અપડેટ ઇન્સ્ટોલ કરી રહ્યાં છે…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"કાઢી નાખી રહ્યાં છે…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"કોઈ આદેશ નથી."</string> + <string name="recovery_error" msgid="4550265746256727080">"ભૂલ!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-hi/strings.xml b/tools/recovery_l10n/res/values-hi/strings.xml index de8757848..a470d12b6 100644 --- a/tools/recovery_l10n/res/values-hi/strings.xml +++ b/tools/recovery_l10n/res/values-hi/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"सिस्टम अपडेट इंस्टॉल किया जा रहा है"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"मिटाया जा रहा है"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"कोई आदेश नहीं"</string> - <string name="recovery_error" msgid="5748178989622716736">"त्रुटि!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"सुरक्षा अपडेट इंस्टॉल किया जा रहा है"</string> + <string name="recovery_installing" msgid="7864047928003865598">"सिस्टम के बारे में नई जानकारी मिल रही है…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"मिटा रहा है…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"कोई आदेश नहीं."</string> + <string name="recovery_error" msgid="4550265746256727080">"त्रुटि!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-hr/strings.xml b/tools/recovery_l10n/res/values-hr/strings.xml index 3b75ff115..56225c015 100644 --- a/tools/recovery_l10n/res/values-hr/strings.xml +++ b/tools/recovery_l10n/res/values-hr/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instaliranje ažuriranja sustava"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Brisanje"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nema naredbe"</string> - <string name="recovery_error" msgid="5748178989622716736">"Pogreška!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instaliranje sigurnosnog ažuriranja"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instaliranje ažuriranja sustava…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Brisanje…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nema naredbe."</string> + <string name="recovery_error" msgid="4550265746256727080">"Pogreška!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-hu/strings.xml b/tools/recovery_l10n/res/values-hu/strings.xml index 12d4d9fe7..a64f50176 100644 --- a/tools/recovery_l10n/res/values-hu/strings.xml +++ b/tools/recovery_l10n/res/values-hu/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Rendszerfrissítés telepítése"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Törlés"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nincs parancs"</string> - <string name="recovery_error" msgid="5748178989622716736">"Hiba!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Biztonsági frissítés telepítése"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Rendszerfrissítés telepítése..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Törlés..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nincs parancs."</string> + <string name="recovery_error" msgid="4550265746256727080">"Hiba!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-hy-rAM/strings.xml b/tools/recovery_l10n/res/values-hy-rAM/strings.xml index 9d62bb763..7babe80c8 100644 --- a/tools/recovery_l10n/res/values-hy-rAM/strings.xml +++ b/tools/recovery_l10n/res/values-hy-rAM/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Համակարգի թարմացման տեղադրում"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Ջնջում"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Հրամանը տրված չէ"</string> - <string name="recovery_error" msgid="5748178989622716736">"Սխալ"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Անվտանգության թարմացման տեղադրում"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Համակարգի թարմացման տեղադրում…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Ջնջում…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Հրամանը տրված չէ:"</string> + <string name="recovery_error" msgid="4550265746256727080">"Սխալ"</string> </resources> diff --git a/tools/recovery_l10n/res/values-in/strings.xml b/tools/recovery_l10n/res/values-in/strings.xml index 0e56e0dd9..93f9c2876 100644 --- a/tools/recovery_l10n/res/values-in/strings.xml +++ b/tools/recovery_l10n/res/values-in/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Memasang pembaruan sistem"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Menghapus"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Tidak ada perintah"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Memasang pembaruan keamanan"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Memasang pembaruan sistem…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Menghapus..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Tidak ada perintah."</string> + <string name="recovery_error" msgid="4550265746256727080">"Kesalahan!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-is-rIS/strings.xml b/tools/recovery_l10n/res/values-is-rIS/strings.xml index 5065b6522..926e85132 100644 --- a/tools/recovery_l10n/res/values-is-rIS/strings.xml +++ b/tools/recovery_l10n/res/values-is-rIS/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Setur upp kerfisuppfærslu"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Eyðir"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Engin skipun"</string> - <string name="recovery_error" msgid="5748178989622716736">"Villa!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Setur upp öryggisuppfærslu"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Setur upp kerfisuppfærslu…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Þurrkar út…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Engin skipun."</string> + <string name="recovery_error" msgid="4550265746256727080">"Villa!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-it/strings.xml b/tools/recovery_l10n/res/values-it/strings.xml index 2c0364e60..9defe36bd 100644 --- a/tools/recovery_l10n/res/values-it/strings.xml +++ b/tools/recovery_l10n/res/values-it/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installazione aggiornamento di sistema…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Cancellazione…"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nessun comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Errore!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installazione aggiornamento sicurezza…"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installazione aggiornamento di sistema…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Cancellazione…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nessun comando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Errore!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-iw/strings.xml b/tools/recovery_l10n/res/values-iw/strings.xml index ea5e6f2c9..e43bb20a9 100644 --- a/tools/recovery_l10n/res/values-iw/strings.xml +++ b/tools/recovery_l10n/res/values-iw/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"מתקין עדכון מערכת"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"מוחק"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"אין פקודה"</string> - <string name="recovery_error" msgid="5748178989622716736">"שגיאה!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"מתקין עדכון אבטחה"</string> + <string name="recovery_installing" msgid="7864047928003865598">"מתקין עדכון מערכת…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"מוחק…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"אין פקודה."</string> + <string name="recovery_error" msgid="4550265746256727080">"שגיאה!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ja/strings.xml b/tools/recovery_l10n/res/values-ja/strings.xml index 36e029b0f..da0fa623a 100644 --- a/tools/recovery_l10n/res/values-ja/strings.xml +++ b/tools/recovery_l10n/res/values-ja/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"システム アップデートをインストールしています"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"消去しています"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"コマンドが指定されていません"</string> - <string name="recovery_error" msgid="5748178989622716736">"エラーが発生しました。"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"セキュリティ アップデートをインストールしています"</string> + <string name="recovery_installing" msgid="7864047928003865598">"システムアップデートをインストールしています…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"消去しています…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"コマンドが指定されていません。"</string> + <string name="recovery_error" msgid="4550265746256727080">"エラーです"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ka-rGE/strings.xml b/tools/recovery_l10n/res/values-ka-rGE/strings.xml index 6a46b3677..2d27c1799 100644 --- a/tools/recovery_l10n/res/values-ka-rGE/strings.xml +++ b/tools/recovery_l10n/res/values-ka-rGE/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"მიმდინარეობს სისტემის განახლების ინსტალაცია"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"მიმდინარეობს ამოშლა"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ბრძანება არ არის"</string> - <string name="recovery_error" msgid="5748178989622716736">"წარმოიქმნა შეცდომა!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"მიმდინარეობს უსაფრთხოების განახლების ინსტალაცია"</string> + <string name="recovery_installing" msgid="7864047928003865598">"სისტემის განახლების დაყენება…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"მიმდინარეობს წაშლა…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ბრძანება არ არის."</string> + <string name="recovery_error" msgid="4550265746256727080">"შეცდომა!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-kk-rKZ/strings.xml b/tools/recovery_l10n/res/values-kk-rKZ/strings.xml index a4bd86e66..3ca05b9eb 100644 --- a/tools/recovery_l10n/res/values-kk-rKZ/strings.xml +++ b/tools/recovery_l10n/res/values-kk-rKZ/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Жүйе жаңартуы орнатылуда"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Өшірілуде"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Пәрмен жоқ"</string> - <string name="recovery_error" msgid="5748178989622716736">"Қате!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Қауіпсіздік жаңартуы орнатылуда"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Жүйе жаңартуларын орнатуда…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Өшіруде..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Пәрмен берілген жоқ."</string> + <string name="recovery_error" msgid="4550265746256727080">"Қате!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-km-rKH/strings.xml b/tools/recovery_l10n/res/values-km-rKH/strings.xml index 313c0f457..0c1c272e0 100644 --- a/tools/recovery_l10n/res/values-km-rKH/strings.xml +++ b/tools/recovery_l10n/res/values-km-rKH/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"កំពុងអាប់ដេតប្រព័ន្ធ"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"លុប"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"គ្មានពាក្យបញ្ជាទេ"</string> - <string name="recovery_error" msgid="5748178989622716736">"កំហុស!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"កំពុងដំឡើងការអាប់ដេតសុវត្ថិភាព"</string> + <string name="recovery_installing" msgid="7864047928003865598">"កំពុងដំឡើងបច្ចុប្បន្នភាពប្រព័ន្ធ…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"កំពុងលុប…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"គ្មានពាក្យបញ្ជា។"</string> + <string name="recovery_error" msgid="4550265746256727080">"កំហុស!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-kn-rIN/strings.xml b/tools/recovery_l10n/res/values-kn-rIN/strings.xml index 5bf6260ee..be25d7a9d 100644 --- a/tools/recovery_l10n/res/values-kn-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-kn-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"ಸಿಸ್ಟಂ ಅಪ್ಡೇಟ್ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"ಅಳಿಸಲಾಗುತ್ತಿದೆ"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ಯಾವುದೇ ಆದೇಶವಿಲ್ಲ"</string> - <string name="recovery_error" msgid="5748178989622716736">"ದೋಷ!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"ಭದ್ರತೆಯ ಅಪ್ಡೇಟ್ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string> + <string name="recovery_installing" msgid="7864047928003865598">"ಸಿಸ್ಟಂ ನವೀಕರಣವನ್ನು ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"ಅಳಿಸಲಾಗುತ್ತಿದೆ…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ಯಾವುದೇ ಆದೇಶವಿಲ್ಲ."</string> + <string name="recovery_error" msgid="4550265746256727080">"ದೋಷ!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ko/strings.xml b/tools/recovery_l10n/res/values-ko/strings.xml index aca13bbe7..e46a87606 100644 --- a/tools/recovery_l10n/res/values-ko/strings.xml +++ b/tools/recovery_l10n/res/values-ko/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"시스템 업데이트 설치"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"지우는 중"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"명령어 없음"</string> - <string name="recovery_error" msgid="5748178989622716736">"오류!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"보안 업데이트 설치 중"</string> + <string name="recovery_installing" msgid="7864047928003865598">"시스템 업데이트 설치 중…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"지우는 중…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"명령어가 없습니다."</string> + <string name="recovery_error" msgid="4550265746256727080">"오류!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ky-rKG/strings.xml b/tools/recovery_l10n/res/values-ky-rKG/strings.xml index 0a6bd783a..e2ced27a4 100644 --- a/tools/recovery_l10n/res/values-ky-rKG/strings.xml +++ b/tools/recovery_l10n/res/values-ky-rKG/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Тутум жаңыртуусу орнотулууда"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Тазаланууда"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Буйрук берилген жок"</string> - <string name="recovery_error" msgid="5748178989622716736">"Ката!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Коопсуздук жаңыртуусу орнотулууда"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Системдик жаңыртууларды орнотуу…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Өчүрүлүүдө…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Буйрук берилген жок."</string> + <string name="recovery_error" msgid="4550265746256727080">"Ката!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-lo-rLA/strings.xml b/tools/recovery_l10n/res/values-lo-rLA/strings.xml index d3dbb3970..5880cca75 100644 --- a/tools/recovery_l10n/res/values-lo-rLA/strings.xml +++ b/tools/recovery_l10n/res/values-lo-rLA/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"ກຳລັງຕິດຕັ້ງການອັບເດດລະບົບ"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"ກຳລັງລຶບ"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ບໍ່ມີຄຳສັ່ງ"</string> - <string name="recovery_error" msgid="5748178989622716736">"ຜິດພາດ!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"ກຳລັງຕິດຕັ້ງອັບເດດຄວາມປອດໄພ"</string> + <string name="recovery_installing" msgid="7864047928003865598">"ກຳລັງຕິດຕັ້ງການອັບເດດລະບົບ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"ກຳລັງລຶບ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ບໍ່ມີຄຳສັ່ງ."</string> + <string name="recovery_error" msgid="4550265746256727080">"ຜິດພາດ!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-lt/strings.xml b/tools/recovery_l10n/res/values-lt/strings.xml index d5d5e88fd..957ac7557 100644 --- a/tools/recovery_l10n/res/values-lt/strings.xml +++ b/tools/recovery_l10n/res/values-lt/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Diegiamas sistemos naujinys"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Ištrinama"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nėra jokių komandų"</string> - <string name="recovery_error" msgid="5748178989622716736">"Klaida!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Diegiamas saugos naujinys"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Diegiamas sistemos naujinys…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Ištrinama…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nėra komandos."</string> + <string name="recovery_error" msgid="4550265746256727080">"Klaida!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-lv/strings.xml b/tools/recovery_l10n/res/values-lv/strings.xml index d877f6a61..c5d5b93a6 100644 --- a/tools/recovery_l10n/res/values-lv/strings.xml +++ b/tools/recovery_l10n/res/values-lv/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Notiek sistēmas atjauninājuma instalēšana"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Notiek dzēšana"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nav nevienas komandas"</string> - <string name="recovery_error" msgid="5748178989622716736">"Kļūda!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Notiek drošības atjauninājuma instalēšana"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Notiek sistēmas atjauninājuma instalēšana..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Notiek dzēšana..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nav nevienas komandas."</string> + <string name="recovery_error" msgid="4550265746256727080">"Kļūda!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-mk-rMK/strings.xml b/tools/recovery_l10n/res/values-mk-rMK/strings.xml index 351459730..d91a67cac 100644 --- a/tools/recovery_l10n/res/values-mk-rMK/strings.xml +++ b/tools/recovery_l10n/res/values-mk-rMK/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Се инсталира ажурирање на системот"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Се брише"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Нема наредба"</string> - <string name="recovery_error" msgid="5748178989622716736">"Грешка!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Се инсталира безбедносно ажурирање"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Се инсталира ажурирање на системот..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Се брише..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Нема наредба."</string> + <string name="recovery_error" msgid="4550265746256727080">"Грешка!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ml-rIN/strings.xml b/tools/recovery_l10n/res/values-ml-rIN/strings.xml index b506e2530..38ebcd120 100644 --- a/tools/recovery_l10n/res/values-ml-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-ml-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"സിസ്റ്റം അപ്ഡേറ്റ് ഇൻസ്റ്റാൾ ചെയ്യുന്നു"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"മായ്ക്കുന്നു"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"കമാൻഡ് ഒന്നുമില്ല"</string> - <string name="recovery_error" msgid="5748178989622716736">"പിശക്!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"സുരക്ഷാ അപ്ഡേറ്റ് ഇൻസ്റ്റാൾ ചെയ്യുന്നു"</string> + <string name="recovery_installing" msgid="7864047928003865598">"സിസ്റ്റം അപ്ഡേറ്റ് ഇൻസ്റ്റാളുചെയ്യുന്നു…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"മായ്ക്കുന്നു…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"കമാൻഡ് ഒന്നുമില്ല."</string> + <string name="recovery_error" msgid="4550265746256727080">"പിശക്!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-mn-rMN/strings.xml b/tools/recovery_l10n/res/values-mn-rMN/strings.xml index e3dd2e90e..463cafeaf 100644 --- a/tools/recovery_l10n/res/values-mn-rMN/strings.xml +++ b/tools/recovery_l10n/res/values-mn-rMN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Системийн шинэчлэлтийг суулгаж байна"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Устгаж байна"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Тушаал байхгүй"</string> - <string name="recovery_error" msgid="5748178989622716736">"Алдаа!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Аюулгүй байдлын шинэчлэлтийг суулгаж байна"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Системийн шинэчлэлтийг суулгаж байна…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Арилгаж байна…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Команд байхгүй."</string> + <string name="recovery_error" msgid="4550265746256727080">"Алдаа!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-mr-rIN/strings.xml b/tools/recovery_l10n/res/values-mr-rIN/strings.xml index 8cf86f773..25c5d0c57 100644 --- a/tools/recovery_l10n/res/values-mr-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-mr-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"सिस्टम अद्यतन स्थापित करीत आहे"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"मिटवत आहे"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"कोणताही आदेश नाही"</string> - <string name="recovery_error" msgid="5748178989622716736">"त्रुटी!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"सुरक्षा अद्यतन स्थापित करीत आहे"</string> + <string name="recovery_installing" msgid="7864047928003865598">"सिस्टम अद्यतन स्थापित करीत आहे..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"मिटवित आहे…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"कोणताही आदेश नाही."</string> + <string name="recovery_error" msgid="4550265746256727080">"त्रुटी!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ms-rMY/strings.xml b/tools/recovery_l10n/res/values-ms-rMY/strings.xml index 0e24ac4e1..f5635910e 100644 --- a/tools/recovery_l10n/res/values-ms-rMY/strings.xml +++ b/tools/recovery_l10n/res/values-ms-rMY/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Memasang kemas kini sistem"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Memadam"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Tiada perintah"</string> - <string name="recovery_error" msgid="5748178989622716736">"Ralat!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Memasang kemas kini keselamatan"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Memasang kemas kini sistem..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Memadam..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Tiada arahan."</string> + <string name="recovery_error" msgid="4550265746256727080">"Ralat!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-my-rMM/strings.xml b/tools/recovery_l10n/res/values-my-rMM/strings.xml index f13752461..4091b1923 100644 --- a/tools/recovery_l10n/res/values-my-rMM/strings.xml +++ b/tools/recovery_l10n/res/values-my-rMM/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"စနစ်အပ်ဒိတ်ကို ထည့်သွင်းနေသည်"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"ဖျက်နေသည်"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ညွှန်ကြားချက်မပေးထားပါ"</string> - <string name="recovery_error" msgid="5748178989622716736">"မှားနေပါသည်!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"လုံခြုံရေး အပ်ဒိတ်ကို ထည့်သွင်းနေသည်"</string> + <string name="recovery_installing" msgid="7864047928003865598">"စနစ်အား အဆင့်မြှင့်ခြင်း လုပ်ဆောင်နေသည်…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"ဖျက်နေသည် ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ညွှန်ကြားချက်မပေးထားပါ"</string> + <string name="recovery_error" msgid="4550265746256727080">"မှားနေပါသည်!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-nb/strings.xml b/tools/recovery_l10n/res/values-nb/strings.xml index ad6f20e46..4e89ad7c8 100644 --- a/tools/recovery_l10n/res/values-nb/strings.xml +++ b/tools/recovery_l10n/res/values-nb/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Installerer systemoppdateringen"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Tømmer"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ingen kommandoer"</string> - <string name="recovery_error" msgid="5748178989622716736">"Feil!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Installerer sikkerhetsoppdateringen"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installerer systemoppdateringen ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Sletter ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ingen kommando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Feil!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ne-rNP/strings.xml b/tools/recovery_l10n/res/values-ne-rNP/strings.xml index 1880e807b..835f275b4 100644 --- a/tools/recovery_l10n/res/values-ne-rNP/strings.xml +++ b/tools/recovery_l10n/res/values-ne-rNP/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"प्रणालीको अद्यावधिकलाई स्थापना गर्दै"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"मेटाउँदै"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"कुनै आदेश छैन"</string> - <string name="recovery_error" msgid="5748178989622716736">"त्रुटि!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"सुरक्षा सम्बन्धी अद्यावधिकलाई स्थापना गर्दै"</string> + <string name="recovery_installing" msgid="7864047928003865598">"प्रणाली अद्यावधिक स्थापना गर्दै..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"मेटाइदै..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"कुनै आदेश छैन।"</string> + <string name="recovery_error" msgid="4550265746256727080">"त्रुटि!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-nl/strings.xml b/tools/recovery_l10n/res/values-nl/strings.xml index 0d6c15abb..be80a6b5c 100644 --- a/tools/recovery_l10n/res/values-nl/strings.xml +++ b/tools/recovery_l10n/res/values-nl/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Systeemupdate installeren"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Wissen"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Geen opdracht"</string> - <string name="recovery_error" msgid="5748178989622716736">"Fout!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Beveiligingsupdate installeren"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Systeemupdate installeren…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Wissen…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Geen opdracht."</string> + <string name="recovery_error" msgid="4550265746256727080">"Fout!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-pa-rIN/strings.xml b/tools/recovery_l10n/res/values-pa-rIN/strings.xml index 8564c9c36..39ef32f55 100644 --- a/tools/recovery_l10n/res/values-pa-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-pa-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"ਮਿਟਾਈ ਜਾ ਰਹੀ ਹੈ"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ਕੋਈ ਕਮਾਂਡ ਨਹੀਂ"</string> - <string name="recovery_error" msgid="5748178989622716736">"ਅਸ਼ੁੱਧੀ!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> + <string name="recovery_installing" msgid="7864047928003865598">"ਸਿਸਟਮ ਅਪਡੇਟ ਇੰਸਟੌਲ ਕਰ ਰਿਹਾ ਹੈ…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"ਹਟਾ ਰਿਹਾ ਹੈ…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ਕੋਈ ਕਮਾਂਡ ਨਹੀਂ।"</string> + <string name="recovery_error" msgid="4550265746256727080">"ਅਸ਼ੁੱਧੀ!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-pl/strings.xml b/tools/recovery_l10n/res/values-pl/strings.xml index 8d6db388d..b1e5b7b66 100644 --- a/tools/recovery_l10n/res/values-pl/strings.xml +++ b/tools/recovery_l10n/res/values-pl/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instaluję aktualizację systemu"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Kasuję"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Brak polecenia"</string> - <string name="recovery_error" msgid="5748178989622716736">"Błąd"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instaluję aktualizację zabezpieczeń"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instaluję aktualizację systemu…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Usuwam…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Brak polecenia."</string> + <string name="recovery_error" msgid="4550265746256727080">"Błąd"</string> </resources> diff --git a/tools/recovery_l10n/res/values-pt-rBR/strings.xml b/tools/recovery_l10n/res/values-pt-rBR/strings.xml index b72704385..3cc57234e 100644 --- a/tools/recovery_l10n/res/values-pt-rBR/strings.xml +++ b/tools/recovery_l10n/res/values-pt-rBR/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalando atualização do sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Apagando"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nenhum comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erro!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando atualização de segurança"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalando atualização do sistema..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Apagando..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nenhum comando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Erro!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-pt-rPT/strings.xml b/tools/recovery_l10n/res/values-pt-rPT/strings.xml index 981463739..7d6bc18a9 100644 --- a/tools/recovery_l10n/res/values-pt-rPT/strings.xml +++ b/tools/recovery_l10n/res/values-pt-rPT/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"A instalar atualização do sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"A apagar"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nenhum comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erro!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"A instalar atualização de segurança"</string> + <string name="recovery_installing" msgid="7864047928003865598">"A instalar a atualização do sistema..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"A apagar…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nenhum comando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Erro!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-pt/strings.xml b/tools/recovery_l10n/res/values-pt/strings.xml index b72704385..3cc57234e 100644 --- a/tools/recovery_l10n/res/values-pt/strings.xml +++ b/tools/recovery_l10n/res/values-pt/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Instalando atualização do sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Apagando"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nenhum comando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Erro!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando atualização de segurança"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Instalando atualização do sistema..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Apagando..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nenhum comando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Erro!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ro/strings.xml b/tools/recovery_l10n/res/values-ro/strings.xml index 8032865b8..ad924da08 100644 --- a/tools/recovery_l10n/res/values-ro/strings.xml +++ b/tools/recovery_l10n/res/values-ro/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Se instalează actualizarea de sistem"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Se șterge"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nicio comandă"</string> - <string name="recovery_error" msgid="5748178989622716736">"Eroare!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Se instalează actualizarea de securitate"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Se instalează actualizarea de sistem…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Se efectuează ștergerea…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nicio comandă."</string> + <string name="recovery_error" msgid="4550265746256727080">"Eroare!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ru/strings.xml b/tools/recovery_l10n/res/values-ru/strings.xml index feebecf31..de0da4004 100644 --- a/tools/recovery_l10n/res/values-ru/strings.xml +++ b/tools/recovery_l10n/res/values-ru/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Установка обновления системы…"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Удаление…"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Команды нет"</string> - <string name="recovery_error" msgid="5748178989622716736">"Ошибка"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Установка обновления системы безопасности…"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Установка обновления системы…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Удаление…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Команды нет"</string> + <string name="recovery_error" msgid="4550265746256727080">"Ошибка"</string> </resources> diff --git a/tools/recovery_l10n/res/values-si-rLK/strings.xml b/tools/recovery_l10n/res/values-si-rLK/strings.xml index 456cdc567..e717a9762 100644 --- a/tools/recovery_l10n/res/values-si-rLK/strings.xml +++ b/tools/recovery_l10n/res/values-si-rLK/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"පද්ධති යාවත්කාලීනය ස්ථාපනය කරමින්"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"මකමින්"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"විධානයක් නොමැත"</string> - <string name="recovery_error" msgid="5748178989622716736">"දෝෂය!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"ආරක්ෂක යාවත්කාලීනය ස්ථාපනය කරමින්"</string> + <string name="recovery_installing" msgid="7864047928003865598">"පද්ධති යාවත්කාල ස්ථාපනය කරමින්…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"මකමින්...."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"විධානයක් නොමැත."</string> + <string name="recovery_error" msgid="4550265746256727080">"දෝෂය!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sk/strings.xml b/tools/recovery_l10n/res/values-sk/strings.xml index b15f3802b..cae6bce7c 100644 --- a/tools/recovery_l10n/res/values-sk/strings.xml +++ b/tools/recovery_l10n/res/values-sk/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Inštaluje sa aktualizácia systému"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Prebieha vymazávanie"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Žiadny príkaz"</string> - <string name="recovery_error" msgid="5748178989622716736">"Chyba!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Inštaluje sa bezpečnostná aktualizácia"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Inštalácia aktualizácie systému..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Prebieha mazanie..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Žiadny príkaz."</string> + <string name="recovery_error" msgid="4550265746256727080">"Chyba!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sl/strings.xml b/tools/recovery_l10n/res/values-sl/strings.xml index d608b7506..3f8d46fe6 100644 --- a/tools/recovery_l10n/res/values-sl/strings.xml +++ b/tools/recovery_l10n/res/values-sl/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Nameščanje posodobitve sistema"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Brisanje"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Ni ukaza"</string> - <string name="recovery_error" msgid="5748178989622716736">"Napaka"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Nameščanje varnostne posodobitve"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Namestitev posodobitve sistema ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Brisanje ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Ni ukaza"</string> + <string name="recovery_error" msgid="4550265746256727080">"Napaka"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sq-rAL/strings.xml b/tools/recovery_l10n/res/values-sq-rAL/strings.xml index 1156931fb..29f8ef592 100644 --- a/tools/recovery_l10n/res/values-sq-rAL/strings.xml +++ b/tools/recovery_l10n/res/values-sq-rAL/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Po instalon përditësimin e sistemit"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Po spastron"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Nuk ka komanda"</string> - <string name="recovery_error" msgid="5748178989622716736">"Gabim!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Po instalon përditësimin e sigurisë"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Po instalon përditësimin e sistemit..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Po spastron..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Nuk ka komanda."</string> + <string name="recovery_error" msgid="4550265746256727080">"Gabim!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sr/strings.xml b/tools/recovery_l10n/res/values-sr/strings.xml index a593d8faa..955326053 100644 --- a/tools/recovery_l10n/res/values-sr/strings.xml +++ b/tools/recovery_l10n/res/values-sr/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Ажурирање система се инсталира"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Брише се"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Нема команде"</string> - <string name="recovery_error" msgid="5748178989622716736">"Грешка!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Инсталира се безбедносно ажурирање"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Инсталирање ажурирања система..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Брисање..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Нема команде."</string> + <string name="recovery_error" msgid="4550265746256727080">"Грешка!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sv/strings.xml b/tools/recovery_l10n/res/values-sv/strings.xml index b33ce253f..f875d3008 100644 --- a/tools/recovery_l10n/res/values-sv/strings.xml +++ b/tools/recovery_l10n/res/values-sv/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Systemuppdatering installeras"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Rensar"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Inget kommando"</string> - <string name="recovery_error" msgid="5748178989622716736">"Fel!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Säkerhetsuppdatering installeras"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Installerar systemuppdatering ..."</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Tar bort ..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Inget kommando."</string> + <string name="recovery_error" msgid="4550265746256727080">"Fel!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-sw/strings.xml b/tools/recovery_l10n/res/values-sw/strings.xml index 156765881..1a5304649 100644 --- a/tools/recovery_l10n/res/values-sw/strings.xml +++ b/tools/recovery_l10n/res/values-sw/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Inasakinisha sasisho la mfumo"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Inafuta"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Hakuna amri"</string> - <string name="recovery_error" msgid="5748178989622716736">"Hitilafu fulani imetokea!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Inasakinisha sasisho la usalama"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Inasakinisha sasisho la mfumo…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Inafuta…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Hakuna amri."</string> + <string name="recovery_error" msgid="4550265746256727080">"Hitilafu!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ta-rIN/strings.xml b/tools/recovery_l10n/res/values-ta-rIN/strings.xml index d49186d8d..f6f3e0e6a 100644 --- a/tools/recovery_l10n/res/values-ta-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-ta-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"முறைமைப் புதுப்பிப்பை நிறுவுகிறது"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"அழிக்கிறது"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"கட்டளை இல்லை"</string> - <string name="recovery_error" msgid="5748178989622716736">"பிழை!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"பாதுகாப்புப் புதுப்பிப்பை நிறுவுகிறது"</string> + <string name="recovery_installing" msgid="7864047928003865598">"முறைமை புதுப்பிப்பை நிறுவுகிறது…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"அழிக்கிறது…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"கட்டளை இல்லை."</string> + <string name="recovery_error" msgid="4550265746256727080">"பிழை!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-te-rIN/strings.xml b/tools/recovery_l10n/res/values-te-rIN/strings.xml index cfb02c915..6d0d17af5 100644 --- a/tools/recovery_l10n/res/values-te-rIN/strings.xml +++ b/tools/recovery_l10n/res/values-te-rIN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"సిస్టమ్ నవీకరణను ఇన్స్టాల్ చేస్తోంది"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"డేటాను తొలగిస్తోంది"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ఆదేశం లేదు"</string> - <string name="recovery_error" msgid="5748178989622716736">"లోపం సంభవించింది!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"భద్రతా నవీకరణను ఇన్స్టాల్ చేస్తోంది"</string> + <string name="recovery_installing" msgid="7864047928003865598">"సిస్టమ్ నవీకరణను ఇన్స్టాల్ చేస్తోంది…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"ఎరేజ్ చేస్తోంది…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ఆదేశం లేదు."</string> + <string name="recovery_error" msgid="4550265746256727080">"లోపం!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-th/strings.xml b/tools/recovery_l10n/res/values-th/strings.xml index 155affea0..bcdfa2b25 100644 --- a/tools/recovery_l10n/res/values-th/strings.xml +++ b/tools/recovery_l10n/res/values-th/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"กำลังติดตั้งการอัปเดตระบบ"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"กำลังลบ"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"ไม่มีคำสั่ง"</string> - <string name="recovery_error" msgid="5748178989622716736">"ข้อผิดพลาด!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"กำลังติดตั้งการอัปเดตความปลอดภัย"</string> + <string name="recovery_installing" msgid="7864047928003865598">"กำลังติดตั้งการอัปเดตระบบ…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"กำลังลบ…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"ไม่มีคำสั่ง"</string> + <string name="recovery_error" msgid="4550265746256727080">"ข้อผิดพลาด!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-tl/strings.xml b/tools/recovery_l10n/res/values-tl/strings.xml index 555b42b8d..be2ba264c 100644 --- a/tools/recovery_l10n/res/values-tl/strings.xml +++ b/tools/recovery_l10n/res/values-tl/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Nag-i-install ng pag-update ng system"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Binubura"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Walang command"</string> - <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Nag-i-install ng update sa seguridad"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Ini-install ang update sa system…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Binubura…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Walang command."</string> + <string name="recovery_error" msgid="4550265746256727080">"Error!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-tr/strings.xml b/tools/recovery_l10n/res/values-tr/strings.xml index 5387cb2ae..8629029ca 100644 --- a/tools/recovery_l10n/res/values-tr/strings.xml +++ b/tools/recovery_l10n/res/values-tr/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Sistem güncellemesi yükleniyor"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Siliniyor"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Komut yok"</string> - <string name="recovery_error" msgid="5748178989622716736">"Hata!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Güvenlik güncellemesi yükleniyor"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Sistem güncellemesi yükleniyor…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Siliniyor…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Komut yok."</string> + <string name="recovery_error" msgid="4550265746256727080">"Hata!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-uk/strings.xml b/tools/recovery_l10n/res/values-uk/strings.xml index 0c2fa164a..762c06ff3 100644 --- a/tools/recovery_l10n/res/values-uk/strings.xml +++ b/tools/recovery_l10n/res/values-uk/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Установлюється оновлення системи"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Стирання"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Немає команди"</string> - <string name="recovery_error" msgid="5748178989622716736">"Помилка!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Установлюється оновлення системи безпеки"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Встановлення оновлення системи…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Стирання…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Немає команди."</string> + <string name="recovery_error" msgid="4550265746256727080">"Помилка!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-ur-rPK/strings.xml b/tools/recovery_l10n/res/values-ur-rPK/strings.xml index 12e32fbc1..dc6eb6aa1 100644 --- a/tools/recovery_l10n/res/values-ur-rPK/strings.xml +++ b/tools/recovery_l10n/res/values-ur-rPK/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"سسٹم اپ ڈیٹ انسٹال ہو رہی ہے"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"صاف ہو رہا ہے"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"کوئی کمانڈ نہیں ہے"</string> - <string name="recovery_error" msgid="5748178989622716736">"خرابی!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"سیکیورٹی اپ ڈیٹ انسٹال ہو رہی ہے"</string> + <string name="recovery_installing" msgid="7864047928003865598">"سسٹم اپ ڈیٹ انسٹال ہو رہا ہے…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"صاف کر رہا ہے…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"کوئی کمانڈ نہیں ہے۔"</string> + <string name="recovery_error" msgid="4550265746256727080">"خرابی!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-uz-rUZ/strings.xml b/tools/recovery_l10n/res/values-uz-rUZ/strings.xml index 2c309d646..287448418 100644 --- a/tools/recovery_l10n/res/values-uz-rUZ/strings.xml +++ b/tools/recovery_l10n/res/values-uz-rUZ/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Tizim yangilanishi o‘rnatilmoqda"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Tozalanmoqda…"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Buyruq yo‘q"</string> - <string name="recovery_error" msgid="5748178989622716736">"Xato!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Xavfsizlik yangilanishi o‘rnatilmoqda"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Tizim yangilanishi o‘rnatilmoqda…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Tozalanmoqda…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Buyruq yo‘q."</string> + <string name="recovery_error" msgid="4550265746256727080">"Xato!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-vi/strings.xml b/tools/recovery_l10n/res/values-vi/strings.xml index c77d0c8c2..ab4005b7f 100644 --- a/tools/recovery_l10n/res/values-vi/strings.xml +++ b/tools/recovery_l10n/res/values-vi/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Đang cài đặt bản cập nhật hệ thống"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Đang xóa"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Không có lệnh nào"</string> - <string name="recovery_error" msgid="5748178989622716736">"Lỗi!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Đang cài đặt bản cập nhật bảo mật"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Đang cài đặt bản cập nhật hệ thống…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Đang xóa…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Không có lệnh nào."</string> + <string name="recovery_error" msgid="4550265746256727080">"Lỗi!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-zh-rCN/strings.xml b/tools/recovery_l10n/res/values-zh-rCN/strings.xml index e06149791..2e1a6f57f 100644 --- a/tools/recovery_l10n/res/values-zh-rCN/strings.xml +++ b/tools/recovery_l10n/res/values-zh-rCN/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"正在安装系统更新"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"正在清空"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"无命令"</string> - <string name="recovery_error" msgid="5748178989622716736">"出错了!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"正在安装安全更新"</string> + <string name="recovery_installing" msgid="7864047928003865598">"正在安装系统更新…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"正在清除…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"无命令。"</string> + <string name="recovery_error" msgid="4550265746256727080">"出错了!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-zh-rHK/strings.xml b/tools/recovery_l10n/res/values-zh-rHK/strings.xml index ec3315d32..f615c7a29 100644 --- a/tools/recovery_l10n/res/values-zh-rHK/strings.xml +++ b/tools/recovery_l10n/res/values-zh-rHK/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"正在安裝系統更新"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"正在清除"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"沒有指令"</string> - <string name="recovery_error" msgid="5748178989622716736">"錯誤!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"正在安裝安全性更新"</string> + <string name="recovery_installing" msgid="7864047928003865598">"正在安裝系統更新…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"正在清除…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"沒有指令。"</string> + <string name="recovery_error" msgid="4550265746256727080">"錯誤!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-zh-rTW/strings.xml b/tools/recovery_l10n/res/values-zh-rTW/strings.xml index 78eae2429..f3f6a2c21 100644 --- a/tools/recovery_l10n/res/values-zh-rTW/strings.xml +++ b/tools/recovery_l10n/res/values-zh-rTW/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"正在安裝系統更新"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"清除中"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"沒有指令"</string> - <string name="recovery_error" msgid="5748178989622716736">"錯誤!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"正在安裝安全性更新"</string> + <string name="recovery_installing" msgid="7864047928003865598">"正在安裝系統更新…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"清除中..."</string> + <string name="recovery_no_command" msgid="1915703879031023455">"沒有指令。"</string> + <string name="recovery_error" msgid="4550265746256727080">"錯誤!"</string> </resources> diff --git a/tools/recovery_l10n/res/values-zu/strings.xml b/tools/recovery_l10n/res/values-zu/strings.xml index 6b815e1ab..1f904a203 100644 --- a/tools/recovery_l10n/res/values-zu/strings.xml +++ b/tools/recovery_l10n/res/values-zu/strings.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Ifaka isibuyekezo sesistimu"</string> - <string name="recovery_erasing" msgid="7334826894904037088">"Iyasula"</string> - <string name="recovery_no_command" msgid="4465476568623024327">"Awukho umyalo"</string> - <string name="recovery_error" msgid="5748178989622716736">"Iphutha!"</string> - <string name="recovery_installing_security" msgid="9184031299717114342">"Ifaka isibuyekezo sokuphepha"</string> + <string name="recovery_installing" msgid="7864047928003865598">"Ifaka isibuyekezo sesistimu…"</string> + <string name="recovery_erasing" msgid="4612809744968710197">"Iyasula…"</string> + <string name="recovery_no_command" msgid="1915703879031023455">"Awukho umyalo."</string> + <string name="recovery_error" msgid="4550265746256727080">"Iphutha!"</string> </resources> diff --git a/tools/recovery_l10n/res/values/strings.xml b/tools/recovery_l10n/res/values/strings.xml index 971e038d3..d56d0733c 100644 --- a/tools/recovery_l10n/res/values/strings.xml +++ b/tools/recovery_l10n/res/values/strings.xml @@ -9,6 +9,7 @@ <item>erasing</item> <item>no_command</item> <item>error</item> + <item>installing_security</item> </string-array> <!-- Displayed on the screen beneath the animated android while the diff --git a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java index 817a3ad7d..ac94bde1c 100644 --- a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java +++ b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java @@ -139,6 +139,7 @@ public class Main extends Activity { case 1: mStringId = R.string.recovery_erasing; break; case 2: mStringId = R.string.recovery_no_command; break; case 3: mStringId = R.string.recovery_error; break; + case 4: mStringId = R.string.recovery_installing_security; break; } } @Override public void onNothingSelected(AdapterView parent) { } @@ -28,7 +28,7 @@ #include <time.h> #include <unistd.h> -#include <cutils/properties.h> +#include <android-base/properties.h> #include <cutils/android_reboot.h> #include "common.h" @@ -175,7 +175,7 @@ void RecoveryUI::ProcessKey(int key_code, int updown) { case RecoveryUI::REBOOT: if (reboot_enabled) { - property_set(ANDROID_RB_PROPERTY, "reboot,"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,"); while (true) { pause(); } } break; diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk index bb276edd5..59084b0bb 100644 --- a/uncrypt/Android.mk +++ b/uncrypt/Android.mk @@ -17,16 +17,16 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CLANG := true - LOCAL_SRC_FILES := uncrypt.cpp - LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. - LOCAL_MODULE := uncrypt - -LOCAL_STATIC_LIBRARIES := libbootloader_message libbase \ - liblog libfs_mgr libcutils \ - +LOCAL_STATIC_LIBRARIES := \ + libbootloader_message \ + libbase \ + liblog \ + libfs_mgr \ + libcutils +LOCAL_CFLAGS := -Werror LOCAL_INIT_RC := uncrypt.rc include $(BUILD_EXECUTABLE) diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 280568d23..f31d55aa8 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -107,19 +107,16 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> #include <bootloader_message/bootloader_message.h> #include <cutils/android_reboot.h> -#include <cutils/properties.h> #include <cutils/sockets.h> #include <fs_mgr.h> -#define LOG_TAG "uncrypt" -#include <log/log.h> - #include "error_code.h" -#include "unique_fd.h" #define WINDOW_SIZE 5 @@ -142,11 +139,11 @@ static struct fstab* fstab = nullptr; static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) { if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) { - ALOGE("error seeking to offset %" PRId64 ": %s", offset, strerror(errno)); + PLOG(ERROR) << "error seeking to offset " << offset; return -1; } if (!android::base::WriteFully(wfd, buffer, size)) { - ALOGE("error writing offset %" PRId64 ": %s", offset, strerror(errno)); + PLOG(ERROR) << "error writing offset " << offset; return -1; } return 0; @@ -168,15 +165,17 @@ static struct fstab* read_fstab() { fstab = NULL; // The fstab path is always "/fstab.${ro.hardware}". - char fstab_path[PATH_MAX+1] = "/fstab."; - if (!property_get("ro.hardware", fstab_path+strlen(fstab_path), "")) { - ALOGE("failed to get ro.hardware"); + std::string ro_hardware = android::base::GetProperty("ro.hardware", ""); + if (ro_hardware.empty()) { + LOG(ERROR) << "failed to get ro.hardware"; return NULL; } - fstab = fs_mgr_read_fstab(fstab_path); + std::string fstab_path = "/fstab." + ro_hardware; + + fstab = fs_mgr_read_fstab(fstab_path.c_str()); if (!fstab) { - ALOGE("failed to read %s", fstab_path); + LOG(ERROR) << "failed to read " << fstab_path; return NULL; } @@ -199,9 +198,7 @@ static const char* find_block_device(const char* path, bool* encryptable, bool* *encryptable = false; if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) { *encryptable = true; - char buffer[PROPERTY_VALUE_MAX+1]; - if (property_get("ro.crypto.state", buffer, "") && - strcmp(buffer, "encrypted") == 0) { + if (android::base::GetProperty("ro.crypto.state", "") == "encrypted") { *encrypted = true; } } @@ -222,7 +219,7 @@ static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::stri CHECK(package_name != nullptr); std::string uncrypt_path; if (!android::base::ReadFileToString(uncrypt_path_file, &uncrypt_path)) { - ALOGE("failed to open \"%s\": %s", uncrypt_path_file.c_str(), strerror(errno)); + PLOG(ERROR) << "failed to open \"" << uncrypt_path_file << "\""; return false; } @@ -235,39 +232,41 @@ static int produce_block_map(const char* path, const char* map_file, const char* bool encrypted, int socket) { std::string err; if (!android::base::RemoveFileIfExists(map_file, &err)) { - ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str()); + LOG(ERROR) << "failed to remove the existing map file " << map_file << ": " << err; return kUncryptFileRemoveError; } std::string tmp_map_file = std::string(map_file) + ".tmp"; - unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)); - if (!mapfd) { - ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno)); + android::base::unique_fd mapfd(open(tmp_map_file.c_str(), + O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)); + if (mapfd == -1) { + PLOG(ERROR) << "failed to open " << tmp_map_file; return kUncryptFileOpenError; } // Make sure we can write to the socket. if (!write_status_to_socket(0, socket)) { - ALOGE("failed to write to socket %d\n", socket); + LOG(ERROR) << "failed to write to socket " << socket; return kUncryptSocketWriteError; } struct stat sb; if (stat(path, &sb) != 0) { - ALOGE("failed to stat %s", path); + LOG(ERROR) << "failed to stat " << path; return kUncryptFileStatError; } - ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize)); + LOG(INFO) << " block size: " << sb.st_blksize << " bytes"; int blocks = ((sb.st_size-1) / sb.st_blksize) + 1; - ALOGI(" file size: %" PRId64 " bytes, %d blocks", sb.st_size, blocks); + LOG(INFO) << " file size: " << sb.st_size << " bytes, " << blocks << " blocks"; std::vector<int> ranges; - std::string s = android::base::StringPrintf("%s\n%" PRId64 " %ld\n", - blk_dev, sb.st_size, static_cast<long>(sb.st_blksize)); - if (!android::base::WriteStringToFd(s, mapfd.get())) { - ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); + std::string s = android::base::StringPrintf("%s\n%" PRId64 " %" PRId64 "\n", + blk_dev, static_cast<int64_t>(sb.st_size), + static_cast<int64_t>(sb.st_blksize)); + if (!android::base::WriteStringToFd(s, mapfd)) { + PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } @@ -278,17 +277,17 @@ static int produce_block_map(const char* path, const char* map_file, const char* int head_block = 0; int head = 0, tail = 0; - unique_fd fd(open(path, O_RDONLY)); - if (!fd) { - ALOGE("failed to open %s for reading: %s", path, strerror(errno)); + android::base::unique_fd fd(open(path, O_RDONLY)); + if (fd == -1) { + PLOG(ERROR) << "failed to open " << path << " for reading"; return kUncryptFileOpenError; } - unique_fd wfd(-1); + android::base::unique_fd wfd; if (encrypted) { - wfd = open(blk_dev, O_WRONLY); - if (!wfd) { - ALOGE("failed to open fd for writing: %s", strerror(errno)); + wfd.reset(open(blk_dev, O_WRONLY)); + if (wfd == -1) { + PLOG(ERROR) << "failed to open " << blk_dev << " for writing"; return kUncryptBlockOpenError; } } @@ -306,14 +305,14 @@ static int produce_block_map(const char* path, const char* map_file, const char* if ((tail+1) % WINDOW_SIZE == head) { // write out head buffer int block = head_block; - if (ioctl(fd.get(), FIBMAP, &block) != 0) { - ALOGE("failed to find block %d", head_block); + if (ioctl(fd, FIBMAP, &block) != 0) { + PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } add_block_to_ranges(ranges, block); if (encrypted) { - if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), - static_cast<off64_t>(sb.st_blksize) * block) != 0) { + if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, + static_cast<off64_t>(sb.st_blksize) * block) != 0) { return kUncryptWriteError; } } @@ -325,8 +324,8 @@ static int produce_block_map(const char* path, const char* map_file, const char* if (encrypted) { size_t to_read = static_cast<size_t>( std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos)); - if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) { - ALOGE("failed to read: %s", strerror(errno)); + if (!android::base::ReadFully(fd, buffers[tail].data(), to_read)) { + PLOG(ERROR) << "failed to read " << path; return kUncryptReadError; } pos += to_read; @@ -342,14 +341,14 @@ static int produce_block_map(const char* path, const char* map_file, const char* while (head != tail) { // write out head buffer int block = head_block; - if (ioctl(fd.get(), FIBMAP, &block) != 0) { - ALOGE("failed to find block %d", head_block); + if (ioctl(fd, FIBMAP, &block) != 0) { + PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } add_block_to_ranges(ranges, block); if (encrypted) { - if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), - static_cast<off64_t>(sb.st_blksize) * block) != 0) { + if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, + static_cast<off64_t>(sb.st_blksize) * block) != 0) { return kUncryptWriteError; } } @@ -358,72 +357,69 @@ static int produce_block_map(const char* path, const char* map_file, const char* } if (!android::base::WriteStringToFd( - android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) { - ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); + android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd)) { + PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } for (size_t i = 0; i < ranges.size(); i += 2) { if (!android::base::WriteStringToFd( - android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) { - ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); + android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd)) { + PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } } - if (fsync(mapfd.get()) == -1) { - ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno)); + if (fsync(mapfd) == -1) { + PLOG(ERROR) << "failed to fsync \"" << tmp_map_file << "\""; return kUncryptFileSyncError; } - if (close(mapfd.get()) == -1) { - ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno)); + if (close(mapfd.release()) == -1) { + PLOG(ERROR) << "failed to close " << tmp_map_file; return kUncryptFileCloseError; } - mapfd = -1; if (encrypted) { - if (fsync(wfd.get()) == -1) { - ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno)); + if (fsync(wfd) == -1) { + PLOG(ERROR) << "failed to fsync \"" << blk_dev << "\""; return kUncryptFileSyncError; } - if (close(wfd.get()) == -1) { - ALOGE("failed to close %s: %s", blk_dev, strerror(errno)); + if (close(wfd.release()) == -1) { + PLOG(ERROR) << "failed to close " << blk_dev; return kUncryptFileCloseError; } - wfd = -1; } if (rename(tmp_map_file.c_str(), map_file) == -1) { - ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno)); + PLOG(ERROR) << "failed to rename " << tmp_map_file << " to " << map_file; return kUncryptFileRenameError; } // Sync dir to make rename() result written to disk. std::string file_name = map_file; std::string dir_name = dirname(&file_name[0]); - unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); - if (!dfd) { - ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno)); + android::base::unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); + if (dfd == -1) { + PLOG(ERROR) << "failed to open dir " << dir_name; return kUncryptFileOpenError; } - if (fsync(dfd.get()) == -1) { - ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno)); + if (fsync(dfd) == -1) { + PLOG(ERROR) << "failed to fsync " << dir_name; return kUncryptFileSyncError; } - if (close(dfd.get()) == -1) { - ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno)); + if (close(dfd.release()) == -1) { + PLOG(ERROR) << "failed to close " << dir_name; return kUncryptFileCloseError; } - dfd = -1; return 0; } static int uncrypt(const char* input_path, const char* map_file, const int socket) { - ALOGI("update package is \"%s\"", input_path); + LOG(INFO) << "update package is \"" << input_path << "\""; // Turn the name of the file we're supposed to convert into an // absolute path, so we can find what filesystem it's on. char path[PATH_MAX+1]; if (realpath(input_path, path) == NULL) { - ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno)); + PLOG(ERROR) << "failed to convert \"" << input_path << "\" to absolute path"; return 1; } @@ -431,15 +427,15 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke bool encrypted; const char* blk_dev = find_block_device(path, &encryptable, &encrypted); if (blk_dev == NULL) { - ALOGE("failed to find block device for %s", path); + LOG(ERROR) << "failed to find block device for " << path; return 1; } // If the filesystem it's on isn't encrypted, we only produce the // block map, we don't rewrite the file contents (it would be // pointless to do so). - ALOGI("encryptable: %s", encryptable ? "yes" : "no"); - ALOGI(" encrypted: %s", encrypted ? "yes" : "no"); + LOG(INFO) << "encryptable: " << (encryptable ? "yes" : "no"); + LOG(INFO) << " encrypted: " << (encrypted ? "yes" : "no"); // Recovery supports installing packages from 3 paths: /cache, // /data, and /sdcard. (On a particular device, other locations @@ -449,7 +445,7 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke // can read the package without mounting the partition. On /cache // and /sdcard we leave the file alone. if (strncmp(path, "/data/", 6) == 0) { - ALOGI("writing block map %s", map_file); + LOG(INFO) << "writing block map " << map_file; return produce_block_map(path, map_file, blk_dev, encrypted, socket); } @@ -459,7 +455,7 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke static void log_uncrypt_error_code(UncryptErrorCode error_code) { if (!android::base::WriteStringToFile(android::base::StringPrintf( "uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) { - ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; } } @@ -489,7 +485,7 @@ static bool uncrypt_wrapper(const char* input_path, const char* map_file, const // Log the time cost and error code if uncrypt fails. uncrypt_message += android::base::StringPrintf("uncrypt_error: %d\n", status); if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) { - ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; } write_status_to_socket(-1, socket); @@ -497,7 +493,7 @@ static bool uncrypt_wrapper(const char* input_path, const char* map_file, const } if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) { - ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; } write_status_to_socket(100, socket); @@ -508,7 +504,7 @@ static bool uncrypt_wrapper(const char* input_path, const char* map_file, const static bool clear_bcb(const int socket) { std::string err; if (!clear_bootloader_message(&err)) { - ALOGE("failed to clear bootloader message: %s", err.c_str()); + LOG(ERROR) << "failed to clear bootloader message: " << err; write_status_to_socket(-1, socket); return false; } @@ -520,7 +516,7 @@ static bool setup_bcb(const int socket) { // c5. receive message length int length; if (!android::base::ReadFully(socket, &length, 4)) { - ALOGE("failed to read the length: %s", strerror(errno)); + PLOG(ERROR) << "failed to read the length"; return false; } length = ntohl(length); @@ -529,17 +525,17 @@ static bool setup_bcb(const int socket) { std::string content; content.resize(length); if (!android::base::ReadFully(socket, &content[0], length)) { - ALOGE("failed to read the length: %s", strerror(errno)); + PLOG(ERROR) << "failed to read the length"; return false; } - ALOGI(" received command: [%s] (%zu)", content.c_str(), content.size()); + LOG(INFO) << " received command: [" << content << "] (" << content.size() << ")"; std::vector<std::string> options = android::base::Split(content, "\n"); std::string wipe_package; for (auto& option : options) { if (android::base::StartsWith(option, "--wipe_package=")) { std::string path = option.substr(strlen("--wipe_package=")); if (!android::base::ReadFileToString(path, &wipe_package)) { - ALOGE("failed to read %s: %s", path.c_str(), strerror(errno)); + PLOG(ERROR) << "failed to read " << path; return false; } option = android::base::StringPrintf("--wipe_package_size=%zu", wipe_package.size()); @@ -549,12 +545,12 @@ static bool setup_bcb(const int socket) { // c8. setup the bcb command std::string err; if (!write_bootloader_message(options, &err)) { - ALOGE("failed to set bootloader message: %s", err.c_str()); + LOG(ERROR) << "failed to set bootloader message: " << err; write_status_to_socket(-1, socket); return false; } if (!wipe_package.empty() && !write_wipe_package(wipe_package, &err)) { - ALOGE("failed to set wipe package: %s", err.c_str()); + PLOG(ERROR) << "failed to set wipe package: " << err; write_status_to_socket(-1, socket); return false; } @@ -597,23 +593,23 @@ int main(int argc, char** argv) { // c3. The socket is created by init when starting the service. uncrypt // will use the socket to communicate with its caller. - unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); - if (!service_socket) { - ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno)); + android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); + if (service_socket == -1) { + PLOG(ERROR) << "failed to open socket \"" << UNCRYPT_SOCKET << "\""; log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } - fcntl(service_socket.get(), F_SETFD, FD_CLOEXEC); + fcntl(service_socket, F_SETFD, FD_CLOEXEC); - if (listen(service_socket.get(), 1) == -1) { - ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno)); + if (listen(service_socket, 1) == -1) { + PLOG(ERROR) << "failed to listen on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketListenError); return 1; } - unique_fd socket_fd(accept4(service_socket.get(), nullptr, nullptr, SOCK_CLOEXEC)); - if (!socket_fd) { - ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno)); + android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC)); + if (socket_fd == -1) { + PLOG(ERROR) << "failed to accept on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } @@ -621,16 +617,16 @@ int main(int argc, char** argv) { bool success = false; switch (action) { case UNCRYPT: - success = uncrypt_wrapper(input_path, map_file, socket_fd.get()); + success = uncrypt_wrapper(input_path, map_file, socket_fd); break; case SETUP_BCB: - success = setup_bcb(socket_fd.get()); + success = setup_bcb(socket_fd); break; case CLEAR_BCB: - success = clear_bcb(socket_fd.get()); + success = clear_bcb(socket_fd); break; default: // Should never happen. - ALOGE("Invalid uncrypt action code: %d", action); + LOG(ERROR) << "Invalid uncrypt action code: " << action; return 1; } @@ -638,10 +634,10 @@ int main(int argc, char** argv) { // ensure the client to receive the last status code before the socket gets // destroyed. int code; - if (android::base::ReadFully(socket_fd.get(), &code, 4)) { - ALOGI(" received %d, exiting now", code); + if (android::base::ReadFully(socket_fd, &code, 4)) { + LOG(INFO) << " received " << code << ", exiting now"; } else { - ALOGE("failed to read the code: %s", strerror(errno)); + PLOG(ERROR) << "failed to read the code"; } return success ? 0 : 1; } diff --git a/unique_fd.h b/unique_fd.h deleted file mode 100644 index cc85383f8..000000000 --- a/unique_fd.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 UNIQUE_FD_H -#define UNIQUE_FD_H - -#include <stdio.h> - -#include <memory> - -class unique_fd { - public: - unique_fd(int fd) : fd_(fd) { } - - unique_fd(unique_fd&& uf) { - fd_ = uf.fd_; - uf.fd_ = -1; - } - - ~unique_fd() { - if (fd_ != -1) { - close(fd_); - } - } - - int get() { - return fd_; - } - - // Movable. - unique_fd& operator=(unique_fd&& uf) { - fd_ = uf.fd_; - uf.fd_ = -1; - return *this; - } - - explicit operator bool() const { - return fd_ != -1; - } - - private: - int fd_; - - // Non-copyable. - unique_fd(const unique_fd&) = delete; - unique_fd& operator=(const unique_fd&) = delete; -}; - -#endif // UNIQUE_FD_H diff --git a/update_verifier/Android.mk b/update_verifier/Android.mk index 2bfd01622..090db998b 100644 --- a/update_verifier/Android.mk +++ b/update_verifier/Android.mk @@ -23,5 +23,6 @@ LOCAL_MODULE := update_verifier LOCAL_SHARED_LIBRARIES := libbase libcutils libhardware liblog LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. +LOCAL_CFLAGS := -Werror include $(BUILD_EXECUTABLE) diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp index 5cff8be93..93ac605b1 100644 --- a/update_verifier/update_verifier.cpp +++ b/update_verifier/update_verifier.cpp @@ -40,13 +40,12 @@ #include <vector> #include <android-base/file.h> +#include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/properties.h> #include <hardware/boot_control.h> -#define LOG_TAG "update_verifier" -#include <log/log.h> constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; constexpr int BLOCKSIZE = 4096; @@ -57,7 +56,7 @@ static bool read_blocks(const std::string& blk_device_prefix, const std::string& std::string blk_device = blk_device_prefix + std::string(slot_suffix); android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY))); if (fd.get() == -1) { - SLOGE("Error reading partition %s: %s\n", blk_device.c_str(), strerror(errno)); + PLOG(ERROR) << "Error reading partition " << blk_device; return false; } @@ -70,7 +69,7 @@ static bool read_blocks(const std::string& blk_device_prefix, const std::string& bool status = android::base::ParseUint(ranges[0].c_str(), &range_count); if (!status || (range_count == 0) || (range_count % 2 != 0) || (range_count != ranges.size()-1)) { - SLOGE("Error in parsing range string.\n"); + LOG(ERROR) << "Error in parsing range string."; return false; } @@ -80,26 +79,25 @@ static bool read_blocks(const std::string& blk_device_prefix, const std::string& bool parse_status = android::base::ParseUint(ranges[i].c_str(), &range_start); parse_status = parse_status && android::base::ParseUint(ranges[i+1].c_str(), &range_end); if (!parse_status || range_start >= range_end) { - SLOGE("Invalid range pair %s, %s.\n", ranges[i].c_str(), ranges[i+1].c_str()); + LOG(ERROR) << "Invalid range pair " << ranges[i] << ", " << ranges[i+1]; return false; } if (lseek64(fd.get(), static_cast<off64_t>(range_start) * BLOCKSIZE, SEEK_SET) == -1) { - SLOGE("lseek to %u failed: %s.\n", range_start, strerror(errno)); + PLOG(ERROR) << "lseek to " << range_start << " failed"; return false; } size_t size = (range_end - range_start) * BLOCKSIZE; std::vector<uint8_t> buf(size); if (!android::base::ReadFully(fd.get(), buf.data(), size)) { - SLOGE("Failed to read blocks %u to %u: %s.\n", range_start, range_end, - strerror(errno)); + PLOG(ERROR) << "Failed to read blocks " << range_start << " to " << range_end; return false; } blk_count += (range_end - range_start); } - SLOGI("Finished reading %zu blocks on %s.\n", blk_count, blk_device.c_str()); + LOG(INFO) << "Finished reading " << blk_count << " blocks on " << blk_device; return true; } @@ -109,7 +107,7 @@ static bool verify_image(const std::string& care_map_name) { // in /data/ota_package. To allow the device to continue booting in this situation, // we should print a warning and skip the block verification. if (care_map_fd.get() == -1) { - SLOGI("Warning: care map %s not found.\n", care_map_name.c_str()); + LOG(WARNING) << "Warning: care map " << care_map_name << " not found."; return true; } // Care map file has four lines (two lines if vendor partition is not present): @@ -118,15 +116,15 @@ static bool verify_image(const std::string& care_map_name) { // The next two lines have the same format but for vendor partition. std::string file_content; if (!android::base::ReadFdToString(care_map_fd.get(), &file_content)) { - SLOGE("Error reading care map contents to string.\n"); + LOG(ERROR) << "Error reading care map contents to string."; return false; } std::vector<std::string> lines; lines = android::base::Split(android::base::Trim(file_content), "\n"); if (lines.size() != 2 && lines.size() != 4) { - SLOGE("Invalid lines in care_map: found %zu lines, expecting 2 or 4 lines.\n", - lines.size()); + LOG(ERROR) << "Invalid lines in care_map: found " << lines.size() + << " lines, expecting 2 or 4 lines."; return false; } @@ -141,12 +139,12 @@ static bool verify_image(const std::string& care_map_name) { int main(int argc, char** argv) { for (int i = 1; i < argc; i++) { - SLOGI("Started with arg %d: %s\n", i, argv[i]); + LOG(INFO) << "Started with arg " << i << ": " << argv[i]; } const hw_module_t* hw_module; if (hw_get_module("bootctrl", &hw_module) != 0) { - SLOGE("Error getting bootctrl module.\n"); + LOG(ERROR) << "Error getting bootctrl module."; return -1; } @@ -156,34 +154,35 @@ int main(int argc, char** argv) { unsigned current_slot = module->getCurrentSlot(module); int is_successful= module->isSlotMarkedSuccessful(module, current_slot); - SLOGI("Booting slot %u: isSlotMarkedSuccessful=%d\n", current_slot, is_successful); + LOG(INFO) << "Booting slot " << current_slot << ": isSlotMarkedSuccessful=" << is_successful; + if (is_successful == 0) { // The current slot has not booted successfully. char verity_mode[PROPERTY_VALUE_MAX]; if (property_get("ro.boot.veritymode", verity_mode, "") == -1) { - SLOGE("Failed to get dm-verity mode"); + LOG(ERROR) << "Failed to get dm-verity mode."; return -1; } else if (strcasecmp(verity_mode, "eio") == 0) { // We shouldn't see verity in EIO mode if the current slot hasn't booted // successfully before. Therefore, fail the verification when veritymode=eio. - SLOGE("Found dm-verity in EIO mode, skip verification."); + LOG(ERROR) << "Found dm-verity in EIO mode, skip verification."; return -1; } else if (strcmp(verity_mode, "enforcing") != 0) { - SLOGE("Unexpected dm-verity mode : %s, expecting enforcing.", verity_mode); + LOG(ERROR) << "Unexpected dm-verity mode : " << verity_mode << ", expecting enforcing."; return -1; } else if (!verify_image(CARE_MAP_FILE)) { - SLOGE("Failed to verify all blocks in care map file.\n"); + LOG(ERROR) << "Failed to verify all blocks in care map file."; return -1; } int ret = module->markBootSuccessful(module); if (ret != 0) { - SLOGE("Error marking booted successfully: %s\n", strerror(-ret)); + LOG(ERROR) << "Error marking booted successfully: " << strerror(-ret); return -1; } - SLOGI("Marked slot %u as booted successfully.\n", current_slot); + LOG(INFO) << "Marked slot " << current_slot << " as booted successfully."; } - SLOGI("Leaving update_verifier.\n"); + LOG(INFO) << "Leaving update_verifier."; return 0; } diff --git a/updater/Android.mk b/updater/Android.mk index d7aa613e9..3c1d0d41f 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -14,52 +14,87 @@ LOCAL_PATH := $(call my-dir) -updater_src_files := \ - install.cpp \ - blockimg.cpp \ - updater.cpp - -# -# Build a statically-linked binary to include in OTA packages -# +tune2fs_static_libraries := \ + libext2_com_err \ + libext2_blkid \ + libext2_quota \ + libext2_uuid_static \ + libext2_e2p \ + libext2fs + +updater_common_static_libraries := \ + libapplypatch \ + libedify \ + libziparchive \ + libotautil \ + libutils \ + libmounts \ + libotafault \ + libext4_utils_static \ + libfec \ + libfec_rs \ + liblog \ + libselinux \ + libsparse_static \ + libsquashfs_utils \ + libbz \ + libz \ + libbase \ + libcrypto \ + libcrypto_utils \ + libcutils \ + libtune2fs \ + $(tune2fs_static_libraries) + +# libupdater (static library) +# =============================== include $(CLEAR_VARS) -# Build only in eng, so we don't end up with a copy of this in /system -# on user builds. (TODO: find a better way to build device binaries -# needed only for OTA packages.) -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE := libupdater -LOCAL_CLANG := true +LOCAL_SRC_FILES := \ + install.cpp \ + blockimg.cpp -LOCAL_SRC_FILES := $(updater_src_files) +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/.. \ + $(LOCAL_PATH)/include \ + external/e2fsprogs/misc -LOCAL_STATIC_LIBRARIES += libfec libfec_rs libext4_utils_static libsquashfs_utils libcrypto_static +LOCAL_CFLAGS := \ + -Wno-unused-parameter \ + -Werror -ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) -LOCAL_CFLAGS += -DUSE_EXT4 -LOCAL_CFLAGS += -Wno-unused-parameter -LOCAL_C_INCLUDES += system/extras/ext4_utils -LOCAL_STATIC_LIBRARIES += \ - libsparse_static \ - libz -endif - -LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS) -LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libedify libmtdutils libminzip libz -LOCAL_STATIC_LIBRARIES += libbz -LOCAL_STATIC_LIBRARIES += libcutils liblog libc -LOCAL_STATIC_LIBRARIES += libselinux -tune2fs_static_libraries := \ - libext2_com_err \ - libext2_blkid \ - libext2_quota \ - libext2_uuid_static \ - libext2_e2p \ - libext2fs -LOCAL_STATIC_LIBRARIES += libtune2fs $(tune2fs_static_libraries) +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/include + +LOCAL_STATIC_LIBRARIES := \ + $(updater_common_static_libraries) + +include $(BUILD_STATIC_LIBRARY) -LOCAL_C_INCLUDES += external/e2fsprogs/misc -LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. +# updater (static executable) +# =============================== +include $(CLEAR_VARS) + +LOCAL_MODULE := updater + +LOCAL_SRC_FILES := \ + updater.cpp + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/.. \ + $(LOCAL_PATH)/include + +LOCAL_CFLAGS := \ + -Wno-unused-parameter \ + -Werror + +LOCAL_STATIC_LIBRARIES := \ + libupdater \ + $(TARGET_RECOVERY_UPDATER_LIBS) \ + $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS) \ + $(updater_common_static_libraries) # Each library in TARGET_RECOVERY_UPDATER_LIBS should have a function # named "Register_<libname>()". Here we emit a little C function that @@ -100,8 +135,6 @@ LOCAL_C_INCLUDES += $(dir $(inc)) inc := inc_dep_file := -LOCAL_MODULE := updater - LOCAL_FORCE_STATIC_EXECUTABLE := true include $(BUILD_EXECUTABLE) diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index a80180a9a..f08ca5b0c 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -33,24 +33,24 @@ #include <unistd.h> #include <fec/io.h> -#include <map> #include <memory> #include <string> +#include <unordered_map> #include <vector> #include <android-base/parseint.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> +#include <ziparchive/zip_archive.h> #include "applypatch/applypatch.h" #include "edify/expr.h" #include "error_code.h" -#include "install.h" +#include "updater/install.h" #include "openssl/sha.h" -#include "minzip/Hash.h" #include "ota_io.h" #include "print_sha1.h" -#include "unique_fd.h" -#include "updater.h" +#include "updater/updater.h" #define BLOCKSIZE 4096 @@ -71,7 +71,7 @@ struct RangeSet { static CauseCode failure_type = kNoCause; static bool is_retry = false; -static std::map<std::string, RangeSet> stash_map; +static std::unordered_map<std::string, RangeSet> stash_map; static void parse_range(const std::string& range_text, RangeSet& rs) { @@ -151,6 +151,10 @@ static int read_all(int fd, uint8_t* data, size_t size) { failure_type = kFreadFailure; fprintf(stderr, "read failed: %s\n", strerror(errno)); return -1; + } else if (r == 0) { + failure_type = kFreadFailure; + fprintf(stderr, "read reached unexpected EOF.\n"); + return -1; } so_far += r; } @@ -213,7 +217,7 @@ static void allocate(size_t size, std::vector<uint8_t>& buffer) { } struct RangeSinkState { - RangeSinkState(RangeSet& rs) : tgt(rs) { }; + explicit RangeSinkState(RangeSet& rs) : tgt(rs) { }; int fd; const RangeSet& tgt; @@ -296,8 +300,8 @@ static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) { // rss and signals the condition again. struct NewThreadInfo { - ZipArchive* za; - const ZipEntry* entry; + ZipArchiveHandle za; + ZipEntry entry; RangeSinkState* rss; @@ -305,7 +309,7 @@ struct NewThreadInfo { pthread_cond_t cv; }; -static bool receive_new_data(const unsigned char* data, int size, void* cookie) { +static bool receive_new_data(const uint8_t* data, size_t size, void* cookie) { NewThreadInfo* nti = reinterpret_cast<NewThreadInfo*>(cookie); while (size > 0) { @@ -338,7 +342,7 @@ static bool receive_new_data(const unsigned char* data, int size, void* cookie) static void* unzip_new_data(void* cookie) { NewThreadInfo* nti = (NewThreadInfo*) cookie; - mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti); + ProcessZipEntryContents(nti->za, &nti->entry, receive_new_data, nti); return nullptr; } @@ -398,7 +402,7 @@ struct CommandParameters { std::string stashbase; bool canwrite; int createdstash; - int fd; + android::base::unique_fd fd; bool foundwrites; bool isunresumable; int version; @@ -608,9 +612,7 @@ static int LoadStash(CommandParameters& params, const std::string& base, const s return -1; } - int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY)); - unique_fd fd_holder(fd); - + android::base::unique_fd fd(TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_RDONLY))); if (fd == -1) { fprintf(stderr, "open \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); return -1; @@ -665,9 +667,9 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks fprintf(stderr, " writing %d blocks to %s\n", blocks, cn.c_str()); - int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)); - unique_fd fd_holder(fd); - + android::base::unique_fd fd(TEMP_FAILURE_RETRY(ota_open(fn.c_str(), + O_WRONLY | O_CREAT | O_TRUNC, + STASH_FILE_MODE))); if (fd == -1) { fprintf(stderr, "failed to create \"%s\": %s\n", fn.c_str(), strerror(errno)); return -1; @@ -690,9 +692,8 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks } std::string dname = GetStashFileName(base, "", ""); - int dfd = TEMP_FAILURE_RETRY(open(dname.c_str(), O_RDONLY | O_DIRECTORY)); - unique_fd dfd_holder(dfd); - + android::base::unique_fd dfd(TEMP_FAILURE_RETRY(ota_open(dname.c_str(), + O_RDONLY | O_DIRECTORY))); if (dfd == -1) { failure_type = kFileOpenFailure; fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno)); @@ -980,8 +981,8 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& tgthash = params.tokens[params.cpos++]; } - if (LoadSrcTgtVersion2(params, tgt, src_blocks, params.buffer, params.fd, params.stashbase, - &overlap) == -1) { + if (LoadSrcTgtVersion2(params, tgt, src_blocks, params.buffer, params.fd, + params.stashbase, &overlap) == -1) { return -1; } @@ -1215,7 +1216,7 @@ static int PerformCommandDiff(CommandParameters& params) { size_t len; if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) { - fprintf(stderr, "invalid patch offset\n"); + fprintf(stderr, "invalid patch len\n"); return -1; } @@ -1247,10 +1248,8 @@ static int PerformCommandDiff(CommandParameters& params) { if (status == 0) { fprintf(stderr, "patching %zu blocks to %zu\n", blocks, tgt.size); - Value patch_value; - patch_value.type = VAL_BLOB; - patch_value.size = len; - patch_value.data = (char*) (params.patch_start + offset); + Value patch_value(VAL_BLOB, + std::string(reinterpret_cast<const char*>(params.patch_start + offset), len)); RangeSinkState rss(tgt); rss.fd = params.fd; @@ -1352,28 +1351,6 @@ struct Command { CommandFunction f; }; -// CompareCommands and CompareCommandNames are for the hash table - -static int CompareCommands(const void* c1, const void* c2) { - return strcmp(((const Command*) c1)->name, ((const Command*) c2)->name); -} - -static int CompareCommandNames(const void* c1, const void* c2) { - return strcmp(((const Command*) c1)->name, (const char*) c2); -} - -// HashString is used to hash command names for the hash table - -static unsigned int HashString(const char *s) { - unsigned int hash = 0; - if (s) { - while (*s) { - hash = hash * 33 + *s++; - } - } - return hash; -} - // args: // - block device (or file) to modify in-place // - transfer list (blob) @@ -1382,8 +1359,7 @@ static unsigned int HashString(const char *s) { static Value* PerformBlockImageUpdate(const char* name, State* state, int /* argc */, Expr* argv[], const Command* commands, size_t cmdcount, bool dryrun) { - CommandParameters params; - memset(¶ms, 0, sizeof(params)); + CommandParameters params = {}; params.canwrite = !dryrun; fprintf(stderr, "performing %s\n", dryrun ? "verification" : "update"); @@ -1398,66 +1374,64 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg Value* patch_data_fn = nullptr; if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value, &new_data_fn, &patch_data_fn) < 0) { - return StringValue(strdup("")); + return StringValue(""); } - std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, - FreeValue); - std::unique_ptr<Value, decltype(&FreeValue)> transfer_list_value_holder(transfer_list_value, - FreeValue); - std::unique_ptr<Value, decltype(&FreeValue)> new_data_fn_holder(new_data_fn, FreeValue); - std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue); + std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename); + std::unique_ptr<Value> transfer_list_value_holder(transfer_list_value); + std::unique_ptr<Value> new_data_fn_holder(new_data_fn); + std::unique_ptr<Value> patch_data_fn_holder(patch_data_fn); if (blockdev_filename->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } if (transfer_list_value->type != VAL_BLOB) { ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name); - return StringValue(strdup("")); + return StringValue(""); } if (new_data_fn->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } if (patch_data_fn->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie); if (ui == nullptr) { - return StringValue(strdup("")); + return StringValue(""); } FILE* cmd_pipe = ui->cmd_pipe; - ZipArchive* za = ui->package_zip; + ZipArchiveHandle za = ui->package_zip; if (cmd_pipe == nullptr || za == nullptr) { - return StringValue(strdup("")); + return StringValue(""); } - const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data); - if (patch_entry == nullptr) { - fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data); - return StringValue(strdup("")); + ZipString path_data(patch_data_fn->data.c_str()); + ZipEntry patch_entry; + if (FindEntry(za, path_data, &patch_entry) != 0) { + fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data.c_str()); + return StringValue(""); } - params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry); - const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data); - if (new_entry == nullptr) { - fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data); - return StringValue(strdup("")); + params.patch_start = ui->package_zip_addr + patch_entry.offset; + ZipString new_data(new_data_fn->data.c_str()); + ZipEntry new_entry; + if (FindEntry(za, new_data, &new_entry) != 0) { + fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data.c_str()); + return StringValue(""); } - params.fd = TEMP_FAILURE_RETRY(open(blockdev_filename->data, O_RDWR)); - unique_fd fd_holder(params.fd); - + params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data.c_str(), O_RDWR))); if (params.fd == -1) { - fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data, strerror(errno)); - return StringValue(strdup("")); + fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data.c_str(), strerror(errno)); + return StringValue(""); } if (params.canwrite) { @@ -1473,24 +1447,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg int error = pthread_create(¶ms.thread, &attr, unzip_new_data, ¶ms.nti); if (error != 0) { fprintf(stderr, "pthread_create failed: %s\n", strerror(error)); - return StringValue(strdup("")); + return StringValue(""); } } - // Copy all the lines in transfer_list_value into std::string for - // processing. - const std::string transfer_list(transfer_list_value->data, transfer_list_value->size); - std::vector<std::string> lines = android::base::Split(transfer_list, "\n"); + std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n"); if (lines.size() < 2) { ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n", lines.size()); - return StringValue(strdup("")); + return StringValue(""); } // First line in transfer list is the version number if (!android::base::ParseInt(lines[0].c_str(), ¶ms.version, 1, 4)) { fprintf(stderr, "unexpected transfer list version [%s]\n", lines[0].c_str()); - return StringValue(strdup("")); + return StringValue(""); } fprintf(stderr, "blockimg version is %d\n", params.version); @@ -1499,11 +1470,11 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg int total_blocks; if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) { ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str()); - return StringValue(strdup("")); + return StringValue(""); } if (total_blocks == 0) { - return StringValue(strdup("t")); + return StringValue("t"); } size_t start = 2; @@ -1511,7 +1482,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg if (lines.size() < 4) { ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n", lines.size()); - return StringValue(strdup("")); + return StringValue(""); } // Third line is how many stash entries are needed simultaneously @@ -1522,12 +1493,12 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) { ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n", lines[3].c_str()); - return StringValue(strdup("")); + return StringValue(""); } - int res = CreateStash(state, stash_max_blocks, blockdev_filename->data, params.stashbase); + int res = CreateStash(state, stash_max_blocks, blockdev_filename->data.c_str(), params.stashbase); if (res == -1) { - return StringValue(strdup("")); + return StringValue(""); } params.createdstash = res; @@ -1535,13 +1506,15 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg start += 2; } - // Build a hash table of the available commands - HashTable* cmdht = mzHashTableCreate(cmdcount, nullptr); - std::unique_ptr<HashTable, decltype(&mzHashTableFree)> cmdht_holder(cmdht, mzHashTableFree); - + // Build a map of the available commands + std::unordered_map<std::string, const Command*> cmd_map; for (size_t i = 0; i < cmdcount; ++i) { - unsigned int cmdhash = HashString(commands[i].name); - mzHashTableLookup(cmdht, cmdhash, (void*) &commands[i], CompareCommands, true); + if (cmd_map.find(commands[i].name) != cmd_map.end()) { + fprintf(stderr, "Error: command [%s] already exists in the cmd map.\n", + commands[i].name); + return StringValue(strdup("")); + } + cmd_map[commands[i].name] = &commands[i]; } int rc = -1; @@ -1558,16 +1531,13 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg params.cmdname = params.tokens[params.cpos++].c_str(); params.cmdline = line_str.c_str(); - unsigned int cmdhash = HashString(params.cmdname); - const Command* cmd = reinterpret_cast<const Command*>(mzHashTableLookup(cmdht, cmdhash, - const_cast<char*>(params.cmdname), CompareCommandNames, - false)); - - if (cmd == nullptr) { + if (cmd_map.find(params.cmdname) == cmd_map.end()) { fprintf(stderr, "unexpected command [%s]\n", params.cmdname); goto pbiudone; } + const Command* cmd = cmd_map[params.cmdname]; + if (cmd->f != nullptr && cmd->f(params) == -1) { fprintf(stderr, "failed to execute command [%s]\n", line_str.c_str()); goto pbiudone; @@ -1591,7 +1561,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg fprintf(stderr, "stashed %zu blocks\n", params.stashed); fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size()); - const char* partition = strrchr(blockdev_filename->data, '/'); + const char* partition = strrchr(blockdev_filename->data.c_str(), '/'); if (partition != nullptr && *(partition+1) != 0) { fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1, params.written * BLOCKSIZE); @@ -1613,7 +1583,7 @@ pbiudone: failure_type = kFsyncFailure; fprintf(stderr, "fsync failed: %s\n", strerror(errno)); } - // params.fd will be automatically closed because of the fd_holder above. + // params.fd will be automatically closed because it's a unique_fd. // Only delete the stash if the update cannot be resumed, or it's // a verification run and we created the stash. @@ -1625,7 +1595,7 @@ pbiudone: state->cause_code = failure_type; } - return StringValue(rc == 0 ? strdup("t") : strdup("")); + return StringValue(rc == 0 ? "t" : ""); } // The transfer list is a text file containing commands to @@ -1723,28 +1693,26 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) Value* ranges; if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) { - return StringValue(strdup("")); + return StringValue(""); } - std::unique_ptr<Value, decltype(&FreeValue)> ranges_holder(ranges, FreeValue); - std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, - FreeValue); + std::unique_ptr<Value> ranges_holder(ranges); + std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename); if (blockdev_filename->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } if (ranges->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } - int fd = open(blockdev_filename->data, O_RDWR); - unique_fd fd_holder(fd); - if (fd < 0) { - ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data, - strerror(errno)); - return StringValue(strdup("")); + android::base::unique_fd fd(ota_open(blockdev_filename->data.c_str(), O_RDWR)); + if (fd == -1) { + ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", + blockdev_filename->data.c_str(), strerror(errno)); + return StringValue(""); } RangeSet rs; @@ -1756,16 +1724,16 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) std::vector<uint8_t> buffer(BLOCKSIZE); for (size_t i = 0; i < rs.count; ++i) { if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) { - ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data, - strerror(errno)); - return StringValue(strdup("")); + ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", + blockdev_filename->data.c_str(), strerror(errno)); + return StringValue(""); } for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) { if (read_all(fd, buffer, BLOCKSIZE) == -1) { - ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data, - strerror(errno)); - return StringValue(strdup("")); + ErrorAbort(state, kFreadFailure, "failed to read %s: %s", + blockdev_filename->data.c_str(), strerror(errno)); + return StringValue(""); } SHA1_Update(&ctx, buffer.data(), BLOCKSIZE); @@ -1774,7 +1742,7 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) uint8_t digest[SHA_DIGEST_LENGTH]; SHA1_Final(digest, &ctx); - return StringValue(strdup(print_sha1(digest).c_str())); + return StringValue(print_sha1(digest)); } // This function checks if a device has been remounted R/W prior to an incremental @@ -1788,28 +1756,27 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) if (ReadValueArgs(state, argv, 1, &arg_filename) < 0) { return nullptr; } - std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); + std::unique_ptr<Value> filename(arg_filename); if (filename->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } - int fd = open(arg_filename->data, O_RDONLY); - unique_fd fd_holder(fd); + android::base::unique_fd fd(ota_open(arg_filename->data.c_str(), O_RDONLY)); if (fd == -1) { - ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data, + ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data.c_str(), strerror(errno)); - return StringValue(strdup("")); + return StringValue(""); } RangeSet blk0 {1 /*count*/, 1/*size*/, std::vector<size_t> {0, 1}/*position*/}; std::vector<uint8_t> block0_buffer(BLOCKSIZE); if (ReadBlocks(blk0, block0_buffer, fd) == -1) { - ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data, + ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data.c_str(), strerror(errno)); - return StringValue(strdup("")); + return StringValue(""); } // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout @@ -1827,7 +1794,7 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) uiPrintf(state, "Last remount happened on %s", ctime(&mount_time)); } - return StringValue(strdup("t")); + return StringValue("t"); } @@ -1839,40 +1806,40 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[ return NULL; } - std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); - std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue); + std::unique_ptr<Value> filename(arg_filename); + std::unique_ptr<Value> ranges(arg_ranges); if (filename->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } if (ranges->type != VAL_STRING) { ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); - return StringValue(strdup("")); + return StringValue(""); } // Output notice to log when recover is attempted - fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data); + fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data.c_str()); // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read - fec::io fh(filename->data, O_RDWR); + fec::io fh(filename->data.c_str(), O_RDWR); if (!fh) { - ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data, + ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data.c_str(), strerror(errno)); - return StringValue(strdup("")); + return StringValue(""); } if (!fh.has_ecc() || !fh.has_verity()) { ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors"); - return StringValue(strdup("")); + return StringValue(""); } fec_status status; if (!fh.get_status(status)) { ErrorAbort(state, kLibfecFailure, "failed to read FEC status"); - return StringValue(strdup("")); + return StringValue(""); } RangeSet rs; @@ -1889,8 +1856,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[ if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) { ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s", - filename->data, j, strerror(errno)); - return StringValue(strdup("")); + filename->data.c_str(), j, strerror(errno)); + return StringValue(""); } // If we want to be able to recover from a situation where rewriting a corrected @@ -1905,8 +1872,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[ // read and check if the errors field value has increased. } } - fprintf(stderr, "...%s image recovered successfully.\n", filename->data); - return StringValue(strdup("t")); + fprintf(stderr, "...%s image recovered successfully.\n", filename->data.c_str()); + return StringValue("t"); } void RegisterBlockImageFunctions() { diff --git a/updater/blockimg.h b/updater/include/updater/blockimg.h index 2f4ad3c04..2f4ad3c04 100644 --- a/updater/blockimg.h +++ b/updater/include/updater/blockimg.h diff --git a/updater/install.h b/updater/include/updater/install.h index 70e343404..8d6ca4728 100644 --- a/updater/install.h +++ b/updater/include/updater/install.h @@ -17,11 +17,12 @@ #ifndef _UPDATER_INSTALL_H_ #define _UPDATER_INSTALL_H_ +struct State; + void RegisterInstallFunctions(); // uiPrintf function prints msg to screen as well as logs -void uiPrintf(State* state, const char* format, ...); - -static int make_parents(char* name); +void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) + __attribute__((__format__(printf, 2, 3))); #endif diff --git a/updater/updater.h b/updater/include/updater/updater.h index d1dfdd05e..f4a2fe874 100644 --- a/updater/updater.h +++ b/updater/include/updater/updater.h @@ -18,20 +18,18 @@ #define _UPDATER_UPDATER_H_ #include <stdio.h> -#include "minzip/Zip.h" - -#include <selinux/selinux.h> -#include <selinux/label.h> +#include <ziparchive/zip_archive.h> typedef struct { FILE* cmd_pipe; - ZipArchive* package_zip; + ZipArchiveHandle package_zip; int version; uint8_t* package_zip_addr; size_t package_zip_len; } UpdaterInfo; +struct selabel_handle; extern struct selabel_handle *sehandle; #endif diff --git a/updater/install.cpp b/updater/install.cpp index 005f9f97d..a41c5db3c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -14,53 +14,54 @@ * limitations under the License. */ +#include "updater/install.h" + #include <ctype.h> #include <errno.h> +#include <fcntl.h> +#include <ftw.h> +#include <inttypes.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/capability.h> #include <sys/mount.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <time.h> -#include <selinux/selinux.h> -#include <ftw.h> -#include <sys/capability.h> #include <sys/xattr.h> -#include <linux/xattr.h> -#include <inttypes.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> #include <memory> +#include <string> #include <vector> #include <android-base/parseint.h> +#include <android-base/properties.h> #include <android-base/strings.h> #include <android-base/stringprintf.h> +#include <cutils/android_reboot.h> +#include <ext4_utils/make_ext4fs.h> +#include <ext4_utils/wipe.h> +#include <openssl/sha.h> +#include <selinux/label.h> +#include <selinux/selinux.h> +#include <ziparchive/zip_archive.h> -#include "bootloader.h" #include "applypatch/applypatch.h" -#include "cutils/android_reboot.h" -#include "cutils/misc.h" -#include "cutils/properties.h" +#include "bootloader.h" #include "edify/expr.h" #include "error_code.h" -#include "minzip/DirUtil.h" -#include "mtdutils/mounts.h" -#include "mtdutils/mtdutils.h" -#include "openssl/sha.h" +#include "mounts.h" #include "ota_io.h" -#include "updater.h" -#include "install.h" +#include "otautil/DirUtil.h" +#include "otautil/ZipUtil.h" +#include "print_sha1.h" #include "tune2fs.h" - -#ifdef USE_EXT4 -#include "make_ext4fs.h" -#include "wipe.h" -#endif +#include "updater/updater.h" // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { @@ -82,8 +83,7 @@ static void uiPrint(State* state, const std::string& buffer) { fprintf(stderr, "%s", buffer.c_str()); } -__attribute__((__format__(printf, 2, 3))) __nonnull((2)) -void uiPrintf(State* state, const char* format, ...) { +void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { std::string error_msg; va_list ap; @@ -94,25 +94,32 @@ void uiPrintf(State* state, const char* format, ...) { uiPrint(state, error_msg); } -// Take a sha-1 digest and return it as a newly-allocated hex string. -char* PrintSha1(const uint8_t* digest) { - char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_LENGTH*2 + 1)); - const char* alphabet = "0123456789abcdef"; - size_t i; - for (i = 0; i < SHA_DIGEST_LENGTH; ++i) { - buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; - buffer[i*2+1] = alphabet[digest[i] & 0xf]; - } - buffer[i*2] = '\0'; - return buffer; +// Create all parent directories of name, if necessary. +static int make_parents(char* name) { + char* p; + for (p = name + (strlen(name)-1); p > name; --p) { + if (*p != '/') continue; + *p = '\0'; + if (make_parents(name) < 0) return -1; + int result = mkdir(name, 0700); + if (result == 0) printf("created [%s]\n", name); + *p = '/'; + if (result == 0 || errno == EEXIST) { + // successfully created or already existed; we're done + return 0; + } else { + printf("failed to mkdir %s: %s\n", name, strerror(errno)); + return -1; + } + } + return 0; } // mount(fs_type, partition_type, location, mount_point) // -// fs_type="yaffs2" partition_type="MTD" location=partition // fs_type="ext4" partition_type="EMMC" location=device Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; + char* result = nullptr; if (argc != 4 && argc != 5) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); } @@ -171,33 +178,14 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { } } - if (strcmp(partition_type, "MTD") == 0) { - mtd_scan_partitions(); - const MtdPartition* mtd; - mtd = mtd_find_partition_by_name(location); - if (mtd == NULL) { - uiPrintf(state, "%s: no mtd partition named \"%s\"\n", - name, location); - result = strdup(""); - goto done; - } - if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) { - uiPrintf(state, "mtd mount of %s failed: %s\n", - location, strerror(errno)); - result = strdup(""); - goto done; - } - result = mount_point; + if (mount(location, mount_point, fs_type, + MS_NOATIME | MS_NODEV | MS_NODIRATIME, + has_mount_options ? mount_options : "") < 0) { + uiPrintf(state, "%s: failed to mount %s at %s: %s\n", + name, location, mount_point, strerror(errno)); + result = strdup(""); } else { - if (mount(location, mount_point, fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, - has_mount_options ? mount_options : "") < 0) { - uiPrintf(state, "%s: failed to mount %s at %s: %s\n", - name, location, mount_point, strerror(errno)); - result = strdup(""); - } else { - result = mount_point; - } + result = mount_point; } done: @@ -212,7 +200,7 @@ done: // is_mounted(mount_point) Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; + char* result = nullptr; if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } @@ -227,7 +215,7 @@ Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { scan_mounted_volumes(); { - const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); if (vol == NULL) { result = strdup(""); } else { @@ -242,7 +230,7 @@ done: Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; + char* result = nullptr; if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } @@ -257,7 +245,7 @@ Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { scan_mounted_volumes(); { - const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); if (vol == NULL) { uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point); result = strdup(""); @@ -293,14 +281,13 @@ static int exec_cmd(const char* path, char* const argv[]) { // format(fs_type, partition_type, location, fs_size, mount_point) // -// fs_type="yaffs2" partition_type="MTD" location=partition fs_size=<bytes> mount_point=<location> // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> // fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> // if fs_size == 0, then make fs uses the entire partition. // if fs_size > 0, that is the size to use // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; + char* result = nullptr; if (argc != 5) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); } @@ -334,35 +321,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } - if (strcmp(partition_type, "MTD") == 0) { - mtd_scan_partitions(); - const MtdPartition* mtd = mtd_find_partition_by_name(location); - if (mtd == NULL) { - printf("%s: no mtd partition named \"%s\"", - name, location); - result = strdup(""); - goto done; - } - MtdWriteContext* ctx = mtd_write_partition(mtd); - if (ctx == NULL) { - printf("%s: can't write \"%s\"", name, location); - result = strdup(""); - goto done; - } - if (mtd_erase_blocks(ctx, -1) == -1) { - mtd_write_close(ctx); - printf("%s: failed to erase \"%s\"", name, location); - result = strdup(""); - goto done; - } - if (mtd_write_close(ctx) != 0) { - printf("%s: failed to close \"%s\"", name, location); - result = strdup(""); - goto done; - } - result = location; -#ifdef USE_EXT4 - } else if (strcmp(fs_type, "ext4") == 0) { + if (strcmp(fs_type, "ext4") == 0) { int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle); if (status != 0) { printf("%s: make_ext4fs failed (%d) on %s", @@ -389,7 +348,6 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } result = location; -#endif } else { printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", name, fs_type, partition_type); @@ -403,7 +361,7 @@ done: } Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; + char* result = nullptr; if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } @@ -442,15 +400,10 @@ done: } Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - char** paths = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); + std::vector<std::string> paths; for (int i = 0; i < argc; ++i) { - paths[i] = Evaluate(state, argv[i]); - if (paths[i] == NULL) { - for (int j = 0; j < i; ++j) { - free(paths[j]); - } - free(paths); - return NULL; + if (!Evaluate(state, argv[i], &paths[i])) { + return nullptr; } } @@ -458,15 +411,12 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { int success = 0; for (int i = 0; i < argc; ++i) { - if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0) + if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) { ++success; - free(paths[i]); + } } - free(paths); - char buffer[10]; - sprintf(buffer, "%d", success); - return StringValue(strdup(buffer)); + return StringValue(android::base::StringPrintf("%d", success)); } @@ -518,17 +468,16 @@ Value* PackageExtractDirFn(const char* name, State* state, char* dest_path; if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; + ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; // To create a consistent system image, never use the clock for timestamps. struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default - bool success = mzExtractRecursive(za, zip_path, dest_path, - ×tamp, - NULL, NULL, sehandle); + bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle); + free(zip_path); free(dest_path); - return StringValue(strdup(success ? "t" : "")); + return StringValue(success ? "t" : ""); } @@ -548,26 +497,27 @@ Value* PackageExtractFileFn(const char* name, State* state, if (argc == 2) { // The two-argument version extracts to a file. - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; + ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; char* zip_path; char* dest_path; if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; - const ZipEntry* entry = mzFindZipEntry(za, zip_path); - if (entry == NULL) { + ZipString zip_string_path(zip_path); + ZipEntry entry; + if (FindEntry(za, zip_string_path, &entry) != 0) { printf("%s: no %s in package\n", name, zip_path); goto done2; } { - int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, + int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); if (fd == -1) { printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno)); goto done2; } - success = mzExtractZipEntryToFile(za, entry, fd); + success = ExtractEntryToFile(za, &entry, fd); if (ota_fsync(fd) == -1) { printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno)); success = false; @@ -581,7 +531,7 @@ Value* PackageExtractFileFn(const char* name, State* state, done2: free(zip_path); free(dest_path); - return StringValue(strdup(success ? "t" : "")); + return StringValue(success ? "t" : ""); } else { // The one-argument version returns the contents of the file // as the result. @@ -589,59 +539,33 @@ Value* PackageExtractFileFn(const char* name, State* state, char* zip_path; if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; - Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); - v->type = VAL_BLOB; - v->size = -1; - v->data = NULL; + Value* v = new Value(VAL_INVALID, ""); - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; - const ZipEntry* entry = mzFindZipEntry(za, zip_path); - if (entry == NULL) { + ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; + ZipString zip_string_path(zip_path); + ZipEntry entry; + if (FindEntry(za, zip_string_path, &entry) != 0) { printf("%s: no %s in package\n", name, zip_path); goto done1; } - v->size = mzGetZipEntryUncompLen(entry); - v->data = reinterpret_cast<char*>(malloc(v->size)); - if (v->data == NULL) { - printf("%s: failed to allocate %ld bytes for %s\n", - name, (long)v->size, zip_path); - goto done1; + v->data.resize(entry.uncompressed_length); + if (ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&v->data[0]), + v->data.size()) != 0) { + printf("%s: faled to extract %zu bytes to memory\n", name, v->data.size()); + } else { + success = true; } - success = mzExtractZipEntryToBuffer(za, entry, - (unsigned char *)v->data); - done1: free(zip_path); if (!success) { - free(v->data); - v->data = NULL; - v->size = -1; - } - return v; - } -} - -// Create all parent directories of name, if necessary. -static int make_parents(char* name) { - char* p; - for (p = name + (strlen(name)-1); p > name; --p) { - if (*p != '/') continue; - *p = '\0'; - if (make_parents(name) < 0) return -1; - int result = mkdir(name, 0700); - if (result == 0) printf("created [%s]\n", name); - *p = '/'; - if (result == 0 || errno == EEXIST) { - // successfully created or already existed; we're done - return 0; + v->data.clear(); } else { - printf("failed to mkdir %s: %s\n", name, strerror(errno)); - return -1; + v->type = VAL_BLOB; } + return v; } - return 0; } // symlink target src1 src2 ... @@ -650,13 +574,13 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc == 0) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); } - char* target; - target = Evaluate(state, argv[0]); - if (target == NULL) return NULL; + std::string target; + if (!Evaluate(state, argv[0], &target)) { + return nullptr; + } char** srcs = ReadVarArgs(state, argc-1, argv+1); if (srcs == NULL) { - free(target); return NULL; } @@ -672,12 +596,12 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { } if (make_parents(srcs[i])) { printf("%s: failed to symlink %s to %s: making parents failed\n", - name, srcs[i], target); + name, srcs[i], target.c_str()); ++bad; } - if (symlink(target, srcs[i]) < 0) { + if (symlink(target.c_str(), srcs[i]) < 0) { printf("%s: failed to symlink %s to %s: %s\n", - name, srcs[i], target, strerror(errno)); + name, srcs[i], target.c_str(), strerror(errno)); ++bad; } free(srcs[i]); @@ -686,7 +610,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { if (bad) { return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); } - return StringValue(strdup("")); + return StringValue(""); } struct perm_parsed_args { @@ -949,21 +873,20 @@ done: return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); } - return StringValue(strdup("")); + return StringValue(""); } Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } - char* key = Evaluate(state, argv[0]); - if (key == NULL) return NULL; - - char value[PROPERTY_VALUE_MAX]; - property_get(key, value, ""); - free(key); + std::string key; + if (!Evaluate(state, argv[0], &key)) { + return nullptr; + } + std::string value = android::base::GetProperty(key, ""); - return StringValue(strdup(value)); + return StringValue(value); } @@ -998,13 +921,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { buffer = reinterpret_cast<char*>(malloc(st.st_size+1)); if (buffer == NULL) { - ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %lld bytes", name, - (long long)st.st_size+1); + ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %zu bytes", name, + static_cast<size_t>(st.st_size+1)); goto done; } FILE* f; - f = fopen(filename, "rb"); + f = ota_fopen(filename, "rb"); if (f == NULL) { ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename, strerror(errno)); @@ -1012,14 +935,14 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) { - ErrorAbort(state, kFreadFailure, "%s: failed to read %lld bytes from %s", - name, (long long)st.st_size+1, filename); - fclose(f); + ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", + name, static_cast<size_t>(st.st_size), filename); + ota_fclose(f); goto done; } buffer[st.st_size] = '\0'; - fclose(f); + ota_fclose(f); char* line; line = strtok(buffer, "\n"); @@ -1066,98 +989,6 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -// write_raw_image(filename_or_blob, partition) -Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; - - Value* partition_value; - Value* contents; - if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) { - return NULL; - } - - char* partition = NULL; - if (partition_value->type != VAL_STRING) { - ErrorAbort(state, kArgsParsingFailure, "partition argument to %s must be string", name); - goto done; - } - partition = partition_value->data; - if (strlen(partition) == 0) { - ErrorAbort(state, kArgsParsingFailure, "partition argument to %s can't be empty", name); - goto done; - } - if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) { - ErrorAbort(state, kArgsParsingFailure, "file argument to %s can't be empty", name); - goto done; - } - - mtd_scan_partitions(); - const MtdPartition* mtd; - mtd = mtd_find_partition_by_name(partition); - if (mtd == NULL) { - printf("%s: no mtd partition named \"%s\"\n", name, partition); - result = strdup(""); - goto done; - } - - MtdWriteContext* ctx; - ctx = mtd_write_partition(mtd); - if (ctx == NULL) { - printf("%s: can't write mtd partition \"%s\"\n", - name, partition); - result = strdup(""); - goto done; - } - - bool success; - - if (contents->type == VAL_STRING) { - // we're given a filename as the contents - char* filename = contents->data; - FILE* f = ota_fopen(filename, "rb"); - if (f == NULL) { - printf("%s: can't open %s: %s\n", name, filename, strerror(errno)); - result = strdup(""); - goto done; - } - - success = true; - char* buffer = reinterpret_cast<char*>(malloc(BUFSIZ)); - int read; - while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) { - int wrote = mtd_write_data(ctx, buffer, read); - success = success && (wrote == read); - } - free(buffer); - ota_fclose(f); - } else { - // we're given a blob as the contents - ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size); - success = (wrote == contents->size); - } - if (!success) { - printf("mtd_write_data to %s failed: %s\n", - partition, strerror(errno)); - } - - if (mtd_erase_blocks(ctx, -1) == -1) { - printf("%s: error erasing blocks of %s\n", name, partition); - } - if (mtd_write_close(ctx) != 0) { - printf("%s: error closing write of %s\n", name, partition); - } - - printf("%s %s partition\n", - success ? "wrote" : "failed to write", partition); - - result = success ? partition : strdup(""); - -done: - if (result != partition) FreeValue(partition_value); - FreeValue(contents); - return StringValue(result); -} - // apply_patch_space(bytes) Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1174,7 +1005,7 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, return nullptr; } - return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); + return StringValue(CacheSizeCheck(bytes) ? "" : "t"); } // apply_patch(file, size, init_sha1, tgt_sha1, patch) @@ -1206,17 +1037,16 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } int patchcount = (argc-4) / 2; - std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4), - free); + std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc-4, argv+4)); if (!arg_values) { return nullptr; } - std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas; - std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches; + std::vector<std::unique_ptr<Value>> patch_shas; + std::vector<std::unique_ptr<Value>> patches; // Protect values by unique_ptrs first to get rid of memory leak. for (int i = 0; i < patchcount * 2; i += 2) { - patch_shas.emplace_back(arg_values.get()[i], FreeValue); - patches.emplace_back(arg_values.get()[i+1], FreeValue); + patch_shas.emplace_back(arg_values.get()[i]); + patches.emplace_back(arg_values.get()[i+1]); } for (int i = 0; i < patchcount; ++i) { @@ -1230,7 +1060,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } } - std::vector<char*> patch_sha_str; + std::vector<std::string> patch_sha_str; std::vector<Value*> patch_ptrs; for (int i = 0; i < patchcount; ++i) { patch_sha_str.push_back(patch_shas[i]->data); @@ -1239,9 +1069,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { int result = applypatch(source_filename, target_filename, target_sha1, target_size, - patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL); + patch_sha_str, patch_ptrs.data(), NULL); - return StringValue(strdup(result == 0 ? "t" : "")); + return StringValue(result == 0 ? "t" : ""); } // apply_patch_check(file, [sha1_1, ...]) @@ -1254,21 +1084,17 @@ Value* ApplyPatchCheckFn(const char* name, State* state, char* filename; if (ReadArgs(state, argv, 1, &filename) < 0) { - return NULL; + return nullptr; } - int patchcount = argc-1; - char** sha1s = ReadVarArgs(state, argc-1, argv+1); - - int result = applypatch_check(filename, patchcount, sha1s); - - int i; - for (i = 0; i < patchcount; ++i) { - free(sha1s[i]); + std::vector<std::string> sha1s; + if (!ReadArgs(state, argc-1, argv+1, &sha1s)) { + return nullptr; } - free(sha1s); - return StringValue(strdup(result == 0 ? "t" : "")); + int result = applypatch_check(filename, sha1s); + + return StringValue(result == 0 ? "t" : ""); } // This is the updater side handler for ui_print() in edify script. Contents @@ -1288,7 +1114,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { buffer += "\n"; uiPrint(state, buffer); - return StringValue(strdup(buffer.c_str())); + return StringValue(buffer); } Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1296,7 +1122,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); } fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); - return StringValue(strdup("t")); + return StringValue("t"); } Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1339,10 +1165,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { free(args); free(args2); - char buffer[20]; - sprintf(buffer, "%d", status); - - return StringValue(strdup(buffer)); + return StringValue(android::base::StringPrintf("%d", status)); } // sha1_check(data) @@ -1358,45 +1181,40 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } - std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free); + std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc, argv)); if (arg_values == nullptr) { return nullptr; } - std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args; + std::vector<std::unique_ptr<Value>> args; for (int i = 0; i < argc; ++i) { - args.emplace_back(arg_values.get()[i], FreeValue); + args.emplace_back(arg_values.get()[i]); } - if (args[0]->size < 0) { - return StringValue(strdup("")); + if (args[0]->type == VAL_INVALID) { + return StringValue(""); } uint8_t digest[SHA_DIGEST_LENGTH]; - SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest); + SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest); if (argc == 1) { - return StringValue(PrintSha1(digest)); + return StringValue(print_sha1(digest)); } - int i; - uint8_t arg_digest[SHA_DIGEST_LENGTH]; - for (i = 1; i < argc; ++i) { + for (int i = 1; i < argc; ++i) { + uint8_t arg_digest[SHA_DIGEST_LENGTH]; if (args[i]->type != VAL_STRING) { - printf("%s(): arg %d is not a string; skipping", - name, i); - } else if (ParseSha1(args[i]->data, arg_digest) != 0) { + printf("%s(): arg %d is not a string; skipping", name, i); + } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) { // Warn about bad args and skip them. - printf("%s(): error parsing \"%s\" as sha-1; skipping", - name, args[i]->data); + printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data.c_str()); } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { - break; + // Found a match. + return args[i].release(); } } - if (i >= argc) { - // Didn't match any of the hex strings; return false. - return StringValue(strdup("")); - } - // Found a match. - return args[i].release(); + + // Didn't match any of the hex strings; return false. + return StringValue(""); } // Read a local file and return its contents (the Value* returned @@ -1408,21 +1226,12 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { char* filename; if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; - Value* v = static_cast<Value*>(malloc(sizeof(Value))); - if (v == nullptr) { - return nullptr; - } - v->type = VAL_BLOB; - v->size = -1; - v->data = nullptr; + Value* v = new Value(VAL_INVALID, ""); FileContents fc; if (LoadFileContents(filename, &fc) == 0) { - v->data = static_cast<char*>(malloc(fc.data.size())); - if (v->data != nullptr) { - memcpy(v->data, fc.data.data(), fc.data.size()); - v->size = fc.data.size(); - } + v->type = VAL_BLOB; + v->data = std::string(fc.data.begin(), fc.data.end()); } free(filename); return v; @@ -1446,22 +1255,18 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { char* property; if (ReadArgs(state, argv, 2, &filename, &property) < 0) return NULL; - char buffer[80]; - // zero out the 'command' field of the bootloader message. + char buffer[80]; memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); - FILE* f = fopen(filename, "r+b"); + FILE* f = ota_fopen(filename, "r+b"); fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); - fclose(f); + ota_fclose(f); free(filename); - strcpy(buffer, "reboot,"); - if (property != NULL) { - strncat(buffer, property, sizeof(buffer)-10); - } - - property_set(ANDROID_RB_PROPERTY, buffer); + std::string reboot_cmd = "reboot,"; + if (property != nullptr) reboot_cmd += property; + android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); sleep(5); free(property); @@ -1492,18 +1297,21 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // bootloader message that the main recovery uses to save its // arguments in case of the device restarting midway through // package installation. - FILE* f = fopen(filename, "r+b"); + FILE* f = ota_fopen(filename, "r+b"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - int to_write = strlen(stagestr)+1; - int max_size = sizeof(((struct bootloader_message*)0)->stage); + size_t to_write = strlen(stagestr) + 1; + size_t max_size = sizeof(((struct bootloader_message*)0)->stage); if (to_write > max_size) { to_write = max_size; - stagestr[max_size-1] = 0; + stagestr[max_size - 1] = 0; } - ota_fwrite(stagestr, to_write, 1, f); - fclose(f); + size_t status = ota_fwrite(stagestr, to_write, 1, f); + ota_fclose(f); free(stagestr); + if (status != to_write) { + return StringValue(""); + } return StringValue(filename); } @@ -1518,13 +1326,16 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; char buffer[sizeof(((struct bootloader_message*)0)->stage)]; - FILE* f = fopen(filename, "rb"); + FILE* f = ota_fopen(filename, "rb"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - ota_fread(buffer, sizeof(buffer), 1, f); - fclose(f); - buffer[sizeof(buffer)-1] = '\0'; + size_t status = ota_fread(buffer, sizeof(buffer), 1, f); + ota_fclose(f); + if (status != sizeof(buffer)) { + return StringValue(""); + } - return StringValue(strdup(buffer)); + buffer[sizeof(buffer)-1] = '\0'; + return StringValue(buffer); } Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1546,7 +1357,7 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) ota_close(fd); - return StringValue(strdup(success ? "t" : "")); + return StringValue(success ? "t" : ""); } Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1555,7 +1366,7 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { } UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); fprintf(ui->cmd_pipe, "enable_reboot\n"); - return StringValue(strdup("t")); + return StringValue("t"); } Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1586,7 +1397,7 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); } - return StringValue(strdup("t")); + return StringValue("t"); } void RegisterInstallFunctions() { @@ -1616,7 +1427,6 @@ void RegisterInstallFunctions() { RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); - RegisterFunction("write_raw_image", WriteRawImageFn); RegisterFunction("apply_patch", ApplyPatchFn); RegisterFunction("apply_patch_check", ApplyPatchCheckFn); diff --git a/updater/updater.cpp b/updater/updater.cpp index e956dd557..7327c52e3 100644 --- a/updater/updater.cpp +++ b/updater/updater.cpp @@ -14,18 +14,26 @@ * limitations under the License. */ +#include "updater/updater.h" + #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> -#include "edify/expr.h" -#include "updater.h" -#include "install.h" -#include "blockimg.h" -#include "minzip/Zip.h" -#include "minzip/SysUtil.h" +#include <string> + +#include <android-base/strings.h> +#include <selinux/label.h> +#include <selinux/selinux.h> +#include <ziparchive/zip_archive.h> + #include "config.h" +#include "edify/expr.h" +#include "otautil/DirUtil.h" +#include "otautil/SysUtil.h" +#include "updater/blockimg.h" +#include "updater/install.h" // Generated by the makefile, this function defines the // RegisterDeviceExtensions() function, which calls all the @@ -77,28 +85,35 @@ int main(int argc, char** argv) { printf("failed to map package %s\n", argv[3]); return 3; } - ZipArchive za; - int err; - err = mzOpenZipArchive(map.addr, map.length, &za); - if (err != 0) { + ZipArchiveHandle za; + int open_err = OpenArchiveFromMemory(map.addr, map.length, argv[3], &za); + if (open_err != 0) { printf("failed to open package %s: %s\n", - argv[3], strerror(err)); + argv[3], ErrorCodeString(open_err)); + CloseArchive(za); return 3; } - ota_io_init(&za); - - const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME); - if (script_entry == NULL) { - printf("failed to find %s in %s\n", SCRIPT_NAME, package_filename); + ota_io_init(za); + + ZipString script_name(SCRIPT_NAME); + ZipEntry script_entry; + int find_err = FindEntry(za, script_name, &script_entry); + if (find_err != 0) { + printf("failed to find %s in %s: %s\n", SCRIPT_NAME, package_filename, + ErrorCodeString(find_err)); + CloseArchive(za); return 4; } - char* script = reinterpret_cast<char*>(malloc(script_entry->uncompLen+1)); - if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) { - printf("failed to read script from package\n"); + std::string script; + script.resize(script_entry.uncompressed_length); + int extract_err = ExtractToMemory(za, &script_entry, reinterpret_cast<uint8_t*>(&script[0]), + script_entry.uncompressed_length); + if (extract_err != 0) { + printf("failed to read script from package: %s\n", ErrorCodeString(extract_err)); + CloseArchive(za); return 5; } - script[script_entry->uncompLen] = '\0'; // Configure edify's functions. @@ -106,15 +121,15 @@ int main(int argc, char** argv) { RegisterInstallFunctions(); RegisterBlockImageFunctions(); RegisterDeviceExtensions(); - FinishRegistration(); // Parse the script. Expr* root; int error_count = 0; - int error = parse_string(script, &root, &error_count); + int error = parse_string(script.c_str(), &root, &error_count); if (error != 0 || error_count > 0) { printf("%d parse errors\n", error_count); + CloseArchive(za); return 6; } @@ -132,15 +147,12 @@ int main(int argc, char** argv) { UpdaterInfo updater_info; updater_info.cmd_pipe = cmd_pipe; - updater_info.package_zip = &za; + updater_info.package_zip = za; updater_info.version = atoi(version); updater_info.package_zip_addr = map.addr; updater_info.package_zip_len = map.length; - State state; - state.cookie = &updater_info; - state.script = script; - state.errmsg = NULL; + State state(script, &updater_info); if (argc == 5) { if (strcmp(argv[4], "retry") == 0) { @@ -150,29 +162,29 @@ int main(int argc, char** argv) { } } - char* result = Evaluate(&state, root); + std::string result; + bool status = Evaluate(&state, root, &result); if (have_eio_error) { fprintf(cmd_pipe, "retry_update\n"); } - if (result == NULL) { - if (state.errmsg == NULL) { + if (!status) { + if (state.errmsg.empty()) { printf("script aborted (no error message)\n"); fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); } else { - printf("script aborted: %s\n", state.errmsg); - char* line = strtok(state.errmsg, "\n"); - while (line) { + printf("script aborted: %s\n", state.errmsg.c_str()); + const std::vector<std::string> lines = android::base::Split(state.errmsg, "\n"); + for (const std::string& line : lines) { // Parse the error code in abort message. // Example: "E30: This package is for bullhead devices." - if (*line == 'E') { - if (sscanf(line, "E%u: ", &state.error_code) != 1) { - printf("Failed to parse error code: [%s]\n", line); + if (!line.empty() && line[0] == 'E') { + if (sscanf(line.c_str(), "E%u: ", &state.error_code) != 1) { + printf("Failed to parse error code: [%s]\n", line.c_str()); } } - fprintf(cmd_pipe, "ui_print %s\n", line); - line = strtok(NULL, "\n"); + fprintf(cmd_pipe, "ui_print %s\n", line.c_str()); } fprintf(cmd_pipe, "ui_print\n"); } @@ -186,18 +198,18 @@ int main(int argc, char** argv) { } } - free(state.errmsg); + if (updater_info.package_zip) { + CloseArchive(updater_info.package_zip); + } return 7; } else { - fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); - free(result); + fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result.c_str()); } if (updater_info.package_zip) { - mzCloseZipArchive(updater_info.package_zip); + CloseArchive(updater_info.package_zip); } sysReleaseMap(&map); - free(script); return 0; } diff --git a/verifier.cpp b/verifier.cpp index 16cc7cf03..82cdd3bc7 100644 --- a/verifier.cpp +++ b/verifier.cpp @@ -22,6 +22,8 @@ #include <algorithm> #include <memory> +#include <android-base/logging.h> +#include <openssl/bn.h> #include <openssl/ecdsa.h> #include <openssl/obj_mac.h> @@ -130,24 +132,24 @@ int verify_file(unsigned char* addr, size_t length, #define FOOTER_SIZE 6 if (length < FOOTER_SIZE) { - LOGE("not big enough to contain footer\n"); + LOG(ERROR) << "not big enough to contain footer"; return VERIFY_FAILURE; } unsigned char* footer = addr + length - FOOTER_SIZE; if (footer[2] != 0xff || footer[3] != 0xff) { - LOGE("footer is wrong\n"); + LOG(ERROR) << "footer is wrong"; return VERIFY_FAILURE; } size_t comment_size = footer[4] + (footer[5] << 8); size_t signature_start = footer[0] + (footer[1] << 8); - LOGI("comment is %zu bytes; signature %zu bytes from end\n", - comment_size, signature_start); + LOG(INFO) << "comment is " << comment_size << " bytes; signature is " << signature_start + << " bytes from end"; if (signature_start <= FOOTER_SIZE) { - LOGE("Signature start is in the footer"); + LOG(ERROR) << "Signature start is in the footer"; return VERIFY_FAILURE; } @@ -158,7 +160,7 @@ int verify_file(unsigned char* addr, size_t length, size_t eocd_size = comment_size + EOCD_HEADER_SIZE; if (length < eocd_size) { - LOGE("not big enough to contain EOCD\n"); + LOG(ERROR) << "not big enough to contain EOCD"; return VERIFY_FAILURE; } @@ -174,7 +176,7 @@ int verify_file(unsigned char* addr, size_t length, // magic number $50 $4b $05 $06. if (eocd[0] != 0x50 || eocd[1] != 0x4b || eocd[2] != 0x05 || eocd[3] != 0x06) { - LOGE("signature length doesn't match EOCD marker\n"); + LOG(ERROR) << "signature length doesn't match EOCD marker"; return VERIFY_FAILURE; } @@ -182,10 +184,10 @@ int verify_file(unsigned char* addr, size_t length, if (eocd[i ] == 0x50 && eocd[i+1] == 0x4b && eocd[i+2] == 0x05 && eocd[i+3] == 0x06) { // if the sequence $50 $4b $05 $06 appears anywhere after - // the real one, minzip will find the later (wrong) one, + // the real one, libziparchive will find the later (wrong) one, // which could be exploitable. Fail verification if // this sequence occurs anywhere after the real one. - LOGE("EOCD marker occurs after start of EOCD\n"); + LOG(ERROR) << "EOCD marker occurs after start of EOCD"; return VERIFY_FAILURE; } } @@ -234,12 +236,11 @@ int verify_file(unsigned char* addr, size_t length, uint8_t* signature = eocd + eocd_size - signature_start; size_t signature_size = signature_start - FOOTER_SIZE; - LOGI("signature (offset: 0x%zx, length: %zu): %s\n", - length - signature_start, signature_size, - print_hex(signature, signature_size).c_str()); + LOG(INFO) << "signature (offset: " << std::hex << (length - signature_start) << ", length: " + << signature_size << "): " << print_hex(signature, signature_size); if (!read_pkcs7(signature, signature_size, &sig_der, &sig_der_length)) { - LOGE("Could not find signature DER block\n"); + LOG(ERROR) << "Could not find signature DER block"; return VERIFY_FAILURE; } @@ -270,38 +271,38 @@ int verify_file(unsigned char* addr, size_t length, if (key.key_type == Certificate::KEY_TYPE_RSA) { if (!RSA_verify(hash_nid, hash, key.hash_len, sig_der, sig_der_length, key.rsa.get())) { - LOGI("failed to verify against RSA key %zu\n", i); + LOG(INFO) << "failed to verify against RSA key " << i; continue; } - LOGI("whole-file signature verified against RSA key %zu\n", i); + LOG(INFO) << "whole-file signature verified against RSA key " << i; free(sig_der); return VERIFY_SUCCESS; } else if (key.key_type == Certificate::KEY_TYPE_EC && key.hash_len == SHA256_DIGEST_LENGTH) { if (!ECDSA_verify(0, hash, key.hash_len, sig_der, sig_der_length, key.ec.get())) { - LOGI("failed to verify against EC key %zu\n", i); + LOG(INFO) << "failed to verify against EC key " << i; continue; } - LOGI("whole-file signature verified against EC key %zu\n", i); + LOG(INFO) << "whole-file signature verified against EC key " << i; free(sig_der); return VERIFY_SUCCESS; } else { - LOGI("Unknown key type %d\n", key.key_type); + LOG(INFO) << "Unknown key type " << key.key_type; } i++; } if (need_sha1) { - LOGI("SHA-1 digest: %s\n", print_hex(sha1, SHA_DIGEST_LENGTH).c_str()); + LOG(INFO) << "SHA-1 digest: " << print_hex(sha1, SHA_DIGEST_LENGTH); } if (need_sha256) { - LOGI("SHA-256 digest: %s\n", print_hex(sha256, SHA256_DIGEST_LENGTH).c_str()); + LOG(INFO) << "SHA-256 digest: " << print_hex(sha256, SHA256_DIGEST_LENGTH); } free(sig_der); - LOGE("failed to verify whole-file signature\n"); + LOG(ERROR) << "failed to verify whole-file signature"; return VERIFY_FAILURE; } @@ -322,7 +323,7 @@ std::unique_ptr<RSA, RSADeleter> parse_rsa_key(FILE* file, uint32_t exponent) { } if (key_len_words > 8192 / 32) { - LOGE("key length (%d) too large\n", key_len_words); + LOG(ERROR) << "key length (" << key_len_words << ") too large"; return nullptr; } @@ -478,7 +479,7 @@ std::unique_ptr<EC_KEY, ECKEYDeleter> parse_ec_key(FILE* file) { bool load_keys(const char* filename, std::vector<Certificate>& certs) { std::unique_ptr<FILE, decltype(&fclose)> f(fopen(filename, "r"), fclose); if (!f) { - LOGE("opening %s: %s\n", filename, strerror(errno)); + PLOG(ERROR) << "error opening " << filename; return false; } @@ -528,14 +529,14 @@ bool load_keys(const char* filename, std::vector<Certificate>& certs) { return false; } - LOGI("read key e=%d hash=%d\n", exponent, cert.hash_len); + LOG(INFO) << "read key e=" << exponent << " hash=" << cert.hash_len; } else if (cert.key_type == Certificate::KEY_TYPE_EC) { cert.ec = parse_ec_key(f.get()); if (!cert.ec) { return false; } } else { - LOGE("Unknown key type %d\n", cert.key_type); + LOG(ERROR) << "Unknown key type " << cert.key_type; return false; } @@ -547,7 +548,7 @@ bool load_keys(const char* filename, std::vector<Certificate>& certs) { } else if (ch == EOF) { break; } else { - LOGE("unexpected character between keys\n"); + LOG(ERROR) << "unexpected character between keys"; return false; } } diff --git a/wear_touch.cpp b/wear_touch.cpp index f22d40b88..cf33daa9f 100644 --- a/wear_touch.cpp +++ b/wear_touch.cpp @@ -14,9 +14,6 @@ * limitations under the License. */ -#include "common.h" -#include "wear_touch.h" - #include <dirent.h> #include <fcntl.h> #include <stdio.h> @@ -25,8 +22,11 @@ #include <errno.h> #include <string.h> +#include <android-base/logging.h> #include <linux/input.h> +#include "wear_touch.h" + #define DEVICE_PATH "/dev/input" WearSwipeDetector::WearSwipeDetector(int low, int high, OnSwipeCallback callback, void* cookie): @@ -49,11 +49,11 @@ void WearSwipeDetector::detect(int dx, int dy) { } else if (abs(dx) < mLowThreshold && abs(dy) > mHighThreshold) { direction = dy < 0 ? UP : DOWN; } else { - LOGD("Ignore %d %d\n", dx, dy); + LOG(DEBUG) << "Ignore " << dx << " " << dy; return; } - LOGD("Swipe direction=%d\n", direction); + LOG(DEBUG) << "Swipe direction=" << direction; mCallback(mCookie, direction); } @@ -105,7 +105,7 @@ void WearSwipeDetector::process(struct input_event *event) { void WearSwipeDetector::run() { int fd = findDevice(DEVICE_PATH); if (fd < 0) { - LOGE("no input devices found\n"); + LOG(ERROR) << "no input devices found"; return; } @@ -122,19 +122,19 @@ void* WearSwipeDetector::touch_thread(void* cookie) { return NULL; } -#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) +#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8))) int WearSwipeDetector::openDevice(const char *device) { int fd = open(device, O_RDONLY); if (fd < 0) { - LOGE("could not open %s, %s\n", device, strerror(errno)); + PLOG(ERROR) << "could not open " << device; return false; } char name[80]; name[sizeof(name) - 1] = '\0'; if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { - LOGE("could not get device name for %s, %s\n", device, strerror(errno)); + PLOG(ERROR) << "could not get device name for " << device; name[0] = '\0'; } @@ -143,7 +143,7 @@ int WearSwipeDetector::openDevice(const char *device) { int ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits); if (ret > 0) { if (test_bit(ABS_MT_POSITION_X, bits) && test_bit(ABS_MT_POSITION_Y, bits)) { - LOGD("Found %s %s\n", device, name); + LOG(DEBUG) << "Found " << device << " " << name; return fd; } } @@ -155,7 +155,7 @@ int WearSwipeDetector::openDevice(const char *device) { int WearSwipeDetector::findDevice(const char* path) { DIR* dir = opendir(path); if (dir == NULL) { - LOGE("Could not open directory %s", path); + PLOG(ERROR) << "Could not open directory " << path; return false; } diff --git a/wear_ui.cpp b/wear_ui.cpp index bfa7097ea..0918ac457 100644 --- a/wear_ui.cpp +++ b/wear_ui.cpp @@ -30,7 +30,7 @@ #include "common.h" #include "device.h" #include "wear_ui.h" -#include "cutils/properties.h" +#include "android-base/properties.h" #include "android-base/strings.h" #include "android-base/stringprintf.h" @@ -119,8 +119,8 @@ void WearRecoveryUI::draw_screen_locked() int y = outer_height; int x = outer_width; if (show_menu) { - char recovery_fingerprint[PROPERTY_VALUE_MAX]; - property_get("ro.bootimage.build.fingerprint", recovery_fingerprint, ""); + std::string recovery_fingerprint = + android::base::GetProperty("ro.bootimage.build.fingerprint", ""); SetColor(HEADER); DrawTextLine(x + 4, &y, "Android Recovery", true); for (auto& chunk: android::base::Split(recovery_fingerprint, ":")) { @@ -293,8 +293,8 @@ int WearRecoveryUI::SelectMenu(int sel) { } void WearRecoveryUI::ShowFile(FILE* fp) { - std::vector<long> offsets; - offsets.push_back(ftell(fp)); + std::vector<off_t> offsets; + offsets.push_back(ftello(fp)); ClearText(); struct stat sb; @@ -304,7 +304,7 @@ void WearRecoveryUI::ShowFile(FILE* fp) { while (true) { if (show_prompt) { Print("--(%d%% of %d bytes)--", - static_cast<int>(100 * (double(ftell(fp)) / double(sb.st_size))), + static_cast<int>(100 * (double(ftello(fp)) / double(sb.st_size))), static_cast<int>(sb.st_size)); Redraw(); while (show_prompt) { @@ -323,7 +323,7 @@ void WearRecoveryUI::ShowFile(FILE* fp) { if (feof(fp)) { return; } - offsets.push_back(ftell(fp)); + offsets.push_back(ftello(fp)); } } ClearText(); |