aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2012-11-24 16:50:10 -0800
committerKoushik Dutta <koushd@gmail.com>2012-11-24 17:01:08 -0800
commiteaee7190f5ab851a76cd59e899dce253297cbb31 (patch)
treef2a2551ed2c38e45fb0bcd838c304a489bd6f225
parent53e139f8b3b982f130d387a6261a1613435d6f40 (diff)
downloadbootable_recovery-eaee7190f5ab851a76cd59e899dce253297cbb31.zip
bootable_recovery-eaee7190f5ab851a76cd59e899dce253297cbb31.tar.gz
bootable_recovery-eaee7190f5ab851a76cd59e899dce253297cbb31.tar.bz2
Pull in android 4.2 updater bits willy nilly. Next commit will fix.
Change-Id: Id2616d1fead045688a5acf13b3420016322f664b
-rw-r--r--applypatch/Android.mk1
-rw-r--r--applypatch/applypatch.c13
-rw-r--r--applypatch/applypatch.h6
-rw-r--r--applypatch/imgdiff.c57
-rw-r--r--applypatch/imgpatch.c21
-rw-r--r--applypatch/main.c23
-rw-r--r--minzip/inline_magic.h2
-rw-r--r--testdata/otasigned_f4.zipbin0 -> 5195 bytes
-rw-r--r--testdata/test_f4.pk8bin0 -> 1217 bytes
-rw-r--r--testdata/test_f4.x509.pem25
-rw-r--r--tools/ota/check-lost+found.c2
-rw-r--r--updater/Android.mk32
-rw-r--r--updater/install.c99
13 files changed, 233 insertions, 48 deletions
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 0e529d4..ef57f24 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -50,7 +50,6 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := imgdiff.c utils.c bsdiff.c
LOCAL_MODULE := imgdiff
LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += external/zlib external/bzip2
LOCAL_STATIC_LIBRARIES += libz libbz
diff --git a/applypatch/applypatch.c b/applypatch/applypatch.c
index 488fd8c..7b8a010 100644
--- a/applypatch/applypatch.c
+++ b/applypatch/applypatch.c
@@ -39,7 +39,8 @@ static int GenerateTarget(FileContents* source_file,
const char* source_filename,
const char* target_filename,
const uint8_t target_sha1[SHA_DIGEST_SIZE],
- size_t target_size);
+ size_t target_size,
+ const Value* bonus_data);
static int mtd_partitions_scanned = 0;
@@ -617,7 +618,8 @@ int applypatch(const char* source_filename,
size_t target_size,
int num_patches,
char** const patch_sha1_str,
- Value** patch_data) {
+ Value** patch_data,
+ Value* bonus_data) {
printf("\napplying patch to %s\n", source_filename);
if (target_filename[0] == '-' &&
@@ -699,7 +701,7 @@ int applypatch(const char* source_filename,
int result = GenerateTarget(&source_file, source_patch_value,
&copy_file, copy_patch_value,
source_filename, target_filename,
- target_sha1, target_size);
+ target_sha1, target_size, bonus_data);
free(source_file.data);
free(copy_file.data);
@@ -713,7 +715,8 @@ static int GenerateTarget(FileContents* source_file,
const char* source_filename,
const char* target_filename,
const uint8_t target_sha1[SHA_DIGEST_SIZE],
- size_t target_size) {
+ size_t target_size,
+ const Value* bonus_data) {
int retry = 1;
SHA_CTX ctx;
int output;
@@ -867,7 +870,7 @@ static int GenerateTarget(FileContents* source_file,
} else if (header_bytes_read >= 8 &&
memcmp(header, "IMGDIFF2", 8) == 0) {
result = ApplyImagePatch(source_to_use->data, source_to_use->size,
- patch, sink, token, &ctx);
+ patch, sink, token, &ctx, bonus_data);
} else {
printf("Unknown patch file format\n");
return 1;
diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h
index fb58843..d1a0232 100644
--- a/applypatch/applypatch.h
+++ b/applypatch/applypatch.h
@@ -55,7 +55,8 @@ int applypatch(const char* source_filename,
size_t target_size,
int num_patches,
char** const patch_sha1_str,
- Value** patch_data);
+ Value** patch_data,
+ Value* bonus_data);
int applypatch_check(const char* filename,
int num_patches,
char** const patch_sha1_str);
@@ -79,7 +80,8 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
// imgpatch.c
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch,
- SinkFn sink, void* token, SHA_CTX* ctx);
+ SinkFn sink, void* token, SHA_CTX* ctx,
+ const Value* bonus_data);
// freecache.c
int MakeFreeSpaceOnCache(size_t bytes_needed);
diff --git a/applypatch/imgdiff.c b/applypatch/imgdiff.c
index 6b9ebee..05c4f25 100644
--- a/applypatch/imgdiff.c
+++ b/applypatch/imgdiff.c
@@ -111,6 +111,14 @@
*
* After the header there are 'chunk count' bsdiff patches; the offset
* of each from the beginning of the file is specified in the header.
+ *
+ * This tool can take an optional file of "bonus data". This is an
+ * extra file of data that is appended to chunk #1 after it is
+ * compressed (it must be a CHUNK_DEFLATE chunk). The same file must
+ * be available (and passed to applypatch with -b) when applying the
+ * patch. This is used to reduce the size of recovery-from-boot
+ * patches by combining the boot image with recovery ramdisk
+ * information that is stored on the system partition.
*/
#include <errno.h>
@@ -772,21 +780,45 @@ void DumpChunks(ImageChunk* chunks, int num_chunks) {
}
int main(int argc, char** argv) {
- if (argc != 4 && argc != 5) {
- usage:
- printf("usage: %s [-z] <src-img> <tgt-img> <patch-file>\n",
- argv[0]);
- return 2;
- }
-
int zip_mode = 0;
- if (strcmp(argv[1], "-z") == 0) {
+ if (argc >= 2 && strcmp(argv[1], "-z") == 0) {
zip_mode = 1;
--argc;
++argv;
}
+ size_t bonus_size = 0;
+ unsigned char* bonus_data = NULL;
+ if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
+ struct stat st;
+ if (stat(argv[2], &st) != 0) {
+ printf("failed to stat bonus file %s: %s\n", argv[2], strerror(errno));
+ return 1;
+ }
+ bonus_size = st.st_size;
+ bonus_data = malloc(bonus_size);
+ FILE* f = fopen(argv[2], "rb");
+ if (f == NULL) {
+ printf("failed to open bonus file %s: %s\n", argv[2], strerror(errno));
+ return 1;
+ }
+ if (fread(bonus_data, 1, bonus_size, f) != bonus_size) {
+ printf("failed to read bonus file %s: %s\n", argv[2], strerror(errno));
+ return 1;
+ }
+ fclose(f);
+
+ argc -= 2;
+ argv += 2;
+ }
+
+ if (argc != 4) {
+ usage:
+ printf("usage: %s [-z] [-b <bonus-file>] <src-img> <tgt-img> <patch-file>\n",
+ argv[0]);
+ return 2;
+ }
int num_src_chunks;
ImageChunk* src_chunks;
@@ -909,6 +941,8 @@ int main(int argc, char** argv) {
// Compute bsdiff patches for each chunk's data (the uncompressed
// data, in the case of deflate chunks).
+ DumpChunks(src_chunks, num_src_chunks);
+
printf("Construct patches for %d chunks...\n", num_tgt_chunks);
unsigned char** patch_data = malloc(num_tgt_chunks * sizeof(unsigned char*));
size_t* patch_size = malloc(num_tgt_chunks * sizeof(size_t));
@@ -923,6 +957,13 @@ int main(int argc, char** argv) {
patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i);
}
} else {
+ if (i == 1 && bonus_data) {
+ printf(" using %d bytes of bonus data for chunk %d\n", bonus_size, i);
+ src_chunks[i].data = realloc(src_chunks[i].data, src_chunks[i].len + bonus_size);
+ memcpy(src_chunks[i].data+src_chunks[i].len, bonus_data, bonus_size);
+ src_chunks[i].len += bonus_size;
+ }
+
patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i);
}
printf("patch %3d is %d bytes (of %d)\n",
diff --git a/applypatch/imgpatch.c b/applypatch/imgpatch.c
index e3ee80a..3a1df38 100644
--- a/applypatch/imgpatch.c
+++ b/applypatch/imgpatch.c
@@ -37,7 +37,8 @@
*/
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch,
- SinkFn sink, void* token, SHA_CTX* ctx) {
+ SinkFn sink, void* token, SHA_CTX* ctx,
+ const Value* bonus_data) {
ssize_t pos = 12;
char* header = patch->data;
if (patch->size < 12) {
@@ -123,6 +124,12 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// Decompress the source data; the chunk header tells us exactly
// how big we expect it to be when decompressed.
+ // Note: expanded_len will include the bonus data size if
+ // the patch was constructed with bonus data. The
+ // deflation will come up 'bonus_size' bytes short; these
+ // must be appended from the bonus_data value.
+ size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0;
+
unsigned char* expanded_source = malloc(expanded_len);
if (expanded_source == NULL) {
printf("failed to allocate %d bytes for expanded_source\n",
@@ -153,13 +160,19 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
printf("source inflation returned %d\n", ret);
return -1;
}
- // We should have filled the output buffer exactly.
- if (strm.avail_out != 0) {
- printf("source inflation short by %d bytes\n", strm.avail_out);
+ // We should have filled the output buffer exactly, except
+ // for the bonus_size.
+ if (strm.avail_out != bonus_size) {
+ printf("source inflation short by %d bytes\n", strm.avail_out-bonus_size);
return -1;
}
inflateEnd(&strm);
+ if (bonus_size) {
+ memcpy(expanded_source + (expanded_len - bonus_size),
+ bonus_data->data, bonus_size);
+ }
+
// Next, apply the bsdiff patch (in memory) to the uncompressed
// data.
unsigned char* uncompressed_target_data;
diff --git a/applypatch/main.c b/applypatch/main.c
index 7025a2e..f61db5d 100644
--- a/applypatch/main.c
+++ b/applypatch/main.c
@@ -100,6 +100,21 @@ static int ParsePatchArgs(int argc, char** argv,
}
int PatchMode(int argc, char** argv) {
+ Value* bonus = NULL;
+ if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
+ FileContents fc;
+ if (LoadFileContents(argv[2], &fc, RETOUCH_DONT_MASK) != 0) {
+ printf("failed to load bonus file %s\n", argv[2]);
+ return 1;
+ }
+ bonus = malloc(sizeof(Value));
+ bonus->type = VAL_BLOB;
+ bonus->size = fc.size;
+ bonus->data = (char*)fc.data;
+ argc -= 2;
+ argv += 2;
+ }
+
if (argc < 6) {
return 2;
}
@@ -120,7 +135,7 @@ int PatchMode(int argc, char** argv) {
}
int result = applypatch(argv[1], argv[2], argv[3], target_size,
- num_patches, sha1s, patches);
+ num_patches, sha1s, patches, bonus);
int i;
for (i = 0; i < num_patches; ++i) {
@@ -130,6 +145,10 @@ int PatchMode(int argc, char** argv) {
free(p);
}
}
+ if (bonus) {
+ free(bonus->data);
+ free(bonus);
+ }
free(sha1s);
free(patches);
@@ -163,7 +182,7 @@ int main(int argc, char** argv) {
if (argc < 2) {
usage:
printf(
- "usage: %s <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
+ "usage: %s [-b <bonus-file>] <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
"[<src-sha1>:<patch> ...]\n"
" or %s -c <file> [<sha1> ...]\n"
" or %s -s <bytes>\n"
diff --git a/minzip/inline_magic.h b/minzip/inline_magic.h
index 8c185e1..59c659f 100644
--- a/minzip/inline_magic.h
+++ b/minzip/inline_magic.h
@@ -18,7 +18,7 @@
#define MINZIP_INLINE_MAGIC_H_
#ifndef MINZIP_GENERATE_INLINES
-#define INLINE extern __inline__
+#define INLINE extern inline __attribute((__gnu_inline__))
#else
#define INLINE
#endif
diff --git a/testdata/otasigned_f4.zip b/testdata/otasigned_f4.zip
new file mode 100644
index 0000000..dd1e4dd
--- /dev/null
+++ b/testdata/otasigned_f4.zip
Binary files differ
diff --git a/testdata/test_f4.pk8 b/testdata/test_f4.pk8
new file mode 100644
index 0000000..3052613
--- /dev/null
+++ b/testdata/test_f4.pk8
Binary files differ
diff --git a/testdata/test_f4.x509.pem b/testdata/test_f4.x509.pem
new file mode 100644
index 0000000..814abcf
--- /dev/null
+++ b/testdata/test_f4.x509.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIJAKhkCO1dDYMaMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBW
+aWV3MQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMT
+B1Rlc3QxMjMwHhcNMTIwNzI1MTg1NzAzWhcNMzkxMjExMTg1NzAzWjBvMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
+VmlldzEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQD
+EwdUZXN0MTIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu8WwMN9x
+4Mz7YgkG2qy9g8/kl5ZoYrUM0ApHhaITAcL7RXLZaNipCf0w/YjYTQgj+75MK30x
+TsnPeWNOEwA62gkHrZyyWfxBRO6kBYuIuI4roGDBJOmKQ1OEaDeIRKu7q5V8v3Cs
+0wQDAQWTbhpxBZr9UYFgJUg8XWBfPrGJLVwsoiy4xrMhoTlNZKHfwOMMqVtSHkZX
+qydYrcIzyjh+TO0e/xSNQ8MMRRbtqWgCHN6Rzhog3IHZu0RaPoukariopjXM/s0V
+gTm3rHDHCOpna2pNblyiFlvbkoCs769mtNmx/yrDShO30jg/xaG8RypKDvTChzOT
+oWW/XQ5VEXjbHwIDAQABo4HUMIHRMB0GA1UdDgQWBBRlT2dEZJY1tmUM8mZ0xnhS
+GdD9TTCBoQYDVR0jBIGZMIGWgBRlT2dEZJY1tmUM8mZ0xnhSGdD9TaFzpHEwbzEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50
+YWluIFZpZXcxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEQMA4G
+A1UEAxMHVGVzdDEyM4IJAKhkCO1dDYMaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADggEBAHqnXHtE+h3hvGmHh24GT51vGAYLc68WUUtCVlMIU85zQ757wlxZ
+BmRypZ1i9hSqnXj5n+mETV5rFX3g2gvdAPVHkRycuDa2aUdZSE8cW4Z6qYFx6SaD
+e+3SyXokpUquW64RuHJrf/yd/FnGjneBe3Qpm2reuzGWNH90qZGdbsfNaCm5kx2L
+X+ZNHM3CcGMLaphY5++sM0JxSEcju5EK33ZYgLf4YdlbyMp8LDFVNd7ff0SFi9fF
+0ZlAsJWoS3QmVCj2744BFdsCu7UHpnYpG6X3MT4SHAawdOaT5zSuaCl2xx6H0O7t
+w/Fvbl/KVD1ZmLHgBKjDMNSh0OB9mSsDWpw=
+-----END CERTIFICATE-----
diff --git a/tools/ota/check-lost+found.c b/tools/ota/check-lost+found.c
index f856275..da02f46 100644
--- a/tools/ota/check-lost+found.c
+++ b/tools/ota/check-lost+found.c
@@ -44,7 +44,7 @@ static const char *kPartitions[] = { "/system", "/data", "/cache", NULL };
* 2. Write a log entry with the number of files in lost+found directories.
*/
-int main(int argc, char **argv) {
+int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) {
mkdir(kOutputDir, 0755);
chown(kOutputDir, AID_SYSTEM, AID_SYSTEM);
FILE *out = fopen(kOutputFile, "a");
diff --git a/updater/Android.mk b/updater/Android.mk
index a3f6c28..8876120 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -3,7 +3,6 @@
LOCAL_PATH := $(call my-dir)
updater_src_files := \
- ../mounts.c \
install.c \
updater.c
@@ -22,7 +21,10 @@ LOCAL_SRC_FILES := $(updater_src_files)
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
LOCAL_CFLAGS += -DUSE_EXT4
LOCAL_C_INCLUDES += system/extras/ext4_utils
-LOCAL_STATIC_LIBRARIES += libext4_utils_static libz libsparse_static
+LOCAL_STATIC_LIBRARIES += \
+ libext4_utils_static \
+ libsparse_static \
+ libz
endif
ifeq ($(HAVE_SELINUX), true)
@@ -31,8 +33,6 @@ LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_CFLAGS += -DHAVE_SELINUX
endif # HAVE_SELINUX
-LOCAL_STATIC_LIBRARIES += libflashutils libmtdutils libmmcutils libbmlutils
-
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
@@ -53,18 +53,19 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
inc := $(call intermediates-dir-for,PACKAGING,updater_extensions)/register.inc
-# During the first pass of reading the makefiles, we dump the list of
-# extension libs to a temp file, then copy that to the ".list" file if
-# it is different than the existing .list (if any). The register.inc
-# file then uses the .list as a prerequisite, so it is only rebuilt
-# (and updater.o recompiled) when the list of extension libs changes.
-
-junk := $(shell mkdir -p $(dir $(inc));\
- echo $(TARGET_RECOVERY_UPDATER_LIBS) > $(inc).temp;\
- diff -q $(inc).temp $(inc).list 2>/dev/null || cp -f $(inc).temp $(inc).list)
+# Encode the value of TARGET_RECOVERY_UPDATER_LIBS into the filename of the dependency.
+# So if TARGET_RECOVERY_UPDATER_LIBS is changed, a new dependency file will be generated.
+# Note that we have to remove any existing depency files before creating new one,
+# so no obsolete dependecy file gets used if you switch back to an old value.
+inc_dep_file := $(inc).dep.$(subst $(space),-,$(sort $(TARGET_RECOVERY_UPDATER_LIBS)))
+$(inc_dep_file): stem := $(inc).dep
+$(inc_dep_file) :
+ $(hide) mkdir -p $(dir $@)
+ $(hide) rm -f $(stem).*
+ $(hide) touch $@
$(inc) : libs := $(TARGET_RECOVERY_UPDATER_LIBS)
-$(inc) : $(inc).list
+$(inc) : $(inc_dep_file)
$(hide) mkdir -p $(dir $@)
$(hide) echo "" > $@
$(hide) $(foreach lib,$(libs),echo "extern void Register_$(lib)(void);" >> $@;)
@@ -75,6 +76,9 @@ $(inc) : $(inc).list
$(call intermediates-dir-for,EXECUTABLES,updater)/updater.o : $(inc)
LOCAL_C_INCLUDES += $(dir $(inc))
+inc :=
+inc_dep_file :=
+
LOCAL_MODULE := updater
LOCAL_FORCE_STATIC_EXECUTABLE := true
diff --git a/updater/install.c b/updater/install.c
index 1ad6d81..41f053d 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -33,7 +33,7 @@
#include "edify/expr.h"
#include "mincrypt/sha.h"
#include "minzip/DirUtil.h"
-#include "mounts.h"
+#include "mtdutils/mounts.h"
#include "mtdutils/mtdutils.h"
#include "updater.h"
#include "applypatch/applypatch.h"
@@ -456,6 +456,26 @@ Value* PackageExtractFileFn(const char* name, State* state,
}
}
+// Create all parent directories of name, if necessary.
+static int make_parents(char* name) {
+ char* p;
+ for (p = name + (strlen(name)-1); p > name; --p) {
+ if (*p != '/') continue;
+ *p = '\0';
+ if (make_parents(name) < 0) return -1;
+ int result = mkdir(name, 0700);
+ if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name);
+ *p = '/';
+ if (result == 0 || errno == EEXIST) {
+ // successfully created or already existed; we're done
+ return 0;
+ } else {
+ fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
// symlink target src1 src2 ...
// unlinks any previously existing src1, src2, etc before creating symlinks.
@@ -483,6 +503,11 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
++bad;
}
}
+ if (make_parents(srcs[i])) {
+ fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n",
+ name, srcs[i], target);
+ ++bad;
+ }
if (symlink(target, srcs[i]) < 0) {
fprintf(stderr, "%s: failed to symlink %s to %s: %s\n",
name, srcs[i], target, strerror(errno));
@@ -504,7 +529,8 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) {
int min_args = 4 + (recursive ? 1 : 0);
if (argc < min_args) {
- return ErrorAbort(state, "%s() expects %d+ args, got %d", name, argc);
+ return ErrorAbort(state, "%s() expects %d+ args, got %d",
+ name, min_args, argc);
}
char** args = ReadVarArgs(state, argc, argv);
@@ -626,7 +652,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
buffer = malloc(st.st_size+1);
if (buffer == NULL) {
- ErrorAbort(state, "%s: failed to alloc %d bytes", name, st.st_size+1);
+ ErrorAbort(state, "%s: failed to alloc %lld bytes", name, st.st_size+1);
goto done;
}
@@ -638,7 +664,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (fread(buffer, 1, st.st_size, f) != st.st_size) {
- ErrorAbort(state, "%s: failed to read %d bytes from %s",
+ ErrorAbort(state, "%s: failed to read %lld bytes from %s",
name, st.st_size+1, filename);
fclose(f);
goto done;
@@ -712,11 +738,12 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
return NULL;
}
+ char* partition = NULL;
if (partition_value->type != VAL_STRING) {
ErrorAbort(state, "partition argument to %s must be string", name);
goto done;
}
- char* partition = partition_value->data;
+ partition = partition_value->data;
if (strlen(partition) == 0) {
ErrorAbort(state, "partition argument to %s can't be empty", name);
goto done;
@@ -726,14 +753,66 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
goto done;
}
- char* filename = contents->data;
- if (0 == restore_raw_partition(NULL, partition, filename))
- result = strdup(partition);
- else {
+ mtd_scan_partitions();
+ const MtdPartition* mtd = mtd_find_partition_by_name(partition);
+ if (mtd == NULL) {
+ fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition);
+ result = strdup("");
+ goto done;
+ }
+
+ MtdWriteContext* ctx = mtd_write_partition(mtd);
+ if (ctx == NULL) {
+ fprintf(stderr, "%s: can't write mtd partition \"%s\"\n",
+ name, partition);
result = strdup("");
goto done;
}
+ bool success;
+
+ if (contents->type == VAL_STRING) {
+ // we're given a filename as the contents
+ char* filename = contents->data;
+ FILE* f = fopen(filename, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ name, filename, strerror(errno));
+ result = strdup("");
+ goto done;
+ }
+
+ success = true;
+ char* buffer = malloc(BUFSIZ);
+ int read;
+ while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
+ int wrote = mtd_write_data(ctx, buffer, read);
+ success = success && (wrote == read);
+ }
+ free(buffer);
+ fclose(f);
+ } else {
+ // we're given a blob as the contents
+ ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
+ success = (wrote == contents->size);
+ }
+ if (!success) {
+ fprintf(stderr, "mtd_write_data to %s failed: %s\n",
+ partition, strerror(errno));
+ }
+
+ if (mtd_erase_blocks(ctx, -1) == -1) {
+ fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
+ }
+ if (mtd_write_close(ctx) != 0) {
+ fprintf(stderr, "%s: error closing write of %s\n", name, partition);
+ }
+
+ printf("%s %s partition\n",
+ success ? "wrote" : "failed to write", partition);
+
+ result = success ? partition : strdup("");
+
done:
if (result != partition) FreeValue(partition_value);
FreeValue(contents);
@@ -822,7 +901,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
int result = applypatch(source_filename, target_filename,
target_sha1, target_size,
- patchcount, patch_sha_str, patches);
+ patchcount, patch_sha_str, patches, NULL);
for (i = 0; i < patchcount; ++i) {
FreeValue(patches[i]);