summaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
Diffstat (limited to 'updater')
-rw-r--r--updater/blockimg.cpp169
-rw-r--r--updater/install.cpp122
-rw-r--r--updater/updater.cpp27
3 files changed, 222 insertions, 96 deletions
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 12a549dba..f00bc4bff 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -44,6 +44,7 @@
#include "applypatch/applypatch.h"
#include "edify/expr.h"
+#include "error_code.h"
#include "install.h"
#include "openssl/sha.h"
#include "minzip/Hash.h"
@@ -68,6 +69,8 @@ struct RangeSet {
std::vector<size_t> pos; // Actual limit is INT_MAX.
};
+static CauseCode failure_type = kNoCause;
+static bool is_retry = false;
static std::map<std::string, RangeSet> stash_map;
static void parse_range(const std::string& range_text, RangeSet& rs) {
@@ -145,6 +148,7 @@ static int read_all(int fd, uint8_t* data, size_t size) {
while (so_far < size) {
ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far));
if (r == -1) {
+ failure_type = kFreadFailure;
fprintf(stderr, "read failed: %s\n", strerror(errno));
return -1;
}
@@ -162,6 +166,7 @@ static int write_all(int fd, const uint8_t* data, size_t size) {
while (written < size) {
ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written));
if (w == -1) {
+ failure_type = kFwriteFailure;
fprintf(stderr, "write failed: %s\n", strerror(errno));
return -1;
}
@@ -175,9 +180,25 @@ static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) {
return write_all(fd, buffer.data(), size);
}
+static bool discard_blocks(int fd, off64_t offset, uint64_t size) {
+ // Don't discard blocks unless the update is a retry run.
+ if (!is_retry) {
+ return true;
+ }
+
+ uint64_t args[2] = {static_cast<uint64_t>(offset), size};
+ int status = ioctl(fd, BLKDISCARD, &args);
+ if (status == -1) {
+ fprintf(stderr, "BLKDISCARD ioctl failed: %s\n", strerror(errno));
+ return false;
+ }
+ return true;
+}
+
static bool check_lseek(int fd, off64_t offset, int whence) {
off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
if (rc == -1) {
+ failure_type = kLseekFailure;
fprintf(stderr, "lseek64 failed: %s\n", strerror(errno));
return false;
}
@@ -233,10 +254,15 @@ static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) {
rss->p_remain = (rss->tgt.pos[rss->p_block * 2 + 1] -
rss->tgt.pos[rss->p_block * 2]) * BLOCKSIZE;
- if (!check_lseek(rss->fd, (off64_t)rss->tgt.pos[rss->p_block*2] * BLOCKSIZE,
- SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(rss->tgt.pos[rss->p_block*2]) * BLOCKSIZE;
+ if (!discard_blocks(rss->fd, offset, rss->p_remain)) {
+ break;
+ }
+
+ if (!check_lseek(rss->fd, offset, SEEK_SET)) {
break;
}
+
} else {
// we can't write any more; return how many bytes have
// been written so far.
@@ -342,11 +368,15 @@ static int WriteBlocks(const RangeSet& tgt, const std::vector<uint8_t>& buffer,
size_t p = 0;
for (size_t i = 0; i < tgt.count; ++i) {
- if (!check_lseek(fd, (off64_t) tgt.pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[i * 2]) * BLOCKSIZE;
+ size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!discard_blocks(fd, offset, size)) {
return -1;
}
- size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!check_lseek(fd, offset, SEEK_SET)) {
+ return -1;
+ }
if (write_all(fd, data + p, size) == -1) {
return -1;
@@ -373,6 +403,7 @@ struct CommandParameters {
bool isunresumable;
int version;
size_t written;
+ size_t stashed;
NewThreadInfo nti;
pthread_t thread;
std::vector<uint8_t> buffer;
@@ -645,6 +676,7 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
}
if (ota_fsync(fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno));
return -1;
}
@@ -659,11 +691,13 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
android::base::unique_fd dfd(TEMP_FAILURE_RETRY(ota_open(dname.c_str(),
O_RDONLY | O_DIRECTORY)));
if (dfd == -1) {
+ failure_type = kFileOpenFailure;
fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
return -1;
}
if (ota_fsync(dfd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
return -1;
}
@@ -692,19 +726,21 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
int res = stat(dirname.c_str(), &sb);
if (res == -1 && errno != ENOENT) {
- ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname.c_str(), strerror(errno));
+ ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s\n",
+ dirname.c_str(), strerror(errno));
return -1;
} else if (res != 0) {
fprintf(stderr, "creating stash %s\n", dirname.c_str());
res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE);
if (res != 0) {
- ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno));
+ ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s\n",
+ dirname.c_str(), strerror(errno));
return -1;
}
if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) {
- ErrorAbort(state, "not enough space for stash\n");
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash\n");
return -1;
}
@@ -724,7 +760,8 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
size = maxblocks * BLOCKSIZE - size;
if (size > 0 && CacheSizeCheck(size) != 0) {
- ErrorAbort(state, "not enough space for stash (%d more needed)\n", size);
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%d more needed)\n",
+ size);
return -1;
}
@@ -774,6 +811,7 @@ static int SaveStash(CommandParameters& params, const std::string& base,
}
fprintf(stderr, "stashing %zu blocks to %s\n", blocks, id.c_str());
+ params.stashed += blocks;
return WriteStash(base, id, blocks, buffer, false, nullptr);
}
@@ -970,6 +1008,7 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t&
return -1;
}
+ params.stashed += src_blocks;
// Can be deleted when the write has completed
if (!stash_exists) {
params.freestash = srchash;
@@ -1087,7 +1126,13 @@ static int PerformCommandZero(CommandParameters& params) {
if (params.canwrite) {
for (size_t i = 0; i < tgt.count; ++i) {
- if (!check_lseek(params.fd, (off64_t) tgt.pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[i * 2]) * BLOCKSIZE;
+ size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, size)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
@@ -1126,7 +1171,12 @@ static int PerformCommandNew(CommandParameters& params) {
rss.p_block = 0;
rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
- if (!check_lseek(params.fd, (off64_t) tgt.pos[0] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, tgt.size * BLOCKSIZE)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
@@ -1204,16 +1254,27 @@ static int PerformCommandDiff(CommandParameters& params) {
rss.p_block = 0;
rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
- if (!check_lseek(params.fd, (off64_t) tgt.pos[0] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, rss.p_remain)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
if (params.cmdname[0] == 'i') { // imgdiff
- ApplyImagePatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
- &RangeSinkWrite, &rss, nullptr, nullptr);
+ if (ApplyImagePatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
+ &RangeSinkWrite, &rss, nullptr, nullptr) != 0) {
+ fprintf(stderr, "Failed to apply image patch.\n");
+ return -1;
+ }
} else {
- ApplyBSDiffPatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value, 0,
- &RangeSinkWrite, &rss, nullptr);
+ if (ApplyBSDiffPatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
+ 0, &RangeSinkWrite, &rss, nullptr) != 0) {
+ fprintf(stderr, "Failed to apply bsdiff patch.\n");
+ return -1;
+ }
}
// We expect the output of the patcher to fill the tgt ranges exactly.
@@ -1322,6 +1383,10 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
params.canwrite = !dryrun;
fprintf(stderr, "performing %s\n", dryrun ? "verification" : "update");
+ if (state->is_retry) {
+ is_retry = true;
+ fprintf(stderr, "This update is a retry.\n");
+ }
Value* blockdev_filename = nullptr;
Value* transfer_list_value = nullptr;
@@ -1339,19 +1404,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue);
if (blockdev_filename->type != VAL_STRING) {
- ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
if (transfer_list_value->type != VAL_BLOB) {
- ErrorAbort(state, "transfer_list argument to %s must be blob", name);
+ ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
return StringValue(strdup(""));
}
if (new_data_fn->type != VAL_STRING) {
- ErrorAbort(state, "new_data_fn argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
return StringValue(strdup(""));
}
if (patch_data_fn->type != VAL_STRING) {
- ErrorAbort(state, "patch_data_fn argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
@@ -1409,7 +1476,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
const std::string transfer_list(transfer_list_value->data, transfer_list_value->size);
std::vector<std::string> lines = android::base::Split(transfer_list, "\n");
if (lines.size() < 2) {
- ErrorAbort(state, "too few lines in the transfer list [%zd]\n", lines.size());
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n",
+ lines.size());
return StringValue(strdup(""));
}
@@ -1424,7 +1492,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
// Second line in transfer list is the total number of blocks we expect to write
int total_blocks;
if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
- ErrorAbort(state, "unexpected block count [%s]\n", lines[1].c_str());
+ ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
return StringValue(strdup(""));
}
@@ -1435,7 +1503,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
size_t start = 2;
if (params.version >= 2) {
if (lines.size() < 4) {
- ErrorAbort(state, "too few lines in the transfer list [%zu]\n", lines.size());
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
+ lines.size());
return StringValue(strdup(""));
}
@@ -1445,7 +1514,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
// Fourth line is the maximum number of blocks that will be stashed simultaneously
int stash_max_blocks;
if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
- ErrorAbort(state, "unexpected maximum stash blocks [%s]\n", lines[3].c_str());
+ ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
+ lines[3].c_str());
return StringValue(strdup(""));
}
@@ -1499,6 +1569,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
if (params.canwrite) {
if (ota_fsync(params.fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
goto pbiudone;
}
@@ -1511,8 +1582,17 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
pthread_join(params.thread, nullptr);
fprintf(stderr, "wrote %zu blocks; expected %d\n", params.written, total_blocks);
+ fprintf(stderr, "stashed %zu blocks\n", params.stashed);
fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size());
+ const char* partition = strrchr(blockdev_filename->data, '/');
+ if (partition != nullptr && *(partition+1) != 0) {
+ fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1,
+ params.written * BLOCKSIZE);
+ fprintf(cmd_pipe, "log bytes_stashed_%s: %zu\n", partition + 1,
+ params.stashed * BLOCKSIZE);
+ fflush(cmd_pipe);
+ }
// Delete stash only after successfully completing the update, as it
// may contain blocks needed to complete the update later.
DeleteStash(params.stashbase);
@@ -1524,6 +1604,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
pbiudone:
if (ota_fsync(params.fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
}
// params.fd will be automatically closed because it's a unique_fd.
@@ -1534,6 +1615,10 @@ pbiudone:
DeleteStash(params.stashbase);
}
+ if (failure_type != kNoCause && state->cause_code == kNoCause) {
+ state->cause_code = failure_type;
+ }
+
return StringValue(rc == 0 ? strdup("t") : strdup(""));
}
@@ -1639,17 +1724,19 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
FreeValue);
if (blockdev_filename->type != VAL_STRING) {
- ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
if (ranges->type != VAL_STRING) {
- ErrorAbort(state, "ranges argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup(""));
}
android::base::unique_fd fd(ota_open(blockdev_filename->data, O_RDWR));
if (fd == -1) {
- ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1662,14 +1749,15 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
std::vector<uint8_t> buffer(BLOCKSIZE);
for (size_t i = 0; i < rs.count; ++i) {
if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) {
- ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data, strerror(errno));
+ ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) {
if (read_all(fd, buffer, BLOCKSIZE) == -1) {
- ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data,
- strerror(errno));
+ ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1696,13 +1784,14 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue);
if (filename->type != VAL_STRING) {
- ErrorAbort(state, "filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup(""));
}
android::base::unique_fd fd(ota_open(arg_filename->data, O_RDONLY));
if (fd == -1) {
- ErrorAbort(state, "open \"%s\" failed: %s", arg_filename->data, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1710,7 +1799,8 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
std::vector<uint8_t> block0_buffer(BLOCKSIZE);
if (ReadBlocks(blk0, block0_buffer, fd) == -1) {
- ErrorAbort(state, "failed to read %s: %s", arg_filename->data, strerror(errno));
+ ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1745,11 +1835,11 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue);
if (filename->type != VAL_STRING) {
- ErrorAbort(state, "filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup(""));
}
if (ranges->type != VAL_STRING) {
- ErrorAbort(state, "ranges argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup(""));
}
@@ -1760,19 +1850,20 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
fec::io fh(filename->data, O_RDWR);
if (!fh) {
- ErrorAbort(state, "fec_open \"%s\" failed: %s", filename->data, strerror(errno));
+ ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
if (!fh.has_ecc() || !fh.has_verity()) {
- ErrorAbort(state, "unable to use metadata to correct errors");
+ ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
return StringValue(strdup(""));
}
fec_status status;
if (!fh.get_status(status)) {
- ErrorAbort(state, "failed to read FEC status");
+ ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
return StringValue(strdup(""));
}
@@ -1789,8 +1880,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
}
if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) {
- ErrorAbort(state, "failed to recover %s (block %zu): %s", filename->data,
- j, strerror(errno));
+ ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
+ filename->data, j, strerror(errno));
return StringValue(strdup(""));
}
diff --git a/updater/install.cpp b/updater/install.cpp
index 3e7e9285a..4c4886d51 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -48,9 +48,10 @@
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "edify/expr.h"
-#include "openssl/sha.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"
@@ -109,7 +110,7 @@ char* PrintSha1(const uint8_t* digest) {
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 4 && argc != 5) {
- return ErrorAbort(state, "%s() expects 4-5 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
}
char* fs_type;
char* partition_type;
@@ -132,20 +133,21 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (strlen(fs_type) == 0) {
- ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
goto done;
}
if (strlen(partition_type) == 0) {
- ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
name);
goto done;
}
if (strlen(location) == 0) {
- ErrorAbort(state, "location argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
goto done;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
+ name);
goto done;
}
@@ -189,14 +191,14 @@ done:
Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ 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;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to unmount() can't be empty");
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
goto done;
}
@@ -219,14 +221,14 @@ done:
Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ 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;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to unmount() can't be empty");
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
goto done;
}
@@ -276,7 +278,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 5) {
- return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
}
char* fs_type;
char* partition_type;
@@ -289,21 +291,22 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (strlen(fs_type) == 0) {
- ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
goto done;
}
if (strlen(partition_type) == 0) {
- ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
name);
goto done;
}
if (strlen(location) == 0) {
- ErrorAbort(state, "location argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
goto done;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
+ name);
goto done;
}
@@ -349,7 +352,7 @@ done:
Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* src_name;
@@ -359,21 +362,21 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
return NULL;
}
if (strlen(src_name) == 0) {
- ErrorAbort(state, "src_name argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
goto done;
}
if (strlen(dst_name) == 0) {
- ErrorAbort(state, "dst_name argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
goto done;
}
if (make_parents(dst_name) != 0) {
- ErrorAbort(state, "Creating parent of %s failed, error %s",
+ 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) {
// File was already moved
result = dst_name;
} else if (rename(src_name, dst_name) != 0) {
- ErrorAbort(state, "Rename of %s to %s failed, error %s",
+ ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
src_name, dst_name, strerror(errno));
} else {
result = dst_name;
@@ -416,7 +419,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* frac_str;
char* sec_str;
@@ -437,7 +440,7 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* frac_str;
if (ReadArgs(state, argv, 1, &frac_str) < 0) {
@@ -456,7 +459,7 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* PackageExtractDirFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* zip_path;
char* dest_path;
@@ -484,7 +487,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
Value* PackageExtractFileFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc < 1 || argc > 2) {
- return ErrorAbort(state, "%s() expects 1 or 2 args, got %d",
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d",
name, argc);
}
bool success = false;
@@ -592,7 +595,7 @@ static int make_parents(char* name) {
// 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, "%s() expects 1+ args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
}
char* target;
target = Evaluate(state, argv[0]);
@@ -628,7 +631,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
}
free(srcs);
if (bad) {
- return ErrorAbort(state, "%s: some symlinks failed", name);
+ return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
}
return StringValue(strdup(""));
}
@@ -852,14 +855,16 @@ static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv
bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
if ((argc % 2) != 1) {
- return ErrorAbort(state, "%s() expects an odd number of arguments, got %d", name, argc);
+ 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, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno));
+ result = ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s",
+ name, args[0], strerror(errno));
goto done;
}
@@ -888,7 +893,7 @@ done:
}
if (bad > 0) {
- return ErrorAbort(state, "%s: some changes failed", name);
+ return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
}
return StringValue(strdup(""));
@@ -896,7 +901,7 @@ done:
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* key = Evaluate(state, argv[0]);
if (key == NULL) return NULL;
@@ -925,20 +930,22 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
struct stat st;
if (stat(filename, &st) < 0) {
- ErrorAbort(state, "%s: failed to stat \"%s\": %s", name, filename, strerror(errno));
+ ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, filename,
+ strerror(errno));
goto done;
}
#define MAX_FILE_GETPROP_SIZE 65536
if (st.st_size > MAX_FILE_GETPROP_SIZE) {
- ErrorAbort(state, "%s too large for %s (max %d)", filename, name, 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<char*>(malloc(st.st_size+1));
if (buffer == NULL) {
- ErrorAbort(state, "%s: failed to alloc %zu bytes", name,
+ ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %zu bytes", name,
static_cast<size_t>(st.st_size+1));
goto done;
}
@@ -946,12 +953,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
FILE* f;
f = ota_fopen(filename, "rb");
if (f == NULL) {
- ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename,
+ strerror(errno));
goto done;
}
if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
- ErrorAbort(state, "%s: failed to read %zu bytes from %s",
+ ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s",
name, static_cast<size_t>(st.st_size), filename);
ota_fclose(f);
goto done;
@@ -1015,7 +1023,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
size_t bytes;
if (!android::base::ParseUint(bytes_str, &bytes)) {
- ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n", name, bytes_str);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n",
+ name, bytes_str);
free(bytes_str);
return nullptr;
}
@@ -1027,9 +1036,8 @@ 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, "%s(): expected at least 6 args and an "
- "even number, got %d",
- name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an "
+ "even number, got %d", name, argc);
}
char* source_filename;
@@ -1043,7 +1051,8 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
size_t target_size;
if (!android::base::ParseUint(target_size_str, &target_size)) {
- ErrorAbort(state, "%s(): can't parse \"%s\" as byte count", name, target_size_str);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count",
+ name, target_size_str);
free(source_filename);
free(target_filename);
free(target_sha1);
@@ -1067,11 +1076,11 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
for (int i = 0; i < patchcount; ++i) {
if (patch_shas[i]->type != VAL_STRING) {
- ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i);
return nullptr;
}
if (patches[i]->type != VAL_BLOB) {
- ErrorAbort(state, "%s(): patch #%d is not blob", name, i);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i);
return nullptr;
}
}
@@ -1094,7 +1103,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* ApplyPatchCheckFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s(): expected at least 1 arg, got %d",
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d",
name, argc);
}
@@ -1139,7 +1148,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 0) {
- return ErrorAbort(state, "%s() expects no args, got %d", name, argc);
+ 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"));
@@ -1147,7 +1156,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s() expects at least 1 arg", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
@@ -1201,7 +1210,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
//
Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s() expects at least 1 arg", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
}
std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
@@ -1249,7 +1258,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
// is actually a FileContents*).
Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* filename;
if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
@@ -1285,7 +1294,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
// partition.
Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1311,7 +1320,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
sleep(5);
free(property);
- ErrorAbort(state, "%s() failed to reboot", name);
+ ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
return NULL;
}
@@ -1327,7 +1336,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
// bytes.
Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1357,7 +1366,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
// 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, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* filename;
@@ -1375,7 +1384,7 @@ 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, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1397,7 +1406,7 @@ 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, "%s() expects no args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
}
UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
fprintf(ui->cmd_pipe, "enable_reboot\n");
@@ -1406,12 +1415,12 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc == 0) {
- return ErrorAbort(state, "%s() expects args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
- return ErrorAbort(state, "%s() could not read args", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
}
char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1)));
@@ -1429,7 +1438,8 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
free(args2[0]);
free(args2);
if (result != 0) {
- return ErrorAbort(state, "%s() returned error code %d", name, result);
+ return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
+ name, result);
}
return StringValue(strdup("t"));
}
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 0497d6a85..c222cee0d 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -51,7 +51,7 @@ int main(int argc, char** argv) {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
- if (argc != 4) {
+ if (argc != 4 && argc != 5) {
printf("unexpected number of arguments (%d)\n", argc);
return 1;
}
@@ -145,6 +145,14 @@ int main(int argc, char** argv) {
state.script = script;
state.errmsg = NULL;
+ if (argc == 5) {
+ if (strcmp(argv[4], "retry") == 0) {
+ state.is_retry = true;
+ } else {
+ printf("unexpected argument: %s", argv[4]);
+ }
+ }
+
char* result = Evaluate(&state, root);
if (have_eio_error) {
@@ -159,11 +167,28 @@ int main(int argc, char** argv) {
printf("script aborted: %s\n", state.errmsg);
char* line = strtok(state.errmsg, "\n");
while (line) {
+ // Parse the error code in abort message.
+ // Example: "E30: This package is for bullhead devices."
+ if (*line == 'E') {
+ if (sscanf(line, "E%u: ", &state.error_code) != 1) {
+ printf("Failed to parse error code: [%s]\n", line);
+ }
+ }
fprintf(cmd_pipe, "ui_print %s\n", line);
line = strtok(NULL, "\n");
}
fprintf(cmd_pipe, "ui_print\n");
}
+
+ if (state.error_code != kNoError) {
+ fprintf(cmd_pipe, "log error: %d\n", state.error_code);
+ // Cause code should provide additional information about the abort;
+ // report only when an error exists.
+ if (state.cause_code != kNoCause) {
+ fprintf(cmd_pipe, "log cause: %d\n", state.cause_code);
+ }
+ }
+
free(state.errmsg);
return 7;
} else {