From a7b9a4660c18a88413280c84c03917ae953d62b0 Mon Sep 17 00:00:00 2001 From: Jed Estep Date: Tue, 15 Dec 2015 16:04:53 -0800 Subject: IO fault injection for OTA packages Bug: 25951086 Change-Id: I31c74c735eb7a975b7f41fe2b2eff042e5699c0c (cherry-picked from commit f1fc48c6e62cfee42d25ad12f443e22d50c15d0b) --- updater/install.cpp | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 45bbf2bc1..1cd9a5690 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -51,6 +51,7 @@ #include "minzip/DirUtil.h" #include "mtdutils/mounts.h" #include "mtdutils/mtdutils.h" +#include "otafault/ota_io.h" #include "updater.h" #include "install.h" #include "tune2fs.h" @@ -557,18 +558,18 @@ Value* PackageExtractFileFn(const char* name, State* state, } { - int fd = TEMP_FAILURE_RETRY(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 | O_SYNC, 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); - if (fsync(fd) == -1) { + if (ota_fsync(fd) == -1) { printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno)); success = false; } - if (close(fd) == -1) { + if (ota_close(fd) == -1) { printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno)); success = false; } @@ -995,21 +996,21 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } FILE* f; - f = fopen(filename, "rb"); + f = ota_fopen(filename, "rb"); if (f == NULL) { ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno)); goto done; } - if (fread(buffer, 1, st.st_size, f) != static_cast(st.st_size)) { + if (ota_fread(buffer, 1, st.st_size, f) != static_cast(st.st_size)) { ErrorAbort(state, "%s: failed to read %lld bytes from %s", name, (long long)st.st_size+1, filename); - fclose(f); + ota_fclose(f); goto done; } buffer[st.st_size] = '\0'; - fclose(f); + ota_fclose(f); char* line; line = strtok(buffer, "\n"); @@ -1104,7 +1105,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { if (contents->type == VAL_STRING) { // we're given a filename as the contents char* filename = contents->data; - FILE* f = fopen(filename, "rb"); + FILE* f = ota_fopen(filename, "rb"); if (f == NULL) { printf("%s: can't open %s: %s\n", name, filename, strerror(errno)); result = strdup(""); @@ -1114,12 +1115,12 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { success = true; char* buffer = reinterpret_cast(malloc(BUFSIZ)); int read; - while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) { + while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) { int wrote = mtd_write_data(ctx, buffer, read); success = success && (wrote == read); } free(buffer); - fclose(f); + ota_fclose(f); } else { // we're given a blob as the contents ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size); @@ -1438,10 +1439,10 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // zero out the 'command' field of the bootloader message. 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); - fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); - fclose(f); + ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); + ota_fclose(f); free(filename); strcpy(buffer, "reboot,"); @@ -1480,7 +1481,7 @@ 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); @@ -1488,8 +1489,8 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { to_write = max_size; stagestr[max_size-1] = 0; } - fwrite(stagestr, to_write, 1, f); - fclose(f); + ota_fwrite(stagestr, to_write, 1, f); + ota_fclose(f); free(stagestr); return StringValue(filename); @@ -1506,10 +1507,10 @@ 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); - fread(buffer, sizeof(buffer), 1, f); - fclose(f); + ota_fread(buffer, sizeof(buffer), 1, f); + ota_fclose(f); buffer[sizeof(buffer)-1] = '\0'; return StringValue(strdup(buffer)); @@ -1526,13 +1527,13 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) size_t len; android::base::ParseUint(len_str, &len); - int fd = open(filename, O_WRONLY, 0644); + int fd = ota_open(filename, O_WRONLY, 0644); int success = wipe_block_device(fd, len); free(filename); free(len_str); - close(fd); + ota_close(fd); return StringValue(strdup(success ? "t" : "")); } -- cgit v1.2.3 From d6c93afcc28cc65217ba65eeb646009c4f15a2ad Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Wed, 10 Feb 2016 16:41:10 -0800 Subject: applypatch: use vector to store data in FileContents. Bug: 26906416 Change-Id: Ib53b445cd415a1ed5e95733fbc4073f9ef4dbc43 --- updater/install.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 1cd9a5690..413e147a1 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -1398,21 +1398,22 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { char* filename; if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; - Value* v = reinterpret_cast(malloc(sizeof(Value))); + Value* v = static_cast(malloc(sizeof(Value))); + if (v == nullptr) { + return nullptr; + } v->type = VAL_BLOB; + v->size = -1; + v->data = nullptr; FileContents fc; if (LoadFileContents(filename, &fc) != 0) { - free(filename); - v->size = -1; - v->data = NULL; - free(fc.data); - return v; + v->data = static_cast(malloc(fc.data.size())); + if (v->data != nullptr) { + memcpy(v->data, fc.data.data(), fc.data.size()); + v->size = fc.data.size(); + } } - - v->size = fc.size; - v->data = (char*)fc.data; - free(filename); return v; } -- cgit v1.2.3 From 39c1b5e8722dbf0bbb3ee45e201373099f075345 Mon Sep 17 00:00:00 2001 From: Jed Estep Date: Tue, 15 Dec 2015 16:04:53 -0800 Subject: Control fault injection with config files instead of build flags Bug: 26570379 Change-Id: I76109d09276d6e3ed3a32b6fedafb2582f545c0c (cherry picked from commit d940887dde23597dc358b16d96ca48dd7480fee6) --- updater/install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 413e147a1..bc4cca913 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -51,7 +51,7 @@ #include "minzip/DirUtil.h" #include "mtdutils/mounts.h" #include "mtdutils/mtdutils.h" -#include "otafault/ota_io.h" +#include "ota_io.h" #include "updater.h" #include "install.h" #include "tune2fs.h" -- cgit v1.2.3 From 4bbd5bf8a6383d31341221b97e5e320d5abba085 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 1 Apr 2016 18:24:39 -0700 Subject: Move selinux dependencies out of header files. Bug: http://b/27764900 Change-Id: Ib62a59edcb13054f40f514c404d32b87b14ed5f1 --- updater/install.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index bc4cca913..925604f31 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +39,8 @@ #include #include #include +#include +#include #include "bootloader.h" #include "applypatch/applypatch.h" -- cgit v1.2.3 From 54a2747ef305c10d07d8db393125dbcbb461c428 Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Mon, 18 Apr 2016 11:30:55 -0700 Subject: Fix google-runtime-int warnings. Bug: 28220065 Change-Id: Ida199c66692a1638be6990d583d2ed42583fb592 --- updater/install.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 925604f31..4f5268401 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -602,8 +602,8 @@ Value* PackageExtractFileFn(const char* name, State* state, v->size = mzGetZipEntryUncompLen(entry); v->data = reinterpret_cast(malloc(v->size)); if (v->data == NULL) { - printf("%s: failed to allocate %ld bytes for %s\n", - name, (long)v->size, zip_path); + printf("%s: failed to allocate %zd bytes for %s\n", + name, v->size, zip_path); goto done1; } @@ -992,7 +992,8 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { buffer = reinterpret_cast(malloc(st.st_size+1)); if (buffer == NULL) { - ErrorAbort(state, "%s: failed to alloc %lld bytes", name, (long long)st.st_size+1); + ErrorAbort(state, "%s: failed to alloc %zu bytes", name, + static_cast(st.st_size+1)); goto done; } @@ -1004,8 +1005,8 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } if (ota_fread(buffer, 1, st.st_size, f) != static_cast(st.st_size)) { - ErrorAbort(state, "%s: failed to read %lld bytes from %s", - name, (long long)st.st_size+1, filename); + ErrorAbort(state, "%s: failed to read %zu bytes from %s", + name, static_cast(st.st_size), filename); ota_fclose(f); goto done; } -- cgit v1.2.3 From 733285fea265af4fc91cf37916fada1a66cec470 Mon Sep 17 00:00:00 2001 From: Alistair Strachan Date: Thu, 5 May 2016 16:04:32 -0700 Subject: updater, minzip: Remove unnecessary O_SYNC flags. Remove O_SYNC from mzExtractRecursive() and PackageExtractFileFn(). These functions deal with extracting whole files from the update package onto a filesystem. If run on ext4 on a rotating disk, for example, the O_SYNC flag will cause serious performance problems and the extraction proecss can take over 30 minutes, with no obvious benefits. This API function already calls fsync(fd) after each file is extracted to ensure data and metadata is written to the underlying block device, so the O_SYNC calls should be superfluous and safely removable. This change does not affect the OTA patch paths or any modification of the bootloader partition or writes to other 'emmc' partitions. Signed-off-by: Alistair Strachan Change-Id: I9cbb98a98e6278bf5c0d7efaae340773d1fbfcd2 --- updater/install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 4f5268401..bab2fe166 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -559,7 +559,7 @@ Value* PackageExtractFileFn(const char* name, State* state, } { - 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)); -- cgit v1.2.3 From 3f6eb86390e27707d1204e60e33b6a41e88f0dc8 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 23 May 2016 14:58:53 -0700 Subject: resolve merge conflicts of 50f6417 Fix a typo for ota_fclose(). Change-Id: Ia93e911aa5391afc604874fc3a09c5a45c094c80 --- updater/install.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index dc2756141..a65b32d81 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -1013,7 +1013,6 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } if (ota_fread(buffer, 1, st.st_size, f) != static_cast(st.st_size)) { - ota_fclose(f); ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name, static_cast(st.st_size), filename); ota_fclose(f); -- cgit v1.2.3 From 63a319201fc0f5c34c1c62b446527e06f57f8d40 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 9 Jun 2016 17:41:22 -0700 Subject: Remove obsolete MTD support. Bug: http://b/29250988 Change-Id: Ia97ba9082a165c37f74d6e1c3f71a367adc59945 --- updater/install.cpp | 168 ++++------------------------------------------------ 1 file changed, 11 insertions(+), 157 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index bab2fe166..a6a29b286 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -50,17 +50,14 @@ #include "edify/expr.h" #include "openssl/sha.h" #include "minzip/DirUtil.h" -#include "mtdutils/mounts.h" -#include "mtdutils/mtdutils.h" +#include "mounts.h" #include "ota_io.h" #include "updater.h" #include "install.h" #include "tune2fs.h" -#ifdef USE_EXT4 #include "make_ext4fs.h" #include "wipe.h" -#endif // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { @@ -109,7 +106,6 @@ char* PrintSha1(const uint8_t* digest) { // 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; @@ -170,33 +166,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: @@ -226,7 +203,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 { @@ -256,7 +233,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(""); @@ -292,7 +269,6 @@ 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= mount_point= // fs_type="ext4" partition_type="EMMC" location=device fs_size= mount_point= // fs_type="f2fs" partition_type="EMMC" location=device fs_size= mount_point= // if fs_size == 0, then make fs uses the entire partition. @@ -332,35 +308,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", @@ -387,7 +335,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); @@ -1059,98 +1006,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, "partition argument to %s must be string", name); - goto done; - } - partition = partition_value->data; - if (strlen(partition) == 0) { - ErrorAbort(state, "partition argument to %s can't be empty", name); - goto done; - } - if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) { - ErrorAbort(state, "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(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[]) { @@ -1607,7 +1462,6 @@ void RegisterInstallFunctions() { RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); - RegisterFunction("write_raw_image", WriteRawImageFn); RegisterFunction("apply_patch", ApplyPatchFn); RegisterFunction("apply_patch_check", ApplyPatchCheckFn); -- cgit v1.2.3 From efacd80364c7ed42d56310949790d89febaf3444 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Sat, 11 Jun 2016 03:56:38 -0700 Subject: updater: Fix the broken ReadFileFn. Was accidentally broken by the CL in [1]. [1]: commit d6c93afcc28cc65217ba65eeb646009c4f15a2ad Change-Id: I851e13ccea6f5be6fcd47f712cc95867245f9934 --- updater/install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index bab2fe166..cfd6a97ee 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -1409,7 +1409,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { v->data = nullptr; FileContents fc; - if (LoadFileContents(filename, &fc) != 0) { + if (LoadFileContents(filename, &fc) == 0) { v->data = static_cast(malloc(fc.data.size())); if (v->data != nullptr) { memcpy(v->data, fc.data.data(), fc.data.size()); -- cgit v1.2.3 From 83ce7555183a9aa5bac6ccb82d3fa56447d22345 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 30 Jun 2016 09:28:42 -0700 Subject: Fix install.h's use of attribute printf. And move off the bionic __nonnull macro, which I'm removing. Change-Id: I40b4424f4fd7bd8076e0eee3ec35de36c3ded8de --- updater/install.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 11d5215c3..3e7e9285a 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -79,8 +79,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; -- cgit v1.2.3 From cb22040c6303144a42a90f424f29a267e43bef74 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 23 Sep 2016 15:30:55 -0700 Subject: Switch to . Bug: http://b/23102347 Test: boot into recovery. Change-Id: Ib2ca560f1312961c21fbaa294bb068de19cb883e Merged-In: Ib2ca560f1312961c21fbaa294bb068de19cb883e --- updater/install.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 4c4886d51..8c33c2bf3 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #include "applypatch/applypatch.h" #include "cutils/android_reboot.h" #include "cutils/misc.h" -#include "cutils/properties.h" #include "edify/expr.h" #include "error_code.h" #include "minzip/DirUtil.h" @@ -906,11 +906,10 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { char* key = Evaluate(state, argv[0]); if (key == NULL) return NULL; - char value[PROPERTY_VALUE_MAX]; - property_get(key, value, ""); + std::string value = android::base::GetProperty(key, ""); free(key); - return StringValue(strdup(value)); + return StringValue(strdup(value.c_str())); } @@ -1301,9 +1300,8 @@ 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 = ota_fopen(filename, "r+b"); fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); @@ -1311,12 +1309,9 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { 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); -- cgit v1.2.3 From de40ba59c8e5091221752e9d7c6e072c29a7055f Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 5 Oct 2016 23:17:01 -0700 Subject: Update the header path for ext4_utils. Test: `mmma bootable/recovery` Change-Id: I70ccddb3ddf46bb012fdc5f632afc46ebdd5473e --- updater/install.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 8c33c2bf3..24e35cfb8 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -57,9 +59,6 @@ #include "install.h" #include "tune2fs.h" -#include "make_ext4fs.h" -#include "wipe.h" - // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { UpdaterInfo* ui = reinterpret_cast(state->cookie); -- cgit v1.2.3 From 0c7839ac14a00f32d740c23ddf6df65f2757ece5 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 10 Oct 2016 15:48:37 -0700 Subject: Refactor libupdater into a seperate module. So that we can write native tests for updater functions. This CL adds a testcase for getprop() function. Test: mmma bootable/recovery; Run recovery_component_test on device. Change-Id: Iff4c1ff63c5c71aded2f9686fed6b71cc298c228 --- updater/install.cpp | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 24e35cfb8..86cdd5d32 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "updater/install.h" + #include #include #include @@ -40,24 +42,22 @@ #include #include #include +#include #include #include #include #include -#include "bootloader.h" #include "applypatch/applypatch.h" -#include "cutils/android_reboot.h" -#include "cutils/misc.h" +#include "bootloader.h" #include "edify/expr.h" #include "error_code.h" #include "minzip/DirUtil.h" #include "mounts.h" #include "openssl/sha.h" #include "ota_io.h" -#include "updater.h" -#include "install.h" #include "tune2fs.h" +#include "updater/updater.h" // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { @@ -90,6 +90,27 @@ void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { uiPrint(state, error_msg); } +// 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; +} + // Take a sha-1 digest and return it as a newly-allocated hex string. char* PrintSha1(const uint8_t* digest) { char* buffer = reinterpret_cast(malloc(SHA_DIGEST_LENGTH*2 + 1)); @@ -569,27 +590,6 @@ Value* PackageExtractFileFn(const char* name, State* state, } } -// 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; -} - // symlink target src1 src2 ... // unlinks any previously existing src1, src2, etc before creating symlinks. Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { -- cgit v1.2.3 From 361342cbd2af4bbf74ac9e91ddfb2a973220a106 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 8 Feb 2016 11:15:50 -0800 Subject: updater: Kill the duplicate PrintSha1() in install.cpp. Also add a testcase for sha1_check(). Test: mmma bootable/recovery; recovery_component_test passes. Change-Id: I4d06d551a771aec84e460148544f68b247a7e721 --- updater/install.cpp | 55 ++++++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 86cdd5d32..3546968d7 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -18,24 +18,24 @@ #include #include +#include +#include +#include #include #include #include #include +#include #include #include #include #include -#include -#include -#include -#include -#include #include -#include -#include +#include +#include #include +#include #include #include @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,8 @@ #include "error_code.h" #include "minzip/DirUtil.h" #include "mounts.h" -#include "openssl/sha.h" #include "ota_io.h" +#include "print_sha1.h" #include "tune2fs.h" #include "updater/updater.h" @@ -111,19 +112,6 @@ static int make_parents(char* name) { return 0; } -// Take a sha-1 digest and return it as a newly-allocated hex string. -char* PrintSha1(const uint8_t* digest) { - char* buffer = reinterpret_cast(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; -} - // mount(fs_type, partition_type, location, mount_point) // // fs_type="ext4" partition_type="EMMC" location=device @@ -1227,29 +1215,24 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { SHA1(reinterpret_cast(args[0]->data), args[0]->size, digest); if (argc == 1) { - return StringValue(PrintSha1(digest)); + return StringValue(strdup(print_sha1(digest).c_str())); } - 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); + printf("%s(): arg %d is not a string; skipping", name, i); } else if (ParseSha1(args[i]->data, 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); } 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(strdup("")); } // Read a local file and return its contents (the Value* returned -- cgit v1.2.3 From aced5d9e4e438ba478ce54f9217166b8ab7cc24f Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Wed, 12 Oct 2016 10:55:04 -0700 Subject: Change StringValue to use std::string Changing the field of 'Value' in edify to std::string from char*. Meanwhile cleaning up the users of 'Value' and switching them to cpp style. Test: compontent tests passed. Bug: 31713288 Change-Id: Iec5a7d601b1e4ca40935bf1c70d325dafecec235 --- updater/install.cpp | 191 ++++++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 110 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 3546968d7..d723b3880 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -116,7 +116,7 @@ static int make_parents(char* name) { // // 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); } @@ -197,7 +197,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 +227,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); } @@ -284,7 +284,7 @@ static int exec_cmd(const char* path, char* const argv[]) { // 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); } @@ -358,7 +358,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); } @@ -397,15 +397,10 @@ done: } Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - char** paths = reinterpret_cast(malloc(argc * sizeof(char*))); + std::vector 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; } } @@ -413,15 +408,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)); } @@ -483,7 +475,7 @@ Value* PackageExtractDirFn(const char* name, State* state, NULL, NULL, sehandle); free(zip_path); free(dest_path); - return StringValue(strdup(success ? "t" : "")); + return StringValue(success ? "t" : ""); } @@ -536,7 +528,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. @@ -544,10 +536,7 @@ Value* PackageExtractFileFn(const char* name, State* state, char* zip_path; if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; - Value* v = reinterpret_cast(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); @@ -556,23 +545,16 @@ Value* PackageExtractFileFn(const char* name, State* state, goto done1; } - v->size = mzGetZipEntryUncompLen(entry); - v->data = reinterpret_cast(malloc(v->size)); - if (v->data == NULL) { - printf("%s: failed to allocate %zd bytes for %s\n", - name, v->size, zip_path); - goto done1; - } - + v->data.resize(mzGetZipEntryUncompLen(entry)); success = mzExtractZipEntryToBuffer(za, entry, - (unsigned char *)v->data); + reinterpret_cast(&v->data[0])); done1: free(zip_path); if (!success) { - free(v->data); - v->data = NULL; - v->size = -1; + v->data.clear(); + } else { + v->type = VAL_BLOB; } return v; } @@ -584,13 +566,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; } @@ -606,12 +588,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]); @@ -620,7 +602,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 { @@ -883,20 +865,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; - + std::string key; + if (!Evaluate(state, argv[0], &key)) { + return nullptr; + } std::string value = android::base::GetProperty(key, ""); - free(key); - return StringValue(strdup(value.c_str())); + return StringValue(value); } @@ -1015,7 +997,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) @@ -1047,17 +1029,16 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } int patchcount = (argc-4) / 2; - std::unique_ptr arg_values(ReadValueVarArgs(state, argc-4, argv+4), - free); + std::unique_ptr arg_values(ReadValueVarArgs(state, argc-4, argv+4)); if (!arg_values) { return nullptr; } - std::vector> patch_shas; - std::vector> patches; + std::vector> patch_shas; + std::vector> 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) { @@ -1071,7 +1052,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } } - std::vector patch_sha_str; + std::vector patch_sha_str; std::vector patch_ptrs; for (int i = 0; i < patchcount; ++i) { patch_sha_str.push_back(patch_shas[i]->data); @@ -1080,9 +1061,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, ...]) @@ -1095,21 +1076,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 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 @@ -1129,7 +1106,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[]) { @@ -1137,7 +1114,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[]) { @@ -1180,10 +1157,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) @@ -1199,32 +1173,32 @@ 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 arg_values(ReadValueVarArgs(state, argc, argv), free); + std::unique_ptr arg_values(ReadValueVarArgs(state, argc, argv)); if (arg_values == nullptr) { return nullptr; } - std::vector> args; + std::vector> 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(args[0]->data), args[0]->size, digest); + SHA1(reinterpret_cast(args[0]->data.c_str()), args[0]->data.size(), digest); if (argc == 1) { - return StringValue(strdup(print_sha1(digest).c_str())); + return StringValue(print_sha1(digest)); } 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) { + } 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) { // Found a match. return args[i].release(); @@ -1232,7 +1206,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { } // Didn't match any of the hex strings; return false. - return StringValue(strdup("")); + return StringValue(""); } // Read a local file and return its contents (the Value* returned @@ -1244,21 +1218,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(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(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; @@ -1326,16 +1291,19 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // package installation. 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); + size_t status = ota_fwrite(stagestr, to_write, 1, f); ota_fclose(f); free(stagestr); + if (status != to_write) { + return StringValue(""); + } return StringValue(filename); } @@ -1352,11 +1320,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { char buffer[sizeof(((struct bootloader_message*)0)->stage)]; FILE* f = ota_fopen(filename, "rb"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - ota_fread(buffer, sizeof(buffer), 1, f); + size_t status = ota_fread(buffer, sizeof(buffer), 1, f); ota_fclose(f); - buffer[sizeof(buffer)-1] = '\0'; + 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[]) { @@ -1378,7 +1349,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[]) { @@ -1387,7 +1358,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[]) { @@ -1418,7 +1389,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() { -- cgit v1.2.3 From 8cf5c8f60f51049278b08ae4cbc31df397b651fd Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Thu, 8 Sep 2016 20:10:11 -0700 Subject: Replace minzip with libziparchive Clean up the duplicated codes that handle the zip files in bootable/recovery; and rename the library of the remaining utility functions to libotautil. Test: Update package installed successfully on angler. Bug: 19472796 Change-Id: Iea8962fcf3004473cb0322b6bb3a9ea3ca7f679e --- updater/install.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index d723b3880..a41c5db3c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -48,14 +49,16 @@ #include #include #include +#include #include "applypatch/applypatch.h" #include "bootloader.h" #include "edify/expr.h" #include "error_code.h" -#include "minzip/DirUtil.h" #include "mounts.h" #include "ota_io.h" +#include "otautil/DirUtil.h" +#include "otautil/ZipUtil.h" #include "print_sha1.h" #include "tune2fs.h" #include "updater/updater.h" @@ -465,14 +468,13 @@ 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(success ? "t" : ""); @@ -495,14 +497,15 @@ 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; } @@ -514,7 +517,7 @@ Value* PackageExtractFileFn(const char* name, State* state, 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; @@ -538,16 +541,21 @@ Value* PackageExtractFileFn(const char* name, State* state, 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->data.resize(mzGetZipEntryUncompLen(entry)); - success = mzExtractZipEntryToBuffer(za, entry, - reinterpret_cast(&v->data[0])); + v->data.resize(entry.uncompressed_length); + if (ExtractToMemory(za, &entry, reinterpret_cast(&v->data[0]), + v->data.size()) != 0) { + printf("%s: faled to extract %zu bytes to memory\n", name, v->data.size()); + } else { + success = true; + } done1: free(zip_path); -- cgit v1.2.3 From fada91ccf2b31d69d72899388b1833186d763d1a Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 27 Oct 2016 18:16:06 -0700 Subject: applypatch: Switch the parameter of Value** to std::vector. Test: Unit tests and install-recovery.sh pass on angler and dragon. Change-Id: I328e6554edca667cf850f5584ebf1ac211e3d4d1 --- updater/install.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index a41c5db3c..5f3f675b1 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -1061,15 +1061,13 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { } std::vector patch_sha_str; - std::vector patch_ptrs; for (int i = 0; i < patchcount; ++i) { patch_sha_str.push_back(patch_shas[i]->data); - patch_ptrs.push_back(patches[i].get()); } int result = applypatch(source_filename, target_filename, target_sha1, target_size, - patch_sha_str, patch_ptrs.data(), NULL); + patch_sha_str, patches, NULL); return StringValue(result == 0 ? "t" : ""); } -- cgit v1.2.3 From 5fe280ac96a2c13f613b7138bb239c3f36d35c9f Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 17 Oct 2016 18:15:20 -0700 Subject: Cleanup ReadArgs & ReadValueArgs usage ReadArgs will switch to using std::string and std::unique_ptr. Also cleanup the callers. Test: mma & component test passed. Change-Id: I4724406ae6c0c134a27bbd1cdd24ad5d343b2a3b --- updater/install.cpp | 854 ++++++++++++++++++++++++---------------------------- 1 file changed, 387 insertions(+), 467 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 5f3f675b1..efc96c454 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -119,58 +120,50 @@ static int make_parents(char* name) { // // fs_type="ext4" partition_type="EMMC" location=device Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = nullptr; if (argc != 4 && argc != 5) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); } - char* fs_type; - char* partition_type; - char* location; - char* mount_point; - char* mount_options; - bool has_mount_options; + + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& fs_type = args[0]; + const std::string& partition_type = args[1]; + const std::string& location = args[2]; + const std::string& mount_point = args[3]; + std::string mount_options; + if (argc == 5) { - has_mount_options = true; - if (ReadArgs(state, argv, 5, &fs_type, &partition_type, - &location, &mount_point, &mount_options) < 0) { - return NULL; - } - } else { - has_mount_options = false; - if (ReadArgs(state, argv, 4, &fs_type, &partition_type, - &location, &mount_point) < 0) { - return NULL; - } + mount_options = args[4]; } - if (strlen(fs_type) == 0) { - ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name); - goto done; + if (fs_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", + name); } - if (strlen(partition_type) == 0) { - ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", - name); - goto done; + if (partition_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", + name); } - if (strlen(location) == 0) { - ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name); - goto done; + if (location.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", + name); } - if (strlen(mount_point) == 0) { - ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", - name); - goto done; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", + name); } { char *secontext = NULL; if (sehandle) { - selabel_lookup(sehandle, &secontext, mount_point, 0755); + selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755); setfscreatecon(secontext); } - mkdir(mount_point, 0755); + mkdir(mount_point.c_str(), 0755); if (secontext) { freecon(secontext); @@ -178,90 +171,71 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { } } - if (mount(location, mount_point, fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, - has_mount_options ? mount_options : "") < 0) { + if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(), + MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) { uiPrintf(state, "%s: failed to mount %s at %s: %s\n", - name, location, mount_point, strerror(errno)); - result = strdup(""); - } else { - result = mount_point; + name, location.c_str(), mount_point.c_str(), strerror(errno)); + return StringValue(""); } -done: - free(fs_type); - free(partition_type); - free(location); - if (result != mount_point) free(mount_point); - if (has_mount_options) free(mount_options); - return StringValue(result); + return StringValue(mount_point); } // is_mounted(mount_point) Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = nullptr; if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } - char* mount_point; - if (ReadArgs(state, argv, 1, &mount_point) < 0) { - return NULL; + + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - if (strlen(mount_point) == 0) { - ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty"); - goto done; + const std::string& mount_point = args[0]; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "mount_point argument to unmount() can't be empty"); } scan_mounted_volumes(); - { - MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); - if (vol == NULL) { - result = strdup(""); - } else { - result = mount_point; - } + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); + if (vol == nullptr) { + return StringValue(""); } -done: - if (result != mount_point) free(mount_point); - return StringValue(result); + return StringValue(mount_point); } Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = nullptr; if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } - char* mount_point; - if (ReadArgs(state, argv, 1, &mount_point) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - if (strlen(mount_point) == 0) { - ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty"); - goto done; + const std::string& mount_point = args[0]; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "mount_point argument to unmount() can't be empty"); } scan_mounted_volumes(); - { - 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(""); - } else { - int ret = unmount_mounted_volume(vol); - if (ret != 0) { - uiPrintf(state, "unmount of %s failed (%d): %s\n", - mount_point, ret, strerror(errno)); - } - result = mount_point; + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); + if (vol == nullptr) { + uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point.c_str()); + return nullptr; + } else { + int ret = unmount_mounted_volume(vol); + if (ret != 0) { + uiPrintf(state, "unmount of %s failed (%d): %s\n", + mount_point.c_str(), ret, strerror(errno)); } } -done: - if (result != mount_point) free(mount_point); - return StringValue(result); + return StringValue(mount_point); } static int exec_cmd(const char* path, char* const argv[]) { @@ -287,116 +261,108 @@ static int exec_cmd(const char* path, char* const argv[]) { // 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 = nullptr; if (argc != 5) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); } - char* fs_type; - char* partition_type; - char* location; - char* fs_size; - char* mount_point; - if (ReadArgs(state, argv, 5, &fs_type, &partition_type, &location, &fs_size, &mount_point) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& fs_type = args[0]; + const std::string& partition_type = args[1]; + const std::string& location = args[2]; + const std::string& fs_size = args[3]; + const std::string& mount_point = args[4]; - if (strlen(fs_type) == 0) { - ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name); - goto done; + if (fs_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", + name); + } + if (partition_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "partition_type argument to %s() can't be empty", name); } - if (strlen(partition_type) == 0) { - ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", - name); - goto done; + if (location.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", + name); } - if (strlen(location) == 0) { - ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name); - goto done; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "mount_point argument to %s() can't be empty", name); } - if (strlen(mount_point) == 0) { - ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", - name); - goto done; + int64_t size; + if (!android::base::ParseInt(fs_size.c_str(), &size)) { + return ErrorAbort(state, kArgsParsingFailure, + "%s: failed to parse int in %s\n", name, fs_size.c_str()); } - if (strcmp(fs_type, "ext4") == 0) { - int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle); + if (fs_type == "ext4") { + int status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle); if (status != 0) { printf("%s: make_ext4fs failed (%d) on %s", - name, status, location); - result = strdup(""); - goto done; + name, status, location.c_str()); + return StringValue(""); } - result = location; - } else if (strcmp(fs_type, "f2fs") == 0) { - char *num_sectors; - if (asprintf(&num_sectors, "%lld", atoll(fs_size) / 512) <= 0) { - printf("format_volume: failed to create %s command for %s\n", fs_type, location); - result = strdup(""); - goto done; + return StringValue(location); + } else if (fs_type == "f2fs") { + if (size < 0) { + printf("fs_size can't be negative for f2fs: %s", fs_size.c_str()); + return StringValue(""); } + std::string num_sectors = std::to_string(size / 512); + const char *f2fs_path = "/sbin/mkfs.f2fs"; - const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location, num_sectors, NULL}; + const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location.c_str(), + num_sectors.c_str(), nullptr}; int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv); - free(num_sectors); if (status != 0) { printf("%s: mkfs.f2fs failed (%d) on %s", - name, status, location); - result = strdup(""); - goto done; + name, status, location.c_str()); + return StringValue(""); } - result = location; + return StringValue(location); } else { printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", - name, fs_type, partition_type); + name, fs_type.c_str(), partition_type.c_str()); } -done: - free(fs_type); - free(partition_type); - if (result != location) free(location); - return StringValue(result); + return nullptr; } Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = nullptr; if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* src_name; - char* dst_name; - - if (ReadArgs(state, argv, 2, &src_name, &dst_name) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - if (strlen(src_name) == 0) { - ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name); - goto done; + const std::string& src_name = args[0]; + std::string& dst_name = args[1]; + + if (src_name.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", + name); } - if (strlen(dst_name) == 0) { - ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); - goto done; + if (dst_name.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", + name); } - if (make_parents(dst_name) != 0) { - ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", - dst_name, strerror(errno)); - } else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) { + if (make_parents(&dst_name[0]) != 0) { + return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", + dst_name.c_str(), strerror(errno)); + } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { // File was already moved - result = dst_name; - } else if (rename(src_name, dst_name) != 0) { - ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", - src_name, dst_name, strerror(errno)); - } else { - result = dst_name; + return StringValue(dst_name); + } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) { + return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", + src_name.c_str(), dst_name.c_str(), strerror(errno)); } -done: - free(src_name); - if (result != dst_name) free(dst_name); - return StringValue(result); + return StringValue(dst_name); } Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -424,20 +390,28 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* frac_str; - char* sec_str; - if (ReadArgs(state, argv, 2, &frac_str, &sec_str) < 0) { - return NULL; + + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& frac_str = args[0]; + const std::string& sec_str = args[1]; - double frac = strtod(frac_str, NULL); + double frac; + if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { + return ErrorAbort(state, kArgsParsingFailure, + "%s: failed to parse double in %s\n", name, frac_str.c_str()); + } int sec; - android::base::ParseInt(sec_str, &sec); + if (!android::base::ParseInt(sec_str.c_str(), &sec)) { + return ErrorAbort(state, kArgsParsingFailure, + "%s: failed to parse int in %s\n", name, sec_str.c_str()); + } UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec); - free(sec_str); return StringValue(frac_str); } @@ -445,12 +419,18 @@ Value* SetProgressFn(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* frac_str; - if (ReadArgs(state, argv, 1, &frac_str) < 0) { - return NULL; + + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& frac_str = args[0]; - double frac = strtod(frac_str, NULL); + double frac; + if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { + return ErrorAbort(state, kArgsParsingFailure, + "%s: failed to parse double in %s\n", name, frac_str.c_str()); + } UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); fprintf(ui->cmd_pipe, "set_progress %f\n", frac); @@ -464,9 +444,13 @@ Value* PackageExtractDirFn(const char* name, State* state, if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* zip_path; - char* dest_path; - if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; + + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& zip_path = args[0]; + const std::string& dest_path = args[1]; ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; @@ -475,8 +459,6 @@ Value* PackageExtractDirFn(const char* name, State* state, bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle); - free(zip_path); - free(dest_path); return StringValue(success ? "t" : ""); } @@ -499,54 +481,57 @@ Value* PackageExtractFileFn(const char* name, State* state, 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; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, + argc); + } + const std::string& zip_path = args[0]; + const std::string& dest_path = args[1]; - ZipString zip_string_path(zip_path); + ZipString zip_string_path(zip_path.c_str()); ZipEntry entry; if (FindEntry(za, zip_string_path, &entry) != 0) { - printf("%s: no %s in package\n", name, zip_path); - goto done2; + printf("%s: no %s in package\n", name, zip_path.c_str()); + return StringValue(""); } - { - 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 = ExtractEntryToFile(za, &entry, fd); - if (ota_fsync(fd) == -1) { - printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno)); - success = false; - } - if (ota_close(fd) == -1) { - printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno)); - success = false; - } + int fd = TEMP_FAILURE_RETRY(ota_open(dest_path.c_str(), 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.c_str(), strerror(errno)); + return StringValue(""); + } + success = ExtractEntryToFile(za, &entry, fd); + if (ota_fsync(fd) == -1) { + printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + success = false; + } + if (ota_close(fd) == -1) { + printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + success = false; } - done2: - free(zip_path); - free(dest_path); return StringValue(success ? "t" : ""); } else { // The one-argument version returns the contents of the file // as the result. - char* zip_path; - if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, + argc); + } + const std::string& zip_path = args[0]; Value* v = new Value(VAL_INVALID, ""); ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; - ZipString zip_string_path(zip_path); + ZipString zip_string_path(zip_path.c_str()); ZipEntry entry; if (FindEntry(za, zip_string_path, &entry) != 0) { - printf("%s: no %s in package\n", name, zip_path); - goto done1; + printf("%s: no %s in package\n", name, zip_path.c_str()); + return v; } v->data.resize(entry.uncompressed_length); @@ -557,8 +542,6 @@ Value* PackageExtractFileFn(const char* name, State* state, success = true; } - done1: - free(zip_path); if (!success) { v->data.clear(); } else { @@ -579,34 +562,31 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } - char** srcs = ReadVarArgs(state, argc-1, argv+1); - if (srcs == NULL) { - return NULL; + std::vector srcs; + if (!ReadArgs(state, argc-1, argv+1, &srcs)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } int bad = 0; - int i; - for (i = 0; i < argc-1; ++i) { - if (unlink(srcs[i]) < 0) { + for (int i = 0; i < argc-1; ++i) { + if (unlink(srcs[i].c_str()) < 0) { if (errno != ENOENT) { printf("%s: failed to remove %s: %s\n", - name, srcs[i], strerror(errno)); + name, srcs[i].c_str(), strerror(errno)); ++bad; } } - if (make_parents(srcs[i])) { + if (make_parents(&srcs[i][0])) { printf("%s: failed to symlink %s to %s: making parents failed\n", - name, srcs[i], target.c_str()); + name, srcs[i].c_str(), target.c_str()); ++bad; } - if (symlink(target.c_str(), srcs[i]) < 0) { + if (symlink(target.c_str(), srcs[i].c_str()) < 0) { printf("%s: failed to symlink %s to %s: %s\n", - name, srcs[i], target.c_str(), strerror(errno)); + name, srcs[i].c_str(), target.c_str(), strerror(errno)); ++bad; } - free(srcs[i]); } - free(srcs); if (bad) { return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); } @@ -625,12 +605,13 @@ struct perm_parsed_args { bool has_dmode; mode_t dmode; bool has_selabel; - char* selabel; + const char* selabel; bool has_capabilities; uint64_t capabilities; }; -static struct perm_parsed_args ParsePermArgs(State * state, int argc, char** args) { +static struct perm_parsed_args ParsePermArgs(State * state, int argc, + const std::vector& args) { int i; struct perm_parsed_args parsed; int bad = 0; @@ -639,84 +620,84 @@ static struct perm_parsed_args ParsePermArgs(State * state, int argc, char** arg memset(&parsed, 0, sizeof(parsed)); for (i = 1; i < argc; i += 2) { - if (strcmp("uid", args[i]) == 0) { + if (args[i] == "uid") { int64_t uid; - if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNd64, &uid) == 1) { parsed.uid = uid; parsed.has_uid = true; } else { - uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("gid", args[i]) == 0) { + if (args[i] == "gid") { int64_t gid; - if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNd64, &gid) == 1) { parsed.gid = gid; parsed.has_gid = true; } else { - uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("mode", args[i]) == 0) { + if (args[i] == "mode") { int32_t mode; - if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { parsed.mode = mode; parsed.has_mode = true; } else { - uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("dmode", args[i]) == 0) { + if (args[i] == "dmode") { int32_t mode; - if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { parsed.dmode = mode; parsed.has_dmode = true; } else { - uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("fmode", args[i]) == 0) { + if (args[i] == "fmode") { int32_t mode; - if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { parsed.fmode = mode; parsed.has_fmode = true; } else { - uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("capabilities", args[i]) == 0) { + if (args[i] == "capabilities") { int64_t capabilities; - if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) { + if (sscanf(args[i+1].c_str(), "%" SCNi64, &capabilities) == 1) { parsed.capabilities = capabilities; parsed.has_capabilities = true; } else { - uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } - if (strcmp("selabel", args[i]) == 0) { - if (args[i+1][0] != '\0') { - parsed.selabel = args[i+1]; + if (args[i] == "selabel") { + if (!args[i+1].empty()) { + parsed.selabel = args[i+1].c_str(); parsed.has_selabel = true; } else { - uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]); + uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str()); bad++; } continue; } if (max_warnings != 0) { - printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]); + printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str()); max_warnings--; if (max_warnings == 0) { printf("ParsedPermArgs: suppressing further warnings\n"); @@ -825,48 +806,34 @@ static int do_SetMetadataRecursive(const char* filename, const struct stat *stat } static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { - int bad = 0; - struct stat sb; - Value* result = NULL; - - bool recursive = (strcmp(name, "set_metadata_recursive") == 0); - if ((argc % 2) != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %d", name, argc); } - char** args = ReadVarArgs(state, argc, argv); - if (args == NULL) return NULL; - - if (lstat(args[0], &sb) == -1) { - result = ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", - name, args[0], strerror(errno)); - goto done; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - { - struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); - - if (recursive) { - recursive_parsed_args = parsed; - recursive_state = state; - bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); - memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); - recursive_state = NULL; - } else { - bad += ApplyParsedPerms(state, args[0], &sb, parsed); - } + struct stat sb; + if (lstat(args[0].c_str(), &sb) == -1) { + return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", + name, args[0].c_str(), strerror(errno)); } -done: - for (int i = 0; i < argc; ++i) { - free(args[i]); - } - free(args); + struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); + int bad = 0; + bool recursive = (strcmp(name, "set_metadata_recursive") == 0); - if (result != NULL) { - return result; + if (recursive) { + recursive_parsed_args = parsed; + recursive_state = state; + bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); + memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); + recursive_state = NULL; + } else { + bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed); } if (bad > 0) { @@ -896,113 +863,80 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // per line. # comment lines,blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - char* result = NULL; - char* buffer = NULL; - char* filename; - char* key; - if (ReadArgs(state, argv, 2, &filename, &key) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& filename = args[0]; + const std::string& key = args[1]; struct stat st; - if (stat(filename, &st) < 0) { - ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, filename, - strerror(errno)); - goto done; + if (stat(filename.c_str(), &st) < 0) { + return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, + filename.c_str(), strerror(errno)); } #define MAX_FILE_GETPROP_SIZE 65536 if (st.st_size > MAX_FILE_GETPROP_SIZE) { - ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", filename, name, - MAX_FILE_GETPROP_SIZE); - goto done; - } - - buffer = reinterpret_cast(malloc(st.st_size+1)); - if (buffer == NULL) { - ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %zu bytes", name, - static_cast(st.st_size+1)); - goto done; + return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", + filename.c_str(), name, MAX_FILE_GETPROP_SIZE); } - FILE* f; - f = ota_fopen(filename, "rb"); - if (f == NULL) { - ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename, - strerror(errno)); - goto done; + std::string buffer(st.st_size, '\0'); + FILE* f = ota_fopen(filename.c_str(), "rb"); + if (f == nullptr) { + return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, + filename.c_str(), strerror(errno)); } - if (ota_fread(buffer, 1, st.st_size, f) != static_cast(st.st_size)) { + if (ota_fread(&buffer[0], 1, st.st_size, f) != static_cast(st.st_size)) { ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", - name, static_cast(st.st_size), filename); + name, static_cast(st.st_size), filename.c_str()); ota_fclose(f); - goto done; + return nullptr; } - buffer[st.st_size] = '\0'; ota_fclose(f); - char* line; - line = strtok(buffer, "\n"); - do { - // skip whitespace at start of line - while (*line && isspace(*line)) ++line; + std::vector lines = android::base::Split(buffer, "\n"); + for (size_t i = 0; i < lines.size(); i++) { + std::string line = android::base::Trim(lines[i]); // comment or blank line: skip to next line - if (*line == '\0' || *line == '#') continue; - - char* equal = strchr(line, '='); - if (equal == NULL) { + if (line.empty() || line[0] == '#') { + continue; + } + size_t equal_pos = line.find('='); + if (equal_pos == std::string::npos) { continue; } // trim whitespace between key and '=' - char* key_end = equal-1; - while (key_end > line && isspace(*key_end)) --key_end; - key_end[1] = '\0'; + std::string str = android::base::Trim(line.substr(0, equal_pos - 1)); // not the key we're looking for - if (strcmp(key, line) != 0) continue; - - // skip whitespace after the '=' to the start of the value - char* val_start = equal+1; - while(*val_start && isspace(*val_start)) ++val_start; - - // trim trailing whitespace - char* val_end = val_start + strlen(val_start)-1; - while (val_end > val_start && isspace(*val_end)) --val_end; - val_end[1] = '\0'; + if (key != str) continue; - result = strdup(val_start); - break; - - } while ((line = strtok(NULL, "\n"))); - - if (result == NULL) result = strdup(""); + return StringValue(android::base::Trim(line.substr(equal_pos + 1))); + } - done: - free(filename); - free(key); - free(buffer); - return StringValue(result); + return StringValue(""); } // apply_patch_space(bytes) Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { - char* bytes_str; - if (ReadArgs(state, argv, 1, &bytes_str) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& bytes_str = args[0]; size_t bytes; - if (!android::base::ParseUint(bytes_str, &bytes)) { - ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n", - name, bytes_str); - free(bytes_str); - return nullptr; + if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n", + name, bytes_str.c_str()); } return StringValue(CacheSizeCheck(bytes) ? "" : "t"); @@ -1013,61 +947,51 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc < 6 || (argc % 2) == 1) { return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " - "even number, got %d", name, argc); + "even number, got %d", name, argc); } - char* source_filename; - char* target_filename; - char* target_sha1; - char* target_size_str; - if (ReadArgs(state, argv, 4, &source_filename, &target_filename, - &target_sha1, &target_size_str) < 0) { - return NULL; + std::vector args; + if (!ReadArgs(state, 4, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& source_filename = args[0]; + const std::string& target_filename = args[1]; + const std::string& target_sha1 = args[2]; + const std::string& target_size_str = args[3]; size_t target_size; - if (!android::base::ParseUint(target_size_str, &target_size)) { - ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", - name, target_size_str); - free(source_filename); - free(target_filename); - free(target_sha1); - free(target_size_str); - return nullptr; + if (!android::base::ParseUint(target_size_str.c_str(), &target_size)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", + name, target_size_str.c_str()); } int patchcount = (argc-4) / 2; - std::unique_ptr arg_values(ReadValueVarArgs(state, argc-4, argv+4)); - if (!arg_values) { + std::vector> arg_values; + if (!ReadValueArgs(state, argc-4, argv+4, &arg_values)) { return nullptr; } - std::vector> patch_shas; - std::vector> 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]); - patches.emplace_back(arg_values.get()[i+1]); - } for (int i = 0; i < patchcount; ++i) { - if (patch_shas[i]->type != VAL_STRING) { - ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i); - return nullptr; + if (arg_values[i * 2]->type != VAL_STRING) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, + i * 2); } - if (patches[i]->type != VAL_BLOB) { - ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i); - return nullptr; + if (arg_values[i * 2 + 1]->type != VAL_BLOB) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, + i * 2 + 1); } } std::vector patch_sha_str; + std::vector> patches; for (int i = 0; i < patchcount; ++i) { - patch_sha_str.push_back(patch_shas[i]->data); + patch_sha_str.push_back(arg_values[i * 2]->data); + patches.push_back(std::move(arg_values[i * 2 + 1])); } - int result = applypatch(source_filename, target_filename, - target_sha1, target_size, - patch_sha_str, patches, NULL); + int result = applypatch(source_filename.c_str(), target_filename.c_str(), + target_sha1.c_str(), target_size, + patch_sha_str, patches, nullptr); return StringValue(result == 0 ? "t" : ""); } @@ -1080,17 +1004,17 @@ Value* ApplyPatchCheckFn(const char* name, State* state, name, argc); } - char* filename; - if (ReadArgs(state, argv, 1, &filename) < 0) { - return nullptr; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } + const std::string& filename = args[0]; std::vector sha1s; - if (!ReadArgs(state, argc-1, argv+1, &sha1s)) { - return nullptr; + if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - - int result = applypatch_check(filename, sha1s); + int result = applypatch_check(filename.c_str(), sha1s); return StringValue(result == 0 ? "t" : ""); } @@ -1098,19 +1022,12 @@ Value* ApplyPatchCheckFn(const char* name, State* state, // This is the updater side handler for ui_print() in edify script. Contents // will be sent over to the recovery side for on-screen display. Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { - char** args = ReadVarArgs(state, argc, argv); - if (args == NULL) { - return NULL; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - std::string buffer; - for (int i = 0; i < argc; ++i) { - buffer += args[i]; - free(args[i]); - } - free(args); - - buffer += "\n"; + std::string buffer = android::base::Join(args, "") + "\n"; uiPrint(state, buffer); return StringValue(buffer); } @@ -1127,14 +1044,17 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } - char** args = ReadVarArgs(state, argc, argv); - if (args == NULL) { - return NULL; + + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - char** args2 = reinterpret_cast(malloc(sizeof(char*) * (argc+1))); - memcpy(args2, args, sizeof(char*) * argc); - args2[argc] = NULL; + char* args2[argc+1]; + for (int i = 0; i < argc; i++) { + args2[i] = &args[i][0]; + } + args2[argc] = nullptr; printf("about to run program [%s] with %d args\n", args2[0], argc); @@ -1156,13 +1076,6 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { WTERMSIG(status)); } - int i; - for (i = 0; i < argc; ++i) { - free(args[i]); - } - free(args); - free(args2); - return StringValue(android::base::StringPrintf("%d", status)); } @@ -1179,13 +1092,9 @@ 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 arg_values(ReadValueVarArgs(state, argc, argv)); - if (arg_values == nullptr) { - return nullptr; - } std::vector> args; - for (int i = 0; i < argc; ++i) { - args.emplace_back(arg_values.get()[i]); + if (!ReadValueArgs(state, argc, argv, &args)) { + return nullptr; } if (args[0]->type == VAL_INVALID) { @@ -1221,17 +1130,20 @@ Value* ReadFileFn(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* filename; - if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; + + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; Value* v = new Value(VAL_INVALID, ""); FileContents fc; - if (LoadFileContents(filename, &fc) == 0) { + if (LoadFileContents(filename.c_str(), &fc) == 0) { v->type = VAL_BLOB; v->data = std::string(fc.data.begin(), fc.data.end()); } - free(filename); return v; } @@ -1249,27 +1161,27 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* filename; - char* property; - if (ReadArgs(state, argv, 2, &filename, &property) < 0) return NULL; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& property = args[1]; // zero out the 'command' field of the bootloader message. char buffer[80]; memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); - FILE* f = ota_fopen(filename, "r+b"); + FILE* f = ota_fopen(filename.c_str(), "r+b"); fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); ota_fclose(f); - free(filename); std::string reboot_cmd = "reboot,"; - if (property != nullptr) reboot_cmd += property; + reboot_cmd += property; android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); sleep(5); - free(property); - ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); - return NULL; + return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); } // Store a string value somewhere that future invocations of recovery @@ -1287,26 +1199,28 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* filename; - char* stagestr; - if (ReadArgs(state, argv, 2, &filename, &stagestr) < 0) return NULL; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + std::string& stagestr = args[1]; // Store this value in the misc partition, immediately after the // bootloader message that the main recovery uses to save its // arguments in case of the device restarting midway through // package installation. - FILE* f = ota_fopen(filename, "r+b"); + FILE* f = ota_fopen(filename.c_str(), "r+b"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - size_t to_write = strlen(stagestr) + 1; + size_t to_write = stagestr.size(); 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 = stagestr.substr(0, max_size-1); } - size_t status = ota_fwrite(stagestr, to_write, 1, f); + size_t status = ota_fwrite(stagestr.c_str(), to_write, 1, f); ota_fclose(f); - free(stagestr); if (status != to_write) { return StringValue(""); } @@ -1320,11 +1234,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); } - char* filename; - if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; char buffer[sizeof(((struct bootloader_message*)0)->stage)]; - FILE* f = ota_fopen(filename, "rb"); + FILE* f = ota_fopen(filename.c_str(), "rb"); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); size_t status = ota_fread(buffer, sizeof(buffer), 1, f); ota_fclose(f); @@ -1341,21 +1258,25 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); } - char* filename; - char* len_str; - if (ReadArgs(state, argv, 2, &filename, &len_str) < 0) return NULL; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& len_str = args[1]; size_t len; - android::base::ParseUint(len_str, &len); - int fd = ota_open(filename, O_WRONLY, 0644); - int success = wipe_block_device(fd, len); - - free(filename); - free(len_str); + if (!android::base::ParseUint(len_str.c_str(), &len)) { + return nullptr; + } + int fd = ota_open(filename.c_str(), O_WRONLY, 0644); + // The wipe_block_device function in ext4_utils returns 0 on success and 1 + // for failure. + int status = wipe_block_device(fd, len); ota_close(fd); - return StringValue(success ? "t" : ""); + return StringValue((status == 0) ? "t" : ""); } Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1372,28 +1293,27 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); } - char** args = ReadVarArgs(state, argc, argv); - if (args == NULL) { + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); } - char** args2 = reinterpret_cast(malloc(sizeof(char*) * (argc+1))); + char* args2[argc+1]; // Tune2fs expects the program name as its args[0] - args2[0] = strdup(name); - for (int i = 0; i < argc; ++i) { - args2[i + 1] = args[i]; + args2[0] = const_cast(name); + if (args2[0] == nullptr) { + return nullptr; } - int result = tune2fs_main(argc + 1, args2); for (int i = 0; i < argc; ++i) { - free(args[i]); + args2[i + 1] = &args[i][0]; } - free(args); - free(args2[0]); - free(args2); + // tune2fs changes the file system parameters on an ext2 file system; it + // returns 0 on success. + int result = tune2fs_main(argc + 1, args2); + if (result != 0) { - return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", - name, result); + return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); } return StringValue("t"); } -- cgit v1.2.3 From 51d516e913753a3a1416130b215591e309f0eb2c Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 3 Nov 2016 14:49:01 -0700 Subject: updater: Fix an off-by-1 bug in file_getprop(). Also add a testcase for file_getprop(). Test: recovery_component_test passes. Change-Id: I8eb2f9a5702b43997ac9f4b29665eea087b1c146 --- updater/install.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index efc96c454..19ba36534 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -860,9 +860,13 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // file_getprop(file, key) // // interprets 'file' as a getprop-style file (key=value pairs, one -// per line. # comment lines,blank lines, lines without '=' ignored), +// per line. # comment lines, blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } + std::vector args; if (!ReadArgs(state, 2, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); @@ -876,11 +880,10 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { filename.c_str(), strerror(errno)); } -#define MAX_FILE_GETPROP_SIZE 65536 - + constexpr off_t MAX_FILE_GETPROP_SIZE = 65536; if (st.st_size > MAX_FILE_GETPROP_SIZE) { - return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", - filename.c_str(), name, MAX_FILE_GETPROP_SIZE); + return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)", + filename.c_str(), name, static_cast(MAX_FILE_GETPROP_SIZE)); } std::string buffer(st.st_size, '\0'); @@ -913,7 +916,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } // trim whitespace between key and '=' - std::string str = android::base::Trim(line.substr(0, equal_pos - 1)); + std::string str = android::base::Trim(line.substr(0, equal_pos)); // not the key we're looking for if (key != str) continue; -- cgit v1.2.3 From 0831d0b592b2b4abb317a785d0b27e443b8a83db Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 3 Nov 2016 23:25:04 -0700 Subject: updater: Fix a bug in DeleteFn(). Also add a testcase for delete() function. Test: recovery_component_test passes. Change-Id: I064d1ad4693c3ed339d0a69eabadd08a61a2ea86 --- updater/install.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 19ba36534..25f6a9106 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -66,7 +66,7 @@ // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { - UpdaterInfo* ui = reinterpret_cast(state->cookie); + UpdaterInfo* ui = static_cast(state->cookie); // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "". // So skip sending empty strings to UI. @@ -117,6 +117,7 @@ static int make_parents(char* name) { } // mount(fs_type, partition_type, location, mount_point) +// mount(fs_type, partition_type, location, mount_point, mount_options) // // fs_type="ext4" partition_type="EMMC" location=device Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -252,7 +253,6 @@ static int exec_cmd(const char* path, char* const argv[]) { return WEXITSTATUS(status); } - // format(fs_type, partition_type, location, fs_size, mount_point) // // fs_type="ext4" partition_type="EMMC" location=device fs_size= mount_point= @@ -301,14 +301,13 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { if (fs_type == "ext4") { int status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle); if (status != 0) { - printf("%s: make_ext4fs failed (%d) on %s", - name, status, location.c_str()); + printf("%s: make_ext4fs failed (%d) on %s", name, status, location.c_str()); return StringValue(""); } return StringValue(location); } else if (fs_type == "f2fs") { if (size < 0) { - printf("fs_size can't be negative for f2fs: %s", fs_size.c_str()); + printf("%s: fs_size can't be negative for f2fs: %s", name, fs_size.c_str()); return StringValue(""); } std::string num_sectors = std::to_string(size / 512); @@ -318,8 +317,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { num_sectors.c_str(), nullptr}; int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv); if (status != 0) { - printf("%s: mkfs.f2fs failed (%d) on %s", - name, status, location.c_str()); + printf("%s: mkfs.f2fs failed (%d) on %s", name, status, location.c_str()); return StringValue(""); } return StringValue(location); @@ -365,8 +363,14 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(dst_name); } +// delete([filename, ...]) +// Deletes all the filenames listed. Returns the number of files successfully deleted. +// +// delete_recursive([dirname, ...]) +// Recursively deletes dirnames and all their contents. Returns the number of directories +// successfully deleted. Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - std::vector paths; + std::vector paths(argc); for (int i = 0; i < argc; ++i) { if (!Evaluate(state, argv[i], &paths[i])) { return nullptr; @@ -382,7 +386,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { } } - return StringValue(android::base::StringPrintf("%d", success)); + return StringValue(std::to_string(success)); } -- cgit v1.2.3 From a659d79b923cfce21f13519747d2f16048290849 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 3 Nov 2016 23:25:04 -0700 Subject: updater: Add a testcase for RenameFn(). Test: recovery_component_test passes. Change-Id: Iba5a0fdf6c79e2bed6b30b8fc19a306c1ab29d8a --- updater/install.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 25f6a9106..ed55ea517 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -293,7 +293,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { } int64_t size; - if (!android::base::ParseInt(fs_size.c_str(), &size)) { + if (!android::base::ParseInt(fs_size, &size)) { return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s\n", name, fs_size.c_str()); } @@ -329,6 +329,9 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } +// rename(src_name, dst_name) +// Renames src_name to dst_name. It automatically creates the necessary directories for dst_name. +// Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk") Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); -- cgit v1.2.3 From d75003d24c6e33befe041dd0cad7be3df199636c Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Fri, 4 Nov 2016 11:31:29 -0700 Subject: Make make_parent() to take const argument Switch to use const std::string; and add corresponding tests. Bug: 32649858 Test: Component tests pass Change-Id: I640f3ec81f1481fa91aa310f8d4d96dac9649cb9 --- updater/install.cpp | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index ed55ea517..cba95f5b0 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -95,25 +95,33 @@ void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { uiPrint(state, error_msg); } +static bool is_dir(const std::string& dirpath) { + struct stat st; + return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode); +} + // 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; +static bool make_parents(const std::string& name) { + size_t prev_end = 0; + while (prev_end < name.size()) { + size_t next_end = name.find('/', prev_end + 1); + if (next_end == std::string::npos) { + break; + } + std::string dir_path = name.substr(0, next_end); + if (!is_dir(dir_path)) { + int result = mkdir(dir_path.c_str(), 0700); + if (result != 0) { + printf("failed to mkdir %s when make parents for %s: %s\n", dir_path.c_str(), + name.c_str(), strerror(errno)); + return false; + } + + printf("created [%s]\n", dir_path.c_str()); } + prev_end = next_end; } - return 0; + return true; } // mount(fs_type, partition_type, location, mount_point) @@ -342,7 +350,7 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& src_name = args[0]; - std::string& dst_name = args[1]; + const std::string& dst_name = args[1]; if (src_name.empty()) { return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", @@ -352,7 +360,7 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); } - if (make_parents(&dst_name[0]) != 0) { + if (!make_parents(dst_name)) { return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", dst_name.c_str(), strerror(errno)); } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { @@ -583,7 +591,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { ++bad; } } - if (make_parents(&srcs[i][0])) { + if (!make_parents(srcs[i])) { printf("%s: failed to symlink %s to %s: making parents failed\n", name, srcs[i].c_str(), target.c_str()); ++bad; -- cgit v1.2.3 From 8992902aab88b26b383d95dd7b35c17934b069d5 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 8 Nov 2016 20:51:31 -0800 Subject: updater: Add more testcase for symlink(). Clean up SymlinkFn() a bit. Also clean up the temp files created when running the tests; otherwise non-empty TemporaryDir won't be removed. Test: recovery_component_test passes. Change-Id: Id3844abebd168c40125c4dcec54e6ef680a83c3a --- updater/install.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index cba95f5b0..59c54dd4c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -566,8 +566,9 @@ Value* PackageExtractFileFn(const char* name, State* state, } } -// symlink target src1 src2 ... -// unlinks any previously existing src1, src2, etc before creating symlinks. +// symlink(target, [src1, src2, ...]) +// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc +// before creating symlinks. 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); @@ -579,33 +580,29 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { std::vector srcs; if (!ReadArgs(state, argc-1, argv+1, &srcs)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", + name); } - int bad = 0; - for (int i = 0; i < argc-1; ++i) { - if (unlink(srcs[i].c_str()) < 0) { - if (errno != ENOENT) { - printf("%s: failed to remove %s: %s\n", - name, srcs[i].c_str(), strerror(errno)); - ++bad; - } - } - if (!make_parents(srcs[i])) { + size_t bad = 0; + for (const auto& src : srcs) { + if (unlink(src.c_str()) == -1 && errno != ENOENT) { + printf("%s: failed to remove %s: %s\n", name, src.c_str(), strerror(errno)); + ++bad; + } else if (!make_parents(src)) { printf("%s: failed to symlink %s to %s: making parents failed\n", - name, srcs[i].c_str(), target.c_str()); + name, src.c_str(), target.c_str()); ++bad; - } - if (symlink(target.c_str(), srcs[i].c_str()) < 0) { + } else if (symlink(target.c_str(), src.c_str()) == -1) { printf("%s: failed to symlink %s to %s: %s\n", - name, srcs[i].c_str(), target.c_str(), strerror(errno)); + name, src.c_str(), target.c_str(), strerror(errno)); ++bad; } } - if (bad) { - return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); + if (bad != 0) { + return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); } - return StringValue(""); + return StringValue("t"); } struct perm_parsed_args { -- cgit v1.2.3 From ef0eb3b01b66fbbc97908667a3dd1e02d710cbb7 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 14 Nov 2016 21:29:52 -0800 Subject: updater: Fix the wrong return value for package_extract_file(). 'bool success = ExtractEntryToFile()' gives opposite result. Fix the issue and add testcases. Change the one-argument version of package_extract_file() to explicitly abort for non-existent zip entry. Note that this is NOT changing the behavior. Prior to this CL, it aborts from Evaluate() function, by giving a general cause code. Now it returns kPackageExtractFileFailure. BUg: 32903624 Test: recovery_component_test works. Change-Id: I7a273e9c0d9aaaf8c472b2c778f7b8d90362c24f --- updater/install.cpp | 145 +++++++++++++++++++++++++--------------------------- 1 file changed, 69 insertions(+), 76 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 59c54dd4c..b885f864e 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -477,93 +477,86 @@ Value* PackageExtractDirFn(const char* name, State* state, return StringValue(success ? "t" : ""); } +// package_extract_file(package_file[, dest_file]) +// Extracts a single package_file from the update package and writes it to dest_file, +// overwriting existing files if necessary. Without the dest_file argument, returns the +// contents of the package file as a binary blob. +Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc < 1 || argc > 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc); + } + + if (argc == 2) { + // The two-argument version extracts to a file. -// package_extract_file(package_path, destination_path) -// or -// package_extract_file(package_path) -// to return the entire contents of the file as the result of this -// function (the char* returned is actually a FileContents*). -Value* PackageExtractFileFn(const char* name, State* state, - int argc, Expr* argv[]) { - if (argc < 1 || argc > 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", - name, argc); + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); } - bool success = false; - - if (argc == 2) { - // The two-argument version extracts to a file. - - ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; - - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, - argc); - } - const std::string& zip_path = args[0]; - const std::string& dest_path = args[1]; + const std::string& zip_path = args[0]; + const std::string& dest_path = args[1]; - ZipString zip_string_path(zip_path.c_str()); - ZipEntry entry; - if (FindEntry(za, zip_string_path, &entry) != 0) { - printf("%s: no %s in package\n", name, zip_path.c_str()); - return StringValue(""); - } + ZipArchiveHandle za = static_cast(state->cookie)->package_zip; + ZipString zip_string_path(zip_path.c_str()); + ZipEntry entry; + if (FindEntry(za, zip_string_path, &entry) != 0) { + printf("%s: no %s in package\n", name, zip_path.c_str()); + return StringValue(""); + } - int fd = TEMP_FAILURE_RETRY(ota_open(dest_path.c_str(), 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.c_str(), strerror(errno)); - return StringValue(""); - } - success = ExtractEntryToFile(za, &entry, fd); - if (ota_fsync(fd) == -1) { - printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); - success = false; - } - if (ota_close(fd) == -1) { - printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); - success = false; - } + int fd = TEMP_FAILURE_RETRY( + ota_open(dest_path.c_str(), 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.c_str(), strerror(errno)); + return StringValue(""); + } - return StringValue(success ? "t" : ""); - } else { - // The one-argument version returns the contents of the file - // as the result. + bool success = true; + int32_t ret = ExtractEntryToFile(za, &entry, fd); + if (ret != 0) { + printf("%s: Failed to extract entry \"%s\" (%u bytes) to \"%s\": %s\n", name, + zip_path.c_str(), entry.uncompressed_length, dest_path.c_str(), ErrorCodeString(ret)); + success = false; + } + if (ota_fsync(fd) == -1) { + printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + success = false; + } + if (ota_close(fd) == -1) { + printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + success = false; + } - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, - argc); - } - const std::string& zip_path = args[0]; + return StringValue(success ? "t" : ""); + } else { + // The one-argument version returns the contents of the file as the result. - Value* v = new Value(VAL_INVALID, ""); + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + } + const std::string& zip_path = args[0]; - ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; - ZipString zip_string_path(zip_path.c_str()); - ZipEntry entry; - if (FindEntry(za, zip_string_path, &entry) != 0) { - printf("%s: no %s in package\n", name, zip_path.c_str()); - return v; - } + ZipArchiveHandle za = static_cast(state->cookie)->package_zip; + ZipString zip_string_path(zip_path.c_str()); + ZipEntry entry; + if (FindEntry(za, zip_string_path, &entry) != 0) { + return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name, + zip_path.c_str()); + } - v->data.resize(entry.uncompressed_length); - if (ExtractToMemory(za, &entry, reinterpret_cast(&v->data[0]), - v->data.size()) != 0) { - printf("%s: faled to extract %zu bytes to memory\n", name, v->data.size()); - } else { - success = true; - } + std::string buffer; + buffer.resize(entry.uncompressed_length); - if (!success) { - v->data.clear(); - } else { - v->type = VAL_BLOB; - } - return v; + int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast(&buffer[0]), buffer.size()); + if (ret != 0) { + return ErrorAbort(state, kPackageExtractFileFailure, + "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name, + zip_path.c_str(), buffer.size(), ErrorCodeString(ret)); } + + return new Value(VAL_BLOB, buffer); + } } // symlink(target, [src1, src2, ...]) -- cgit v1.2.3 From d0f3088aa95e255b39ed4b83da6b08866c2c3e0c Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 3 Nov 2016 23:52:01 -0700 Subject: updater: Add "write_value()" function. write_value(value, filename) writes 'value' to 'filename'. It can be used to tune device settings when applying an OTA package. For example, write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"). Bug: 32463933 Test: recovery_component_test passes. Test: Apply an OTA package that contains a call to write_value(), and check the result. Change-Id: Ib009ecb8a45a94353f10c59e2383fe1f49796e35 --- updater/install.cpp | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index b885f864e..da68420e8 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -39,11 +39,12 @@ #include #include -#include +#include #include +#include #include -#include #include +#include #include #include #include @@ -861,7 +862,6 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(value); } - // file_getprop(file, key) // // interprets 'file' as a getprop-style file (key=value pairs, one @@ -1155,6 +1155,33 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { return v; } +// write_value(value, filename) +// Writes 'value' to 'filename'. +// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") +Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } + + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); + } + + const std::string& filename = args[1]; + if (filename.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name); + } + + const std::string& value = args[0]; + if (!android::base::WriteStringToFile(value, filename)) { + printf("%s: Failed to write to \"%s\": %s\n", name, filename.c_str(), strerror(errno)); + return StringValue(""); + } else { + return StringValue("t"); + } +} + // Immediately reboot the device. Recovery is not finished normally, // so if you reboot into recovery it will re-start applying the // current package (because nothing has cleared the copy of the @@ -1363,6 +1390,7 @@ void RegisterInstallFunctions() { RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); RegisterFunction("rename", RenameFn); + RegisterFunction("write_value", WriteValueFn); RegisterFunction("wipe_cache", WipeCacheFn); -- cgit v1.2.3 From 1036d36542c452b8df0200d13029d172646a2719 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 17 Nov 2016 22:49:56 -0800 Subject: updater: Add testcase for package_extract_dir(). Test: recovery_component_test passes. Change-Id: I3af4707bc42c7331ca961be8b967a53de82ea25b --- updater/install.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index da68420e8..6c110732a 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -454,28 +454,32 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(frac_str); } -// package_extract_dir(package_path, destination_path) -Value* PackageExtractDirFn(const char* name, State* state, - int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } +// package_extract_dir(package_dir, dest_dir) +// Extracts all files from the package underneath package_dir and writes them to the +// corresponding tree beneath dest_dir. Any existing files are overwritten. +// Example: package_extract_dir("system", "/system") +// +// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path. +Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& zip_path = args[0]; - const std::string& dest_path = args[1]; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& zip_path = args[0]; + const std::string& dest_path = args[1]; - ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip; + ZipArchiveHandle za = static_cast(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 + // To create a consistent system image, never use the clock for timestamps. + constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default - bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle); + bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle); - return StringValue(success ? "t" : ""); + return StringValue(success ? "t" : ""); } // package_extract_file(package_file[, dest_file]) -- cgit v1.2.3 From bedf5fc11cea9cc6b92f37597fe8624d25b8d371 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 18 Nov 2016 12:01:26 -0800 Subject: updater: Refactor set_stage() and get_stage() functions. Add read_bootloader_message_from() and write_bootloader_message_to() to allow specifying the BCB device (/misc). Also add testcases for set_stage() and get_stage(). Test: recovery_component_test passes. Test: Build a recovery image and apply a two-step OTA package. Change-Id: If5ab06a1aaaea168d2a9e5dd63c07c0a3190e4ae --- updater/install.cpp | 135 ++++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 68 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 6c110732a..b9bc19e2c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -1196,31 +1196,35 @@ Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { // partition, or "" (empty string) to boot from the regular boot // partition. Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; - const std::string& property = args[1]; - - // zero out the 'command' field of the bootloader message. - char buffer[80]; - memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); - FILE* f = ota_fopen(filename.c_str(), "r+b"); - fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); - ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); - ota_fclose(f); + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& property = args[1]; + + // Zero out the 'command' field of the bootloader message. Leave the rest intact. + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } + memset(boot.command, 0, sizeof(boot.command)); + if (!write_bootloader_message_to(boot, filename, &err)) { + printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - std::string reboot_cmd = "reboot,"; - reboot_cmd += property; - android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); + const std::string reboot_cmd = "reboot," + property; + android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); - sleep(5); - return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); + sleep(5); + return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); } // Store a string value somewhere that future invocations of recovery @@ -1234,62 +1238,57 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // second argument is the string to store; it should not exceed 31 // bytes. Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; - std::string& stagestr = args[1]; - - // Store this value in the misc partition, immediately after the - // bootloader message that the main recovery uses to save its - // arguments in case of the device restarting midway through - // package installation. - FILE* f = ota_fopen(filename.c_str(), "r+b"); - fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - size_t to_write = stagestr.size(); - size_t max_size = sizeof(((struct bootloader_message*)0)->stage); - if (to_write > max_size) { - to_write = max_size; - stagestr = stagestr.substr(0, max_size-1); - } - size_t status = ota_fwrite(stagestr.c_str(), to_write, 1, f); - ota_fclose(f); + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& stagestr = args[1]; + + // Store this value in the misc partition, immediately after the + // bootloader message that the main recovery uses to save its + // arguments in case of the device restarting midway through + // package installation. + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } + strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage)); + if (!write_bootloader_message_to(boot, filename, &err)) { + printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - if (status != to_write) { - return StringValue(""); - } - return StringValue(filename); + return StringValue(filename); } // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; - char buffer[sizeof(((struct bootloader_message*)0)->stage)]; - FILE* f = ota_fopen(filename.c_str(), "rb"); - fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - size_t status = ota_fread(buffer, sizeof(buffer), 1, f); - ota_fclose(f); - if (status != sizeof(buffer)) { - return StringValue(""); - } + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - buffer[sizeof(buffer)-1] = '\0'; - return StringValue(buffer); + return StringValue(boot.stage); } Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { -- cgit v1.2.3 From 358c2ec1dca24d48a503b441d38545ace021ea8e Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 28 Nov 2016 11:48:43 -0800 Subject: Remove ota_close(int) and ota_fclose(FILE*). We should always use unique_fd or unique_file to hold the FD or FILE* pointer when opening via ota_(f)open functions. This CL avoids accidentally closing raw FDs or FILE* pointers that are managed by unique_fd/unique_file. Test: recovery_component_test passes. Change-Id: If58eb8b5c5da507563f85efd5d56276472a1c957 --- updater/install.cpp | 142 +++++++++++++++++++++++++--------------------------- 1 file changed, 69 insertions(+), 73 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index b9bc19e2c..8db5c1fe0 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -509,8 +509,8 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv return StringValue(""); } - int fd = TEMP_FAILURE_RETRY( - ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + unique_fd fd(TEMP_FAILURE_RETRY( + ota_open(dest_path.c_str(), 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.c_str(), strerror(errno)); return StringValue(""); @@ -872,68 +872,67 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // per line. # comment lines, blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; - const std::string& key = args[1]; + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& key = args[1]; - struct stat st; - if (stat(filename.c_str(), &st) < 0) { - return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, - filename.c_str(), strerror(errno)); - } + struct stat st; + if (stat(filename.c_str(), &st) < 0) { + return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, + filename.c_str(), strerror(errno)); + } - constexpr off_t MAX_FILE_GETPROP_SIZE = 65536; - if (st.st_size > MAX_FILE_GETPROP_SIZE) { - return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)", - filename.c_str(), name, static_cast(MAX_FILE_GETPROP_SIZE)); - } + constexpr off_t MAX_FILE_GETPROP_SIZE = 65536; + if (st.st_size > MAX_FILE_GETPROP_SIZE) { + return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)", + filename.c_str(), name, static_cast(MAX_FILE_GETPROP_SIZE)); + } - std::string buffer(st.st_size, '\0'); - FILE* f = ota_fopen(filename.c_str(), "rb"); - if (f == nullptr) { - return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, - filename.c_str(), strerror(errno)); - } + std::string buffer(st.st_size, '\0'); + unique_file f(ota_fopen(filename.c_str(), "rb")); + if (f == nullptr) { + return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename.c_str(), + strerror(errno)); + } - if (ota_fread(&buffer[0], 1, st.st_size, f) != static_cast(st.st_size)) { - ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", - name, static_cast(st.st_size), filename.c_str()); - ota_fclose(f); - return nullptr; - } + if (ota_fread(&buffer[0], 1, st.st_size, f.get()) != static_cast(st.st_size)) { + ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name, + static_cast(st.st_size), filename.c_str()); + return nullptr; + } - ota_fclose(f); + ota_fclose(f); - std::vector lines = android::base::Split(buffer, "\n"); - for (size_t i = 0; i < lines.size(); i++) { - std::string line = android::base::Trim(lines[i]); + std::vector lines = android::base::Split(buffer, "\n"); + for (size_t i = 0; i < lines.size(); i++) { + std::string line = android::base::Trim(lines[i]); - // comment or blank line: skip to next line - if (line.empty() || line[0] == '#') { - continue; - } - size_t equal_pos = line.find('='); - if (equal_pos == std::string::npos) { - continue; - } + // comment or blank line: skip to next line + if (line.empty() || line[0] == '#') { + continue; + } + size_t equal_pos = line.find('='); + if (equal_pos == std::string::npos) { + continue; + } - // trim whitespace between key and '=' - std::string str = android::base::Trim(line.substr(0, equal_pos)); + // trim whitespace between key and '=' + std::string str = android::base::Trim(line.substr(0, equal_pos)); - // not the key we're looking for - if (key != str) continue; + // not the key we're looking for + if (key != str) continue; - return StringValue(android::base::Trim(line.substr(equal_pos + 1))); - } + return StringValue(android::base::Trim(line.substr(equal_pos + 1))); + } - return StringValue(""); + return StringValue(""); } // apply_patch_space(bytes) @@ -1292,29 +1291,26 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } - - std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; - const std::string& len_str = args[1]; - - size_t len; - if (!android::base::ParseUint(len_str.c_str(), &len)) { - return nullptr; - } - int fd = ota_open(filename.c_str(), O_WRONLY, 0644); - // The wipe_block_device function in ext4_utils returns 0 on success and 1 - // for failure. - int status = wipe_block_device(fd, len); + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - ota_close(fd); + std::vector args; + if (!ReadArgs(state, 2, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; + const std::string& len_str = args[1]; - return StringValue((status == 0) ? "t" : ""); + size_t len; + if (!android::base::ParseUint(len_str.c_str(), &len)) { + return nullptr; + } + unique_fd fd(ota_open(filename.c_str(), O_WRONLY, 0644)); + // The wipe_block_device function in ext4_utils returns 0 on success and 1 + // for failure. + int status = wipe_block_device(fd, len); + return StringValue((status == 0) ? "t" : ""); } Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { -- cgit v1.2.3 From 039f2da3e464034404afe27aebd93f84fba119b6 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 22 Nov 2016 16:29:50 -0800 Subject: updater: Switch to libbase logging. Test: Build an updater into a package and apply it on device. Change-Id: I289b5768e9b1e44ef78e0479c64dbaa36fb1a685 --- updater/install.cpp | 1484 +++++++++++++++++++++++++-------------------------- 1 file changed, 742 insertions(+), 742 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 8db5c1fe0..3cf38774e 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -67,33 +68,33 @@ // Send over the buffer to recovery though the command pipe. static void uiPrint(State* state, const std::string& buffer) { - UpdaterInfo* ui = static_cast(state->cookie); - - // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "". - // So skip sending empty strings to UI. - std::vector lines = android::base::Split(buffer, "\n"); - for (auto& line: lines) { - if (!line.empty()) { - fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str()); - fprintf(ui->cmd_pipe, "ui_print\n"); - } + UpdaterInfo* ui = static_cast(state->cookie); + + // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "". + // So skip sending empty strings to UI. + std::vector lines = android::base::Split(buffer, "\n"); + for (auto& line : lines) { + if (!line.empty()) { + fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str()); + fprintf(ui->cmd_pipe, "ui_print\n"); } + } - // On the updater side, we need to dump the contents to stderr (which has - // been redirected to the log file). Because the recovery will only print - // the contents to screen when processing pipe command ui_print. - fprintf(stderr, "%s", buffer.c_str()); + // On the updater side, we need to dump the contents to stderr (which has + // been redirected to the log file). Because the recovery will only print + // the contents to screen when processing pipe command ui_print. + LOG(INFO) << buffer; } void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { - std::string error_msg; + std::string error_msg; - va_list ap; - va_start(ap, format); - android::base::StringAppendV(&error_msg, format, ap); - va_end(ap); + va_list ap; + va_start(ap, format); + android::base::StringAppendV(&error_msg, format, ap); + va_end(ap); - uiPrint(state, error_msg); + uiPrint(state, error_msg); } static bool is_dir(const std::string& dirpath) { @@ -103,26 +104,25 @@ static bool is_dir(const std::string& dirpath) { // Create all parent directories of name, if necessary. static bool make_parents(const std::string& name) { - size_t prev_end = 0; - while (prev_end < name.size()) { - size_t next_end = name.find('/', prev_end + 1); - if (next_end == std::string::npos) { - break; - } - std::string dir_path = name.substr(0, next_end); - if (!is_dir(dir_path)) { - int result = mkdir(dir_path.c_str(), 0700); - if (result != 0) { - printf("failed to mkdir %s when make parents for %s: %s\n", dir_path.c_str(), - name.c_str(), strerror(errno)); - return false; - } - - printf("created [%s]\n", dir_path.c_str()); - } - prev_end = next_end; - } - return true; + size_t prev_end = 0; + while (prev_end < name.size()) { + size_t next_end = name.find('/', prev_end + 1); + if (next_end == std::string::npos) { + break; + } + std::string dir_path = name.substr(0, next_end); + if (!is_dir(dir_path)) { + int result = mkdir(dir_path.c_str(), 0700); + if (result != 0) { + PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name; + return false; + } + + LOG(INFO) << "created [" << dir_path << "]"; + } + prev_end = next_end; + } + return true; } // mount(fs_type, partition_type, location, mount_point) @@ -130,249 +130,242 @@ static bool make_parents(const std::string& name) { // // fs_type="ext4" partition_type="EMMC" location=device Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 4 && argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); - } + if (argc != 4 && argc != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& fs_type = args[0]; - const std::string& partition_type = args[1]; - const std::string& location = args[2]; - const std::string& mount_point = args[3]; - std::string mount_options; - - if (argc == 5) { - mount_options = args[4]; - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& fs_type = args[0]; + const std::string& partition_type = args[1]; + const std::string& location = args[2]; + const std::string& mount_point = args[3]; + std::string mount_options; + + if (argc == 5) { + mount_options = args[4]; + } - if (fs_type.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", - name); - } - if (partition_type.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", - name); - } - if (location.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", - name); - } - if (mount_point.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", - name); - } + if (fs_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name); + } + if (partition_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", + name); + } + if (location.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name); + } + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", + name); + } - { - char *secontext = NULL; + { + char* secontext = nullptr; - if (sehandle) { - selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755); - setfscreatecon(secontext); - } + if (sehandle) { + selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755); + setfscreatecon(secontext); + } - mkdir(mount_point.c_str(), 0755); + mkdir(mount_point.c_str(), 0755); - if (secontext) { - freecon(secontext); - setfscreatecon(NULL); - } + if (secontext) { + freecon(secontext); + setfscreatecon(nullptr); } + } - if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(), - MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) { - uiPrintf(state, "%s: failed to mount %s at %s: %s\n", - name, location.c_str(), mount_point.c_str(), strerror(errno)); - return StringValue(""); - } + if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(), + MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) { + uiPrintf(state, "%s: failed to mount %s at %s: %s\n", name, location.c_str(), + mount_point.c_str(), strerror(errno)); + return StringValue(""); + } - return StringValue(mount_point); + return StringValue(mount_point); } // is_mounted(mount_point) Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& mount_point = args[0]; - if (mount_point.empty()) { - return ErrorAbort(state, kArgsParsingFailure, - "mount_point argument to unmount() can't be empty"); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& mount_point = args[0]; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "mount_point argument to unmount() can't be empty"); + } - scan_mounted_volumes(); - MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); - if (vol == nullptr) { - return StringValue(""); - } + scan_mounted_volumes(); + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); + if (vol == nullptr) { + return StringValue(""); + } - return StringValue(mount_point); + return StringValue(mount_point); } - Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& mount_point = args[0]; - if (mount_point.empty()) { - return ErrorAbort(state, kArgsParsingFailure, - "mount_point argument to unmount() can't be empty"); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& mount_point = args[0]; + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, + "mount_point argument to unmount() can't be empty"); + } - scan_mounted_volumes(); - MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); - if (vol == nullptr) { - uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point.c_str()); - return nullptr; - } else { - int ret = unmount_mounted_volume(vol); - if (ret != 0) { - uiPrintf(state, "unmount of %s failed (%d): %s\n", - mount_point.c_str(), ret, strerror(errno)); - } + scan_mounted_volumes(); + MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str()); + if (vol == nullptr) { + uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point.c_str()); + return nullptr; + } else { + int ret = unmount_mounted_volume(vol); + if (ret != 0) { + uiPrintf(state, "unmount of %s failed (%d): %s\n", mount_point.c_str(), ret, strerror(errno)); } + } - return StringValue(mount_point); + return StringValue(mount_point); } static int exec_cmd(const char* path, char* const argv[]) { - int status; - pid_t child; - if ((child = vfork()) == 0) { - execv(path, argv); - _exit(-1); - } - waitpid(child, &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - printf("%s failed with status %d\n", path, WEXITSTATUS(status)); - } - return WEXITSTATUS(status); + pid_t child; + if ((child = vfork()) == 0) { + execv(path, argv); + _exit(-1); + } + + int status; + waitpid(child, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + LOG(ERROR) << path << " failed with status " << WEXITSTATUS(status); + } + return WEXITSTATUS(status); } // format(fs_type, partition_type, location, fs_size, mount_point) // -// fs_type="ext4" partition_type="EMMC" location=device fs_size= mount_point= -// fs_type="f2fs" partition_type="EMMC" location=device fs_size= mount_point= +// fs_type="ext4" partition_type="EMMC" location=device fs_size= mount_point= +// fs_type="f2fs" partition_type="EMMC" location=device fs_size= mount_point= // 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[]) { - if (argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); - } + if (argc != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& fs_type = args[0]; - const std::string& partition_type = args[1]; - const std::string& location = args[2]; - const std::string& fs_size = args[3]; - const std::string& mount_point = args[4]; - - if (fs_type.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", - name); - } - if (partition_type.empty()) { - return ErrorAbort(state, kArgsParsingFailure, - "partition_type argument to %s() can't be empty", name); - } - if (location.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", - name); - } - if (mount_point.empty()) { - return ErrorAbort(state, kArgsParsingFailure, - "mount_point argument to %s() can't be empty", name); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& fs_type = args[0]; + const std::string& partition_type = args[1]; + const std::string& location = args[2]; + const std::string& fs_size = args[3]; + const std::string& mount_point = args[4]; + + if (fs_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name); + } + if (partition_type.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty", + name); + } + if (location.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name); + } + if (mount_point.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty", + name); + } - int64_t size; - if (!android::base::ParseInt(fs_size, &size)) { - return ErrorAbort(state, kArgsParsingFailure, - "%s: failed to parse int in %s\n", name, fs_size.c_str()); + int64_t size; + if (!android::base::ParseInt(fs_size, &size)) { + return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s\n", name, + fs_size.c_str()); + } + + if (fs_type == "ext4") { + int status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle); + if (status != 0) { + LOG(ERROR) << name << ": make_ext4fs failed (" << status << ") on " << location; + return StringValue(""); } + return StringValue(location); + } else if (fs_type == "f2fs") { + if (size < 0) { + LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size; + return StringValue(""); + } + std::string num_sectors = std::to_string(size / 512); - if (fs_type == "ext4") { - int status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle); - if (status != 0) { - printf("%s: make_ext4fs failed (%d) on %s", name, status, location.c_str()); - return StringValue(""); - } - return StringValue(location); - } else if (fs_type == "f2fs") { - if (size < 0) { - printf("%s: fs_size can't be negative for f2fs: %s", name, fs_size.c_str()); - return StringValue(""); - } - std::string num_sectors = std::to_string(size / 512); - - const char *f2fs_path = "/sbin/mkfs.f2fs"; - const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location.c_str(), - num_sectors.c_str(), nullptr}; - int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv); - if (status != 0) { - printf("%s: mkfs.f2fs failed (%d) on %s", name, status, location.c_str()); - return StringValue(""); - } - return StringValue(location); - } else { - printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", - name, fs_type.c_str(), partition_type.c_str()); + const char* f2fs_path = "/sbin/mkfs.f2fs"; + const char* const f2fs_argv[] = { "mkfs.f2fs", "-t", "-d1", location.c_str(), + num_sectors.c_str(), nullptr }; + int status = exec_cmd(f2fs_path, const_cast(f2fs_argv)); + if (status != 0) { + LOG(ERROR) << name << ": mkfs.f2fs failed (" << status << ") on " << location; + return StringValue(""); } + return StringValue(location); + } else { + LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \"" + << partition_type << "\""; + } - return nullptr; + return nullptr; } // rename(src_name, dst_name) // Renames src_name to dst_name. It automatically creates the necessary directories for dst_name. // Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk") Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } - - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& src_name = args[0]; - const std::string& dst_name = args[1]; + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - if (src_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", - name); - } - if (dst_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", - name); - } - if (!make_parents(dst_name)) { - return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", - dst_name.c_str(), strerror(errno)); - } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { - // File was already moved - return StringValue(dst_name); - } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) { - return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", - src_name.c_str(), dst_name.c_str(), strerror(errno)); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& src_name = args[0]; + const std::string& dst_name = args[1]; + if (src_name.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name); + } + if (dst_name.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); + } + if (!make_parents(dst_name)) { + return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", + dst_name.c_str(), strerror(errno)); + } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { + // File was already moved return StringValue(dst_name); + } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) { + return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", + src_name.c_str(), dst_name.c_str(), strerror(errno)); + } + + return StringValue(dst_name); } // delete([filename, ...]) @@ -382,76 +375,76 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { // Recursively deletes dirnames and all their contents. Returns the number of directories // successfully deleted. Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - std::vector paths(argc); - for (int i = 0; i < argc; ++i) { - if (!Evaluate(state, argv[i], &paths[i])) { - return nullptr; - } + std::vector paths(argc); + for (int i = 0; i < argc; ++i) { + if (!Evaluate(state, argv[i], &paths[i])) { + return nullptr; } + } - bool recursive = (strcmp(name, "delete_recursive") == 0); + bool recursive = (strcmp(name, "delete_recursive") == 0); - int success = 0; - for (int i = 0; i < argc; ++i) { - if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) { - ++success; - } + int success = 0; + for (int i = 0; i < argc; ++i) { + if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) { + ++success; } + } - return StringValue(std::to_string(success)); + return StringValue(std::to_string(success)); } Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + if (argc != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& frac_str = args[0]; - const std::string& sec_str = args[1]; + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& frac_str = args[0]; + const std::string& sec_str = args[1]; - double frac; - if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { - return ErrorAbort(state, kArgsParsingFailure, - "%s: failed to parse double in %s\n", name, frac_str.c_str()); - } - int sec; - if (!android::base::ParseInt(sec_str.c_str(), &sec)) { - return ErrorAbort(state, kArgsParsingFailure, - "%s: failed to parse int in %s\n", name, sec_str.c_str()); - } + double frac; + if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { + return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s\n", name, + frac_str.c_str()); + } + int sec; + if (!android::base::ParseInt(sec_str.c_str(), &sec)) { + return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s\n", name, + sec_str.c_str()); + } - UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); - fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec); + UpdaterInfo* ui = static_cast(state->cookie); + fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec); - return StringValue(frac_str); + return StringValue(frac_str); } Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& frac_str = args[0]; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& frac_str = args[0]; - double frac; - if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { - return ErrorAbort(state, kArgsParsingFailure, - "%s: failed to parse double in %s\n", name, frac_str.c_str()); - } + double frac; + if (!android::base::ParseDouble(frac_str.c_str(), &frac)) { + return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s\n", name, + frac_str.c_str()); + } - UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); - fprintf(ui->cmd_pipe, "set_progress %f\n", frac); + UpdaterInfo* ui = static_cast(state->cookie); + fprintf(ui->cmd_pipe, "set_progress %f\n", frac); - return StringValue(frac_str); + return StringValue(frac_str); } // package_extract_dir(package_dir, dest_dir) @@ -505,30 +498,31 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv ZipString zip_string_path(zip_path.c_str()); ZipEntry entry; if (FindEntry(za, zip_string_path, &entry) != 0) { - printf("%s: no %s in package\n", name, zip_path.c_str()); + LOG(ERROR) << name << ": no " << zip_path << " in package"; return StringValue(""); } unique_fd fd(TEMP_FAILURE_RETRY( ota_open(dest_path.c_str(), 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.c_str(), strerror(errno)); + PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; return StringValue(""); } bool success = true; int32_t ret = ExtractEntryToFile(za, &entry, fd); if (ret != 0) { - printf("%s: Failed to extract entry \"%s\" (%u bytes) to \"%s\": %s\n", name, - zip_path.c_str(), entry.uncompressed_length, dest_path.c_str(), ErrorCodeString(ret)); + LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" (" + << entry.uncompressed_length << " bytes) to \"" << dest_path + << "\": " << ErrorCodeString(ret); success = false; } if (ota_fsync(fd) == -1) { - printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed"; success = false; } if (ota_close(fd) == -1) { - printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno)); + PLOG(ERROR) << "close of \"" << dest_path << "\" failed"; success = false; } @@ -568,241 +562,234 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv // Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc // before creating symlinks. 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); - } - std::string target; - if (!Evaluate(state, argv[0], &target)) { - return nullptr; - } + if (argc == 0) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); + } + std::string target; + if (!Evaluate(state, argv[0], &target)) { + return nullptr; + } - std::vector srcs; - if (!ReadArgs(state, argc-1, argv+1, &srcs)) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", - name); - } + std::vector srcs; + if (!ReadArgs(state, argc - 1, argv + 1, &srcs)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); + } - size_t bad = 0; - for (const auto& src : srcs) { - if (unlink(src.c_str()) == -1 && errno != ENOENT) { - printf("%s: failed to remove %s: %s\n", name, src.c_str(), strerror(errno)); - ++bad; - } else if (!make_parents(src)) { - printf("%s: failed to symlink %s to %s: making parents failed\n", - name, src.c_str(), target.c_str()); - ++bad; - } else if (symlink(target.c_str(), src.c_str()) == -1) { - printf("%s: failed to symlink %s to %s: %s\n", - name, src.c_str(), target.c_str(), strerror(errno)); - ++bad; - } - } - if (bad != 0) { - return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); + size_t bad = 0; + for (const auto& src : srcs) { + if (unlink(src.c_str()) == -1 && errno != ENOENT) { + PLOG(ERROR) << name << ": failed to remove " << src; + ++bad; + } else if (!make_parents(src)) { + LOG(ERROR) << name << ": failed to symlink " << src << " to " << target + << ": making parents failed"; + ++bad; + } else if (symlink(target.c_str(), src.c_str()) == -1) { + PLOG(ERROR) << name << ": failed to symlink " << src << " to " << target; + ++bad; } - return StringValue("t"); + } + if (bad != 0) { + return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); + } + return StringValue("t"); } struct perm_parsed_args { - bool has_uid; - uid_t uid; - bool has_gid; - gid_t gid; - bool has_mode; - mode_t mode; - bool has_fmode; - mode_t fmode; - bool has_dmode; - mode_t dmode; - bool has_selabel; - const char* selabel; - bool has_capabilities; - uint64_t capabilities; + bool has_uid; + uid_t uid; + bool has_gid; + gid_t gid; + bool has_mode; + mode_t mode; + bool has_fmode; + mode_t fmode; + bool has_dmode; + mode_t dmode; + bool has_selabel; + const char* selabel; + bool has_capabilities; + uint64_t capabilities; }; static struct perm_parsed_args ParsePermArgs(State * state, int argc, const std::vector& args) { - int i; - struct perm_parsed_args parsed; - int bad = 0; - static int max_warnings = 20; - - memset(&parsed, 0, sizeof(parsed)); - - for (i = 1; i < argc; i += 2) { - if (args[i] == "uid") { - int64_t uid; - if (sscanf(args[i+1].c_str(), "%" SCNd64, &uid) == 1) { - parsed.uid = uid; - parsed.has_uid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "gid") { - int64_t gid; - if (sscanf(args[i+1].c_str(), "%" SCNd64, &gid) == 1) { - parsed.gid = gid; - parsed.has_gid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "mode") { - int32_t mode; - if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.mode = mode; - parsed.has_mode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "dmode") { - int32_t mode; - if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.dmode = mode; - parsed.has_dmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "fmode") { - int32_t mode; - if (sscanf(args[i+1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.fmode = mode; - parsed.has_fmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "capabilities") { - int64_t capabilities; - if (sscanf(args[i+1].c_str(), "%" SCNi64, &capabilities) == 1) { - parsed.capabilities = capabilities; - parsed.has_capabilities = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "selabel") { - if (!args[i+1].empty()) { - parsed.selabel = args[i+1].c_str(); - parsed.has_selabel = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (max_warnings != 0) { - printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str()); - max_warnings--; - if (max_warnings == 0) { - printf("ParsedPermArgs: suppressing further warnings\n"); - } - } + struct perm_parsed_args parsed; + int bad = 0; + static int max_warnings = 20; + + memset(&parsed, 0, sizeof(parsed)); + + for (int i = 1; i < argc; i += 2) { + if (args[i] == "uid") { + int64_t uid; + if (sscanf(args[i + 1].c_str(), "%" SCNd64, &uid) == 1) { + parsed.uid = uid; + parsed.has_uid = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (args[i] == "gid") { + int64_t gid; + if (sscanf(args[i + 1].c_str(), "%" SCNd64, &gid) == 1) { + parsed.gid = gid; + parsed.has_gid = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (args[i] == "mode") { + int32_t mode; + if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { + parsed.mode = mode; + parsed.has_mode = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; } - return parsed; + if (args[i] == "dmode") { + int32_t mode; + if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { + parsed.dmode = mode; + parsed.has_dmode = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (args[i] == "fmode") { + int32_t mode; + if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { + parsed.fmode = mode; + parsed.has_fmode = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (args[i] == "capabilities") { + int64_t capabilities; + if (sscanf(args[i + 1].c_str(), "%" SCNi64, &capabilities) == 1) { + parsed.capabilities = capabilities; + parsed.has_capabilities = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (args[i] == "selabel") { + if (!args[i + 1].empty()) { + parsed.selabel = args[i + 1].c_str(); + parsed.has_selabel = true; + } else { + uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str()); + bad++; + } + continue; + } + if (max_warnings != 0) { + printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str()); + max_warnings--; + if (max_warnings == 0) { + LOG(INFO) << "ParsedPermArgs: suppressing further warnings"; + } + } + } + return parsed; } -static int ApplyParsedPerms( - State * state, - const char* filename, - const struct stat *statptr, - struct perm_parsed_args parsed) -{ - int bad = 0; - - if (parsed.has_selabel) { - if (lsetfilecon(filename, parsed.selabel) != 0) { - uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", - filename, parsed.selabel, strerror(errno)); - bad++; - } - } +static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr, + struct perm_parsed_args parsed) { + int bad = 0; - /* ignore symlinks */ - if (S_ISLNK(statptr->st_mode)) { - return bad; + if (parsed.has_selabel) { + if (lsetfilecon(filename, parsed.selabel) != 0) { + uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", filename, + parsed.selabel, strerror(errno)); + bad++; } + } - if (parsed.has_uid) { - if (chown(filename, parsed.uid, -1) < 0) { - uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", - filename, parsed.uid, strerror(errno)); - bad++; - } + /* ignore symlinks */ + if (S_ISLNK(statptr->st_mode)) { + return bad; + } + + if (parsed.has_uid) { + if (chown(filename, parsed.uid, -1) < 0) { + uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", filename, parsed.uid, + strerror(errno)); + bad++; } + } - if (parsed.has_gid) { - if (chown(filename, -1, parsed.gid) < 0) { - uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", - filename, parsed.gid, strerror(errno)); - bad++; - } + if (parsed.has_gid) { + if (chown(filename, -1, parsed.gid) < 0) { + uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", filename, parsed.gid, + strerror(errno)); + bad++; } + } - if (parsed.has_mode) { - if (chmod(filename, parsed.mode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", - filename, parsed.mode, strerror(errno)); - bad++; - } + if (parsed.has_mode) { + if (chmod(filename, parsed.mode) < 0) { + uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.mode, + strerror(errno)); + bad++; } + } - if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { - if (chmod(filename, parsed.dmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", - filename, parsed.dmode, strerror(errno)); - bad++; - } + if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { + if (chmod(filename, parsed.dmode) < 0) { + uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.dmode, + strerror(errno)); + bad++; } + } - if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { - if (chmod(filename, parsed.fmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", - filename, parsed.fmode, strerror(errno)); - bad++; - } + if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { + if (chmod(filename, parsed.fmode) < 0) { + uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.fmode, + strerror(errno)); + bad++; } + } - if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) { - if (parsed.capabilities == 0) { - if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) { - // Report failure unless it's ENODATA (attribute not set) - uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", - filename, parsed.capabilities, strerror(errno)); - bad++; - } - } else { - struct vfs_cap_data cap_data; - memset(&cap_data, 0, sizeof(cap_data)); - cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; - cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff); - cap_data.data[0].inheritable = 0; - cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32); - cap_data.data[1].inheritable = 0; - if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) { - uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", - filename, parsed.capabilities, strerror(errno)); - bad++; - } - } + if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) { + if (parsed.capabilities == 0) { + if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) { + // Report failure unless it's ENODATA (attribute not set) + uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", filename, + parsed.capabilities, strerror(errno)); + bad++; + } + } else { + struct vfs_cap_data cap_data; + memset(&cap_data, 0, sizeof(cap_data)); + cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; + cap_data.data[0].permitted = (uint32_t)(parsed.capabilities & 0xffffffff); + cap_data.data[0].inheritable = 0; + cap_data.data[1].permitted = (uint32_t)(parsed.capabilities >> 32); + cap_data.data[1].inheritable = 0; + if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) { + uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", filename, + parsed.capabilities, strerror(errno)); + bad++; + } } + } - return bad; + return bad; } // nftw doesn't allow us to pass along context, so we need to use @@ -810,60 +797,60 @@ static int ApplyParsedPerms( static struct perm_parsed_args recursive_parsed_args; static State* recursive_state; -static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr, - int fileflags, struct FTW *pfwt) { - return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args); +static int do_SetMetadataRecursive(const char* filename, const struct stat* statptr, int fileflags, + struct FTW* pfwt) { + return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args); } static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { - if ((argc % 2) != 1) { - return ErrorAbort(state, kArgsParsingFailure, - "%s() expects an odd number of arguments, got %d", name, argc); - } + if ((argc % 2) != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %d", + name, argc); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } - struct stat sb; - if (lstat(args[0].c_str(), &sb) == -1) { - return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", - name, args[0].c_str(), strerror(errno)); - } + struct stat sb; + if (lstat(args[0].c_str(), &sb) == -1) { + return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", name, + args[0].c_str(), strerror(errno)); + } - struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); - int bad = 0; - bool recursive = (strcmp(name, "set_metadata_recursive") == 0); + struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); + int bad = 0; + bool recursive = (strcmp(name, "set_metadata_recursive") == 0); - if (recursive) { - recursive_parsed_args = parsed; - recursive_state = state; - bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); - memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); - recursive_state = NULL; - } else { - bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed); - } + if (recursive) { + recursive_parsed_args = parsed; + recursive_state = state; + bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); + memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); + recursive_state = NULL; + } else { + bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed); + } - if (bad > 0) { - return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); - } + if (bad > 0) { + return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); + } - return StringValue(""); + 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); - } - std::string key; - if (!Evaluate(state, argv[0], &key)) { - return nullptr; - } - std::string value = android::base::GetProperty(key, ""); + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } + std::string key; + if (!Evaluate(state, argv[0], &key)) { + return nullptr; + } + std::string value = android::base::GetProperty(key, ""); - return StringValue(value); + return StringValue(value); } // file_getprop(file, key) @@ -936,25 +923,34 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } // apply_patch_space(bytes) -Value* ApplyPatchSpaceFn(const char* name, State* state, - int argc, Expr* argv[]) { - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& bytes_str = args[0]; +Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& bytes_str = args[0]; - size_t bytes; - if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n", - name, bytes_str.c_str()); - } + size_t bytes; + if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n", + name, bytes_str.c_str()); + } - return StringValue(CacheSizeCheck(bytes) ? "" : "t"); + return StringValue(CacheSizeCheck(bytes) ? "" : "t"); } -// apply_patch(file, size, init_sha1, tgt_sha1, patch) - +// apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...]) +// Applies a binary patch to the src_file to produce the tgt_file. If the desired target is the +// same as the source, pass "-" for tgt_file. tgt_sha1 and tgt_size are the expected final SHA1 +// hash and size of the target file. The remaining arguments must come in pairs: a SHA1 hash (a +// 40-character hex string) and a blob. The blob is the patch to be applied when the source +// file's current contents have the given SHA1. +// +// The patching is done in a safe manner that guarantees the target file either has the desired +// SHA1 hash and size, or it is untouched -- it will not be left in an unrecoverable intermediate +// state. If the process is interrupted during patching, the target file may be in an intermediate +// state; a copy exists in the cache partition so restarting the update can successfully update +// the file. Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc < 6 || (argc % 2) == 1) { return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " @@ -1007,87 +1003,90 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result == 0 ? "t" : ""); } -// apply_patch_check(file, [sha1_1, ...]) -Value* ApplyPatchCheckFn(const char* name, State* state, - int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", - name, argc); - } +// apply_patch_check(filename, [sha1, ...]) +// Returns true if the contents of filename or the temporary copy in the cache partition (if +// present) have a SHA-1 checksum equal to one of the given sha1 values. sha1 values are +// specified as 40 hex digits. This function differs from sha1_check(read_file(filename), +// sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will +// succeed even if the file was corrupted by an interrupted apply_patch() update. +Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", name, + argc); + } - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; - std::vector sha1s; - if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - int result = applypatch_check(filename.c_str(), sha1s); + std::vector sha1s; + if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + int result = applypatch_check(filename.c_str(), sha1s); - return StringValue(result == 0 ? "t" : ""); + return StringValue(result == 0 ? "t" : ""); } // This is the updater side handler for ui_print() in edify script. Contents // will be sent over to the recovery side for on-screen display. Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } - std::string buffer = android::base::Join(args, "") + "\n"; - uiPrint(state, buffer); - return StringValue(buffer); + std::string buffer = android::base::Join(args, "") + "\n"; + uiPrint(state, buffer); + return StringValue(buffer); } Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); - } - fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); - return StringValue("t"); + if (argc != 0) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); + } + fprintf(static_cast(state->cookie)->cmd_pipe, "wipe_cache\n"); + return StringValue("t"); } Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); - } + if (argc < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); + } - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } - char* args2[argc+1]; - for (int i = 0; i < argc; i++) { - args2[i] = &args[i][0]; - } - args2[argc] = nullptr; + char* args2[argc + 1]; + for (int i = 0; i < argc; i++) { + args2[i] = &args[i][0]; + } + args2[argc] = nullptr; - printf("about to run program [%s] with %d args\n", args2[0], argc); + LOG(INFO) << "about to run program [" << args2[0] << "] with " << argc << " args"; - pid_t child = fork(); - if (child == 0) { - execv(args2[0], args2); - printf("run_program: execv failed: %s\n", strerror(errno)); - _exit(1); - } - int status; - waitpid(child, &status, 0); - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - printf("run_program: child exited with status %d\n", - WEXITSTATUS(status)); - } - } else if (WIFSIGNALED(status)) { - printf("run_program: child terminated by signal %d\n", - WTERMSIG(status)); + pid_t child = fork(); + if (child == 0) { + execv(args2[0], args2); + PLOG(ERROR) << "run_program: execv failed"; + _exit(1); + } + + int status; + waitpid(child, &status, 0); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + LOG(ERROR) << "run_program: child exited with status " << WEXITSTATUS(status); } + } else if (WIFSIGNALED(status)) { + LOG(ERROR) << "run_program: child terminated by signal " << WTERMSIG(status); + } - return StringValue(android::base::StringPrintf("%d", status)); + return StringValue(std::to_string(status)); } // sha1_check(data) @@ -1099,63 +1098,63 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { // strings passed, or "" if it does not equal any of them. // Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); - } + if (argc < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); + } - std::vector> args; - if (!ReadValueArgs(state, argc, argv, &args)) { - return nullptr; - } + std::vector> args; + if (!ReadValueArgs(state, argc, argv, &args)) { + return nullptr; + } - if (args[0]->type == VAL_INVALID) { - return StringValue(""); - } - uint8_t digest[SHA_DIGEST_LENGTH]; - SHA1(reinterpret_cast(args[0]->data.c_str()), args[0]->data.size(), digest); + if (args[0]->type == VAL_INVALID) { + return StringValue(""); + } + uint8_t digest[SHA_DIGEST_LENGTH]; + SHA1(reinterpret_cast(args[0]->data.c_str()), args[0]->data.size(), digest); - if (argc == 1) { - return StringValue(print_sha1(digest)); - } + if (argc == 1) { + return StringValue(print_sha1(digest)); + } - 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.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.c_str()); - } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { - // Found a match. - return args[i].release(); - } + for (int i = 1; i < argc; ++i) { + uint8_t arg_digest[SHA_DIGEST_LENGTH]; + if (args[i]->type != VAL_STRING) { + LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; + } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) { + // Warn about bad args and skip them. + LOG(ERROR) << name << "(): error parsing \"" << args[i]->data << "\" as sha-1; skipping"; + } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { + // Found a match. + return args[i].release(); } + } - // Didn't match any of the hex strings; return false. - return StringValue(""); + // Didn't match any of the hex strings; return false. + return StringValue(""); } // Read a local file and return its contents (the Value* returned // is actually a FileContents*). Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } - std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; + std::vector args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; - Value* v = new Value(VAL_INVALID, ""); + Value* v = new Value(VAL_INVALID, ""); - FileContents fc; - if (LoadFileContents(filename.c_str(), &fc) == 0) { - v->type = VAL_BLOB; - v->data = std::string(fc.data.begin(), fc.data.end()); - } - return v; + FileContents fc; + if (LoadFileContents(filename.c_str(), &fc) == 0) { + v->type = VAL_BLOB; + v->data = std::string(fc.data.begin(), fc.data.end()); + } + return v; } // write_value(value, filename) @@ -1178,7 +1177,7 @@ Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { const std::string& value = args[0]; if (!android::base::WriteStringToFile(value, filename)) { - printf("%s: Failed to write to \"%s\": %s\n", name, filename.c_str(), strerror(errno)); + PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\""; return StringValue(""); } else { return StringValue("t"); @@ -1210,12 +1209,12 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { bootloader_message boot; std::string err; if (!read_bootloader_message_from(&boot, filename, &err)) { - printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err; return StringValue(""); } memset(boot.command, 0, sizeof(boot.command)); if (!write_bootloader_message_to(boot, filename, &err)) { - printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err; return StringValue(""); } @@ -1255,12 +1254,12 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { bootloader_message boot; std::string err; if (!read_bootloader_message_from(&boot, filename, &err)) { - printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err; return StringValue(""); } strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage)); if (!write_bootloader_message_to(boot, filename, &err)) { - printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err; return StringValue(""); } @@ -1283,7 +1282,7 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { bootloader_message boot; std::string err; if (!read_bootloader_message_from(&boot, filename, &err)) { - printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err; return StringValue(""); } @@ -1314,93 +1313,94 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) } Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); - } - UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); - fprintf(ui->cmd_pipe, "enable_reboot\n"); - return StringValue("t"); + if (argc != 0) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); + } + UpdaterInfo* ui = static_cast(state->cookie); + fprintf(ui->cmd_pipe, "enable_reboot\n"); + return StringValue("t"); } Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); - } - - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); - } + if (argc == 0) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); + } - char* args2[argc+1]; - // Tune2fs expects the program name as its args[0] - args2[0] = const_cast(name); - if (args2[0] == nullptr) { - return nullptr; - } - for (int i = 0; i < argc; ++i) { - args2[i + 1] = &args[i][0]; - } + std::vector args; + if (!ReadArgs(state, argc, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); + } - // tune2fs changes the file system parameters on an ext2 file system; it - // returns 0 on success. - int result = tune2fs_main(argc + 1, args2); + char* args2[argc + 1]; + // Tune2fs expects the program name as its args[0] + args2[0] = const_cast(name); + if (args2[0] == nullptr) { + return nullptr; + } + for (int i = 0; i < argc; ++i) { + args2[i + 1] = &args[i][0]; + } - if (result != 0) { - return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); - } - return StringValue("t"); + // tune2fs changes the file system parameters on an ext2 file system; it + // returns 0 on success. + int result = tune2fs_main(argc + 1, args2); + if (result != 0) { + return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); + } + return StringValue("t"); } void RegisterInstallFunctions() { - RegisterFunction("mount", MountFn); - RegisterFunction("is_mounted", IsMountedFn); - RegisterFunction("unmount", UnmountFn); - RegisterFunction("format", FormatFn); - RegisterFunction("show_progress", ShowProgressFn); - RegisterFunction("set_progress", SetProgressFn); - RegisterFunction("delete", DeleteFn); - RegisterFunction("delete_recursive", DeleteFn); - RegisterFunction("package_extract_dir", PackageExtractDirFn); - RegisterFunction("package_extract_file", PackageExtractFileFn); - RegisterFunction("symlink", SymlinkFn); - - // Usage: - // set_metadata("filename", "key1", "value1", "key2", "value2", ...) - // Example: - // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); - RegisterFunction("set_metadata", SetMetadataFn); - - // Usage: - // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) - // Example: - // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); - RegisterFunction("set_metadata_recursive", SetMetadataFn); - - RegisterFunction("getprop", GetPropFn); - RegisterFunction("file_getprop", FileGetPropFn); - - RegisterFunction("apply_patch", ApplyPatchFn); - RegisterFunction("apply_patch_check", ApplyPatchCheckFn); - RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); - - RegisterFunction("wipe_block_device", WipeBlockDeviceFn); - - RegisterFunction("read_file", ReadFileFn); - RegisterFunction("sha1_check", Sha1CheckFn); - RegisterFunction("rename", RenameFn); - RegisterFunction("write_value", WriteValueFn); - - RegisterFunction("wipe_cache", WipeCacheFn); - - RegisterFunction("ui_print", UIPrintFn); - - RegisterFunction("run_program", RunProgramFn); - - RegisterFunction("reboot_now", RebootNowFn); - RegisterFunction("get_stage", GetStageFn); - RegisterFunction("set_stage", SetStageFn); - - RegisterFunction("enable_reboot", EnableRebootFn); - RegisterFunction("tune2fs", Tune2FsFn); + RegisterFunction("mount", MountFn); + RegisterFunction("is_mounted", IsMountedFn); + RegisterFunction("unmount", UnmountFn); + RegisterFunction("format", FormatFn); + RegisterFunction("show_progress", ShowProgressFn); + RegisterFunction("set_progress", SetProgressFn); + RegisterFunction("delete", DeleteFn); + RegisterFunction("delete_recursive", DeleteFn); + RegisterFunction("package_extract_dir", PackageExtractDirFn); + RegisterFunction("package_extract_file", PackageExtractFileFn); + RegisterFunction("symlink", SymlinkFn); + + // Usage: + // set_metadata("filename", "key1", "value1", "key2", "value2", ...) + // Example: + // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", + // "u:object_r:system_file:s0", "capabilities", 0x0); + RegisterFunction("set_metadata", SetMetadataFn); + + // Usage: + // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) + // Example: + // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, + // "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); + RegisterFunction("set_metadata_recursive", SetMetadataFn); + + RegisterFunction("getprop", GetPropFn); + RegisterFunction("file_getprop", FileGetPropFn); + + RegisterFunction("apply_patch", ApplyPatchFn); + RegisterFunction("apply_patch_check", ApplyPatchCheckFn); + RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); + + RegisterFunction("wipe_block_device", WipeBlockDeviceFn); + + RegisterFunction("read_file", ReadFileFn); + RegisterFunction("sha1_check", Sha1CheckFn); + RegisterFunction("rename", RenameFn); + RegisterFunction("write_value", WriteValueFn); + + RegisterFunction("wipe_cache", WipeCacheFn); + + RegisterFunction("ui_print", UIPrintFn); + + RegisterFunction("run_program", RunProgramFn); + + RegisterFunction("reboot_now", RebootNowFn); + RegisterFunction("get_stage", GetStageFn); + RegisterFunction("set_stage", SetStageFn); + + RegisterFunction("enable_reboot", EnableRebootFn); + RegisterFunction("tune2fs", Tune2FsFn); } -- cgit v1.2.3 From 0d3f84f237b2fab810de1438f7207b1763ad4011 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 28 Dec 2016 15:09:20 -0800 Subject: updater: Update the header name for bootloader.h. We should include "bootloader_message/bootloader_message.h" now. Test: m updater Change-Id: I65b22a8a0bcc5976ff1ba827bd30b46ee9d59c53 --- updater/install.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 3cf38774e..643145447 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include @@ -54,8 +56,6 @@ #include #include -#include "applypatch/applypatch.h" -#include "bootloader.h" #include "edify/expr.h" #include "error_code.h" #include "mounts.h" -- cgit v1.2.3 From f013642477dbe0a5ed8d440571e9c8676ed42b2d Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Sat, 21 Jan 2017 13:03:25 -0800 Subject: Print with newline for ui_print. Currently the ui_print command between the recovery and updater doesn't append newline. Updater has to send an extra "ui_print" command without any argument to get the line break. This looks unnecessary. And not all the callers (including the ones in bootable/recovery) are following this protocol when sending the ui_print command. This CL simplifies the protocol to always print with a newline for ui_print command. When updating from an old recovery with the new updater, all the ui_print'd strings would appear in one line as a side effect. But a) it would only affect the text-mode UI, which won't be shown to users; b) log files won't be affected. Bug: 32305035 Test: Apply an update with the new updater on top of an old and new recovery image respectively. Change-Id: I305a0ffc6f180daf60919cf99d24d1495d68749b --- updater/install.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 643145447..7a8e92f6c 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -76,7 +76,6 @@ static void uiPrint(State* state, const std::string& buffer) { for (auto& line : lines) { if (!line.empty()) { fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str()); - fprintf(ui->cmd_pipe, "ui_print\n"); } } -- cgit v1.2.3 From 3da880156b4a56a6af5065ac10dfd6833cdcb1d4 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 3 Feb 2017 13:09:23 -0800 Subject: Replace _exit(-1) with _exit(EXIT_FAILURE). -1 is not a valid exit status. Also replace a few exit(1) with exit(EXIT_FAILURE). Test: mmma bootable/recovery Change-Id: I4596c8328b770bf95acccc06a4401bd5cabd4bfd --- updater/install.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 7a8e92f6c..c7ecdb5c7 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -247,7 +247,7 @@ static int exec_cmd(const char* path, char* const argv[]) { pid_t child; if ((child = vfork()) == 0) { execv(path, argv); - _exit(-1); + _exit(EXIT_FAILURE); } int status; @@ -1072,7 +1072,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { if (child == 0) { execv(args2[0], args2); PLOG(ERROR) << "run_program: execv failed"; - _exit(1); + _exit(EXIT_FAILURE); } int status; -- cgit v1.2.3 From 63d786cf22cb44fe32e8b9c1f18b32da3c9d2e1b Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 8 Mar 2017 16:42:20 -0800 Subject: updater: Remove some obsoleted functions for file-based OTA. This CL removes the updater support for delete(), symlink(), rename(), set_metadata() and set_metadata_recursive(). Such functions have been removed from the generation script in commit f388104eaacd05cfa075d6478369e1d0df5ddbf3 (platform/build). Note: This CL also removes delete_recursive() which seems to have never been supported in generation script. Bug: 35853185 Test: recovery_component_test passes. Change-Id: I51e1ec946fa73761118fa1eaa082423df6d588e9 --- updater/install.cpp | 362 ---------------------------------------------------- 1 file changed, 362 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index c7ecdb5c7..0963333fc 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -332,68 +332,6 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -// rename(src_name, dst_name) -// Renames src_name to dst_name. It automatically creates the necessary directories for dst_name. -// Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk") -Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } - - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& src_name = args[0]; - const std::string& dst_name = args[1]; - - if (src_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name); - } - if (dst_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); - } - if (!make_parents(dst_name)) { - return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", - dst_name.c_str(), strerror(errno)); - } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { - // File was already moved - return StringValue(dst_name); - } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) { - return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", - src_name.c_str(), dst_name.c_str(), strerror(errno)); - } - - return StringValue(dst_name); -} - -// delete([filename, ...]) -// Deletes all the filenames listed. Returns the number of files successfully deleted. -// -// delete_recursive([dirname, ...]) -// Recursively deletes dirnames and all their contents. Returns the number of directories -// successfully deleted. -Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - std::vector paths(argc); - for (int i = 0; i < argc; ++i) { - if (!Evaluate(state, argv[i], &paths[i])) { - return nullptr; - } - } - - bool recursive = (strcmp(name, "delete_recursive") == 0); - - int success = 0; - for (int i = 0; i < argc; ++i) { - if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) { - ++success; - } - } - - return StringValue(std::to_string(success)); -} - - Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); @@ -557,288 +495,6 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv } } -// symlink(target, [src1, src2, ...]) -// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc -// before creating symlinks. -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); - } - std::string target; - if (!Evaluate(state, argv[0], &target)) { - return nullptr; - } - - std::vector srcs; - if (!ReadArgs(state, argc - 1, argv + 1, &srcs)) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); - } - - size_t bad = 0; - for (const auto& src : srcs) { - if (unlink(src.c_str()) == -1 && errno != ENOENT) { - PLOG(ERROR) << name << ": failed to remove " << src; - ++bad; - } else if (!make_parents(src)) { - LOG(ERROR) << name << ": failed to symlink " << src << " to " << target - << ": making parents failed"; - ++bad; - } else if (symlink(target.c_str(), src.c_str()) == -1) { - PLOG(ERROR) << name << ": failed to symlink " << src << " to " << target; - ++bad; - } - } - if (bad != 0) { - return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); - } - return StringValue("t"); -} - -struct perm_parsed_args { - bool has_uid; - uid_t uid; - bool has_gid; - gid_t gid; - bool has_mode; - mode_t mode; - bool has_fmode; - mode_t fmode; - bool has_dmode; - mode_t dmode; - bool has_selabel; - const char* selabel; - bool has_capabilities; - uint64_t capabilities; -}; - -static struct perm_parsed_args ParsePermArgs(State * state, int argc, - const std::vector& args) { - struct perm_parsed_args parsed; - int bad = 0; - static int max_warnings = 20; - - memset(&parsed, 0, sizeof(parsed)); - - for (int i = 1; i < argc; i += 2) { - if (args[i] == "uid") { - int64_t uid; - if (sscanf(args[i + 1].c_str(), "%" SCNd64, &uid) == 1) { - parsed.uid = uid; - parsed.has_uid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "gid") { - int64_t gid; - if (sscanf(args[i + 1].c_str(), "%" SCNd64, &gid) == 1) { - parsed.gid = gid; - parsed.has_gid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "mode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.mode = mode; - parsed.has_mode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "dmode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.dmode = mode; - parsed.has_dmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "fmode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.fmode = mode; - parsed.has_fmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "capabilities") { - int64_t capabilities; - if (sscanf(args[i + 1].c_str(), "%" SCNi64, &capabilities) == 1) { - parsed.capabilities = capabilities; - parsed.has_capabilities = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "selabel") { - if (!args[i + 1].empty()) { - parsed.selabel = args[i + 1].c_str(); - parsed.has_selabel = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (max_warnings != 0) { - printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str()); - max_warnings--; - if (max_warnings == 0) { - LOG(INFO) << "ParsedPermArgs: suppressing further warnings"; - } - } - } - return parsed; -} - -static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr, - struct perm_parsed_args parsed) { - int bad = 0; - - if (parsed.has_selabel) { - if (lsetfilecon(filename, parsed.selabel) != 0) { - uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", filename, - parsed.selabel, strerror(errno)); - bad++; - } - } - - /* ignore symlinks */ - if (S_ISLNK(statptr->st_mode)) { - return bad; - } - - if (parsed.has_uid) { - if (chown(filename, parsed.uid, -1) < 0) { - uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", filename, parsed.uid, - strerror(errno)); - bad++; - } - } - - if (parsed.has_gid) { - if (chown(filename, -1, parsed.gid) < 0) { - uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", filename, parsed.gid, - strerror(errno)); - bad++; - } - } - - if (parsed.has_mode) { - if (chmod(filename, parsed.mode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.mode, - strerror(errno)); - bad++; - } - } - - if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { - if (chmod(filename, parsed.dmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.dmode, - strerror(errno)); - bad++; - } - } - - if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { - if (chmod(filename, parsed.fmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.fmode, - strerror(errno)); - bad++; - } - } - - if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) { - if (parsed.capabilities == 0) { - if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) { - // Report failure unless it's ENODATA (attribute not set) - uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", filename, - parsed.capabilities, strerror(errno)); - bad++; - } - } else { - struct vfs_cap_data cap_data; - memset(&cap_data, 0, sizeof(cap_data)); - cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; - cap_data.data[0].permitted = (uint32_t)(parsed.capabilities & 0xffffffff); - cap_data.data[0].inheritable = 0; - cap_data.data[1].permitted = (uint32_t)(parsed.capabilities >> 32); - cap_data.data[1].inheritable = 0; - if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) { - uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", filename, - parsed.capabilities, strerror(errno)); - bad++; - } - } - } - - return bad; -} - -// nftw doesn't allow us to pass along context, so we need to use -// global variables. *sigh* -static struct perm_parsed_args recursive_parsed_args; -static State* recursive_state; - -static int do_SetMetadataRecursive(const char* filename, const struct stat* statptr, int fileflags, - struct FTW* pfwt) { - return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args); -} - -static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { - if ((argc % 2) != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %d", - name, argc); - } - - std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - - struct stat sb; - if (lstat(args[0].c_str(), &sb) == -1) { - return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", name, - args[0].c_str(), strerror(errno)); - } - - struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); - int bad = 0; - bool recursive = (strcmp(name, "set_metadata_recursive") == 0); - - if (recursive) { - recursive_parsed_args = parsed; - recursive_state = state; - bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); - memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); - recursive_state = NULL; - } else { - bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed); - } - - if (bad > 0) { - return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); - } - - 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); @@ -1356,25 +1012,8 @@ void RegisterInstallFunctions() { RegisterFunction("format", FormatFn); RegisterFunction("show_progress", ShowProgressFn); RegisterFunction("set_progress", SetProgressFn); - RegisterFunction("delete", DeleteFn); - RegisterFunction("delete_recursive", DeleteFn); RegisterFunction("package_extract_dir", PackageExtractDirFn); RegisterFunction("package_extract_file", PackageExtractFileFn); - RegisterFunction("symlink", SymlinkFn); - - // Usage: - // set_metadata("filename", "key1", "value1", "key2", "value2", ...) - // Example: - // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", - // "u:object_r:system_file:s0", "capabilities", 0x0); - RegisterFunction("set_metadata", SetMetadataFn); - - // Usage: - // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) - // Example: - // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, - // "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); - RegisterFunction("set_metadata_recursive", SetMetadataFn); RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); @@ -1387,7 +1026,6 @@ void RegisterInstallFunctions() { RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); - RegisterFunction("rename", RenameFn); RegisterFunction("write_value", WriteValueFn); RegisterFunction("wipe_cache", WipeCacheFn); -- cgit v1.2.3 From c444732540d5245b6219293e96d29f325daa7839 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 6 Mar 2017 14:44:59 -0800 Subject: Remove malloc in edify functions And switch them to std::vector & std::unique_ptr Bug: 32117870 Test: recovery tests passed on sailfish Change-Id: I5a45951c4bdf895be311d6d760e52e7a1b0798c3 --- updater/install.cpp | 242 ++++++++++++++++++++++++++++------------------------ 1 file changed, 131 insertions(+), 111 deletions(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index 0963333fc..c9a0270ec 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -126,15 +126,16 @@ static bool make_parents(const std::string& name) { // mount(fs_type, partition_type, location, mount_point) // mount(fs_type, partition_type, location, mount_point, mount_options) -// + // fs_type="ext4" partition_type="EMMC" location=device -Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 4 && argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); +Value* MountFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 4 && argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -143,7 +144,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { const std::string& mount_point = args[3]; std::string mount_options; - if (argc == 5) { + if (argv.size() == 5) { mount_options = args[4]; } @@ -188,15 +189,14 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } - // is_mounted(mount_point) -Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* IsMountedFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -214,12 +214,12 @@ Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } -Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* UnmountFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -265,13 +265,14 @@ static int exec_cmd(const char* path, char* const argv[]) { // 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[]) { - if (argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); +Value* FormatFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -332,13 +333,15 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* ShowProgressFn(const char* name, State* state, + const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -361,13 +364,13 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(frac_str); } -Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* SetProgressFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -390,13 +393,15 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { // Example: package_extract_dir("system", "/system") // // Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path. -Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* PackageExtractDirFn(const char* name, State* state, + const std::vector>&argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& zip_path = args[0]; @@ -416,17 +421,20 @@ Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[ // Extracts a single package_file from the update package and writes it to dest_file, // overwriting existing files if necessary. Without the dest_file argument, returns the // contents of the package file as a binary blob. -Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1 || argc > 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc); +Value* PackageExtractFileFn(const char* name, State* state, + const std::vector>& argv) { + if (argv.size() < 1 || argv.size() > 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, + argv.size()); } - if (argc == 2) { + if (argv.size() == 2) { // The two-argument version extracts to a file. std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; const std::string& dest_path = args[1]; @@ -468,8 +476,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv // The one-argument version returns the contents of the file as the result. std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; @@ -495,9 +504,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv } } -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); +Value* GetPropFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::string key; if (!Evaluate(state, argv[0], &key)) { @@ -513,13 +522,14 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // interprets 'file' as a getprop-style file (key=value pairs, one // per line. # comment lines, blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). -Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* FileGetPropFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -578,9 +588,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } // apply_patch_space(bytes) -Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, + argv.size()); + } std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& bytes_str = args[0]; @@ -606,14 +620,14 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) // state. If the process is interrupted during patching, the target file may be in an intermediate // state; a copy exists in the cache partition so restarting the update can successfully update // the file. -Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 6 || (argc % 2) == 1) { +Value* ApplyPatchFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() < 6 || (argv.size() % 2) == 1) { return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " - "even number, got %d", name, argc); + "even number, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, 4, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 4)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& source_filename = args[0]; @@ -627,9 +641,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { name, target_size_str.c_str()); } - int patchcount = (argc-4) / 2; + int patchcount = (argv.size()-4) / 2; std::vector> arg_values; - if (!ReadValueArgs(state, argc-4, argv+4, &arg_values)) { + if (!ReadValueArgs(state, argv, &arg_values, 4, argv.size() - 4)) { return nullptr; } @@ -664,20 +678,20 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { // specified as 40 hex digits. This function differs from sha1_check(read_file(filename), // sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will // succeed even if the file was corrupted by an interrupted apply_patch() update. -Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", name, - argc); +Value* ApplyPatchCheckFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; std::vector sha1s; - if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { + if (!ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } int result = applypatch_check(filename.c_str(), sha1s); @@ -687,9 +701,9 @@ Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) // This is the updater side handler for ui_print() in edify script. Contents // will be sent over to the recovery side for on-screen display. -Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* UIPrintFn(const char* name, State* state, const std::vector>& argv) { std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } @@ -698,31 +712,32 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(buffer); } -Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* WipeCacheFn(const char* name, State* state, const std::vector>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } fprintf(static_cast(state->cookie)->cmd_pipe, "wipe_cache\n"); return StringValue("t"); } -Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* RunProgramFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - char* args2[argc + 1]; - for (int i = 0; i < argc; i++) { + char* args2[argv.size() + 1]; + for (size_t i = 0; i < argv.size(); i++) { args2[i] = &args[i][0]; } - args2[argc] = nullptr; + args2[argv.size()] = nullptr; - LOG(INFO) << "about to run program [" << args2[0] << "] with " << argc << " args"; + LOG(INFO) << "about to run program [" << args2[0] << "] with " << argv.size() << " args"; pid_t child = fork(); if (child == 0) { @@ -752,13 +767,13 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { // returns the sha1 of the file if it matches any of the hex // strings passed, or "" if it does not equal any of them. // -Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* Sha1CheckFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector> args; - if (!ReadValueArgs(state, argc, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -768,11 +783,11 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { uint8_t digest[SHA_DIGEST_LENGTH]; SHA1(reinterpret_cast(args[0]->data.c_str()), args[0]->data.size(), digest); - if (argc == 1) { + if (argv.size() == 1) { return StringValue(print_sha1(digest)); } - for (int i = 1; i < argc; ++i) { + for (size_t i = 1; i < argv.size(); ++i) { uint8_t arg_digest[SHA_DIGEST_LENGTH]; if (args[i]->type != VAL_STRING) { LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; @@ -791,13 +806,13 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { // Read a local file and return its contents (the Value* returned // is actually a FileContents*). -Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* ReadFileFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -815,13 +830,14 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { // write_value(value, filename) // Writes 'value' to 'filename'. // Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") -Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WriteValueFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } @@ -848,13 +864,14 @@ Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { // property. It can be "recovery" to boot from the recovery // partition, or "" (empty string) to boot from the regular boot // partition. -Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* RebootNowFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -890,13 +907,14 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // ("/misc" in the fstab), which is where this value is stored. The // second argument is the string to store; it should not exceed 31 // bytes. -Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* SetStageFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -923,13 +941,13 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. -Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* GetStageFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -944,13 +962,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(boot.stage); } -Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -967,38 +986,39 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) return StringValue((status == 0) ? "t" : ""); } -Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* EnableRebootFn(const char* name, State* state, const std::vector>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } UpdaterInfo* ui = static_cast(state->cookie); fprintf(ui->cmd_pipe, "enable_reboot\n"); return StringValue("t"); } -Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); +Value* Tune2FsFn(const char* name, State* state, const std::vector>& argv) { + if (argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size()); } std::vector args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); } - char* args2[argc + 1]; + char* args2[argv.size() + 1]; // Tune2fs expects the program name as its args[0] args2[0] = const_cast(name); if (args2[0] == nullptr) { return nullptr; } - for (int i = 0; i < argc; ++i) { + for (size_t i = 0; i < argv.size(); ++i) { args2[i + 1] = &args[i][0]; } // tune2fs changes the file system parameters on an ext2 file system; it // returns 0 on success. - int result = tune2fs_main(argc + 1, args2); + int result = tune2fs_main(argv.size() + 1, args2); if (result != 0) { return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); } -- cgit v1.2.3 From db56eb073e595a862f620e244e23471665f63527 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 23 Mar 2017 06:34:20 -0700 Subject: updater: Fix the broken case for apply_patch_check(). It's valid to provide only 1 argument to apply_patch_check(). We shouldn't fail the argument parsing. Bug: 36541737 Test: recovery_component_test passes. Test: recovery_component_test captures the failure without the fix. Test: The previously failed update applies successfully. Change-Id: Iee4c54ed33b877fc4885945b085341ec5c64f663 --- updater/install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index c9a0270ec..f91f3fc9f 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -691,7 +691,7 @@ Value* ApplyPatchCheckFn(const char* name, State* state, const std::vector sha1s; - if (!ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { + if (argv.size() > 1 && !ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } int result = applypatch_check(filename.c_str(), sha1s); -- cgit v1.2.3 From ed9db0fd73f0368be354a65d7bdc3de5d01bdc88 Mon Sep 17 00:00:00 2001 From: Dmitri Plotnikov Date: Tue, 18 Apr 2017 08:28:26 -0700 Subject: Adding support for quiescent reboot to recovery Bug: 37401320 Test: build and push OTA and hit adb reboot recovery,quiescent. The screen should remain off throughout the upgrade process. (cherry picked from commit 8706a98aa635236a95795f0a0c122bb3e591a50d) Change-Id: I79789a151f6faafda8ecc6198c2182cc2a91da70 --- updater/install.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'updater/install.cpp') diff --git a/updater/install.cpp b/updater/install.cpp index f91f3fc9f..84cf5d6c0 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -890,7 +890,10 @@ Value* RebootNowFn(const char* name, State* state, const std::vector