summaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
Diffstat (limited to 'updater')
-rw-r--r--updater/Android.mk115
-rw-r--r--updater/blockimg.cpp267
-rw-r--r--updater/include/updater/blockimg.h (renamed from updater/blockimg.h)0
-rw-r--r--updater/include/updater/install.h (renamed from updater/install.h)7
-rw-r--r--updater/include/updater/updater.h (renamed from updater/updater.h)8
-rw-r--r--updater/install.cpp544
-rw-r--r--updater/updater.cpp98
7 files changed, 430 insertions, 609 deletions
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(&params, 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(&params.thread, &attr, unzip_new_data, &params.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(), &params.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,
- &timestamp,
- NULL, NULL, sehandle);
+ bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, 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;
}