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