Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Don't compress in bsdiff.

bsdiff-produced patch is included in xar archive, where it's compressed
with bzip2 a second time. Leaving the bsdiff output uncompressed makes
it possible to compress it better in xar (e.g. using LZMA2 or gzip,
either of which performs better on some files).

Changes header signature of bsdiff patch file to BSDIFN40 to clearly
mark the format as different.

Backward compatibility is preserved, bspatch can read both BSDIFF40 and
BSDIFN40 formats.
  • Loading branch information...
commit 39bb82bd9acddacae7befbb587ed90b371dda53c 1 parent 25d7fae
@vslavik vslavik authored andymatuschak committed
Showing with 103 additions and 64 deletions.
  1. +19 −42 bsdiff.c
  2. +84 −22 bspatch.c
View
61 bsdiff.c
@@ -30,7 +30,6 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c, v 1.1 2005/08/06 01:59:0
#include <sys/types.h>
-#include <bzlib.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
@@ -270,8 +269,6 @@ int bsdiff(int argc, char *argv[])
u_char buf[8];
u_char header[32];
FILE * pf;
- BZFILE * pfbz2;
- int bz2err;
if (argc != 4)
errx(1,"usage: %s oldfile newfile patchfile\n", argv[0]);
@@ -316,16 +313,16 @@ int bsdiff(int argc, char *argv[])
err(1, "%s", argv[3]);
/* Header is
- 0 8 "BSDIFF40"
- 8 8 length of bzip2ed ctrl block
- 16 8 length of bzip2ed diff block
+ 0 8 "BSDIFN40"
+ 8 8 length of ctrl block
+ 16 8 length of 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);
+ 32 ?? ctrl block
+ ?? ?? diff block
+ ?? ?? extra block */
+ memcpy(header, "BSDIFN40", 8);
offtout(0, header + 8);
offtout(0, header + 16);
offtout(newsize, header + 24);
@@ -333,8 +330,6 @@ int bsdiff(int argc, char *argv[])
err(1, "fwrite(%s)", argv[3]);
/* 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;
@@ -448,19 +443,16 @@ int bsdiff(int argc, char *argv[])
* diff, in the old file
*/
offtout(lenf, buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ if (fwrite(buf, 8, 1, pf) != 1)
+ errx(1, "fwrite");
offtout((scan - lenb) - (lastscan + lenf), buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ if (fwrite(buf, 8, 1, pf) != 1)
+ err(1, "fwrite");
offtout((pos - lenb) - (lastpos + lenf), buf);
- BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
- if (bz2err != BZ_OK)
- errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ if (fwrite(buf, 8, 1, pf) != 1)
+ err(1, "fwrite");
/* Update the variables describing the last match. Note that
* 'lastscan' is set to the start of the current match _after_ the
@@ -471,39 +463,24 @@ int bsdiff(int argc, char *argv[])
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);
- /* 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);
+ /* Write diff data */
+ if (dblen && fwrite(db, dblen, 1, pf) != 1)
+ err(1, "fwrite");
/* Compute size of compressed diff data */
if ((newsize = ftello(pf)) == -1)
err(1, "ftello");
offtout(newsize - len, header + 16);
- /* 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);
+ /* Write extra data */
+ if (eblen && fwrite(eb, eblen, 1, pf) != 1)
+ err(1, "fwrite");
/* Seek to the beginning, write the header, and close the file */
if (fseeko(pf, 0, SEEK_SET))
View
106 bspatch.c
@@ -37,6 +37,70 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:
#include <unistd.h>
#include <fcntl.h>
+/* Compatibility layer for reading either the old BSDIFF40 or the new BSDIFN40
+ patch formats: */
+
+typedef void* stream_t;
+
+typedef struct
+{
+ stream_t (*open)(FILE*);
+ void (*close)(stream_t);
+ int (*read)(stream_t, void*, int);
+} io_funcs_t;
+
+static stream_t BSDIFF40_open(FILE *f)
+{
+ int bzerr;
+ BZFILE *s;
+ if ((s = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", bzerr);
+ return s;
+}
+
+static void BSDIFF40_close(stream_t s)
+{
+ int bzerr;
+ BZ2_bzReadClose(&bzerr, (BZFILE*)s);
+}
+
+static int BSDIFF40_read(stream_t s, void *buf, int len)
+{
+ int bzerr, lenread;
+ lenread = BZ2_bzRead(&bzerr, (BZFILE*)s, buf, len);
+ if (bzerr != BZ_OK && bzerr != BZ_STREAM_END)
+ errx(1, "Corrupt patch\n");
+ return lenread;
+}
+
+static io_funcs_t BSDIFF40_funcs = {
+ BSDIFF40_open,
+ BSDIFF40_close,
+ BSDIFF40_read
+};
+
+
+static stream_t BSDIFN40_open(FILE *f)
+{
+ return f;
+}
+
+static void BSDIFN40_close(stream_t s)
+{
+}
+
+static int BSDIFN40_read(stream_t s, void *buf, int len)
+{
+ return fread(buf, 1, len, (FILE*)s);
+}
+
+static io_funcs_t BSDIFN40_funcs = {
+ BSDIFN40_open,
+ BSDIFN40_close,
+ BSDIFN40_read
+};
+
+
#ifndef u_char
typedef unsigned char u_char;
#endif
@@ -62,8 +126,7 @@ static off_t offtin(u_char *buf)
int bspatch(int argc,char * argv[])
{
FILE * f, * cpf, * dpf, * epf;
- BZFILE * cpfbz2, * dpfbz2, * epfbz2;
- int cbz2err, dbz2err, ebz2err;
+ stream_t cstream, dstream, estream;
int fd;
ssize_t oldsize,newsize;
ssize_t bzctrllen,bzdatalen;
@@ -73,6 +136,7 @@ int bspatch(int argc,char * argv[])
off_t ctrl[3];
off_t lenread;
off_t i;
+ io_funcs_t * io;
if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
@@ -82,7 +146,7 @@ int bspatch(int argc,char * argv[])
/*
File format:
- 0 8 "BSDIFF40"
+ 0 8 "BSDIFF40" (bzip2) or "BSDIFN40" (raw)
8 8 X
16 8 Y
24 8 sizeof(newfile)
@@ -102,7 +166,11 @@ int bspatch(int argc,char * argv[])
}
/* Check for appropriate magic */
- if (memcmp(header, "BSDIFF40", 8) != 0)
+ if (memcmp(header, "BSDIFF40", 8) == 0)
+ io = &BSDIFF40_funcs;
+ else if (memcmp(header, "BSDIFN40", 8) == 0)
+ io = &BSDIFN40_funcs;
+ else
errx(1, "Corrupt patch\n");
/* Read lengths from header */
@@ -120,22 +188,19 @@ int bspatch(int argc,char * argv[])
if (fseeko(cpf, 32, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3],
(long long)32);
- if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
- errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
+ cstream = io->open(cpf);
if ((dpf = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3],
(long long)(32 + bzctrllen));
- if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
- errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
+ dstream = io->open(dpf);
if ((epf = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3],
(long long)(32 + bzctrllen + bzdatalen));
- if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
- errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
+ estream = io->open(epf);
if(((fd=open(argv[1],O_RDONLY,0))<0) ||
((oldsize=lseek(fd,0,SEEK_END))==-1) ||
@@ -149,9 +214,8 @@ int bspatch(int argc,char * argv[])
while(newpos<newsize) {
/* Read control data */
for(i=0;i<=2;i++) {
- lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
- if ((lenread < 8) || ((cbz2err != BZ_OK) &&
- (cbz2err != BZ_STREAM_END)))
+ lenread = io->read(cstream, buf, 8);
+ if (lenread < 8)
errx(1, "Corrupt patch\n");
ctrl[i]=offtin(buf);
};
@@ -161,9 +225,8 @@ int bspatch(int argc,char * argv[])
errx(1,"Corrupt patch\n");
/* Read diff string */
- lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
- if ((lenread < ctrl[0]) ||
- ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
+ lenread = io->read(dstream, new + newpos, ctrl[0]);
+ if (lenread < ctrl[0])
errx(1, "Corrupt patch\n");
/* Add old data to diff string */
@@ -180,9 +243,8 @@ int bspatch(int argc,char * argv[])
errx(1,"Corrupt patch\n");
/* Read extra string */
- lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
- if ((lenread < ctrl[1]) ||
- ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
+ lenread = io->read(estream, new + newpos, ctrl[1]);
+ if (lenread < ctrl[1])
errx(1, "Corrupt patch\n");
/* Adjust pointers */
@@ -191,9 +253,9 @@ int bspatch(int argc,char * argv[])
};
/* Clean up the bzip2 reads */
- BZ2_bzReadClose(&cbz2err, cpfbz2);
- BZ2_bzReadClose(&dbz2err, dpfbz2);
- BZ2_bzReadClose(&ebz2err, epfbz2);
+ io->close(cstream);
+ io->close(dstream);
+ io->close(estream);
if (fclose(cpf) || fclose(dpf) || fclose(epf))
err(1, "fclose(%s)", argv[3]);
Please sign in to comment.
Something went wrong with that request. Please try again.