int nileDiff(FILE *oldfile, FILE *newfile, FILE *output, enum Options options) { int rv = 1; off_t oldoff = 0, newoff = 0, lastSkip = 0; size_t oldsize, newsize; char *olddata = NULL, *newdata = NULL, md5sum[MD5_DIGEST_LENGTH] = { 0 }, header[8]; if((oldsize = mapfile(oldfile, &olddata)) == -1) rv = 1; else if((newsize = mapfile(newfile, &newdata)) == -1) rv = 1; fputs(MAGIC, output); // newfile: uncompress and build md5sum if((newfile = uncompress(newfile, output, options)) == NULL) goto diff_cleanup; buildhash(md5sum, newfile); fwrite(md5sum, sizeof(md5sum), 1, output); // oldfile: uncompress and build md5sum if((oldfile = uncompress(oldfile, NULL, options)) == NULL) goto diff_cleanup; buildhash(md5sum, oldfile); fwrite(md5sum, sizeof(md5sum), 1, output); // Building Diff for(oldoff = newoff = 0; oldoff < oldsize && newoff < newsize;) { if(lcs(olddata, &oldoff, oldsize, newdata, &newoff, newsize, &lastSkip, output)) break; } // write trailing diff offtout(lastSkip, header); fwrite(header, sizeof(header), 1, output); offtout(oldsize - oldoff, header); fwrite(header, sizeof(header), 1, output); offtout(newsize - newoff, header); fwrite(header, sizeof(header), 1, output); fwrite(&newdata[newoff], newsize - newoff, 1, output); diff_cleanup: if(oldsize >= 0) munmap(olddata, oldsize); if(newsize >= 0) munmap(newdata, newsize); return rv; }
/** * 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 sporkel_bsdiff(u_char* oldp, off_t oldsize, u_char* newp, off_t newsize, u_char* patch, off_t patchsz) { 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]; u_char *fileblock; off_t ctrllen; /* Sanity checks */ if (oldp == NULL || newp == NULL || patch == NULL) return -1; if (oldsize < 0 || newsize < 0 || patchsz < 0) return -1; if (sporkel_bsdiff_patchsize_max(oldsize, newsize) > patchsz) return -1; /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) /*|| ((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)*/) return -1; I[0] = oldsize; sporkel_sais(oldp, I + 1, oldsize); //qsufsort(I,V,oldp,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(((db=malloc(newsize+1))==NULL) || ((eb=malloc(newsize+1))==NULL)) { free(I); return -1; } dblen=0; eblen=0; /* Write initial header */ memcpy(header,BSDIFF_CONFIG_MAGIC,8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); memcpy(patch, header, 32); /* Set up initial pointers */ fileblock = patch + 32; ctrllen = 0; /* Compute the differences, writing ctrl as we go */ scan=0;len=0;pos=0; lastscan=0;lastpos=0;lastoffset=0; while(scan<newsize) { oldscore=0; for(scsc=scan+=len;scan<newsize;scan++) { len=search(I,oldp,oldsize,newp+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (oldp[scsc+lastoffset] == newp[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (oldp[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(oldp[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(oldp[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]== oldp[lastpos+lenf-overlap+i]) s++; if(newp[scan-lenb+i]== oldp[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]-oldp[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); memcpy(fileblock, buf, 8); fileblock += 8; ctrllen += 8; offtout((scan-lenb)-(lastscan+lenf),buf); memcpy(fileblock, buf, 8); fileblock += 8; ctrllen += 8; offtout((pos-lenb)-(lastpos+lenf),buf); memcpy(fileblock, buf, 8); fileblock += 8; ctrllen += 8; lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan; }; }; /* Write size of ctrl data */ offtout(ctrllen, header + 8); /* Write diff data */ memcpy(fileblock, db, dblen); fileblock += dblen; /* Write size of diff data */ offtout(dblen, header + 16); /* Write extra data */ memcpy(fileblock, eb, eblen); /* Write the final header */ memcpy(patch, header, 32); /* Free the memory we used */ free(db); free(eb); free(I); return (32+ctrllen+dblen+eblen); }
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; }
static int lcs(const char *olddata, off_t *oldoff, size_t oldsize, const char *newdata, off_t *newoff, size_t newsize, off_t *lastSkip, FILE *output) { off_t oi, ni, bufi, lastni, lastoi, no = *newoff, oo = *oldoff, skip, baseSkip = *lastSkip, end = 0; int map[LCS_BLOCKSIZE][LCS_BLOCKSIZE] = { { 0 } }; char buf[LCS_BLOCKSIZE * 17], *p = NULL; // Build LCS Map for(oi = 0; oi < oldsize - oo && oi < LCS_BLOCKSIZE; oi++) { for(ni = 0; ni < newsize - no && ni < LCS_BLOCKSIZE; ni++) { if(olddata[oo + oi] == newdata[no + ni]) { map[oi][ni] = oi == 0 || ni == 0 ? 1 : map[oi-1][ni-1] + 1; } else if(map[oi][ni-1] < map[oi-1][ni]) { map[oi][ni] = oi == 0 ? 0 : map[oi-1][ni]; } else { map[oi][ni] = ni == 0 ? 0 : map[oi][ni-1]; } } } // Check if we hit boundarys end = oi == oldsize - oo || ni == newsize - no; // Tell caller about the new maximal offsets; *oldoff = oo + oi; *newoff = no + ni; for(skip = 0, lastni = --ni, lastoi = --oi, bufi = sizeof(buf);oi >= 0 && ni >= 0;) { // LEFT if(ni != 0 && map[oi][ni-1] == map[oi][ni]) { buf[--bufi] = newdata[no + ni]; ni--; } // UP else if(oi != 0 && map[oi-1][ni] == map[oi][ni]) { oi--; } // DIAGONAL else { // Set Offset to last common sequence if(oldoff != NULL) { *oldoff = oo + oi; *newoff = no + ni; newoff = oldoff = NULL; } // This is the first common character after // differences, so set new diff header if(skip == 0 && (lastni - ni != 0 || lastoi - oi != 0)) { bufi-=8; offtout(lastni - ni, &buf[bufi]); bufi-=8; offtout(lastoi - oi, &buf[bufi]); bufi-=8; p=&buf[bufi]; } ni--;oi--; skip++; lastni = ni; lastoi = oi; continue; } if(p != NULL) { offtout(skip, p); p = NULL; } // tell caller how much data we skipped if(lastSkip) { *lastSkip += skip; lastSkip = NULL; } skip = 0; } // Set skip for first header in this round if(p != NULL) offtout(skip+baseSkip, p); // tell caller how much data we skipped if we haven't done // that already. if(lastSkip) *lastSkip += skip; fwrite(&buf[bufi], sizeof(buf) - bufi, 1, output); return end; }