Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Unified Diff: chrome/installer/mac/third_party/bsdiff/goobsdiff.c

Issue 2716005: Modify bsdiff 4.3 to goobsdiff, which is appropriate for use as the Mac binary differ/patcher (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/installer/mac/third_party/bsdiff/goobsdiff.c
===================================================================
--- chrome/installer/mac/third_party/bsdiff/goobsdiff.c (revision 49280)
+++ chrome/installer/mac/third_party/bsdiff/goobsdiff.c (working copy)
@@ -33,11 +33,24 @@
#include <bzlib.h>
#include <err.h>
#include <fcntl.h>
+#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <zlib.h>
+#if defined(__APPLE__)
+#include <libkern/OSByteOrder.h>
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#elif defined(__linux__)
+#include <endian.h>
+#elif defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))
+#define htole64(x) (x)
+#else
+#error Provide htole64 for this platform
+#endif
+
#define MIN(x,y) (((x)<(y)) ? (x) : (y))
static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h)
@@ -175,24 +188,114 @@
};
}
-static void offtout(off_t x,u_char *buf)
+static inline void offtout(off_t x,u_char *buf)
{
- off_t y;
+ *((off_t*)buf) = htole64(x);
+}
- if(x<0) y=-x; else y=x;
+/* zlib provides compress2, which deflates to deflate (zlib) format. This is
+ * unfortunately distinct from gzip format in that the headers wrapping the
+ * decompressed data are different. gbspatch reads gzip-compressed data using
+ * the file-oriented gzread interface, which only supports gzip format.
+ * compress2gzip is identical to zlib's compress2 except that it produces gzip
+ * output compatible with gzread. This change is achieved by calling
+ * deflateInit2 instead of deflateInit and specifying 31 for windowBits;
+ * numbers greater than 15 cause the addition of a gzip wrapper. */
+static int compress2gzip(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen, int level)
+{
+ z_stream stream;
+ int err;
- 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;
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
- if(x<0) buf[7]|=0x80;
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit2(&stream,
+ level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
}
+/* Recompress buf of size buf_len using bzip2 or gzip. The smallest version is
+ * used. The original uncompressed variant may be the smallest. Returns a
+ * number identifying the encoding, 1 for uncompressed, 2 for bzip2, and 3 for
+ * gzip. If the original uncompressed variant is not smallest, it is freed.
+ * The caller must free any buf after this function returns. */
+static char make_small(u_char **buf, off_t *buf_len)
+{
+ u_char *source = *buf;
+ off_t source_len = *buf_len;
+ u_char *bz2, *gz;
+ unsigned int bz2_len;
+ unsigned long gz_len;
+ int zerr;
+ char smallest;
+
+ smallest = 1;
+
+ bz2_len = source_len + 1;
+ bz2 = malloc(bz2_len);
+ zerr = BZ2_bzBuffToBuffCompress((char*)bz2, &bz2_len, (char*)source,
+ source_len, 9, 0, 0);
+ if (zerr == BZ_OK) {
+ if (bz2_len < *buf_len) {
+ smallest = 2;
+ *buf = bz2;
+ *buf_len = bz2_len;
+ } else {
+ free(bz2);
+ bz2 = NULL;
+ }
+ } else if (zerr == BZ_OUTBUFF_FULL) {
+ free(bz2);
+ bz2 = NULL;
+ } else {
+ errx(1, "BZ2_bzBuffToBuffCompress: %d", zerr);
+ }
+
+ gz_len = source_len + 1;
+ gz = malloc(gz_len);
+ zerr = compress2gzip(gz, &gz_len, source, source_len, 9);
+ if (zerr == Z_OK) {
+ if (gz_len < *buf_len) {
+ smallest = 3;
+ *buf = gz;
+ *buf_len = gz_len;
+ } else {
+ free(gz);
+ gz = NULL;
+ }
+ } else if (zerr == Z_BUF_ERROR) {
+ free(gz);
+ gz = NULL;
+ } else {
+ errx(1, "compress2gzip: %d", zerr);
+ }
+
+ if (smallest != 1) {
+ free(source);
+ }
+
+ return smallest;
+}
+
int main(int argc,char *argv[])
{
int fd;
@@ -205,15 +308,12 @@
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];
+ off_t cblen, dblen, eblen;
+ u_char *cb, *db, *eb;
+ u_char header[96];
FILE * pf;
- BZFILE * pfbz2;
- int bz2err;
- if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+ if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile",argv[0]);
/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
that we never try to malloc(0) and get a NULL pointer */
@@ -240,35 +340,44 @@
(read(fd,new,newsize)!=newsize) ||
(close(fd)==-1)) err(1,"%s",argv[2]);
- if(((db=malloc(newsize+1))==NULL) ||
+ if(((cb=malloc(newsize+1))==NULL) ||
+ ((db=malloc(newsize+1))==NULL) ||
((eb=malloc(newsize+1))==NULL)) err(1,NULL);
+ cblen=0;
dblen=0;
eblen=0;
/* Create the patch file */
- if ((pf = fopen(argv[3], "w")) == NULL)
+ if ((pf = fopen(argv[3], "wb")) == NULL)
err(1, "%s", argv[3]);
- /* 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)
+ /* File format:
+ 0 8 "BSDIFF4G"
+ 8 8 length of compressed control block (x)
+ 16 8 length of compressed diff block (y)
+ 24 8 length of compressed extra block (z)
+ 32 8 length of old file
+ 40 8 length of new file
+ 48 20 SHA1 of old file
+ 68 20 SHA1 of new file
+ 88 1 encoding of control block
+ 89 1 encoding of diff block
+ 90 1 encoding of extra block
+ 91 5 unused
+ 96 x compressed control block
+ 96+x y compressed diff block
+ 96+x+y z compressed extra block
+ Encodings are 1 (uncompressed), 2 (bzip2), and 3 (gzip). */
+ memset(header, 0, sizeof(header));
+ if (fwrite(header, sizeof(header), 1, pf) != 1)
err(1, "fwrite(%s)", argv[3]);
+ memcpy(header, "BSDIFF4G", 8);
+ offtout(oldsize, header + 32);
+ offtout(newsize, header + 40);
+ SHA1(old, oldsize, header + 48);
+ SHA1(new, newsize, header + 68);
- /* 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);
+ /* Compute the differences */
scan=0;len=0;
lastscan=0;lastpos=0;lastoffset=0;
while(scan<newsize) {
@@ -331,69 +440,46 @@
dblen+=lenf;
eblen+=(scan-lenb)-(lastscan+lenf);
- offtout(lenf,buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ offtout(lenf, cb + cblen);
+ cblen += 8;
- offtout((scan-lenb)-(lastscan+lenf),buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ offtout((scan - lenb) - (lastscan + lenf), cb + cblen);
+ cblen += 8;
- offtout((pos-lenb)-(lastpos+lenf),buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ offtout((pos - lenb) - (lastpos + lenf), cb + cblen);
+ cblen += 8;
lastscan=scan-lenb;
lastpos=pos-lenb;
lastoffset=pos-scan;
};
};
- BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
- /* Compute size of compressed ctrl data */
- if ((len = ftello(pf)) == -1)
- err(1, "ftello");
- offtout(len-32, header + 8);
+ header[88] = make_small(&cb, &cblen);
+ header[89] = make_small(&db, &dblen);
+ header[90] = make_small(&eb, &eblen);
- /* Write compressed diff data */
- if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
- errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
- BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
- BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
+ if (fwrite(cb, 1, cblen, pf) != cblen)
+ err(1, "fwrite");
+ if (fwrite(db, 1, dblen, pf) != dblen)
+ err(1, "fwrite");
+ if (fwrite(eb, 1, eblen, pf) != eblen)
+ err(1, "fwrite");
- /* Compute size of compressed diff data */
- if ((newsize = ftello(pf)) == -1)
- err(1, "ftello");
- offtout(newsize - len, header + 16);
+ offtout(cblen, header + 8);
+ offtout(dblen, header + 16);
+ offtout(eblen, header + 24);
- /* Write compressed extra data */
- if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
- errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
- BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
- BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
-
/* Seek to the beginning, write the header, and close the file */
if (fseeko(pf, 0, SEEK_SET))
err(1, "fseeko");
- if (fwrite(header, 32, 1, pf) != 1)
+ if (fwrite(header, sizeof(header), 1, pf) != 1)
err(1, "fwrite(%s)", argv[3]);
if (fclose(pf))
err(1, "fclose");
/* Free the memory we used */
+ free(cb);
free(db);
free(eb);
free(I);
« no previous file with comments | « chrome/installer/mac/third_party/bsdiff/bspatch.c ('k') | chrome/installer/mac/third_party/bsdiff/goobsdiff.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698