summaryrefslogtreecommitdiffstats
path: root/applypatch
diff options
context:
space:
mode:
authorTao Bao <tbao@google.com>2016-12-28 19:18:42 +0100
committerandroid-build-merger <android-build-merger@google.com>2016-12-28 19:18:42 +0100
commit4e2471d6dd035159f198a9d76d2422e8115ef701 (patch)
tree3e8544c0a40e1b6c777236166cc88f7954c9500c /applypatch
parentMerge "tests: Add test coverage for DirUtil." am: f24d2a6b39 (diff)
parentMerge "Add tests for imgdiff." (diff)
downloadandroid_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar.gz
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar.bz2
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar.lz
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar.xz
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.tar.zst
android_bootable_recovery-4e2471d6dd035159f198a9d76d2422e8115ef701.zip
Diffstat (limited to 'applypatch')
-rw-r--r--applypatch/Android.mk90
-rw-r--r--applypatch/imgdiff.cpp54
-rw-r--r--applypatch/imgdiff_main.cpp21
-rw-r--r--applypatch/imgpatch.cpp405
-rw-r--r--applypatch/include/applypatch/imgdiff.h (renamed from applypatch/imgdiff.h)21
-rw-r--r--applypatch/include/applypatch/imgpatch.h10
6 files changed, 335 insertions, 266 deletions
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index fa0fe8a37..61e110617 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -17,7 +17,6 @@ LOCAL_PATH := $(call my-dir)
# libapplypatch (static library)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
LOCAL_SRC_FILES := \
applypatch.cpp \
bspatch.cpp \
@@ -26,11 +25,11 @@ LOCAL_SRC_FILES := \
utils.cpp
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
-LOCAL_C_INCLUDES += \
+LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += \
+LOCAL_STATIC_LIBRARIES := \
libotafault \
libbase \
libcrypto \
@@ -42,36 +41,45 @@ include $(BUILD_STATIC_LIBRARY)
# libimgpatch (static library)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
+LOCAL_SRC_FILES := \
+ bspatch.cpp \
+ imgpatch.cpp \
+ utils.cpp
LOCAL_MODULE := libimgpatch
-LOCAL_C_INCLUDES += \
+LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libcrypto libbz libz
+LOCAL_STATIC_LIBRARIES := \
+ libcrypto \
+ libbz \
+ libz
LOCAL_CFLAGS := -Werror
include $(BUILD_STATIC_LIBRARY)
# libimgpatch (host static library)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
+LOCAL_SRC_FILES := \
+ bspatch.cpp \
+ imgpatch.cpp \
+ utils.cpp
LOCAL_MODULE := libimgpatch
LOCAL_MODULE_HOST_OS := linux
-LOCAL_C_INCLUDES += \
+LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libcrypto libbz libz
+LOCAL_STATIC_LIBRARIES := \
+ libcrypto \
+ libbz \
+ libz
LOCAL_CFLAGS := -Werror
include $(BUILD_HOST_STATIC_LIBRARY)
# libapplypatch_modes (static library)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
LOCAL_SRC_FILES := \
applypatch_modes.cpp
LOCAL_MODULE := libapplypatch_modes
@@ -87,7 +95,6 @@ include $(BUILD_STATIC_LIBRARY)
# applypatch (target executable)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
LOCAL_SRC_FILES := applypatch_main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES := bootable/recovery
@@ -106,18 +113,59 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)
+libimgdiff_src_files := \
+ imgdiff.cpp \
+ utils.cpp
+
+# libbsdiff is compiled with -D_FILE_OFFSET_BITS=64.
+libimgdiff_cflags := \
+ -Werror \
+ -D_FILE_OFFSET_BITS=64
+
+libimgdiff_static_libraries := \
+ libbsdiff \
+ libz
+
+# libimgdiff (static library)
+# ===============================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ $(libimgdiff_src_files)
+LOCAL_MODULE := libimgdiff
+LOCAL_CFLAGS := \
+ $(libimgdiff_cflags)
+LOCAL_STATIC_LIBRARIES := \
+ $(libimgdiff_static_libraries)
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
+
+# libimgdiff (host static library)
+# ===============================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ $(libimgdiff_src_files)
+LOCAL_MODULE := libimgdiff
+LOCAL_CFLAGS := \
+ $(libimgdiff_cflags)
+LOCAL_STATIC_LIBRARIES := \
+ $(libimgdiff_static_libraries)
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+include $(BUILD_HOST_STATIC_LIBRARY)
+
# imgdiff (host static executable)
# ===============================
include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SRC_FILES := imgdiff.cpp utils.cpp
+LOCAL_SRC_FILES := imgdiff_main.cpp
LOCAL_MODULE := imgdiff
-LOCAL_STATIC_LIBRARIES += \
- libbsdiff \
+LOCAL_CFLAGS := -Werror
+LOCAL_STATIC_LIBRARIES := \
+ libimgdiff \
+ $(libimgdiff_static_libraries) \
libbz \
- libdivsufsort64 \
libdivsufsort \
- libz
-LOCAL_CFLAGS := -Werror
-LOCAL_FORCE_STATIC_EXECUTABLE := true
+ libdivsufsort64
include $(BUILD_HOST_EXECUTABLE)
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index 528daf113..18a15a164 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -121,19 +121,19 @@
* information that is stored on the system partition.
*/
+#include "applypatch/imgdiff.h"
+
#include <errno.h>
-#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#include <unistd.h>
#include <sys/types.h>
+#include <unistd.h>
#include <bsdiff.h>
+#include <zlib.h>
-#include "zlib.h"
-#include "imgdiff.h"
#include "utils.h"
typedef struct {
@@ -374,8 +374,7 @@ unsigned char* ReadZip(const char* filename,
* return value when done with all the chunks. Returns NULL on
* failure.
*/
-unsigned char* ReadImage(const char* filename,
- int* num_chunks, ImageChunk** chunks) {
+unsigned char* ReadImage(const char* filename, int* num_chunks, ImageChunk** chunks) {
struct stat st;
if (stat(filename, &st) != 0) {
printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
@@ -403,7 +402,7 @@ unsigned char* ReadImage(const char* filename,
*chunks = NULL;
while (pos < sz) {
- unsigned char* p = img+pos;
+ unsigned char* p = img + pos;
if (sz - pos >= 4 &&
p[0] == 0x1f && p[1] == 0x8b &&
@@ -413,8 +412,7 @@ unsigned char* ReadImage(const char* filename,
size_t chunk_offset = pos;
*num_chunks += 3;
- *chunks = static_cast<ImageChunk*>(realloc(*chunks,
- *num_chunks * sizeof(ImageChunk)));
+ *chunks = static_cast<ImageChunk*>(realloc(*chunks, *num_chunks * sizeof(ImageChunk)));
ImageChunk* curr = *chunks + (*num_chunks-3);
// create a normal chunk for the header.
@@ -502,8 +500,7 @@ unsigned char* ReadImage(const char* filename,
// the decompression.
size_t footer_size = Read4(p-4);
if (footer_size != curr[-2].len) {
- printf("Error: footer size %zu != decompressed size %zu\n",
- footer_size, curr[-2].len);
+ printf("Error: footer size %zu != decompressed size %zu\n", footer_size, curr[-2].len);
free(img);
return NULL;
}
@@ -637,7 +634,11 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
}
}
+#if defined(__ANDROID__)
+ char ptemp[] = "/data/local/tmp/imgdiff-patch-XXXXXX";
+#else
char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
+#endif
int fd = mkstemp(ptemp);
if (fd == -1) {
@@ -793,10 +794,8 @@ void MergeAdjacentNormalChunks(ImageChunk* chunks, int* num_chunks) {
*num_chunks = out;
}
-ImageChunk* FindChunkByName(const char* name,
- ImageChunk* chunks, int num_chunks) {
- int i;
- for (i = 0; i < num_chunks; ++i) {
+ImageChunk* FindChunkByName(const char* name, ImageChunk* chunks, int num_chunks) {
+ for (int i = 0; i < num_chunks; ++i) {
if (chunks[i].type == CHUNK_DEFLATE && chunks[i].filename &&
strcmp(name, chunks[i].filename) == 0) {
return chunks+i;
@@ -812,11 +811,11 @@ void DumpChunks(ImageChunk* chunks, int num_chunks) {
}
}
-int main(int argc, char** argv) {
- int zip_mode = 0;
+int imgdiff(int argc, const char** argv) {
+ bool zip_mode = false;
if (argc >= 2 && strcmp(argv[1], "-z") == 0) {
- zip_mode = 1;
+ zip_mode = true;
--argc;
++argv;
}
@@ -880,12 +879,10 @@ int main(int argc, char** argv) {
// Verify that the source and target images have the same chunk
// structure (ie, the same sequence of deflate and normal chunks).
- if (!zip_mode) {
- // Merge the gzip header and footer in with any adjacent
- // normal chunks.
- MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
- MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
- }
+ // Merge the gzip header and footer in with any adjacent
+ // normal chunks.
+ MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
+ MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
if (num_src_chunks != num_tgt_chunks) {
printf("source and target don't have same number of chunks!\n");
@@ -897,8 +894,7 @@ int main(int argc, char** argv) {
}
for (i = 0; i < num_src_chunks; ++i) {
if (src_chunks[i].type != tgt_chunks[i].type) {
- printf("source and target don't have same chunk "
- "structure! (chunk %d)\n", i);
+ printf("source and target don't have same chunk structure! (chunk %d)\n", i);
printf("source chunks:\n");
DumpChunks(src_chunks, num_src_chunks);
printf("target chunks:\n");
@@ -983,8 +979,7 @@ int main(int argc, char** argv) {
if (zip_mode) {
ImageChunk* src;
if (tgt_chunks[i].type == CHUNK_DEFLATE &&
- (src = FindChunkByName(tgt_chunks[i].filename, src_chunks,
- num_src_chunks))) {
+ (src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks))) {
patch_data[i] = MakePatch(src, tgt_chunks+i, patch_size+i);
} else {
patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i);
@@ -1000,8 +995,7 @@ int main(int argc, char** argv) {
patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i);
}
- printf("patch %3d is %zu bytes (of %zu)\n",
- i, patch_size[i], tgt_chunks[i].source_len);
+ printf("patch %3d is %zu bytes (of %zu)\n", i, patch_size[i], tgt_chunks[i].source_len);
}
// Figure out how big the imgdiff file header is going to be, so
diff --git a/applypatch/imgdiff_main.cpp b/applypatch/imgdiff_main.cpp
new file mode 100644
index 000000000..7d5bdf9aa
--- /dev/null
+++ b/applypatch/imgdiff_main.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "applypatch/imgdiff.h"
+
+int main(int argc, char** argv) {
+ return imgdiff(argc, const_cast<const char**>(argv));
+}
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 1c4409e36..ae6071f0e 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -14,32 +14,34 @@
* limitations under the License.
*/
-// See imgdiff.c in this directory for a description of the patch file
+// See imgdiff.cpp in this directory for a description of the patch file
// format.
+#include <applypatch/imgpatch.h>
+
+#include <errno.h>
#include <stdio.h>
+#include <string.h>
#include <sys/cdefs.h>
#include <sys/stat.h>
-#include <errno.h>
#include <unistd.h>
-#include <string.h>
#include <string>
#include <vector>
-#include "zlib.h"
-#include "openssl/sha.h"
-#include "applypatch/applypatch.h"
-#include "imgdiff.h"
+#include <applypatch/applypatch.h>
+#include <applypatch/imgdiff.h>
+#include <openssl/sha.h>
+#include <zlib.h>
+
#include "utils.h"
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const unsigned char* patch_data, ssize_t patch_size,
SinkFn sink, void* token) {
- Value patch(VAL_BLOB, std::string(
- reinterpret_cast<const char*>(patch_data), patch_size));
+ Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));
- return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
+ return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
}
/*
@@ -48,208 +50,201 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
* file, and update the SHA context with the output data as well.
* Return 0 on success.
*/
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
- const Value* patch,
- SinkFn sink, void* token, SHA_CTX* ctx,
- const Value* bonus_data) {
- if (patch->data.size() < 12) {
- printf("patch too short to contain header\n");
- return -1;
+int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value* patch,
+ SinkFn sink, void* token, SHA_CTX* ctx, const Value* bonus_data) {
+ if (patch->data.size() < 12) {
+ printf("patch too short to contain header\n");
+ return -1;
+ }
+
+ // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW.
+ // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and
+ // CHUNK_GZIP.)
+ size_t pos = 12;
+ const char* header = &patch->data[0];
+ if (memcmp(header, "IMGDIFF2", 8) != 0) {
+ printf("corrupt patch file header (magic number)\n");
+ return -1;
+ }
+
+ int num_chunks = Read4(header + 8);
+
+ for (int i = 0; i < num_chunks; ++i) {
+ // each chunk's header record starts with 4 bytes.
+ if (pos + 4 > patch->data.size()) {
+ printf("failed to read chunk %d record\n", i);
+ return -1;
}
+ int type = Read4(&patch->data[pos]);
+ pos += 4;
+
+ if (type == CHUNK_NORMAL) {
+ const char* normal_header = &patch->data[pos];
+ pos += 24;
+ if (pos > patch->data.size()) {
+ printf("failed to read chunk %d normal header data\n", i);
+ return -1;
+ }
- // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW.
- // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and
- // CHUNK_GZIP.)
- size_t pos = 12;
- const char* header = &patch->data[0];
- if (memcmp(header, "IMGDIFF2", 8) != 0) {
- printf("corrupt patch file header (magic number)\n");
+ size_t src_start = Read8(normal_header);
+ size_t src_len = Read8(normal_header + 8);
+ size_t patch_offset = Read8(normal_header + 16);
+
+ if (src_start + src_len > static_cast<size_t>(old_size)) {
+ printf("source data too short\n");
return -1;
- }
+ }
+ ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, token, ctx);
+ } else if (type == CHUNK_RAW) {
+ const char* raw_header = &patch->data[pos];
+ pos += 4;
+ if (pos > patch->data.size()) {
+ printf("failed to read chunk %d raw header data\n", i);
+ return -1;
+ }
- int num_chunks = Read4(header+8);
+ ssize_t data_len = Read4(raw_header);
- for (int i = 0; i < num_chunks; ++i) {
- // each chunk's header record starts with 4 bytes.
- if (pos + 4 > patch->data.size()) {
- printf("failed to read chunk %d record\n", i);
- return -1;
+ if (pos + data_len > patch->data.size()) {
+ printf("failed to read chunk %d raw data\n", i);
+ return -1;
+ }
+ if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
+ if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len, token) !=
+ data_len) {
+ printf("failed to write chunk %d raw data\n", i);
+ return -1;
+ }
+ pos += data_len;
+ } else if (type == CHUNK_DEFLATE) {
+ // deflate chunks have an additional 60 bytes in their chunk header.
+ const char* deflate_header = &patch->data[pos];
+ pos += 60;
+ if (pos > patch->data.size()) {
+ printf("failed to read chunk %d deflate header data\n", i);
+ return -1;
+ }
+
+ size_t src_start = Read8(deflate_header);
+ size_t src_len = Read8(deflate_header + 8);
+ size_t patch_offset = Read8(deflate_header + 16);
+ size_t expanded_len = Read8(deflate_header + 24);
+ size_t target_len = Read8(deflate_header + 32);
+ int level = Read4(deflate_header + 40);
+ int method = Read4(deflate_header + 44);
+ int windowBits = Read4(deflate_header + 48);
+ int memLevel = Read4(deflate_header + 52);
+ int strategy = Read4(deflate_header + 56);
+
+ if (src_start + src_len > static_cast<size_t>(old_size)) {
+ printf("source data too short\n");
+ return -1;
+ }
+
+ // 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->data.size() : 0;
+
+ std::vector<unsigned char> expanded_source(expanded_len);
+
+ // inflate() doesn't like strm.next_out being a nullptr even with
+ // avail_out being zero (Z_STREAM_ERROR).
+ if (expanded_len != 0) {
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = src_len;
+ strm.next_in = const_cast<unsigned char*>(old_data + src_start);
+ strm.avail_out = expanded_len;
+ strm.next_out = expanded_source.data();
+
+ int ret = inflateInit2(&strm, -15);
+ if (ret != Z_OK) {
+ printf("failed to init source inflation: %d\n", ret);
+ return -1;
}
- int type = Read4(&patch->data[pos]);
- pos += 4;
-
- if (type == CHUNK_NORMAL) {
- const char* normal_header = &patch->data[pos];
- pos += 24;
- if (pos > patch->data.size()) {
- printf("failed to read chunk %d normal header data\n", i);
- return -1;
- }
-
- size_t src_start = Read8(normal_header);
- size_t src_len = Read8(normal_header+8);
- size_t patch_offset = Read8(normal_header+16);
-
- if (src_start + src_len > static_cast<size_t>(old_size)) {
- printf("source data too short\n");
- return -1;
- }
- ApplyBSDiffPatch(old_data + src_start, src_len,
- patch, patch_offset, sink, token, ctx);
- } else if (type == CHUNK_RAW) {
- const char* raw_header = &patch->data[pos];
- pos += 4;
- if (pos > patch->data.size()) {
- printf("failed to read chunk %d raw header data\n", i);
- return -1;
- }
-
- ssize_t data_len = Read4(raw_header);
-
- if (pos + data_len > patch->data.size()) {
- printf("failed to read chunk %d raw data\n", i);
- return -1;
- }
- if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
- if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]),
- data_len, token) != data_len) {
- printf("failed to write chunk %d raw data\n", i);
- return -1;
- }
- pos += data_len;
- } else if (type == CHUNK_DEFLATE) {
- // deflate chunks have an additional 60 bytes in their chunk header.
- const char* deflate_header = &patch->data[pos];
- pos += 60;
- if (pos > patch->data.size()) {
- printf("failed to read chunk %d deflate header data\n", i);
- return -1;
- }
-
- size_t src_start = Read8(deflate_header);
- size_t src_len = Read8(deflate_header+8);
- size_t patch_offset = Read8(deflate_header+16);
- size_t expanded_len = Read8(deflate_header+24);
- size_t target_len = Read8(deflate_header+32);
- int level = Read4(deflate_header+40);
- int method = Read4(deflate_header+44);
- int windowBits = Read4(deflate_header+48);
- int memLevel = Read4(deflate_header+52);
- int strategy = Read4(deflate_header+56);
-
- if (src_start + src_len > static_cast<size_t>(old_size)) {
- printf("source data too short\n");
- return -1;
- }
-
- // 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->data.size() : 0;
-
- std::vector<unsigned char> expanded_source(expanded_len);
-
- // inflate() doesn't like strm.next_out being a nullptr even with
- // avail_out being zero (Z_STREAM_ERROR).
- if (expanded_len != 0) {
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = src_len;
- strm.next_in = (unsigned char*)(old_data + src_start);
- strm.avail_out = expanded_len;
- strm.next_out = expanded_source.data();
-
- int ret;
- ret = inflateInit2(&strm, -15);
- if (ret != Z_OK) {
- printf("failed to init source inflation: %d\n", ret);
- return -1;
- }
-
- // Because we've provided enough room to accommodate the output
- // data, we expect one call to inflate() to suffice.
- ret = inflate(&strm, Z_SYNC_FLUSH);
- if (ret != Z_STREAM_END) {
- printf("source inflation returned %d\n", ret);
- return -1;
- }
- // We should have filled the output buffer exactly, except
- // for the bonus_size.
- if (strm.avail_out != bonus_size) {
- printf("source inflation short by %zu bytes\n", strm.avail_out-bonus_size);
- return -1;
- }
- inflateEnd(&strm);
-
- if (bonus_size) {
- memcpy(expanded_source.data() + (expanded_len - bonus_size),
- &bonus_data->data[0], bonus_size);
- }
- }
-
- // Next, apply the bsdiff patch (in memory) to the uncompressed
- // data.
- std::vector<unsigned char> uncompressed_target_data;
- if (ApplyBSDiffPatchMem(expanded_source.data(), expanded_len,
- patch, patch_offset,
- &uncompressed_target_data) != 0) {
- return -1;
- }
- if (uncompressed_target_data.size() != target_len) {
- printf("expected target len to be %zu, but it's %zu\n",
- target_len, uncompressed_target_data.size());
- return -1;
- }
-
- // Now compress the target data and append it to the output.
-
- // we're done with the expanded_source data buffer, so we'll
- // reuse that memory to receive the output of deflate.
- if (expanded_source.size() < 32768U) {
- expanded_source.resize(32768U);
- }
-
- {
- std::vector<unsigned char>& temp_data = expanded_source;
-
- // now the deflate stream
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = uncompressed_target_data.size();
- strm.next_in = uncompressed_target_data.data();
- int ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
- if (ret != Z_OK) {
- printf("failed to init uncompressed data deflation: %d\n", ret);
- return -1;
- }
- do {
- strm.avail_out = temp_data.size();
- strm.next_out = temp_data.data();
- ret = deflate(&strm, Z_FINISH);
- ssize_t have = temp_data.size() - strm.avail_out;
-
- if (sink(temp_data.data(), have, token) != have) {
- printf("failed to write %zd compressed bytes to output\n",
- have);
- return -1;
- }
- if (ctx) SHA1_Update(ctx, temp_data.data(), have);
- } while (ret != Z_STREAM_END);
- deflateEnd(&strm);
- }
- } else {
- printf("patch chunk %d is unknown type %d\n", i, type);
- return -1;
+
+ // Because we've provided enough room to accommodate the output
+ // data, we expect one call to inflate() to suffice.
+ ret = inflate(&strm, Z_SYNC_FLUSH);
+ if (ret != Z_STREAM_END) {
+ printf("source inflation returned %d\n", ret);
+ return -1;
+ }
+ // We should have filled the output buffer exactly, except
+ // for the bonus_size.
+ if (strm.avail_out != bonus_size) {
+ printf("source inflation short by %zu bytes\n", strm.avail_out - bonus_size);
+ return -1;
}
+ inflateEnd(&strm);
+
+ if (bonus_size) {
+ memcpy(expanded_source.data() + (expanded_len - bonus_size), &bonus_data->data[0],
+ bonus_size);
+ }
+ }
+
+ // Next, apply the bsdiff patch (in memory) to the uncompressed data.
+ std::vector<unsigned char> uncompressed_target_data;
+ if (ApplyBSDiffPatchMem(expanded_source.data(), expanded_len, patch, patch_offset,
+ &uncompressed_target_data) != 0) {
+ return -1;
+ }
+ if (uncompressed_target_data.size() != target_len) {
+ printf("expected target len to be %zu, but it's %zu\n", target_len,
+ uncompressed_target_data.size());
+ return -1;
+ }
+
+ // Now compress the target data and append it to the output.
+
+ // we're done with the expanded_source data buffer, so we'll
+ // reuse that memory to receive the output of deflate.
+ if (expanded_source.size() < 32768U) {
+ expanded_source.resize(32768U);
+ }
+
+ {
+ std::vector<unsigned char>& temp_data = expanded_source;
+
+ // now the deflate stream
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = uncompressed_target_data.size();
+ strm.next_in = uncompressed_target_data.data();
+ int ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
+ if (ret != Z_OK) {
+ printf("failed to init uncompressed data deflation: %d\n", ret);
+ return -1;
+ }
+ do {
+ strm.avail_out = temp_data.size();
+ strm.next_out = temp_data.data();
+ ret = deflate(&strm, Z_FINISH);
+ ssize_t have = temp_data.size() - strm.avail_out;
+
+ if (sink(temp_data.data(), have, token) != have) {
+ printf("failed to write %zd compressed bytes to output\n", have);
+ return -1;
+ }
+ if (ctx) SHA1_Update(ctx, temp_data.data(), have);
+ } while (ret != Z_STREAM_END);
+ deflateEnd(&strm);
+ }
+ } else {
+ printf("patch chunk %d is unknown type %d\n", i, type);
+ return -1;
}
+ }
- return 0;
+ return 0;
}
diff --git a/applypatch/imgdiff.h b/applypatch/include/applypatch/imgdiff.h
index f2069b4f3..22cbd4fa0 100644
--- a/applypatch/imgdiff.h
+++ b/applypatch/include/applypatch/imgdiff.h
@@ -14,17 +14,26 @@
* limitations under the License.
*/
+#ifndef _APPLYPATCH_IMGDIFF_H
+#define _APPLYPATCH_IMGDIFF_H
+
+#include <stddef.h>
+
// Image patch chunk types
-#define CHUNK_NORMAL 0
-#define CHUNK_GZIP 1 // version 1 only
-#define CHUNK_DEFLATE 2 // version 2 only
-#define CHUNK_RAW 3 // version 2 only
+#define CHUNK_NORMAL 0
+#define CHUNK_GZIP 1 // version 1 only
+#define CHUNK_DEFLATE 2 // version 2 only
+#define CHUNK_RAW 3 // version 2 only
// The gzip header size is actually variable, but we currently don't
// support gzipped data with any of the optional fields, so for now it
// will always be ten bytes. See RFC 1952 for the definition of the
// gzip format.
-#define GZIP_HEADER_LEN 10
+static constexpr size_t GZIP_HEADER_LEN = 10;
// The gzip footer size really is fixed.
-#define GZIP_FOOTER_LEN 8
+static constexpr size_t GZIP_FOOTER_LEN = 8;
+
+int imgdiff(int argc, const char** argv);
+
+#endif // _APPLYPATCH_IMGDIFF_H
diff --git a/applypatch/include/applypatch/imgpatch.h b/applypatch/include/applypatch/imgpatch.h
index 64d9aa9eb..6549f79f0 100644
--- a/applypatch/include/applypatch/imgpatch.h
+++ b/applypatch/include/applypatch/imgpatch.h
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-#ifndef _IMGPATCH_H
-#define _IMGPATCH_H
+#ifndef _APPLYPATCH_IMGPATCH_H
+#define _APPLYPATCH_IMGPATCH_H
-typedef ssize_t (*SinkFn)(const unsigned char*, ssize_t, void*);
+#include <sys/types.h>
+
+using SinkFn = ssize_t (*)(const unsigned char*, ssize_t, void*);
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const unsigned char* patch_data, ssize_t patch_size,
SinkFn sink, void* token);
-#endif //_IMGPATCH_H
+#endif // _APPLYPATCH_IMGPATCH_H