Refactor bsdiff patch writing code to another file.

bsdiff.cc had code to handle both the sub-streams compression and the
patch format. This CL moves the patch file format logic to a new class
in a separated file, and the bzip2 compression to another class. This
allows to replace the core bsdiff logic separatedly from the patch
format.

There are no changes to the functionality of bsdiff and the generated
patches. The code does a bit more of memcpy() since it doesn't write
the control stream to disk as it goes.

Bug: 34220646
Test: Ran bsdiff and compared results with previous version.

Change-Id: Ibdc1482e98cbd370cbed677c326008e19a217ef8
diff --git a/bsdiff.cc b/bsdiff.cc
index 854c882..0fbbe5b 100644
--- a/bsdiff.cc
+++ b/bsdiff.cc
@@ -32,7 +32,6 @@
 
 #include <sys/types.h>
 
-#include <bzlib.h>
 #include <err.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -42,6 +41,8 @@
 
 #include <algorithm>
 
+#include "patch_writer.h"
+
 namespace bsdiff {
 
 static off_t matchlen(const u_char* old, off_t oldsize, const u_char* new_buf,
@@ -85,24 +86,6 @@
 	};
 }
 
-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 bsdiff(const char* old_filename, const char* new_filename,
            const char* patch_filename) {
 	int fd;
@@ -148,13 +131,7 @@
 	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;
+	BsdiffPatchWriter patch(old_buf, oldsize, new_buf, newsize);
 
 	if (I_cache && *I_cache) {
 		I = *I_cache;
@@ -167,35 +144,11 @@
 			*I_cache = I;
 	}
 
-	if(((db=static_cast<u_char*>(malloc(newsize+1)))==NULL) ||
-		((eb=static_cast<u_char*>(malloc(newsize+1)))==NULL)) err(1,NULL);
-	dblen=0;
-	eblen=0;
-
 	/* Create the patch file */
-	if ((pf = fopen(patch_filename, "w")) == NULL)
-		err(1, "%s", patch_filename);
-
-	/* Header is
-		0	8	 "BSDIFF40"
-		8	8	length of bzip2ed ctrl block
-		16	8	length of bzip2ed diff block
-		24	8	length of new file */
-	/* File is
-		0	32	Header
-		32	??	Bzip2ed ctrl block
-		??	??	Bzip2ed diff block
-		??	??	Bzip2ed extra block */
-	memcpy(header,"BSDIFF40",8);
-	offtout(0, header + 8);
-	offtout(0, header + 16);
-	offtout(newsize, header + 24);
-	if (fwrite(header, 32, 1, pf) != 1)
-		err(1, "fwrite(%s)", patch_filename);
+	if (!patch.Open(patch_filename))
+		return 1;
 
 	/* 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) {
@@ -271,79 +224,19 @@
 				lenb-=lens;
 			};
 
-			for(i=0;i<lenf;i++)
-				db[dblen+i]=new_buf[lastscan+i]-old_buf[lastpos+i];
-			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
-				eb[eblen+i]=new_buf[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);
+			if (!patch.AddControlEntry(ControlEntry(lenf,
+			                                        (scan - lenb) - (lastscan + lenf),
+			                                        (pos - lenb) - (lastpos + lenf))))
+				errx(1, "Writing a control entry");
 
 			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);
+	if (!patch.Close())
+		errx(1, "Closing the patch file");
 
-	/* 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)", patch_filename);
-	if (fclose(pf))
-		err(1, "fclose");
-
-	/* Free the memory we used */
-	free(db);
-	free(eb);
 	if (I_cache == nullptr)
 		free(I);