#include #include #include typedef __m128i vector; // vector of 4 int (mmx) inline void bdiff_vdiff(vector *a, vector *b, vector *c) { *c = *a ^ *b; } union vec128 { vector v; struct { uint64_t a; uint64_t b; } data; }; inline int filter_AND(union vec128 *a, union vec128 *filter) { return (a->data.a & filter->data.a) || (a->data.b & filter->data.b); } int bdiff_buf(unsigned char *ibuf, unsigned char *obuf, unsigned char *filter, int size, int bsize) { static int bnum=0; int numblocks = size/bsize; int numvec = bsize/sizeof(vector); union vec128 *ba, *bb, *bc, *fb; union vec128 va __attribute__ ((aligned(16))); union vec128 vb __attribute__ ((aligned(16))); union vec128 vc __attribute__ ((aligned(16))); int i,j; int fres=0; fb = (union vec128 *)&filter[0]; for (i=0; i<(numblocks-1); i++, bnum++) { ba=(union vec128 *)&ibuf[i*bsize]; bb=(union vec128 *)&ibuf[(i+1)*bsize]; bc=(union vec128 *)&obuf[i*bsize]; for (j=0; j #include #include #include #include #include #define BUF_NUMBLOCKS (1024) void usage() { fprintf(stderr, "bdiff [-f ] []\n"); } int main(int argc, char **argv) { int ifd, ofd, ffd; int n, p, rc, blocksize, bufsize, bufsize_read; char *ifile, *ofile, *ffile=NULL; unsigned char *ibuf, *obuf, *ibuf_read, *fbuf; int i; int opt; while ((opt = getopt(argc, argv, "f")) != -1) { switch (opt) { case 'f': ffile=optarg; break; default: usage(); return -1; } } if (!ffile && optind+2 < argc) { usage(); return -1; } blocksize = atoi(argv[optind]); ifile = argv[optind+1]; if (!ffile) ofile = argv[optind+2]; bufsize = blocksize * BUF_NUMBLOCKS; if (posix_memalign((void *)&ibuf, 4096, bufsize)!=0) { perror("ERROR: posix_malloc"); return -1; } ifd = open(ifile, O_RDONLY); if (ifd < 0 ) { perror("ERROR: open"); return -1; } if (!ffile) { if (posix_memalign((void *)&obuf, 4096, bufsize)!=0) { perror("ERROR: posix_malloc"); return -1; } ofd = open(ofile, O_WRONLY|O_CREAT, 00666); if (ofd < 0 ) { perror("ERROR: open"); return -1; } } if (ffile) { ffd = open(ffile, O_RDONLY); if (ffd < 0) { perror("ERROR: open"); return -1; } if (posix_memalign((void *)&fbuf, 4096, blocksize)!=0) { perror("ERROR: posix_malloc"); return -1; } if (read(ffd, fbuf, blocksize)!=blocksize) { perror("ERROR: filter must contain a complete block"); return -1; } close(ffd); } ibuf_read = ibuf; bufsize_read = bufsize; while ((n = read(ifd, ibuf_read, bufsize_read)) > 0) { if (ibuf != ibuf_read) n += blocksize; if (n % blocksize) { fprintf(stderr, "ERROR: n=%d read not a multiple of blocksize=%d\n", n, blocksize); } rc = bdiff_buf(ibuf, obuf, fbuf, n, blocksize); if (rc != n-blocksize) { fprintf(stderr, "n=%d but only did %d bytes (blocksize=%d)\n", n, rc, blocksize); } p = write(ofd, obuf, rc); if (p!=rc) { perror("write"); return -1; } for (i=0; i