int patch(AbstractFile* in, AbstractFile* out, AbstractFile* patch) { unsigned char header[32], buf[8]; off_t oldsize, newsize; off_t bzctrllen, bzdatalen; off_t oldpos, newpos; int i; int cbz2err, dbz2err, ebz2err; off_t ctrl[3]; size_t lenread; BZStream* cpfbz2; BZStream* dpfbz2; BZStream* epfbz2; /* Read header */ if (patch->read(patch, header, 32) < 32) { return -1; } /* Check for appropriate magic */ if (memcmp(header, "BSDIFF40", 8) != 0) return -2; /* Read lengths from header */ bzctrllen = offtin(header + 8); bzdatalen = offtin(header + 16); newsize = offtin(header + 24); if((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0)) return -3; cpfbz2 = openBZStream(patch, 32, 1024); dpfbz2 = openBZStream(patch, 32 + bzctrllen, 1024); epfbz2 = openBZStream(patch, 32 + bzctrllen + bzdatalen, 1024); oldsize = in->getLength(in); oldpos = 0; newpos = 0; unsigned char* writeBuffer = (unsigned char*) malloc(BUFFERSIZE); unsigned char* readBuffer = (unsigned char*) malloc(BUFFERSIZE); while(newpos < newsize) { /* Read control data */ for(i=0;i<=2;i++) { lenread = bzRead(&cbz2err, cpfbz2, buf, 8); if ((lenread < 8) || ((cbz2err != BZ_OK) && (cbz2err != BZ_STREAM_END))) return -4; ctrl[i] = offtin(buf); }; /* Sanity-check */ if((newpos + ctrl[0]) > newsize) return -5; /* Read diff string */ unsigned int toRead; unsigned int total = ctrl[0]; while(total > 0) { if(total > BUFFERSIZE) toRead = BUFFERSIZE; else toRead = total; memset(writeBuffer, 0, toRead); lenread = bzRead(&dbz2err, dpfbz2, writeBuffer, toRead); if ((lenread < toRead) || ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) return -6; /* Add old data to diff string */ in->seek(in, oldpos); unsigned int maxRead; if((oldpos + toRead) > oldsize) maxRead = oldsize - oldpos; else maxRead = toRead; in->read(in, readBuffer, maxRead); for(i = 0; i < maxRead; i++) { writeBuffer[i] += readBuffer[i]; } out->seek(out, newpos); out->write(out, writeBuffer, toRead); /* Adjust pointers */ newpos += toRead; oldpos += toRead; total -= toRead; } /* Sanity-check */ if((newpos + ctrl[1]) > newsize) return -7; total = ctrl[1]; while(total > 0){ if(total > BUFFERSIZE) toRead = BUFFERSIZE; else toRead = total; /* Read extra string */ lenread = bzRead(&ebz2err, epfbz2, writeBuffer, toRead); if ((lenread < toRead) || ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) return -8; out->seek(out, newpos); out->write(out, writeBuffer, toRead); /* Adjust pointers */ newpos += toRead; total -= toRead; } oldpos += ctrl[2]; }; free(writeBuffer); free(readBuffer); closeBZStream(cpfbz2); closeBZStream(dpfbz2); closeBZStream(epfbz2); out->close(out); in->close(in); patch->close(patch); return 0; }
int patch(AbstractFile* in, AbstractFile* out, AbstractFile* patch) { unsigned char header[32], buf[8]; off_t oldsize, newsize; off_t bzctrllen, bzdatalen; off_t oldpos, newpos; unsigned char *old, *newBuffer; int i; int cbz2err, dbz2err, ebz2err; off_t ctrl[3]; size_t lenread; BZStream* cpfbz2; BZStream* dpfbz2; BZStream* epfbz2; /* Read header */ if (patch->read(patch, header, 32) < 32) { return -1; } /* Check for appropriate magic */ if (memcmp(header, "BSDIFF40", 8) != 0) return -2; /* Read lengths from header */ bzctrllen = offtin(header + 8); bzdatalen = offtin(header + 16); newsize = offtin(header + 24); if((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0)) return -3; cpfbz2 = openBZStream(patch, 32, 1024); dpfbz2 = openBZStream(patch, 32 + bzctrllen, 1024); epfbz2 = openBZStream(patch, 32 + bzctrllen + bzdatalen, 1024); oldsize = in->getLength(in); old = malloc(oldsize + 1); in->seek(in, 0); in->read(in, old, oldsize); in->close(in); newBuffer = malloc(newsize + 1); oldpos = 0; newpos = 0; while(newpos < newsize) { /* Read control data */ for(i=0;i<=2;i++) { lenread = bzRead(&cbz2err, cpfbz2, buf, 8); if ((lenread < 8) || ((cbz2err != BZ_OK) && (cbz2err != BZ_STREAM_END))) return -4; ctrl[i] = offtin(buf); }; /* Sanity-check */ if((newpos + ctrl[0]) > newsize) return -5; /* Read diff string */ memset(newBuffer + newpos, 0, ctrl[0]); lenread = bzRead(&dbz2err, dpfbz2, newBuffer + newpos, ctrl[0]); if ((lenread < ctrl[0]) || ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) return -6; /* Add old data to diff string */ for(i = 0; i < ctrl[0]; i++) { if(((oldpos + i)>=0) && ((oldpos + i)<oldsize)) { newBuffer[newpos + i] += old[oldpos + i]; } } /* Adjust pointers */ newpos += ctrl[0]; oldpos += ctrl[0]; /* Sanity-check */ if((newpos + ctrl[1]) > newsize) return -7; /* Read extra string */ lenread = bzRead(&ebz2err, epfbz2, newBuffer + newpos, ctrl[1]); if ((lenread < ctrl[1]) || ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) return -8; /* Adjust pointers */ newpos += ctrl[1]; oldpos += ctrl[2]; }; closeBZStream(cpfbz2); closeBZStream(dpfbz2); closeBZStream(epfbz2); out->seek(out, 0); if(out->write(out, newBuffer, newsize) != newsize) return -9; out->close(out); free(newBuffer); free(old); patch->close(patch); return 0; }