diff options
author | Tianjie Xu | 2018-02-02 18:49:15 -0600 |
---|---|---|
committer | Tianjie Xu | 2018-02-12 13:55:05 -0600 |
commit | 5419ad31e7dafae35ab1ac9f56e234fff0c2de50 (patch) | |
tree | fca056a5473790add5080c3f6a7324f1f767b80b | |
parent | 6a3646fc0306b8f8781e3f080dc2f957ae811f75 (diff) | |
download | platform-bootable-recovery-5419ad31e7dafae35ab1ac9f56e234fff0c2de50.tar.gz platform-bootable-recovery-5419ad31e7dafae35ab1ac9f56e234fff0c2de50.tar.xz platform-bootable-recovery-5419ad31e7dafae35ab1ac9f56e234fff0c2de50.zip |
Reorder the functions in updater/install.cpp
There is no logical change to the file; merely the function definition
reorder and some comestic change to make the future review easier.
Test: mma
Change-Id: I7ffe952f8c78e840f10aa6bfad0c4b5a58e29896
-rw-r--r-- | updater/install.cpp | 483 |
1 files changed, 244 insertions, 239 deletions
diff --git a/updater/install.cpp b/updater/install.cpp index eef252e3..2b6c20fe 100644 --- a/updater/install.cpp +++ b/updater/install.cpp | |||
@@ -94,6 +94,244 @@ void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) { | |||
94 | uiPrint(state, error_msg); | 94 | uiPrint(state, error_msg); |
95 | } | 95 | } |
96 | 96 | ||
97 | // This is the updater side handler for ui_print() in edify script. Contents will be sent over to | ||
98 | // the recovery side for on-screen display. | ||
99 | Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
100 | std::vector<std::string> args; | ||
101 | if (!ReadArgs(state, argv, &args)) { | ||
102 | return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); | ||
103 | } | ||
104 | |||
105 | std::string buffer = android::base::Join(args, ""); | ||
106 | uiPrint(state, buffer); | ||
107 | return StringValue(buffer); | ||
108 | } | ||
109 | |||
110 | // package_extract_file(package_file[, dest_file]) | ||
111 | // Extracts a single package_file from the update package and writes it to dest_file, | ||
112 | // overwriting existing files if necessary. Without the dest_file argument, returns the | ||
113 | // contents of the package file as a binary blob. | ||
114 | Value* PackageExtractFileFn(const char* name, State* state, | ||
115 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
116 | if (argv.size() < 1 || argv.size() > 2) { | ||
117 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, | ||
118 | argv.size()); | ||
119 | } | ||
120 | |||
121 | if (argv.size() == 2) { | ||
122 | // The two-argument version extracts to a file. | ||
123 | |||
124 | std::vector<std::string> args; | ||
125 | if (!ReadArgs(state, argv, &args)) { | ||
126 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, | ||
127 | argv.size()); | ||
128 | } | ||
129 | const std::string& zip_path = args[0]; | ||
130 | const std::string& dest_path = args[1]; | ||
131 | |||
132 | ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; | ||
133 | ZipString zip_string_path(zip_path.c_str()); | ||
134 | ZipEntry entry; | ||
135 | if (FindEntry(za, zip_string_path, &entry) != 0) { | ||
136 | LOG(ERROR) << name << ": no " << zip_path << " in package"; | ||
137 | return StringValue(""); | ||
138 | } | ||
139 | |||
140 | unique_fd fd(TEMP_FAILURE_RETRY( | ||
141 | ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); | ||
142 | if (fd == -1) { | ||
143 | PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; | ||
144 | return StringValue(""); | ||
145 | } | ||
146 | |||
147 | bool success = true; | ||
148 | int32_t ret = ExtractEntryToFile(za, &entry, fd); | ||
149 | if (ret != 0) { | ||
150 | LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" (" | ||
151 | << entry.uncompressed_length << " bytes) to \"" << dest_path | ||
152 | << "\": " << ErrorCodeString(ret); | ||
153 | success = false; | ||
154 | } | ||
155 | if (ota_fsync(fd) == -1) { | ||
156 | PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed"; | ||
157 | success = false; | ||
158 | } | ||
159 | if (ota_close(fd) == -1) { | ||
160 | PLOG(ERROR) << "close of \"" << dest_path << "\" failed"; | ||
161 | success = false; | ||
162 | } | ||
163 | |||
164 | return StringValue(success ? "t" : ""); | ||
165 | } else { | ||
166 | // The one-argument version returns the contents of the file as the result. | ||
167 | |||
168 | std::vector<std::string> args; | ||
169 | if (!ReadArgs(state, argv, &args)) { | ||
170 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, | ||
171 | argv.size()); | ||
172 | } | ||
173 | const std::string& zip_path = args[0]; | ||
174 | |||
175 | ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; | ||
176 | ZipString zip_string_path(zip_path.c_str()); | ||
177 | ZipEntry entry; | ||
178 | if (FindEntry(za, zip_string_path, &entry) != 0) { | ||
179 | return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name, | ||
180 | zip_path.c_str()); | ||
181 | } | ||
182 | |||
183 | std::string buffer; | ||
184 | buffer.resize(entry.uncompressed_length); | ||
185 | |||
186 | int32_t ret = | ||
187 | ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size()); | ||
188 | if (ret != 0) { | ||
189 | return ErrorAbort(state, kPackageExtractFileFailure, | ||
190 | "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name, | ||
191 | zip_path.c_str(), buffer.size(), ErrorCodeString(ret)); | ||
192 | } | ||
193 | |||
194 | return new Value(VAL_BLOB, buffer); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | // apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...]) | ||
199 | // Applies a binary patch to the src_file to produce the tgt_file. If the desired target is the | ||
200 | // same as the source, pass "-" for tgt_file. tgt_sha1 and tgt_size are the expected final SHA1 | ||
201 | // hash and size of the target file. The remaining arguments must come in pairs: a SHA1 hash (a | ||
202 | // 40-character hex string) and a blob. The blob is the patch to be applied when the source | ||
203 | // file's current contents have the given SHA1. | ||
204 | // | ||
205 | // The patching is done in a safe manner that guarantees the target file either has the desired | ||
206 | // SHA1 hash and size, or it is untouched -- it will not be left in an unrecoverable intermediate | ||
207 | // state. If the process is interrupted during patching, the target file may be in an intermediate | ||
208 | // state; a copy exists in the cache partition so restarting the update can successfully update | ||
209 | // the file. | ||
210 | Value* ApplyPatchFn(const char* name, State* state, | ||
211 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
212 | if (argv.size() < 6 || (argv.size() % 2) == 1) { | ||
213 | return ErrorAbort(state, kArgsParsingFailure, | ||
214 | "%s(): expected at least 6 args and an " | ||
215 | "even number, got %zu", | ||
216 | name, argv.size()); | ||
217 | } | ||
218 | |||
219 | std::vector<std::string> args; | ||
220 | if (!ReadArgs(state, argv, &args, 0, 4)) { | ||
221 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
222 | } | ||
223 | const std::string& source_filename = args[0]; | ||
224 | const std::string& target_filename = args[1]; | ||
225 | const std::string& target_sha1 = args[2]; | ||
226 | const std::string& target_size_str = args[3]; | ||
227 | |||
228 | size_t target_size; | ||
229 | if (!android::base::ParseUint(target_size_str.c_str(), &target_size)) { | ||
230 | return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name, | ||
231 | target_size_str.c_str()); | ||
232 | } | ||
233 | |||
234 | int patchcount = (argv.size() - 4) / 2; | ||
235 | std::vector<std::unique_ptr<Value>> arg_values; | ||
236 | if (!ReadValueArgs(state, argv, &arg_values, 4, argv.size() - 4)) { | ||
237 | return nullptr; | ||
238 | } | ||
239 | |||
240 | for (int i = 0; i < patchcount; ++i) { | ||
241 | if (arg_values[i * 2]->type != VAL_STRING) { | ||
242 | return ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i * 2); | ||
243 | } | ||
244 | if (arg_values[i * 2 + 1]->type != VAL_BLOB) { | ||
245 | return ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i * 2 + 1); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | std::vector<std::string> patch_sha_str; | ||
250 | std::vector<std::unique_ptr<Value>> patches; | ||
251 | for (int i = 0; i < patchcount; ++i) { | ||
252 | patch_sha_str.push_back(arg_values[i * 2]->data); | ||
253 | patches.push_back(std::move(arg_values[i * 2 + 1])); | ||
254 | } | ||
255 | |||
256 | int result = applypatch(source_filename.c_str(), target_filename.c_str(), target_sha1.c_str(), | ||
257 | target_size, patch_sha_str, patches, nullptr); | ||
258 | |||
259 | return StringValue(result == 0 ? "t" : ""); | ||
260 | } | ||
261 | |||
262 | // apply_patch_check(filename, [sha1, ...]) | ||
263 | // Returns true if the contents of filename or the temporary copy in the cache partition (if | ||
264 | // present) have a SHA-1 checksum equal to one of the given sha1 values. sha1 values are | ||
265 | // specified as 40 hex digits. This function differs from sha1_check(read_file(filename), | ||
266 | // sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will | ||
267 | // succeed even if the file was corrupted by an interrupted apply_patch() update. | ||
268 | Value* ApplyPatchCheckFn(const char* name, State* state, | ||
269 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
270 | if (argv.size() < 1) { | ||
271 | return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %zu", name, | ||
272 | argv.size()); | ||
273 | } | ||
274 | |||
275 | std::vector<std::string> args; | ||
276 | if (!ReadArgs(state, argv, &args, 0, 1)) { | ||
277 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
278 | } | ||
279 | const std::string& filename = args[0]; | ||
280 | |||
281 | std::vector<std::string> sha1s; | ||
282 | if (argv.size() > 1 && !ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { | ||
283 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
284 | } | ||
285 | int result = applypatch_check(filename.c_str(), sha1s); | ||
286 | |||
287 | return StringValue(result == 0 ? "t" : ""); | ||
288 | } | ||
289 | |||
290 | // sha1_check(data) | ||
291 | // to return the sha1 of the data (given in the format returned by | ||
292 | // read_file). | ||
293 | // | ||
294 | // sha1_check(data, sha1_hex, [sha1_hex, ...]) | ||
295 | // returns the sha1 of the file if it matches any of the hex | ||
296 | // strings passed, or "" if it does not equal any of them. | ||
297 | // | ||
298 | Value* Sha1CheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
299 | if (argv.size() < 1) { | ||
300 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); | ||
301 | } | ||
302 | |||
303 | std::vector<std::unique_ptr<Value>> args; | ||
304 | if (!ReadValueArgs(state, argv, &args)) { | ||
305 | return nullptr; | ||
306 | } | ||
307 | |||
308 | if (args[0]->type == VAL_INVALID) { | ||
309 | return StringValue(""); | ||
310 | } | ||
311 | uint8_t digest[SHA_DIGEST_LENGTH]; | ||
312 | SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest); | ||
313 | |||
314 | if (argv.size() == 1) { | ||
315 | return StringValue(print_sha1(digest)); | ||
316 | } | ||
317 | |||
318 | for (size_t i = 1; i < argv.size(); ++i) { | ||
319 | uint8_t arg_digest[SHA_DIGEST_LENGTH]; | ||
320 | if (args[i]->type != VAL_STRING) { | ||
321 | LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; | ||
322 | } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) { | ||
323 | // Warn about bad args and skip them. | ||
324 | LOG(ERROR) << name << "(): error parsing \"" << args[i]->data << "\" as sha-1; skipping"; | ||
325 | } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { | ||
326 | // Found a match. | ||
327 | return args[i].release(); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | // Didn't match any of the hex strings; return false. | ||
332 | return StringValue(""); | ||
333 | } | ||
334 | |||
97 | // mount(fs_type, partition_type, location, mount_point) | 335 | // mount(fs_type, partition_type, location, mount_point) |
98 | // mount(fs_type, partition_type, location, mount_point, mount_options) | 336 | // mount(fs_type, partition_type, location, mount_point, mount_options) |
99 | 337 | ||
@@ -367,7 +605,8 @@ Value* ShowProgressFn(const char* name, State* state, | |||
367 | return StringValue(frac_str); | 605 | return StringValue(frac_str); |
368 | } | 606 | } |
369 | 607 | ||
370 | Value* SetProgressFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 608 | Value* SetProgressFn(const char* name, State* state, |
609 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
371 | if (argv.size() != 1) { | 610 | if (argv.size() != 1) { |
372 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); | 611 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); |
373 | } | 612 | } |
@@ -390,93 +629,6 @@ Value* SetProgressFn(const char* name, State* state, const std::vector<std::uniq | |||
390 | return StringValue(frac_str); | 629 | return StringValue(frac_str); |
391 | } | 630 | } |
392 | 631 | ||
393 | // package_extract_file(package_file[, dest_file]) | ||
394 | // Extracts a single package_file from the update package and writes it to dest_file, | ||
395 | // overwriting existing files if necessary. Without the dest_file argument, returns the | ||
396 | // contents of the package file as a binary blob. | ||
397 | Value* PackageExtractFileFn(const char* name, State* state, | ||
398 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
399 | if (argv.size() < 1 || argv.size() > 2) { | ||
400 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, | ||
401 | argv.size()); | ||
402 | } | ||
403 | |||
404 | if (argv.size() == 2) { | ||
405 | // The two-argument version extracts to a file. | ||
406 | |||
407 | std::vector<std::string> args; | ||
408 | if (!ReadArgs(state, argv, &args)) { | ||
409 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, | ||
410 | argv.size()); | ||
411 | } | ||
412 | const std::string& zip_path = args[0]; | ||
413 | const std::string& dest_path = args[1]; | ||
414 | |||
415 | ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; | ||
416 | ZipString zip_string_path(zip_path.c_str()); | ||
417 | ZipEntry entry; | ||
418 | if (FindEntry(za, zip_string_path, &entry) != 0) { | ||
419 | LOG(ERROR) << name << ": no " << zip_path << " in package"; | ||
420 | return StringValue(""); | ||
421 | } | ||
422 | |||
423 | unique_fd fd(TEMP_FAILURE_RETRY( | ||
424 | ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); | ||
425 | if (fd == -1) { | ||
426 | PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; | ||
427 | return StringValue(""); | ||
428 | } | ||
429 | |||
430 | bool success = true; | ||
431 | int32_t ret = ExtractEntryToFile(za, &entry, fd); | ||
432 | if (ret != 0) { | ||
433 | LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" (" | ||
434 | << entry.uncompressed_length << " bytes) to \"" << dest_path | ||
435 | << "\": " << ErrorCodeString(ret); | ||
436 | success = false; | ||
437 | } | ||
438 | if (ota_fsync(fd) == -1) { | ||
439 | PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed"; | ||
440 | success = false; | ||
441 | } | ||
442 | if (ota_close(fd) == -1) { | ||
443 | PLOG(ERROR) << "close of \"" << dest_path << "\" failed"; | ||
444 | success = false; | ||
445 | } | ||
446 | |||
447 | return StringValue(success ? "t" : ""); | ||
448 | } else { | ||
449 | // The one-argument version returns the contents of the file as the result. | ||
450 | |||
451 | std::vector<std::string> args; | ||
452 | if (!ReadArgs(state, argv, &args)) { | ||
453 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, | ||
454 | argv.size()); | ||
455 | } | ||
456 | const std::string& zip_path = args[0]; | ||
457 | |||
458 | ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; | ||
459 | ZipString zip_string_path(zip_path.c_str()); | ||
460 | ZipEntry entry; | ||
461 | if (FindEntry(za, zip_string_path, &entry) != 0) { | ||
462 | return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name, | ||
463 | zip_path.c_str()); | ||
464 | } | ||
465 | |||
466 | std::string buffer; | ||
467 | buffer.resize(entry.uncompressed_length); | ||
468 | |||
469 | int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size()); | ||
470 | if (ret != 0) { | ||
471 | return ErrorAbort(state, kPackageExtractFileFailure, | ||
472 | "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name, | ||
473 | zip_path.c_str(), buffer.size(), ErrorCodeString(ret)); | ||
474 | } | ||
475 | |||
476 | return new Value(VAL_BLOB, buffer); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 632 | Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { |
481 | if (argv.size() != 1) { | 633 | if (argv.size() != 1) { |
482 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); | 634 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); |
@@ -495,7 +647,8 @@ Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_p | |||
495 | // interprets 'file' as a getprop-style file (key=value pairs, one | 647 | // interprets 'file' as a getprop-style file (key=value pairs, one |
496 | // per line. # comment lines, blank lines, lines without '=' ignored), | 648 | // per line. # comment lines, blank lines, lines without '=' ignored), |
497 | // and returns the value for 'key' (or "" if it isn't defined). | 649 | // and returns the value for 'key' (or "" if it isn't defined). |
498 | Value* FileGetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 650 | Value* FileGetPropFn(const char* name, State* state, |
651 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
499 | if (argv.size() != 2) { | 652 | if (argv.size() != 2) { |
500 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, | 653 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, |
501 | argv.size()); | 654 | argv.size()); |
@@ -561,7 +714,8 @@ Value* FileGetPropFn(const char* name, State* state, const std::vector<std::uniq | |||
561 | } | 714 | } |
562 | 715 | ||
563 | // apply_patch_space(bytes) | 716 | // apply_patch_space(bytes) |
564 | Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 717 | Value* ApplyPatchSpaceFn(const char* name, State* state, |
718 | const std::vector<std::unique_ptr<Expr>>& argv) { | ||
565 | if (argv.size() != 1) { | 719 | if (argv.size() != 1) { |
566 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, | 720 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, |
567 | argv.size()); | 721 | argv.size()); |
@@ -585,110 +739,6 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std:: | |||
585 | return StringValue(""); | 739 | return StringValue(""); |
586 | } | 740 | } |
587 | 741 | ||
588 | // apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...]) | ||
589 | // Applies a binary patch to the src_file to produce the tgt_file. If the desired target is the | ||
590 | // same as the source, pass "-" for tgt_file. tgt_sha1 and tgt_size are the expected final SHA1 | ||
591 | // hash and size of the target file. The remaining arguments must come in pairs: a SHA1 hash (a | ||
592 | // 40-character hex string) and a blob. The blob is the patch to be applied when the source | ||
593 | // file's current contents have the given SHA1. | ||
594 | // | ||
595 | // The patching is done in a safe manner that guarantees the target file either has the desired | ||
596 | // SHA1 hash and size, or it is untouched -- it will not be left in an unrecoverable intermediate | ||
597 | // state. If the process is interrupted during patching, the target file may be in an intermediate | ||
598 | // state; a copy exists in the cache partition so restarting the update can successfully update | ||
599 | // the file. | ||
600 | Value* ApplyPatchFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
601 | if (argv.size() < 6 || (argv.size() % 2) == 1) { | ||
602 | return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " | ||
603 | "even number, got %zu", name, argv.size()); | ||
604 | } | ||
605 | |||
606 | std::vector<std::string> args; | ||
607 | if (!ReadArgs(state, argv, &args, 0, 4)) { | ||
608 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
609 | } | ||
610 | const std::string& source_filename = args[0]; | ||
611 | const std::string& target_filename = args[1]; | ||
612 | const std::string& target_sha1 = args[2]; | ||
613 | const std::string& target_size_str = args[3]; | ||
614 | |||
615 | size_t target_size; | ||
616 | if (!android::base::ParseUint(target_size_str.c_str(), &target_size)) { | ||
617 | return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", | ||
618 | name, target_size_str.c_str()); | ||
619 | } | ||
620 | |||
621 | int patchcount = (argv.size()-4) / 2; | ||
622 | std::vector<std::unique_ptr<Value>> arg_values; | ||
623 | if (!ReadValueArgs(state, argv, &arg_values, 4, argv.size() - 4)) { | ||
624 | return nullptr; | ||
625 | } | ||
626 | |||
627 | for (int i = 0; i < patchcount; ++i) { | ||
628 | if (arg_values[i * 2]->type != VAL_STRING) { | ||
629 | return ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, | ||
630 | i * 2); | ||
631 | } | ||
632 | if (arg_values[i * 2 + 1]->type != VAL_BLOB) { | ||
633 | return ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, | ||
634 | i * 2 + 1); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | std::vector<std::string> patch_sha_str; | ||
639 | std::vector<std::unique_ptr<Value>> patches; | ||
640 | for (int i = 0; i < patchcount; ++i) { | ||
641 | patch_sha_str.push_back(arg_values[i * 2]->data); | ||
642 | patches.push_back(std::move(arg_values[i * 2 + 1])); | ||
643 | } | ||
644 | |||
645 | int result = applypatch(source_filename.c_str(), target_filename.c_str(), | ||
646 | target_sha1.c_str(), target_size, | ||
647 | patch_sha_str, patches, nullptr); | ||
648 | |||
649 | return StringValue(result == 0 ? "t" : ""); | ||
650 | } | ||
651 | |||
652 | // apply_patch_check(filename, [sha1, ...]) | ||
653 | // Returns true if the contents of filename or the temporary copy in the cache partition (if | ||
654 | // present) have a SHA-1 checksum equal to one of the given sha1 values. sha1 values are | ||
655 | // specified as 40 hex digits. This function differs from sha1_check(read_file(filename), | ||
656 | // sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will | ||
657 | // succeed even if the file was corrupted by an interrupted apply_patch() update. | ||
658 | Value* ApplyPatchCheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
659 | if (argv.size() < 1) { | ||
660 | return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %zu", name, | ||
661 | argv.size()); | ||
662 | } | ||
663 | |||
664 | std::vector<std::string> args; | ||
665 | if (!ReadArgs(state, argv, &args, 0, 1)) { | ||
666 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
667 | } | ||
668 | const std::string& filename = args[0]; | ||
669 | |||
670 | std::vector<std::string> sha1s; | ||
671 | if (argv.size() > 1 && !ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { | ||
672 | return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); | ||
673 | } | ||
674 | int result = applypatch_check(filename.c_str(), sha1s); | ||
675 | |||
676 | return StringValue(result == 0 ? "t" : ""); | ||
677 | } | ||
678 | |||
679 | // This is the updater side handler for ui_print() in edify script. Contents will be sent over to | ||
680 | // the recovery side for on-screen display. | ||
681 | Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
682 | std::vector<std::string> args; | ||
683 | if (!ReadArgs(state, argv, &args)) { | ||
684 | return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); | ||
685 | } | ||
686 | |||
687 | std::string buffer = android::base::Join(args, ""); | ||
688 | uiPrint(state, buffer); | ||
689 | return StringValue(buffer); | ||
690 | } | ||
691 | |||
692 | Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 742 | Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { |
693 | if (!argv.empty()) { | 743 | if (!argv.empty()) { |
694 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, | 744 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, |
@@ -736,51 +786,6 @@ Value* RunProgramFn(const char* name, State* state, const std::vector<std::uniqu | |||
736 | return StringValue(std::to_string(status)); | 786 | return StringValue(std::to_string(status)); |
737 | } | 787 | } |
738 | 788 | ||
739 | // sha1_check(data) | ||
740 | // to return the sha1 of the data (given in the format returned by | ||
741 | // read_file). | ||
742 | // | ||
743 | // sha1_check(data, sha1_hex, [sha1_hex, ...]) | ||
744 | // returns the sha1 of the file if it matches any of the hex | ||
745 | // strings passed, or "" if it does not equal any of them. | ||
746 | // | ||
747 | Value* Sha1CheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | ||
748 | if (argv.size() < 1) { | ||
749 | return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); | ||
750 | } | ||
751 | |||
752 | std::vector<std::unique_ptr<Value>> args; | ||
753 | if (!ReadValueArgs(state, argv, &args)) { | ||
754 | return nullptr; | ||
755 | } | ||
756 | |||
757 | if (args[0]->type == VAL_INVALID) { | ||
758 | return StringValue(""); | ||
759 | } | ||
760 | uint8_t digest[SHA_DIGEST_LENGTH]; | ||
761 | SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest); | ||
762 | |||
763 | if (argv.size() == 1) { | ||
764 | return StringValue(print_sha1(digest)); | ||
765 | } | ||
766 | |||
767 | for (size_t i = 1; i < argv.size(); ++i) { | ||
768 | uint8_t arg_digest[SHA_DIGEST_LENGTH]; | ||
769 | if (args[i]->type != VAL_STRING) { | ||
770 | LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; | ||
771 | } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) { | ||
772 | // Warn about bad args and skip them. | ||
773 | LOG(ERROR) << name << "(): error parsing \"" << args[i]->data << "\" as sha-1; skipping"; | ||
774 | } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { | ||
775 | // Found a match. | ||
776 | return args[i].release(); | ||
777 | } | ||
778 | } | ||
779 | |||
780 | // Didn't match any of the hex strings; return false. | ||
781 | return StringValue(""); | ||
782 | } | ||
783 | |||
784 | // Read a local file and return its contents (the Value* returned | 789 | // Read a local file and return its contents (the Value* returned |
785 | // is actually a FileContents*). | 790 | // is actually a FileContents*). |
786 | Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { | 791 | Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { |