diff --git a/tools/applypatch/Android.mk b/tools/applypatch/Android.mk index 5796cefe3..bb1519eee 100644 --- a/tools/applypatch/Android.mk +++ b/tools/applypatch/Android.mk @@ -17,7 +17,7 @@ ifneq ($(TARGET_SIMULATOR),true) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := applypatch.c bsdiff.c freecache.c imgpatch.c utils.c +LOCAL_SRC_FILES := applypatch.c bspatch.c freecache.c imgpatch.c utils.c LOCAL_MODULE := libapplypatch LOCAL_MODULE_TAGS := eng LOCAL_C_INCLUDES += external/bzip2 external/zlib bootable/recovery @@ -47,12 +47,12 @@ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) -LOCAL_SRC_FILES := imgdiff.c utils.c +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 -LOCAL_STATIC_LIBRARIES += libz +LOCAL_STATIC_LIBRARIES += libz libbz include $(BUILD_HOST_EXECUTABLE) diff --git a/tools/applypatch/bsdiff.c b/tools/applypatch/bsdiff.c index d5cd6174d..b6d342b7a 100644 --- a/tools/applypatch/bsdiff.c +++ b/tools/applypatch/bsdiff.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2009 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. @@ -14,239 +14,397 @@ * limitations under the License. */ -// This file is a nearly line-for-line copy of bspatch.c from the -// bsdiff-4.3 distribution; the primary differences being how the -// input and output data are read and the error handling. Running -// applypatch with the -l option will display the bsdiff license -// notice. +/* + * Most of this code comes from bsdiff.c from the bsdiff-4.3 + * distribution, which is: + */ -#include -#include -#include -#include -#include +/*- + * Copyright 2003-2005 Colin Percival + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include #include +#include +#include +#include +#include +#include +#include -#include "mincrypt/sha.h" -#include "applypatch.h" +#define MIN(x,y) (((x)<(y)) ? (x) : (y)) -void ShowBSDiffLicense() { - puts("The bsdiff library used herein is:\n" - "\n" - "Copyright 2003-2005 Colin Percival\n" - "All rights reserved\n" - "\n" - "Redistribution and use in source and binary forms, with or without\n" - "modification, are permitted providing that the following conditions\n" - "are met:\n" - "1. Redistributions of source code must retain the above copyright\n" - " notice, this list of conditions and the following disclaimer.\n" - "2. Redistributions in binary form must reproduce the above copyright\n" - " notice, this list of conditions and the following disclaimer in the\n" - " documentation and/or other materials provided with the distribution.\n" - "\n" - "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n" - "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n" - "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" - "ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n" - "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n" - "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" - "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n" - "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n" - "STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n" - "IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" - "POSSIBILITY OF SUCH DAMAGE.\n" - "\n------------------\n\n" - "This program uses Julian R Seward's \"libbzip2\" library, available\n" - "from http://www.bzip.org/.\n" - ); -} - -static off_t offtin(u_char *buf) +static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h) { - off_t y; + off_t i,j,k,x,tmp,jj,kk; - 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(len<16) { + for(k=start;kstart) split(I,V,start,jj-start,h); + + for(i=0;ikk) split(I,V,kk,start+len-kk,h); } +static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize) +{ + off_t buckets[256]; + off_t i,h,len; -int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, - const char* patch_filename, ssize_t patch_offset, - SinkFn sink, void* token, SHA_CTX* ctx) { + for(i=0;i<256;i++) buckets[i]=0; + for(i=0;i0;i--) buckets[i]=buckets[i-1]; + buckets[0]=0; - unsigned char* new_data; - ssize_t new_size; - if (ApplyBSDiffPatchMem(old_data, old_size, patch_filename, patch_offset, - &new_data, &new_size) != 0) { - return -1; - } + for(i=0;i *new_size) { - fprintf(stderr, "corrupt patch (new file overrun)\n"); - return 1; - } - - // Read diff string - len_read = BZ2_bzRead(&bzerr, dpfbz2, *new_data + newpos, ctrl[0]); - if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) { - fprintf(stderr, "corrupt patch (read diff)\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) { - fprintf(stderr, "corrupt patch (new file overrun)\n"); - return 1; - } - - // Read extra string - len_read = BZ2_bzRead(&bzerr, epfbz2, *new_data + newpos, ctrl[1]); - if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) { - fprintf(stderr, "corrupt patch (read extra)\n"); - return 1; - } - - // Adjust pointers - newpos += ctrl[1]; - oldpos += ctrl[2]; - } - - BZ2_bzReadClose(&bzerr, cpfbz2); - BZ2_bzReadClose(&bzerr, dpfbz2); - BZ2_bzReadClose(&bzerr, epfbz2); - fclose(cpf); - fclose(dpf); - fclose(epf); - - return 0; + return i; +} + +static off_t search(off_t *I,u_char *old,off_t oldsize, + u_char *new,off_t newsize,off_t st,off_t en,off_t *pos) +{ + off_t x,y; + + if(en-st<2) { + x=matchlen(old+I[st],oldsize-I[st],new,newsize); + y=matchlen(old+I[en],oldsize-I[en],new,newsize); + + if(x>y) { + *pos=I[st]; + return x; + } else { + *pos=I[en]; + return y; + } + }; + + x=st+(en-st)/2; + if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) { + return search(I,old,oldsize,new,newsize,x,en,pos); + } else { + return search(I,old,oldsize,new,newsize,st,x,pos); + }; +} + +static void offtout(off_t x,u_char *buf) +{ + off_t y; + + if(x<0) y=-x; else y=x; + + buf[0]=y%256;y-=buf[0]; + y=y/256;buf[1]=y%256;y-=buf[1]; + y=y/256;buf[2]=y%256;y-=buf[2]; + y=y/256;buf[3]=y%256;y-=buf[3]; + y=y/256;buf[4]=y%256;y-=buf[4]; + y=y/256;buf[5]=y%256;y-=buf[5]; + y=y/256;buf[6]=y%256;y-=buf[6]; + y=y/256;buf[7]=y%256; + + if(x<0) buf[7]|=0x80; +} + +// This is main() from bsdiff.c, with the following changes: +// +// - old, oldsize, new, newsize are arguments; we don't load this +// data from files. old and new are owned by the caller; we +// don't free them at the end. +// +// - the "I" block of memory is owned by the caller, who passes a +// pointer to *I, which can be NULL. This way if we call +// bsdiff() multiple times with the same 'old' data, we only do +// the qsufsort() step the first time. +// +int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize, + const char* patch_filename) +{ + int fd; + off_t *I; + off_t scan,pos,len; + off_t lastscan,lastpos,lastoffset; + off_t oldscore,scsc; + off_t s,Sf,lenf,Sb,lenb; + off_t overlap,Ss,lens; + off_t i; + off_t dblen,eblen; + u_char *db,*eb; + u_char buf[8]; + u_char header[32]; + FILE * pf; + BZFILE * pfbz2; + int bz2err; + + if (*IP == NULL) { + off_t* V; + *IP = malloc((oldsize+1) * sizeof(off_t)); + V = malloc((oldsize+1) * sizeof(off_t)); + qsufsort(*IP, V, old, oldsize); + free(V); + } + I = *IP; + + if(((db=malloc(newsize+1))==NULL) || + ((eb=malloc(newsize+1))==NULL)) err(1,NULL); + dblen=0; + eblen=0; + + /* Create the patch file */ + if ((pf = fopen(patch_filename, "w")) == NULL) + err(1, "%s", patch_filename); + + /* Header is + 0 8 "BSDIFF40" + 8 8 length of bzip2ed ctrl block + 16 8 length of bzip2ed diff block + 24 8 length of new file */ + /* File is + 0 32 Header + 32 ?? Bzip2ed ctrl block + ?? ?? Bzip2ed diff block + ?? ?? Bzip2ed extra block */ + memcpy(header,"BSDIFF40",8); + offtout(0, header + 8); + offtout(0, header + 16); + offtout(newsize, header + 24); + if (fwrite(header, 32, 1, pf) != 1) + err(1, "fwrite(%s)", patch_filename); + + /* Compute the differences, writing ctrl as we go */ + if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) + errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); + scan=0;len=0; + lastscan=0;lastpos=0;lastoffset=0; + while(scanoldscore+8)) break; + + if((scan+lastoffsetSf*2-lenf) { Sf=s; lenf=i; }; + }; + + lenb=0; + if(scan=lastscan+i)&&(pos>=i);i++) { + if(old[pos-i]==new[scan-i]) s++; + if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; + }; + }; + + if(lastscan+lenf>scan-lenb) { + overlap=(lastscan+lenf)-(scan-lenb); + s=0;Ss=0;lens=0; + for(i=0;iSs) { Ss=s; lens=i+1; }; + }; + + lenf+=lens-overlap; + lenb-=lens; + }; + + for(i=0;i +#include +#include +#include +#include + +#include + +#include "mincrypt/sha.h" +#include "applypatch.h" + +void ShowBSDiffLicense() { + puts("The bsdiff library used herein is:\n" + "\n" + "Copyright 2003-2005 Colin Percival\n" + "All rights reserved\n" + "\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted providing that the following conditions\n" + "are met:\n" + "1. Redistributions of source code must retain the above copyright\n" + " notice, this list of conditions and the following disclaimer.\n" + "2. Redistributions in binary form must reproduce the above copyright\n" + " notice, this list of conditions and the following disclaimer in the\n" + " documentation and/or other materials provided with the distribution.\n" + "\n" + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n" + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n" + "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" + "ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n" + "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n" + "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" + "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n" + "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n" + "STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n" + "IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" + "POSSIBILITY OF SUCH DAMAGE.\n" + "\n------------------\n\n" + "This program uses Julian R Seward's \"libbzip2\" library, available\n" + "from http://www.bzip.org/.\n" + ); +} + +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 ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, + const char* patch_filename, ssize_t patch_offset, + SinkFn sink, void* token, SHA_CTX* ctx) { + + unsigned char* new_data; + ssize_t new_size; + if (ApplyBSDiffPatchMem(old_data, old_size, patch_filename, patch_offset, + &new_data, &new_size) != 0) { + return -1; + } + + if (sink(new_data, new_size, token) < new_size) { + fprintf(stderr, "short write of output: %d (%s)\n", errno, strerror(errno)); + return 1; + } + if (ctx) { + SHA_update(ctx, new_data, new_size); + } + free(new_data); + + return 0; +} + +int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, + const char* patch_filename, ssize_t patch_offset, + unsigned char** new_data, ssize_t* new_size) { + + FILE* f; + if ((f = fopen(patch_filename, "rb")) == NULL) { + fprintf(stderr, "failed to open patch file\n"); + return 1; + } + + // File 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". + + fseek(f, patch_offset, SEEK_SET); + + unsigned char header[32]; + if (fread(header, 1, 32, f) < 32) { + fprintf(stderr, "failed to read patch file header\n"); + return 1; + } + + if (memcmp(header, "BSDIFF40", 8) != 0) { + fprintf(stderr, "corrupt bsdiff patch file header (magic number)\n"); + return 1; + } + + ssize_t ctrl_len, data_len; + 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) { + fprintf(stderr, "corrupt patch file header (data lengths)\n"); + return 1; + } + + fclose(f); + + int bzerr; + +#define OPEN_AT(f, bzf, offset) \ + FILE* f; \ + BZFILE* bzf; \ + if ((f = fopen(patch_filename, "rb")) == NULL) { \ + fprintf(stderr, "failed to open patch file\n"); \ + return 1; \ + } \ + if (fseeko(f, offset+patch_offset, SEEK_SET)) { \ + fprintf(stderr, "failed to seek in patch file\n"); \ + return 1; \ + } \ + if ((bzf = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL) { \ + fprintf(stderr, "failed to bzReadOpen in patch file (%d)\n", bzerr); \ + return 1; \ + } + + OPEN_AT(cpf, cpfbz2, 32); + OPEN_AT(dpf, dpfbz2, 32+ctrl_len); + OPEN_AT(epf, epfbz2, 32+ctrl_len+data_len); + +#undef OPEN_AT + + *new_data = malloc(*new_size); + if (*new_data == NULL) { + fprintf(stderr, "failed to allocate %d bytes of memory for output file\n", + (int)*new_size); + return 1; + } + + off_t oldpos = 0, newpos = 0; + off_t ctrl[3]; + off_t len_read; + int i; + unsigned char buf[8]; + while (newpos < *new_size) { + // Read control data + for (i = 0; i < 3; ++i) { + len_read = BZ2_bzRead(&bzerr, cpfbz2, buf, 8); + if (len_read < 8 || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) { + fprintf(stderr, "corrupt patch (read control)\n"); + return 1; + } + ctrl[i] = offtin(buf); + } + + // Sanity check + if (newpos + ctrl[0] > *new_size) { + fprintf(stderr, "corrupt patch (new file overrun)\n"); + return 1; + } + + // Read diff string + len_read = BZ2_bzRead(&bzerr, dpfbz2, *new_data + newpos, ctrl[0]); + if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) { + fprintf(stderr, "corrupt patch (read diff)\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) { + fprintf(stderr, "corrupt patch (new file overrun)\n"); + return 1; + } + + // Read extra string + len_read = BZ2_bzRead(&bzerr, epfbz2, *new_data + newpos, ctrl[1]); + if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) { + fprintf(stderr, "corrupt patch (read extra)\n"); + return 1; + } + + // Adjust pointers + newpos += ctrl[1]; + oldpos += ctrl[2]; + } + + BZ2_bzReadClose(&bzerr, cpfbz2); + BZ2_bzReadClose(&bzerr, dpfbz2); + BZ2_bzReadClose(&bzerr, epfbz2); + fclose(cpf); + fclose(dpf); + fclose(epf); + + return 0; +} diff --git a/tools/applypatch/imgdiff.c b/tools/applypatch/imgdiff.c index 5386d9b72..38e3c8392 100644 --- a/tools/applypatch/imgdiff.c +++ b/tools/applypatch/imgdiff.c @@ -134,6 +134,8 @@ typedef struct { size_t source_start; size_t source_len; + off_t* I; // used by bsdiff + // --- for CHUNK_DEFLATE chunks only: --- // original (compressed) deflate data @@ -167,6 +169,10 @@ static int fileentry_compare(const void* a, const void* b) { } } +// from bsdiff.c +int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize, + const char* patch_filename); + unsigned char* ReadZip(const char* filename, int* num_chunks, ImageChunk** chunks, int include_pseudo_chunk) { @@ -278,6 +284,7 @@ unsigned char* ReadZip(const char* filename, curr->len = st.st_size; curr->data = img; curr->filename = NULL; + curr->I = NULL; ++curr; ++*num_chunks; } @@ -292,6 +299,7 @@ unsigned char* ReadZip(const char* filename, curr->deflate_len = temp_entries[nextentry].deflate_len; curr->deflate_data = img + pos; curr->filename = temp_entries[nextentry].filename; + curr->I = NULL; curr->len = temp_entries[nextentry].uncomp_len; curr->data = malloc(curr->len); @@ -336,6 +344,7 @@ unsigned char* ReadZip(const char* filename, } curr->data = img + pos; curr->filename = NULL; + curr->I = NULL; pos += curr->len; ++*num_chunks; @@ -400,6 +409,7 @@ unsigned char* ReadImage(const char* filename, curr->type = CHUNK_NORMAL; curr->len = GZIP_HEADER_LEN; curr->data = p; + curr->I = NULL; pos += curr->len; p += curr->len; @@ -407,6 +417,7 @@ unsigned char* ReadImage(const char* filename, curr->type = CHUNK_DEFLATE; curr->filename = NULL; + curr->I = NULL; // We must decompress this chunk in order to discover where it // ends, and so we can put the uncompressed data and its length @@ -452,6 +463,7 @@ unsigned char* ReadImage(const char* filename, curr->start = pos; curr->len = GZIP_FOOTER_LEN; curr->data = img+pos; + curr->I = NULL; pos += curr->len; p += curr->len; @@ -475,6 +487,7 @@ unsigned char* ReadImage(const char* filename, *chunks = realloc(*chunks, *num_chunks * sizeof(ImageChunk)); ImageChunk* curr = *chunks + (*num_chunks-1); curr->start = pos; + curr->I = NULL; // 'pos' is not the offset of the start of a gzip chunk, so scan // forward until we find a gzip header. @@ -591,43 +604,12 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) { } } - char stemp[] = "/tmp/imgdiff-src-XXXXXX"; - char ttemp[] = "/tmp/imgdiff-tgt-XXXXXX"; char ptemp[] = "/tmp/imgdiff-patch-XXXXXX"; - mkstemp(stemp); - mkstemp(ttemp); mkstemp(ptemp); - FILE* f = fopen(stemp, "wb"); - if (f == NULL) { - fprintf(stderr, "failed to open src chunk %s: %s\n", - stemp, strerror(errno)); - return NULL; - } - if (fwrite(src->data, 1, src->len, f) != src->len) { - fprintf(stderr, "failed to write src chunk to %s: %s\n", - stemp, strerror(errno)); - return NULL; - } - fclose(f); - - f = fopen(ttemp, "wb"); - if (f == NULL) { - fprintf(stderr, "failed to open tgt chunk %s: %s\n", - ttemp, strerror(errno)); - return NULL; - } - if (fwrite(tgt->data, 1, tgt->len, f) != tgt->len) { - fprintf(stderr, "failed to write tgt chunk to %s: %s\n", - ttemp, strerror(errno)); - return NULL; - } - fclose(f); - - char cmd[200]; - sprintf(cmd, "bsdiff %s %s %s", stemp, ttemp, ptemp); - if (system(cmd) != 0) { - fprintf(stderr, "failed to run bsdiff: %s\n", strerror(errno)); + int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp); + if (r != 0) { + fprintf(stderr, "bsdiff() failed: %d\n", r); return NULL; } @@ -641,8 +623,6 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) { unsigned char* data = malloc(st.st_size); if (tgt->type == CHUNK_NORMAL && tgt->len <= st.st_size) { - unlink(stemp); - unlink(ttemp); unlink(ptemp); tgt->type = CHUNK_RAW; @@ -652,7 +632,7 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) { *size = st.st_size; - f = fopen(ptemp, "rb"); + FILE* f = fopen(ptemp, "rb"); if (f == NULL) { fprintf(stderr, "failed to open patch %s: %s\n", ptemp, strerror(errno)); return NULL; @@ -663,8 +643,6 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) { } fclose(f); - unlink(stemp); - unlink(ttemp); unlink(ptemp); tgt->source_start = src->start;