static bool bsdiffmain(MCBsDiffInputStream *p_old_file, MCBsDiffInputStream *p_new_file, MCBsDiffOutputStream *p_patch_file) { u_char *old,*newp; 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; // if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); bool t_success; t_success = true; V = NULL; /* 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 (t_success) { uint32_t t_size; t_success = p_old_file -> Measure(t_size); oldsize = (signed)t_size; } if (t_success) t_success = MCMemoryNewArray(oldsize + 1, old); if (t_success) t_success = p_old_file -> ReadBytes(old, oldsize); /*if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL);*/ if (t_success) t_success = MCMemoryNewArray(oldsize + 1, I); if (t_success) t_success = MCMemoryNewArray(oldsize + 1, V); if (t_success) qsufsort(I,V,old,oldsize); /*free(V);*/ MCMemoryDeleteArray(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) || ((newp=malloc(newsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || (read(fd,newp,newsize)!=newsize) || (close(fd)==-1)) err(1,"%s",argv[2]);*/ if (t_success) { uint32_t t_size; t_success = p_new_file -> Measure(t_size); newsize = (signed)t_size; } if (t_success) t_success = MCMemoryNewArray(newsize + 1, newp); if (t_success) t_success = p_new_file -> ReadBytes(newp, newsize); /*if(((db=malloc(newsize+1))==NULL) || ((eb=malloc(newsize+1))==NULL)) err(1,NULL);*/ if (t_success) t_success = MCMemoryNewArray(newsize + 1, db); if (t_success) t_success = MCMemoryNewArray(newsize + 1, eb); 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]);*/ uint32_t t_control_size, t_diff_size, t_extra_size; t_control_size = 0; t_diff_size = 0; t_extra_size = 0; if (t_success) t_success = p_patch_file -> WriteInt32(t_control_size) && p_patch_file -> WriteInt32(t_diff_size) && p_patch_file -> WriteInt32(t_extra_size) && p_patch_file -> WriteInt32(newsize); /* 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(t_success && scan<newsize) { oldscore=0; for(scsc=scan+=len;scan<newsize;scan++) { len=search(I,old,oldsize,newp+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == newp[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == newp[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]==newp[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]==newp[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(newp[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(newp[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]=newp[lastscan+i]-old[lastpos+i]; for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) eb[eblen+i]=newp[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 (t_success) t_success = p_patch_file -> WriteInt32(lenf) && p_patch_file -> WriteInt32((scan-lenb)-(lastscan+lenf)) && p_patch_file -> WriteInt32((pos-lenb)-(lastpos+lenf)); if (t_success) t_control_size += 12; 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);*/ if (t_success) t_success = p_patch_file -> WriteBytes(db, dblen); if (t_success) t_diff_size = dblen; /* 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);*/ if (t_success) t_success = p_patch_file -> WriteBytes(eb, eblen); if (t_success) t_extra_size = eblen; /* 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");*/ if (t_success) t_success = p_patch_file -> Rewind() && p_patch_file -> WriteInt32(t_control_size) && p_patch_file -> WriteInt32(t_diff_size) && p_patch_file -> WriteInt32(t_extra_size) && p_patch_file -> Rewind(); /* Free the memory we used */ /*free(db); free(eb); free(I); free(old); free(new);*/ MCMemoryDeleteArray(db); MCMemoryDeleteArray(eb); MCMemoryDeleteArray(I); MCMemoryDeleteArray(old); MCMemoryDeleteArray(newp); return t_success; }
int CreateBinaryPatch(const char *oldFile, const char *newFile, const char *patchFile) { if (NULL == oldFile || NULL == newFile || NULL == patchFile) return -1; int fd; unsigned char *old,*newbuf; PROffset32 oldsize,newsize; PROffset32 *I,*V; PROffset32 scan,pos,len; PROffset32 lastscan,lastpos,lastoffset; PROffset32 oldscore,scsc; PROffset32 s,Sf,lenf,Sb,lenb; PROffset32 overlap,Ss,lens; PROffset32 i; PROffset32 dblen,eblen; unsigned char *db,*eb; unsigned int scrc; // 校验码 PRUint32 numtriples; // 节点个数 MBSPatchHeader header = { {'M','B','D','I','F','F','1','0'}, 0, 0, 0, 0, 0, 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(oldFile,O_RDONLY|_O_BINARY,0))<0) || ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=(unsigned char*) malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || (read(fd,old,oldsize)!=oldsize) || (close(fd)==-1)) reporterr(1,"%s\n",oldFile); scrc = crc32(old, oldsize); if(((I=(PROffset32*) malloc((oldsize+1)*sizeof(PROffset32)))==NULL) || ((V=(PROffset32*) malloc((oldsize+1)*sizeof(PROffset32)))==NULL)) reporterr(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(newFile,O_RDONLY|_O_BINARY,0))<0) || ((newsize=lseek(fd,0,SEEK_END))==-1) || ((newbuf=(unsigned char*) malloc(newsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || (read(fd,newbuf,newsize)!=newsize) || (close(fd)==-1)) reporterr(1,"%s\n",newFile); if(((db=(unsigned char*) malloc(newsize+1))==NULL) || ((eb=(unsigned char*) malloc(newsize+1))==NULL)) reporterr(1,NULL); dblen=0; eblen=0; if((fd=open(patchFile,O_CREAT|O_TRUNC|O_WRONLY|_O_BINARY,0666))<0) reporterr(1,"%s\n",patchFile); /* start writing here */ /* We don't know the lengths yet, so we will write the header again at the end */ if(write(fd,&header,sizeof(MBSPatchHeader))!=sizeof(MBSPatchHeader)) reporterr(1,"%s\n",patchFile); scan=0;len=0; lastscan=0;lastpos=0;lastoffset=0; numtriples = 0; while(scan<newsize) { oldscore=0; for(scsc=scan+=len;scan<newsize;scan++) { len=search(I,old,oldsize,newbuf+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == newbuf[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == newbuf[scan])) oldscore--; }; if((len!=oldscore) || (scan==newsize)) { MBSPatchTriple triple; s=0;Sf=0;lenf=0; for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) { if(old[lastpos+i]==newbuf[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]==newbuf[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(newbuf[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(newbuf[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]=newbuf[lastscan+i]-old[lastpos+i]; for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) eb[eblen+i]=newbuf[lastscan+lenf+i]; dblen+=lenf; eblen+=(scan-lenb)-(lastscan+lenf); triple.x = htonl(lenf); triple.y = htonl((scan-lenb)-(lastscan+lenf)); triple.z = htonl((pos-lenb)-(lastpos+lenf)); if (write(fd,&triple,sizeof(triple)) != sizeof(triple)) reporterr(1,NULL); #ifdef _DEBUG TRACE("Writing a block: X=%u,Y=%u,Z=%i\n", (PRUint32) lenf, (PRUint32) ((scan-lenb)-(lastscan+lenf)), (PRUint32) ((pos-lenb)-(lastpos+lenf))); #endif ++numtriples; lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan; }; }; if(write(fd,db,dblen)!=dblen) reporterr(1,NULL); if(write(fd,eb,eblen)!=eblen) reporterr(1,NULL); header.slen = htonl(oldsize); header.scrc32 = htonl(scrc); header.dlen = htonl(newsize); header.cblen = htonl(numtriples * sizeof(MBSPatchTriple)); header.difflen = htonl(dblen); header.extralen = htonl(eblen); if (lseek(fd,0,SEEK_SET) == -1 || write(fd,&header,sizeof(header)) != sizeof(header) || close(fd) == -1) reporterr(1,NULL); free(db); free(eb); free(I); free(old); free(newbuf); return 0; }
/** * I have rewritten this function so it can be called from other places; * I have also rewritten it to not use a patch file but instead a passed * buffer; the bsdiff patch is already in memory. * * ryan, 7.2.09 */ int bsdiff_create_patch(char *patchFile, char *oldFile, char *newFile) { FILE* fd = NULL; BZFILE * bz = NULL; u_char *old,*pnew; 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]; int bzerror; /*if(argc!=4) err(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 = fopen(oldFile, "rb")) <= 0) || (fseek(fd, 0, SEEK_END) != 0) || ((oldsize = ftell(fd)) == 0) || ((old = (u_char *) malloc(oldsize + 1)) == NULL) || (fseek(fd, 0, SEEK_SET) != 0) || (fread(old,1, oldsize, fd) != oldsize) || (fclose(fd) == -1)) err(1, "%s", oldFile); if(((I = (off_t*) malloc((oldsize + 1) * sizeof(off_t))) == NULL) || ((V = (off_t*) 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 = fopen(newFile, "rb")) < 0) || (fseek(fd, 0, SEEK_END) != 0) || ((newsize = ftell(fd)) == 0) || ((pnew = (u_char *) malloc(newsize + 1)) == NULL) || (fseek(fd, 0, SEEK_SET) != 0) || (fread(pnew, 1, newsize, fd) != newsize) || (fclose(fd) == -1)) err(1, "%s", newFile); if(((db=(u_char*)malloc(newsize+1))==NULL) || ((eb=(u_char*)malloc(newsize+1))==NULL)) err(1,NULL); dblen=0; eblen=0; fd = fopen(patchFile, "wb"); if(fd == NULL) err(1,"%s",patchFile); /* 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); memset(header+8,0,24); if(fwrite(header,1,32,fd)!=32) err(1,"%s",patchFile); scan=0;len=0; lastscan=0;lastpos=0;lastoffset=0; bz = BZ2_bzWriteOpen ( &bzerror, fd, blockSize100k, 0, 30); if (bzerror != BZ_OK) err(1, "Problem bzWriteOpen"); while(scan<newsize) { oldscore=0; for(scsc=scan+=len;scan<newsize;scan++) { len=search(I,old,oldsize,pnew+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == pnew[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == pnew[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]==pnew[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]==pnew[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(pnew[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(pnew[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]=pnew[lastscan+i]-old[lastpos+i]; for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) eb[eblen+i]=pnew[lastscan+lenf+i]; dblen+=lenf; eblen+=(scan-lenb)-(lastscan+lenf); offtout(lenf,buf); if((8 != BZ2_bzwrite(bz,buf,8)) || (bzerror != BZ_OK)) err(1,"bzwrite"); offtout((scan-lenb)-(lastscan+lenf),buf); if((8 != BZ2_bzwrite(bz,buf,8)) || (bzerror != BZ_OK)) err(1,"bzwrite"); offtout((pos-lenb)-(lastpos+lenf),buf); if((8 != BZ2_bzwrite(bz,buf,8)) || (bzerror != BZ_OK)) err(1,"bzwrite"); lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan; }; }; BZ2_bzWriteClose ( &bzerror, bz, 0, NULL, NULL); if((fseek(fd,0,SEEK_END))!=0 || ((len=ftell(fd))==-1)) err(1,"problem 0: %s",patchFile); offtout(len-32,buf); if((fseek(fd,8,SEEK_SET)!=0) || (ftell(fd) != 8) || (fwrite(buf,1,8,fd)!=8)) err(1,"problem 1: %s",patchFile); offtout(newsize,buf); if((fseek(fd,24,SEEK_SET)!=0) || (ftell(fd) != 24)|| (fwrite(buf,1,8,fd)!=8)) err(1,"problem 2:%s",patchFile); if(fseek(fd,0,SEEK_END)!=0) err(1,"problem 3: %s",patchFile); bz = BZ2_bzWriteOpen ( &bzerror, fd, blockSize100k, 0, 30); if (bzerror != BZ_OK) err(1, "Problem bzWriteOpen"); if((dblen != BZ2_bzwrite(bz,db,dblen)) || (bzerror != BZ_OK)) { // printf("%s", BZ2_bzerror ( bz, &bzerror )); err(1,"bzwrite"); } BZ2_bzWriteClose ( &bzerror, bz, 0, NULL, NULL); if((fseek(fd,0,SEEK_END)!=0) || ((newsize=ftell(fd))==-1)) err(1,"problem 4: %s",patchFile); offtout(newsize-len,buf); if((fseek(fd,16,SEEK_SET)!=0) || (ftell(fd)!=16) || (fwrite(buf,1,8,fd)!=8)) err(1,"problem 5:%s",patchFile); if(fseek(fd,0,SEEK_END)!=0 || (ftell(fd) == -1)) err(1,"problem 6: %s",patchFile); bz = BZ2_bzWriteOpen ( &bzerror, fd, blockSize100k, 0, 30); if (bzerror != BZ_OK) err(1, "Problem bzWriteOpen"); if((eblen != BZ2_bzwrite(bz,eb,eblen)) || (bzerror != BZ_OK)) err(1,"bzwrite"); BZ2_bzWriteClose ( &bzerror, bz, 0, NULL, NULL); fclose(fd); free(db); free(eb); free(I); free(old); free(pnew); return 0; }
int DIFF_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; int bytesWritten=0; 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|O_BINARY,0))<0) || ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=(u_char*)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=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=(off_t*)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|O_BINARY,0))<0) || ((newsize=lseek(fd,0,SEEK_END))==-1) || ((_new=(u_char*)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=(u_char*)malloc(newsize+1))==NULL) || ((eb=(u_char*)malloc(newsize+1))==NULL)) err(1,NULL); dblen=0; eblen=0; /* Create the patch file */ if ((pf = fopen(argv[3], "wb")) == NULL) err(1, "%s", argv[3]); /* Header is 0 8 "BSDIFF40" 8 8 length of bzip2ed ctrl block 16 8 length of bzip2ed diff block 24 8 length of new file */ /* File is 0 32 Header 32 ?? Bzip2ed ctrl block ?? ?? Bzip2ed diff block ?? ?? Bzip2ed extra block */ memcpy(header,"BSDIFF40",8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); if (fwrite(header, 32, 1, pf) != 1) 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); bytesWritten+=8; // printf("bz2err 8 %i\n", bytesWritten); offtout((scan-lenb)-(lastscan+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); bytesWritten+=8; // printf("bz2err 8 %i\n", bytesWritten); offtout((pos-lenb)-(lastpos+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); bytesWritten+=8; // printf("bz2err 8 %i\n", bytesWritten); 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); bytesWritten+=dblen; // printf("bz2err dblen %i %i\n", dblen, bytesWritten); 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); bytesWritten+=eblen; //printf("bz2err eblen %i %i\n", eblen, bytesWritten); BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); if (bz2err != BZ_OK) errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); // REMOVEME // if ((newsize = ftello(pf)) == -1) // err(1, "ftello"); /* 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; }
// This function modifies the main() function included in bsdiff.c of bsdiff-4.3 found at http://www.daemonology.net/bsdiff/ // It is changed to be a standalone function, to work entirely in memory, and to use my class MemoryCompressor as an interface to BZip // Up to the caller to delete out bool CreatePatch(const char *old, unsigned oldsize, char *_new, unsigned int newsize, char **out, unsigned *outSize) { // 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]; MemoryCompressor patch; // unsigned outWriteOffset; // 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 | _O_BINARY ,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=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL)) // err(1,NULL); return false; qsufsort(I,V,(u_char*)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 | _O_BINARY ,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=(u_char*)malloc(newsize+1))==NULL) || ((eb=(u_char*)malloc(newsize+1))==NULL)) // err(1,NULL); { free(I); return false; } dblen=0; eblen=0; /* Create the patch file */ // if ((pf = fopen(argv[3], "wb")) == NULL) // err(1, "%s", argv[3]); /* Header is 0 8 "BSDIFF40" 8 8 length of bzip2ed ctrl block 16 8 length of bzip2ed diff block 24 8 length of new file */ /* File is 0 32 Header 32 ?? Bzip2ed ctrl block ?? ?? Bzip2ed diff block ?? ?? Bzip2ed extra block */ memcpy(header,"BSDIFF40",8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); // if (fwrite(header, 32, 1, pf) != 1) // err(1, "fwrite(%s)", argv[3]); // Allocate enough to hold any output // *out = (char*) malloc(oldsize+newsize); // Copy out the header // memcpy(*out, header, 32); //outWriteOffset=32; /* 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,(u_char*)old,oldsize,(u_char*)_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); if (patch.Compress((char*)buf, 8, false)==false) { free(db); free(eb); free(I); return false; } //BZ2_bzWrite(&bz2err, pfbz2, buf, 8); //if (bz2err != BZ_OK) // errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); offtout((scan-lenb)-(lastscan+lenf),buf); if (patch.Compress((char*)buf, 8, false)==false) { free(db); free(eb); free(I); return false; } //BZ2_bzWrite(&bz2err, pfbz2, buf, 8); //if (bz2err != BZ_OK) // errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); offtout((pos-lenb)-(lastpos+lenf),buf); if (patch.Compress((char*)buf, 8, false)==false) { free(db); free(eb); free(I); return false; } //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"); if (patch.Compress(0,0,true)==false) { free(db); free(eb); free(I); return false; } len=patch.GetTotalOutputSize()+32; // test: len should be 188 offtout(len-32, header + 8); //memcpy(*out+outWriteOffset, patch.GetOutput(), patch.GetTotalOutputSize()); //outWriteOffset+=patch.GetTotalOutputSize(); //patch.Clear(_FILE_AND_LINE_); /* 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 (patch.Compress((char*)db,dblen,true)==false) { free(db); free(eb); free(I); return false; } // memcpy(*out+outWriteOffset, patch.GetOutput(), patch.GetTotalOutputSize()); // outWriteOffset+=patch.GetTotalOutputSize(); // patch.Clear(_FILE_AND_LINE_); // 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"); newsize=32+patch.GetTotalOutputSize(); offtout(newsize - len, header + 16); // memcpy(*out+outWriteOffset, patch.GetOutput(), patch.GetTotalOutputSize()); // outWriteOffset+=patch.GetTotalOutputSize(); // patch.Clear(_FILE_AND_LINE_); /* 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 (patch.Compress((char*)eb,eblen,true)==false) { free(db); free(eb); free(I); return false; } // memcpy(*out+outWriteOffset, patch.GetOutput(), patch.GetTotalOutputSize()); // outWriteOffset+=patch.GetTotalOutputSize(); // patch.Clear(_FILE_AND_LINE_); // 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"); // memcpy(*out,header,32); // *out=(char*) realloc(*out, outWriteOffset); // *outSize=outWriteOffset; *outSize=patch.GetTotalOutputSize()+32; *out = new char [*outSize]; memcpy(*out, header, 32); memcpy(*out+32, patch.GetOutput(), patch.GetTotalOutputSize()); /* Free the memory we used */ free(db); free(eb); free(I); //free(old); //free(new); return true; }
// This is main() from bsdiff.c, with the following changes: // // - old, oldsize, newdata, newsize are arguments; we don't load this // data from files. old and newdata are owned by the caller; we // don't free them at the end. // // - the "I" block of memory is owned by the caller, who passes a // pointer to *I, which can be NULL. This way if we call // bsdiff() multiple times with the same 'old' data, we only do // the qsufsort() step the first time. // int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* newdata, off_t newsize, const char* patch_filename) { int fd; off_t *I; off_t scan,pos,len; off_t lastscan,lastpos,lastoffset; off_t oldscore,scsc; off_t s,Sf,lenf,Sb,lenb; off_t overlap,Ss,lens; off_t i; off_t dblen,eblen; u_char *db,*eb; u_char buf[8]; u_char header[32]; FILE * pf; BZFILE * pfbz2; int bz2err; if (*IP == NULL) { off_t* V; *IP = reinterpret_cast<off_t*>(malloc((oldsize+1) * sizeof(off_t))); V = reinterpret_cast<off_t*>(malloc((oldsize+1) * sizeof(off_t))); qsufsort(*IP, V, old, oldsize); free(V); } I = *IP; if(((db=reinterpret_cast<u_char*>(malloc(newsize+1)))==NULL) || ((eb=reinterpret_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); /* 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,newdata+scan,newsize-scan, 0,oldsize,&pos); for(; scsc<scan+len; scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == newdata[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == newdata[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]==newdata[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]==newdata[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(newdata[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(newdata[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]=newdata[lastscan+i]-old[lastpos+i]; for(i=0; i<(scan-lenb)-(lastscan+lenf); i++) eb[eblen+i]=newdata[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)", patch_filename); if (fclose(pf)) err(1, "fclose"); /* Free the memory we used */ free(db); free(eb); return 0; }
int bsdiff(u_char* old, off_t oldsize, u_char* newp, off_t newsize, FILE* pf) { size_t offset; off_t *I=NULL,*V=NULL; off_t scan,pos = 0,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=NULL,*eb=NULL; u_char buf[8]; u_char header[32]; BZFILE * pfbz2=NULL; int bz2err; unsigned int nbytes_in; unsigned int nbytes_out; if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) { goto error; } qsufsort(I,V,old,oldsize); free(V); V = NULL; if(((db=malloc(newsize+1))==NULL) || ((eb=malloc(newsize+1))==NULL)) { goto error; } dblen=0; eblen=0; offset = ftell(pf); /* Header is 0 8 length of newp file 8 8 length of bzip2ed ctrl block 16 8 length of bzip2ed diff block 24 8 length of bzip2ed extra block */ /* File is 0 32 Header 32 ?? Bzip2ed ctrl block ?? ?? Bzip2ed diff block ?? ?? Bzip2ed extra block */ memcpy(header, "BSDIFFXX", 8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); if (fwrite(header, 32, 1, pf) != 1) { printf("fwrite(%s)", "patch_file"); goto error; } /* Compute the differences, writing ctrl as we go */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) { printf("BZ2_bzWriteOpen, bz2err = %d", bz2err); goto error; } 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,newp+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == newp[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == newp[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]==newp[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]==newp[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(newp[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(newp[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]=newp[lastscan+i]-old[lastpos+i]; for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) eb[eblen+i]=newp[lastscan+lenf+i]; dblen+=lenf; eblen+=(scan-lenb)-(lastscan+lenf); offtout(lenf,buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) { printf("BZ2_bzWrite, bz2err = %d", bz2err); goto error; } offtout((scan-lenb)-(lastscan+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) { printf("BZ2_bzWrite, bz2err = %d", bz2err); goto error; } offtout((pos-lenb)-(lastpos+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) { printf("BZ2_bzWrite, bz2err = %d", bz2err); goto error; } lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan; }; }; BZ2_bzWriteClose(&bz2err, pfbz2, 0, &nbytes_in, &nbytes_out); pfbz2 = NULL; if (bz2err != BZ_OK) { printf("BZ2_bzWriteClose, bz2err = %d", bz2err); goto error; } /* Compute size of compressed ctrl data */ if ((len = ftell(pf)) == -1) { printf("ftello"); goto error; } offtout((off_t)(len-32-offset), header + 8); printf("--ctrl data %d %d %d\n", len-32-offset, nbytes_in, nbytes_out); /* Write compressed diff data */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) { printf("BZ2_bzWriteOpen, bz2err = %d", bz2err); goto error; } BZ2_bzWrite(&bz2err, pfbz2, db, dblen); if (bz2err != BZ_OK) { printf("BZ2_bzWrite, bz2err = %d", bz2err); goto error; } BZ2_bzWriteClose(&bz2err, pfbz2, 0, &nbytes_in, &nbytes_out); pfbz2 = NULL; if (bz2err != BZ_OK) { printf("BZ2_bzWriteClose, bz2err = %d", bz2err); goto error; } /* Compute size of compressed diff data */ if ((newsize = ftell(pf)) == -1) { printf("ftello"); goto error; } offtout(newsize - len, header + 16); printf("--diff data %d %d %d\n", newsize - len, nbytes_in, nbytes_out); /* Write compressed extra data */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) { printf("BZ2_bzWriteOpen, bz2err = %d", bz2err); goto error; } BZ2_bzWrite(&bz2err, pfbz2, eb, eblen); if (bz2err != BZ_OK) { printf("BZ2_bzWrite, bz2err = %d", bz2err); goto error; } BZ2_bzWriteClose(&bz2err, pfbz2, 0, &nbytes_in, &nbytes_out); pfbz2 = NULL; if (bz2err != BZ_OK) { printf("BZ2_bzWriteClose, bz2err = %d", bz2err); goto error; } if ((len = ftell(pf)) == -1) { printf("ftello"); goto error; } printf("--extra data %d %d %d\n", len - newsize, nbytes_in, nbytes_out); printf("--total %d\n", len - offset); /* Seek to the beginning, write the header, and close the file */ if (fseek(pf, (long)(0+offset), SEEK_SET)) { printf("fseeko"); goto error; } if (fwrite(header, 32, 1, pf) != 1) { printf("fwrite(%s)", "patch_file"); goto error; } fseek(pf, len, SEEK_SET); /* Free the memory we used */ free(db); free(eb); free(I); return 0; error: if(pfbz2) BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); if(I) free(I); if(V) free(V); if(db) free(db); if(eb) free(eb); return -1; }