summaryrefslogtreecommitdiffstats
path: root/updater/install.c
diff options
context:
space:
mode:
Diffstat (limited to 'updater/install.c')
-rw-r--r--updater/install.c205
1 files changed, 179 insertions, 26 deletions
diff --git a/updater/install.c b/updater/install.c
index e869134be..6a8c5d401 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -25,35 +25,49 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "edify/expr.h"
#include "mincrypt/sha.h"
#include "minzip/DirUtil.h"
+#include "minelf/Retouch.h"
#include "mtdutils/mounts.h"
#include "mtdutils/mtdutils.h"
#include "updater.h"
#include "applypatch/applypatch.h"
-// mount(type, location, mount_point)
+#ifdef USE_EXT4
+#include "make_ext4fs.h"
+#endif
+
+// mount(fs_type, partition_type, location, mount_point)
//
-// what: type="MTD" location="<partition>" to mount a yaffs2 filesystem
-// type="vfat" location="/dev/block/<whatever>" to mount a device
+// fs_type="yaffs2" partition_type="MTD" location=partition
+// fs_type="ext4" partition_type="EMMC" location=device
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
- if (argc != 3) {
- return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
+ if (argc != 4) {
+ return ErrorAbort(state, "%s() expects 4 args, got %d", name, argc);
}
- char* type;
+ char* fs_type;
+ char* partition_type;
char* location;
char* mount_point;
- if (ReadArgs(state, argv, 3, &type, &location, &mount_point) < 0) {
+ if (ReadArgs(state, argv, 4, &fs_type, &partition_type,
+ &location, &mount_point) < 0) {
return NULL;
}
- if (strlen(type) == 0) {
- ErrorAbort(state, "type argument to %s() can't be empty", name);
+ if (strlen(fs_type) == 0) {
+ ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ goto done;
+ }
+ if (strlen(partition_type) == 0) {
+ ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ name);
goto done;
}
if (strlen(location) == 0) {
@@ -67,7 +81,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
mkdir(mount_point, 0755);
- if (strcmp(type, "MTD") == 0) {
+ if (strcmp(partition_type, "MTD") == 0) {
mtd_scan_partitions();
const MtdPartition* mtd;
mtd = mtd_find_partition_by_name(location);
@@ -77,7 +91,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
result = strdup("");
goto done;
}
- if (mtd_mount_partition(mtd, mount_point, "yaffs2", 0 /* rw */) != 0) {
+ if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) {
fprintf(stderr, "mtd mount of %s failed: %s\n",
location, strerror(errno));
result = strdup("");
@@ -85,7 +99,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
}
result = mount_point;
} else {
- if (mount(location, mount_point, type,
+ if (mount(location, mount_point, fs_type,
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) {
fprintf(stderr, "%s: failed to mount %s at %s: %s\n",
name, location, mount_point, strerror(errno));
@@ -96,7 +110,8 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
}
done:
- free(type);
+ free(fs_type);
+ free(partition_type);
free(location);
if (result != mount_point) free(mount_point);
return StringValue(result);
@@ -162,22 +177,29 @@ done:
}
-// format(type, location)
+// format(fs_type, partition_type, location)
//
-// type="MTD" location=partition
+// fs_type="yaffs2" partition_type="MTD" location=partition
+// fs_type="ext4" partition_type="EMMC" location=device
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
- if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ if (argc != 3) {
+ return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
}
- char* type;
+ char* fs_type;
+ char* partition_type;
char* location;
- if (ReadArgs(state, argv, 2, &type, &location) < 0) {
+ if (ReadArgs(state, argv, 3, &fs_type, &partition_type, &location) < 0) {
return NULL;
}
- if (strlen(type) == 0) {
- ErrorAbort(state, "type argument to %s() can't be empty", name);
+ if (strlen(fs_type) == 0) {
+ ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ goto done;
+ }
+ if (strlen(partition_type) == 0) {
+ ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ name);
goto done;
}
if (strlen(location) == 0) {
@@ -185,7 +207,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
goto done;
}
- if (strcmp(type, "MTD") == 0) {
+ if (strcmp(partition_type, "MTD") == 0) {
mtd_scan_partitions();
const MtdPartition* mtd = mtd_find_partition_by_name(location);
if (mtd == NULL) {
@@ -212,12 +234,26 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
goto done;
}
result = location;
+#ifdef USE_EXT4
+ } else if (strcmp(fs_type, "ext4") == 0) {
+ reset_ext4fs_info();
+ int status = make_ext4fs(location, NULL, NULL, 0, 0);
+ if (status != 0) {
+ fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
+ name, status, location);
+ result = strdup("");
+ goto done;
+ }
+ result = location;
+#endif
} else {
- fprintf(stderr, "%s: unsupported type \"%s\"", name, type);
+ fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"",
+ name, fs_type, partition_type);
}
done:
- free(type);
+ free(fs_type);
+ free(partition_type);
if (result != location) free(location);
return StringValue(result);
}
@@ -396,6 +432,121 @@ Value* PackageExtractFileFn(const char* name, State* state,
}
+// retouch_binaries(lib1, lib2, ...)
+Value* RetouchBinariesFn(const char* name, State* state,
+ int argc, Expr* argv[]) {
+ UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
+
+ char **retouch_entries = ReadVarArgs(state, argc, argv);
+ if (retouch_entries == NULL) {
+ return StringValue(strdup("t"));
+ }
+
+ // some randomness from the clock
+ int32_t override_base;
+ bool override_set = false;
+ int32_t random_base = time(NULL) % 1024;
+ // some more randomness from /dev/random
+ FILE *f_random = fopen("/dev/random", "rb");
+ uint16_t random_bits = 0;
+ if (f_random != NULL) {
+ fread(&random_bits, 2, 1, f_random);
+ random_bits = random_bits % 1024;
+ fclose(f_random);
+ }
+ random_base = (random_base + random_bits) % 1024;
+ fprintf(ui->cmd_pipe, "ui_print Random offset: 0x%x\n", random_base);
+ fprintf(ui->cmd_pipe, "ui_print\n");
+
+ // make sure we never randomize to zero; this let's us look at a file
+ // and know for sure whether it has been processed; important in the
+ // crash recovery process
+ if (random_base == 0) random_base = 1;
+ // make sure our randomization is page-aligned
+ random_base *= -0x1000;
+ override_base = random_base;
+
+ int i = 0;
+ bool success = true;
+ while (i < (argc - 1)) {
+ success = success && retouch_one_library(retouch_entries[i],
+ retouch_entries[i+1],
+ random_base,
+ override_set ?
+ NULL :
+ &override_base);
+ if (!success)
+ ErrorAbort(state, "Failed to retouch '%s'.", retouch_entries[i]);
+
+ free(retouch_entries[i]);
+ free(retouch_entries[i+1]);
+ i += 2;
+
+ if (success && override_base != 0) {
+ random_base = override_base;
+ override_set = true;
+ }
+ }
+ if (i < argc) {
+ free(retouch_entries[i]);
+ success = false;
+ }
+ free(retouch_entries);
+
+ if (!success) {
+ Value* v = malloc(sizeof(Value));
+ v->type = VAL_STRING;
+ v->data = NULL;
+ v->size = -1;
+ return v;
+ }
+ return StringValue(strdup("t"));
+}
+
+
+// undo_retouch_binaries(lib1, lib2, ...)
+Value* UndoRetouchBinariesFn(const char* name, State* state,
+ int argc, Expr* argv[]) {
+ UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
+
+ char **retouch_entries = ReadVarArgs(state, argc, argv);
+ if (retouch_entries == NULL) {
+ return StringValue(strdup("t"));
+ }
+
+ int i = 0;
+ bool success = true;
+ int32_t override_base;
+ while (i < (argc-1)) {
+ success = success && retouch_one_library(retouch_entries[i],
+ retouch_entries[i+1],
+ 0 /* undo => offset==0 */,
+ NULL);
+ if (!success)
+ ErrorAbort(state, "Failed to unretouch '%s'.",
+ retouch_entries[i]);
+
+ free(retouch_entries[i]);
+ free(retouch_entries[i+1]);
+ i += 2;
+ }
+ if (i < argc) {
+ free(retouch_entries[i]);
+ success = false;
+ }
+ free(retouch_entries);
+
+ if (!success) {
+ Value* v = malloc(sizeof(Value));
+ v->type = VAL_STRING;
+ v->data = NULL;
+ v->size = -1;
+ return v;
+ }
+ return StringValue(strdup("t"));
+}
+
+
// symlink target src1 src2 ...
// unlinks any previously existing src1, src2, etc before creating symlinks.
Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -974,7 +1125,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
return args[i];
}
-// Read a local file and return its contents (the char* returned
+// Read a local file and return its contents (the Value* returned
// is actually a FileContents*).
Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
@@ -987,7 +1138,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
v->type = VAL_BLOB;
FileContents fc;
- if (LoadFileContents(filename, &fc) != 0) {
+ if (LoadFileContents(filename, &fc, RETOUCH_DONT_MASK) != 0) {
ErrorAbort(state, "%s() loading \"%s\" failed: %s",
name, filename, strerror(errno));
free(filename);
@@ -1014,6 +1165,8 @@ void RegisterInstallFunctions() {
RegisterFunction("delete_recursive", DeleteFn);
RegisterFunction("package_extract_dir", PackageExtractDirFn);
RegisterFunction("package_extract_file", PackageExtractFileFn);
+ RegisterFunction("retouch_binaries", RetouchBinariesFn);
+ RegisterFunction("undo_retouch_binaries", UndoRetouchBinariesFn);
RegisterFunction("symlink", SymlinkFn);
RegisterFunction("set_perm", SetPermFn);
RegisterFunction("set_perm_recursive", SetPermFn);