summaryrefslogtreecommitdiffstats
path: root/applypatch/bspatch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'applypatch/bspatch.cpp')
-rw-r--r--applypatch/bspatch.cpp205
1 files changed, 21 insertions, 184 deletions
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index ebb55f1d1..9920c2be1 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -21,16 +21,12 @@
// notice.
#include <stdio.h>
-#include <sys/stat.h>
#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <bzlib.h>
+#include <bspatch.h>
+#include "applypatch/applypatch.h"
#include "openssl/sha.h"
-#include "applypatch.h"
void ShowBSDiffLicense() {
puts("The bsdiff library used herein is:\n"
@@ -64,184 +60,25 @@ void ShowBSDiffLicense() {
);
}
-static off_t offtin(u_char *buf)
-{
- off_t y;
-
- y=buf[7]&0x7F;
- y=y*256;y+=buf[6];
- y=y*256;y+=buf[5];
- y=y*256;y+=buf[4];
- y=y*256;y+=buf[3];
- y=y*256;y+=buf[2];
- y=y*256;y+=buf[1];
- y=y*256;y+=buf[0];
-
- if(buf[7]&0x80) y=-y;
-
- return y;
-}
-
-int FillBuffer(unsigned char* buffer, int size, bz_stream* stream) {
- stream->next_out = (char*)buffer;
- stream->avail_out = size;
- while (stream->avail_out > 0) {
- int bzerr = BZ2_bzDecompress(stream);
- if (bzerr != BZ_OK && bzerr != BZ_STREAM_END) {
- printf("bz error %d decompressing\n", bzerr);
- return -1;
- }
- if (stream->avail_out > 0) {
- printf("need %d more bytes\n", stream->avail_out);
- }
- }
- return 0;
-}
-
-int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
- const Value* patch, ssize_t patch_offset,
- SinkFn sink, void* token, SHA_CTX* ctx) {
-
- std::vector<unsigned char> new_data;
- if (ApplyBSDiffPatchMem(old_data, old_size, patch, patch_offset, &new_data) != 0) {
- return -1;
- }
-
- if (sink(new_data.data(), new_data.size(), token) < static_cast<ssize_t>(new_data.size())) {
- printf("short write of output: %d (%s)\n", errno, strerror(errno));
- return 1;
- }
- if (ctx) SHA1_Update(ctx, new_data.data(), new_data.size());
- return 0;
+int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, const Value* patch,
+ ssize_t patch_offset, SinkFn sink, void* token, SHA_CTX* ctx) {
+ auto sha_sink = [&](const uint8_t* data, size_t len) {
+ len = sink(data, len, token);
+ if (ctx) SHA1_Update(ctx, data, len);
+ return len;
+ };
+ return bsdiff::bspatch(old_data, old_size,
+ reinterpret_cast<const uint8_t*>(&patch->data[patch_offset]),
+ patch->data.size(), sha_sink);
}
-int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
- const Value* patch, ssize_t patch_offset,
- std::vector<unsigned char>* new_data) {
- // Patch data format:
- // 0 8 "BSDIFF40"
- // 8 8 X
- // 16 8 Y
- // 24 8 sizeof(newfile)
- // 32 X bzip2(control block)
- // 32+X Y bzip2(diff block)
- // 32+X+Y ??? bzip2(extra block)
- // with control block a set of triples (x,y,z) meaning "add x bytes
- // from oldfile to x bytes from the diff block; copy y bytes from the
- // extra block; seek forwards in oldfile by z bytes".
-
- unsigned char* header = (unsigned char*) patch->data + patch_offset;
- if (memcmp(header, "BSDIFF40", 8) != 0) {
- printf("corrupt bsdiff patch file header (magic number)\n");
- return 1;
- }
-
- ssize_t ctrl_len, data_len, new_size;
- ctrl_len = offtin(header+8);
- data_len = offtin(header+16);
- new_size = offtin(header+24);
-
- if (ctrl_len < 0 || data_len < 0 || new_size < 0) {
- printf("corrupt patch file header (data lengths)\n");
- return 1;
- }
-
- int bzerr;
-
- bz_stream cstream;
- cstream.next_in = patch->data + patch_offset + 32;
- cstream.avail_in = ctrl_len;
- cstream.bzalloc = NULL;
- cstream.bzfree = NULL;
- cstream.opaque = NULL;
- if ((bzerr = BZ2_bzDecompressInit(&cstream, 0, 0)) != BZ_OK) {
- printf("failed to bzinit control stream (%d)\n", bzerr);
- }
-
- bz_stream dstream;
- dstream.next_in = patch->data + patch_offset + 32 + ctrl_len;
- dstream.avail_in = data_len;
- dstream.bzalloc = NULL;
- dstream.bzfree = NULL;
- dstream.opaque = NULL;
- if ((bzerr = BZ2_bzDecompressInit(&dstream, 0, 0)) != BZ_OK) {
- printf("failed to bzinit diff stream (%d)\n", bzerr);
- }
-
- bz_stream estream;
- estream.next_in = patch->data + patch_offset + 32 + ctrl_len + data_len;
- estream.avail_in = patch->size - (patch_offset + 32 + ctrl_len + data_len);
- estream.bzalloc = NULL;
- estream.bzfree = NULL;
- estream.opaque = NULL;
- if ((bzerr = BZ2_bzDecompressInit(&estream, 0, 0)) != BZ_OK) {
- printf("failed to bzinit extra stream (%d)\n", bzerr);
- }
-
- new_data->resize(new_size);
-
- off_t oldpos = 0, newpos = 0;
- off_t ctrl[3];
- off_t len_read;
- int i;
- unsigned char buf[24];
- while (newpos < new_size) {
- // Read control data
- if (FillBuffer(buf, 24, &cstream) != 0) {
- printf("error while reading control stream\n");
- return 1;
- }
- ctrl[0] = offtin(buf);
- ctrl[1] = offtin(buf+8);
- ctrl[2] = offtin(buf+16);
-
- if (ctrl[0] < 0 || ctrl[1] < 0) {
- printf("corrupt patch (negative byte counts)\n");
- return 1;
- }
-
- // Sanity check
- if (newpos + ctrl[0] > new_size) {
- printf("corrupt patch (new file overrun)\n");
- return 1;
- }
-
- // Read diff string
- if (FillBuffer(new_data->data() + newpos, ctrl[0], &dstream) != 0) {
- printf("error while reading diff stream\n");
- return 1;
- }
-
- // Add old data to diff string
- for (i = 0; i < ctrl[0]; ++i) {
- if ((oldpos+i >= 0) && (oldpos+i < old_size)) {
- (*new_data)[newpos+i] += old_data[oldpos+i];
- }
- }
-
- // Adjust pointers
- newpos += ctrl[0];
- oldpos += ctrl[0];
-
- // Sanity check
- if (newpos + ctrl[1] > new_size) {
- printf("corrupt patch (new file overrun)\n");
- return 1;
- }
-
- // Read extra string
- if (FillBuffer(new_data->data() + newpos, ctrl[1], &estream) != 0) {
- printf("error while reading extra stream\n");
- return 1;
- }
-
- // Adjust pointers
- newpos += ctrl[1];
- oldpos += ctrl[2];
- }
-
- BZ2_bzDecompressEnd(&cstream);
- BZ2_bzDecompressEnd(&dstream);
- BZ2_bzDecompressEnd(&estream);
- return 0;
+int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, const Value* patch,
+ ssize_t patch_offset, std::vector<unsigned char>* new_data) {
+ auto vector_sink = [new_data](const uint8_t* data, size_t len) {
+ new_data->insert(new_data->end(), data, data + len);
+ return len;
+ };
+ return bsdiff::bspatch(old_data, old_size,
+ reinterpret_cast<const uint8_t*>(&patch->data[patch_offset]),
+ patch->data.size(), vector_sink);
}