diff --git a/src/bdelta.cpp b/src/bdelta.cpp index 6f68846..19191ba 100644 --- a/src/bdelta.cpp +++ b/src/bdelta.cpp @@ -10,6 +10,8 @@ #include "file.h" #include "compatibility.h" +#define FEFE + const void *f_read(void *f, void *buf, unsigned place, unsigned num) { fseek((FILE *)f, place, SEEK_SET); fread_fixed((FILE *)f, buf, num); @@ -103,9 +105,15 @@ int main(int argc, char **argv) { nummatches = bdelta_numMatches(b); +#ifdef FEFE + long long * copyloc1 = new long long[nummatches + 1]; + long long * copyloc2 = new long long[nummatches + 1]; + unsigned * copynum = new unsigned[nummatches + 1]; +#else unsigned * copyloc1 = new unsigned[nummatches + 1]; unsigned * copyloc2 = new unsigned[nummatches + 1]; unsigned * copynum = new unsigned[nummatches + 1]; +#endif FILE *fout = fopen(argv[3], "wb"); if (!fout) { @@ -115,7 +123,7 @@ int main(int argc, char **argv) { const char *magic = "BDT"; fwrite_fixed(fout, magic, 3); - unsigned short version = 1; + unsigned short version = 2; write_word(fout, version); unsigned char intsize = 4; fwrite_fixed(fout, &intsize, 1); @@ -129,12 +137,22 @@ int main(int argc, char **argv) { unsigned p1, p2, num; bdelta_getMatch(b, i, &p1, &p2, &num); // printf("%*x, %*x, %*x, %*x\n", 10, p1, 10, p2, 10, num, 10, p2-lastp2); +#ifdef FEFE + copyloc1[i] = (long long)p1 - lastp1; + copyloc2[i] = (long long)p2 - lastp2; + copynum[i] = num; + write_varint(fout, copyloc1[i]); + write_varint(fout, copyloc2[i]); + write_varint(fout, copynum[i]); +// printf("%u/%u: (%ld -> %u,%ld -> %u,%u)\n",i,nummatches,copyloc1[i],p1,copyloc2[i],p2,copynum[i]); +#else copyloc1[i] = p1 - lastp1; write_dword(fout, copyloc1[i]); copyloc2[i] = p2 - lastp2; write_dword(fout, copyloc2[i]); copynum[i] = num; write_dword(fout, copynum[i]); +#endif lastp1 = p1 + num; lastp2 = p2 + num; } diff --git a/src/bpatch.cpp b/src/bpatch.cpp index 8817ce6..68d0c17 100644 --- a/src/bpatch.cpp +++ b/src/bpatch.cpp @@ -7,6 +7,8 @@ #include "file.h" #include "compatibility.h" +#define FEFE + bool copy_bytes_to_file(FILE *infile, FILE *outfile, unsigned numleft) { size_t numread; do { @@ -42,10 +44,17 @@ int main(int argc, char **argv) { return 1; } unsigned short version = read_word(patchfile); +#ifdef FEFE + if (version != 1 && version != 2) { + printf("unsupported patch version\n"); + return 1; + } +#else if (version != 1) { printf("unsupported patch version\n"); return 1; } +#endif char intsize; fread_fixed(patchfile, &intsize, 1); if (intsize != 4) { @@ -57,14 +66,32 @@ int main(int argc, char **argv) { unsigned nummatches = read_dword(patchfile); +#ifdef FEFE + long long * copyloc1 = new long long[nummatches + 1]; + long long * copyloc2 = new long long[nummatches + 1]; + unsigned * copynum = new unsigned[nummatches + 1]; +#else unsigned * copyloc1 = new unsigned[nummatches + 1]; unsigned * copyloc2 = new unsigned[nummatches + 1]; unsigned * copynum = new unsigned[nummatches + 1]; +#endif for (unsigned i = 0; i < nummatches; ++i) { +#ifdef FEFE + if (version==2) { + copyloc1[i] = read_varint(patchfile); + copyloc2[i] = read_varint(patchfile); + copynum[i] = read_varint(patchfile); + } else { copyloc1[i] = read_dword(patchfile); copyloc2[i] = read_dword(patchfile); copynum[i] = read_dword(patchfile); + } +#else + copyloc1[i] = read_dword(patchfile); + copyloc2[i] = read_dword(patchfile); + copynum[i] = read_dword(patchfile); +#endif size2 -= copyloc2[i] + copynum[i]; } if (size2) { @@ -77,16 +104,22 @@ int main(int argc, char **argv) { FILE *outfile = fopen(argv[2], "wb"); for (unsigned i = 0; i < nummatches; ++i) { +// printf("%u/%u: copy %u bytes from patch file ofs %ld (dest ofs %u)\n",i,nummatches,copyloc2[i],ftell(patchfile),ftell(outfile)); if (!copy_bytes_to_file(patchfile, outfile, copyloc2[i])) { printf("Error. patchfile is truncated\n"); return -1; } - int copyloc = copyloc1[i]; + long long copyloc = copyloc1[i]; fseek(ref, copyloc, SEEK_CUR); + long curofs=ftell(ref); + +#ifdef FEFE +// printf("%u/%u: (%d -> %u,%d -> %u,%u)\n",i,nummatches-1,copyloc,ftell(ref),copyloc2[i],ftell(outfile),copynum[i]); +#endif if (!copy_bytes_to_file(ref, outfile, copynum[i])) { - printf("Error while copying from reference file\n"); + printf("Error while copying from reference file (ofs %ld, %u bytes)\n", curofs, copynum[i]); return -1; } } diff --git a/src/file.h b/src/file.h index 0e03fb0..e4a03f7 100644 --- a/src/file.h +++ b/src/file.h @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #define MAX_IO_BLOCK_SIZE (1024 * 1024) @@ -58,6 +59,44 @@ unsigned read_dword(FILE *f) { return (read_word(f) << 16) + low; } +static size_t scan_varint(const char* in,size_t len, unsigned long long* n) { + size_t i; + unsigned long long l; + if (len==0) return 0; + for (l=0, i=0; i>1); + return n; +} + +long long read_varint(FILE* f) { + char buf[20]; + size_t i; + long long l; + for (i=0; i> 8; @@ -70,6 +109,31 @@ void write_dword(FILE *f, unsigned number) { write_word(f, number >> 16); } + +/* write int in least amount of bytes, return number of bytes */ +/* as used in varints from Google protocol buffers */ +static size_t fmt_varint(char* dest,unsigned long long l) { + /* high bit says if more bytes are coming, lower 7 bits are payload; little endian */ + size_t i; + for (i=0; l; ++i, l>>=7) { + if (dest) dest[i]=(l&0x7f) | ((!!(l&~0x7f))<<7); + } + if (!i) { /* l was 0 */ + if (dest) dest[0]=0; + ++i; + } + return i; +} + +static size_t fmt_pb_type0_sint(char* dest,signed long long l) { + return fmt_varint(dest,(l << 1) ^ (l >> (sizeof(l)*8-1))); +} + +void write_varint(FILE* f, long long number) { + char tmp[20]; + fwrite_fixed(f,tmp,fmt_pb_type0_sint(tmp,number)); +} + bool fileExists(char *fname) { FILE *f = fopen(fname, "rb"); bool exists = (f != NULL);