summaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
Diffstat (limited to 'updater')
-rw-r--r--updater/install.c172
1 files changed, 107 insertions, 65 deletions
diff --git a/updater/install.c b/updater/install.c
index 2ffb3842f..e869134be 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -705,52 +705,124 @@ done:
return StringValue(result);
}
-// apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1:patch, ...)
-// apply_patch_check(file, sha1, ...)
// apply_patch_space(bytes)
-Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
- printf("in applypatchfn (%s)\n", name);
+Value* ApplyPatchSpaceFn(const char* name, State* state,
+ int argc, Expr* argv[]) {
+ char* bytes_str;
+ if (ReadArgs(state, argv, 1, &bytes_str) < 0) {
+ return NULL;
+ }
- char* prepend = NULL;
- if (strstr(name, "check") != NULL) {
- prepend = "-c";
- } else if (strstr(name, "space") != NULL) {
- prepend = "-s";
+ char* endptr;
+ size_t bytes = strtol(bytes_str, &endptr, 10);
+ if (bytes == 0 && endptr == bytes_str) {
+ ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n",
+ name, bytes_str);
+ free(bytes_str);
+ return NULL;
}
- char** args = ReadVarArgs(state, argc, argv);
- if (args == NULL) return NULL;
+ return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t"));
+}
- // insert the "program name" argv[0] and a copy of the "prepend"
- // string (if any) at the start of the args.
- int extra = 1 + (prepend != NULL ? 1 : 0);
- char** temp = malloc((argc+extra) * sizeof(char*));
- memcpy(temp+extra, args, argc * sizeof(char*));
- temp[0] = strdup("updater");
- if (prepend) {
- temp[1] = strdup(prepend);
+// 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 "
+ "even number, got %d",
+ name, argc);
+ }
+
+ char* source_filename;
+ char* target_filename;
+ char* target_sha1;
+ char* target_size_str;
+ if (ReadArgs(state, argv, 4, &source_filename, &target_filename,
+ &target_sha1, &target_size_str) < 0) {
+ return NULL;
}
- free(args);
- args = temp;
- argc += extra;
- printf("calling applypatch\n");
- fflush(stdout);
- int result = applypatch(argc, args);
- printf("applypatch returned %d\n", result);
+ char* endptr;
+ size_t target_size = strtol(target_size_str, &endptr, 10);
+ if (target_size == 0 && endptr == target_size_str) {
+ ErrorAbort(state, "%s(): can't parse \"%s\" as byte count",
+ name, target_size_str);
+ free(source_filename);
+ free(target_filename);
+ free(target_sha1);
+ free(target_size_str);
+ return NULL;
+ }
+
+ int patchcount = (argc-4) / 2;
+ Value** patches = ReadValueVarArgs(state, argc-4, argv+4);
int i;
- for (i = 0; i < argc; ++i) {
- free(args[i]);
+ for (i = 0; i < patchcount; ++i) {
+ if (patches[i*2]->type != VAL_STRING) {
+ ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i);
+ break;
+ }
+ if (patches[i*2+1]->type != VAL_BLOB) {
+ ErrorAbort(state, "%s(): patch #%d is not blob", name, i);
+ break;
+ }
+ }
+ if (i != patchcount) {
+ for (i = 0; i < patchcount*2; ++i) {
+ FreeValue(patches[i]);
+ }
+ free(patches);
+ return NULL;
}
- free(args);
- switch (result) {
- case 0: return StringValue(strdup("t"));
- case 1: return StringValue(strdup(""));
- default: return ErrorAbort(state, "applypatch couldn't parse args");
+ char** patch_sha_str = malloc(patchcount * sizeof(char*));
+ for (i = 0; i < patchcount; ++i) {
+ patch_sha_str[i] = patches[i*2]->data;
+ patches[i*2]->data = NULL;
+ FreeValue(patches[i*2]);
+ patches[i] = patches[i*2+1];
}
+
+ int result = applypatch(source_filename, target_filename,
+ target_sha1, target_size,
+ patchcount, patch_sha_str, patches);
+
+ for (i = 0; i < patchcount; ++i) {
+ FreeValue(patches[i]);
+ }
+ free(patch_sha_str);
+ free(patches);
+
+ return StringValue(strdup(result == 0 ? "t" : ""));
+}
+
+// apply_patch_check(file, [sha1_1, ...])
+Value* ApplyPatchCheckFn(const char* name, State* state,
+ int argc, Expr* argv[]) {
+ if (argc < 1) {
+ return ErrorAbort(state, "%s(): expected at least 1 arg, got %d",
+ name, argc);
+ }
+
+ char* filename;
+ if (ReadArgs(state, argv, 1, &filename) < 0) {
+ return NULL;
+ }
+
+ int patchcount = argc-1;
+ char** sha1s = ReadVarArgs(state, argc-1, argv+1);
+
+ int result = applypatch_check(filename, patchcount, sha1s);
+
+ int i;
+ for (i = 0; i < patchcount; ++i) {
+ free(sha1s[i]);
+ }
+ free(sha1s);
+
+ return StringValue(strdup(result == 0 ? "t" : ""));
}
Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -831,36 +903,6 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(strdup(buffer));
}
-// Take a string 'str' of 40 hex digits and parse it into the 20
-// byte array 'digest'. 'str' may contain only the digest or be of
-// the form "<digest>:<anything>". Return 0 on success, -1 on any
-// error.
-static int ParseSha1(const char* str, uint8_t* digest) {
- int i;
- const char* ps = str;
- uint8_t* pd = digest;
- for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
- int digit;
- if (*ps >= '0' && *ps <= '9') {
- digit = *ps - '0';
- } else if (*ps >= 'a' && *ps <= 'f') {
- digit = *ps - 'a' + 10;
- } else if (*ps >= 'A' && *ps <= 'F') {
- digit = *ps - 'A' + 10;
- } else {
- return -1;
- }
- if (i % 2 == 0) {
- *pd = digit << 4;
- } else {
- *pd |= digit;
- ++pd;
- }
- }
- if (*ps != '\0') return -1;
- return 0;
-}
-
// 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);
@@ -981,8 +1023,8 @@ void RegisterInstallFunctions() {
RegisterFunction("write_raw_image", WriteRawImageFn);
RegisterFunction("apply_patch", ApplyPatchFn);
- RegisterFunction("apply_patch_check", ApplyPatchFn);
- RegisterFunction("apply_patch_space", ApplyPatchFn);
+ RegisterFunction("apply_patch_check", ApplyPatchCheckFn);
+ RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
RegisterFunction("read_file", ReadFileFn);
RegisterFunction("sha1_check", Sha1CheckFn);