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 #include <selinux/selinux.h> 31 #include <ftw.h> 32 #include <sys/capability.h> 33 #include <sys/xattr.h> 34 #include <linux/xattr.h> 35 #include <inttypes.h> 36 37 #include "bootloader.h" 38 #include "applypatch/applypatch.h" 39 #include "cutils/android_reboot.h" 40 #include "cutils/misc.h" 41 #include "cutils/properties.h" 42 #include "edify/expr.h" 43 #include "mincrypt/sha.h" 44 #include "minzip/DirUtil.h" 45 #include "mtdutils/mounts.h" 46 #include "mtdutils/mtdutils.h" 47 #include "updater.h" 48 #include "install.h" 49 50 #ifdef USE_EXT4 51 #include "make_ext4fs.h" 52 #include "wipe.h" 53 #endif 54 55 void uiPrint(State* state, char* buffer) { 56 char* line = strtok(buffer, "\n"); 57 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 58 while (line) { 59 fprintf(ui->cmd_pipe, "ui_print %s\n", line); 60 line = strtok(NULL, "\n"); 61 } 62 fprintf(ui->cmd_pipe, "ui_print\n"); 63 } 64 65 __attribute__((__format__(printf, 2, 3))) __nonnull((2)) 66 void uiPrintf(State* state, const char* format, ...) { 67 char error_msg[1024]; 68 va_list ap; 69 va_start(ap, format); 70 vsnprintf(error_msg, sizeof(error_msg), format, ap); 71 va_end(ap); 72 uiPrint(state, error_msg); 73 } 74 75 // Take a sha-1 digest and return it as a newly-allocated hex string. 76 char* PrintSha1(const uint8_t* digest) { 77 char* buffer = malloc(SHA_DIGEST_SIZE*2 + 1); 78 int i; 79 const char* alphabet = "0123456789abcdef"; 80 for (i = 0; i < SHA_DIGEST_SIZE; ++i) { 81 buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; 82 buffer[i*2+1] = alphabet[digest[i] & 0xf]; 83 } 84 buffer[i*2] = '\0'; 85 return buffer; 86 } 87 88 // mount(fs_type, partition_type, location, mount_point) 89 // 90 // fs_type="yaffs2" partition_type="MTD" location=partition 91 // fs_type="ext4" partition_type="EMMC" location=device 92 Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { 93 char* result = NULL; 94 if (argc != 4 && argc != 5) { 95 return ErrorAbort(state, "%s() expects 4-5 args, got %d", name, argc); 96 } 97 char* fs_type; 98 char* partition_type; 99 char* location; 100 char* mount_point; 101 char* mount_options; 102 bool has_mount_options; 103 if (argc == 5) { 104 has_mount_options = true; 105 if (ReadArgs(state, argv, 5, &fs_type, &partition_type, 106 &location, &mount_point, &mount_options) < 0) { 107 return NULL; 108 } 109 } else { 110 has_mount_options = false; 111 if (ReadArgs(state, argv, 4, &fs_type, &partition_type, 112 &location, &mount_point) < 0) { 113 return NULL; 114 } 115 } 116 117 if (strlen(fs_type) == 0) { 118 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 119 goto done; 120 } 121 if (strlen(partition_type) == 0) { 122 ErrorAbort(state, "partition_type argument to %s() can't be empty", 123 name); 124 goto done; 125 } 126 if (strlen(location) == 0) { 127 ErrorAbort(state, "location argument to %s() can't be empty", name); 128 goto done; 129 } 130 if (strlen(mount_point) == 0) { 131 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 132 goto done; 133 } 134 135 char *secontext = NULL; 136 137 if (sehandle) { 138 selabel_lookup(sehandle, &secontext, mount_point, 0755); 139 setfscreatecon(secontext); 140 } 141 142 mkdir(mount_point, 0755); 143 144 if (secontext) { 145 freecon(secontext); 146 setfscreatecon(NULL); 147 } 148 149 if (strcmp(partition_type, "MTD") == 0) { 150 mtd_scan_partitions(); 151 const MtdPartition* mtd; 152 mtd = mtd_find_partition_by_name(location); 153 if (mtd == NULL) { 154 uiPrintf(state, "%s: no mtd partition named \"%s\"", 155 name, location); 156 result = strdup(""); 157 goto done; 158 } 159 if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) { 160 uiPrintf(state, "mtd mount of %s failed: %s\n", 161 location, strerror(errno)); 162 result = strdup(""); 163 goto done; 164 } 165 result = mount_point; 166 } else { 167 if (mount(location, mount_point, fs_type, 168 MS_NOATIME | MS_NODEV | MS_NODIRATIME, 169 has_mount_options ? mount_options : "") < 0) { 170 uiPrintf(state, "%s: failed to mount %s at %s: %s\n", 171 name, location, mount_point, strerror(errno)); 172 result = strdup(""); 173 } else { 174 result = mount_point; 175 } 176 } 177 178 done: 179 free(fs_type); 180 free(partition_type); 181 free(location); 182 if (result != mount_point) free(mount_point); 183 if (has_mount_options) free(mount_options); 184 return StringValue(result); 185 } 186 187 188 // is_mounted(mount_point) 189 Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { 190 char* result = NULL; 191 if (argc != 1) { 192 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 193 } 194 char* mount_point; 195 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 196 return NULL; 197 } 198 if (strlen(mount_point) == 0) { 199 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 200 goto done; 201 } 202 203 scan_mounted_volumes(); 204 const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); 205 if (vol == NULL) { 206 result = strdup(""); 207 } else { 208 result = mount_point; 209 } 210 211 done: 212 if (result != mount_point) free(mount_point); 213 return StringValue(result); 214 } 215 216 217 Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { 218 char* result = NULL; 219 if (argc != 1) { 220 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 221 } 222 char* mount_point; 223 if (ReadArgs(state, argv, 1, &mount_point) < 0) { 224 return NULL; 225 } 226 if (strlen(mount_point) == 0) { 227 ErrorAbort(state, "mount_point argument to unmount() can't be empty"); 228 goto done; 229 } 230 231 scan_mounted_volumes(); 232 const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); 233 if (vol == NULL) { 234 uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point); 235 result = strdup(""); 236 } else { 237 int ret = unmount_mounted_volume(vol); 238 if (ret != 0) { 239 uiPrintf(state, "unmount of %s failed (%d): %s\n", 240 mount_point, ret, strerror(errno)); 241 } 242 result = mount_point; 243 } 244 245 done: 246 if (result != mount_point) free(mount_point); 247 return StringValue(result); 248 } 249 250 static int exec_cmd(const char* path, char* const argv[]) { 251 int status; 252 pid_t child; 253 if ((child = vfork()) == 0) { 254 execv(path, argv); 255 _exit(-1); 256 } 257 waitpid(child, &status, 0); 258 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 259 printf("%s failed with status %d\n", path, WEXITSTATUS(status)); 260 } 261 return WEXITSTATUS(status); 262 } 263 264 265 // format(fs_type, partition_type, location, fs_size, mount_point) 266 // 267 // fs_type="yaffs2" partition_type="MTD" location=partition fs_size=<bytes> mount_point=<location> 268 // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> 269 // fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> 270 // if fs_size == 0, then make fs uses the entire partition. 271 // if fs_size > 0, that is the size to use 272 // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") 273 Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { 274 char* result = NULL; 275 if (argc != 5) { 276 return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc); 277 } 278 char* fs_type; 279 char* partition_type; 280 char* location; 281 char* fs_size; 282 char* mount_point; 283 284 if (ReadArgs(state, argv, 5, &fs_type, &partition_type, &location, &fs_size, &mount_point) < 0) { 285 return NULL; 286 } 287 288 if (strlen(fs_type) == 0) { 289 ErrorAbort(state, "fs_type argument to %s() can't be empty", name); 290 goto done; 291 } 292 if (strlen(partition_type) == 0) { 293 ErrorAbort(state, "partition_type argument to %s() can't be empty", 294 name); 295 goto done; 296 } 297 if (strlen(location) == 0) { 298 ErrorAbort(state, "location argument to %s() can't be empty", name); 299 goto done; 300 } 301 302 if (strlen(mount_point) == 0) { 303 ErrorAbort(state, "mount_point argument to %s() can't be empty", name); 304 goto done; 305 } 306 307 if (strcmp(partition_type, "MTD") == 0) { 308 mtd_scan_partitions(); 309 const MtdPartition* mtd = mtd_find_partition_by_name(location); 310 if (mtd == NULL) { 311 printf("%s: no mtd partition named \"%s\"", 312 name, location); 313 result = strdup(""); 314 goto done; 315 } 316 MtdWriteContext* ctx = mtd_write_partition(mtd); 317 if (ctx == NULL) { 318 printf("%s: can't write \"%s\"", name, location); 319 result = strdup(""); 320 goto done; 321 } 322 if (mtd_erase_blocks(ctx, -1) == -1) { 323 mtd_write_close(ctx); 324 printf("%s: failed to erase \"%s\"", name, location); 325 result = strdup(""); 326 goto done; 327 } 328 if (mtd_write_close(ctx) != 0) { 329 printf("%s: failed to close \"%s\"", name, location); 330 result = strdup(""); 331 goto done; 332 } 333 result = location; 334 #ifdef USE_EXT4 335 } else if (strcmp(fs_type, "ext4") == 0) { 336 int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle); 337 if (status != 0) { 338 printf("%s: make_ext4fs failed (%d) on %s", 339 name, status, location); 340 result = strdup(""); 341 goto done; 342 } 343 result = location; 344 } else if (strcmp(fs_type, "f2fs") == 0) { 345 char *num_sectors; 346 if (asprintf(&num_sectors, "%lld", atoll(fs_size) / 512) <= 0) { 347 printf("format_volume: failed to create %s command for %s\n", fs_type, location); 348 result = strdup(""); 349 goto done; 350 } 351 const char *f2fs_path = "/sbin/mkfs.f2fs"; 352 const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location, num_sectors, NULL}; 353 int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv); 354 free(num_sectors); 355 if (status != 0) { 356 printf("%s: mkfs.f2fs failed (%d) on %s", 357 name, status, location); 358 result = strdup(""); 359 goto done; 360 } 361 result = location; 362 #endif 363 } else { 364 printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", 365 name, fs_type, partition_type); 366 } 367 368 done: 369 free(fs_type); 370 free(partition_type); 371 if (result != location) free(location); 372 return StringValue(result); 373 } 374 375 Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { 376 char* result = NULL; 377 if (argc != 2) { 378 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 379 } 380 381 char* src_name; 382 char* dst_name; 383 384 if (ReadArgs(state, argv, 2, &src_name, &dst_name) < 0) { 385 return NULL; 386 } 387 if (strlen(src_name) == 0) { 388 ErrorAbort(state, "src_name argument to %s() can't be empty", name); 389 goto done; 390 } 391 if (strlen(dst_name) == 0) { 392 ErrorAbort(state, "dst_name argument to %s() can't be empty", name); 393 goto done; 394 } 395 if (make_parents(dst_name) != 0) { 396 ErrorAbort(state, "Creating parent of %s failed, error %s", 397 dst_name, strerror(errno)); 398 } else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) { 399 // File was already moved 400 result = dst_name; 401 } else if (rename(src_name, dst_name) != 0) { 402 ErrorAbort(state, "Rename of %s to %s failed, error %s", 403 src_name, dst_name, strerror(errno)); 404 } else { 405 result = dst_name; 406 } 407 408 done: 409 free(src_name); 410 if (result != dst_name) free(dst_name); 411 return StringValue(result); 412 } 413 414 Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { 415 char** paths = malloc(argc * sizeof(char*)); 416 int i; 417 for (i = 0; i < argc; ++i) { 418 paths[i] = Evaluate(state, argv[i]); 419 if (paths[i] == NULL) { 420 int j; 421 for (j = 0; j < i; ++i) { 422 free(paths[j]); 423 } 424 free(paths); 425 return NULL; 426 } 427 } 428 429 bool recursive = (strcmp(name, "delete_recursive") == 0); 430 431 int success = 0; 432 for (i = 0; i < argc; ++i) { 433 if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0) 434 ++success; 435 free(paths[i]); 436 } 437 free(paths); 438 439 char buffer[10]; 440 sprintf(buffer, "%d", success); 441 return StringValue(strdup(buffer)); 442 } 443 444 445 Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 446 if (argc != 2) { 447 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 448 } 449 char* frac_str; 450 char* sec_str; 451 if (ReadArgs(state, argv, 2, &frac_str, &sec_str) < 0) { 452 return NULL; 453 } 454 455 double frac = strtod(frac_str, NULL); 456 int sec = strtol(sec_str, NULL, 10); 457 458 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 459 fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec); 460 461 free(sec_str); 462 return StringValue(frac_str); 463 } 464 465 Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { 466 if (argc != 1) { 467 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 468 } 469 char* frac_str; 470 if (ReadArgs(state, argv, 1, &frac_str) < 0) { 471 return NULL; 472 } 473 474 double frac = strtod(frac_str, NULL); 475 476 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 477 fprintf(ui->cmd_pipe, "set_progress %f\n", frac); 478 479 return StringValue(frac_str); 480 } 481 482 // package_extract_dir(package_path, destination_path) 483 Value* PackageExtractDirFn(const char* name, State* state, 484 int argc, Expr* argv[]) { 485 if (argc != 2) { 486 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 487 } 488 char* zip_path; 489 char* dest_path; 490 if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; 491 492 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 493 494 // To create a consistent system image, never use the clock for timestamps. 495 struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default 496 497 bool success = mzExtractRecursive(za, zip_path, dest_path, 498 MZ_EXTRACT_FILES_ONLY, ×tamp, 499 NULL, NULL, sehandle); 500 free(zip_path); 501 free(dest_path); 502 return StringValue(strdup(success ? "t" : "")); 503 } 504 505 506 // package_extract_file(package_path, destination_path) 507 // or 508 // package_extract_file(package_path) 509 // to return the entire contents of the file as the result of this 510 // function (the char* returned is actually a FileContents*). 511 Value* PackageExtractFileFn(const char* name, State* state, 512 int argc, Expr* argv[]) { 513 if (argc < 1 || argc > 2) { 514 return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", 515 name, argc); 516 } 517 bool success = false; 518 519 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 520 521 if (argc == 2) { 522 // The two-argument version extracts to a file. 523 524 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 525 526 char* zip_path; 527 char* dest_path; 528 if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; 529 530 const ZipEntry* entry = mzFindZipEntry(za, zip_path); 531 if (entry == NULL) { 532 printf("%s: no %s in package\n", name, zip_path); 533 goto done2; 534 } 535 536 FILE* f = fopen(dest_path, "wb"); 537 if (f == NULL) { 538 printf("%s: can't open %s for write: %s\n", 539 name, dest_path, strerror(errno)); 540 goto done2; 541 } 542 success = mzExtractZipEntryToFile(za, entry, fileno(f)); 543 fclose(f); 544 545 done2: 546 free(zip_path); 547 free(dest_path); 548 return StringValue(strdup(success ? "t" : "")); 549 } else { 550 // The one-argument version returns the contents of the file 551 // as the result. 552 553 char* zip_path; 554 Value* v = malloc(sizeof(Value)); 555 v->type = VAL_BLOB; 556 v->size = -1; 557 v->data = NULL; 558 559 if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; 560 561 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 562 const ZipEntry* entry = mzFindZipEntry(za, zip_path); 563 if (entry == NULL) { 564 printf("%s: no %s in package\n", name, zip_path); 565 goto done1; 566 } 567 568 v->size = mzGetZipEntryUncompLen(entry); 569 v->data = malloc(v->size); 570 if (v->data == NULL) { 571 printf("%s: failed to allocate %ld bytes for %s\n", 572 name, (long)v->size, zip_path); 573 goto done1; 574 } 575 576 success = mzExtractZipEntryToBuffer(za, entry, 577 (unsigned char *)v->data); 578 579 done1: 580 free(zip_path); 581 if (!success) { 582 free(v->data); 583 v->data = NULL; 584 v->size = -1; 585 } 586 return v; 587 } 588 } 589 590 // Create all parent directories of name, if necessary. 591 static int make_parents(char* name) { 592 char* p; 593 for (p = name + (strlen(name)-1); p > name; --p) { 594 if (*p != '/') continue; 595 *p = '\0'; 596 if (make_parents(name) < 0) return -1; 597 int result = mkdir(name, 0700); 598 if (result == 0) printf("created [%s]\n", name); 599 *p = '/'; 600 if (result == 0 || errno == EEXIST) { 601 // successfully created or already existed; we're done 602 return 0; 603 } else { 604 printf("failed to mkdir %s: %s\n", name, strerror(errno)); 605 return -1; 606 } 607 } 608 return 0; 609 } 610 611 // symlink target src1 src2 ... 612 // unlinks any previously existing src1, src2, etc before creating symlinks. 613 Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { 614 if (argc == 0) { 615 return ErrorAbort(state, "%s() expects 1+ args, got %d", name, argc); 616 } 617 char* target; 618 target = Evaluate(state, argv[0]); 619 if (target == NULL) return NULL; 620 621 char** srcs = ReadVarArgs(state, argc-1, argv+1); 622 if (srcs == NULL) { 623 free(target); 624 return NULL; 625 } 626 627 int bad = 0; 628 int i; 629 for (i = 0; i < argc-1; ++i) { 630 if (unlink(srcs[i]) < 0) { 631 if (errno != ENOENT) { 632 printf("%s: failed to remove %s: %s\n", 633 name, srcs[i], strerror(errno)); 634 ++bad; 635 } 636 } 637 if (make_parents(srcs[i])) { 638 printf("%s: failed to symlink %s to %s: making parents failed\n", 639 name, srcs[i], target); 640 ++bad; 641 } 642 if (symlink(target, srcs[i]) < 0) { 643 printf("%s: failed to symlink %s to %s: %s\n", 644 name, srcs[i], target, strerror(errno)); 645 ++bad; 646 } 647 free(srcs[i]); 648 } 649 free(srcs); 650 if (bad) { 651 return ErrorAbort(state, "%s: some symlinks failed", name); 652 } 653 return StringValue(strdup("")); 654 } 655 656 struct perm_parsed_args { 657 bool has_uid; 658 uid_t uid; 659 bool has_gid; 660 gid_t gid; 661 bool has_mode; 662 mode_t mode; 663 bool has_fmode; 664 mode_t fmode; 665 bool has_dmode; 666 mode_t dmode; 667 bool has_selabel; 668 char* selabel; 669 bool has_capabilities; 670 uint64_t capabilities; 671 }; 672 673 static struct perm_parsed_args ParsePermArgs(State * state, int argc, char** args) { 674 int i; 675 struct perm_parsed_args parsed; 676 int bad = 0; 677 static int max_warnings = 20; 678 679 memset(&parsed, 0, sizeof(parsed)); 680 681 for (i = 1; i < argc; i += 2) { 682 if (strcmp("uid", args[i]) == 0) { 683 int64_t uid; 684 if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) { 685 parsed.uid = uid; 686 parsed.has_uid = true; 687 } else { 688 uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]); 689 bad++; 690 } 691 continue; 692 } 693 if (strcmp("gid", args[i]) == 0) { 694 int64_t gid; 695 if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) { 696 parsed.gid = gid; 697 parsed.has_gid = true; 698 } else { 699 uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]); 700 bad++; 701 } 702 continue; 703 } 704 if (strcmp("mode", args[i]) == 0) { 705 int32_t mode; 706 if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { 707 parsed.mode = mode; 708 parsed.has_mode = true; 709 } else { 710 uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]); 711 bad++; 712 } 713 continue; 714 } 715 if (strcmp("dmode", args[i]) == 0) { 716 int32_t mode; 717 if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { 718 parsed.dmode = mode; 719 parsed.has_dmode = true; 720 } else { 721 uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]); 722 bad++; 723 } 724 continue; 725 } 726 if (strcmp("fmode", args[i]) == 0) { 727 int32_t mode; 728 if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { 729 parsed.fmode = mode; 730 parsed.has_fmode = true; 731 } else { 732 uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]); 733 bad++; 734 } 735 continue; 736 } 737 if (strcmp("capabilities", args[i]) == 0) { 738 int64_t capabilities; 739 if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) { 740 parsed.capabilities = capabilities; 741 parsed.has_capabilities = true; 742 } else { 743 uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]); 744 bad++; 745 } 746 continue; 747 } 748 if (strcmp("selabel", args[i]) == 0) { 749 if (args[i+1][0] != '\0') { 750 parsed.selabel = args[i+1]; 751 parsed.has_selabel = true; 752 } else { 753 uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]); 754 bad++; 755 } 756 continue; 757 } 758 if (max_warnings != 0) { 759 printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]); 760 max_warnings--; 761 if (max_warnings == 0) { 762 printf("ParsedPermArgs: suppressing further warnings\n"); 763 } 764 } 765 } 766 return parsed; 767 } 768 769 static int ApplyParsedPerms( 770 State * state, 771 const char* filename, 772 const struct stat *statptr, 773 struct perm_parsed_args parsed) 774 { 775 int bad = 0; 776 777 if (parsed.has_selabel) { 778 if (lsetfilecon(filename, parsed.selabel) != 0) { 779 uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", 780 filename, parsed.selabel, strerror(errno)); 781 bad++; 782 } 783 } 784 785 /* ignore symlinks */ 786 if (S_ISLNK(statptr->st_mode)) { 787 return bad; 788 } 789 790 if (parsed.has_uid) { 791 if (chown(filename, parsed.uid, -1) < 0) { 792 uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", 793 filename, parsed.uid, strerror(errno)); 794 bad++; 795 } 796 } 797 798 if (parsed.has_gid) { 799 if (chown(filename, -1, parsed.gid) < 0) { 800 uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", 801 filename, parsed.gid, strerror(errno)); 802 bad++; 803 } 804 } 805 806 if (parsed.has_mode) { 807 if (chmod(filename, parsed.mode) < 0) { 808 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", 809 filename, parsed.mode, strerror(errno)); 810 bad++; 811 } 812 } 813 814 if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { 815 if (chmod(filename, parsed.dmode) < 0) { 816 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", 817 filename, parsed.dmode, strerror(errno)); 818 bad++; 819 } 820 } 821 822 if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { 823 if (chmod(filename, parsed.fmode) < 0) { 824 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", 825 filename, parsed.fmode, strerror(errno)); 826 bad++; 827 } 828 } 829 830 if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) { 831 if (parsed.capabilities == 0) { 832 if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) { 833 // Report failure unless it's ENODATA (attribute not set) 834 uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", 835 filename, parsed.capabilities, strerror(errno)); 836 bad++; 837 } 838 } else { 839 struct vfs_cap_data cap_data; 840 memset(&cap_data, 0, sizeof(cap_data)); 841 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; 842 cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff); 843 cap_data.data[0].inheritable = 0; 844 cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32); 845 cap_data.data[1].inheritable = 0; 846 if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) { 847 uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", 848 filename, parsed.capabilities, strerror(errno)); 849 bad++; 850 } 851 } 852 } 853 854 return bad; 855 } 856 857 // nftw doesn't allow us to pass along context, so we need to use 858 // global variables. *sigh* 859 static struct perm_parsed_args recursive_parsed_args; 860 static State* recursive_state; 861 862 static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr, 863 int fileflags, struct FTW *pfwt) { 864 return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args); 865 } 866 867 static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { 868 int i; 869 int bad = 0; 870 static int nwarnings = 0; 871 struct stat sb; 872 Value* result = NULL; 873 874 bool recursive = (strcmp(name, "set_metadata_recursive") == 0); 875 876 if ((argc % 2) != 1) { 877 return ErrorAbort(state, "%s() expects an odd number of arguments, got %d", 878 name, argc); 879 } 880 881 char** args = ReadVarArgs(state, argc, argv); 882 if (args == NULL) return NULL; 883 884 if (lstat(args[0], &sb) == -1) { 885 result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno)); 886 goto done; 887 } 888 889 struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); 890 891 if (recursive) { 892 recursive_parsed_args = parsed; 893 recursive_state = state; 894 bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); 895 memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); 896 recursive_state = NULL; 897 } else { 898 bad += ApplyParsedPerms(state, args[0], &sb, parsed); 899 } 900 901 done: 902 for (i = 0; i < argc; ++i) { 903 free(args[i]); 904 } 905 free(args); 906 907 if (result != NULL) { 908 return result; 909 } 910 911 if (bad > 0) { 912 return ErrorAbort(state, "%s: some changes failed", name); 913 } 914 915 return StringValue(strdup("")); 916 } 917 918 Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 919 if (argc != 1) { 920 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 921 } 922 char* key; 923 key = Evaluate(state, argv[0]); 924 if (key == NULL) return NULL; 925 926 char value[PROPERTY_VALUE_MAX]; 927 property_get(key, value, ""); 928 free(key); 929 930 return StringValue(strdup(value)); 931 } 932 933 934 // file_getprop(file, key) 935 // 936 // interprets 'file' as a getprop-style file (key=value pairs, one 937 // per line. # comment lines,blank lines, lines without '=' ignored), 938 // and returns the value for 'key' (or "" if it isn't defined). 939 Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 940 char* result = NULL; 941 char* buffer = NULL; 942 char* filename; 943 char* key; 944 if (ReadArgs(state, argv, 2, &filename, &key) < 0) { 945 return NULL; 946 } 947 948 struct stat st; 949 if (stat(filename, &st) < 0) { 950 ErrorAbort(state, "%s: failed to stat \"%s\": %s", 951 name, filename, strerror(errno)); 952 goto done; 953 } 954 955 #define MAX_FILE_GETPROP_SIZE 65536 956 957 if (st.st_size > MAX_FILE_GETPROP_SIZE) { 958 ErrorAbort(state, "%s too large for %s (max %d)", 959 filename, name, MAX_FILE_GETPROP_SIZE); 960 goto done; 961 } 962 963 buffer = malloc(st.st_size+1); 964 if (buffer == NULL) { 965 ErrorAbort(state, "%s: failed to alloc %lld bytes", name, (long long)st.st_size+1); 966 goto done; 967 } 968 969 FILE* f = fopen(filename, "rb"); 970 if (f == NULL) { 971 ErrorAbort(state, "%s: failed to open %s: %s", 972 name, filename, strerror(errno)); 973 goto done; 974 } 975 976 if (fread(buffer, 1, st.st_size, f) != st.st_size) { 977 ErrorAbort(state, "%s: failed to read %lld bytes from %s", 978 name, (long long)st.st_size+1, filename); 979 fclose(f); 980 goto done; 981 } 982 buffer[st.st_size] = '\0'; 983 984 fclose(f); 985 986 char* line = strtok(buffer, "\n"); 987 do { 988 // skip whitespace at start of line 989 while (*line && isspace(*line)) ++line; 990 991 // comment or blank line: skip to next line 992 if (*line == '\0' || *line == '#') continue; 993 994 char* equal = strchr(line, '='); 995 if (equal == NULL) { 996 continue; 997 } 998 999 // trim whitespace between key and '=' 1000 char* key_end = equal-1; 1001 while (key_end > line && isspace(*key_end)) --key_end; 1002 key_end[1] = '\0'; 1003 1004 // not the key we're looking for 1005 if (strcmp(key, line) != 0) continue; 1006 1007 // skip whitespace after the '=' to the start of the value 1008 char* val_start = equal+1; 1009 while(*val_start && isspace(*val_start)) ++val_start; 1010 1011 // trim trailing whitespace 1012 char* val_end = val_start + strlen(val_start)-1; 1013 while (val_end > val_start && isspace(*val_end)) --val_end; 1014 val_end[1] = '\0'; 1015 1016 result = strdup(val_start); 1017 break; 1018 1019 } while ((line = strtok(NULL, "\n"))); 1020 1021 if (result == NULL) result = strdup(""); 1022 1023 done: 1024 free(filename); 1025 free(key); 1026 free(buffer); 1027 return StringValue(result); 1028 } 1029 1030 1031 static bool write_raw_image_cb(const unsigned char* data, 1032 int data_len, void* ctx) { 1033 int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len); 1034 if (r == data_len) return true; 1035 printf("%s\n", strerror(errno)); 1036 return false; 1037 } 1038 1039 // write_raw_image(filename_or_blob, partition) 1040 Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { 1041 char* result = NULL; 1042 1043 Value* partition_value; 1044 Value* contents; 1045 if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) { 1046 return NULL; 1047 } 1048 1049 char* partition = NULL; 1050 if (partition_value->type != VAL_STRING) { 1051 ErrorAbort(state, "partition argument to %s must be string", name); 1052 goto done; 1053 } 1054 partition = partition_value->data; 1055 if (strlen(partition) == 0) { 1056 ErrorAbort(state, "partition argument to %s can't be empty", name); 1057 goto done; 1058 } 1059 if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) { 1060 ErrorAbort(state, "file argument to %s can't be empty", name); 1061 goto done; 1062 } 1063 1064 mtd_scan_partitions(); 1065 const MtdPartition* mtd = mtd_find_partition_by_name(partition); 1066 if (mtd == NULL) { 1067 printf("%s: no mtd partition named \"%s\"\n", name, partition); 1068 result = strdup(""); 1069 goto done; 1070 } 1071 1072 MtdWriteContext* ctx = mtd_write_partition(mtd); 1073 if (ctx == NULL) { 1074 printf("%s: can't write mtd partition \"%s\"\n", 1075 name, partition); 1076 result = strdup(""); 1077 goto done; 1078 } 1079 1080 bool success; 1081 1082 if (contents->type == VAL_STRING) { 1083 // we're given a filename as the contents 1084 char* filename = contents->data; 1085 FILE* f = fopen(filename, "rb"); 1086 if (f == NULL) { 1087 printf("%s: can't open %s: %s\n", 1088 name, filename, strerror(errno)); 1089 result = strdup(""); 1090 goto done; 1091 } 1092 1093 success = true; 1094 char* buffer = malloc(BUFSIZ); 1095 int read; 1096 while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) { 1097 int wrote = mtd_write_data(ctx, buffer, read); 1098 success = success && (wrote == read); 1099 } 1100 free(buffer); 1101 fclose(f); 1102 } else { 1103 // we're given a blob as the contents 1104 ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size); 1105 success = (wrote == contents->size); 1106 } 1107 if (!success) { 1108 printf("mtd_write_data to %s failed: %s\n", 1109 partition, strerror(errno)); 1110 } 1111 1112 if (mtd_erase_blocks(ctx, -1) == -1) { 1113 printf("%s: error erasing blocks of %s\n", name, partition); 1114 } 1115 if (mtd_write_close(ctx) != 0) { 1116 printf("%s: error closing write of %s\n", name, partition); 1117 } 1118 1119 printf("%s %s partition\n", 1120 success ? "wrote" : "failed to write", partition); 1121 1122 result = success ? partition : strdup(""); 1123 1124 done: 1125 if (result != partition) FreeValue(partition_value); 1126 FreeValue(contents); 1127 return StringValue(result); 1128 } 1129 1130 // apply_patch_space(bytes) 1131 Value* ApplyPatchSpaceFn(const char* name, State* state, 1132 int argc, Expr* argv[]) { 1133 char* bytes_str; 1134 if (ReadArgs(state, argv, 1, &bytes_str) < 0) { 1135 return NULL; 1136 } 1137 1138 char* endptr; 1139 size_t bytes = strtol(bytes_str, &endptr, 10); 1140 if (bytes == 0 && endptr == bytes_str) { 1141 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n", 1142 name, bytes_str); 1143 free(bytes_str); 1144 return NULL; 1145 } 1146 1147 return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); 1148 } 1149 1150 // apply_patch(file, size, init_sha1, tgt_sha1, patch) 1151 1152 Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { 1153 if (argc < 6 || (argc % 2) == 1) { 1154 return ErrorAbort(state, "%s(): expected at least 6 args and an " 1155 "even number, got %d", 1156 name, argc); 1157 } 1158 1159 char* source_filename; 1160 char* target_filename; 1161 char* target_sha1; 1162 char* target_size_str; 1163 if (ReadArgs(state, argv, 4, &source_filename, &target_filename, 1164 &target_sha1, &target_size_str) < 0) { 1165 return NULL; 1166 } 1167 1168 char* endptr; 1169 size_t target_size = strtol(target_size_str, &endptr, 10); 1170 if (target_size == 0 && endptr == target_size_str) { 1171 ErrorAbort(state, "%s(): can't parse \"%s\" as byte count", 1172 name, target_size_str); 1173 free(source_filename); 1174 free(target_filename); 1175 free(target_sha1); 1176 free(target_size_str); 1177 return NULL; 1178 } 1179 1180 int patchcount = (argc-4) / 2; 1181 Value** patches = ReadValueVarArgs(state, argc-4, argv+4); 1182 1183 int i; 1184 for (i = 0; i < patchcount; ++i) { 1185 if (patches[i*2]->type != VAL_STRING) { 1186 ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i); 1187 break; 1188 } 1189 if (patches[i*2+1]->type != VAL_BLOB) { 1190 ErrorAbort(state, "%s(): patch #%d is not blob", name, i); 1191 break; 1192 } 1193 } 1194 if (i != patchcount) { 1195 for (i = 0; i < patchcount*2; ++i) { 1196 FreeValue(patches[i]); 1197 } 1198 free(patches); 1199 return NULL; 1200 } 1201 1202 char** patch_sha_str = malloc(patchcount * sizeof(char*)); 1203 for (i = 0; i < patchcount; ++i) { 1204 patch_sha_str[i] = patches[i*2]->data; 1205 patches[i*2]->data = NULL; 1206 FreeValue(patches[i*2]); 1207 patches[i] = patches[i*2+1]; 1208 } 1209 1210 int result = applypatch(source_filename, target_filename, 1211 target_sha1, target_size, 1212 patchcount, patch_sha_str, patches, NULL); 1213 1214 for (i = 0; i < patchcount; ++i) { 1215 FreeValue(patches[i]); 1216 } 1217 free(patch_sha_str); 1218 free(patches); 1219 1220 return StringValue(strdup(result == 0 ? "t" : "")); 1221 } 1222 1223 // apply_patch_check(file, [sha1_1, ...]) 1224 Value* ApplyPatchCheckFn(const char* name, State* state, 1225 int argc, Expr* argv[]) { 1226 if (argc < 1) { 1227 return ErrorAbort(state, "%s(): expected at least 1 arg, got %d", 1228 name, argc); 1229 } 1230 1231 char* filename; 1232 if (ReadArgs(state, argv, 1, &filename) < 0) { 1233 return NULL; 1234 } 1235 1236 int patchcount = argc-1; 1237 char** sha1s = ReadVarArgs(state, argc-1, argv+1); 1238 1239 int result = applypatch_check(filename, patchcount, sha1s); 1240 1241 int i; 1242 for (i = 0; i < patchcount; ++i) { 1243 free(sha1s[i]); 1244 } 1245 free(sha1s); 1246 1247 return StringValue(strdup(result == 0 ? "t" : "")); 1248 } 1249 1250 Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { 1251 char** args = ReadVarArgs(state, argc, argv); 1252 if (args == NULL) { 1253 return NULL; 1254 } 1255 1256 int size = 0; 1257 int i; 1258 for (i = 0; i < argc; ++i) { 1259 size += strlen(args[i]); 1260 } 1261 char* buffer = malloc(size+1); 1262 size = 0; 1263 for (i = 0; i < argc; ++i) { 1264 strcpy(buffer+size, args[i]); 1265 size += strlen(args[i]); 1266 free(args[i]); 1267 } 1268 free(args); 1269 buffer[size] = '\0'; 1270 uiPrint(state, buffer); 1271 return StringValue(buffer); 1272 } 1273 1274 Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { 1275 if (argc != 0) { 1276 return ErrorAbort(state, "%s() expects no args, got %d", name, argc); 1277 } 1278 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); 1279 return StringValue(strdup("t")); 1280 } 1281 1282 Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { 1283 if (argc < 1) { 1284 return ErrorAbort(state, "%s() expects at least 1 arg", name); 1285 } 1286 char** args = ReadVarArgs(state, argc, argv); 1287 if (args == NULL) { 1288 return NULL; 1289 } 1290 1291 char** args2 = malloc(sizeof(char*) * (argc+1)); 1292 memcpy(args2, args, sizeof(char*) * argc); 1293 args2[argc] = NULL; 1294 1295 printf("about to run program [%s] with %d args\n", args2[0], argc); 1296 1297 pid_t child = fork(); 1298 if (child == 0) { 1299 execv(args2[0], args2); 1300 printf("run_program: execv failed: %s\n", strerror(errno)); 1301 _exit(1); 1302 } 1303 int status; 1304 waitpid(child, &status, 0); 1305 if (WIFEXITED(status)) { 1306 if (WEXITSTATUS(status) != 0) { 1307 printf("run_program: child exited with status %d\n", 1308 WEXITSTATUS(status)); 1309 } 1310 } else if (WIFSIGNALED(status)) { 1311 printf("run_program: child terminated by signal %d\n", 1312 WTERMSIG(status)); 1313 } 1314 1315 int i; 1316 for (i = 0; i < argc; ++i) { 1317 free(args[i]); 1318 } 1319 free(args); 1320 free(args2); 1321 1322 char buffer[20]; 1323 sprintf(buffer, "%d", status); 1324 1325 return StringValue(strdup(buffer)); 1326 } 1327 1328 // sha1_check(data) 1329 // to return the sha1 of the data (given in the format returned by 1330 // read_file). 1331 // 1332 // sha1_check(data, sha1_hex, [sha1_hex, ...]) 1333 // returns the sha1 of the file if it matches any of the hex 1334 // strings passed, or "" if it does not equal any of them. 1335 // 1336 Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { 1337 if (argc < 1) { 1338 return ErrorAbort(state, "%s() expects at least 1 arg", name); 1339 } 1340 1341 Value** args = ReadValueVarArgs(state, argc, argv); 1342 if (args == NULL) { 1343 return NULL; 1344 } 1345 1346 if (args[0]->size < 0) { 1347 return StringValue(strdup("")); 1348 } 1349 uint8_t digest[SHA_DIGEST_SIZE]; 1350 SHA_hash(args[0]->data, args[0]->size, digest); 1351 FreeValue(args[0]); 1352 1353 if (argc == 1) { 1354 return StringValue(PrintSha1(digest)); 1355 } 1356 1357 int i; 1358 uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE); 1359 for (i = 1; i < argc; ++i) { 1360 if (args[i]->type != VAL_STRING) { 1361 printf("%s(): arg %d is not a string; skipping", 1362 name, i); 1363 } else if (ParseSha1(args[i]->data, arg_digest) != 0) { 1364 // Warn about bad args and skip them. 1365 printf("%s(): error parsing \"%s\" as sha-1; skipping", 1366 name, args[i]->data); 1367 } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) { 1368 break; 1369 } 1370 FreeValue(args[i]); 1371 } 1372 if (i >= argc) { 1373 // Didn't match any of the hex strings; return false. 1374 return StringValue(strdup("")); 1375 } 1376 // Found a match; free all the remaining arguments and return the 1377 // matched one. 1378 int j; 1379 for (j = i+1; j < argc; ++j) { 1380 FreeValue(args[j]); 1381 } 1382 return args[i]; 1383 } 1384 1385 // Read a local file and return its contents (the Value* returned 1386 // is actually a FileContents*). 1387 Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { 1388 if (argc != 1) { 1389 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 1390 } 1391 char* filename; 1392 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; 1393 1394 Value* v = malloc(sizeof(Value)); 1395 v->type = VAL_BLOB; 1396 1397 FileContents fc; 1398 if (LoadFileContents(filename, &fc) != 0) { 1399 free(filename); 1400 v->size = -1; 1401 v->data = NULL; 1402 free(fc.data); 1403 return v; 1404 } 1405 1406 v->size = fc.size; 1407 v->data = (char*)fc.data; 1408 1409 free(filename); 1410 return v; 1411 } 1412 1413 // Immediately reboot the device. Recovery is not finished normally, 1414 // so if you reboot into recovery it will re-start applying the 1415 // current package (because nothing has cleared the copy of the 1416 // arguments stored in the BCB). 1417 // 1418 // The argument is the partition name passed to the android reboot 1419 // property. It can be "recovery" to boot from the recovery 1420 // partition, or "" (empty string) to boot from the regular boot 1421 // partition. 1422 Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { 1423 if (argc != 2) { 1424 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1425 } 1426 1427 char* filename; 1428 char* property; 1429 if (ReadArgs(state, argv, 2, &filename, &property) < 0) return NULL; 1430 1431 char buffer[80]; 1432 1433 // zero out the 'command' field of the bootloader message. 1434 memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); 1435 FILE* f = fopen(filename, "r+b"); 1436 fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); 1437 fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); 1438 fclose(f); 1439 free(filename); 1440 1441 strcpy(buffer, "reboot,"); 1442 if (property != NULL) { 1443 strncat(buffer, property, sizeof(buffer)-10); 1444 } 1445 1446 property_set(ANDROID_RB_PROPERTY, buffer); 1447 1448 sleep(5); 1449 free(property); 1450 ErrorAbort(state, "%s() failed to reboot", name); 1451 return NULL; 1452 } 1453 1454 // Store a string value somewhere that future invocations of recovery 1455 // can access it. This value is called the "stage" and can be used to 1456 // drive packages that need to do reboots in the middle of 1457 // installation and keep track of where they are in the multi-stage 1458 // install. 1459 // 1460 // The first argument is the block device for the misc partition 1461 // ("/misc" in the fstab), which is where this value is stored. The 1462 // second argument is the string to store; it should not exceed 31 1463 // bytes. 1464 Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { 1465 if (argc != 2) { 1466 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1467 } 1468 1469 char* filename; 1470 char* stagestr; 1471 if (ReadArgs(state, argv, 2, &filename, &stagestr) < 0) return NULL; 1472 1473 // Store this value in the misc partition, immediately after the 1474 // bootloader message that the main recovery uses to save its 1475 // arguments in case of the device restarting midway through 1476 // package installation. 1477 FILE* f = fopen(filename, "r+b"); 1478 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); 1479 int to_write = strlen(stagestr)+1; 1480 int max_size = sizeof(((struct bootloader_message*)0)->stage); 1481 if (to_write > max_size) { 1482 to_write = max_size; 1483 stagestr[max_size-1] = 0; 1484 } 1485 fwrite(stagestr, to_write, 1, f); 1486 fclose(f); 1487 1488 free(stagestr); 1489 return StringValue(filename); 1490 } 1491 1492 // Return the value most recently saved with SetStageFn. The argument 1493 // is the block device for the misc partition. 1494 Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { 1495 if (argc != 1) { 1496 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); 1497 } 1498 1499 char* filename; 1500 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; 1501 1502 char buffer[sizeof(((struct bootloader_message*)0)->stage)]; 1503 FILE* f = fopen(filename, "rb"); 1504 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); 1505 fread(buffer, sizeof(buffer), 1, f); 1506 fclose(f); 1507 buffer[sizeof(buffer)-1] = '\0'; 1508 1509 return StringValue(strdup(buffer)); 1510 } 1511 1512 Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { 1513 if (argc != 2) { 1514 return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); 1515 } 1516 1517 char* filename; 1518 char* len_str; 1519 if (ReadArgs(state, argv, 2, &filename, &len_str) < 0) return NULL; 1520 1521 size_t len = strtoull(len_str, NULL, 0); 1522 int fd = open(filename, O_WRONLY, 0644); 1523 int success = wipe_block_device(fd, len); 1524 1525 free(filename); 1526 free(len_str); 1527 1528 close(fd); 1529 1530 return StringValue(strdup(success ? "t" : "")); 1531 } 1532 1533 Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { 1534 if (argc != 0) { 1535 return ErrorAbort(state, "%s() expects no args, got %d", name, argc); 1536 } 1537 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 1538 fprintf(ui->cmd_pipe, "enable_reboot\n"); 1539 return StringValue(strdup("t")); 1540 } 1541 1542 void RegisterInstallFunctions() { 1543 RegisterFunction("mount", MountFn); 1544 RegisterFunction("is_mounted", IsMountedFn); 1545 RegisterFunction("unmount", UnmountFn); 1546 RegisterFunction("format", FormatFn); 1547 RegisterFunction("show_progress", ShowProgressFn); 1548 RegisterFunction("set_progress", SetProgressFn); 1549 RegisterFunction("delete", DeleteFn); 1550 RegisterFunction("delete_recursive", DeleteFn); 1551 RegisterFunction("package_extract_dir", PackageExtractDirFn); 1552 RegisterFunction("package_extract_file", PackageExtractFileFn); 1553 RegisterFunction("symlink", SymlinkFn); 1554 1555 // Usage: 1556 // set_metadata("filename", "key1", "value1", "key2", "value2", ...) 1557 // Example: 1558 // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); 1559 RegisterFunction("set_metadata", SetMetadataFn); 1560 1561 // Usage: 1562 // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) 1563 // Example: 1564 // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); 1565 RegisterFunction("set_metadata_recursive", SetMetadataFn); 1566 1567 RegisterFunction("getprop", GetPropFn); 1568 RegisterFunction("file_getprop", FileGetPropFn); 1569 RegisterFunction("write_raw_image", WriteRawImageFn); 1570 1571 RegisterFunction("apply_patch", ApplyPatchFn); 1572 RegisterFunction("apply_patch_check", ApplyPatchCheckFn); 1573 RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); 1574 1575 RegisterFunction("wipe_block_device", WipeBlockDeviceFn); 1576 1577 RegisterFunction("read_file", ReadFileFn); 1578 RegisterFunction("sha1_check", Sha1CheckFn); 1579 RegisterFunction("rename", RenameFn); 1580 1581 RegisterFunction("wipe_cache", WipeCacheFn); 1582 1583 RegisterFunction("ui_print", UIPrintFn); 1584 1585 RegisterFunction("run_program", RunProgramFn); 1586 1587 RegisterFunction("reboot_now", RebootNowFn); 1588 RegisterFunction("get_stage", GetStageFn); 1589 RegisterFunction("set_stage", SetStageFn); 1590 1591 RegisterFunction("enable_reboot", EnableRebootFn); 1592 } 1593