diff options
Diffstat (limited to 'updater/install.c')
-rw-r--r-- | updater/install.c | 134 |
1 files changed, 103 insertions, 31 deletions
diff --git a/updater/install.c b/updater/install.c index 872cbf857..dad0d08c9 100644 --- a/updater/install.c +++ b/updater/install.c @@ -45,11 +45,26 @@ #include "mtdutils/mounts.h" #include "mtdutils/mtdutils.h" #include "updater.h" +#include "install.h" #ifdef USE_EXT4 #include "make_ext4fs.h" +#include "wipe.h" #endif +// Take a sha-1 digest and return it as a newly-allocated hex string. +char* PrintSha1(const uint8_t* digest) { + char* buffer = malloc(SHA_DIGEST_SIZE*2 + 1); + int i; + const char* alphabet = "0123456789abcdef"; + for (i = 0; i < SHA_DIGEST_SIZE; ++i) { + buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; + buffer[i*2+1] = alphabet[digest[i] & 0xf]; + } + buffer[i*2] = '\0'; + return buffer; +} + // mount(fs_type, partition_type, location, mount_point) // // fs_type="yaffs2" partition_type="MTD" location=partition @@ -195,14 +210,29 @@ done: return StringValue(result); } +static int exec_cmd(const char* path, char* const argv[]) { + int status; + pid_t child; + if ((child = vfork()) == 0) { + execv(path, argv); + _exit(-1); + } + waitpid(child, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + printf("%s failed with status %d\n", path, WEXITSTATUS(status)); + } + return WEXITSTATUS(status); +} + // format(fs_type, partition_type, location, fs_size, mount_point) // // fs_type="yaffs2" partition_type="MTD" location=partition fs_size=<bytes> mount_point=<location> // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> -// if fs_size == 0, then make_ext4fs uses the entire partition. +// fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location> +// if fs_size == 0, then make fs uses the entire partition. // if fs_size > 0, that is the size to use -// if fs_size < 0, then reserve that many bytes at the end of the partition +// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; if (argc != 5) { @@ -274,6 +304,24 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } result = location; + } else if (strcmp(fs_type, "f2fs") == 0) { + char *num_sectors; + if (asprintf(&num_sectors, "%lld", atoll(fs_size) / 512) <= 0) { + printf("format_volume: failed to create %s command for %s\n", fs_type, location); + result = strdup(""); + goto done; + } + const char *f2fs_path = "/sbin/mkfs.f2fs"; + const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location, num_sectors, NULL}; + int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv); + free(num_sectors); + if (status != 0) { + printf("%s: mkfs.f2fs failed (%d) on %s", + name, status, location); + result = strdup(""); + goto done; + } + result = location; #endif } else { printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", @@ -304,13 +352,14 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } if (strlen(dst_name) == 0) { - ErrorAbort(state, "dst_name argument to %s() can't be empty", - name); + ErrorAbort(state, "dst_name argument to %s() can't be empty", name); goto done; } - - if (rename(src_name, dst_name) != 0) { - ErrorAbort(state, "Rename of %s() to %s() failed, error %s()", + if (make_parents(dst_name) != 0) { + ErrorAbort(state, "Creating parent of %s failed, error %s", + dst_name, strerror(errno)); + } else if (rename(src_name, dst_name) != 0) { + ErrorAbort(state, "Rename of %s to %s failed, error %s", src_name, dst_name, strerror(errno)); } else { result = dst_name; @@ -421,19 +470,23 @@ Value* PackageExtractDirFn(const char* name, State* state, // function (the char* returned is actually a FileContents*). Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1 && argc != 2) { + if (argc < 1 || argc > 2) { return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", name, argc); } bool success = false; + + UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); + if (argc == 2) { // The two-argument version extracts to a file. + ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; + char* zip_path; char* dest_path; if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { printf("%s: no %s in package\n", name, zip_path); @@ -502,7 +555,7 @@ static int make_parents(char* name) { *p = '\0'; if (make_parents(name) < 0) return -1; int result = mkdir(name, 0700); - if (result == 0) printf("symlink(): created [%s]\n", name); + if (result == 0) printf("created [%s]\n", name); *p = '/'; if (result == 0 || errno == EEXIST) { // successfully created or already existed; we're done @@ -838,8 +891,8 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // file_getprop(file, key) // // interprets 'file' as a getprop-style file (key=value pairs, one -// per line, # comment lines and blank lines okay), and returns the value -// for 'key' (or "" if it isn't defined). +// per line. # comment lines,blank lines, lines without '=' ignored), +// and returns the value for 'key' (or "" if it isn't defined). Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; char* buffer = NULL; @@ -897,9 +950,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { char* equal = strchr(line, '='); if (equal == NULL) { - ErrorAbort(state, "%s: malformed line \"%s\": %s not a prop file?", - name, line, filename); - goto done; + continue; } // trim whitespace between key and '=' @@ -1053,8 +1104,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); } +// apply_patch(file, size, init_sha1, tgt_sha1, patch) -// apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1_1, patch_1, ...) Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc < 6 || (argc % 2) == 1) { return ErrorAbort(state, "%s(): expected at least 6 args and an " @@ -1239,19 +1290,6 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(strdup(buffer)); } -// Take a sha-1 digest and return it as a newly-allocated hex string. -static char* PrintSha1(uint8_t* digest) { - char* buffer = malloc(SHA_DIGEST_SIZE*2 + 1); - int i; - const char* alphabet = "0123456789abcdef"; - for (i = 0; i < SHA_DIGEST_SIZE; ++i) { - buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf]; - buffer[i*2+1] = alphabet[digest[i] & 0xf]; - } - buffer[i*2] = '\0'; - return buffer; -} - // sha1_check(data) // to return the sha1 of the data (given in the format returned by // read_file). @@ -1322,7 +1360,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { v->type = VAL_BLOB; FileContents fc; - if (LoadFileContents(filename, &fc, RETOUCH_DONT_MASK) != 0) { + if (LoadFileContents(filename, &fc) != 0) { free(filename); v->size = -1; v->data = NULL; @@ -1419,7 +1457,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { + if (argc != 1) { return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); } @@ -1436,6 +1474,36 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(strdup(buffer)); } +Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc != 2) { + return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); + } + + char* filename; + char* len_str; + if (ReadArgs(state, argv, 2, &filename, &len_str) < 0) return NULL; + + size_t len = strtoull(len_str, NULL, 0); + int fd = open(filename, O_WRONLY, 0644); + int success = wipe_block_device(fd, len); + + free(filename); + free(len_str); + + close(fd); + + return StringValue(strdup(success ? "t" : "")); +} + +Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc != 0) { + return ErrorAbort(state, "%s() expects no args, got %d", name, argc); + } + UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); + fprintf(ui->cmd_pipe, "enable_reboot\n"); + return StringValue(strdup("t")); +} + void RegisterInstallFunctions() { RegisterFunction("mount", MountFn); RegisterFunction("is_mounted", IsMountedFn); @@ -1469,6 +1537,8 @@ void RegisterInstallFunctions() { RegisterFunction("apply_patch_check", ApplyPatchCheckFn); RegisterFunction("apply_patch_space", ApplyPatchSpaceFn); + RegisterFunction("wipe_block_device", WipeBlockDeviceFn); + RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); RegisterFunction("rename", RenameFn); @@ -1482,4 +1552,6 @@ void RegisterInstallFunctions() { RegisterFunction("reboot_now", RebootNowFn); RegisterFunction("get_stage", GetStageFn); RegisterFunction("set_stage", SetStageFn); + + RegisterFunction("enable_reboot", EnableRebootFn); } |