From 08a13cd9759451ccf298000448ad52513a451dfe Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Wed, 17 Aug 2011 06:59:05 -0300 Subject: [PATCH] bitcmp/: little utility to find which bits differ between two files --- bitcmp/Makefile | 3 ++ bitcmp/bitcmp.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 bitcmp/Makefile create mode 100644 bitcmp/bitcmp.c diff --git a/bitcmp/Makefile b/bitcmp/Makefile new file mode 100644 index 0000000..304914c --- /dev/null +++ b/bitcmp/Makefile @@ -0,0 +1,3 @@ +CFLAGS=-Wall + +all: bitcmp diff --git a/bitcmp/bitcmp.c b/bitcmp/bitcmp.c new file mode 100644 index 0000000..2ed76d4 --- /dev/null +++ b/bitcmp/bitcmp.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include + + +#define BUFFER 4096 + + +static int do_open(const char *name) +{ + int fd; + + fd = open(name, O_RDONLY); + if (fd >= 0) + return fd; + + perror(name); + exit(1); +} + + +static void usage(const char *name) +{ + fprintf(stderr, +"usage: %s [-w|-l] [-B] file1 file2\n" +" -w compare words (16 bits; default is bytes)\n" +" -l compare long words (32 bits; default is bytes)\n" +" -B use big-endian (default: little-endian)\n" + , name); + exit(1); +} + + +int main(int argc, char *const *argv) +{ + int little = 1; + int bytes = 1; + int c; + int fd1, fd2; + const char *name1, *name2; + uint8_t buf1[BUFFER], buf2[BUFFER]; + ssize_t got1, got2, len; + uint32_t diff; + int i, j; + static unsigned bin[32]; + + while ((c = getopt(argc, argv, "Blw")) != EOF) { + switch (c) { + case 'B': + little = 0; + break; + case 'l': + bytes = 4; + break; + case 'w': + bytes = 2; + break; + default: + usage(*argv); + } + } + if (argc-optind != 2) + usage(*argv); + + name1 = argv[optind]; + name2 = argv[optind+1]; + + fd1 = do_open(name1); + fd2 = do_open(name2); + + while (1) { + memset(buf1, 0, BUFFER); + memset(buf2, 0, BUFFER); + got1 = read(fd1, buf1, BUFFER); + if (got1 < 0) { + perror(name1); + return 1; + } + got2 = read(fd2, buf2, BUFFER); + if (got2 < 0) { + perror(name2); + return 1; + } + if (got1 != got2) + fprintf(stderr, "%s < %s\n", + got1 < got2 ? name1 : name2, + got1 < got2 ? name2 : name1); + len = got1 < got2 ? got1 : got2; + if (!len) + break; + for (i = 0; i <= len; i += bytes) { + diff = 0; + switch (bytes) { + case 4: + diff |= (buf1[i+2] ^ buf2[i+2]) << 16; + diff |= (buf1[i+3] ^ buf2[i+3]) << 24; + /* fall through */ + case 2: + diff |= (buf1[i+1] ^ buf2[i+1]) << 8; + /* fall through */ + case 1: + diff |= buf1[i] ^ buf2[i]; + break; + default: + abort(); + } + for (j = 0; j != 32; j++) + if (diff & (1 << j)) + bin[j]++; + } + } + + for (j = 0; j != 8*bytes; j++) { + if (little) + i = j; + else + i = 8*(bytes-1-(j >> 3))+(j & 7); + if (bin[i]) + printf("%2d: %u\n", j, bin[i]); + } + return 0; +}