1 /* 2 * Copyright (C) 2014 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 <ctype.h> 18 #include <errno.h> 19 #include <dirent.h> 20 #include <fcntl.h> 21 #include <inttypes.h> 22 #include <libgen.h> 23 #include <pthread.h> 24 #include <stdarg.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <sys/wait.h> 31 #include <sys/ioctl.h> 32 #include <time.h> 33 #include <unistd.h> 34 35 #include "applypatch/applypatch.h" 36 #include "edify/expr.h" 37 #include "mincrypt/sha.h" 38 #include "minzip/Hash.h" 39 #include "updater.h" 40 41 #define BLOCKSIZE 4096 42 43 // Set this to 0 to interpret 'erase' transfers to mean do a 44 // BLKDISCARD ioctl (the normal behavior). Set to 1 to interpret 45 // erase to mean fill the region with zeroes. 46 #define DEBUG_ERASE 0 47 48 #ifndef BLKDISCARD 49 #define BLKDISCARD _IO(0x12,119) 50 #endif 51 52 #define STASH_DIRECTORY_BASE "/cache/recovery" 53 #define STASH_DIRECTORY_MODE 0700 54 #define STASH_FILE_MODE 0600 55 56 char* PrintSha1(const uint8_t* digest); 57 58 typedef struct { 59 int count; 60 int size; 61 int pos[0]; 62 } RangeSet; 63 64 static RangeSet* parse_range(char* text) { 65 char* save; 66 int num; 67 num = strtol(strtok_r(text, ",", &save), NULL, 0); 68 69 RangeSet* out = malloc(sizeof(RangeSet) + num * sizeof(int)); 70 if (out == NULL) { 71 fprintf(stderr, "failed to allocate range of %zu bytes\n", 72 sizeof(RangeSet) + num * sizeof(int)); 73 exit(1); 74 } 75 out->count = num / 2; 76 out->size = 0; 77 int i; 78 for (i = 0; i < num; ++i) { 79 out->pos[i] = strtol(strtok_r(NULL, ",", &save), NULL, 0); 80 if (i%2) { 81 out->size += out->pos[i]; 82 } else { 83 out->size -= out->pos[i]; 84 } 85 } 86 87 return out; 88 } 89 90 static int range_overlaps(RangeSet* r1, RangeSet* r2) { 91 int i, j, r1_0, r1_1, r2_0, r2_1; 92 93 if (!r1 || !r2) { 94 return 0; 95 } 96 97 for (i = 0; i < r1->count; ++i) { 98 r1_0 = r1->pos[i * 2]; 99 r1_1 = r1->pos[i * 2 + 1]; 100 101 for (j = 0; j < r2->count; ++j) { 102 r2_0 = r2->pos[j * 2]; 103 r2_1 = r2->pos[j * 2 + 1]; 104 105 if (!(r2_0 >= r1_1 || r1_0 >= r2_1)) { 106 return 1; 107 } 108 } 109 } 110 111 return 0; 112 } 113 114 static int read_all(int fd, uint8_t* data, size_t size) { 115 size_t so_far = 0; 116 while (so_far < size) { 117 ssize_t r = TEMP_FAILURE_RETRY(read(fd, data+so_far, size-so_far)); 118 if (r == -1) { 119 fprintf(stderr, "read failed: %s\n", strerror(errno)); 120 return -1; 121 } 122 so_far += r; 123 } 124 return 0; 125 } 126 127 static int write_all(int fd, const uint8_t* data, size_t size) { 128 size_t written = 0; 129 while (written < size) { 130 ssize_t w = TEMP_FAILURE_RETRY(write(fd, data+written, size-written)); 131 if (w == -1) { 132 fprintf(stderr, "write failed: %s\n", strerror(errno)); 133 return -1; 134 } 135 written += w; 136 } 137 138 if (fsync(fd) == -1) { 139 fprintf(stderr, "fsync failed: %s\n", strerror(errno)); 140 return -1; 141 } 142 143 return 0; 144 } 145 146 static bool check_lseek(int fd, off64_t offset, int whence) { 147 off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)); 148 if (rc == -1) { 149 fprintf(stderr, "lseek64 failed: %s\n", strerror(errno)); 150 return false; 151 } 152 return true; 153 } 154 155 static void allocate(size_t size, uint8_t** buffer, size_t* buffer_alloc) { 156 // if the buffer's big enough, reuse it. 157 if (size <= *buffer_alloc) return; 158 159 free(*buffer); 160 161 *buffer = (uint8_t*) malloc(size); 162 if (*buffer == NULL) { 163 fprintf(stderr, "failed to allocate %zu bytes\n", size); 164 exit(1); 165 } 166 *buffer_alloc = size; 167 } 168 169 typedef struct { 170 int fd; 171 RangeSet* tgt; 172 int p_block; 173 size_t p_remain; 174 } RangeSinkState; 175 176 static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) { 177 RangeSinkState* rss = (RangeSinkState*) token; 178 179 if (rss->p_remain <= 0) { 180 fprintf(stderr, "range sink write overrun"); 181 return 0; 182 } 183 184 ssize_t written = 0; 185 while (size > 0) { 186 size_t write_now = size; 187 188 if (rss->p_remain < write_now) { 189 write_now = rss->p_remain; 190 } 191 192 if (write_all(rss->fd, data, write_now) == -1) { 193 break; 194 } 195 196 data += write_now; 197 size -= write_now; 198 199 rss->p_remain -= write_now; 200 written += write_now; 201 202 if (rss->p_remain == 0) { 203 // move to the next block 204 ++rss->p_block; 205 if (rss->p_block < rss->tgt->count) { 206 rss->p_remain = (rss->tgt->pos[rss->p_block * 2 + 1] - 207 rss->tgt->pos[rss->p_block * 2]) * BLOCKSIZE; 208 209 if (!check_lseek(rss->fd, (off64_t)rss->tgt->pos[rss->p_block*2] * BLOCKSIZE, 210 SEEK_SET)) { 211 break; 212 } 213 } else { 214 // we can't write any more; return how many bytes have 215 // been written so far. 216 break; 217 } 218 } 219 } 220 221 return written; 222 } 223 224 // All of the data for all the 'new' transfers is contained in one 225 // file in the update package, concatenated together in the order in 226 // which transfers.list will need it. We want to stream it out of the 227 // archive (it's compressed) without writing it to a temp file, but we 228 // can't write each section until it's that transfer's turn to go. 229 // 230 // To achieve this, we expand the new data from the archive in a 231 // background thread, and block that threads 'receive uncompressed 232 // data' function until the main thread has reached a point where we 233 // want some new data to be written. We signal the background thread 234 // with the destination for the data and block the main thread, 235 // waiting for the background thread to complete writing that section. 236 // Then it signals the main thread to wake up and goes back to 237 // blocking waiting for a transfer. 238 // 239 // NewThreadInfo is the struct used to pass information back and forth 240 // between the two threads. When the main thread wants some data 241 // written, it sets rss to the destination location and signals the 242 // condition. When the background thread is done writing, it clears 243 // rss and signals the condition again. 244 245 typedef struct { 246 ZipArchive* za; 247 const ZipEntry* entry; 248 249 RangeSinkState* rss; 250 251 pthread_mutex_t mu; 252 pthread_cond_t cv; 253 } NewThreadInfo; 254 255 static bool receive_new_data(const unsigned char* data, int size, void* cookie) { 256 NewThreadInfo* nti = (NewThreadInfo*) cookie; 257 258 while (size > 0) { 259 // Wait for nti->rss to be non-NULL, indicating some of this 260 // data is wanted. 261 pthread_mutex_lock(&nti->mu); 262 while (nti->rss == NULL) { 263 pthread_cond_wait(&nti->cv, &nti->mu); 264 } 265 pthread_mutex_unlock(&nti->mu); 266 267 // At this point nti->rss is set, and we own it. The main 268 // thread is waiting for it to disappear from nti. 269 ssize_t written = RangeSinkWrite(data, size, nti->rss); 270 data += written; 271 size -= written; 272 273 if (nti->rss->p_block == nti->rss->tgt->count) { 274 // we have written all the bytes desired by this rss. 275 276 pthread_mutex_lock(&nti->mu); 277 nti->rss = NULL; 278 pthread_cond_broadcast(&nti->cv); 279 pthread_mutex_unlock(&nti->mu); 280 } 281 } 282 283 return true; 284 } 285 286 static void* unzip_new_data(void* cookie) { 287 NewThreadInfo* nti = (NewThreadInfo*) cookie; 288 mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti); 289 return NULL; 290 } 291 292 static int ReadBlocks(RangeSet* src, uint8_t* buffer, int fd) { 293 int i; 294 size_t p = 0; 295 size_t size; 296 297 if (!src || !buffer) { 298 return -1; 299 } 300 301 for (i = 0; i < src->count; ++i) { 302 if (!check_lseek(fd, (off64_t) src->pos[i * 2] * BLOCKSIZE, SEEK_SET)) { 303 return -1; 304 } 305 306 size = (src->pos[i * 2 + 1] - src->pos[i * 2]) * BLOCKSIZE; 307 308 if (read_all(fd, buffer + p, size) == -1) { 309 return -1; 310 } 311 312 p += size; 313 } 314 315 return 0; 316 } 317 318 static int WriteBlocks(RangeSet* tgt, uint8_t* buffer, int fd) { 319 int i; 320 size_t p = 0; 321 size_t size; 322 323 if (!tgt || !buffer) { 324 return -1; 325 } 326 327 for (i = 0; i < tgt->count; ++i) { 328 if (!check_lseek(fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) { 329 return -1; 330 } 331 332 size = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * BLOCKSIZE; 333 334 if (write_all(fd, buffer + p, size) == -1) { 335 return -1; 336 } 337 338 p += size; 339 } 340 341 return 0; 342 } 343 344 // Do a source/target load for move/bsdiff/imgdiff in version 1. 345 // 'wordsave' is the save_ptr of a strtok_r()-in-progress. We expect 346 // to parse the remainder of the string as: 347 // 348 // <src_range> <tgt_range> 349 // 350 // The source range is loaded into the provided buffer, reallocating 351 // it to make it larger if necessary. The target ranges are returned 352 // in *tgt, if tgt is non-NULL. 353 354 static int LoadSrcTgtVersion1(char** wordsave, RangeSet** tgt, int* src_blocks, 355 uint8_t** buffer, size_t* buffer_alloc, int fd) { 356 char* word; 357 int rc; 358 359 word = strtok_r(NULL, " ", wordsave); 360 RangeSet* src = parse_range(word); 361 362 if (tgt != NULL) { 363 word = strtok_r(NULL, " ", wordsave); 364 *tgt = parse_range(word); 365 } 366 367 allocate(src->size * BLOCKSIZE, buffer, buffer_alloc); 368 rc = ReadBlocks(src, *buffer, fd); 369 *src_blocks = src->size; 370 371 free(src); 372 return rc; 373 } 374 375 static int VerifyBlocks(const char *expected, const uint8_t *buffer, 376 size_t blocks, int printerror) { 377 char* hexdigest = NULL; 378 int rc = -1; 379 uint8_t digest[SHA_DIGEST_SIZE]; 380 381 if (!expected || !buffer) { 382 return rc; 383 } 384 385 SHA_hash(buffer, blocks * BLOCKSIZE, digest); 386 hexdigest = PrintSha1(digest); 387 388 if (hexdigest != NULL) { 389 rc = strcmp(expected, hexdigest); 390 391 if (rc != 0 && printerror) { 392 fprintf(stderr, "failed to verify blocks (expected %s, read %s)\n", 393 expected, hexdigest); 394 } 395 396 free(hexdigest); 397 } 398 399 return rc; 400 } 401 402 static char* GetStashFileName(const char* base, const char* id, const char* postfix) { 403 char* fn; 404 int len; 405 int res; 406 407 if (base == NULL) { 408 return NULL; 409 } 410 411 if (id == NULL) { 412 id = ""; 413 } 414 415 if (postfix == NULL) { 416 postfix = ""; 417 } 418 419 len = strlen(STASH_DIRECTORY_BASE) + 1 + strlen(base) + 1 + strlen(id) + strlen(postfix) + 1; 420 fn = malloc(len); 421 422 if (fn == NULL) { 423 fprintf(stderr, "failed to malloc %d bytes for fn\n", len); 424 return NULL; 425 } 426 427 res = snprintf(fn, len, STASH_DIRECTORY_BASE "/%s/%s%s", base, id, postfix); 428 429 if (res < 0 || res >= len) { 430 fprintf(stderr, "failed to format file name (return value %d)\n", res); 431 free(fn); 432 return NULL; 433 } 434 435 return fn; 436 } 437 438 typedef void (*StashCallback)(const char*, void*); 439 440 // Does a best effort enumeration of stash files. Ignores possible non-file 441 // items in the stash directory and continues despite of errors. Calls the 442 // 'callback' function for each file and passes 'data' to the function as a 443 // parameter. 444 445 static void EnumerateStash(const char* dirname, StashCallback callback, void* data) { 446 char* fn; 447 DIR* directory; 448 int len; 449 int res; 450 struct dirent* item; 451 452 if (dirname == NULL || callback == NULL) { 453 return; 454 } 455 456 directory = opendir(dirname); 457 458 if (directory == NULL) { 459 if (errno != ENOENT) { 460 fprintf(stderr, "opendir \"%s\" failed: %s\n", dirname, strerror(errno)); 461 } 462 return; 463 } 464 465 while ((item = readdir(directory)) != NULL) { 466 if (item->d_type != DT_REG) { 467 continue; 468 } 469 470 len = strlen(dirname) + 1 + strlen(item->d_name) + 1; 471 fn = malloc(len); 472 473 if (fn == NULL) { 474 fprintf(stderr, "failed to malloc %d bytes for fn\n", len); 475 continue; 476 } 477 478 res = snprintf(fn, len, "%s/%s", dirname, item->d_name); 479 480 if (res < 0 || res >= len) { 481 fprintf(stderr, "failed to format file name (return value %d)\n", res); 482 free(fn); 483 continue; 484 } 485 486 callback(fn, data); 487 free(fn); 488 } 489 490 if (closedir(directory) == -1) { 491 fprintf(stderr, "closedir \"%s\" failed: %s\n", dirname, strerror(errno)); 492 } 493 } 494 495 static void UpdateFileSize(const char* fn, void* data) { 496 int* size = (int*) data; 497 struct stat st; 498 499 if (!fn || !data) { 500 return; 501 } 502 503 if (stat(fn, &st) == -1) { 504 fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno)); 505 return; 506 } 507 508 *size += st.st_size; 509 } 510 511 // Deletes the stash directory and all files in it. Assumes that it only 512 // contains files. There is nothing we can do about unlikely, but possible 513 // errors, so they are merely logged. 514 515 static void DeleteFile(const char* fn, void* data) { 516 if (fn) { 517 fprintf(stderr, "deleting %s\n", fn); 518 519 if (unlink(fn) == -1 && errno != ENOENT) { 520 fprintf(stderr, "unlink \"%s\" failed: %s\n", fn, strerror(errno)); 521 } 522 } 523 } 524 525 static void DeletePartial(const char* fn, void* data) { 526 if (fn && strstr(fn, ".partial") != NULL) { 527 DeleteFile(fn, data); 528 } 529 } 530 531 static void DeleteStash(const char* base) { 532 char* dirname; 533 534 if (base == NULL) { 535 return; 536 } 537 538 dirname = GetStashFileName(base, NULL, NULL); 539 540 if (dirname == NULL) { 541 return; 542 } 543 544 fprintf(stderr, "deleting stash %s\n", base); 545 EnumerateStash(dirname, DeleteFile, NULL); 546 547 if (rmdir(dirname) == -1) { 548 if (errno != ENOENT && errno != ENOTDIR) { 549 fprintf(stderr, "rmdir \"%s\" failed: %s\n", dirname, strerror(errno)); 550 } 551 } 552 553 free(dirname); 554 } 555 556 static int LoadStash(const char* base, const char* id, int verify, int* blocks, uint8_t** buffer, 557 size_t* buffer_alloc, int printnoent) { 558 char *fn = NULL; 559 int blockcount = 0; 560 int fd = -1; 561 int rc = -1; 562 int res; 563 struct stat st; 564 565 if (!base || !id || !buffer || !buffer_alloc) { 566 goto lsout; 567 } 568 569 if (!blocks) { 570 blocks = &blockcount; 571 } 572 573 fn = GetStashFileName(base, id, NULL); 574 575 if (fn == NULL) { 576 goto lsout; 577 } 578 579 res = stat(fn, &st); 580 581 if (res == -1) { 582 if (errno != ENOENT || printnoent) { 583 fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno)); 584 } 585 goto lsout; 586 } 587 588 fprintf(stderr, " loading %s\n", fn); 589 590 if ((st.st_size % BLOCKSIZE) != 0) { 591 fprintf(stderr, "%s size %zd not multiple of block size %d", fn, st.st_size, BLOCKSIZE); 592 goto lsout; 593 } 594 595 fd = TEMP_FAILURE_RETRY(open(fn, O_RDONLY)); 596 597 if (fd == -1) { 598 fprintf(stderr, "open \"%s\" failed: %s\n", fn, strerror(errno)); 599 goto lsout; 600 } 601 602 allocate(st.st_size, buffer, buffer_alloc); 603 604 if (read_all(fd, *buffer, st.st_size) == -1) { 605 goto lsout; 606 } 607 608 *blocks = st.st_size / BLOCKSIZE; 609 610 if (verify && VerifyBlocks(id, *buffer, *blocks, 1) != 0) { 611 fprintf(stderr, "unexpected contents in %s\n", fn); 612 DeleteFile(fn, NULL); 613 goto lsout; 614 } 615 616 rc = 0; 617 618 lsout: 619 if (fd != -1) { 620 close(fd); 621 } 622 623 if (fn) { 624 free(fn); 625 } 626 627 return rc; 628 } 629 630 static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buffer, 631 int checkspace, int *exists) { 632 char *fn = NULL; 633 char *cn = NULL; 634 int fd = -1; 635 int rc = -1; 636 int dfd = -1; 637 int res; 638 struct stat st; 639 640 if (base == NULL || buffer == NULL) { 641 goto wsout; 642 } 643 644 if (checkspace && CacheSizeCheck(blocks * BLOCKSIZE) != 0) { 645 fprintf(stderr, "not enough space to write stash\n"); 646 goto wsout; 647 } 648 649 fn = GetStashFileName(base, id, ".partial"); 650 cn = GetStashFileName(base, id, NULL); 651 652 if (fn == NULL || cn == NULL) { 653 goto wsout; 654 } 655 656 if (exists) { 657 res = stat(cn, &st); 658 659 if (res == 0) { 660 // The file already exists and since the name is the hash of the contents, 661 // it's safe to assume the contents are identical (accidental hash collisions 662 // are unlikely) 663 fprintf(stderr, " skipping %d existing blocks in %s\n", blocks, cn); 664 *exists = 1; 665 rc = 0; 666 goto wsout; 667 } 668 669 *exists = 0; 670 } 671 672 fprintf(stderr, " writing %d blocks to %s\n", blocks, cn); 673 674 fd = TEMP_FAILURE_RETRY(open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, STASH_FILE_MODE)); 675 676 if (fd == -1) { 677 fprintf(stderr, "failed to create \"%s\": %s\n", fn, strerror(errno)); 678 goto wsout; 679 } 680 681 if (write_all(fd, buffer, blocks * BLOCKSIZE) == -1) { 682 goto wsout; 683 } 684 685 if (fsync(fd) == -1) { 686 fprintf(stderr, "fsync \"%s\" failed: %s\n", fn, strerror(errno)); 687 goto wsout; 688 } 689 690 if (rename(fn, cn) == -1) { 691 fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", fn, cn, strerror(errno)); 692 goto wsout; 693 } 694 695 const char* dname; 696 dname = dirname(cn); 697 dfd = TEMP_FAILURE_RETRY(open(dname, O_RDONLY | O_DIRECTORY)); 698 699 if (dfd == -1) { 700 fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname, strerror(errno)); 701 goto wsout; 702 } 703 704 if (fsync(dfd) == -1) { 705 fprintf(stderr, "fsync \"%s\" failed: %s\n", dname, strerror(errno)); 706 goto wsout; 707 } 708 709 rc = 0; 710 711 wsout: 712 if (fd != -1) { 713 close(fd); 714 } 715 716 if (dfd != -1) { 717 close(dfd); 718 } 719 720 if (fn) { 721 free(fn); 722 } 723 724 if (cn) { 725 free(cn); 726 } 727 728 return rc; 729 } 730 731 // Creates a directory for storing stash files and checks if the /cache partition 732 // hash enough space for the expected amount of blocks we need to store. Returns 733 // >0 if we created the directory, zero if it existed already, and <0 of failure. 734 735 static int CreateStash(State* state, int maxblocks, const char* blockdev, char** base) { 736 char* dirname = NULL; 737 const uint8_t* digest; 738 int rc = -1; 739 int res; 740 int size = 0; 741 SHA_CTX ctx; 742 struct stat st; 743 744 if (blockdev == NULL || base == NULL) { 745 goto csout; 746 } 747 748 // Stash directory should be different for each partition to avoid conflicts 749 // when updating multiple partitions at the same time, so we use the hash of 750 // the block device name as the base directory 751 SHA_init(&ctx); 752 SHA_update(&ctx, blockdev, strlen(blockdev)); 753 digest = SHA_final(&ctx); 754 *base = PrintSha1(digest); 755 756 if (*base == NULL) { 757 goto csout; 758 } 759 760 dirname = GetStashFileName(*base, NULL, NULL); 761 762 if (dirname == NULL) { 763 goto csout; 764 } 765 766 res = stat(dirname, &st); 767 768 if (res == -1 && errno != ENOENT) { 769 ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname, strerror(errno)); 770 goto csout; 771 } else if (res != 0) { 772 fprintf(stderr, "creating stash %s\n", dirname); 773 res = mkdir(dirname, STASH_DIRECTORY_MODE); 774 775 if (res != 0) { 776 ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname, strerror(errno)); 777 goto csout; 778 } 779 780 if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) { 781 ErrorAbort(state, "not enough space for stash\n"); 782 goto csout; 783 } 784 785 rc = 1; // Created directory 786 goto csout; 787 } 788 789 fprintf(stderr, "using existing stash %s\n", dirname); 790 791 // If the directory already exists, calculate the space already allocated to 792 // stash files and check if there's enough for all required blocks. Delete any 793 // partially completed stash files first. 794 795 EnumerateStash(dirname, DeletePartial, NULL); 796 EnumerateStash(dirname, UpdateFileSize, &size); 797 798 size = (maxblocks * BLOCKSIZE) - size; 799 800 if (size > 0 && CacheSizeCheck(size) != 0) { 801 ErrorAbort(state, "not enough space for stash (%d more needed)\n", size); 802 goto csout; 803 } 804 805 rc = 0; // Using existing directory 806 807 csout: 808 if (dirname) { 809 free(dirname); 810 } 811 812 return rc; 813 } 814 815 static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t* buffer_alloc, 816 int fd, int usehash, int* isunresumable) { 817 char *id = NULL; 818 int res = -1; 819 int blocks = 0; 820 821 if (!wordsave || !buffer || !buffer_alloc || !isunresumable) { 822 return -1; 823 } 824 825 id = strtok_r(NULL, " ", wordsave); 826 827 if (id == NULL) { 828 fprintf(stderr, "missing id field in stash command\n"); 829 return -1; 830 } 831 832 if (usehash && LoadStash(base, id, 1, &blocks, buffer, buffer_alloc, 0) == 0) { 833 // Stash file already exists and has expected contents. Do not 834 // read from source again, as the source may have been already 835 // overwritten during a previous attempt. 836 return 0; 837 } 838 839 if (LoadSrcTgtVersion1(wordsave, NULL, &blocks, buffer, buffer_alloc, fd) == -1) { 840 return -1; 841 } 842 843 if (usehash && VerifyBlocks(id, *buffer, blocks, 1) != 0) { 844 // Source blocks have unexpected contents. If we actually need this 845 // data later, this is an unrecoverable error. However, the command 846 // that uses the data may have already completed previously, so the 847 // possible failure will occur during source block verification. 848 fprintf(stderr, "failed to load source blocks for stash %s\n", id); 849 return 0; 850 } 851 852 fprintf(stderr, "stashing %d blocks to %s\n", blocks, id); 853 return WriteStash(base, id, blocks, *buffer, 0, NULL); 854 } 855 856 static int FreeStash(const char* base, const char* id) { 857 char *fn = NULL; 858 859 if (base == NULL || id == NULL) { 860 return -1; 861 } 862 863 fn = GetStashFileName(base, id, NULL); 864 865 if (fn == NULL) { 866 return -1; 867 } 868 869 DeleteFile(fn, NULL); 870 free(fn); 871 872 return 0; 873 } 874 875 static void MoveRange(uint8_t* dest, RangeSet* locs, const uint8_t* source) { 876 // source contains packed data, which we want to move to the 877 // locations given in *locs in the dest buffer. source and dest 878 // may be the same buffer. 879 880 int start = locs->size; 881 int i; 882 for (i = locs->count-1; i >= 0; --i) { 883 int blocks = locs->pos[i*2+1] - locs->pos[i*2]; 884 start -= blocks; 885 memmove(dest + (locs->pos[i*2] * BLOCKSIZE), source + (start * BLOCKSIZE), 886 blocks * BLOCKSIZE); 887 } 888 } 889 890 // Do a source/target load for move/bsdiff/imgdiff in version 2. 891 // 'wordsave' is the save_ptr of a strtok_r()-in-progress. We expect 892 // to parse the remainder of the string as one of: 893 // 894 // <tgt_range> <src_block_count> <src_range> 895 // (loads data from source image only) 896 // 897 // <tgt_range> <src_block_count> - <[stash_id:stash_range] ...> 898 // (loads data from stashes only) 899 // 900 // <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> 901 // (loads data from both source image and stashes) 902 // 903 // On return, buffer is filled with the loaded source data (rearranged 904 // and combined with stashed data as necessary). buffer may be 905 // reallocated if needed to accommodate the source data. *tgt is the 906 // target RangeSet. Any stashes required are loaded using LoadStash. 907 908 static int LoadSrcTgtVersion2(char** wordsave, RangeSet** tgt, int* src_blocks, 909 uint8_t** buffer, size_t* buffer_alloc, int fd, 910 const char* stashbase, int* overlap) { 911 char* word; 912 char* colonsave; 913 char* colon; 914 int id; 915 int res; 916 RangeSet* locs; 917 size_t stashalloc = 0; 918 uint8_t* stash = NULL; 919 920 if (tgt != NULL) { 921 word = strtok_r(NULL, " ", wordsave); 922 *tgt = parse_range(word); 923 } 924 925 word = strtok_r(NULL, " ", wordsave); 926 *src_blocks = strtol(word, NULL, 0); 927 928 allocate(*src_blocks * BLOCKSIZE, buffer, buffer_alloc); 929 930 word = strtok_r(NULL, " ", wordsave); 931 if (word[0] == '-' && word[1] == '\0') { 932 // no source ranges, only stashes 933 } else { 934 RangeSet* src = parse_range(word); 935 res = ReadBlocks(src, *buffer, fd); 936 937 if (overlap && tgt) { 938 *overlap = range_overlaps(src, *tgt); 939 } 940 941 free(src); 942 943 if (res == -1) { 944 return -1; 945 } 946 947 word = strtok_r(NULL, " ", wordsave); 948 if (word == NULL) { 949 // no stashes, only source range 950 return 0; 951 } 952 953 locs = parse_range(word); 954 MoveRange(*buffer, locs, *buffer); 955 free(locs); 956 } 957 958 while ((word = strtok_r(NULL, " ", wordsave)) != NULL) { 959 // Each word is a an index into the stash table, a colon, and 960 // then a rangeset describing where in the source block that 961 // stashed data should go. 962 colonsave = NULL; 963 colon = strtok_r(word, ":", &colonsave); 964 965 res = LoadStash(stashbase, colon, 0, NULL, &stash, &stashalloc, 1); 966 967 if (res == -1) { 968 // These source blocks will fail verification if used later, but we 969 // will let the caller decide if this is a fatal failure 970 fprintf(stderr, "failed to load stash %s\n", colon); 971 continue; 972 } 973 974 colon = strtok_r(NULL, ":", &colonsave); 975 locs = parse_range(colon); 976 977 MoveRange(*buffer, locs, stash); 978 free(locs); 979 } 980 981 if (stash) { 982 free(stash); 983 } 984 985 return 0; 986 } 987 988 // Parameters for transfer list command functions 989 typedef struct { 990 char* cmdname; 991 char* cpos; 992 char* freestash; 993 char* stashbase; 994 int canwrite; 995 int createdstash; 996 int fd; 997 int foundwrites; 998 int isunresumable; 999 int version; 1000 int written; 1001 NewThreadInfo nti; 1002 pthread_t thread; 1003 size_t bufsize; 1004 uint8_t* buffer; 1005 uint8_t* patch_start; 1006 } CommandParameters; 1007 1008 // Do a source/target load for move/bsdiff/imgdiff in version 3. 1009 // 1010 // Parameters are the same as for LoadSrcTgtVersion2, except for 'onehash', which 1011 // tells the function whether to expect separate source and targe block hashes, or 1012 // if they are both the same and only one hash should be expected, and 1013 // 'isunresumable', which receives a non-zero value if block verification fails in 1014 // a way that the update cannot be resumed anymore. 1015 // 1016 // If the function is unable to load the necessary blocks or their contents don't 1017 // match the hashes, the return value is -1 and the command should be aborted. 1018 // 1019 // If the return value is 1, the command has already been completed according to 1020 // the contents of the target blocks, and should not be performed again. 1021 // 1022 // If the return value is 0, source blocks have expected content and the command 1023 // can be performed. 1024 1025 static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* src_blocks, 1026 int onehash, int* overlap) { 1027 char* srchash = NULL; 1028 char* tgthash = NULL; 1029 int stash_exists = 0; 1030 int overlap_blocks = 0; 1031 int rc = -1; 1032 uint8_t* tgtbuffer = NULL; 1033 1034 if (!params|| !tgt || !src_blocks || !overlap) { 1035 goto v3out; 1036 } 1037 1038 srchash = strtok_r(NULL, " ", ¶ms->cpos); 1039 1040 if (srchash == NULL) { 1041 fprintf(stderr, "missing source hash\n"); 1042 goto v3out; 1043 } 1044 1045 if (onehash) { 1046 tgthash = srchash; 1047 } else { 1048 tgthash = strtok_r(NULL, " ", ¶ms->cpos); 1049 1050 if (tgthash == NULL) { 1051 fprintf(stderr, "missing target hash\n"); 1052 goto v3out; 1053 } 1054 } 1055 1056 if (LoadSrcTgtVersion2(¶ms->cpos, tgt, src_blocks, ¶ms->buffer, ¶ms->bufsize, 1057 params->fd, params->stashbase, overlap) == -1) { 1058 goto v3out; 1059 } 1060 1061 tgtbuffer = (uint8_t*) malloc((*tgt)->size * BLOCKSIZE); 1062 1063 if (tgtbuffer == NULL) { 1064 fprintf(stderr, "failed to allocate %d bytes\n", (*tgt)->size * BLOCKSIZE); 1065 goto v3out; 1066 } 1067 1068 if (ReadBlocks(*tgt, tgtbuffer, params->fd) == -1) { 1069 goto v3out; 1070 } 1071 1072 if (VerifyBlocks(tgthash, tgtbuffer, (*tgt)->size, 0) == 0) { 1073 // Target blocks already have expected content, command should be skipped 1074 rc = 1; 1075 goto v3out; 1076 } 1077 1078 if (VerifyBlocks(srchash, params->buffer, *src_blocks, 1) == 0) { 1079 // If source and target blocks overlap, stash the source blocks so we can 1080 // resume from possible write errors 1081 if (*overlap) { 1082 fprintf(stderr, "stashing %d overlapping blocks to %s\n", *src_blocks, 1083 srchash); 1084 1085 if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, 1, 1086 &stash_exists) != 0) { 1087 fprintf(stderr, "failed to stash overlapping source blocks\n"); 1088 goto v3out; 1089 } 1090 1091 // Can be deleted when the write has completed 1092 if (!stash_exists) { 1093 params->freestash = srchash; 1094 } 1095 } 1096 1097 // Source blocks have expected content, command can proceed 1098 rc = 0; 1099 goto v3out; 1100 } 1101 1102 if (*overlap && LoadStash(params->stashbase, srchash, 1, NULL, ¶ms->buffer, 1103 ¶ms->bufsize, 1) == 0) { 1104 // Overlapping source blocks were previously stashed, command can proceed. 1105 // We are recovering from an interrupted command, so we don't know if the 1106 // stash can safely be deleted after this command. 1107 rc = 0; 1108 goto v3out; 1109 } 1110 1111 // Valid source data not available, update cannot be resumed 1112 fprintf(stderr, "partition has unexpected contents\n"); 1113 params->isunresumable = 1; 1114 1115 v3out: 1116 if (tgtbuffer) { 1117 free(tgtbuffer); 1118 } 1119 1120 return rc; 1121 } 1122 1123 static int PerformCommandMove(CommandParameters* params) { 1124 int blocks = 0; 1125 int overlap = 0; 1126 int rc = -1; 1127 int status = 0; 1128 RangeSet* tgt = NULL; 1129 1130 if (!params) { 1131 goto pcmout; 1132 } 1133 1134 if (params->version == 1) { 1135 status = LoadSrcTgtVersion1(¶ms->cpos, &tgt, &blocks, ¶ms->buffer, 1136 ¶ms->bufsize, params->fd); 1137 } else if (params->version == 2) { 1138 status = LoadSrcTgtVersion2(¶ms->cpos, &tgt, &blocks, ¶ms->buffer, 1139 ¶ms->bufsize, params->fd, params->stashbase, NULL); 1140 } else if (params->version >= 3) { 1141 status = LoadSrcTgtVersion3(params, &tgt, &blocks, 1, &overlap); 1142 } 1143 1144 if (status == -1) { 1145 fprintf(stderr, "failed to read blocks for move\n"); 1146 goto pcmout; 1147 } 1148 1149 if (status == 0) { 1150 params->foundwrites = 1; 1151 } else if (params->foundwrites) { 1152 fprintf(stderr, "warning: commands executed out of order [%s]\n", params->cmdname); 1153 } 1154 1155 if (params->canwrite) { 1156 if (status == 0) { 1157 fprintf(stderr, " moving %d blocks\n", blocks); 1158 1159 if (WriteBlocks(tgt, params->buffer, params->fd) == -1) { 1160 goto pcmout; 1161 } 1162 } else { 1163 fprintf(stderr, "skipping %d already moved blocks\n", blocks); 1164 } 1165 1166 } 1167 1168 if (params->freestash) { 1169 FreeStash(params->stashbase, params->freestash); 1170 params->freestash = NULL; 1171 } 1172 1173 params->written += tgt->size; 1174 rc = 0; 1175 1176 pcmout: 1177 if (tgt) { 1178 free(tgt); 1179 } 1180 1181 return rc; 1182 } 1183 1184 static int PerformCommandStash(CommandParameters* params) { 1185 if (!params) { 1186 return -1; 1187 } 1188 1189 return SaveStash(params->stashbase, ¶ms->cpos, ¶ms->buffer, ¶ms->bufsize, 1190 params->fd, (params->version >= 3), ¶ms->isunresumable); 1191 } 1192 1193 static int PerformCommandFree(CommandParameters* params) { 1194 if (!params) { 1195 return -1; 1196 } 1197 1198 if (params->createdstash || params->canwrite) { 1199 return FreeStash(params->stashbase, params->cpos); 1200 } 1201 1202 return 0; 1203 } 1204 1205 static int PerformCommandZero(CommandParameters* params) { 1206 char* range = NULL; 1207 int i; 1208 int j; 1209 int rc = -1; 1210 RangeSet* tgt = NULL; 1211 1212 if (!params) { 1213 goto pczout; 1214 } 1215 1216 range = strtok_r(NULL, " ", ¶ms->cpos); 1217 1218 if (range == NULL) { 1219 fprintf(stderr, "missing target blocks for zero\n"); 1220 goto pczout; 1221 } 1222 1223 tgt = parse_range(range); 1224 1225 fprintf(stderr, " zeroing %d blocks\n", tgt->size); 1226 1227 allocate(BLOCKSIZE, ¶ms->buffer, ¶ms->bufsize); 1228 memset(params->buffer, 0, BLOCKSIZE); 1229 1230 if (params->canwrite) { 1231 for (i = 0; i < tgt->count; ++i) { 1232 if (!check_lseek(params->fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) { 1233 goto pczout; 1234 } 1235 1236 for (j = tgt->pos[i * 2]; j < tgt->pos[i * 2 + 1]; ++j) { 1237 if (write_all(params->fd, params->buffer, BLOCKSIZE) == -1) { 1238 goto pczout; 1239 } 1240 } 1241 } 1242 } 1243 1244 if (params->cmdname[0] == 'z') { 1245 // Update only for the zero command, as the erase command will call 1246 // this if DEBUG_ERASE is defined. 1247 params->written += tgt->size; 1248 } 1249 1250 rc = 0; 1251 1252 pczout: 1253 if (tgt) { 1254 free(tgt); 1255 } 1256 1257 return rc; 1258 } 1259 1260 static int PerformCommandNew(CommandParameters* params) { 1261 char* range = NULL; 1262 int rc = -1; 1263 RangeSet* tgt = NULL; 1264 RangeSinkState rss; 1265 1266 if (!params) { 1267 goto pcnout; 1268 } 1269 1270 range = strtok_r(NULL, " ", ¶ms->cpos); 1271 1272 if (range == NULL) { 1273 goto pcnout; 1274 } 1275 1276 tgt = parse_range(range); 1277 1278 if (params->canwrite) { 1279 fprintf(stderr, " writing %d blocks of new data\n", tgt->size); 1280 1281 rss.fd = params->fd; 1282 rss.tgt = tgt; 1283 rss.p_block = 0; 1284 rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE; 1285 1286 if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) { 1287 goto pcnout; 1288 } 1289 1290 pthread_mutex_lock(¶ms->nti.mu); 1291 params->nti.rss = &rss; 1292 pthread_cond_broadcast(¶ms->nti.cv); 1293 1294 while (params->nti.rss) { 1295 pthread_cond_wait(¶ms->nti.cv, ¶ms->nti.mu); 1296 } 1297 1298 pthread_mutex_unlock(¶ms->nti.mu); 1299 } 1300 1301 params->written += tgt->size; 1302 rc = 0; 1303 1304 pcnout: 1305 if (tgt) { 1306 free(tgt); 1307 } 1308 1309 return rc; 1310 } 1311 1312 static int PerformCommandDiff(CommandParameters* params) { 1313 char* logparams = NULL; 1314 char* value = NULL; 1315 int blocks = 0; 1316 int overlap = 0; 1317 int rc = -1; 1318 int status = 0; 1319 RangeSet* tgt = NULL; 1320 RangeSinkState rss; 1321 size_t len = 0; 1322 size_t offset = 0; 1323 Value patch_value; 1324 1325 if (!params) { 1326 goto pcdout; 1327 } 1328 1329 logparams = strdup(params->cpos); 1330 value = strtok_r(NULL, " ", ¶ms->cpos); 1331 1332 if (value == NULL) { 1333 fprintf(stderr, "missing patch offset for %s\n", params->cmdname); 1334 goto pcdout; 1335 } 1336 1337 offset = strtoul(value, NULL, 0); 1338 1339 value = strtok_r(NULL, " ", ¶ms->cpos); 1340 1341 if (value == NULL) { 1342 fprintf(stderr, "missing patch length for %s\n", params->cmdname); 1343 goto pcdout; 1344 } 1345 1346 len = strtoul(value, NULL, 0); 1347 1348 if (params->version == 1) { 1349 status = LoadSrcTgtVersion1(¶ms->cpos, &tgt, &blocks, ¶ms->buffer, 1350 ¶ms->bufsize, params->fd); 1351 } else if (params->version == 2) { 1352 status = LoadSrcTgtVersion2(¶ms->cpos, &tgt, &blocks, ¶ms->buffer, 1353 ¶ms->bufsize, params->fd, params->stashbase, NULL); 1354 } else if (params->version >= 3) { 1355 status = LoadSrcTgtVersion3(params, &tgt, &blocks, 0, &overlap); 1356 } 1357 1358 if (status == -1) { 1359 fprintf(stderr, "failed to read blocks for diff\n"); 1360 goto pcdout; 1361 } 1362 1363 if (status == 0) { 1364 params->foundwrites = 1; 1365 } else if (params->foundwrites) { 1366 fprintf(stderr, "warning: commands executed out of order [%s]\n", params->cmdname); 1367 } 1368 1369 if (params->canwrite) { 1370 if (status == 0) { 1371 fprintf(stderr, "patching %d blocks to %d\n", blocks, tgt->size); 1372 1373 patch_value.type = VAL_BLOB; 1374 patch_value.size = len; 1375 patch_value.data = (char*) (params->patch_start + offset); 1376 1377 rss.fd = params->fd; 1378 rss.tgt = tgt; 1379 rss.p_block = 0; 1380 rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE; 1381 1382 if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) { 1383 goto pcdout; 1384 } 1385 1386 if (params->cmdname[0] == 'i') { // imgdiff 1387 ApplyImagePatch(params->buffer, blocks * BLOCKSIZE, &patch_value, 1388 &RangeSinkWrite, &rss, NULL, NULL); 1389 } else { 1390 ApplyBSDiffPatch(params->buffer, blocks * BLOCKSIZE, &patch_value, 1391 0, &RangeSinkWrite, &rss, NULL); 1392 } 1393 1394 // We expect the output of the patcher to fill the tgt ranges exactly. 1395 if (rss.p_block != tgt->count || rss.p_remain != 0) { 1396 fprintf(stderr, "range sink underrun?\n"); 1397 } 1398 } else { 1399 fprintf(stderr, "skipping %d blocks already patched to %d [%s]\n", 1400 blocks, tgt->size, logparams); 1401 } 1402 } 1403 1404 if (params->freestash) { 1405 FreeStash(params->stashbase, params->freestash); 1406 params->freestash = NULL; 1407 } 1408 1409 params->written += tgt->size; 1410 rc = 0; 1411 1412 pcdout: 1413 if (logparams) { 1414 free(logparams); 1415 } 1416 1417 if (tgt) { 1418 free(tgt); 1419 } 1420 1421 return rc; 1422 } 1423 1424 static int PerformCommandErase(CommandParameters* params) { 1425 char* range = NULL; 1426 int i; 1427 int rc = -1; 1428 RangeSet* tgt = NULL; 1429 struct stat st; 1430 uint64_t blocks[2]; 1431 1432 if (DEBUG_ERASE) { 1433 return PerformCommandZero(params); 1434 } 1435 1436 if (!params) { 1437 goto pceout; 1438 } 1439 1440 if (fstat(params->fd, &st) == -1) { 1441 fprintf(stderr, "failed to fstat device to erase: %s\n", strerror(errno)); 1442 goto pceout; 1443 } 1444 1445 if (!S_ISBLK(st.st_mode)) { 1446 fprintf(stderr, "not a block device; skipping erase\n"); 1447 goto pceout; 1448 } 1449 1450 range = strtok_r(NULL, " ", ¶ms->cpos); 1451 1452 if (range == NULL) { 1453 fprintf(stderr, "missing target blocks for zero\n"); 1454 goto pceout; 1455 } 1456 1457 tgt = parse_range(range); 1458 1459 if (params->canwrite) { 1460 fprintf(stderr, " erasing %d blocks\n", tgt->size); 1461 1462 for (i = 0; i < tgt->count; ++i) { 1463 // offset in bytes 1464 blocks[0] = tgt->pos[i * 2] * (uint64_t) BLOCKSIZE; 1465 // length in bytes 1466 blocks[1] = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * (uint64_t) BLOCKSIZE; 1467 1468 if (ioctl(params->fd, BLKDISCARD, &blocks) == -1) { 1469 fprintf(stderr, "BLKDISCARD ioctl failed: %s\n", strerror(errno)); 1470 goto pceout; 1471 } 1472 } 1473 } 1474 1475 rc = 0; 1476 1477 pceout: 1478 if (tgt) { 1479 free(tgt); 1480 } 1481 1482 return rc; 1483 } 1484 1485 // Definitions for transfer list command functions 1486 typedef int (*CommandFunction)(CommandParameters*); 1487 1488 typedef struct { 1489 const char* name; 1490 CommandFunction f; 1491 } Command; 1492 1493 // CompareCommands and CompareCommandNames are for the hash table 1494 1495 static int CompareCommands(const void* c1, const void* c2) { 1496 return strcmp(((const Command*) c1)->name, ((const Command*) c2)->name); 1497 } 1498 1499 static int CompareCommandNames(const void* c1, const void* c2) { 1500 return strcmp(((const Command*) c1)->name, (const char*) c2); 1501 } 1502 1503 // HashString is used to hash command names for the hash table 1504 1505 static unsigned int HashString(const char *s) { 1506 unsigned int hash = 0; 1507 if (s) { 1508 while (*s) { 1509 hash = hash * 33 + *s++; 1510 } 1511 } 1512 return hash; 1513 } 1514 1515 // args: 1516 // - block device (or file) to modify in-place 1517 // - transfer list (blob) 1518 // - new data stream (filename within package.zip) 1519 // - patch stream (filename within package.zip, must be uncompressed) 1520 1521 static Value* PerformBlockImageUpdate(const char* name, State* state, int argc, Expr* argv[], 1522 const Command* commands, int cmdcount, int dryrun) { 1523 1524 char* line = NULL; 1525 char* linesave = NULL; 1526 char* logcmd = NULL; 1527 char* transfer_list = NULL; 1528 CommandParameters params; 1529 const Command* cmd = NULL; 1530 const ZipEntry* new_entry = NULL; 1531 const ZipEntry* patch_entry = NULL; 1532 FILE* cmd_pipe = NULL; 1533 HashTable* cmdht = NULL; 1534 int i; 1535 int res; 1536 int rc = -1; 1537 int stash_max_blocks = 0; 1538 int total_blocks = 0; 1539 pthread_attr_t attr; 1540 unsigned int cmdhash; 1541 UpdaterInfo* ui = NULL; 1542 Value* blockdev_filename = NULL; 1543 Value* new_data_fn = NULL; 1544 Value* patch_data_fn = NULL; 1545 Value* transfer_list_value = NULL; 1546 ZipArchive* za = NULL; 1547 1548 memset(¶ms, 0, sizeof(params)); 1549 params.canwrite = !dryrun; 1550 1551 fprintf(stderr, "performing %s\n", dryrun ? "verification" : "update"); 1552 1553 if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value, 1554 &new_data_fn, &patch_data_fn) < 0) { 1555 goto pbiudone; 1556 } 1557 1558 if (blockdev_filename->type != VAL_STRING) { 1559 ErrorAbort(state, "blockdev_filename argument to %s must be string", name); 1560 goto pbiudone; 1561 } 1562 if (transfer_list_value->type != VAL_BLOB) { 1563 ErrorAbort(state, "transfer_list argument to %s must be blob", name); 1564 goto pbiudone; 1565 } 1566 if (new_data_fn->type != VAL_STRING) { 1567 ErrorAbort(state, "new_data_fn argument to %s must be string", name); 1568 goto pbiudone; 1569 } 1570 if (patch_data_fn->type != VAL_STRING) { 1571 ErrorAbort(state, "patch_data_fn argument to %s must be string", name); 1572 goto pbiudone; 1573 } 1574 1575 ui = (UpdaterInfo*) state->cookie; 1576 1577 if (ui == NULL) { 1578 goto pbiudone; 1579 } 1580 1581 cmd_pipe = ui->cmd_pipe; 1582 za = ui->package_zip; 1583 1584 if (cmd_pipe == NULL || za == NULL) { 1585 goto pbiudone; 1586 } 1587 1588 patch_entry = mzFindZipEntry(za, patch_data_fn->data); 1589 1590 if (patch_entry == NULL) { 1591 fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data); 1592 goto pbiudone; 1593 } 1594 1595 params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry); 1596 new_entry = mzFindZipEntry(za, new_data_fn->data); 1597 1598 if (new_entry == NULL) { 1599 fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data); 1600 goto pbiudone; 1601 } 1602 1603 params.fd = TEMP_FAILURE_RETRY(open(blockdev_filename->data, O_RDWR)); 1604 1605 if (params.fd == -1) { 1606 fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data, strerror(errno)); 1607 goto pbiudone; 1608 } 1609 1610 if (params.canwrite) { 1611 params.nti.za = za; 1612 params.nti.entry = new_entry; 1613 1614 pthread_mutex_init(¶ms.nti.mu, NULL); 1615 pthread_cond_init(¶ms.nti.cv, NULL); 1616 pthread_attr_init(&attr); 1617 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1618 1619 int error = pthread_create(¶ms.thread, &attr, unzip_new_data, ¶ms.nti); 1620 if (error != 0) { 1621 fprintf(stderr, "pthread_create failed: %s\n", strerror(error)); 1622 goto pbiudone; 1623 } 1624 } 1625 1626 // The data in transfer_list_value is not necessarily null-terminated, so we need 1627 // to copy it to a new buffer and add the null that strtok_r will need. 1628 transfer_list = malloc(transfer_list_value->size + 1); 1629 1630 if (transfer_list == NULL) { 1631 fprintf(stderr, "failed to allocate %zd bytes for transfer list\n", 1632 transfer_list_value->size + 1); 1633 goto pbiudone; 1634 } 1635 1636 memcpy(transfer_list, transfer_list_value->data, transfer_list_value->size); 1637 transfer_list[transfer_list_value->size] = '\0'; 1638 1639 // First line in transfer list is the version number 1640 line = strtok_r(transfer_list, "\n", &linesave); 1641 params.version = strtol(line, NULL, 0); 1642 1643 if (params.version < 1 || params.version > 3) { 1644 fprintf(stderr, "unexpected transfer list version [%s]\n", line); 1645 goto pbiudone; 1646 } 1647 1648 fprintf(stderr, "blockimg version is %d\n", params.version); 1649 1650 // Second line in transfer list is the total number of blocks we expect to write 1651 line = strtok_r(NULL, "\n", &linesave); 1652 total_blocks = strtol(line, NULL, 0); 1653 1654 if (total_blocks < 0) { 1655 ErrorAbort(state, "unexpected block count [%s]\n", line); 1656 goto pbiudone; 1657 } else if (total_blocks == 0) { 1658 rc = 0; 1659 goto pbiudone; 1660 } 1661 1662 if (params.version >= 2) { 1663 // Third line is how many stash entries are needed simultaneously 1664 line = strtok_r(NULL, "\n", &linesave); 1665 fprintf(stderr, "maximum stash entries %s\n", line); 1666 1667 // Fourth line is the maximum number of blocks that will be stashed simultaneously 1668 line = strtok_r(NULL, "\n", &linesave); 1669 stash_max_blocks = strtol(line, NULL, 0); 1670 1671 if (stash_max_blocks < 0) { 1672 ErrorAbort(state, "unexpected maximum stash blocks [%s]\n", line); 1673 goto pbiudone; 1674 } 1675 1676 if (stash_max_blocks >= 0) { 1677 res = CreateStash(state, stash_max_blocks, blockdev_filename->data, 1678 ¶ms.stashbase); 1679 1680 if (res == -1) { 1681 goto pbiudone; 1682 } 1683 1684 params.createdstash = res; 1685 } 1686 } 1687 1688 // Build a hash table of the available commands 1689 cmdht = mzHashTableCreate(cmdcount, NULL); 1690 1691 for (i = 0; i < cmdcount; ++i) { 1692 cmdhash = HashString(commands[i].name); 1693 mzHashTableLookup(cmdht, cmdhash, (void*) &commands[i], CompareCommands, true); 1694 } 1695 1696 // Subsequent lines are all individual transfer commands 1697 for (line = strtok_r(NULL, "\n", &linesave); line; 1698 line = strtok_r(NULL, "\n", &linesave)) { 1699 1700 logcmd = strdup(line); 1701 params.cmdname = strtok_r(line, " ", ¶ms.cpos); 1702 1703 if (params.cmdname == NULL) { 1704 fprintf(stderr, "missing command [%s]\n", line); 1705 goto pbiudone; 1706 } 1707 1708 cmdhash = HashString(params.cmdname); 1709 cmd = (const Command*) mzHashTableLookup(cmdht, cmdhash, params.cmdname, 1710 CompareCommandNames, false); 1711 1712 if (cmd == NULL) { 1713 fprintf(stderr, "unexpected command [%s]\n", params.cmdname); 1714 goto pbiudone; 1715 } 1716 1717 if (cmd->f != NULL && cmd->f(¶ms) == -1) { 1718 fprintf(stderr, "failed to execute command [%s]\n", 1719 logcmd ? logcmd : params.cmdname); 1720 goto pbiudone; 1721 } 1722 1723 if (logcmd) { 1724 free(logcmd); 1725 logcmd = NULL; 1726 } 1727 1728 if (params.canwrite) { 1729 fprintf(cmd_pipe, "set_progress %.4f\n", (double) params.written / total_blocks); 1730 fflush(cmd_pipe); 1731 } 1732 } 1733 1734 if (params.canwrite) { 1735 pthread_join(params.thread, NULL); 1736 1737 fprintf(stderr, "wrote %d blocks; expected %d\n", params.written, total_blocks); 1738 fprintf(stderr, "max alloc needed was %zu\n", params.bufsize); 1739 1740 // Delete stash only after successfully completing the update, as it 1741 // may contain blocks needed to complete the update later. 1742 DeleteStash(params.stashbase); 1743 } else { 1744 fprintf(stderr, "verified partition contents; update may be resumed\n"); 1745 } 1746 1747 rc = 0; 1748 1749 pbiudone: 1750 if (params.fd != -1) { 1751 if (fsync(params.fd) == -1) { 1752 fprintf(stderr, "fsync failed: %s\n", strerror(errno)); 1753 } 1754 close(params.fd); 1755 } 1756 1757 if (logcmd) { 1758 free(logcmd); 1759 } 1760 1761 if (cmdht) { 1762 mzHashTableFree(cmdht); 1763 } 1764 1765 if (params.buffer) { 1766 free(params.buffer); 1767 } 1768 1769 if (transfer_list) { 1770 free(transfer_list); 1771 } 1772 1773 if (blockdev_filename) { 1774 FreeValue(blockdev_filename); 1775 } 1776 1777 if (transfer_list_value) { 1778 FreeValue(transfer_list_value); 1779 } 1780 1781 if (new_data_fn) { 1782 FreeValue(new_data_fn); 1783 } 1784 1785 if (patch_data_fn) { 1786 FreeValue(patch_data_fn); 1787 } 1788 1789 // Only delete the stash if the update cannot be resumed, or it's 1790 // a verification run and we created the stash. 1791 if (params.isunresumable || (!params.canwrite && params.createdstash)) { 1792 DeleteStash(params.stashbase); 1793 } 1794 1795 if (params.stashbase) { 1796 free(params.stashbase); 1797 } 1798 1799 return StringValue(rc == 0 ? strdup("t") : strdup("")); 1800 } 1801 1802 // The transfer list is a text file containing commands to 1803 // transfer data from one place to another on the target 1804 // partition. We parse it and execute the commands in order: 1805 // 1806 // zero [rangeset] 1807 // - fill the indicated blocks with zeros 1808 // 1809 // new [rangeset] 1810 // - fill the blocks with data read from the new_data file 1811 // 1812 // erase [rangeset] 1813 // - mark the given blocks as empty 1814 // 1815 // move <...> 1816 // bsdiff <patchstart> <patchlen> <...> 1817 // imgdiff <patchstart> <patchlen> <...> 1818 // - read the source blocks, apply a patch (or not in the 1819 // case of move), write result to target blocks. bsdiff or 1820 // imgdiff specifies the type of patch; move means no patch 1821 // at all. 1822 // 1823 // The format of <...> differs between versions 1 and 2; 1824 // see the LoadSrcTgtVersion{1,2}() functions for a 1825 // description of what's expected. 1826 // 1827 // stash <stash_id> <src_range> 1828 // - (version 2+ only) load the given source range and stash 1829 // the data in the given slot of the stash table. 1830 // 1831 // The creator of the transfer list will guarantee that no block 1832 // is read (ie, used as the source for a patch or move) after it 1833 // has been written. 1834 // 1835 // In version 2, the creator will guarantee that a given stash is 1836 // loaded (with a stash command) before it's used in a 1837 // move/bsdiff/imgdiff command. 1838 // 1839 // Within one command the source and target ranges may overlap so 1840 // in general we need to read the entire source into memory before 1841 // writing anything to the target blocks. 1842 // 1843 // All the patch data is concatenated into one patch_data file in 1844 // the update package. It must be stored uncompressed because we 1845 // memory-map it in directly from the archive. (Since patches are 1846 // already compressed, we lose very little by not compressing 1847 // their concatenation.) 1848 // 1849 // In version 3, commands that read data from the partition (i.e. 1850 // move/bsdiff/imgdiff/stash) have one or more additional hashes 1851 // before the range parameters, which are used to check if the 1852 // command has already been completed and verify the integrity of 1853 // the source data. 1854 1855 Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[]) { 1856 // Commands which are not tested are set to NULL to skip them completely 1857 const Command commands[] = { 1858 { "bsdiff", PerformCommandDiff }, 1859 { "erase", NULL }, 1860 { "free", PerformCommandFree }, 1861 { "imgdiff", PerformCommandDiff }, 1862 { "move", PerformCommandMove }, 1863 { "new", NULL }, 1864 { "stash", PerformCommandStash }, 1865 { "zero", NULL } 1866 }; 1867 1868 // Perform a dry run without writing to test if an update can proceed 1869 return PerformBlockImageUpdate(name, state, argc, argv, commands, 1870 sizeof(commands) / sizeof(commands[0]), 1); 1871 } 1872 1873 Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) { 1874 const Command commands[] = { 1875 { "bsdiff", PerformCommandDiff }, 1876 { "erase", PerformCommandErase }, 1877 { "free", PerformCommandFree }, 1878 { "imgdiff", PerformCommandDiff }, 1879 { "move", PerformCommandMove }, 1880 { "new", PerformCommandNew }, 1881 { "stash", PerformCommandStash }, 1882 { "zero", PerformCommandZero } 1883 }; 1884 1885 return PerformBlockImageUpdate(name, state, argc, argv, commands, 1886 sizeof(commands) / sizeof(commands[0]), 0); 1887 } 1888 1889 Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) { 1890 Value* blockdev_filename; 1891 Value* ranges; 1892 const uint8_t* digest = NULL; 1893 if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) { 1894 return NULL; 1895 } 1896 1897 if (blockdev_filename->type != VAL_STRING) { 1898 ErrorAbort(state, "blockdev_filename argument to %s must be string", name); 1899 goto done; 1900 } 1901 if (ranges->type != VAL_STRING) { 1902 ErrorAbort(state, "ranges argument to %s must be string", name); 1903 goto done; 1904 } 1905 1906 int fd = open(blockdev_filename->data, O_RDWR); 1907 if (fd < 0) { 1908 ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno)); 1909 goto done; 1910 } 1911 1912 RangeSet* rs = parse_range(ranges->data); 1913 uint8_t buffer[BLOCKSIZE]; 1914 1915 SHA_CTX ctx; 1916 SHA_init(&ctx); 1917 1918 int i, j; 1919 for (i = 0; i < rs->count; ++i) { 1920 if (!check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET)) { 1921 ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data, 1922 strerror(errno)); 1923 goto done; 1924 } 1925 1926 for (j = rs->pos[i*2]; j < rs->pos[i*2+1]; ++j) { 1927 if (read_all(fd, buffer, BLOCKSIZE) == -1) { 1928 ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data, 1929 strerror(errno)); 1930 goto done; 1931 } 1932 1933 SHA_update(&ctx, buffer, BLOCKSIZE); 1934 } 1935 } 1936 digest = SHA_final(&ctx); 1937 close(fd); 1938 1939 done: 1940 FreeValue(blockdev_filename); 1941 FreeValue(ranges); 1942 if (digest == NULL) { 1943 return StringValue(strdup("")); 1944 } else { 1945 return StringValue(PrintSha1(digest)); 1946 } 1947 } 1948 1949 void RegisterBlockImageFunctions() { 1950 RegisterFunction("block_image_verify", BlockImageVerifyFn); 1951 RegisterFunction("block_image_update", BlockImageUpdateFn); 1952 RegisterFunction("range_sha1", RangeSha1Fn); 1953 } 1954