Module Name:    othersrc
Committed By:   agc
Date:           Thu Apr 28 05:21:31 UTC 2016

Added Files:
        othersrc/external/bsd/delta: Makefile README
        othersrc/external/bsd/delta/bin: 1 2 3 4 Makefile
        othersrc/external/bsd/delta/dist: Makefile delta.1 delta.c delta.h
            libdelta.3 libdelta.c main.c
        othersrc/external/bsd/delta/lib: Makefile shlib_version

Log Message:
Add the delta library and utility program, providing
space-efficient binary diff/patch functionality.

delta is a library (and an associated utility) which allow
us to perform binary diff and patching in an efficient way. It
is similar in function to xdelta and vcdiff (RFC 3284), but more
(space-)efficient.

        -rw-r--r--  1 agc  users  10107 Apr 14 10:41 1
        -rw-r--r--  1 agc  users    206 Apr 19 16:50 1.bsd
        -rw-r--r--  1 agc  users    109 Apr 27 22:11 1.diff
        -rw-r--r--  1 agc  users    222 Apr 19 16:48 1.xd
        -rw-r--r--  1 agc  users    158 Apr 19 17:48 1.xd3
        -rw-r--r--  1 agc  users  10113 Apr 14 10:41 2
        -rw-r--r--  1 agc  users  10113 Apr 27 22:11 2.new

The delta(1) utility takes 3 arguments - oldfile, newfile and
patchfile - and creates the patchfile from the binary difference of
the old and new files. There's an optional -d or -p to diff and
to patch, respectively. The default is to patch.

        % delta -d 2 1 2.diff
        % delta -p 2 1.new 2.diff
        % diff 1 1.new
        %

The patchfile uses bzip2, and is more efficient than both xdelta (v1
and v3) by Josh MacDonald, and bsdiff from Colin Percival, dated 2005.
It also uses zigzag encoding for the numbers stored internally, in
order to be space-efficient.

I also tried using xz/lzma compression, but the results were not good
- around 160 bytes for a delta file where bzip2 ended up with 109
bytes.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 othersrc/external/bsd/delta/Makefile \
    othersrc/external/bsd/delta/README
cvs rdiff -u -r0 -r1.1 othersrc/external/bsd/delta/bin/1 \
    othersrc/external/bsd/delta/bin/2 othersrc/external/bsd/delta/bin/3 \
    othersrc/external/bsd/delta/bin/4 \
    othersrc/external/bsd/delta/bin/Makefile
cvs rdiff -u -r0 -r1.1 othersrc/external/bsd/delta/dist/Makefile \
    othersrc/external/bsd/delta/dist/delta.1 \
    othersrc/external/bsd/delta/dist/delta.c \
    othersrc/external/bsd/delta/dist/delta.h \
    othersrc/external/bsd/delta/dist/libdelta.3 \
    othersrc/external/bsd/delta/dist/libdelta.c \
    othersrc/external/bsd/delta/dist/main.c
cvs rdiff -u -r0 -r1.1 othersrc/external/bsd/delta/lib/Makefile \
    othersrc/external/bsd/delta/lib/shlib_version

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: othersrc/external/bsd/delta/Makefile
diff -u /dev/null othersrc/external/bsd/delta/Makefile:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/Makefile	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,9 @@
+#	$NetBSD: Makefile,v 1.1 2016/04/28 05:21:31 agc Exp $
+
+SUBDIR=		lib .WAIT
+SUBDIR+=	bin
+
+.include <bsd.subdir.mk>
+
+t:
+	cd bin && ${MAKE} t
Index: othersrc/external/bsd/delta/README
diff -u /dev/null othersrc/external/bsd/delta/README:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/README	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,31 @@
+delta is a library (and an associated utility) which allow
+us to perform binary diff and patching in an efficient way. It
+is similar in function to xdelta and vcdiff (RFC 3284), but more
+(space-)efficient.
+
+	-rw-r--r--  1 agc  users  10107 Apr 14 10:41 1
+	-rw-r--r--  1 agc  users    206 Apr 19 16:50 1.bsd
+	-rw-r--r--  1 agc  users    109 Apr 27 22:11 1.diff
+	-rw-r--r--  1 agc  users    222 Apr 19 16:48 1.xd
+	-rw-r--r--  1 agc  users    158 Apr 19 17:48 1.xd3
+	-rw-r--r--  1 agc  users  10113 Apr 14 10:41 2
+	-rw-r--r--  1 agc  users  10113 Apr 27 22:11 2.new
+
+The delta(1) utility takes 3 arguments - oldfile, newfile and
+patchfile - and creates the patchfile from the binary difference of
+the old and new files. There's an optional -d or -p to diff and
+to patch, respectively. The default is to patch.
+
+	% delta -d 2 1 2.diff
+	% delta -p 2 1.new 2.diff
+	% diff 1 1.new
+	%
+
+The patchfile uses bzip2, and is more efficient than both xdelta (v1
+and v3) by Josh MacDonald, and bsdiff from Colin Percival, dated 2005. 
+It also uses zigzag encoding for the numbers stored internally, in
+order to be space-efficient.
+
+I also tried using xz/lzma compression, but the results were not good
+- around 160 bytes for a delta file where bzip2 ended up with 111
+bytes.

