1 /* 2 * Copyright (C) 2008 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 #include "applypatch/applypatch.h" 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <libgen.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/stat.h> 26 #include <sys/statfs.h> 27 #include <sys/types.h> 28 #include <unistd.h> 29 30 #include <functional> 31 #include <memory> 32 #include <string> 33 #include <utility> 34 #include <vector> 35 36 #include <android-base/logging.h> 37 #include <android-base/parseint.h> 38 #include <android-base/strings.h> 39 #include <openssl/sha.h> 40 41 #include "edify/expr.h" 42 #include "otafault/ota_io.h" 43 #include "otautil/cache_location.h" 44 #include "otautil/print_sha1.h" 45 46 static int LoadPartitionContents(const std::string& filename, FileContents* file); 47 static size_t FileSink(const unsigned char* data, size_t len, int fd); 48 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch, 49 const std::string& target_filename, 50 const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data); 51 52 // Read a file into memory; store the file contents and associated metadata in *file. 53 // Return 0 on success. 54 int LoadFileContents(const char* filename, FileContents* file) { 55 // A special 'filename' beginning with "EMMC:" means to load the contents of a partition. 56 if (strncmp(filename, "EMMC:", 5) == 0) { 57 return LoadPartitionContents(filename, file); 58 } 59 60 struct stat sb; 61 if (stat(filename, &sb) == -1) { 62 printf("failed to stat \"%s\": %s\n", filename, strerror(errno)); 63 return -1; 64 } 65 66 std::vector<unsigned char> data(sb.st_size); 67 unique_file f(ota_fopen(filename, "rb")); 68 if (!f) { 69 printf("failed to open \"%s\": %s\n", filename, strerror(errno)); 70 return -1; 71 } 72 73 size_t bytes_read = ota_fread(data.data(), 1, data.size(), f.get()); 74 if (bytes_read != data.size()) { 75 printf("short read of \"%s\" (%zu bytes of %zu)\n", filename, bytes_read, data.size()); 76 return -1; 77 } 78 file->data = std::move(data); 79 SHA1(file->data.data(), file->data.size(), file->sha1); 80 return 0; 81 } 82 83 // Load the contents of an EMMC partition into the provided 84 // FileContents. filename should be a string of the form 85 // "EMMC:<partition_device>:...". The smallest size_n bytes for 86 // which that prefix of the partition contents has the corresponding 87 // sha1 hash will be loaded. It is acceptable for a size value to be 88 // repeated with different sha1s. Will return 0 on success. 89 // 90 // This complexity is needed because if an OTA installation is 91 // interrupted, the partition might contain either the source or the 92 // target data, which might be of different lengths. We need to know 93 // the length in order to read from a partition (there is no 94 // "end-of-file" marker), so the caller must specify the possible 95 // lengths and the hash of the data, and we'll do the load expecting 96 // to find one of those hashes. 97 static int LoadPartitionContents(const std::string& filename, FileContents* file) { 98 std::vector<std::string> pieces = android::base::Split(filename, ":"); 99 if (pieces.size() < 4 || pieces.size() % 2 != 0 || pieces[0] != "EMMC") { 100 printf("LoadPartitionContents called with bad filename \"%s\"\n", filename.c_str()); 101 return -1; 102 } 103 104 size_t pair_count = (pieces.size() - 2) / 2; // # of (size, sha1) pairs in filename 105 std::vector<std::pair<size_t, std::string>> pairs; 106 for (size_t i = 0; i < pair_count; ++i) { 107 size_t size; 108 if (!android::base::ParseUint(pieces[i * 2 + 2], &size) || size == 0) { 109 printf("LoadPartitionContents called with bad size \"%s\"\n", pieces[i * 2 + 2].c_str()); 110 return -1; 111 } 112 pairs.push_back({ size, pieces[i * 2 + 3] }); 113 } 114 115 // Sort the pairs array so that they are in order of increasing size. 116 std::sort(pairs.begin(), pairs.end()); 117 118 const char* partition = pieces[1].c_str(); 119 unique_file dev(ota_fopen(partition, "rb")); 120 if (!dev) { 121 printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); 122 return -1; 123 } 124 125 SHA_CTX sha_ctx; 126 SHA1_Init(&sha_ctx); 127 128 // Allocate enough memory to hold the largest size. 129 std::vector<unsigned char> buffer(pairs[pair_count - 1].first); 130 unsigned char* buffer_ptr = buffer.data(); 131 size_t buffer_size = 0; // # bytes read so far 132 bool found = false; 133 134 for (const auto& pair : pairs) { 135 size_t current_size = pair.first; 136 const std::string& current_sha1 = pair.second; 137 138 // Read enough additional bytes to get us up to the next size. (Again, 139 // we're trying the possibilities in order of increasing size). 140 size_t next = current_size - buffer_size; 141 if (next > 0) { 142 size_t read = ota_fread(buffer_ptr, 1, next, dev.get()); 143 if (next != read) { 144 printf("short read (%zu bytes of %zu) for partition \"%s\"\n", read, next, partition); 145 return -1; 146 } 147 SHA1_Update(&sha_ctx, buffer_ptr, read); 148 buffer_size += read; 149 buffer_ptr += read; 150 } 151 152 // Duplicate the SHA context and finalize the duplicate so we can 153 // check it against this pair's expected hash. 154 SHA_CTX temp_ctx; 155 memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX)); 156 uint8_t sha_so_far[SHA_DIGEST_LENGTH]; 157 SHA1_Final(sha_so_far, &temp_ctx); 158 159 uint8_t parsed_sha[SHA_DIGEST_LENGTH]; 160 if (ParseSha1(current_sha1.c_str(), parsed_sha) != 0) { 161 printf("failed to parse SHA-1 %s in %s\n", current_sha1.c_str(), filename.c_str()); 162 return -1; 163 } 164 165 if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_LENGTH) == 0) { 166 // We have a match. Stop reading the partition; we'll return the data we've read so far. 167 printf("partition read matched size %zu SHA-1 %s\n", current_size, current_sha1.c_str()); 168 found = true; 169 break; 170 } 171 } 172 173 if (!found) { 174 // Ran off the end of the list of (size, sha1) pairs without finding a match. 175 printf("contents of partition \"%s\" didn't match %s\n", partition, filename.c_str()); 176 return -1; 177 } 178 179 SHA1_Final(file->sha1, &sha_ctx); 180 181 buffer.resize(buffer_size); 182 file->data = std::move(buffer); 183 184 return 0; 185 } 186 187 // Save the contents of the given FileContents object under the given 188 // filename. Return 0 on success. 189 int SaveFileContents(const char* filename, const FileContents* file) { 190 unique_fd fd(ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); 191 if (fd == -1) { 192 printf("failed to open \"%s\" for write: %s\n", filename, strerror(errno)); 193 return -1; 194 } 195 196 size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd); 197 if (bytes_written != file->data.size()) { 198 printf("short write of \"%s\" (%zd bytes of %zu): %s\n", filename, bytes_written, 199 file->data.size(), strerror(errno)); 200 return -1; 201 } 202 if (ota_fsync(fd) != 0) { 203 printf("fsync of \"%s\" failed: %s\n", filename, strerror(errno)); 204 return -1; 205 } 206 if (ota_close(fd) != 0) { 207 printf("close of \"%s\" failed: %s\n", filename, strerror(errno)); 208 return -1; 209 } 210 211 return 0; 212 } 213 214 // Write a memory buffer to 'target' partition, a string of the form 215 // "EMMC:<partition_device>[:...]". The target name 216 // might contain multiple colons, but WriteToPartition() only uses the first 217 // two and ignores the rest. Return 0 on success. 218 int WriteToPartition(const unsigned char* data, size_t len, const std::string& target) { 219 std::vector<std::string> pieces = android::base::Split(target, ":"); 220 if (pieces.size() < 2 || pieces[0] != "EMMC") { 221 printf("WriteToPartition called with bad target (%s)\n", target.c_str()); 222 return -1; 223 } 224 225 const char* partition = pieces[1].c_str(); 226 unique_fd fd(ota_open(partition, O_RDWR)); 227 if (fd == -1) { 228 printf("failed to open %s: %s\n", partition, strerror(errno)); 229 return -1; 230 } 231 232 size_t start = 0; 233 bool success = false; 234 for (size_t attempt = 0; attempt < 2; ++attempt) { 235 if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { 236 printf("failed seek on %s: %s\n", partition, strerror(errno)); 237 return -1; 238 } 239 while (start < len) { 240 size_t to_write = len - start; 241 if (to_write > 1 << 20) to_write = 1 << 20; 242 243 ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data + start, to_write)); 244 if (written == -1) { 245 printf("failed write writing to %s: %s\n", partition, strerror(errno)); 246 return -1; 247 } 248 start += written; 249 } 250 251 if (ota_fsync(fd) != 0) { 252 printf("failed to sync to %s: %s\n", partition, strerror(errno)); 253 return -1; 254 } 255 if (ota_close(fd) != 0) { 256 printf("failed to close %s: %s\n", partition, strerror(errno)); 257 return -1; 258 } 259 260 fd.reset(ota_open(partition, O_RDONLY)); 261 if (fd == -1) { 262 printf("failed to reopen %s for verify: %s\n", partition, strerror(errno)); 263 return -1; 264 } 265 266 // Drop caches so our subsequent verification read won't just be reading the cache. 267 sync(); 268 unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY)); 269 if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) { 270 printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno)); 271 } else { 272 printf(" caches dropped\n"); 273 } 274 ota_close(dc); 275 sleep(1); 276 277 // Verify. 278 if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) { 279 printf("failed to seek back to beginning of %s: %s\n", partition, strerror(errno)); 280 return -1; 281 } 282 283 unsigned char buffer[4096]; 284 start = len; 285 for (size_t p = 0; p < len; p += sizeof(buffer)) { 286 size_t to_read = len - p; 287 if (to_read > sizeof(buffer)) { 288 to_read = sizeof(buffer); 289 } 290 291 size_t so_far = 0; 292 while (so_far < to_read) { 293 ssize_t read_count = TEMP_FAILURE_RETRY(ota_read(fd, buffer + so_far, to_read - so_far)); 294 if (read_count == -1) { 295 printf("verify read error %s at %zu: %s\n", partition, p, strerror(errno)); 296 return -1; 297 } else if (read_count == 0) { 298 printf("verify read reached unexpected EOF, %s at %zu\n", partition, p); 299 return -1; 300 } 301 if (static_cast<size_t>(read_count) < to_read) { 302 printf("short verify read %s at %zu: %zd %zu\n", partition, p, read_count, to_read); 303 } 304 so_far += read_count; 305 } 306 307 if (memcmp(buffer, data + p, to_read) != 0) { 308 printf("verification failed starting at %zu\n", p); 309 start = p; 310 break; 311 } 312 } 313 314 if (start == len) { 315 printf("verification read succeeded (attempt %zu)\n", attempt + 1); 316 success = true; 317 break; 318 } 319 320 if (ota_close(fd) != 0) { 321 printf("failed to close %s: %s\n", partition, strerror(errno)); 322 return -1; 323 } 324 325 fd.reset(ota_open(partition, O_RDWR)); 326 if (fd == -1) { 327 printf("failed to reopen %s for retry write && verify: %s\n", partition, strerror(errno)); 328 return -1; 329 } 330 } 331 332 if (!success) { 333 printf("failed to verify after all attempts\n"); 334 return -1; 335 } 336 337 if (ota_close(fd) == -1) { 338 printf("error closing %s: %s\n", partition, strerror(errno)); 339 return -1; 340 } 341 sync(); 342 343 return 0; 344 } 345 346 // Take a string 'str' of 40 hex digits and parse it into the 20 347 // byte array 'digest'. 'str' may contain only the digest or be of 348 // the form "<digest>:<anything>". Return 0 on success, -1 on any 349 // error. 350 int ParseSha1(const char* str, uint8_t* digest) { 351 const char* ps = str; 352 uint8_t* pd = digest; 353 for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) { 354 int digit; 355 if (*ps >= '0' && *ps <= '9') { 356 digit = *ps - '0'; 357 } else if (*ps >= 'a' && *ps <= 'f') { 358 digit = *ps - 'a' + 10; 359 } else if (*ps >= 'A' && *ps <= 'F') { 360 digit = *ps - 'A' + 10; 361 } else { 362 return -1; 363 } 364 if (i % 2 == 0) { 365 *pd = digit << 4; 366 } else { 367 *pd |= digit; 368 ++pd; 369 } 370 } 371 if (*ps != '\0') return -1; 372 return 0; 373 } 374 375 // Search an array of sha1 strings for one matching the given sha1. 376 // Return the index of the match on success, or -1 if no match is 377 // found. 378 static int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) { 379 for (size_t i = 0; i < patch_sha1_str.size(); ++i) { 380 uint8_t patch_sha1[SHA_DIGEST_LENGTH]; 381 if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 && 382 memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { 383 return i; 384 } 385 } 386 return -1; 387 } 388 389 // Returns 0 if the contents of the file (argv[2]) or the cached file 390 // match any of the sha1's on the command line (argv[3:]). Returns 391 // nonzero otherwise. 392 int applypatch_check(const char* filename, const std::vector<std::string>& patch_sha1_str) { 393 FileContents file; 394 395 // It's okay to specify no sha1s; the check will pass if the 396 // LoadFileContents is successful. (Useful for reading 397 // partitions, where the filename encodes the sha1s; no need to 398 // check them twice.) 399 if (LoadFileContents(filename, &file) != 0 || 400 (!patch_sha1_str.empty() && FindMatchingPatch(file.sha1, patch_sha1_str) < 0)) { 401 printf("file \"%s\" doesn't have any of expected sha1 sums; checking cache\n", filename); 402 403 // If the source file is missing or corrupted, it might be because we were killed in the middle 404 // of patching it. A copy of it should have been made in cache_temp_source. If that file 405 // exists and matches the sha1 we're looking for, the check still passes. 406 if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), &file) != 0) { 407 printf("failed to load cache file\n"); 408 return 1; 409 } 410 411 if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) { 412 printf("cache bits don't match any sha1 for \"%s\"\n", filename); 413 return 1; 414 } 415 } 416 return 0; 417 } 418 419 int ShowLicenses() { 420 ShowBSDiffLicense(); 421 return 0; 422 } 423 424 static size_t FileSink(const unsigned char* data, size_t len, int fd) { 425 size_t done = 0; 426 while (done < len) { 427 ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done)); 428 if (wrote == -1) { 429 printf("error writing %zd bytes: %s\n", (len - done), strerror(errno)); 430 return done; 431 } 432 done += wrote; 433 } 434 return done; 435 } 436 437 // Return the amount of free space (in bytes) on the filesystem 438 // containing filename. filename must exist. Return -1 on error. 439 size_t FreeSpaceForFile(const char* filename) { 440 struct statfs sf; 441 if (statfs(filename, &sf) != 0) { 442 printf("failed to statfs %s: %s\n", filename, strerror(errno)); 443 return -1; 444 } 445 return sf.f_bsize * sf.f_bavail; 446 } 447 448 int CacheSizeCheck(size_t bytes) { 449 if (MakeFreeSpaceOnCache(bytes) < 0) { 450 printf("unable to make %zu bytes available on /cache\n", bytes); 451 return 1; 452 } 453 return 0; 454 } 455 456 // This function applies binary patches to EMMC target files in a way that is safe (the original 457 // file is not touched until we have the desired replacement for it) and idempotent (it's okay to 458 // run this program multiple times). 459 // 460 // - If the SHA-1 hash of <target_filename> is <target_sha1_string>, does nothing and exits 461 // successfully. 462 // 463 // - Otherwise, if the SHA-1 hash of <source_filename> is one of the entries in <patch_sha1_str>, 464 // the corresponding patch from <patch_data> (which must be a VAL_BLOB) is applied to produce a 465 // new file (the type of patch is automatically detected from the blob data). If that new file 466 // has SHA-1 hash <target_sha1_str>, moves it to replace <target_filename>, and exits 467 // successfully. Note that if <source_filename> and <target_filename> are not the same, 468 // <source_filename> is NOT deleted on success. <target_filename> may be the string "-" to mean 469 // "the same as <source_filename>". 470 // 471 // - Otherwise, or if any error is encountered, exits with non-zero status. 472 // 473 // <source_filename> must refer to an EMMC partition to read the source data. See the comments for 474 // the LoadPartitionContents() function above for the format of such a filename. <target_size> has 475 // become obsolete since we have dropped the support for patching non-EMMC targets (EMMC targets 476 // have the size embedded in the filename). 477 int applypatch(const char* source_filename, const char* target_filename, 478 const char* target_sha1_str, size_t /* target_size */, 479 const std::vector<std::string>& patch_sha1_str, 480 const std::vector<std::unique_ptr<Value>>& patch_data, const Value* bonus_data) { 481 printf("patch %s: ", source_filename); 482 483 if (target_filename[0] == '-' && target_filename[1] == '\0') { 484 target_filename = source_filename; 485 } 486 487 if (strncmp(target_filename, "EMMC:", 5) != 0) { 488 printf("Supporting patching EMMC targets only.\n"); 489 return 1; 490 } 491 492 uint8_t target_sha1[SHA_DIGEST_LENGTH]; 493 if (ParseSha1(target_sha1_str, target_sha1) != 0) { 494 printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str); 495 return 1; 496 } 497 498 // We try to load the target file into the source_file object. 499 FileContents source_file; 500 if (LoadFileContents(target_filename, &source_file) == 0) { 501 if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) { 502 // The early-exit case: the patch was already applied, this file has the desired hash, nothing 503 // for us to do. 504 printf("already %s\n", short_sha1(target_sha1).c_str()); 505 return 0; 506 } 507 } 508 509 if (source_file.data.empty() || 510 (target_filename != source_filename && strcmp(target_filename, source_filename) != 0)) { 511 // Need to load the source file: either we failed to load the target file, or we did but it's 512 // different from the expected. 513 source_file.data.clear(); 514 LoadFileContents(source_filename, &source_file); 515 } 516 517 if (!source_file.data.empty()) { 518 int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str); 519 if (to_use != -1) { 520 return GenerateTarget(source_file, patch_data[to_use], target_filename, target_sha1, 521 bonus_data); 522 } 523 } 524 525 printf("source file is bad; trying copy\n"); 526 527 FileContents copy_file; 528 if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), ©_file) < 0) { 529 printf("failed to read copy file\n"); 530 return 1; 531 } 532 533 int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str); 534 if (to_use == -1) { 535 printf("copy file doesn't match source SHA-1s either\n"); 536 return 1; 537 } 538 539 return GenerateTarget(copy_file, patch_data[to_use], target_filename, target_sha1, bonus_data); 540 } 541 542 /* 543 * This function flashes a given image to the target partition. It verifies 544 * the target cheksum first, and will return if target has the desired hash. 545 * It checks the checksum of the given source image before flashing, and 546 * verifies the target partition afterwards. The function is idempotent. 547 * Returns zero on success. 548 */ 549 int applypatch_flash(const char* source_filename, const char* target_filename, 550 const char* target_sha1_str, size_t target_size) { 551 printf("flash %s: ", target_filename); 552 553 uint8_t target_sha1[SHA_DIGEST_LENGTH]; 554 if (ParseSha1(target_sha1_str, target_sha1) != 0) { 555 printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str); 556 return 1; 557 } 558 559 std::string target_str(target_filename); 560 std::vector<std::string> pieces = android::base::Split(target_str, ":"); 561 if (pieces.size() != 2 || pieces[0] != "EMMC") { 562 printf("invalid target name \"%s\"", target_filename); 563 return 1; 564 } 565 566 // Load the target into the source_file object to see if already applied. 567 pieces.push_back(std::to_string(target_size)); 568 pieces.push_back(target_sha1_str); 569 std::string fullname = android::base::Join(pieces, ':'); 570 FileContents source_file; 571 if (LoadPartitionContents(fullname, &source_file) == 0 && 572 memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) { 573 // The early-exit case: the image was already applied, this partition 574 // has the desired hash, nothing for us to do. 575 printf("already %s\n", short_sha1(target_sha1).c_str()); 576 return 0; 577 } 578 579 if (LoadFileContents(source_filename, &source_file) == 0) { 580 if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) { 581 // The source doesn't have desired checksum. 582 printf("source \"%s\" doesn't have expected sha1 sum\n", source_filename); 583 printf("expected: %s, found: %s\n", short_sha1(target_sha1).c_str(), 584 short_sha1(source_file.sha1).c_str()); 585 return 1; 586 } 587 } 588 589 if (WriteToPartition(source_file.data.data(), target_size, target_filename) != 0) { 590 printf("write of copied data to %s failed\n", target_filename); 591 return 1; 592 } 593 return 0; 594 } 595 596 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch, 597 const std::string& target_filename, 598 const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data) { 599 if (patch->type != VAL_BLOB) { 600 printf("patch is not a blob\n"); 601 return 1; 602 } 603 604 const char* header = &patch->data[0]; 605 size_t header_bytes_read = patch->data.size(); 606 bool use_bsdiff = false; 607 if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { 608 use_bsdiff = true; 609 } else if (header_bytes_read >= 8 && memcmp(header, "IMGDIFF2", 8) == 0) { 610 use_bsdiff = false; 611 } else { 612 printf("Unknown patch file format\n"); 613 return 1; 614 } 615 616 CHECK(android::base::StartsWith(target_filename, "EMMC:")); 617 618 // We still write the original source to cache, in case the partition write is interrupted. 619 if (MakeFreeSpaceOnCache(source_file.data.size()) < 0) { 620 printf("not enough free space on /cache\n"); 621 return 1; 622 } 623 if (SaveFileContents(CacheLocation::location().cache_temp_source().c_str(), &source_file) < 0) { 624 printf("failed to back up source file\n"); 625 return 1; 626 } 627 628 // We store the decoded output in memory. 629 std::string memory_sink_str; // Don't need to reserve space. 630 SinkFn sink = [&memory_sink_str](const unsigned char* data, size_t len) { 631 memory_sink_str.append(reinterpret_cast<const char*>(data), len); 632 return len; 633 }; 634 635 SHA_CTX ctx; 636 SHA1_Init(&ctx); 637 638 int result; 639 if (use_bsdiff) { 640 result = 641 ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), *patch, 0, sink, &ctx); 642 } else { 643 result = ApplyImagePatch(source_file.data.data(), source_file.data.size(), *patch, sink, &ctx, 644 bonus_data); 645 } 646 647 if (result != 0) { 648 printf("applying patch failed\n"); 649 return 1; 650 } 651 652 uint8_t current_target_sha1[SHA_DIGEST_LENGTH]; 653 SHA1_Final(current_target_sha1, &ctx); 654 if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) { 655 printf("patch did not produce expected sha1\n"); 656 return 1; 657 } else { 658 printf("now %s\n", short_sha1(target_sha1).c_str()); 659 } 660 661 // Write back the temp file to the partition. 662 if (WriteToPartition(reinterpret_cast<const unsigned char*>(memory_sink_str.c_str()), 663 memory_sink_str.size(), target_filename) != 0) { 664 printf("write of patched data to %s failed\n", target_filename.c_str()); 665 return 1; 666 } 667 668 // Delete the backup copy of the source. 669 unlink(CacheLocation::location().cache_temp_source().c_str()); 670 671 // Success! 672 return 0; 673 } 674