From 6aece33b3f3af6a161e326af36bc894427fcf5ad Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Mon, 1 Feb 2010 14:40:12 -0800 Subject: add a one-argument version of package_extract_file Add a version of package_extract_file that returns the file data as its return value (to be consumed by some other edify function that expects to receive a bunch of binary data as an argument). Lets us avoid having two copies of a big file in memory (extracting it into /tmp, which is a ramdisk, and then having something load it into memory) when doing things like radio updates. Change-Id: Ie26ece5fbae457eb0ddcd8a13d74d78a769fbc70 --- updater/install.c | 93 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 24 deletions(-) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index aa80d7576..934acaae4 100644 --- a/updater/install.c +++ b/updater/install.c @@ -315,37 +315,82 @@ char* PackageExtractDirFn(const char* name, State* state, // package_extract_file(package_path, destination_path) +// or +// package_extract_file(package_path) +// to return the entire contents of the file as the result of this +// function (the char* returned points to a long giving the length +// followed by that many bytes of data). char* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); + if (argc != 1 && argc != 2) { + return ErrorAbort(state, "%s() expects 1 or 2 args, got %d", + name, argc); } - char* zip_path; - char* dest_path; - if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL; - bool success = false; + if (argc == 2) { + // The two-argument version extracts to a file. + + 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) { + fprintf(stderr, "%s: no %s in package\n", name, zip_path); + goto done2; + } - ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; - const ZipEntry* entry = mzFindZipEntry(za, zip_path); - if (entry == NULL) { - fprintf(stderr, "%s: no %s in package\n", name, zip_path); - goto done; - } + FILE* f = fopen(dest_path, "wb"); + if (f == NULL) { + fprintf(stderr, "%s: can't open %s for write: %s\n", + name, dest_path, strerror(errno)); + goto done2; + } + success = mzExtractZipEntryToFile(za, entry, fileno(f)); + fclose(f); - FILE* f = fopen(dest_path, "wb"); - if (f == NULL) { - fprintf(stderr, "%s: can't open %s for write: %s\n", - name, dest_path, strerror(errno)); - goto done; - } - success = mzExtractZipEntryToFile(za, entry, fileno(f)); - fclose(f); + done2: + free(zip_path); + free(dest_path); + return strdup(success ? "t" : ""); + } else { + // The one-argument version returns the contents of the file + // as the result. - done: - free(zip_path); - free(dest_path); - return strdup(success ? "t" : ""); + char* zip_path; + char* buffer = NULL; + + if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; + + ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; + const ZipEntry* entry = mzFindZipEntry(za, zip_path); + if (entry == NULL) { + fprintf(stderr, "%s: no %s in package\n", name, zip_path); + goto done1; + } + + long size = mzGetZipEntryUncompLen(entry); + buffer = malloc(size + sizeof(long)); + if (buffer == NULL) { + fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n", + name, size+sizeof(long), zip_path); + goto done1; + } + + *(long *)buffer = size; + success = mzExtractZipEntryToBuffer( + za, entry, (unsigned char *)(buffer + sizeof(long))); + + done1: + free(zip_path); + if (!success) { + free(buffer); + buffer = malloc(sizeof(long)); + *(long *)buffer = -1L; + } + return buffer; + } } -- cgit v1.2.3