aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTianjie Xu2018-02-12 23:32:10 -0600
committerGerrit Code Review2018-02-12 23:32:10 -0600
commit9818283da7a28aaf13c8274c15ec47cb73fb89f0 (patch)
treefca056a5473790add5080c3f6a7324f1f767b80b
parent6a3646fc0306b8f8781e3f080dc2f957ae811f75 (diff)
parent5419ad31e7dafae35ab1ac9f56e234fff0c2de50 (diff)
downloadplatform-bootable-recovery-9818283da7a28aaf13c8274c15ec47cb73fb89f0.tar.gz
platform-bootable-recovery-9818283da7a28aaf13c8274c15ec47cb73fb89f0.tar.xz
platform-bootable-recovery-9818283da7a28aaf13c8274c15ec47cb73fb89f0.zip
Merge "Reorder the functions in updater/install.cpp"
-rw-r--r--updater/install.cpp483
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.
99Value* 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.
114Value* 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.
210Value* 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.
268Value* 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//
298Value* 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
370Value* SetProgressFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 608Value* 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.
397Value* 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
480Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 632Value* 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).
498Value* FileGetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 650Value* 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)
564Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 717Value* 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.
600Value* 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.
658Value* 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.
681Value* 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
692Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 742Value* 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//
747Value* 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*).
786Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { 791Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {