Home | History | Annotate | Download | only in updater
      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, &timestamp,
    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