Index: othersrc/external/bsd/delta/bin/1
diff -u /dev/null othersrc/external/bsd/delta/bin/1:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/bin/1	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,404 @@
+/*-
+ * 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.
+ */
+
+#if 0
+__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
+#endif
+
+#include <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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)
+{
+	off_t i,j,k,x,tmp,jj,kk;
+
+	if(len<16) {
+		for(k=start;k<start+len;k+=j) {
+			j=1;x=V[I[k]+h];
+			for(i=1;k+i<start+len;i++) {
+				if(V[I[k+i]+h]<x) {
+					x=V[I[k+i]+h];
+					j=0;
+				};
+				if(V[I[k+i]+h]==x) {
+					tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
+					j++;
+				};
+			};
+			for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
+			if(j==1) I[k]=-1;
+		};
+		return;
+	};
+
+	x=V[I[start+len/2]+h];
+	jj=0;kk=0;
+	for(i=start;i<start+len;i++) {
+		if(V[I[i]+h]<x) jj++;
+		if(V[I[i]+h]==x) kk++;
+	};
+	jj+=start;kk+=jj;
+
+	i=start;j=0;k=0;
+	while(i<jj) {
+		if(V[I[i]+h]<x) {
+			i++;
+		} else if(V[I[i]+h]==x) {
+			tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
+			j++;
+		} else {
+			tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	while(jj+j<kk) {
+		if(V[I[jj+j]+h]==x) {
+			j++;
+		} else {
+			tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	if(jj>start) split(I,V,start,jj-start,h);
+
+	for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
+	if(jj==kk-1) I[jj]=-1;
+
+	if(start+len>kk) 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;
+
+	for(i=0;i<256;i++) buckets[i]=0;
+	for(i=0;i<oldsize;i++) buckets[old[i]]++;
+	for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
+	for(i=255;i>0;i--) buckets[i]=buckets[i-1];
+	buckets[0]=0;
+
+	for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
+	I[0]=oldsize;
+	for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
+	V[oldsize]=0;
+	for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
+	I[0]=-1;
+
+	for(h=1;I[0]!=-(oldsize+1);h+=h) {
+		len=0;
+		for(i=0;i<oldsize+1;) {
+			if(I[i]<0) {
+				len-=I[i];
+				i-=I[i];
+			} else {
+				if(len) I[i-len]=-len;
+				len=V[I[i]]+1-i;
+				split(I,V,i,len,h);
+				i+=len;
+				len=0;
+			};
+		};
+		if(len) I[i-len]=-len;
+	};
+
+	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
+}
+
+static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
+{
+	off_t i;
+
+	for(i=0;(i<oldsize)&&(i<newsize);i++)
+		if(old[i]!=new[i]) break;
+
+	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;
+}
+
+int main(int argc,char *argv[])
+{
+	int fd;
+	u_char *old,*new;
+	off_t oldsize,newsize;
+	off_t *I,*V;
+	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(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[1]);
+
+	if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) ||
+		((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL);
+
+	qsufsort(I,V,old,oldsize);
+
+	free(V);
+
+	/* Allocate newsize+1 bytes instead of newsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[2],O_RDONLY,0))<0) ||
+		((newsize=lseek(fd,0,SEEK_END))==-1) ||
+		((new=malloc(newsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,new,newsize)!=newsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[2]);
+
+	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(argv[3], "w")) == 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)
+		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;lastpos=0;lastoffset=0;
+	while(scan<newsize) {
+		oldscore=0;
+
+		for(scsc=scan+=len;scan<newsize;scan++) {
+			len=search(I,old,oldsize,new+scan,newsize-scan,
+					0,oldsize,&pos);
+
+			for(;scsc<scan+len;scsc++)
+			if((scsc+lastoffset<oldsize) &&
+				(old[scsc+lastoffset] == new[scsc]))
+				oldscore++;
+
+			if(((len==oldscore) && (len!=0)) || 
+				(len>oldscore+8)) break;
+
+			if((scan+lastoffset<oldsize) &&
+				(old[scan+lastoffset] == new[scan]))
+				oldscore--;
+		};
+
+		if((len!=oldscore) || (scan==newsize)) {
+			s=0;Sf=0;lenf=0;
+			for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
+				if(old[lastpos+i]==new[lastscan+i]) s++;
+				i++;
+				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
+			};
+
+			lenb=0;
+			if(scan<newsize) {
+				s=0;Sb=0;
+				for(i=1;(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;i<overlap;i++) {
+					if(new[lastscan+lenf-overlap+i]==
+					   old[lastpos+lenf-overlap+i]) s++;
+					if(new[scan-lenb+i]==
+					   old[pos-lenb+i]) s--;
+					if(s>Ss) { Ss=s; lens=i+1; };
+				};
+
+				lenf+=lens-overlap;
+				lenb-=lens;
+			};
+
+			for(i=0;i<lenf;i++)
+				db[dblen+i]=new[lastscan+i]-old[lastpos+i];
+			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+				eb[eblen+i]=new[lastscan+lenf+i];
+
+			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((scan-lenb)-(lastscan+lenf),buf);
+			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+			if (bz2err != BZ_OK)
+				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+			offtout((pos-lenb)-(lastpos+lenf),buf);
+			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+			if (bz2err != BZ_OK)
+				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+			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);
+
+	/* 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);
+
+	/* 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);
+
+	/* 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)
+		err(1, "fwrite(%s)", argv[3]);
+	if (fclose(pf))
+		err(1, "fclose");
+
+	/* Free the memory we used */
+	free(db);
+	free(eb);
+	free(I);
+	free(old);
+	free(new);
+
+	return 0;
+}
Index: othersrc/external/bsd/delta/bin/2
diff -u /dev/null othersrc/external/bsd/delta/bin/2:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/bin/2	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,404 @@
+/*-
+ * 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:
+ * 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.
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ */
+
+#if 0
+__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
+#endif
+
+#include <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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)
+{
+	off_t i,j,k,x,tmp,jj,kk;
+
+	if(len<=15) {
+		for(k=start;k<start+len;k+=j) {
+			j=1;x=V[I[k]+h];
+			for(i=1;k+i<start+len;i++) {
+				if(V[I[k+i]+h]<x) {
+					x=V[I[k+i]+h];
+					j=0;
+				};
+				if(V[I[k+i]+h]==x) {
+					tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
+					j++;
+				};
+			};
+			for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
+			if(j==1) I[k]=-1;
+		};
+		return;
+	};
+
+	x=V[I[start+len/2]+h];
+	jj=0;kk=0;
+	for(i=start;i<start+len;i++) {
+		if(V[I[i]+h]<x) jj++;
+		if(V[I[i]+h]==x) kk++;
+	};
+	jj+=start;kk+=jj;
+
+	i=start;j=0;k=0;
+	while(i<jj) {
+		if(V[I[i]+h]<x) {
+			i++;
+		} else if(V[I[i]+h]==x) {
+			tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
+			j++;
+		} else {
+			tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	while(jj+j<kk) {
+		if(V[I[jj+j]+h]==x) {
+			j++;
+		} else {
+			tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	if(jj>start) split(I,V,start,jj-start,h);
+
+	for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
+	if(jj==kk-1) I[jj]=-1;
+
+	if(start+len>kk) 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;
+
+	for(i=0;i<256;i++) buckets[i]=0;
+	for(i=0;i<oldsize;i++) buckets[old[i]]++;
+	for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
+	for(i=255;i>0;i--) buckets[i]=buckets[i-1];
+	buckets[0]=0;
+
+	for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
+	I[0]=oldsize;
+	for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
+	V[oldsize]=0;
+	for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
+	I[0]=-1;
+
+	for(h=1;I[0]!=-(oldsize+1);h+=h) {
+		len=0;
+		for(i=0;i<oldsize+1;) {
+			if(I[i]<0) {
+				len-=I[i];
+				i-=I[i];
+			} else {
+				if(len) I[i-len]=-len;
+				len=V[I[i]]+1-i;
+				split(I,V,i,len,h);
+				i+=len;
+				len=0;
+			};
+		};
+		if(len) I[i-len]=-len;
+	};
+
+	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
+}
+
+static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
+{
+	off_t i;
+
+	for(i=0;(i<oldsize)&&(i<newsize);i++)
+		if(old[i]!=new[i]) break;
+
+	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;
+}
+
+int main(int argc,char *argv[])
+{
+	int fd;
+	u_char *old,*new;
+	off_t oldsize,newsize;
+	off_t *I,*V;
+	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(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[1]);
+
+	if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) ||
+		((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL);
+
+	qsufsort(I,V,old,oldsize);
+
+	free(V);
+
+	/* Allocate newsize+1 bytes instead of newsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[2],O_RDONLY,0))<0) ||
+		((newsize=lseek(fd,0,SEEK_END))==-1) ||
+		((new=malloc(newsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,new,newsize)!=newsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[2]);
+
+	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(argv[3], "w")) == 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)
+		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;lastpos=0;lastoffset=0;
+	while(scan<newsize) {
+		oldscore=0;
+
+		for(scsc=scan+=len;scan<=newsize - 1;scan++) {
+			len=search(I,old,oldsize,new+scan,newsize-scan,
+					0,oldsize,&pos);
+
+			for(;scsc<scan+len;scsc++)
+			if((scsc+lastoffset<oldsize) &&
+				(old[scsc+lastoffset] == new[scsc]))
+				oldscore++;
+
+			if(((len==oldscore) && (len!=0)) || 
+				(len>oldscore+8)) break;
+
+			if((scan+lastoffset<oldsize) &&
+				(old[scan+lastoffset] == new[scan]))
+				oldscore--;
+		};
+
+		if((len!=oldscore) || (scan==newsize)) {
+			s=0;Sf=0;lenf=0;
+			for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
+				if(old[lastpos+i]==new[lastscan+i]) s++;
+				i++;
+				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
+			};
+
+			lenb=0;
+			if(scan<newsize) {
+				s=0;Sb=0;
+				for(i=1;(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;i<overlap;i++) {
+					if(new[lastscan+lenf-overlap+i]==
+					   old[lastpos+lenf-overlap+i]) s++;
+					if(new[scan-lenb+i]==
+					   old[pos-lenb+i]) s--;
+					if(s>Ss) { Ss=s; lens=i+1; };
+				};
+
+				lenf+=lens-overlap;
+				lenb-=lens;
+			};
+
+			for(i=0;i<lenf;i++)
+				db[dblen+i]=new[lastscan+i]-old[lastpos+i];
+			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+				eb[eblen+i]=new[lastscan+lenf+i];
+
+			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((scan-lenb)-(lastscan+lenf),buf);
+			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+			if (bz2err != BZ_OK)
+				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+			offtout((pos-lenb)-(lastpos+lenf),buf);
+			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+			if (bz2err != BZ_OK)
+				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+			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);
+
+	/* 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);
+
+	/* 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);
+
+	/* 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)
+		err(1, "fwrite(%s)", argv[3]);
+	if (fclose(pf))
+		err(1, "fclose");
+
+	/* Free the memory we used */
+	free(db);
+	free(eb);
+	free(I);
+	free(old);
+	free(new);
+
+	return 0;
+}
Index: othersrc/external/bsd/delta/bin/3
diff -u /dev/null othersrc/external/bsd/delta/bin/3:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/bin/3	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,751 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * 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 <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bsdiff.h"
+
+/* an output buffer structure */
+typedef struct obuf_t {
+	uint64_t	 c;	/* # of characters used */
+	uint64_t	 size;	/* output buffer size */
+	uint8_t		*v;	/* the array of chars */
+} obuf_t;
+
+/* the binary diff structure */
+typedef struct bsdiff_t {
+	obuf_t		 control;	/* output buffer for control info */
+	uint8_t		*diff;		/* diff text */
+	size_t		 difflen;	/* diff text length */
+	uint8_t		*extra;		/* extra text */
+	size_t		 extralen;	/* extra text length */
+	off_t		 newsize;	/* size of output */
+	uint8_t		 allocctl;	/* ctl was allocated */
+	uint8_t		 allocdiff;	/* diff was allocated */
+	uint8_t		 allocextra;	/* extra was allocated */
+} bsdiff_t;
+
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
+#ifndef ABS
+#define ABS(x)	(((x) < 0) ? -(x) : (x))
+#endif
+
+#ifndef howmany
+#define	howmany(x, y)	(((x)+((y)-1))/(y))
+#endif
+
+/* add the info to the obuf buffer */
+static int
+owrite(obuf_t *obuf, const void *p, size_t size)
+{
+	uint8_t	*newv;
+	size_t	 newsize;
+
+	if (obuf->c + size >= obuf->size) {
+		newsize = howmany(obuf->c + size, 4096) * 4096;
+		newv = realloc(obuf->v, newsize);
+		if (newv == NULL) {
+			return 0;
+		}
+		obuf->size = newsize;
+		obuf->v = newv;
+	}
+	memcpy(&obuf->v[obuf->c], p, size);
+	obuf->c += size;
+	return 1;
+}
+
+static void 
+split(off_t *I, off_t *V, off_t start, off_t len, off_t h)
+{
+	off_t 		i, j, k, x, tmp, jj, kk;
+
+	if (len < 16) {
+		for (k = start; k < start + len; k += j) {
+			j = 1;
+			x = V[I[k] + h];
+			for (i = 1; k + i < start + len; i++) {
+				if (V[I[k + i] + h] < x) {
+					x = V[I[k + i] + h];
+					j = 0;
+				}
+				if (V[I[k + i] + h] == x) {
+					tmp = I[k + j];
+					I[k + j] = I[k + i];
+					I[k + i] = tmp;
+					j++;
+				}
+			}
+			for (i = 0; i < j; i++)
+				V[I[k + i]] = k + j - 1;
+			if (j == 1)
+				I[k] = -1;
+		}
+		return;
+	}
+
+	x = V[I[start + len / 2] + h];
+	jj = 0;
+	kk = 0;
+	for (i = start; i < start + len; i++) {
+		if (V[I[i] + h] < x)
+			jj++;
+		if (V[I[i] + h] == x)
+			kk++;
+	}
+	jj += start;
+	kk += jj;
+
+	j = k = 0;
+	for (i = start; i < jj ; ) {
+		if (V[I[i] + h] < x) {
+			i++;
+		} else if (V[I[i] + h] == x) {
+			tmp = I[i];
+			I[i] = I[jj + j];
+			I[jj + j] = tmp;
+			j++;
+		} else {
+			tmp = I[i];
+			I[i] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+	while (jj + j < kk) {
+		if (V[I[jj + j] + h] == x) {
+			j++;
+		} else {
+			tmp = I[jj + j];
+			I[jj + j] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+
+	if (jj > start) {
+		split(I, V, start, jj - start, h);
+	}
+	for (i = 0; i < kk - jj; i++) {
+		V[I[jj + i]] = kk - 1;
+	}
+	if (jj == kk - 1) {
+		I[jj] = -1;
+	}
+	if (start + len > kk) {
+		split(I, V, kk, start + len - kk, h);
+	}
+}
+
+static void 
+qsufsort(off_t *I, off_t *V, const uint8_t *old, off_t oldsize)
+{
+	off_t 		buckets[256];
+	off_t 		i, h, len;
+
+	memset(buckets, 0x0, sizeof(buckets));
+	for (i = 0; i < oldsize; i++) {
+		buckets[old[i]]++;
+	}
+	for (i = 1; i < 256; i++) {
+		buckets[i] += buckets[i - 1];
+	}
+	for (i = 255; i > 0; i--) {
+		buckets[i] = buckets[i - 1];
+	}
+	buckets[0] = 0;
+
+	for (i = 0; i < oldsize; i++) {
+		I[++buckets[old[i]]] = i;
+	}
+	I[0] = oldsize;
+	for (i = 0; i < oldsize; i++) {
+		V[i] = buckets[old[i]];
+	}
+	V[oldsize] = 0;
+	for (i = 1; i < 256; i++) {
+		if (buckets[i] == buckets[i - 1] + 1) {
+			I[buckets[i]] = -1;
+		}
+	}
+	I[0] = -1;
+
+	for (h = 1; I[0] != -(oldsize + 1); h += h) {
+		for (len = 0, i = 0; i < oldsize + 1;) {
+			if (I[i] < 0) {
+				len -= I[i];
+				i -= I[i];
+			} else {
+				if (len) {
+					I[i - len] = -len;
+				}
+				len = V[I[i]] + 1 - i;
+				split(I, V, i, len, h);
+				i += len;
+				len = 0;
+			}
+		}
+		if (len) {
+			I[i - len] = -len;
+		}
+	}
+
+	for (i = 0; i < oldsize + 1; i++) {
+		I[V[i]] = i;
+	}
+}
+
+static off_t 
+matchlen(const uint8_t *old, off_t oldsize, const uint8_t *newv, off_t newsize)
+{
+	off_t 		i;
+
+	for (i = 0; i < oldsize && i < newsize && old[i] == newv[i] ; i++) {
+	}
+	return i;
+}
+
+static off_t 
+search(off_t *I, const uint8_t *old, off_t oldsize,
+       const uint8_t *newv, off_t newsize, off_t st, off_t en, size_t *pos)
+{
+	off_t 		x, y;
+
+	if (en - st < 2) {
+		x = matchlen(old + I[st], oldsize - I[st], newv, newsize);
+		y = matchlen(old + I[en], oldsize - I[en], newv, 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], newv, MIN(oldsize - I[x], newsize)) < 0) {
+		return search(I, old, oldsize, newv, newsize, x, en, pos);
+	} else {
+		return search(I, old, oldsize, newv, newsize, st, x, pos);
+	}
+}
+
+/* encode in zigzag encoding */
+static int
+put64(off_t x, uint8_t *buf)
+{
+	uint64_t	n;
+	uint8_t		*b;
+	int		 len;
+	int		 i;
+
+	n = (x << 1) ^ (x >> 63);
+	for (len = 0, b = buf, i = 0 ; i < 9 ; i++, b += len) {
+		*b = ((n >> ((9 - i) * 7)) & 0x7f) | 0x80;
+		if (len == 0 && *b != 0x80) {
+			len = 1;
+		}
+	}
+	*b++ = (n & 0x7f);
+	return (int)(b - buf);
+}
+
+/* decode from zigzag encoding */
+static int64_t
+get64(uint8_t *buf, size_t *len)
+{
+	uint64_t	n;
+
+	for (n = 0, *len = 0 ; *len < 10 ; *len += 1) {
+		n = (n << 7) + (buf[*len] & 0x7f);
+                if ((buf[*len] & 0x80) == 0) {
+			*len += 1;
+                        break;
+                }
+	}
+	return (n >> 1) ^ (-(n & 1));
+}
+
+/* read the file into the array */
+static int
+readfile(const char *f, uint8_t **v, off_t *size)
+{
+	ssize_t	cc;
+	ssize_t	rc;
+	int	fd;
+
+	if (((fd = open(f, O_RDONLY, 0)) < 0) ||
+	    ((*size = lseek(fd, 0, SEEK_END)) == -1) ||
+	    ((*v = malloc(*size + 1)) == NULL) ||
+	    (lseek(fd, 0, SEEK_SET) != 0)) {
+		warn("can't read file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < *size ; cc += rc) {
+		if ((rc = read(fd, &(*v)[cc], *size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == *size;
+}
+
+/* write the array to the file */
+static int
+writefile(const char *f, uint8_t *v, off_t size)
+{
+	ssize_t	cc;
+	ssize_t	wc;
+	int	fd;
+
+	/* Write the new file */
+	if ((fd = open(f, O_CREAT | O_TRUNC | O_WRONLY, 0666)) < 0) {
+		warn("can't write file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < size ; cc += wc) {
+		if ((wc = write(fd, &v[cc], size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == size;
+}
+
+/***********************************************************************/
+
+/* write the patch file from info held in delta struct */
+int
+bsdiff_write_patch_file(bsdiff_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	uint8_t		 buf[10];
+	size_t		 cc;
+	size_t		 wc;
+	size_t		 n;
+	obuf_t		 o;
+	FILE		*fp;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&o, 0x0, sizeof(o));
+	owrite(&o, "BSDIFF50", 8);
+	n = put64(delta->control.c, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->difflen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->extralen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->newsize, buf);
+	owrite(&o, buf, n);
+	if ((fp = fopen(patchfile, "w")) == NULL) {
+		warn("can't open '%s' for writing", patchfile);
+		return 0;
+	}
+	for (cc = 0 ; cc < o.c ; cc += wc) {
+		if ((wc = fwrite(&o.v[cc], 1, o.c - cc, fp)) == 0) {
+			break;
+		}
+	}
+	o.c = 0;
+	/* control info */
+	owrite(&o, delta->control.v, delta->control.c);
+	/* diff info */
+	owrite(&o, delta->diff, delta->difflen);
+	/* extra info */
+	owrite(&o, delta->extra, delta->extralen);
+	n = delta->control.c + delta->difflen + delta->extralen;
+	zsize = ((n + 128) * 101) / 100;
+	z = calloc(1, zsize);
+	BZ2_bzBuffToBuffCompress(z, &zsize, (char *)o.v, o.c, 9, 0, 0);
+	for (cc = 0 ; cc < zsize ; cc += wc) {
+		if ((wc = fwrite(&z[cc], 1, zsize - cc, fp)) == 0) {
+			break;
+		}
+	}
+	free(z);
+	free(o.v);
+	fclose(fp);
+	return cc == zsize;
+}
+
+/* read the patch file into the delta struct */
+int
+bsdiff_read_patch_file(bsdiff_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	size_t		 len;
+	size_t		 cc;
+	obuf_t		 o;
+	off_t	 	 size;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	memset(&o, 0x0, sizeof(o));
+	if (!readfile(patchfile, &o.v, &size)) {
+		return 0;
+	}
+	o.c = o.size = size;
+	if (memcmp(o.v, "BSDIFF50", 8) != 0) {
+		warnx("not a patch at offset 0");
+		return 0;
+	}
+	cc = 8;
+	delta->control.c = get64(&o.v[cc], &len);
+	cc += len;
+	delta->difflen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->extralen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->newsize = get64(&o.v[cc], &len);
+	cc += len;
+	zsize = delta->control.c + delta->difflen + delta->extralen;
+	if ((z = calloc(1, zsize)) == NULL ||
+	    BZ2_bzBuffToBuffDecompress(z, &zsize, (char *)&o.v[cc], size - cc, 0, 0) != BZ_OK) {
+		warn("resource allocation reading patch file");
+		return 0;
+	}
+	delta->allocctl = 1;
+	delta->control.v = (uint8_t *)z;
+	delta->diff = (uint8_t *)&z[delta->control.c];
+	delta->extra = (uint8_t *)&z[delta->control.c + delta->difflen];
+	free(o.v);
+	return 1;
+}
+
+/* diff 2 areas of memory */
+int
+bsdiff_diff_mem(bsdiff_t *delta, const void *aold, size_t oldsize, const void *anewv, size_t newsize)
+{
+	const uint8_t	*old = (const uint8_t *)aold;
+	const uint8_t	*newv = (const uint8_t *)anewv;
+	uint8_t		 buf[10];
+	off_t		 *I, *V;
+	size_t		 lastscan;
+	size_t		 overlap;
+	size_t		 scan;
+	size_t		 scsc;
+	size_t		 lenb;
+	size_t		 lenf;
+	size_t		 pos;
+	size_t		 Sb;
+	size_t		 Sf;
+	size_t		 Ss;
+	size_t		 s;
+	size_t		 i;
+	off_t		 len;
+	off_t		 lastpos, lastoffset;
+	off_t		 oldscore;
+	off_t		 lens;
+	int		 buflen;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	if (((I = malloc((oldsize + 1) * sizeof(*I))) == NULL) ||
+	    ((V = malloc((oldsize + 1) * sizeof(*V))) == NULL)) {
+		warn("allocation failure in bsd_diff_mem");
+		return 0;
+	}
+	qsufsort(I, V, old, oldsize);
+	free(V);
+	/*
+	 * Allocate newsize+1 bytes instead of newsize bytes to ensure that
+	 * we never try to malloc(0) and get a NULL pointer
+	 */
+	delta->newsize = newsize;
+	if (((delta->diff = malloc(newsize + 1)) == NULL) ||
+	    ((delta->extra = malloc(newsize + 1)) == NULL)) {
+		warn("allocation failure 2 in bsd_diff_mem");
+		return 0;
+	}
+	delta->allocdiff = delta->allocextra = 1;
+	scan = 0;
+	len = 0;
+	lastscan = 0;
+	lastpos = 0;
+	lastoffset = 0;
+	while (scan < newsize) {
+		oldscore = 0;
+		for (scsc = scan += len; scan < newsize; scan++) {
+			len = search(I, old, oldsize, newv + scan, newsize - scan,
+				     0, oldsize, &pos);
+
+			for (; scsc < scan + len; scsc++)
+				if ((scsc + lastoffset < oldsize) &&
+				    (old[scsc + lastoffset] == newv[scsc])) {
+					oldscore++;
+			}
+			if (((len == oldscore) && (len != 0)) ||
+			    (len > oldscore + 8)) {
+				break;
+			}
+			if ((scan + lastoffset < oldsize) &&
+			    (old[scan + lastoffset] == newv[scan])) {
+				oldscore--;
+			}
+		}
+		if ((len != oldscore) || (scan == newsize)) {
+			s = 0;
+			Sf = 0;
+			lenf = 0;
+			for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize);) {
+				if (old[lastpos + i] == newv[lastscan + i])
+					s++;
+				i++;
+				if (s * 2 - i > Sf * 2 - lenf) {
+					Sf = s;
+					lenf = i;
+				}
+			}
+			lenb = 0;
+			if (scan < newsize) {
+				s = 0;
+				Sb = 0;
+				for (i = 1; (scan >= lastscan + i) && (pos >= i); i++) {
+					if (old[pos - i] == newv[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; i < overlap; i++) {
+					if (newv[lastscan + lenf - overlap + i] ==
+					  old[lastpos + lenf - overlap + i]) {
+						s++;
+					}
+					if (newv[scan - lenb + i] ==
+					    old[pos - lenb + i]) {
+						s--;
+					}
+					if (s > Ss) {
+						Ss = s;
+						lens = i + 1;
+					}
+				}
+				lenf += lens - overlap;
+				lenb -= lens;
+			}
+			for (i = 0; i < lenf; i++) {
+				delta->diff[delta->difflen + i] = newv[lastscan + i] - old[lastpos + i];
+			}
+			for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++) {
+				delta->extra[delta->extralen + i] = newv[lastscan + lenf + i];
+			}
+			delta->difflen += lenf;
+			delta->extralen += (scan - lenb) - (lastscan + lenf);
+
+			buflen = put64(lenf, buf);
+			owrite(&delta->control, buf, buflen);
+
+			buflen = put64((scan - lenb) - (lastscan + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			buflen = put64((pos - lenb) - (lastpos + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			lastscan = scan - lenb;
+			lastpos = pos - lenb;
+			lastoffset = pos - scan;
+		}
+	}
+	free(I);
+	return 1;
+}
+
+/* diff two files, putting results in patch file */
+int
+bsdiff_diff_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	bsdiff_t	 delta;
+	uint8_t         *oldv;
+	uint8_t         *newv;
+	off_t 		 oldsize;
+	off_t 		 newsize;
+	int		 ok;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!readfile(oldfile, &oldv, &oldsize) ||
+	    !readfile(newfile, &newv, &newsize)) {
+		return 0;
+	}
+	if (!bsdiff_diff_mem(&delta, oldv, oldsize, newv, newsize)) {
+		return 0;
+	}
+	ok = bsdiff_write_patch_file(&delta, patchfile);
+	if (!ok) {
+		return 0;
+	}
+	/* Free the memory we used */
+	bsdiff_free(&delta);
+	free(oldv);
+	free(newv);
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+bsdiff_patch_mem(bsdiff_t *delta, const void *aold, size_t oldsize, void *anewv, size_t *newsize)
+{
+	const uint8_t	 *old = (const uint8_t *)aold;
+	uint8_t		**newv = (uint8_t **)anewv;
+	size_t		  extrac;
+	size_t		  diffc;
+	size_t		  ctlc;
+	size_t		  len;
+	off_t 		  ctrl[3];
+	off_t 		  oldpos;
+	off_t 		  newpos;
+	off_t		  i;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	if ((*newv = malloc(delta->newsize + 1)) == NULL) {
+		warn("allocation failure %zu bytes", delta->newsize + 1);
+		return 0;
+	}
+	for (oldpos = newpos = 0, ctlc = diffc = extrac = 0; newpos < delta->newsize ; ) {
+		/* Read control data */
+		for (i = 0; i < 3; i++) {
+			ctrl[i] = get64(&delta->control.v[ctlc], &len);
+			ctlc += len;
+		}
+		/* Sanity-check */
+		if (newpos + ctrl[0] > delta->newsize) {
+			warnx("Corrupt patch 1\n");
+			return 0;
+		}
+		/* Read diff string */
+		memcpy(&(*newv)[newpos], &delta->diff[diffc], ctrl[0]);
+		diffc += ctrl[0];
+		/* Add old data to diff string */
+		for (i = 0; i < ctrl[0]; i++) {
+			if ((oldpos + i >= 0) && (oldpos + i < (off_t)oldsize)) {
+				(*newv)[newpos + i] += old[oldpos + i];
+			}
+		}
+		/* Adjust pointers */
+		newpos += ctrl[0];
+		oldpos += ctrl[0];
+		/* Sanity-check */
+		if (newpos + ctrl[1] > delta->newsize) {
+			warnx("Corrupt patch 2\n");
+			return 0;
+		}
+		/* Read extra string */
+		memcpy(*newv + newpos, &delta->extra[extrac], ctrl[1]);
+		extrac += ctrl[1];
+		/* Adjust pointers */
+		newpos += ctrl[1];
+		oldpos += ctrl[2];
+	}
+	*newsize = delta->newsize;
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+bsdiff_patch_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	bsdiff_t	 delta;
+	ssize_t 	 oldsize;
+	uint8_t         *newv;
+	uint8_t         *old;
+	size_t 	 	 newsize;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!bsdiff_read_patch_file(&delta, patchfile)) {
+		return 0;
+	}
+	if (!readfile(oldfile, &old, &oldsize)) {
+		warn("%s", oldfile);
+		return 0;
+	}
+	if (!bsdiff_patch_mem(&delta, old, oldsize, &newv, &newsize)) {
+		return 0;
+	}
+	if (!writefile(newfile, newv, delta.newsize)) {
+		warn("%s", newfile);
+		return 0;
+	}
+	bsdiff_free(&delta);
+	return 1;
+}
+
+/* free resources associated with delta struct */
+void
+bsdiff_free(bsdiff_t *delta)
+{
+	if (delta) {
+		if (delta->allocctl) {
+			free(delta->control.v);
+		}
+		if (delta->allocdiff) {
+			free(delta->diff);
+		}
+		if (delta->allocextra) {
+			free(delta->extra);
+		}
+	}
+}
+
+/* make a new struct */
+bsdiff_t *
+bsdiff_new(void)
+{
+	return calloc(1, sizeof(bsdiff_t));
+}
Index: othersrc/external/bsd/delta/bin/4
diff -u /dev/null othersrc/external/bsd/delta/bin/4:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/bin/4	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,751 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * 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 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.
+ * 2. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * 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 <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bsdiff.h"
+
+/* an output buffer structure */
+typedef struct obuf_t {
+	uint64_t	 c;	/* # of characters used */
+	uint64_t	 size;	/* output buffer size */
+	uint8_t		*v;	/* the array of chars */
+} obuf_t;
+
+/* the binary diff structure */
+typedef struct bsdiff_t {
+	obuf_t		 control;	/* output buffer for control info */
+	uint8_t		*diff;		/* diff text */
+	size_t		 difflen;	/* diff text length */
+	uint8_t		*extra;		/* extra text */
+	size_t		 extralen;	/* extra text length */
+	off_t		 newsize;	/* size of output */
+	uint8_t		 allocctl;	/* ctl was allocated */
+	uint8_t		 allocdiff;	/* diff was allocated */
+	uint8_t		 allocextra;	/* extra was allocated */
+} bsdiff_t;
+
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
+#ifndef ABS
+#define ABS(x)	(((x) < 0) ? -(x) : (x))
+#endif
+
+#ifndef howmany
+#define	howmany(x, y)	(((x)+((y)-1))/(y))
+#endif
+
+/* add the info to the obuf buffer */
+static int
+owrite(obuf_t *obuf, const void *p, size_t size)
+{
+	uint8_t	*newv;
+	size_t	 newsize;
+
+	if (obuf->c + size >= obuf->size) {
+		newsize = howmany(obuf->c + size, 4096) * 4096;
+		newv = realloc(obuf->v, newsize);
+		if (newv == NULL) {
+			return 0;
+		}
+		obuf->size = newsize;
+		obuf->v = newv;
+	}
+	memcpy(&obuf->v[obuf->c], p, size);
+	obuf->c += size;
+	return 1;
+}
+
+static void 
+split(off_t *I, off_t *V, off_t start, off_t len, off_t h)
+{
+	off_t 		i, j, k, x, tmp, jj, kk;
+
+	if (len <= 15) {
+		for (k = start; k < start + len; k += j) {
+			j = 1;
+			x = V[I[k] + h];
+			for (i = 1; k + i < start + len; i++) {
+				if (V[I[k + i] + h] < x) {
+					x = V[I[k + i] + h];
+					j = 0;
+				}
+				if (V[I[k + i] + h] == x) {
+					tmp = I[k + j];
+					I[k + j] = I[k + i];
+					I[k + i] = tmp;
+					j++;
+				}
+			}
+			for (i = 0; i < j; i++)
+				V[I[k + i]] = k + j - 1;
+			if (j == 1)
+				I[k] = -1;
+		}
+		return;
+	}
+
+	x = V[I[start + len / 2] + h];
+	jj = 0;
+	kk = 0;
+	for (i = start; i < start + len; i++) {
+		if (V[I[i] + h] < x)
+			jj++;
+		if (V[I[i] + h] == x)
+			kk++;
+	}
+	jj += start;
+	kk += jj;
+
+	j = k = 0;
+	for (i = start; i < jj ; ) {
+		if (V[I[i] + h] < x) {
+			i++;
+		} else if (V[I[i] + h] == x) {
+			tmp = I[i];
+			I[i] = I[jj + j];
+			I[jj + j] = tmp;
+			j++;
+		} else {
+			tmp = I[i];
+			I[i] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+	while (jj + j < kk) {
+		if (V[I[jj + j] + h] == x) {
+			j++;
+		} else {
+			tmp = I[jj + j];
+			I[jj + j] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+
+	if (jj > start) {
+		split(I, V, start, jj - start, h);
+	}
+	for (i = 0; i < kk - jj; i++) {
+		V[I[jj + i]] = kk - 1;
+	}
+	if (jj == kk - 1) {
+		I[jj] = -1;
+	}
+	if (start + len > kk) {
+		split(I, V, kk, start + len - kk, h);
+	}
+}
+
+static void 
+qsufsort(off_t *I, off_t *V, const uint8_t *old, off_t oldsize)
+{
+	off_t 		buckets[256];
+	off_t 		i, h, len;
+
+	memset(buckets, 0x0, sizeof(buckets));
+	for (i = 0; i < oldsize; i++) {
+		buckets[old[i]]++;
+	}
+	for (i = 1; i < 256; i++) {
+		buckets[i] += buckets[i - 1];
+	}
+	for (i = 255; i > 0; i--) {
+		buckets[i] = buckets[i - 1];
+	}
+	buckets[0] = 0;
+
+	for (i = 0; i < oldsize; i++) {
+		I[++buckets[old[i]]] = i;
+	}
+	I[0] = oldsize;
+	for (i = 0; i < oldsize; i++) {
+		V[i] = buckets[old[i]];
+	}
+	V[oldsize] = 0;
+	for (i = 1; i < 256; i++) {
+		if (buckets[i] == buckets[i - 1] + 1) {
+			I[buckets[i]] = -1;
+		}
+	}
+	I[0] = -1;
+
+	for (h = 1; I[0] != -(oldsize + 1); h += h) {
+		for (len = 0, i = 0; i < oldsize + 1;) {
+			if (I[i] < 0) {
+				len -= I[i];
+				i -= I[i];
+			} else {
+				if (len) {
+					I[i - len] = -len;
+				}
+				len = V[I[i]] + 1 - i;
+				split(I, V, i, len, h);
+				i += len;
+				len = 0;
+			}
+		}
+		if (len) {
+			I[i - len] = -len;
+		}
+	}
+
+	for (i = 0; i < oldsize + 1; i++) {
+		I[V[i]] = i;
+	}
+}
+
+static off_t 
+matchlen(const uint8_t *old, off_t oldsize, const uint8_t *newv, off_t newsize)
+{
+	off_t 		i;
+
+	for (i = 0; i < oldsize && i < newsize && old[i] == newv[i] ; i++) {
+	}
+	return i;
+}
+
+static off_t 
+search(off_t *I, const uint8_t *old, off_t oldsize,
+       const uint8_t *newv, off_t newsize, off_t st, off_t en, size_t *pos)
+{
+	off_t 		x, y;
+
+	if (en - st < 2) {
+		x = matchlen(old + I[st], oldsize - I[st], newv, newsize);
+		y = matchlen(old + I[en], oldsize - I[en], newv, 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], newv, MIN(oldsize - I[x], newsize)) < 0) {
+		return search(I, old, oldsize, newv, newsize, x, en, pos);
+	} else {
+		return search(I, old, oldsize, newv, newsize, st, x, pos);
+	}
+}
+
+/* encode in zigzag encoding */
+static int
+put64(off_t x, uint8_t *buf)
+{
+	uint64_t	n;
+	uint8_t		*b;
+	int		 len;
+	int		 i;
+
+	n = (x << 1) ^ (x >> 63);
+	for (len = 0, b = buf, i = 0 ; i < 9 ; i++, b += len) {
+		*b = ((n >> ((9 - i) * 7)) & 0x7f) | 0x80;
+		if (len == 0 && *b != 0x80) {
+			len = 1;
+		}
+	}
+	*b++ = (n & 0x7f);
+	return (int)(b - buf);
+}
+
+/* decode from zigzag encoding */
+static int64_t
+get64(uint8_t *buf, size_t *len)
+{
+	uint64_t	n;
+
+	for (n = 0, *len = 0 ; *len < 10 ; *len += 1) {
+		n = (n << 7) + (buf[*len] & 0x7f);
+                if ((buf[*len] & 0x80) == 0) {
+			*len += 1;
+                        break;
+                }
+	}
+	return (n >> 1) ^ (-(n & 1));
+}
+
+/* read the file into the array */
+static int
+readfile(const char *f, uint8_t **v, off_t *size)
+{
+	ssize_t	cc;
+	ssize_t	rc;
+	int	fd;
+
+	if (((fd = open(f, O_RDONLY, 0)) < 0) ||
+	    ((*size = lseek(fd, 0, SEEK_END)) == -1) ||
+	    ((*v = malloc(*size + 1)) == NULL) ||
+	    (lseek(fd, 0, SEEK_SET) != 0)) {
+		warn("can't read file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < *size ; cc += rc) {
+		if ((rc = read(fd, &(*v)[cc], *size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == *size;
+}
+
+/* write the array to the file */
+static int
+writefile(const char *f, uint8_t *v, off_t size)
+{
+	ssize_t	cc;
+	ssize_t	wc;
+	int	fd;
+
+	/* Write the new file */
+	if ((fd = open(f, O_CREAT | O_TRUNC | O_WRONLY, 0666)) < 0) {
+		warn("can't write file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < size ; cc += wc) {
+		if ((wc = write(fd, &v[cc], size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == size;
+}
+
+/***********************************************************************/
+
+/* write the patch file from info held in delta struct */
+int
+bsdiff_write_patch_file(bsdiff_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	uint8_t		 buf[10];
+	size_t		 cc;
+	size_t		 wc;
+	size_t		 n;
+	obuf_t		 o;
+	FILE		*fp;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&o, 0x0, sizeof(o));
+	owrite(&o, "BSDIFF50", 8);
+	n = put64(delta->control.c, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->difflen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->extralen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->newsize, buf);
+	owrite(&o, buf, n);
+	if ((fp = fopen(patchfile, "w")) == NULL) {
+		warn("can't open '%s' for writing", patchfile);
+		return 0;
+	}
+	for (cc = 0 ; cc < o.c ; cc += wc) {
+		if ((wc = fwrite(&o.v[cc], 1, o.c - cc, fp)) == 0) {
+			break;
+		}
+	}
+	o.c = 0;
+	/* control info */
+	owrite(&o, delta->control.v, delta->control.c);
+	/* diff info */
+	owrite(&o, delta->diff, delta->difflen);
+	/* extra info */
+	owrite(&o, delta->extra, delta->extralen);
+	n = delta->control.c + delta->difflen + delta->extralen;
+	zsize = ((n + 128) * 101) / 100;
+	z = calloc(1, zsize);
+	BZ2_bzBuffToBuffCompress(z, &zsize, (char *)o.v, o.c, 9, 0, 0);
+	for (cc = 0 ; cc < zsize ; cc += wc) {
+		if ((wc = fwrite(&z[cc], 1, zsize - cc, fp)) == 0) {
+			break;
+		}
+	}
+	free(z);
+	free(o.v);
+	fclose(fp);
+	return cc == zsize;
+}
+
+/* read the patch file into the delta struct */
+int
+bsdiff_read_patch_file(bsdiff_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	size_t		 len;
+	size_t		 cc;
+	obuf_t		 o;
+	off_t	 	 size;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	memset(&o, 0x0, sizeof(o));
+	if (!readfile(patchfile, &o.v, &size)) {
+		return 0;
+	}
+	o.c = o.size = size;
+	if (memcmp(o.v, "BSDIFF50", 8) != 0) {
+		warnx("not a patch at offset 0");
+		return 0;
+	}
+	cc = 8;
+	delta->control.c = get64(&o.v[cc], &len);
+	cc += len;
+	delta->difflen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->extralen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->newsize = get64(&o.v[cc], &len);
+	cc += len;
+	zsize = delta->control.c + delta->difflen + delta->extralen;
+	if ((z = calloc(1, zsize)) == NULL ||
+	    BZ2_bzBuffToBuffDecompress(z, &zsize, (char *)&o.v[cc], size - cc, 0, 0) != BZ_OK) {
+		warn("resource allocation reading patch file");
+		return 0;
+	}
+	delta->allocctl = 1;
+	delta->control.v = (uint8_t *)z;
+	delta->diff = (uint8_t *)&z[delta->control.c];
+	delta->extra = (uint8_t *)&z[delta->control.c + delta->difflen];
+	free(o.v);
+	return 1;
+}
+
+/* diff 2 areas of memory */
+int
+bsdiff_diff_mem(bsdiff_t *delta, const void *aold, size_t oldsize, const void *anewv, size_t newsize)
+{
+	const uint8_t	*old = (const uint8_t *)aold;
+	const uint8_t	*newv = (const uint8_t *)anewv;
+	uint8_t		 buf[10];
+	off_t		 *I, *V;
+	size_t		 lastscan;
+	size_t		 overlap;
+	size_t		 scan;
+	size_t		 scsc;
+	size_t		 lenb;
+	size_t		 lenf;
+	size_t		 pos;
+	size_t		 Sb;
+	size_t		 Sf;
+	size_t		 Ss;
+	size_t		 s;
+	size_t		 i;
+	off_t		 len;
+	off_t		 lastpos, lastoffset;
+	off_t		 oldscore;
+	off_t		 lens;
+	int		 buflen;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	if (((I = malloc((oldsize + 1) * sizeof(*I))) == NULL) ||
+	    ((V = malloc((oldsize + 1) * sizeof(*V))) == NULL)) {
+		warn("allocation failure in bsd_diff_mem");
+		return 0;
+	}
+	qsufsort(I, V, old, oldsize);
+	free(V);
+	/*
+	 * Allocate newsize+1 bytes instead of newsize bytes to ensure that
+	 * we never try to malloc(0) and get a NULL pointer
+	 */
+	delta->newsize = newsize;
+	if (((delta->diff = malloc(newsize + 1)) == NULL) ||
+	    ((delta->extra = malloc(newsize + 1)) == NULL)) {
+		warn("allocation failure 2 in bsd_diff_mem");
+		return 0;
+	}
+	delta->allocdiff = delta->allocextra = 1;
+	scan = 0;
+	len = 0;
+	lastscan = 0;
+	lastpos = 0;
+	lastoffset = 0;
+	while (scan < newsize) {
+		oldscore = 0;
+		for (scsc = scan += len; scan < newsize; scan++) {
+			len = search(I, old, oldsize, newv + scan, newsize - scan,
+				     0, oldsize, &pos);
+
+			for (; scsc < scan + len; scsc++)
+				if ((scsc + lastoffset < oldsize) &&
+				    (old[scsc + lastoffset] == newv[scsc])) {
+					oldscore++;
+			}
+			if (((len == oldscore) && (len != 0)) ||
+			    (len > oldscore + 8)) {
+				break;
+			}
+			if ((scan + lastoffset < oldsize) &&
+			    (old[scan + lastoffset] == newv[scan])) {
+				oldscore--;
+			}
+		}
+		if ((len != oldscore) || (scan == newsize)) {
+			s = 0;
+			Sf = 0;
+			lenf = 0;
+			for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize);) {
+				if (old[lastpos + i] == newv[lastscan + i])
+					s++;
+				i++;
+				if (s * 2 - i > Sf * 2 - lenf) {
+					Sf = s;
+					lenf = i;
+				}
+			}
+			lenb = 0;
+			if (scan < newsize) {
+				s = 0;
+				Sb = 0;
+				for (i = 1; (scan >= lastscan + i) && (pos >= i); i++) {
+					if (old[pos - i] == newv[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; i < overlap; i++) {
+					if (newv[lastscan + lenf - overlap + i] ==
+					  old[lastpos + lenf - overlap + i]) {
+						s++;
+					}
+					if (newv[scan - lenb + i] ==
+					    old[pos - lenb + i]) {
+						s--;
+					}
+					if (s > Ss) {
+						Ss = s;
+						lens = i + 1;
+					}
+				}
+				lenf += lens - overlap;
+				lenb -= lens;
+			}
+			for (i = 0; i < lenf; i++) {
+				delta->diff[delta->difflen + i] = newv[lastscan + i] - old[lastpos + i];
+			}
+			for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++) {
+				delta->extra[delta->extralen + i] = newv[lastscan + lenf + i];
+			}
+			delta->difflen += lenf;
+			delta->extralen += (scan - lenb) - (lastscan + lenf);
+
+			buflen = put64(lenf, buf);
+			owrite(&delta->control, buf, buflen);
+
+			buflen = put64((scan - lenb) - (lastscan + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			buflen = put64((pos - lenb) - (lastpos + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			lastscan = scan - lenb;
+			lastpos = pos - lenb;
+			lastoffset = pos - scan;
+		}
+	}
+	free(I);
+	return 1;
+}
+
+/* diff two files, putting results in patch file */
+int
+bsdiff_diff_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	bsdiff_t	 delta;
+	uint8_t         *oldv;
+	uint8_t         *newv;
+	off_t 		 oldsize;
+	off_t 		 newsize;
+	int		 ok;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!readfile(oldfile, &oldv, &oldsize) ||
+	    !readfile(newfile, &newv, &newsize)) {
+		return 0;
+	}
+	if (!bsdiff_diff_mem(&delta, oldv, oldsize, newv, newsize)) {
+		return 0;
+	}
+	ok = bsdiff_write_patch_file(&delta, patchfile);
+	if (!ok) {
+		return 0;
+	}
+	/* Free the memory we used */
+	bsdiff_free(&delta);
+	free(oldv);
+	free(newv);
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+bsdiff_patch_mem(bsdiff_t *delta, const void *aold, size_t oldsize, void *anewv, size_t *newsize)
+{
+	const uint8_t	 *old = (const uint8_t *)aold;
+	uint8_t		**newv = (uint8_t **)anewv;
+	size_t		  extrac;
+	size_t		  diffc;
+	size_t		  ctlc;
+	size_t		  len;
+	off_t 		  ctrl[3];
+	off_t 		  oldpos;
+	off_t 		  newpos;
+	off_t		  i;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	if ((*newv = malloc(delta->newsize + 1)) == NULL) {
+		warn("allocation failure %zu bytes", delta->newsize + 1);
+		return 0;
+	}
+	for (oldpos = newpos = 0, ctlc = diffc = extrac = 0; newpos < delta->newsize ; ) {
+		/* Read control data */
+		for (i = 0; i < 3; i++) {
+			ctrl[i] = get64(&delta->control.v[ctlc], &len);
+			ctlc += len;
+		}
+		/* Sanity-check */
+		if (newpos + ctrl[0] > delta->newsize) {
+			warnx("Corrupt patch 1\n");
+			return 0;
+		}
+		/* Read diff string */
+		memcpy(&(*newv)[newpos], &delta->diff[diffc], ctrl[0]);
+		diffc += ctrl[0];
+		/* Add old data to diff string */
+		for (i = 0; i < ctrl[0]; i++) {
+			if ((oldpos + i >= 0) && (oldpos + i < (off_t)oldsize)) {
+				(*newv)[newpos + i] += old[oldpos + i];
+			}
+		}
+		/* Adjust pointers */
+		newpos += ctrl[0];
+		oldpos += ctrl[0];
+		/* Sanity-check */
+		if (newpos + ctrl[1] > delta->newsize) {
+			warnx("Corrupt patch 2\n");
+			return 0;
+		}
+		/* Read extra string */
+		memcpy(*newv + newpos, &delta->extra[extrac], ctrl[1]);
+		extrac += ctrl[1];
+		/* Adjust pointers */
+		newpos += ctrl[1];
+		oldpos += ctrl[2];
+	}
+	*newsize = delta->newsize;
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+bsdiff_patch_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	bsdiff_t	 delta;
+	ssize_t 	 oldsize;
+	uint8_t         *newv;
+	uint8_t         *old;
+	size_t 	 	 newsize;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!bsdiff_read_patch_file(&delta, patchfile)) {
+		warnx("can't read patchfile '%s'", patchfile);
+		return 0;
+	}
+	if (!readfile(oldfile, &old, &oldsize)) {
+		return 0;
+	}
+	if (!bsdiff_patch_mem(&delta, old, oldsize, &newv, &newsize)) {
+		return 0;
+	}
+	if (!writefile(newfile, newv, delta.newsize)) {
+		warn("%s", newfile);
+		return 0;
+	}
+	bsdiff_free(&delta);
+	return 1;
+}
+
+/* free resources associated with delta struct */
+void
+bsdiff_free(bsdiff_t *delta)
+{
+	if (delta) {
+		if (delta->allocctl) {
+			free(delta->control.v);
+		}
+		if (delta->allocextra) {
+			free(delta->extra);
+		}
+		if (delta->allocdiff) {
+			free(delta->diff);
+		}
+	}
+}
+
+/* make a new struct */
+bsdiff_t *
+bsdiff_new(void)
+{
+	return calloc(1, sizeof(bsdiff_t));
+}
Index: othersrc/external/bsd/delta/bin/Makefile
diff -u /dev/null othersrc/external/bsd/delta/bin/Makefile:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/bin/Makefile	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,53 @@
+# $NetBSD: Makefile,v 1.1 2016/04/28 05:21:31 agc Exp $
+
+.include <bsd.own.mk>
+
+PROG=		delta
+SRCS=		main.c
+BINDIR=		/usr/bin
+
+CPPFLAGS+=	-I${.CURDIR}/../dist/
+
+LIB_DELTA_DIR!=	cd ${.CURDIR}/../lib && ${PRINTOBJDIR}
+LDADD+=		-L${LIB_DELTA_DIR} -ldelta
+DPADD+=		${LIB_DELTA_DIR}/libdelta.a
+
+.ifndef PRODUCTION
+CPPFLAGS+=-g -O0
+LDFLAGS+=-g -O0
+.endif
+
+MAN=		delta.1
+
+WARNS=		5
+
+.PATH: ${.CURDIR}/../dist
+
+.include <bsd.prog.mk>
+
+t:
+	@echo "1. basics"
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -d 1 2 2.diff
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -p 1 2.new 2.diff
+	diff 2 2.new
+	ls -al 1 2 2.new 2.diff
+	rm -f 2.new 2.diff
+	@echo "2. backwards"
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -d 2 1 2.diff
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -p 2 1.new 2.diff
+	diff 1 1.new
+	ls -al 1 2 1.new 2.diff
+	rm -f 1.new 2.diff
+	@echo "3. new patch file"
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -d 2 1 2.diff
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -p 2 1.new 2.diff
+	diff 1 1.new
+	ls -al 1 2 1.new 2.diff
+	rm -f 1.new 2.diff
+	@echo "4. more extensive changes"
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -d 4 3 4.diff
+	env LD_LIBRARY_PATH=${.CURDIR}/../lib ./${PROG} -p 4 3.new 4.diff
+	diff 3 3.new
+	hexdump -C 4.diff
+	ls -al 3 4 3.new 4.diff
+	rm -f 3.new 4.diff

Index: othersrc/external/bsd/delta/dist/Makefile
diff -u /dev/null othersrc/external/bsd/delta/dist/Makefile:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/Makefile	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,24 @@
+CFLAGS		+=	-O3 -lbz2
+
+PREFIX		?=	/usr/local
+INSTALL_PROGRAM	?=	${INSTALL} -c -s -m 555
+INSTALL_MAN	?=	${INSTALL} -c -m 444
+
+all:		bsdiff bspatch
+
+bsdiff:		bsdiff.c libbsdiff.c
+	${CC} ${CFLAGS} bsdiff.c libbsdiff.c -o bsdiff
+bspatch:	bspatch.c libbsdiff.c
+	${CC} ${CFLAGS} bspatch.c libbsdiff.c -o bspatch
+
+install:
+	${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin
+.ifndef WITHOUT_MAN
+	${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1
+.endif
+
+t:
+	./bsdiff 2 1 2.diff
+	./bspatch 2 1.new 2.diff
+	diff 1 1.new
+	rm -f 1.new 2.diff
Index: othersrc/external/bsd/delta/dist/delta.1
diff -u /dev/null othersrc/external/bsd/delta/dist/delta.1:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/delta.1	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,74 @@
+.\"-
+.\" 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.
+.\"
+.\" $FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.1,v 1.1 2005/08/06 01:59:05 cperciva Exp $
+.\"
+.Dd April 14, 2016
+.Dt DELTA 1
+.Os
+.Sh NAME
+.Nm delta
+.Nd manage deltas between two binary files
+.Sh SYNOPSIS
+.Nm
+.Op Fl dp
+.Ar oldfile newfile patchfile
+.Sh DESCRIPTION
+.Nm
+compares
+.Ao Ar oldfile Ac
+to
+.Ao Ar newfile Ac
+and writes to
+.Ao Ar patchfile Ac
+a binary patch suitable for use by bspatch(1).
+When
+.Ao Ar oldfile Ac
+and
+.Ao Ar newfile Ac
+are two versions of an executable program, the
+patches produced are on average a factor of five smaller
+than those produced by any other binary patch tool known
+to the author.
+.Pp
+.Nm
+uses memory equal to 17 times the size of 
+.Ao Ar oldfile Ac ,
+and requires
+an absolute minimum working set size of 8 times the size of oldfile.
+.Sh SEE ALSO
+.Xr libdelta 3
+.Sh HISTORY
+The
+.Nm
+program was first seen in
+.Nx 8 .
+.Sh AUTHORS
+The
+.Nm
+program was written by
+.An Alistair Crooks Aq Mt a...@netbsd.org .
+It was based on some much earlier code by
+.An Colin Percival .
Index: othersrc/external/bsd/delta/dist/delta.c
diff -u /dev/null othersrc/external/bsd/delta/dist/delta.c:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/delta.c	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,47 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * 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 <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "delta.h"
+
+int
+main(int argc, char **argv)
+{
+	int	i;
+
+	while ((i = getopt(argc, argv, "")) != -1) {
+	}
+	if (argc - optind != 3) {
+		errx(EXIT_FAILURE, "usage: %s oldfile newfile patchfile\n", argv[0]);
+	}
+	return delta_diff_file(argv[optind], argv[optind + 1], argv[optind + 2]) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
Index: othersrc/external/bsd/delta/dist/delta.h
diff -u /dev/null othersrc/external/bsd/delta/dist/delta.h:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/delta.h	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided 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.
+ */
+#ifndef DELTA_H_
+#define DELTA_H_	20160414
+
+struct delta_t;
+typedef struct delta_t	delta_t;
+
+#ifndef __BEGIN_DECLS
+#  if defined(__cplusplus)
+#  define __BEGIN_DECLS           extern "C" {
+#  define __END_DECLS             }
+#  else
+#  define __BEGIN_DECLS
+#  define __END_DECLS
+#  endif
+#endif
+
+__BEGIN_DECLS
+
+delta_t *delta_new(void);
+void delta_free(delta_t */*delta*/);
+
+int delta_diff_mem(delta_t */*delta*/, const void */*old*/, size_t /*oldc*/, const void */*new*/, size_t /*newc*/);
+int delta_patch_mem(delta_t */*delta*/, const void */*old*/, size_t /*oldc*/, void */*newv*/, size_t */*newc*/);
+
+int delta_diff_file(const char */*oldfile*/, const char */*newfile*/, const char */*patchfile*/);
+int delta_patch_file(const char */*oldfile*/, const char */*newfile*/, const char */*patchfile*/);
+
+int delta_read_patch_file(delta_t */*delta*/, const char */*patchfile*/);
+int delta_write_patch_file(delta_t */*delta*/, const char */*patchfile*/);
+
+__END_DECLS
+
+#endif
Index: othersrc/external/bsd/delta/dist/libdelta.3
diff -u /dev/null othersrc/external/bsd/delta/dist/libdelta.3:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/libdelta.3	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,120 @@
+.\" $NetBSD: libdelta.3,v 1.1 2016/04/28 05:21:31 agc Exp $
+.\"
+.\" Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided 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.
+.\"
+.Dd April 14, 2016
+.Dt LIBDELTA 3
+.Os
+.Sh NAME
+.Nm libdelta
+.Nd library providing binary diff and patch functionality
+.Sh LIBRARY
+.Lb libdelta
+.Sh SYNOPSIS
+.In delta.h
+.Ft "delta_t *" 
+.Fo delta_new
+.Fa "void"
+.Fc
+.Ft int
+.Fo delta_free
+.Fa "delta_t *delta"
+.Fc
+.Ft int
+.Fo delta_diff_mem
+.Fa "delta_t *delta" "const void *old" "size_t oldc"
+.Fa "const void *new" "size_t newc"
+.Fc
+.Ft int
+.Fo delta_patch_mem
+.Fa "delta_t *delta" "const void *old" "size_t oldc"
+.Fa "void *new" "size_t *newc"
+.Fc
+.Ft int
+.Fo delta_diff_file
+.Fa "const char *oldfile" "const char *newfile" "const char *patchfile"
+.Fc
+.Ft int
+.Fo delta_patch_file
+.Fa "const char *oldfile" "const char *newfile" "const char *patchfile"
+.Fc
+.Ft int
+.Fo delta_read_patch_file
+.Fa "delta_t *delta" "const char *patchfile"
+.Fc
+.Ft int
+.Fo delta_write_patch_file
+.Fa "delta_t *delta" "const char *patchfile"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+library is a library interface which provides
+a space-efficient binary diff and patch functionality
+for use by programs and scripts.
+The typical space usage is about half of xdelta version 1.
+.Pp
+A
+.Dv delta_t
+structure is opaque, and is initialised
+using the
+.Fn delta_new
+function, and all resources freed
+with the
+.Fn delta_free
+function.
+.Pp
+Memory can be
+.Dq diffed
+to produce a patch using the
+.Fn delta_diff_mem
+function,
+and the resulting diff can be re-applied to the original file
+to produce the
+.Dq new
+file using the
+.Fn delta_patch_mem
+function.
+.Pp
+There is a similar set of operations at a file level, using the
+.Fn delta_diff_file
+and 
+.Fn delta_patch_file
+functions.
+.Pp
+The two functions
+.Fn delta_read_patch_file
+and
+.Fn delta_write_patch_file
+can be used to read and write patch files from memory operations
+which have completed successfully.
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Nx 8.0 .
+.Sh AUTHORS
+.An Alistair Crooks Aq Mt a...@netbsd.org
+based on some original code from
+.An Colin Percival
Index: othersrc/external/bsd/delta/dist/libdelta.c
diff -u /dev/null othersrc/external/bsd/delta/dist/libdelta.c:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/libdelta.c	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,749 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * 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 <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "delta.h"
+
+/* an output buffer structure */
+typedef struct obuf_t {
+	uint64_t	 c;	/* # of characters used */
+	uint64_t	 size;	/* output buffer size */
+	uint8_t		*v;	/* the array of chars */
+} obuf_t;
+
+/* the binary diff structure */
+typedef struct delta_t {
+	obuf_t		 control;	/* output buffer for control info */
+	uint8_t		*diff;		/* diff text */
+	size_t		 difflen;	/* diff text length */
+	uint8_t		*extra;		/* extra text */
+	size_t		 extralen;	/* extra text length */
+	off_t		 newsize;	/* size of output */
+	uint8_t		 allocctl;	/* ctl was allocated */
+	uint8_t		 allocdiff;	/* diff was allocated */
+	uint8_t		 allocextra;	/* extra was allocated */
+} delta_t;
+
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
+#ifndef ABS
+#define ABS(x)	(((x) < 0) ? -(x) : (x))
+#endif
+
+#ifndef howmany
+#define	howmany(x, y)	(((x)+((y)-1))/(y))
+#endif
+
+/* add the info to the obuf buffer */
+static int
+owrite(obuf_t *obuf, const void *p, size_t size)
+{
+	uint8_t	*newv;
+	size_t	 newsize;
+
+	if (obuf->c + size >= obuf->size) {
+		newsize = howmany(obuf->c + size, 4096) * 4096;
+		newv = realloc(obuf->v, newsize);
+		if (newv == NULL) {
+			return 0;
+		}
+		obuf->size = newsize;
+		obuf->v = newv;
+	}
+	memcpy(&obuf->v[obuf->c], p, size);
+	obuf->c += size;
+	return 1;
+}
+
+static void 
+split(off_t *I, off_t *V, off_t start, off_t len, off_t h)
+{
+	off_t 		i, j, k, x, tmp, jj, kk;
+
+	if (len < 16) {
+		for (k = start; k < start + len; k += j) {
+			j = 1;
+			x = V[I[k] + h];
+			for (i = 1; k + i < start + len; i++) {
+				if (V[I[k + i] + h] < x) {
+					x = V[I[k + i] + h];
+					j = 0;
+				}
+				if (V[I[k + i] + h] == x) {
+					tmp = I[k + j];
+					I[k + j] = I[k + i];
+					I[k + i] = tmp;
+					j++;
+				}
+			}
+			for (i = 0; i < j; i++)
+				V[I[k + i]] = k + j - 1;
+			if (j == 1)
+				I[k] = -1;
+		}
+		return;
+	}
+
+	x = V[I[start + len / 2] + h];
+	jj = 0;
+	kk = 0;
+	for (i = start; i < start + len; i++) {
+		if (V[I[i] + h] < x)
+			jj++;
+		if (V[I[i] + h] == x)
+			kk++;
+	}
+	jj += start;
+	kk += jj;
+
+	j = k = 0;
+	for (i = start; i < jj ; ) {
+		if (V[I[i] + h] < x) {
+			i++;
+		} else if (V[I[i] + h] == x) {
+			tmp = I[i];
+			I[i] = I[jj + j];
+			I[jj + j] = tmp;
+			j++;
+		} else {
+			tmp = I[i];
+			I[i] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+	while (jj + j < kk) {
+		if (V[I[jj + j] + h] == x) {
+			j++;
+		} else {
+			tmp = I[jj + j];
+			I[jj + j] = I[kk + k];
+			I[kk + k] = tmp;
+			k++;
+		}
+	}
+
+	if (jj > start) {
+		split(I, V, start, jj - start, h);
+	}
+	for (i = 0; i < kk - jj; i++) {
+		V[I[jj + i]] = kk - 1;
+	}
+	if (jj == kk - 1) {
+		I[jj] = -1;
+	}
+	if (start + len > kk) {
+		split(I, V, kk, start + len - kk, h);
+	}
+}
+
+static void 
+qsufsort(off_t *I, off_t *V, const uint8_t *old, off_t oldsize)
+{
+	off_t 		buckets[256];
+	off_t 		i, h, len;
+
+	memset(buckets, 0x0, sizeof(buckets));
+	for (i = 0; i < oldsize; i++) {
+		buckets[old[i]]++;
+	}
+	for (i = 1; i < 256; i++) {
+		buckets[i] += buckets[i - 1];
+	}
+	for (i = 255; i > 0; i--) {
+		buckets[i] = buckets[i - 1];
+	}
+	buckets[0] = 0;
+
+	for (i = 0; i < oldsize; i++) {
+		I[++buckets[old[i]]] = i;
+	}
+	I[0] = oldsize;
+	for (i = 0; i < oldsize; i++) {
+		V[i] = buckets[old[i]];
+	}
+	V[oldsize] = 0;
+	for (i = 1; i < 256; i++) {
+		if (buckets[i] == buckets[i - 1] + 1) {
+			I[buckets[i]] = -1;
+		}
+	}
+	I[0] = -1;
+
+	for (h = 1; I[0] != -(oldsize + 1); h += h) {
+		for (len = 0, i = 0; i < oldsize + 1;) {
+			if (I[i] < 0) {
+				len -= I[i];
+				i -= I[i];
+			} else {
+				if (len) {
+					I[i - len] = -len;
+				}
+				len = V[I[i]] + 1 - i;
+				split(I, V, i, len, h);
+				i += len;
+				len = 0;
+			}
+		}
+		if (len) {
+			I[i - len] = -len;
+		}
+	}
+
+	for (i = 0; i < oldsize + 1; i++) {
+		I[V[i]] = i;
+	}
+}
+
+static off_t 
+matchlen(const uint8_t *old, off_t oldsize, const uint8_t *newv, off_t newsize)
+{
+	off_t 		i;
+
+	for (i = 0; i < oldsize && i < newsize && old[i] == newv[i] ; i++) {
+	}
+	return i;
+}
+
+static off_t 
+search(off_t *I, const uint8_t *old, off_t oldsize,
+       const uint8_t *newv, 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], newv, newsize);
+		y = matchlen(old + I[en], oldsize - I[en], newv, 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], newv, MIN(oldsize - I[x], newsize)) < 0) {
+		return search(I, old, oldsize, newv, newsize, x, en, pos);
+	} else {
+		return search(I, old, oldsize, newv, newsize, st, x, pos);
+	}
+}
+
+/* encode in zigzag encoding */
+static int
+put64(off_t x, uint8_t *buf)
+{
+	uint64_t	n;
+	uint8_t		*b;
+	int		 len;
+	int		 i;
+
+	n = (x << 1) ^ (x >> 63);
+	for (len = 0, b = buf, i = 0 ; i < 9 ; i++, b += len) {
+		*b = ((n >> ((9 - i) * 7)) & 0x7f) | 0x80;
+		if (len == 0 && *b != 0x80) {
+			len = 1;
+		}
+	}
+	*b++ = (n & 0x7f);
+	return (int)(b - buf);
+}
+
+/* decode from zigzag encoding */
+static int64_t
+get64(uint8_t *buf, size_t *len)
+{
+	uint64_t	n;
+
+	for (n = 0, *len = 0 ; *len < 10 ; *len += 1) {
+		n = (n << 7) + (buf[*len] & 0x7f);
+                if ((buf[*len] & 0x80) == 0) {
+			*len += 1;
+                        break;
+                }
+	}
+	return (n >> 1) ^ (-(n & 1));
+}
+
+/* read the file into the array */
+static int
+readfile(const char *f, uint8_t **v, off_t *size)
+{
+	ssize_t	cc;
+	ssize_t	rc;
+	int	fd;
+
+	if (((fd = open(f, O_RDONLY, 0)) < 0) ||
+	    ((*size = lseek(fd, 0, SEEK_END)) == -1) ||
+	    ((*v = malloc(*size + 1)) == NULL) ||
+	    (lseek(fd, 0, SEEK_SET) != 0)) {
+		warn("can't read file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < *size ; cc += rc) {
+		if ((rc = read(fd, &(*v)[cc], *size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == *size;
+}
+
+/* write the array to the file */
+static int
+writefile(const char *f, uint8_t *v, off_t size)
+{
+	ssize_t	cc;
+	ssize_t	wc;
+	int	fd;
+
+	/* Write the new file */
+	if ((fd = open(f, O_CREAT | O_TRUNC | O_WRONLY, 0666)) < 0) {
+		warn("can't write file '%s'", f);
+		return 0;
+	}
+	for (cc = 0 ; cc < size ; cc += wc) {
+		if ((wc = write(fd, &v[cc], size - cc)) < 0) {
+			break;
+		}
+	}
+	close(fd);
+	return cc == size;
+}
+
+/***********************************************************************/
+
+#define HEADER		"/_\\1"	/* delta v1 */
+#define HEADERLEN	4
+
+/* write the patch file from info held in delta struct */
+int
+delta_write_patch_file(delta_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	uint8_t		 buf[10];
+	size_t		 cc;
+	size_t		 wc;
+	size_t		 n;
+	obuf_t		 o;
+	FILE		*fp;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&o, 0x0, sizeof(o));
+	owrite(&o, HEADER, HEADERLEN);
+	n = put64(delta->control.c, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->difflen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->extralen, buf);
+	owrite(&o, buf, n);
+	n = put64(delta->newsize, buf);
+	owrite(&o, buf, n);
+	if ((fp = fopen(patchfile, "w")) == NULL) {
+		warn("can't open '%s' for writing", patchfile);
+		return 0;
+	}
+	for (cc = 0 ; cc < o.c ; cc += wc) {
+		if ((wc = fwrite(&o.v[cc], 1, o.c - cc, fp)) == 0) {
+			break;
+		}
+	}
+	o.c = 0;
+	/* control info */
+	owrite(&o, delta->control.v, delta->control.c);
+	/* diff info */
+	owrite(&o, delta->diff, delta->difflen);
+	/* extra info */
+	owrite(&o, delta->extra, delta->extralen);
+	n = delta->control.c + delta->difflen + delta->extralen;
+	zsize = ((n + 128) * 101) / 100;
+	z = calloc(1, zsize);
+	BZ2_bzBuffToBuffCompress(z, &zsize, (char *)o.v, o.c, 9, 0, 0);
+	for (cc = 0 ; cc < zsize ; cc += wc) {
+		if ((wc = fwrite(&z[cc], 1, zsize - cc, fp)) == 0) {
+			break;
+		}
+	}
+	free(z);
+	free(o.v);
+	fclose(fp);
+	return cc == zsize;
+}
+
+/* read the patch file into the delta struct */
+int
+delta_read_patch_file(delta_t *delta, const char *patchfile)
+{
+	unsigned	 zsize;
+	size_t		 len;
+	size_t		 cc;
+	obuf_t		 o;
+	off_t	 	 size;
+	char		*z;
+
+	if (delta == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	memset(&o, 0x0, sizeof(o));
+	if (!readfile(patchfile, &o.v, &size)) {
+		return 0;
+	}
+	o.c = o.size = size;
+	if (memcmp(o.v, HEADER, HEADERLEN) != 0) {
+		warnx("not a patch at offset 0");
+		return 0;
+	}
+	cc = HEADERLEN;
+	delta->control.c = get64(&o.v[cc], &len);
+	cc += len;
+	delta->difflen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->extralen = get64(&o.v[cc], &len);
+	cc += len;
+	delta->newsize = get64(&o.v[cc], &len);
+	cc += len;
+	zsize = delta->control.c + delta->difflen + delta->extralen;
+	if ((z = calloc(1, zsize)) == NULL) {
+		warn("resource allocation reading patch file");
+		return 0;
+	}
+	if (BZ2_bzBuffToBuffDecompress(z, &zsize, (char *)&o.v[cc], size - cc, 0, 0) != BZ_OK) {
+		warn("resource allocation reading patch file");
+		return 0;
+	}
+	delta->allocctl = 1;
+	delta->control.v = (uint8_t *)z;
+	delta->diff = (uint8_t *)&z[delta->control.c];
+	delta->extra = (uint8_t *)&z[delta->control.c + delta->difflen];
+	free(o.v);
+	return 1;
+}
+
+/* diff 2 areas of memory */
+int
+delta_diff_mem(delta_t *delta, const void *aold, size_t oldc, const void *anewv, size_t newc)
+{
+	const uint8_t	*old = (const uint8_t *)aold;
+	const uint8_t	*newv = (const uint8_t *)anewv;
+	uint8_t		 buf[10];
+	off_t		 oldsize = (off_t)oldc;
+	off_t		 newsize = (off_t)newc;
+	off_t		 *I, *V;
+	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;
+	int		 buflen;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	memset(delta, 0x0, sizeof(*delta));
+	if (((I = malloc((oldsize + 1) * sizeof(*I))) == NULL) ||
+	    ((V = malloc((oldsize + 1) * sizeof(*V))) == NULL)) {
+		warn("allocation failure in bsd_diff_mem");
+		return 0;
+	}
+	qsufsort(I, V, old, oldsize);
+	free(V);
+	/*
+	 * Allocate newsize+1 bytes instead of newsize bytes to ensure that
+	 * we never try to malloc(0) and get a NULL pointer
+	 */
+	delta->newsize = newsize;
+	if (((delta->diff = malloc(newsize + 1)) == NULL) ||
+	    ((delta->extra = malloc(newsize + 1)) == NULL)) {
+		warn("allocation failure 2 in bsd_diff_mem");
+		return 0;
+	}
+	delta->allocdiff = delta->allocextra = 1;
+	scan = 0;
+	len = 0;
+	lastscan = 0;
+	lastpos = 0;
+	lastoffset = 0;
+	while (scan < newsize) {
+		oldscore = 0;
+		for (scsc = scan += len; scan < newsize; scan++) {
+			len = search(I, old, oldsize, newv + scan, newsize - scan,
+				     0, oldsize, &pos);
+
+			for (; scsc < scan + len; scsc++)
+				if ((scsc + lastoffset < oldsize) &&
+				    (old[scsc + lastoffset] == newv[scsc])) {
+					oldscore++;
+			}
+			if (((len == oldscore) && (len != 0)) ||
+			    (len > oldscore + 8)) {
+				break;
+			}
+			if ((scan + lastoffset < oldsize) &&
+			    (old[scan + lastoffset] == newv[scan])) {
+				oldscore--;
+			}
+		}
+		if ((len != oldscore) || (scan == newsize)) {
+			s = 0;
+			Sf = 0;
+			lenf = 0;
+			for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize);) {
+				if (old[lastpos + i] == newv[lastscan + i])
+					s++;
+				i++;
+				if (s * 2 - i > Sf * 2 - lenf) {
+					Sf = s;
+					lenf = i;
+				}
+			}
+			lenb = 0;
+			if (scan < newsize) {
+				s = 0;
+				Sb = 0;
+				for (i = 1; (scan >= lastscan + i) && (pos >= i); i++) {
+					if (old[pos - i] == newv[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; i < overlap; i++) {
+					if (newv[lastscan + lenf - overlap + i] ==
+					  old[lastpos + lenf - overlap + i]) {
+						s++;
+					}
+					if (newv[scan - lenb + i] ==
+					    old[pos - lenb + i]) {
+						s--;
+					}
+					if (s > Ss) {
+						Ss = s;
+						lens = i + 1;
+					}
+				}
+				lenf += lens - overlap;
+				lenb -= lens;
+			}
+			for (i = 0; i < lenf; i++) {
+				delta->diff[delta->difflen + i] = newv[lastscan + i] - old[lastpos + i];
+			}
+			for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++) {
+				delta->extra[delta->extralen + i] = newv[lastscan + lenf + i];
+			}
+			delta->difflen += lenf;
+			delta->extralen += (scan - lenb) - (lastscan + lenf);
+
+			buflen = put64(lenf, buf);
+			owrite(&delta->control, buf, buflen);
+
+			buflen = put64((scan - lenb) - (lastscan + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			buflen = put64((pos - lenb) - (lastpos + lenf), buf);
+			owrite(&delta->control, buf, buflen);
+			lastscan = scan - lenb;
+			lastpos = pos - lenb;
+			lastoffset = pos - scan;
+		}
+	}
+	free(I);
+	return 1;
+}
+
+/* diff two files, putting results in patch file */
+int
+delta_diff_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	delta_t	 delta;
+	uint8_t         *oldv;
+	uint8_t         *newv;
+	off_t 		 oldsize;
+	off_t 		 newsize;
+	int		 ok;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!readfile(oldfile, &oldv, &oldsize) ||
+	    !readfile(newfile, &newv, &newsize)) {
+		return 0;
+	}
+	if (!delta_diff_mem(&delta, oldv, oldsize, newv, newsize)) {
+		return 0;
+	}
+	ok = delta_write_patch_file(&delta, patchfile);
+	if (!ok) {
+		return 0;
+	}
+	/* Free the memory we used */
+	delta_free(&delta);
+	free(oldv);
+	free(newv);
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+delta_patch_mem(delta_t *delta, const void *aold, size_t oldsize, void *anewv, size_t *newsize)
+{
+	const uint8_t	 *old = (const uint8_t *)aold;
+	uint8_t		**newv = (uint8_t **)anewv;
+	size_t		  extrac;
+	size_t		  diffc;
+	size_t		  ctlc;
+	size_t		  len;
+	off_t 		  ctrl[3];
+	off_t 		  oldpos;
+	off_t 		  newpos;
+	off_t		  i;
+
+	if (delta == NULL || old == NULL || newv == NULL) {
+		return 0;
+	}
+	if ((*newv = malloc(delta->newsize + 1)) == NULL) {
+		warn("allocation failure %zu bytes", delta->newsize + 1);
+		return 0;
+	}
+	for (oldpos = newpos = 0, ctlc = diffc = extrac = 0; newpos < delta->newsize ; ) {
+		/* Read control data */
+		for (i = 0; i < 3; i++) {
+			ctrl[i] = get64(&delta->control.v[ctlc], &len);
+			ctlc += len;
+		}
+		/* Sanity-check */
+		if (newpos + ctrl[0] > delta->newsize) {
+			warnx("Corrupt patch 1\n");
+			return 0;
+		}
+		/* Read diff string */
+		memcpy(&(*newv)[newpos], &delta->diff[diffc], ctrl[0]);
+		diffc += ctrl[0];
+		/* Add old data to diff string */
+		for (i = 0; i < ctrl[0]; i++) {
+			if ((oldpos + i >= 0) && (oldpos + i < (off_t)oldsize)) {
+				(*newv)[newpos + i] += old[oldpos + i];
+			}
+		}
+		/* Adjust pointers */
+		newpos += ctrl[0];
+		oldpos += ctrl[0];
+		/* Sanity-check */
+		if (newpos + ctrl[1] > delta->newsize) {
+			warnx("Corrupt patch 2\n");
+			return 0;
+		}
+		/* Read extra string */
+		memcpy(*newv + newpos, &delta->extra[extrac], ctrl[1]);
+		extrac += ctrl[1];
+		/* Adjust pointers */
+		newpos += ctrl[1];
+		oldpos += ctrl[2];
+	}
+	*newsize = delta->newsize;
+	return 1;
+}
+
+/* patch using a binary patch */
+int
+delta_patch_file(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	delta_t	 delta;
+	ssize_t 	 oldsize;
+	uint8_t         *newv;
+	uint8_t         *old;
+	size_t 	 	 newsize;
+
+	if (oldfile == NULL || newfile == NULL || patchfile == NULL) {
+		return 0;
+	}
+	memset(&delta, 0x0, sizeof(delta));
+	if (!delta_read_patch_file(&delta, patchfile)) {
+		return 0;
+	}
+	if (!readfile(oldfile, &old, &oldsize)) {
+		warn("%s", oldfile);
+		return 0;
+	}
+	if (!delta_patch_mem(&delta, old, oldsize, &newv, &newsize)) {
+		return 0;
+	}
+	if (!writefile(newfile, newv, delta.newsize)) {
+		warn("%s", newfile);
+		return 0;
+	}
+	delta_free(&delta);
+	return 1;
+}
+
+/* free resources associated with delta struct */
+void
+delta_free(delta_t *delta)
+{
+	if (delta) {
+		if (delta->allocctl) {
+			free(delta->control.v);
+		}
+		if (delta->allocdiff) {
+			free(delta->diff);
+		}
+		if (delta->allocextra) {
+			free(delta->extra);
+		}
+	}
+}
+
+/* make a new struct */
+delta_t *
+delta_new(void)
+{
+	return calloc(1, sizeof(delta_t));
+}
Index: othersrc/external/bsd/delta/dist/main.c
diff -u /dev/null othersrc/external/bsd/delta/dist/main.c:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/dist/main.c	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2016 Alistair Crooks <a...@netbsd.org>
+ * 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 <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "delta.h"
+
+int
+main(int argc, char **argv)
+{
+	int	dodiff;
+	int	ok;
+	int	i;
+
+	dodiff = 0;
+	while ((i = getopt(argc, argv, "dp")) != -1) {
+		switch(i) {
+		case 'd':
+			dodiff = 1;
+			break;
+		case 'p':
+			dodiff = 0;
+			break;
+		}
+	}
+	if (argc - optind != 3) {
+		fprintf(stderr, "Usage: %s oldfile newfile patchfile\n", *argv);
+		exit(EXIT_FAILURE);
+	}
+	ok = (dodiff) ?
+		delta_diff_file(argv[optind], argv[optind + 1], argv[optind + 2]) :
+		delta_patch_file(argv[optind], argv[optind + 1], argv[optind + 2]);
+	exit((ok) ? EXIT_SUCCESS : EXIT_FAILURE);
+}

Index: othersrc/external/bsd/delta/lib/Makefile
diff -u /dev/null othersrc/external/bsd/delta/lib/Makefile:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/lib/Makefile	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,25 @@
+#	$NetBSD: Makefile,v 1.1 2016/04/28 05:21:31 agc Exp $
+
+.include <bsd.own.mk>
+
+DIST=	${.CURDIR}/../dist
+.PATH:	${DIST}
+
+LIB=	delta
+SRCS+=	libdelta.c
+CPPFLAGS+=	-I. -I${DIST}
+MAN=	libdelta.3
+
+LIBDPLIBS+=	bz2	${NETBSDSRCDIR}/lib/libbz2
+
+.ifndef PRODUCTION
+CPPFLAGS+=-g -O0
+LDFLAGS+=-g -O0
+.endif
+
+WARNS=5
+
+INCS=		delta.h
+INCSDIR=	/usr/include
+
+.include <bsd.lib.mk>
Index: othersrc/external/bsd/delta/lib/shlib_version
diff -u /dev/null othersrc/external/bsd/delta/lib/shlib_version:1.1
--- /dev/null	Thu Apr 28 05:21:31 2016
+++ othersrc/external/bsd/delta/lib/shlib_version	Thu Apr 28 05:21:31 2016
@@ -0,0 +1,2 @@
+major=0
+minor=0

Reply via email to