diff options
author | Tianjie Xu | 2016-04-30 13:49:59 -0500 |
---|---|---|
committer | Tianjie Xu | 2016-05-20 15:56:53 -0500 |
commit | 162558382b768a4120b3e41090a4c7b53f11469a (patch) | |
tree | 7e0d268233fc6bea07a361cf6913fc3a5e524063 | |
parent | dd874b1c87eb04f28db0db2629df0adde568a74c (diff) | |
download | platform-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.cpp | 2 | ||||
-rw-r--r-- | edify/Android.mk | 4 | ||||
-rw-r--r-- | edify/expr.cpp | 39 | ||||
-rw-r--r-- | edify/expr.h | 18 | ||||
-rw-r--r-- | error_code.h | 46 | ||||
-rw-r--r-- | install.cpp | 13 | ||||
-rw-r--r-- | install.h | 4 | ||||
-rw-r--r-- | recovery.cpp | 16 | ||||
-rw-r--r-- | updater/blockimg.cpp | 81 | ||||
-rw-r--r-- | updater/install.cpp | 129 | ||||
-rw-r--r-- | updater/updater.cpp | 17 |
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 | |||
22 | LOCAL_CPPFLAGS += -Wno-unused-parameter | 22 | LOCAL_CPPFLAGS += -Wno-unused-parameter |
23 | LOCAL_CPPFLAGS += -Wno-deprecated-register | 23 | LOCAL_CPPFLAGS += -Wno-deprecated-register |
24 | LOCAL_CLANG := true | 24 | LOCAL_CLANG := true |
25 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. | ||
26 | LOCAL_STATIC_LIBRARIES += libbase | ||
25 | 27 | ||
26 | include $(BUILD_HOST_EXECUTABLE) | 28 | include $(BUILD_HOST_EXECUTABLE) |
27 | 29 | ||
@@ -36,5 +38,7 @@ LOCAL_CPPFLAGS := -Wno-unused-parameter | |||
36 | LOCAL_CPPFLAGS += -Wno-deprecated-register | 38 | LOCAL_CPPFLAGS += -Wno-deprecated-register |
37 | LOCAL_MODULE := libedify | 39 | LOCAL_MODULE := libedify |
38 | LOCAL_CLANG := true | 40 | LOCAL_CLANG := true |
41 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. | ||
42 | LOCAL_STATIC_LIBRARIES += libbase | ||
39 | 43 | ||
40 | include $(BUILD_STATIC_LIBRARY) | 44 | include $(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 | ||
501 | static 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. |
498 | Value* ErrorAbort(State* state, const char* format, ...) { | 511 | Value* 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; | 519 | Value* 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. |
155 | Value* ErrorAbort(State* state, const char* format, ...) __attribute__((format(printf, 2, 3))); | 165 | Value* 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. | ||
170 | Value* 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. |
158 | Value* StringValue(char* str); | 174 | Value* 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 | |||
20 | enum ErrorCode { | ||
21 | kNoError = -1, | ||
22 | kLowBattery = 20, | ||
23 | kZipVerificationFailure, | ||
24 | kZipOpenFailure | ||
25 | }; | ||
26 | |||
27 | enum 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 | ||
281 | int | 289 | int |
282 | install_package(const char* path, bool* wipe_cache, const char* install_file, | 290 | install_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()); |
@@ -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. |
31 | int install_package(const char* root_path, bool* wipe_cache, | 31 | int 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 | ||
72 | static CauseCode failure_type = kNoCause; | ||
71 | static std::map<std::string, RangeSet> stash_map; | 73 | static std::map<std::string, RangeSet> stash_map; |
72 | 74 | ||
73 | static void parse_range(const std::string& range_text, RangeSet& rs) { | 75 | static 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) { | |||
178 | static bool check_lseek(int fd, off64_t offset, int whence) { | 182 | static 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 | ||
1543 | pbiudone: | 1560 | pbiudone: |
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) { | |||
113 | Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { | 114 | Value* 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: | |||
212 | Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { | 214 | Value* 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: | |||
242 | Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { | 244 | Value* 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[]) { | |||
300 | Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { | 302 | Value* 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: | |||
402 | Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { | 405 | Value* 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 | ||
470 | Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { | 473 | Value* 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 | ||
491 | Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { | 494 | Value* 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[]) { | |||
509 | Value* PackageExtractDirFn(const char* name, State* state, | 512 | Value* 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, | |||
537 | Value* PackageExtractFileFn(const char* name, State* state, | 540 | Value* 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. |
646 | Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { | 649 | Value* 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 | ||
950 | Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { | 955 | Value* 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 | ||
1172 | Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { | 1182 | Value* 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[]) { | |||
1238 | Value* ApplyPatchCheckFn(const char* name, State* state, | 1248 | Value* 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 | ||
1284 | Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { | 1294 | Value* 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 | ||
1292 | Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { | 1302 | Value* 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 | // |
1346 | Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { | 1356 | Value* 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*). |
1394 | Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { | 1404 | Value* 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. |
1430 | Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { | 1440 | Value* 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. |
1472 | Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { | 1482 | Value* 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. |
1502 | Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { | 1512 | Value* 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 | ||
1520 | Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { | 1530 | Value* 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 | ||
1542 | Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { | 1552 | Value* 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 | ||
1551 | Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { | 1561 | Value* 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 { |