1 /* 2 * Copyright (C) 2009 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 <stdarg.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/mount.h> 24 #include <sys/stat.h> 25 #include <sys/types.h> 26 #include <sys/wait.h> 27 #include <unistd.h> 28 #include <fcntl.h> 29 #include <time.h> 30 31 #include "cutils/misc.h" 32 #include "cutils/properties.h" 33 #include "edify/expr.h" 34 #include "mincrypt/sha.h" 35 #include "minzip/DirUtil.h" 36 #include "mtdutils/mounts.h" 37 #include "mtdutils/mtdutils.h" 38 #include "updater.h" 39 #include "applypatch/applypatch.h" 40 41 #ifdef USE_EXT4 42 #include "make_ext4fs.h" 43 #endif 44 45 // mount(fs_type, partition_type, location, mount_point) 46 // 47 // fs_type="yaffs2" partition_type="MTD" location=partition 48 // fs_type="ext4" partition_type="EMMC" location=device 49 Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { 50 char* result = NULL; 51 if (argc != 4) { 52 return ErrorAbort(state, "%s() expects 4 args, got %d", name, argc); 53 } 54 char* fs_type; 55 char* partition_type; 56 char* location; 57 char* mount_point; 58 if (ReadArgs(state, argv, 4, &fs_type, &partition_type, 59 &location, &mount_point) < 0) { 60 return NULL; 61 } 62 63 if (strlen(fs_type) == 0) { 64 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 65 goto done; 66 } 67 if (strlen(partition_type) == 0) { 68 ErrorAbort(state, "partition_type argument to %s() can't be empty", 69 name); 70 goto done; 71 } 72 if (strlen(location) == 0) { 73 ErrorAbort(state, "location argument to %s() can't be empty", name); 74 goto done; 75 } 76 if (strlen(mount_point) == 0) { 77 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 78 goto done; 79 } 80 81 char *secontext = NULL; 82 83 if (sehandle) { 84 selabel_lookup(sehandle, &secontext, mount_point, 0755); 85 setfscreatecon(secontext); 86 } 87 88 mkdir(mount_point, 0755); 89 90 if (secontext) { 91 freecon(secontext); 92 setfscreatecon(NULL); 93 } 94 95 if (strcmp(partition_type, "MTD") == 0) { 96 mtd_scan_partitions(); 97 const MtdPartition* mtd; 98 mtd = mtd_find_partition_by_name(location); 99 if (mtd == NULL) { 100 fprintf(stderr, "%s: no mtd partition named \"%s\"", 101 name, location); 102 result = strdup(""); 103 goto done; 104 } 105 if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) { 106 fprintf(stderr, "mtd mount of %s failed: %s\n", 107 location, strerror(errno)); 108 result = strdup(""); 109 goto done; 110 } 111 result = mount_point; 112 } else { 113 if (mount(location, mount_point, fs_type, 114 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) { 115 fprintf(stderr, "%s: failed to mount %s at %s: %s\n", 116 name, location, mount_point, strerror(errno)); 117 result = strdup(""); 118 } else { 119 result = mount_point; 120 } 121 } 122 123 done: 124 free(fs_type); 125 free(partition_type); 126 free(location); 127 if (result != mount_point) free(mount_point); 128 return StringValue(result); 129 } 130 131 132 // is_mounted(mount_point) 133 Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { 134 char* result = NULL; 135 if (argc != 1) { 136 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 137 } 138 char* mount_point; 139 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 140 return NULL; 141 } 142 if (strlen(mount_point) == 0) { 143 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 144 goto done; 145 } 146 147 scan_mounted_volumes(); 148 const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); 149 if (vol == NULL) { 150 result = strdup(""); 151 } else { 152 result = mount_point; 153 } 154 155 done: 156 if (result != mount_point) free(mount_point); 157 return StringValue(result); 158 } 159 160 161 Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { 162 char* result = NULL; 163 if (argc != 1) { 164 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 165 } 166 char* mount_point; 167 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 168 return NULL; 169 } 170 if (strlen(mount_point) == 0) { 171 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 172 goto done; 173 } 174 175 scan_mounted_volumes(); 176 const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); 177 if (vol == NULL) { 178 fprintf(stderr, "unmount of %s failed; no such volume\n", mount_point); 179 result = strdup(""); 180 } else { 181 unmount_mounted_volume(vol); 182 result = mount_point; 183 } 184 185 done: 186 if (result != mount_point) free(mount_point); 187 return StringValue(result); 188 } 189 190 191 // format(fs_type, partition_type, location, fs_size, mount_point) 192 // 193 // fs_type="yaffs2" partition_type="MTD" location=partition fs_size=<bytes> mount_point=<location> 194 // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> 195 // if fs_size == 0, then make_ext4fs uses the entire partition. 196 // if fs_size > 0, that is the size to use 197 // if fs_size < 0, then reserve that many bytes at the end of the partition 198 Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { 199 char* result = NULL; 200 if (argc != 5) { 201 return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc); 202 } 203 char* fs_type; 204 char* partition_type; 205 char* location; 206 char* fs_size; 207 char* mount_point; 208 209 if (ReadArgs(state, argv, 5, &fs_type, &partition_type, &location, &fs_size, &mount_point) < 0) { 210 return NULL; 211 } 212 213 if (strlen(fs_type) == 0) { 214 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 215 goto done; 216 } 217 if (strlen(partition_type) == 0) { 218 ErrorAbort(state, "partition_type argument to %s() can't be empty", 219 name); 220 goto done; 221 } 222 if (strlen(location) == 0) { 223 ErrorAbort(state, "location argument to %s() can't be empty", name); 224 goto done; 225 } 226 227 if (strlen(mount_point) == 0) { 228 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 229 goto done; 230 } 231 232 if (strcmp(partition_type, "MTD") == 0) { 233 mtd_scan_partitions(); 234 const MtdPartition* mtd = mtd_find_partition_by_name(location); 235 if (mtd == NULL) { 236 fprintf(stderr, "%s: no mtd partition named \"%s\"", 237 name, location); 238 result = strdup(""); 239 goto done; 240 } 241 MtdWriteContext* ctx = mtd_write_partition(mtd); 242 if (ctx == NULL) { 243 fprintf(stderr, "%s: can't write \"%s\"", name, location); 244 result = strdup(""); 245 goto done; 246 } 247 if (mtd_erase_blocks(ctx, -1) == -1) { 248 mtd_write_close(ctx); 249 fprintf(stderr, "%s: failed to erase \"%s\"", name, location); 250 result = strdup(""); 251 goto done; 252 } 253 if (mtd_write_close(ctx) != 0) { 254 fprintf(stderr, "%s: failed to close \"%s\"", name, location); 255 result = strdup(""); 256 goto done; 257 } 258 result = location; 259 #ifdef USE_EXT4 260 } else if (strcmp(fs_type, "ext4") == 0) { 261 int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle); 262 if (status != 0) { 263 fprintf(stderr, "%s: make_ext4fs failed (%d) on %s", 264 name, status, location); 265 result = strdup(""); 266 goto done; 267 } 268 result = location; 269 #endif 270 } else { 271 fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"", 272 name, fs_type, partition_type); 273 } 274 275 done: 276 free(fs_type); 277 free(partition_type); 278 if (result != location) free(location); 279 return StringValue(result); 280 } 281 282 283 Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { 284 char** paths = malloc(argc * sizeof(char*)); 285 int i; 286 for (i = 0; i < argc; ++i) { 287 paths[i] = Evaluate(state, argv[i]); 288 if (paths[i] == NULL) { 289 int j; 290 for (j = 0; j < i; ++i) { 291 free(paths[j]); 292 } 293 free(paths); 294 return NULL; 295 } 296 } 297 298 bool recursive = (strcmp(name, "delete_recursive") == 0); 299 300 int success = 0; 301 for (i = 0; i < argc; ++i) { 302 if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0) 303 ++success; 304 free(paths[i]); 305 } 306 free(paths); 307 308 char buffer[10]; 309 sprintf(buffer, "%d", success); 310 return StringValue(strdup(buffer)); 311 } 312 313 314 Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 315 if (argc != 2) { 316 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 317 } 318 char* frac_str; 319 char* sec_str; 320 if (ReadArgs(state, argv, 2, &frac_str, &sec_str) < 0) { 321 return NULL; 322 } 323 324 double frac = strtod(frac_str, NULL); 325 int sec = strtol(sec_str, NULL, 10); 326 327 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 328 fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec); 329 330 free(sec_str); 331 return StringValue(frac_str); 332 } 333 334 Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 335 if (argc != 1) { 336 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 337 } 338 char* frac_str; 339 if (ReadArgs(state, argv, 1, &frac_str) < 0) { 340 return NULL; 341 } 342 343 double frac = strtod(frac_str, NULL); 344 345 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 346 fprintf(ui->cmd_pipe, "set_progress %f\n", frac); 347 348 return StringValue(frac_str); 349 } 350 351 // package_extract_dir(package_path, destination_path) 352 Value* PackageExtractDirFn(const char* name, State* state, 353 int argc, Expr* argv[]) { 354 if (argc != 2) { 355 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 356 } 357 char* zip_path; 358 char* dest_path; 359 if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; 360 361 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 362 363 // To create a consistent system image, never use the clock for timestamps. 364 struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default 365 366 bool success = mzExtractRecursive(za, zip_path, dest_path, 367 MZ_EXTRACT_FILES_ONLY, ×tamp, 368 NULL, NULL, sehandle); 369 free(zip_path); 370 free(dest_path); 371 return StringValue(strdup(success ? "t" : "")); 372 } 373 374 375 // package_extract_file(package_path, destination_path) 376 // or 377 // package_extract_file(package_path) 378 // to return the entire contents of the file as the result of this 379 // function (the char* returned is actually a FileContents*). 380 Value* PackageExtractFileFn(const char* name, State* state, 381 int argc, Expr* argv[]) { 382 if (argc != 1 && argc != 2) { 383 return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", 384 name, argc); 385 } 386 bool success = false; 387 if (argc == 2) { 388 // The two-argument version extracts to a file. 389 390 char* zip_path; 391 char* dest_path; 392 if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; 393 394 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 395 const ZipEntry* entry = mzFindZipEntry(za, zip_path); 396 if (entry == NULL) { 397 fprintf(stderr, "%s: no %s in package\n", name, zip_path); 398 goto done2; 399 } 400 401 FILE* f = fopen(dest_path, "wb"); 402 if (f == NULL) { 403 fprintf(stderr, "%s: can't open %s for write: %s\n", 404 name, dest_path, strerror(errno)); 405 goto done2; 406 } 407 success = mzExtractZipEntryToFile(za, entry, fileno(f)); 408 fclose(f); 409 410 done2: 411 free(zip_path); 412 free(dest_path); 413 return StringValue(strdup(success ? "t" : "")); 414 } else { 415 // The one-argument version returns the contents of the file 416 // as the result. 417 418 char* zip_path; 419 Value* v = malloc(sizeof(Value)); 420 v->type = VAL_BLOB; 421 v->size = -1; 422 v->data = NULL; 423 424 if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; 425 426 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 427 const ZipEntry* entry = mzFindZipEntry(za, zip_path); 428 if (entry == NULL) { 429 fprintf(stderr, "%s: no %s in package\n", name, zip_path); 430 goto done1; 431 } 432 433 v->size = mzGetZipEntryUncompLen(entry); 434 v->data = malloc(v->size); 435 if (v->data == NULL) { 436 fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n", 437 name, (long)v->size, zip_path); 438 goto done1; 439 } 440 441 success = mzExtractZipEntryToBuffer(za, entry, 442 (unsigned char *)v->data); 443 444 done1: 445 free(zip_path); 446 if (!success) { 447 free(v->data); 448 v->data = NULL; 449 v->size = -1; 450 } 451 return v; 452 } 453 } 454 455 // Create all parent directories of name, if necessary. 456 static int make_parents(char* name) { 457 char* p; 458 for (p = name + (strlen(name)-1); p > name; --p) { 459 if (*p != '/') continue; 460 *p = '\0'; 461 if (make_parents(name) < 0) return -1; 462 int result = mkdir(name, 0700); 463 if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name); 464 *p = '/'; 465 if (result == 0 || errno == EEXIST) { 466 // successfully created or already existed; we're done 467 return 0; 468 } else { 469 fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno)); 470 return -1; 471 } 472 } 473 return 0; 474 } 475 476 // symlink target src1 src2 ... 477 // unlinks any previously existing src1, src2, etc before creating symlinks. 478 Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { 479 if (argc == 0) { 480 return ErrorAbort(state, "%s() expects 1+ args, got %d", name, argc); 481 } 482 char* target; 483 target = Evaluate(state, argv[0]); 484 if (target == NULL) return NULL; 485 486 char** srcs = ReadVarArgs(state, argc-1, argv+1); 487 if (srcs == NULL) { 488 free(target); 489 return NULL; 490 } 491 492 int bad = 0; 493 int i; 494 for (i = 0; i < argc-1; ++i) { 495 if (unlink(srcs[i]) < 0) { 496 if (errno != ENOENT) { 497 fprintf(stderr, "%s: failed to remove %s: %s\n", 498 name, srcs[i], strerror(errno)); 499 ++bad; 500 } 501 } 502 if (make_parents(srcs[i])) { 503 fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n", 504 name, srcs[i], target); 505 ++bad; 506 } 507 if (symlink(target, srcs[i]) < 0) { 508 fprintf(stderr, "%s: failed to symlink %s to %s: %s\n", 509 name, srcs[i], target, strerror(errno)); 510 ++bad; 511 } 512 free(srcs[i]); 513 } 514 free(srcs); 515 if (bad) { 516 return ErrorAbort(state, "%s: some symlinks failed", name); 517 } 518 return StringValue(strdup("")); 519 } 520 521 522 Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { 523 char* result = NULL; 524 bool recursive = (strcmp(name, "set_perm_recursive") == 0); 525 526 int min_args = 4 + (recursive ? 1 : 0); 527 if (argc < min_args) { 528 return ErrorAbort(state, "%s() expects %d+ args, got %d", 529 name, min_args, argc); 530 } 531 532 char** args = ReadVarArgs(state, argc, argv); 533 if (args == NULL) return NULL; 534 535 char* end; 536 int i; 537 int bad = 0; 538 539 int uid = strtoul(args[0], &end, 0); 540 if (*end != '\0' || args[0][0] == 0) { 541 ErrorAbort(state, "%s: \"%s\" not a valid uid", name, args[0]); 542 goto done; 543 } 544 545 int gid = strtoul(args[1], &end, 0); 546 if (*end != '\0' || args[1][0] == 0) { 547 ErrorAbort(state, "%s: \"%s\" not a valid gid", name, args[1]); 548 goto done; 549 } 550 551 if (recursive) { 552 int dir_mode = strtoul(args[2], &end, 0); 553 if (*end != '\0' || args[2][0] == 0) { 554 ErrorAbort(state, "%s: \"%s\" not a valid dirmode", name, args[2]); 555 goto done; 556 } 557 558 int file_mode = strtoul(args[3], &end, 0); 559 if (*end != '\0' || args[3][0] == 0) { 560 ErrorAbort(state, "%s: \"%s\" not a valid filemode", 561 name, args[3]); 562 goto done; 563 } 564 565 for (i = 4; i < argc; ++i) { 566 dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode); 567 } 568 } else { 569 int mode = strtoul(args[2], &end, 0); 570 if (*end != '\0' || args[2][0] == 0) { 571 ErrorAbort(state, "%s: \"%s\" not a valid mode", name, args[2]); 572 goto done; 573 } 574 575 for (i = 3; i < argc; ++i) { 576 if (chown(args[i], uid, gid) < 0) { 577 fprintf(stderr, "%s: chown of %s to %d %d failed: %s\n", 578 name, args[i], uid, gid, strerror(errno)); 579 ++bad; 580 } 581 if (chmod(args[i], mode) < 0) { 582 fprintf(stderr, "%s: chmod of %s to %o failed: %s\n", 583 name, args[i], mode, strerror(errno)); 584 ++bad; 585 } 586 } 587 } 588 result = strdup(""); 589 590 done: 591 for (i = 0; i < argc; ++i) { 592 free(args[i]); 593 } 594 free(args); 595 596 if (bad) { 597 free(result); 598 return ErrorAbort(state, "%s: some changes failed", name); 599 } 600 return StringValue(result); 601 } 602 603 604 Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 605 if (argc != 1) { 606 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 607 } 608 char* key; 609 key = Evaluate(state, argv[0]); 610 if (key == NULL) return NULL; 611 612 char value[PROPERTY_VALUE_MAX]; 613 property_get(key, value, ""); 614 free(key); 615 616 return StringValue(strdup(value)); 617 } 618 619 620 // file_getprop(file, key) 621 // 622 // interprets 'file' as a getprop-style file (key=value pairs, one 623 // per line, # comment lines and blank lines okay), and returns the value 624 // for 'key' (or "" if it isn't defined). 625 Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 626 char* result = NULL; 627 char* buffer = NULL; 628 char* filename; 629 char* key; 630 if (ReadArgs(state, argv, 2, &filename, &key) < 0) { 631 return NULL; 632 } 633 634 struct stat st; 635 if (stat(filename, &st) < 0) { 636 ErrorAbort(state, "%s: failed to stat \"%s\": %s", 637 name, filename, strerror(errno)); 638 goto done; 639 } 640 641 #define MAX_FILE_GETPROP_SIZE 65536 642 643 if (st.st_size > MAX_FILE_GETPROP_SIZE) { 644 ErrorAbort(state, "%s too large for %s (max %d)", 645 filename, name, MAX_FILE_GETPROP_SIZE); 646 goto done; 647 } 648 649 buffer = malloc(st.st_size+1); 650 if (buffer == NULL) { 651 ErrorAbort(state, "%s: failed to alloc %lld bytes", name, st.st_size+1); 652 goto done; 653 } 654 655 FILE* f = fopen(filename, "rb"); 656 if (f == NULL) { 657 ErrorAbort(state, "%s: failed to open %s: %s", 658 name, filename, strerror(errno)); 659 goto done; 660 } 661 662 if (fread(buffer, 1, st.st_size, f) != st.st_size) { 663 ErrorAbort(state, "%s: failed to read %lld bytes from %s", 664 name, st.st_size+1, filename); 665 fclose(f); 666 goto done; 667 } 668 buffer[st.st_size] = '\0'; 669 670 fclose(f); 671 672 char* line = strtok(buffer, "\n"); 673 do { 674 // skip whitespace at start of line 675 while (*line && isspace(*line)) ++line; 676 677 // comment or blank line: skip to next line 678 if (*line == '\0' || *line == '#') continue; 679 680 char* equal = strchr(line, '='); 681 if (equal == NULL) { 682 ErrorAbort(state, "%s: malformed line \"%s\": %s not a prop file?", 683 name, line, filename); 684 goto done; 685 } 686 687 // trim whitespace between key and '=' 688 char* key_end = equal-1; 689 while (key_end > line && isspace(*key_end)) --key_end; 690 key_end[1] = '\0'; 691 692 // not the key we're looking for 693 if (strcmp(key, line) != 0) continue; 694 695 // skip whitespace after the '=' to the start of the value 696 char* val_start = equal+1; 697 while(*val_start && isspace(*val_start)) ++val_start; 698 699 // trim trailing whitespace 700 char* val_end = val_start + strlen(val_start)-1; 701 while (val_end > val_start && isspace(*val_end)) --val_end; 702 val_end[1] = '\0'; 703 704 result = strdup(val_start); 705 break; 706 707 } while ((line = strtok(NULL, "\n"))); 708 709 if (result == NULL) result = strdup(""); 710 711 done: 712 free(filename); 713 free(key); 714 free(buffer); 715 return StringValue(result); 716 } 717 718 719 static bool write_raw_image_cb(const unsigned char* data, 720 int data_len, void* ctx) { 721 int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len); 722 if (r == data_len) return true; 723 fprintf(stderr, "%s\n", strerror(errno)); 724 return false; 725 } 726 727 // write_raw_image(filename_or_blob, partition) 728 Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { 729 char* result = NULL; 730 731 Value* partition_value; 732 Value* contents; 733 if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) { 734 return NULL; 735 } 736 737 char* partition = NULL; 738 if (partition_value->type != VAL_STRING) { 739 ErrorAbort(state, "partition argument to %s must be string", name); 740 goto done; 741 } 742 partition = partition_value->data; 743 if (strlen(partition) == 0) { 744 ErrorAbort(state, "partition argument to %s can't be empty", name); 745 goto done; 746 } 747 if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) { 748 ErrorAbort(state, "file argument to %s can't be empty", name); 749 goto done; 750 } 751 752 mtd_scan_partitions(); 753 const MtdPartition* mtd = mtd_find_partition_by_name(partition); 754 if (mtd == NULL) { 755 fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition); 756 result = strdup(""); 757 goto done; 758 } 759 760 MtdWriteContext* ctx = mtd_write_partition(mtd); 761 if (ctx == NULL) { 762 fprintf(stderr, "%s: can't write mtd partition \"%s\"\n", 763 name, partition); 764 result = strdup(""); 765 goto done; 766 } 767 768 bool success; 769 770 if (contents->type == VAL_STRING) { 771 // we're given a filename as the contents 772 char* filename = contents->data; 773 FILE* f = fopen(filename, "rb"); 774 if (f == NULL) { 775 fprintf(stderr, "%s: can't open %s: %s\n", 776 name, filename, strerror(errno)); 777 result = strdup(""); 778 goto done; 779 } 780 781 success = true; 782 char* buffer = malloc(BUFSIZ); 783 int read; 784 while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) { 785 int wrote = mtd_write_data(ctx, buffer, read); 786 success = success && (wrote == read); 787 } 788 free(buffer); 789 fclose(f); 790 } else { 791 // we're given a blob as the contents 792 ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size); 793 success = (wrote == contents->size); 794 } 795 if (!success) { 796 fprintf(stderr, "mtd_write_data to %s failed: %s\n", 797 partition, strerror(errno)); 798 } 799 800 if (mtd_erase_blocks(ctx, -1) == -1) { 801 fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition); 802 } 803 if (mtd_write_close(ctx) != 0) { 804 fprintf(stderr, "%s: error closing write of %s\n", name, partition); 805 } 806 807 printf("%s %s partition\n", 808 success ? "wrote" : "failed to write", partition); 809 810 result = success ? partition : strdup(""); 811 812 done: 813 if (result != partition) FreeValue(partition_value); 814 FreeValue(contents); 815 return StringValue(result); 816 } 817 818 // apply_patch_space(bytes) 819 Value* ApplyPatchSpaceFn(const char* name, State* state, 820 int argc, Expr* argv[]) { 821 char* bytes_str; 822 if (ReadArgs(state, argv, 1, &bytes_str) < 0) { 823 return NULL; 824 } 825 826 char* endptr; 827 size_t bytes = strtol(bytes_str, &endptr, 10); 828 if (bytes == 0 && endptr == bytes_str) { 829 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n", 830 name, bytes_str); 831 free(bytes_str); 832 return NULL; 833 } 834 835 return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); 836 } 837 838 839 // apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1_1, patch_1, ...) 840 Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { 841 if (argc < 6 || (argc % 2) == 1) { 842 return ErrorAbort(state, "%s(): expected at least 6 args and an " 843 "even number, got %d", 844 name, argc); 845 } 846 847 char* source_filename; 848 char* target_filename; 849 char* target_sha1; 850 char* target_size_str; 851 if (ReadArgs(state, argv, 4, &source_filename, &target_filename, 852 &target_sha1, &target_size_str) < 0) { 853 return NULL; 854 } 855 856 char* endptr; 857 size_t target_size = strtol(target_size_str, &endptr, 10); 858 if (target_size == 0 && endptr == target_size_str) { 859 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count", 860 name, target_size_str); 861 free(source_filename); 862 free(target_filename); 863 free(target_sha1); 864 free(target_size_str); 865 return NULL; 866 } 867 868 int patchcount = (argc-4) / 2; 869 Value** patches = ReadValueVarArgs(state, argc-4, argv+4); 870 871 int i; 872 for (i = 0; i < patchcount; ++i) { 873 if (patches[i*2]->type != VAL_STRING) { 874 ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i); 875 break; 876 } 877 if (patches[i*2+1]->type != VAL_BLOB) { 878 ErrorAbort(state, "%s(): patch #%d is not blob", name, i); 879 break; 880 } 881 } 882 if (i != patchcount) { 883 for (i = 0; i < patchcount*2; ++i) { 884 FreeValue(patches[i]); 885 } 886 free(patches); 887 return NULL; 888 } 889 890 char** patch_sha_str = malloc(patchcount * sizeof(char*)); 891 for (i = 0; i < patchcount; ++i) { 892 patch_sha_str[i] = patches[i*2]->data; 893 patches[i*2]->data = NULL; 894 FreeValue(patches[i*2]); 895 patches[i] = patches[i*2+1]; 896 } 897 898 int result = applypatch(source_filename, target_filename, 899 target_sha1, target_size, 900 patchcount, patch_sha_str, patches, NULL); 901 902 for (i = 0; i < patchcount; ++i) { 903 FreeValue(patches[i]); 904 } 905 free(patch_sha_str); 906 free(patches); 907 908 return StringValue(strdup(result == 0 ? "t" : "")); 909 } 910 911 // apply_patch_check(file, [sha1_1, ...]) 912 Value* ApplyPatchCheckFn(const char* name, State* state, 913 int argc, Expr* argv[]) { 914 if (argc < 1) { 915 return ErrorAbort(state, "%s(): expected at least 1 arg, got %d", 916 name, argc); 917 } 918 919 char* filename; 920 if (ReadArgs(state, argv, 1, &filename) < 0) { 921 return NULL; 922 } 923 924 int patchcount = argc-1; 925 char** sha1s = ReadVarArgs(state, argc-1, argv+1); 926 927 int result = applypatch_check(filename, patchcount, sha1s); 928 929 int i; 930 for (i = 0; i < patchcount; ++i) { 931 free(sha1s[i]); 932 } 933 free(sha1s); 934 935 return StringValue(strdup(result == 0 ? "t" : "")); 936 } 937 938 Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { 939 char** args = ReadVarArgs(state, argc, argv); 940 if (args == NULL) { 941 return NULL; 942 } 943 944 int size = 0; 945 int i; 946 for (i = 0; i < argc; ++i) { 947 size += strlen(args[i]); 948 } 949 char* buffer = malloc(size+1); 950 size = 0; 951 for (i = 0; i < argc; ++i) { 952 strcpy(buffer+size, args[i]); 953 size += strlen(args[i]); 954 free(args[i]); 955 } 956 free(args); 957 buffer[size] = '\0'; 958 959 char* line = strtok(buffer, "\n"); 960 while (line) { 961 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, 962 "ui_print %s\n", line); 963 line = strtok(NULL, "\n"); 964 } 965 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "ui_print\n"); 966 967 return StringValue(buffer); 968 } 969 970 Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { 971 if (argc != 0) { 972 return ErrorAbort(state, "%s() expects no args, got %d", name, argc); 973 } 974 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); 975 return StringValue(strdup("t")); 976 } 977 978 Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { 979 if (argc < 1) { 980 return ErrorAbort(state, "%s() expects at least 1 arg", name); 981 } 982 char** args = ReadVarArgs(state, argc, argv); 983 if (args == NULL) { 984 return NULL; 985 } 986 987 char** args2 = malloc(sizeof(char*) * (argc+1)); 988 memcpy(args2, args, sizeof(char*) * argc); 989 args2[argc] = NULL; 990 991 fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc); 992 993 pid_t child = fork(); 994 if (child == 0) { 995 execv(args2[0], args2); 996 fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno)); 997 _exit(1); 998 } 999 int status; 1000 waitpid(child, &status, 0); 1001 if (WIFEXITED(status)) { 1002 if (WEXITSTATUS(status) != 0) { 1003 fprintf(stderr, "run_program: child exited with status %d\n", 1004 WEXITSTATUS(status)); 1005 } 1006 } else if (WIFSIGNALED(status)) { 1007 fprintf(stderr, "run_program: child terminated by signal %d\n", 1008 WTERMSIG(status)); 1009 } 1010 1011 int i; 1012 for (i = 0; i < argc; ++i) { 1013 free(args[i]); 1014 } 1015 free(args); 1016 free(args2); 1017 1018 char buffer[20]; 1019 sprintf(buffer, "%d", status); 1020 1021 return StringValue(strdup(buffer)); 1022 } 1023 1024 // Take a sha-1 digest and return it as a newly-allocated hex string. 1025 static char* PrintSha1(uint8_t* digest) { 1026 char* buffer = malloc(SHA_DIGEST_SIZE*2 + 1); 1027 int i; 1028 const char* alphabet = "0123456789abcdef"; 1029 for (i = 0; i < SHA_DIGEST_SIZE; ++i) { 1030 buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; 1031 buffer[i*2+1] = alphabet[digest[i] & 0xf]; 1032 } 1033 buffer[i*2] = '\0'; 1034 return buffer; 1035 } 1036 1037 // sha1_check(data) 1038 // to return the sha1 of the data (given in the format returned by 1039 // read_file). 1040 // 1041 // sha1_check(data, sha1_hex, [sha1_hex, ...]) 1042 // returns the sha1 of the file if it matches any of the hex 1043 // strings passed, or "" if it does not equal any of them. 1044 // 1045 Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { 1046 if (argc < 1) { 1047 return ErrorAbort(state, "%s() expects at least 1 arg", name); 1048 } 1049 1050 Value** args = ReadValueVarArgs(state, argc, argv); 1051 if (args == NULL) { 1052 return NULL; 1053 } 1054 1055 if (args[0]->size < 0) { 1056 fprintf(stderr, "%s(): no file contents received", name); 1057 return StringValue(strdup("")); 1058 } 1059 uint8_t digest[SHA_DIGEST_SIZE]; 1060 SHA(args[0]->data, args[0]->size, digest); 1061 FreeValue(args[0]); 1062 1063 if (argc == 1) { 1064 return StringValue(PrintSha1(digest)); 1065 } 1066 1067 int i; 1068 uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE); 1069 for (i = 1; i < argc; ++i) { 1070 if (args[i]->type != VAL_STRING) { 1071 fprintf(stderr, "%s(): arg %d is not a string; skipping", 1072 name, i); 1073 } else if (ParseSha1(args[i]->data, arg_digest) != 0) { 1074 // Warn about bad args and skip them. 1075 fprintf(stderr, "%s(): error parsing \"%s\" as sha-1; skipping", 1076 name, args[i]->data); 1077 } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) { 1078 break; 1079 } 1080 FreeValue(args[i]); 1081 } 1082 if (i >= argc) { 1083 // Didn't match any of the hex strings; return false. 1084 return StringValue(strdup("")); 1085 } 1086 // Found a match; free all the remaining arguments and return the 1087 // matched one. 1088 int j; 1089 for (j = i+1; j < argc; ++j) { 1090 FreeValue(args[j]); 1091 } 1092 return args[i]; 1093 } 1094 1095 // Read a local file and return its contents (the Value* returned 1096 // is actually a FileContents*). 1097 Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { 1098 if (argc != 1) { 1099 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 1100 } 1101 char* filename; 1102 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; 1103 1104 Value* v = malloc(sizeof(Value)); 1105 v->type = VAL_BLOB; 1106 1107 FileContents fc; 1108 if (LoadFileContents(filename, &fc, RETOUCH_DONT_MASK) != 0) { 1109 ErrorAbort(state, "%s() loading \"%s\" failed: %s", 1110 name, filename, strerror(errno)); 1111 free(filename); 1112 free(v); 1113 free(fc.data); 1114 return NULL; 1115 } 1116 1117 v->size = fc.size; 1118 v->data = (char*)fc.data; 1119 1120 free(filename); 1121 return v; 1122 } 1123 1124 void RegisterInstallFunctions() { 1125 RegisterFunction("mount", MountFn); 1126 RegisterFunction("is_mounted", IsMountedFn); 1127 RegisterFunction("unmount", UnmountFn); 1128 RegisterFunction("format", FormatFn); 1129 RegisterFunction("show_progress", ShowProgressFn); 1130 RegisterFunction("set_progress", SetProgressFn); 1131 RegisterFunction("delete", DeleteFn); 1132 RegisterFunction("delete_recursive", DeleteFn); 1133 RegisterFunction("package_extract_dir", PackageExtractDirFn); 1134 RegisterFunction("package_extract_file", PackageExtractFileFn); 1135 RegisterFunction("symlink", SymlinkFn); 1136 RegisterFunction("set_perm", SetPermFn); 1137 RegisterFunction("set_perm_recursive", SetPermFn); 1138 1139 RegisterFunction("getprop", GetPropFn); 1140 RegisterFunction("file_getprop", FileGetPropFn); 1141 RegisterFunction("write_raw_image", WriteRawImageFn); 1142 1143 RegisterFunction("apply_patch", ApplyPatchFn); 1144 RegisterFunction("apply_patch_check", ApplyPatchCheckFn); 1145 RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); 1146 1147 RegisterFunction("read_file", ReadFileFn); 1148 RegisterFunction("sha1_check", Sha1CheckFn); 1149 1150 RegisterFunction("wipe_cache", WipeCacheFn); 1151 1152 RegisterFunction("ui_print", UIPrintFn); 1153 1154 RegisterFunction("run_program", RunProgramFn); 1155 } 1156