aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTianjie Xu2016-04-30 13:49:59 -0500
committerTianjie Xu2016-05-20 15:56:53 -0500
commit162558382b768a4120b3e41090a4c7b53f11469a (patch)
tree7e0d268233fc6bea07a361cf6913fc3a5e524063
parentdd874b1c87eb04f28db0db2629df0adde568a74c (diff)
downloadplatform-bootable-recovery-162558382b768a4120b3e41090a4c7b53f11469a.tar.gz
platform-bootable-recovery-162558382b768a4120b3e41090a4c7b53f11469a.tar.xz
platform-bootable-recovery-162558382b768a4120b3e41090a4c7b53f11469a.zip
Allow recovery to return error codes
Write error code, cause code, and retry count into last_install. So we can have more information about the reason of a failed OTA. Example of new last_install: @/cache/recovery/block.map package name 0 install result retry: 1 retry count (new) error: 30 error code (new) cause: 12 error cause (new) Details in: go/android-ota-errorcode Bug: 28471955 Change-Id: I00e7153c821e7355c1be81a86c7f228108f3dc37
-rw-r--r--adb_install.cpp2
-rw-r--r--edify/Android.mk4
-rw-r--r--edify/expr.cpp39
-rw-r--r--edify/expr.h18
-rw-r--r--error_code.h46
-rw-r--r--install.cpp13
-rw-r--r--install.h4
-rw-r--r--recovery.cpp16
-rw-r--r--updater/blockimg.cpp81
-rw-r--r--updater/install.cpp129
-rw-r--r--updater/updater.cpp17
11 files changed, 265 insertions, 104 deletions
diff --git a/adb_install.cpp b/adb_install.cpp
index 4cfcb2ab..4aed9d4b 100644
--- a/adb_install.cpp
+++ b/adb_install.cpp
@@ -113,7 +113,7 @@ apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) {
113 break; 113 break;
114 } 114 }
115 } 115 }
116 result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false); 116 result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false, 0);
117 break; 117 break;
118 } 118 }
119 119
diff --git a/edify/Android.mk b/edify/Android.mk
index 038dec08..71cf7652 100644
--- a/edify/Android.mk
+++ b/edify/Android.mk
@@ -22,6 +22,8 @@ LOCAL_YACCFLAGS := -v
22LOCAL_CPPFLAGS += -Wno-unused-parameter 22LOCAL_CPPFLAGS += -Wno-unused-parameter
23LOCAL_CPPFLAGS += -Wno-deprecated-register 23LOCAL_CPPFLAGS += -Wno-deprecated-register
24LOCAL_CLANG := true 24LOCAL_CLANG := true
25LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
26LOCAL_STATIC_LIBRARIES += libbase
25 27
26include $(BUILD_HOST_EXECUTABLE) 28include $(BUILD_HOST_EXECUTABLE)
27 29
@@ -36,5 +38,7 @@ LOCAL_CPPFLAGS := -Wno-unused-parameter
36LOCAL_CPPFLAGS += -Wno-deprecated-register 38LOCAL_CPPFLAGS += -Wno-deprecated-register
37LOCAL_MODULE := libedify 39LOCAL_MODULE := libedify
38LOCAL_CLANG := true 40LOCAL_CLANG := true
41LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
42LOCAL_STATIC_LIBRARIES += libbase
39 43
40include $(BUILD_STATIC_LIBRARY) 44include $(BUILD_STATIC_LIBRARY)
diff --git a/edify/expr.cpp b/edify/expr.cpp
index cd1e0872..cc14fbe9 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -21,6 +21,11 @@
21#include <stdarg.h> 21#include <stdarg.h>
22#include <unistd.h> 22#include <unistd.h>
23 23
24#include <string>
25
26#include <android-base/stringprintf.h>
27#include <android-base/strings.h>
28
24#include "expr.h" 29#include "expr.h"
25 30
26// Functions should: 31// Functions should:
@@ -36,7 +41,7 @@ char* Evaluate(State* state, Expr* expr) {
36 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv); 41 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
37 if (v == NULL) return NULL; 42 if (v == NULL) return NULL;
38 if (v->type != VAL_STRING) { 43 if (v->type != VAL_STRING) {
39 ErrorAbort(state, "expecting string, got value type %d", v->type); 44 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
40 FreeValue(v); 45 FreeValue(v);
41 return NULL; 46 return NULL;
42 } 47 }
@@ -493,15 +498,29 @@ Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
493 return args; 498 return args;
494} 499}
495 500
501static void ErrorAbortV(State* state, const char* format, va_list ap) {
502 std::string buffer;
503 android::base::StringAppendV(&buffer, format, ap);
504 free(state->errmsg);
505 state->errmsg = strdup(buffer.c_str());
506 return;
507}
508
496// Use printf-style arguments to compose an error message to put into 509// Use printf-style arguments to compose an error message to put into
497// *state. Returns NULL. 510// *state. Returns nullptr.
498Value* ErrorAbort(State* state, const char* format, ...) { 511Value* ErrorAbort(State* state, const char* format, ...) {
499 char* buffer = reinterpret_cast<char*>(malloc(4096)); 512 va_list ap;
500 va_list v; 513 va_start(ap, format);
501 va_start(v, format); 514 ErrorAbortV(state, format, ap);
502 vsnprintf(buffer, 4096, format, v); 515 va_end(ap);
503 va_end(v); 516 return nullptr;
504 free(state->errmsg); 517}
505 state->errmsg = buffer; 518
506 return NULL; 519Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
520 va_list ap;
521 va_start(ap, format);
522 ErrorAbortV(state, format, ap);
523 va_end(ap);
524 state->cause_code = cause_code;
525 return nullptr;
507} 526}
diff --git a/edify/expr.h b/edify/expr.h
index 36f8e961..5c06de84 100644
--- a/edify/expr.h
+++ b/edify/expr.h
@@ -19,6 +19,7 @@
19 19
20#include <unistd.h> 20#include <unistd.h>
21 21
22#include "error_code.h"
22#include "yydefs.h" 23#include "yydefs.h"
23 24
24#define MAX_STRING_LEN 1024 25#define MAX_STRING_LEN 1024
@@ -39,6 +40,15 @@ typedef struct {
39 // Should be NULL initially, will be either NULL or a malloc'd 40 // Should be NULL initially, will be either NULL or a malloc'd
40 // pointer after Evaluate() returns. 41 // pointer after Evaluate() returns.
41 char* errmsg; 42 char* errmsg;
43
44 // error code indicates the type of failure (e.g. failure to update system image)
45 // during the OTA process.
46 ErrorCode error_code = kNoError;
47
48 // cause code provides more detailed reason of an OTA failure (e.g. fsync error)
49 // in addition to the error code.
50 CauseCode cause_code = kNoCause;
51
42} State; 52} State;
43 53
44#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null 54#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null
@@ -152,7 +162,13 @@ Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]);
152 162
153// Use printf-style arguments to compose an error message to put into 163// Use printf-style arguments to compose an error message to put into
154// *state. Returns NULL. 164// *state. Returns NULL.
155Value* ErrorAbort(State* state, const char* format, ...) __attribute__((format(printf, 2, 3))); 165Value* ErrorAbort(State* state, const char* format, ...)
166 __attribute__((format(printf, 2, 3), deprecated));
167
168// ErrorAbort has an optional (but recommended) argument 'cause_code'. If the cause code
169// is set, it will be logged into last_install and provides reason of OTA failures.
170Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...)
171 __attribute__((format(printf, 3, 4)));
156 172
157// Wrap a string into a Value, taking ownership of the string. 173// Wrap a string into a Value, taking ownership of the string.
158Value* StringValue(char* str); 174Value* StringValue(char* str);
diff --git a/error_code.h b/error_code.h
new file mode 100644
index 00000000..259319ab
--- /dev/null
+++ b/error_code.h
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _ERROR_CODE_H_
18#define _ERROR_CODE_H_
19
20enum ErrorCode {
21 kNoError = -1,
22 kLowBattery = 20,
23 kZipVerificationFailure,
24 kZipOpenFailure
25};
26
27enum CauseCode {
28 kNoCause = -1,
29 kArgsParsingFailure = 100,
30 kStashCreationFailure,
31 kFileOpenFailure,
32 kLseekFailure,
33 kFreadFailure,
34 kFwriteFailure,
35 kFsyncFailure,
36 kLibfecFailure,
37 kFileGetPropFailure,
38 kFileRenameFailure,
39 kSymlinkFailure,
40 kSetMetadataFailure,
41 kTune2FsFailure,
42 kRebootFailure,
43 kVendorFailure = 200
44};
45
46#endif
diff --git a/install.cpp b/install.cpp
index d725c7b8..57328528 100644
--- a/install.cpp
+++ b/install.cpp
@@ -27,7 +27,11 @@
27#include <string> 27#include <string>
28#include <vector> 28#include <vector>
29 29
30#include <android-base/stringprintf.h>
31#include <android-base/strings.h>
32
30#include "common.h" 33#include "common.h"
34#include "error_code.h"
31#include "install.h" 35#include "install.h"
32#include "minui/minui.h" 36#include "minui/minui.h"
33#include "minzip/SysUtil.h" 37#include "minzip/SysUtil.h"
@@ -253,6 +257,8 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
253 ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err); 257 ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
254 if (err != VERIFY_SUCCESS) { 258 if (err != VERIFY_SUCCESS) {
255 LOGE("signature verification failed\n"); 259 LOGE("signature verification failed\n");
260 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
261
256 sysReleaseMap(&map); 262 sysReleaseMap(&map);
257 return INSTALL_CORRUPT; 263 return INSTALL_CORRUPT;
258 } 264 }
@@ -262,6 +268,8 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
262 err = mzOpenZipArchive(map.addr, map.length, &zip); 268 err = mzOpenZipArchive(map.addr, map.length, &zip);
263 if (err != 0) { 269 if (err != 0) {
264 LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); 270 LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
271 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
272
265 sysReleaseMap(&map); 273 sysReleaseMap(&map);
266 return INSTALL_CORRUPT; 274 return INSTALL_CORRUPT;
267 } 275 }
@@ -280,7 +288,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
280 288
281int 289int
282install_package(const char* path, bool* wipe_cache, const char* install_file, 290install_package(const char* path, bool* wipe_cache, const char* install_file,
283 bool needs_mount) 291 bool needs_mount, int retry_count)
284{ 292{
285 modified_flash = true; 293 modified_flash = true;
286 auto start = std::chrono::system_clock::now(); 294 auto start = std::chrono::system_clock::now();
@@ -300,13 +308,14 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
300 } else { 308 } else {
301 result = really_install_package(path, wipe_cache, needs_mount, log_buffer); 309 result = really_install_package(path, wipe_cache, needs_mount, log_buffer);
302 } 310 }
303 if (install_log) { 311 if (install_log != nullptr) {
304 fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log); 312 fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
305 fputc('\n', install_log); 313 fputc('\n', install_log);
306 std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; 314 std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
307 int count = static_cast<int>(duration.count()); 315 int count = static_cast<int>(duration.count());
308 // Report the time spent to apply OTA update in seconds. 316 // Report the time spent to apply OTA update in seconds.
309 fprintf(install_log, "time_total: %d\n", count); 317 fprintf(install_log, "time_total: %d\n", count);
318 fprintf(install_log, "retry: %d\n", retry_count);
310 319
311 for (const auto& s : log_buffer) { 320 for (const auto& s : log_buffer) {
312 fprintf(install_log, "%s\n", s.c_str()); 321 fprintf(install_log, "%s\n", s.c_str());
diff --git a/install.h b/install.h
index fd08e3c4..66764f54 100644
--- a/install.h
+++ b/install.h
@@ -28,8 +28,8 @@ enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SK
28// Install the package specified by root_path. If INSTALL_SUCCESS is 28// Install the package specified by root_path. If INSTALL_SUCCESS is
29// returned and *wipe_cache is true on exit, caller should wipe the 29// returned and *wipe_cache is true on exit, caller should wipe the
30// cache partition. 30// cache partition.
31int install_package(const char* root_path, bool* wipe_cache, 31int install_package(const char* root_path, bool* wipe_cache, const char* install_file,
32 const char* install_file, bool needs_mount); 32 bool needs_mount, int retry_count);
33 33
34#ifdef __cplusplus 34#ifdef __cplusplus
35} 35}
diff --git a/recovery.cpp b/recovery.cpp
index 9873f976..6b6643fa 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -50,6 +50,7 @@
50#include "bootloader.h" 50#include "bootloader.h"
51#include "common.h" 51#include "common.h"
52#include "device.h" 52#include "device.h"
53#include "error_code.h"
53#include "fuse_sdcard_provider.h" 54#include "fuse_sdcard_provider.h"
54#include "fuse_sideload.h" 55#include "fuse_sideload.h"
55#include "install.h" 56#include "install.h"
@@ -1000,7 +1001,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
1000 } 1001 }
1001 1002
1002 result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, 1003 result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache,
1003 TEMPORARY_INSTALL_FILE, false); 1004 TEMPORARY_INSTALL_FILE, false, 0/*retry_count*/);
1004 break; 1005 break;
1005 } 1006 }
1006 1007
@@ -1455,10 +1456,21 @@ int main(int argc, char **argv) {
1455 if (!is_battery_ok()) { 1456 if (!is_battery_ok()) {
1456 ui->Print("battery capacity is not enough for installing package, needed is %d%%\n", 1457 ui->Print("battery capacity is not enough for installing package, needed is %d%%\n",
1457 BATTERY_OK_PERCENTAGE); 1458 BATTERY_OK_PERCENTAGE);
1459 // Log the error code to last_install when installation skips due to
1460 // low battery.
1461 FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w");
1462 if (install_log != nullptr) {
1463 fprintf(install_log, "%s\n", update_package);
1464 fprintf(install_log, "0\n");
1465 fprintf(install_log, "error: %d\n", kLowBattery);
1466 fclose(install_log);
1467 } else {
1468 LOGE("failed to open last_install: %s\n", strerror(errno));
1469 }
1458 status = INSTALL_SKIPPED; 1470 status = INSTALL_SKIPPED;
1459 } else { 1471 } else {
1460 status = install_package(update_package, &should_wipe_cache, 1472 status = install_package(update_package, &should_wipe_cache,
1461 TEMPORARY_INSTALL_FILE, true); 1473 TEMPORARY_INSTALL_FILE, true, retry_count);
1462 if (status == INSTALL_SUCCESS && should_wipe_cache) { 1474 if (status == INSTALL_SUCCESS && should_wipe_cache) {
1463 wipe_cache(false, device); 1475 wipe_cache(false, device);
1464 } 1476 }
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index d67af664..2efa1cd4 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -43,6 +43,7 @@
43 43
44#include "applypatch/applypatch.h" 44#include "applypatch/applypatch.h"
45#include "edify/expr.h" 45#include "edify/expr.h"
46#include "error_code.h"
46#include "install.h" 47#include "install.h"
47#include "openssl/sha.h" 48#include "openssl/sha.h"
48#include "minzip/Hash.h" 49#include "minzip/Hash.h"
@@ -68,6 +69,7 @@ struct RangeSet {
68 std::vector<size_t> pos; // Actual limit is INT_MAX. 69 std::vector<size_t> pos; // Actual limit is INT_MAX.
69}; 70};
70 71
72static CauseCode failure_type = kNoCause;
71static std::map<std::string, RangeSet> stash_map; 73static std::map<std::string, RangeSet> stash_map;
72 74
73static void parse_range(const std::string& range_text, RangeSet& rs) { 75static void parse_range(const std::string& range_text, RangeSet& rs) {
@@ -145,6 +147,7 @@ static int read_all(int fd, uint8_t* data, size_t size) {
145 while (so_far < size) { 147 while (so_far < size) {
146 ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far)); 148 ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far));
147 if (r == -1) { 149 if (r == -1) {
150 failure_type = kFreadFailure;
148 fprintf(stderr, "read failed: %s\n", strerror(errno)); 151 fprintf(stderr, "read failed: %s\n", strerror(errno));
149 return -1; 152 return -1;
150 } 153 }
@@ -162,6 +165,7 @@ static int write_all(int fd, const uint8_t* data, size_t size) {
162 while (written < size) { 165 while (written < size) {
163 ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written)); 166 ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written));
164 if (w == -1) { 167 if (w == -1) {
168 failure_type = kFwriteFailure;
165 fprintf(stderr, "write failed: %s\n", strerror(errno)); 169 fprintf(stderr, "write failed: %s\n", strerror(errno));
166 return -1; 170 return -1;
167 } 171 }
@@ -178,6 +182,7 @@ static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) {
178static bool check_lseek(int fd, off64_t offset, int whence) { 182static bool check_lseek(int fd, off64_t offset, int whence) {
179 off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)); 183 off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
180 if (rc == -1) { 184 if (rc == -1) {
185 failure_type = kLseekFailure;
181 fprintf(stderr, "lseek64 failed: %s\n", strerror(errno)); 186 fprintf(stderr, "lseek64 failed: %s\n", strerror(errno));
182 return false; 187 return false;
183 } 188 }
@@ -648,6 +653,7 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
648 } 653 }
649 654
650 if (ota_fsync(fd) == -1) { 655 if (ota_fsync(fd) == -1) {
656 failure_type = kFsyncFailure;
651 fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); 657 fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno));
652 return -1; 658 return -1;
653 } 659 }
@@ -663,11 +669,13 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
663 unique_fd dfd_holder(dfd); 669 unique_fd dfd_holder(dfd);
664 670
665 if (dfd == -1) { 671 if (dfd == -1) {
672 failure_type = kFileOpenFailure;
666 fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno)); 673 fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
667 return -1; 674 return -1;
668 } 675 }
669 676
670 if (ota_fsync(dfd) == -1) { 677 if (ota_fsync(dfd) == -1) {
678 failure_type = kFsyncFailure;
671 fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno)); 679 fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
672 return -1; 680 return -1;
673 } 681 }
@@ -696,19 +704,21 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
696 int res = stat(dirname.c_str(), &sb); 704 int res = stat(dirname.c_str(), &sb);
697 705
698 if (res == -1 && errno != ENOENT) { 706 if (res == -1 && errno != ENOENT) {
699 ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); 707 ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s\n",
708 dirname.c_str(), strerror(errno));
700 return -1; 709 return -1;
701 } else if (res != 0) { 710 } else if (res != 0) {
702 fprintf(stderr, "creating stash %s\n", dirname.c_str()); 711 fprintf(stderr, "creating stash %s\n", dirname.c_str());
703 res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE); 712 res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE);
704 713
705 if (res != 0) { 714 if (res != 0) {
706 ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); 715 ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s\n",
716 dirname.c_str(), strerror(errno));
707 return -1; 717 return -1;
708 } 718 }
709 719
710 if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) { 720 if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) {
711 ErrorAbort(state, "not enough space for stash\n"); 721 ErrorAbort(state, kStashCreationFailure, "not enough space for stash\n");
712 return -1; 722 return -1;
713 } 723 }
714 724
@@ -728,7 +738,8 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
728 size = maxblocks * BLOCKSIZE - size; 738 size = maxblocks * BLOCKSIZE - size;
729 739
730 if (size > 0 && CacheSizeCheck(size) != 0) { 740 if (size > 0 && CacheSizeCheck(size) != 0) {
731 ErrorAbort(state, "not enough space for stash (%d more needed)\n", size); 741 ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%d more needed)\n",
742 size);
732 return -1; 743 return -1;
733 } 744 }
734 745
@@ -1346,19 +1357,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1346 std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue); 1357 std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue);
1347 1358
1348 if (blockdev_filename->type != VAL_STRING) { 1359 if (blockdev_filename->type != VAL_STRING) {
1349 ErrorAbort(state, "blockdev_filename argument to %s must be string", name); 1360 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
1361 name);
1350 return StringValue(strdup("")); 1362 return StringValue(strdup(""));
1351 } 1363 }
1352 if (transfer_list_value->type != VAL_BLOB) { 1364 if (transfer_list_value->type != VAL_BLOB) {
1353 ErrorAbort(state, "transfer_list argument to %s must be blob", name); 1365 ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
1354 return StringValue(strdup("")); 1366 return StringValue(strdup(""));
1355 } 1367 }
1356 if (new_data_fn->type != VAL_STRING) { 1368 if (new_data_fn->type != VAL_STRING) {
1357 ErrorAbort(state, "new_data_fn argument to %s must be string", name); 1369 ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
1358 return StringValue(strdup("")); 1370 return StringValue(strdup(""));
1359 } 1371 }
1360 if (patch_data_fn->type != VAL_STRING) { 1372 if (patch_data_fn->type != VAL_STRING) {
1361 ErrorAbort(state, "patch_data_fn argument to %s must be string", name); 1373 ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string",
1374 name);
1362 return StringValue(strdup("")); 1375 return StringValue(strdup(""));
1363 } 1376 }
1364 1377
@@ -1418,7 +1431,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1418 const std::string transfer_list(transfer_list_value->data, transfer_list_value->size); 1431 const std::string transfer_list(transfer_list_value->data, transfer_list_value->size);
1419 std::vector<std::string> lines = android::base::Split(transfer_list, "\n"); 1432 std::vector<std::string> lines = android::base::Split(transfer_list, "\n");
1420 if (lines.size() < 2) { 1433 if (lines.size() < 2) {
1421 ErrorAbort(state, "too few lines in the transfer list [%zd]\n", lines.size()); 1434 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n",
1435 lines.size());
1422 return StringValue(strdup("")); 1436 return StringValue(strdup(""));
1423 } 1437 }
1424 1438
@@ -1433,7 +1447,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1433 // Second line in transfer list is the total number of blocks we expect to write 1447 // Second line in transfer list is the total number of blocks we expect to write
1434 int total_blocks; 1448 int total_blocks;
1435 if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) { 1449 if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
1436 ErrorAbort(state, "unexpected block count [%s]\n", lines[1].c_str()); 1450 ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
1437 return StringValue(strdup("")); 1451 return StringValue(strdup(""));
1438 } 1452 }
1439 1453
@@ -1444,7 +1458,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1444 size_t start = 2; 1458 size_t start = 2;
1445 if (params.version >= 2) { 1459 if (params.version >= 2) {
1446 if (lines.size() < 4) { 1460 if (lines.size() < 4) {
1447 ErrorAbort(state, "too few lines in the transfer list [%zu]\n", lines.size()); 1461 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
1462 lines.size());
1448 return StringValue(strdup("")); 1463 return StringValue(strdup(""));
1449 } 1464 }
1450 1465
@@ -1454,7 +1469,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1454 // Fourth line is the maximum number of blocks that will be stashed simultaneously 1469 // Fourth line is the maximum number of blocks that will be stashed simultaneously
1455 int stash_max_blocks; 1470 int stash_max_blocks;
1456 if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) { 1471 if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
1457 ErrorAbort(state, "unexpected maximum stash blocks [%s]\n", lines[3].c_str()); 1472 ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
1473 lines[3].c_str());
1458 return StringValue(strdup("")); 1474 return StringValue(strdup(""));
1459 } 1475 }
1460 1476
@@ -1508,6 +1524,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1508 1524
1509 if (params.canwrite) { 1525 if (params.canwrite) {
1510 if (ota_fsync(params.fd) == -1) { 1526 if (ota_fsync(params.fd) == -1) {
1527 failure_type = kFsyncFailure;
1511 fprintf(stderr, "fsync failed: %s\n", strerror(errno)); 1528 fprintf(stderr, "fsync failed: %s\n", strerror(errno));
1512 goto pbiudone; 1529 goto pbiudone;
1513 } 1530 }
@@ -1542,6 +1559,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1542 1559
1543pbiudone: 1560pbiudone:
1544 if (ota_fsync(params.fd) == -1) { 1561 if (ota_fsync(params.fd) == -1) {
1562 failure_type = kFsyncFailure;
1545 fprintf(stderr, "fsync failed: %s\n", strerror(errno)); 1563 fprintf(stderr, "fsync failed: %s\n", strerror(errno));
1546 } 1564 }
1547 // params.fd will be automatically closed because of the fd_holder above. 1565 // params.fd will be automatically closed because of the fd_holder above.
@@ -1552,6 +1570,10 @@ pbiudone:
1552 DeleteStash(params.stashbase); 1570 DeleteStash(params.stashbase);
1553 } 1571 }
1554 1572
1573 if (failure_type != kNoCause && state->cause_code == kNoCause) {
1574 state->cause_code = failure_type;
1575 }
1576
1555 return StringValue(rc == 0 ? strdup("t") : strdup("")); 1577 return StringValue(rc == 0 ? strdup("t") : strdup(""));
1556} 1578}
1557 1579
@@ -1657,18 +1679,20 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
1657 FreeValue); 1679 FreeValue);
1658 1680
1659 if (blockdev_filename->type != VAL_STRING) { 1681 if (blockdev_filename->type != VAL_STRING) {
1660 ErrorAbort(state, "blockdev_filename argument to %s must be string", name); 1682 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
1683 name);
1661 return StringValue(strdup("")); 1684 return StringValue(strdup(""));
1662 } 1685 }
1663 if (ranges->type != VAL_STRING) { 1686 if (ranges->type != VAL_STRING) {
1664 ErrorAbort(state, "ranges argument to %s must be string", name); 1687 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
1665 return StringValue(strdup("")); 1688 return StringValue(strdup(""));
1666 } 1689 }
1667 1690
1668 int fd = open(blockdev_filename->data, O_RDWR); 1691 int fd = open(blockdev_filename->data, O_RDWR);
1669 unique_fd fd_holder(fd); 1692 unique_fd fd_holder(fd);
1670 if (fd < 0) { 1693 if (fd < 0) {
1671 ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno)); 1694 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data,
1695 strerror(errno));
1672 return StringValue(strdup("")); 1696 return StringValue(strdup(""));
1673 } 1697 }
1674 1698
@@ -1681,13 +1705,14 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
1681 std::vector<uint8_t> buffer(BLOCKSIZE); 1705 std::vector<uint8_t> buffer(BLOCKSIZE);
1682 for (size_t i = 0; i < rs.count; ++i) { 1706 for (size_t i = 0; i < rs.count; ++i) {
1683 if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) { 1707 if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) {
1684 ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data, strerror(errno)); 1708 ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data,
1709 strerror(errno));
1685 return StringValue(strdup("")); 1710 return StringValue(strdup(""));
1686 } 1711 }
1687 1712
1688 for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) { 1713 for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) {
1689 if (read_all(fd, buffer, BLOCKSIZE) == -1) { 1714 if (read_all(fd, buffer, BLOCKSIZE) == -1) {
1690 ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data, 1715 ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data,
1691 strerror(errno)); 1716 strerror(errno));
1692 return StringValue(strdup("")); 1717 return StringValue(strdup(""));
1693 } 1718 }
@@ -1715,14 +1740,15 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
1715 std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); 1740 std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue);
1716 1741
1717 if (filename->type != VAL_STRING) { 1742 if (filename->type != VAL_STRING) {
1718 ErrorAbort(state, "filename argument to %s must be string", name); 1743 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
1719 return StringValue(strdup("")); 1744 return StringValue(strdup(""));
1720 } 1745 }
1721 1746
1722 int fd = open(arg_filename->data, O_RDONLY); 1747 int fd = open(arg_filename->data, O_RDONLY);
1723 unique_fd fd_holder(fd); 1748 unique_fd fd_holder(fd);
1724 if (fd == -1) { 1749 if (fd == -1) {
1725 ErrorAbort(state, "open \"%s\" failed: %s", arg_filename->data, strerror(errno)); 1750 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data,
1751 strerror(errno));
1726 return StringValue(strdup("")); 1752 return StringValue(strdup(""));
1727 } 1753 }
1728 1754
@@ -1730,7 +1756,7 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
1730 std::vector<uint8_t> block0_buffer(BLOCKSIZE); 1756 std::vector<uint8_t> block0_buffer(BLOCKSIZE);
1731 1757
1732 if (ReadBlocks(blk0, block0_buffer, fd) == -1) { 1758 if (ReadBlocks(blk0, block0_buffer, fd) == -1) {
1733 ErrorAbort(state, "failed to read %s: %s", arg_filename->data, 1759 ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data,
1734 strerror(errno)); 1760 strerror(errno));
1735 return StringValue(strdup("")); 1761 return StringValue(strdup(""));
1736 } 1762 }
@@ -1766,11 +1792,11 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1766 std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue); 1792 std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue);
1767 1793
1768 if (filename->type != VAL_STRING) { 1794 if (filename->type != VAL_STRING) {
1769 ErrorAbort(state, "filename argument to %s must be string", name); 1795 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
1770 return StringValue(strdup("")); 1796 return StringValue(strdup(""));
1771 } 1797 }
1772 if (ranges->type != VAL_STRING) { 1798 if (ranges->type != VAL_STRING) {
1773 ErrorAbort(state, "ranges argument to %s must be string", name); 1799 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
1774 return StringValue(strdup("")); 1800 return StringValue(strdup(""));
1775 } 1801 }
1776 1802
@@ -1781,19 +1807,20 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1781 fec::io fh(filename->data, O_RDWR); 1807 fec::io fh(filename->data, O_RDWR);
1782 1808
1783 if (!fh) { 1809 if (!fh) {
1784 ErrorAbort(state, "fec_open \"%s\" failed: %s", filename->data, strerror(errno)); 1810 ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data,
1811 strerror(errno));
1785 return StringValue(strdup("")); 1812 return StringValue(strdup(""));
1786 } 1813 }
1787 1814
1788 if (!fh.has_ecc() || !fh.has_verity()) { 1815 if (!fh.has_ecc() || !fh.has_verity()) {
1789 ErrorAbort(state, "unable to use metadata to correct errors"); 1816 ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
1790 return StringValue(strdup("")); 1817 return StringValue(strdup(""));
1791 } 1818 }
1792 1819
1793 fec_status status; 1820 fec_status status;
1794 1821
1795 if (!fh.get_status(status)) { 1822 if (!fh.get_status(status)) {
1796 ErrorAbort(state, "failed to read FEC status"); 1823 ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
1797 return StringValue(strdup("")); 1824 return StringValue(strdup(""));
1798 } 1825 }
1799 1826
@@ -1810,8 +1837,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1810 } 1837 }
1811 1838
1812 if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) { 1839 if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) {
1813 ErrorAbort(state, "failed to recover %s (block %zu): %s", filename->data, 1840 ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
1814 j, strerror(errno)); 1841 filename->data, j, strerror(errno));
1815 return StringValue(strdup("")); 1842 return StringValue(strdup(""));
1816 } 1843 }
1817 1844
diff --git a/updater/install.cpp b/updater/install.cpp
index 6ae1e5fb..1a647dfa 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -47,10 +47,11 @@
47#include "cutils/misc.h" 47#include "cutils/misc.h"
48#include "cutils/properties.h" 48#include "cutils/properties.h"
49#include "edify/expr.h" 49#include "edify/expr.h"
50#include "openssl/sha.h" 50#include "error_code.h"
51#include "minzip/DirUtil.h" 51#include "minzip/DirUtil.h"
52#include "mtdutils/mounts.h" 52#include "mtdutils/mounts.h"
53#include "mtdutils/mtdutils.h" 53#include "mtdutils/mtdutils.h"
54#include "openssl/sha.h"
54#include "ota_io.h" 55#include "ota_io.h"
55#include "updater.h" 56#include "updater.h"
56#include "install.h" 57#include "install.h"
@@ -113,7 +114,7 @@ char* PrintSha1(const uint8_t* digest) {
113Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { 114Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
114 char* result = NULL; 115 char* result = NULL;
115 if (argc != 4 && argc != 5) { 116 if (argc != 4 && argc != 5) {
116 return ErrorAbort(state, "%s() expects 4-5 args, got %d", name, argc); 117 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
117 } 118 }
118 char* fs_type; 119 char* fs_type;
119 char* partition_type; 120 char* partition_type;
@@ -136,20 +137,21 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
136 } 137 }
137 138
138 if (strlen(fs_type) == 0) { 139 if (strlen(fs_type) == 0) {
139 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 140 ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
140 goto done; 141 goto done;
141 } 142 }
142 if (strlen(partition_type) == 0) { 143 if (strlen(partition_type) == 0) {
143 ErrorAbort(state, "partition_type argument to %s() can't be empty", 144 ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
144 name); 145 name);
145 goto done; 146 goto done;
146 } 147 }
147 if (strlen(location) == 0) { 148 if (strlen(location) == 0) {
148 ErrorAbort(state, "location argument to %s() can't be empty", name); 149 ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
149 goto done; 150 goto done;
150 } 151 }
151 if (strlen(mount_point) == 0) { 152 if (strlen(mount_point) == 0) {
152 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 153 ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
154 name);
153 goto done; 155 goto done;
154 } 156 }
155 157
@@ -212,14 +214,14 @@ done:
212Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { 214Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
213 char* result = NULL; 215 char* result = NULL;
214 if (argc != 1) { 216 if (argc != 1) {
215 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 217 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
216 } 218 }
217 char* mount_point; 219 char* mount_point;
218 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 220 if (ReadArgs(state, argv, 1, &mount_point) < 0) {
219 return NULL; 221 return NULL;
220 } 222 }
221 if (strlen(mount_point) == 0) { 223 if (strlen(mount_point) == 0) {
222 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 224 ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
223 goto done; 225 goto done;
224 } 226 }
225 227
@@ -242,14 +244,14 @@ done:
242Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { 244Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
243 char* result = NULL; 245 char* result = NULL;
244 if (argc != 1) { 246 if (argc != 1) {
245 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 247 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
246 } 248 }
247 char* mount_point; 249 char* mount_point;
248 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 250 if (ReadArgs(state, argv, 1, &mount_point) < 0) {
249 return NULL; 251 return NULL;
250 } 252 }
251 if (strlen(mount_point) == 0) { 253 if (strlen(mount_point) == 0) {
252 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 254 ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
253 goto done; 255 goto done;
254 } 256 }
255 257
@@ -300,7 +302,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
300Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { 302Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
301 char* result = NULL; 303 char* result = NULL;
302 if (argc != 5) { 304 if (argc != 5) {
303 return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc); 305 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
304 } 306 }
305 char* fs_type; 307 char* fs_type;
306 char* partition_type; 308 char* partition_type;
@@ -313,21 +315,22 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
313 } 315 }
314 316
315 if (strlen(fs_type) == 0) { 317 if (strlen(fs_type) == 0) {
316 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 318 ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
317 goto done; 319 goto done;
318 } 320 }
319 if (strlen(partition_type) == 0) { 321 if (strlen(partition_type) == 0) {
320 ErrorAbort(state, "partition_type argument to %s() can't be empty", 322 ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
321 name); 323 name);
322 goto done; 324 goto done;
323 } 325 }
324 if (strlen(location) == 0) { 326 if (strlen(location) == 0) {
325 ErrorAbort(state, "location argument to %s() can't be empty", name); 327 ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
326 goto done; 328 goto done;
327 } 329 }
328 330
329 if (strlen(mount_point) == 0) { 331 if (strlen(mount_point) == 0) {
330 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 332 ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
333 name);
331 goto done; 334 goto done;
332 } 335 }
333 336
@@ -402,7 +405,7 @@ done:
402Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { 405Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
403 char* result = NULL; 406 char* result = NULL;
404 if (argc != 2) { 407 if (argc != 2) {
405 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 408 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
406 } 409 }
407 410
408 char* src_name; 411 char* src_name;
@@ -412,21 +415,21 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
412 return NULL; 415 return NULL;
413 } 416 }
414 if (strlen(src_name) == 0) { 417 if (strlen(src_name) == 0) {
415 ErrorAbort(state, "src_name argument to %s() can't be empty", name); 418 ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
416 goto done; 419 goto done;
417 } 420 }
418 if (strlen(dst_name) == 0) { 421 if (strlen(dst_name) == 0) {
419 ErrorAbort(state, "dst_name argument to %s() can't be empty", name); 422 ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
420 goto done; 423 goto done;
421 } 424 }
422 if (make_parents(dst_name) != 0) { 425 if (make_parents(dst_name) != 0) {
423 ErrorAbort(state, "Creating parent of %s failed, error %s", 426 ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s",
424 dst_name, strerror(errno)); 427 dst_name, strerror(errno));
425 } else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) { 428 } else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) {
426 // File was already moved 429 // File was already moved
427 result = dst_name; 430 result = dst_name;
428 } else if (rename(src_name, dst_name) != 0) { 431 } else if (rename(src_name, dst_name) != 0) {
429 ErrorAbort(state, "Rename of %s to %s failed, error %s", 432 ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
430 src_name, dst_name, strerror(errno)); 433 src_name, dst_name, strerror(errno));
431 } else { 434 } else {
432 result = dst_name; 435 result = dst_name;
@@ -469,7 +472,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
469 472
470Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 473Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
471 if (argc != 2) { 474 if (argc != 2) {
472 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 475 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
473 } 476 }
474 char* frac_str; 477 char* frac_str;
475 char* sec_str; 478 char* sec_str;
@@ -490,7 +493,7 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
490 493
491Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 494Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
492 if (argc != 1) { 495 if (argc != 1) {
493 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 496 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
494 } 497 }
495 char* frac_str; 498 char* frac_str;
496 if (ReadArgs(state, argv, 1, &frac_str) < 0) { 499 if (ReadArgs(state, argv, 1, &frac_str) < 0) {
@@ -509,7 +512,7 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
509Value* PackageExtractDirFn(const char* name, State* state, 512Value* PackageExtractDirFn(const char* name, State* state,
510 int argc, Expr* argv[]) { 513 int argc, Expr* argv[]) {
511 if (argc != 2) { 514 if (argc != 2) {
512 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 515 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
513 } 516 }
514 char* zip_path; 517 char* zip_path;
515 char* dest_path; 518 char* dest_path;
@@ -537,7 +540,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
537Value* PackageExtractFileFn(const char* name, State* state, 540Value* PackageExtractFileFn(const char* name, State* state,
538 int argc, Expr* argv[]) { 541 int argc, Expr* argv[]) {
539 if (argc < 1 || argc > 2) { 542 if (argc < 1 || argc > 2) {
540 return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", 543 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d",
541 name, argc); 544 name, argc);
542 } 545 }
543 bool success = false; 546 bool success = false;
@@ -645,7 +648,7 @@ static int make_parents(char* name) {
645// unlinks any previously existing src1, src2, etc before creating symlinks. 648// unlinks any previously existing src1, src2, etc before creating symlinks.
646Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { 649Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
647 if (argc == 0) { 650 if (argc == 0) {
648 return ErrorAbort(state, "%s() expects 1+ args, got %d", name, argc); 651 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
649 } 652 }
650 char* target; 653 char* target;
651 target = Evaluate(state, argv[0]); 654 target = Evaluate(state, argv[0]);
@@ -681,7 +684,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
681 } 684 }
682 free(srcs); 685 free(srcs);
683 if (bad) { 686 if (bad) {
684 return ErrorAbort(state, "%s: some symlinks failed", name); 687 return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
685 } 688 }
686 return StringValue(strdup("")); 689 return StringValue(strdup(""));
687} 690}
@@ -905,14 +908,16 @@ static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv
905 bool recursive = (strcmp(name, "set_metadata_recursive") == 0); 908 bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
906 909
907 if ((argc % 2) != 1) { 910 if ((argc % 2) != 1) {
908 return ErrorAbort(state, "%s() expects an odd number of arguments, got %d", name, argc); 911 return ErrorAbort(state, kArgsParsingFailure,
912 "%s() expects an odd number of arguments, got %d", name, argc);
909 } 913 }
910 914
911 char** args = ReadVarArgs(state, argc, argv); 915 char** args = ReadVarArgs(state, argc, argv);
912 if (args == NULL) return NULL; 916 if (args == NULL) return NULL;
913 917
914 if (lstat(args[0], &sb) == -1) { 918 if (lstat(args[0], &sb) == -1) {
915 result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno)); 919 result = ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s",
920 name, args[0], strerror(errno));
916 goto done; 921 goto done;
917 } 922 }
918 923
@@ -941,7 +946,7 @@ done:
941 } 946 }
942 947
943 if (bad > 0) { 948 if (bad > 0) {
944 return ErrorAbort(state, "%s: some changes failed", name); 949 return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
945 } 950 }
946 951
947 return StringValue(strdup("")); 952 return StringValue(strdup(""));
@@ -949,7 +954,7 @@ done:
949 954
950Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 955Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
951 if (argc != 1) { 956 if (argc != 1) {
952 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 957 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
953 } 958 }
954 char* key = Evaluate(state, argv[0]); 959 char* key = Evaluate(state, argv[0]);
955 if (key == NULL) return NULL; 960 if (key == NULL) return NULL;
@@ -978,32 +983,36 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
978 983
979 struct stat st; 984 struct stat st;
980 if (stat(filename, &st) < 0) { 985 if (stat(filename, &st) < 0) {
981 ErrorAbort(state, "%s: failed to stat \"%s\": %s", name, filename, strerror(errno)); 986 ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, filename,
987 strerror(errno));
982 goto done; 988 goto done;
983 } 989 }
984 990
985#define MAX_FILE_GETPROP_SIZE 65536 991#define MAX_FILE_GETPROP_SIZE 65536
986 992
987 if (st.st_size > MAX_FILE_GETPROP_SIZE) { 993 if (st.st_size > MAX_FILE_GETPROP_SIZE) {
988 ErrorAbort(state, "%s too large for %s (max %d)", filename, name, MAX_FILE_GETPROP_SIZE); 994 ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", filename, name,
995 MAX_FILE_GETPROP_SIZE);
989 goto done; 996 goto done;
990 } 997 }
991 998
992 buffer = reinterpret_cast<char*>(malloc(st.st_size+1)); 999 buffer = reinterpret_cast<char*>(malloc(st.st_size+1));
993 if (buffer == NULL) { 1000 if (buffer == NULL) {
994 ErrorAbort(state, "%s: failed to alloc %lld bytes", name, (long long)st.st_size+1); 1001 ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %lld bytes", name,
1002 (long long)st.st_size+1);
995 goto done; 1003 goto done;
996 } 1004 }
997 1005
998 FILE* f; 1006 FILE* f;
999 f = fopen(filename, "rb"); 1007 f = fopen(filename, "rb");
1000 if (f == NULL) { 1008 if (f == NULL) {
1001 ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno)); 1009 ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename,
1010 strerror(errno));
1002 goto done; 1011 goto done;
1003 } 1012 }
1004 1013
1005 if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) { 1014 if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
1006 ErrorAbort(state, "%s: failed to read %lld bytes from %s", 1015 ErrorAbort(state, kFreadFailure, "%s: failed to read %lld bytes from %s",
1007 name, (long long)st.st_size+1, filename); 1016 name, (long long)st.st_size+1, filename);
1008 fclose(f); 1017 fclose(f);
1009 goto done; 1018 goto done;
@@ -1069,16 +1078,16 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
1069 1078
1070 char* partition = NULL; 1079 char* partition = NULL;
1071 if (partition_value->type != VAL_STRING) { 1080 if (partition_value->type != VAL_STRING) {
1072 ErrorAbort(state, "partition argument to %s must be string", name); 1081 ErrorAbort(state, kArgsParsingFailure, "partition argument to %s must be string", name);
1073 goto done; 1082 goto done;
1074 } 1083 }
1075 partition = partition_value->data; 1084 partition = partition_value->data;
1076 if (strlen(partition) == 0) { 1085 if (strlen(partition) == 0) {
1077 ErrorAbort(state, "partition argument to %s can't be empty", name); 1086 ErrorAbort(state, kArgsParsingFailure, "partition argument to %s can't be empty", name);
1078 goto done; 1087 goto done;
1079 } 1088 }
1080 if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) { 1089 if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
1081 ErrorAbort(state, "file argument to %s can't be empty", name); 1090 ErrorAbort(state, kArgsParsingFailure, "file argument to %s can't be empty", name);
1082 goto done; 1091 goto done;
1083 } 1092 }
1084 1093
@@ -1159,7 +1168,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
1159 1168
1160 size_t bytes; 1169 size_t bytes;
1161 if (!android::base::ParseUint(bytes_str, &bytes)) { 1170 if (!android::base::ParseUint(bytes_str, &bytes)) {
1162 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n", name, bytes_str); 1171 ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n",
1172 name, bytes_str);
1163 free(bytes_str); 1173 free(bytes_str);
1164 return nullptr; 1174 return nullptr;
1165 } 1175 }
@@ -1171,9 +1181,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
1171 1181
1172Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { 1182Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1173 if (argc < 6 || (argc % 2) == 1) { 1183 if (argc < 6 || (argc % 2) == 1) {
1174 return ErrorAbort(state, "%s(): expected at least 6 args and an " 1184 return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an "
1175 "even number, got %d", 1185 "even number, got %d", name, argc);
1176 name, argc);
1177 } 1186 }
1178 1187
1179 char* source_filename; 1188 char* source_filename;
@@ -1187,7 +1196,8 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1187 1196
1188 size_t target_size; 1197 size_t target_size;
1189 if (!android::base::ParseUint(target_size_str, &target_size)) { 1198 if (!android::base::ParseUint(target_size_str, &target_size)) {
1190 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count", name, target_size_str); 1199 ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count",
1200 name, target_size_str);
1191 free(source_filename); 1201 free(source_filename);
1192 free(target_filename); 1202 free(target_filename);
1193 free(target_sha1); 1203 free(target_sha1);
@@ -1211,11 +1221,11 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1211 1221
1212 for (int i = 0; i < patchcount; ++i) { 1222 for (int i = 0; i < patchcount; ++i) {
1213 if (patch_shas[i]->type != VAL_STRING) { 1223 if (patch_shas[i]->type != VAL_STRING) {
1214 ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i); 1224 ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i);
1215 return nullptr; 1225 return nullptr;
1216 } 1226 }
1217 if (patches[i]->type != VAL_BLOB) { 1227 if (patches[i]->type != VAL_BLOB) {
1218 ErrorAbort(state, "%s(): patch #%d is not blob", name, i); 1228 ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i);
1219 return nullptr; 1229 return nullptr;
1220 } 1230 }
1221 } 1231 }
@@ -1238,7 +1248,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1238Value* ApplyPatchCheckFn(const char* name, State* state, 1248Value* ApplyPatchCheckFn(const char* name, State* state,
1239 int argc, Expr* argv[]) { 1249 int argc, Expr* argv[]) {
1240 if (argc < 1) { 1250 if (argc < 1) {
1241 return ErrorAbort(state, "%s(): expected at least 1 arg, got %d", 1251 return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d",
1242 name, argc); 1252 name, argc);
1243 } 1253 }
1244 1254
@@ -1283,7 +1293,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
1283 1293
1284Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { 1294Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
1285 if (argc != 0) { 1295 if (argc != 0) {
1286 return ErrorAbort(state, "%s() expects no args, got %d", name, argc); 1296 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
1287 } 1297 }
1288 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); 1298 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
1289 return StringValue(strdup("t")); 1299 return StringValue(strdup("t"));
@@ -1291,7 +1301,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
1291 1301
1292Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { 1302Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
1293 if (argc < 1) { 1303 if (argc < 1) {
1294 return ErrorAbort(state, "%s() expects at least 1 arg", name); 1304 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1295 } 1305 }
1296 char** args = ReadVarArgs(state, argc, argv); 1306 char** args = ReadVarArgs(state, argc, argv);
1297 if (args == NULL) { 1307 if (args == NULL) {
@@ -1345,7 +1355,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
1345// 1355//
1346Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { 1356Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
1347 if (argc < 1) { 1357 if (argc < 1) {
1348 return ErrorAbort(state, "%s() expects at least 1 arg", name); 1358 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1349 } 1359 }
1350 1360
1351 std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free); 1361 std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
@@ -1393,7 +1403,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
1393// is actually a FileContents*). 1403// is actually a FileContents*).
1394Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { 1404Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
1395 if (argc != 1) { 1405 if (argc != 1) {
1396 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 1406 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
1397 } 1407 }
1398 char* filename; 1408 char* filename;
1399 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; 1409 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
@@ -1429,7 +1439,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
1429// partition. 1439// partition.
1430Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { 1440Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
1431 if (argc != 2) { 1441 if (argc != 2) {
1432 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1442 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1433 } 1443 }
1434 1444
1435 char* filename; 1445 char* filename;
@@ -1455,7 +1465,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
1455 1465
1456 sleep(5); 1466 sleep(5);
1457 free(property); 1467 free(property);
1458 ErrorAbort(state, "%s() failed to reboot", name); 1468 ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
1459 return NULL; 1469 return NULL;
1460} 1470}
1461 1471
@@ -1471,7 +1481,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
1471// bytes. 1481// bytes.
1472Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { 1482Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1473 if (argc != 2) { 1483 if (argc != 2) {
1474 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1484 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1475 } 1485 }
1476 1486
1477 char* filename; 1487 char* filename;
@@ -1501,7 +1511,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1501// is the block device for the misc partition. 1511// is the block device for the misc partition.
1502Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { 1512Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1503 if (argc != 1) { 1513 if (argc != 1) {
1504 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 1514 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
1505 } 1515 }
1506 1516
1507 char* filename; 1517 char* filename;
@@ -1519,7 +1529,7 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1519 1529
1520Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { 1530Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
1521 if (argc != 2) { 1531 if (argc != 2) {
1522 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1532 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1523 } 1533 }
1524 1534
1525 char* filename; 1535 char* filename;
@@ -1541,7 +1551,7 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[])
1541 1551
1542Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { 1552Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
1543 if (argc != 0) { 1553 if (argc != 0) {
1544 return ErrorAbort(state, "%s() expects no args, got %d", name, argc); 1554 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
1545 } 1555 }
1546 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 1556 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
1547 fprintf(ui->cmd_pipe, "enable_reboot\n"); 1557 fprintf(ui->cmd_pipe, "enable_reboot\n");
@@ -1550,12 +1560,12 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
1550 1560
1551Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { 1561Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
1552 if (argc == 0) { 1562 if (argc == 0) {
1553 return ErrorAbort(state, "%s() expects args, got %d", name, argc); 1563 return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc);
1554 } 1564 }
1555 1565
1556 char** args = ReadVarArgs(state, argc, argv); 1566 char** args = ReadVarArgs(state, argc, argv);
1557 if (args == NULL) { 1567 if (args == NULL) {
1558 return ErrorAbort(state, "%s() could not read args", name); 1568 return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
1559 } 1569 }
1560 1570
1561 char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1))); 1571 char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1)));
@@ -1573,7 +1583,8 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
1573 free(args2[0]); 1583 free(args2[0]);
1574 free(args2); 1584 free(args2);
1575 if (result != 0) { 1585 if (result != 0) {
1576 return ErrorAbort(state, "%s() returned error code %d", name, result); 1586 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
1587 name, result);
1577 } 1588 }
1578 return StringValue(strdup("t")); 1589 return StringValue(strdup("t"));
1579} 1590}
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 1693fa1d..b5db71e2 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -156,11 +156,28 @@ int main(int argc, char** argv) {
156 printf("script aborted: %s\n", state.errmsg); 156 printf("script aborted: %s\n", state.errmsg);
157 char* line = strtok(state.errmsg, "\n"); 157 char* line = strtok(state.errmsg, "\n");
158 while (line) { 158 while (line) {
159 // Parse the error code in abort message.
160 // Example: "E30: This package is for bullhead devices."
161 if (*line == 'E') {
162 if (sscanf(line, "E%u: ", &state.error_code) != 1) {
163 printf("Failed to parse error code: [%s]\n", line);
164 }
165 }
159 fprintf(cmd_pipe, "ui_print %s\n", line); 166 fprintf(cmd_pipe, "ui_print %s\n", line);
160 line = strtok(NULL, "\n"); 167 line = strtok(NULL, "\n");
161 } 168 }
162 fprintf(cmd_pipe, "ui_print\n"); 169 fprintf(cmd_pipe, "ui_print\n");
163 } 170 }
171
172 if (state.error_code != kNoError) {
173 fprintf(cmd_pipe, "log error: %d\n", state.error_code);
174 // Cause code should provide additional information about the abort;
175 // report only when an error exists.
176 if (state.cause_code != kNoCause) {
177 fprintf(cmd_pipe, "log cause: %d\n", state.cause_code);
178 }
179 }
180
164 free(state.errmsg); 181 free(state.errmsg);
165 return 7; 182 return 7;
166 } else { 183 } else {