Date:2011-08-17 11:59:05 (8 years 1 day ago)
Author:Werner Almesberger
Commit:08a13cd9759451ccf298000448ad52513a451dfe
Message:bitcmp/: little utility to find which bits differ between two files

Files: bitcmp/Makefile (1 diff)
bitcmp/bitcmp.c (1 diff)

Change Details

bitcmp/Makefile
1CFLAGS=-Wall
2
3all: bitcmp
bitcmp/bitcmp.c
1#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <unistd.h>
5#include <string.h>
6#include <fcntl.h>
7
8
9#define BUFFER 4096
10
11
12static int do_open(const char *name)
13{
14    int fd;
15
16    fd = open(name, O_RDONLY);
17    if (fd >= 0)
18        return fd;
19
20    perror(name);
21    exit(1);
22}
23
24
25static void usage(const char *name)
26{
27    fprintf(stderr,
28"usage: %s [-w|-l] [-B] file1 file2\n"
29" -w compare words (16 bits; default is bytes)\n"
30" -l compare long words (32 bits; default is bytes)\n"
31" -B use big-endian (default: little-endian)\n"
32    , name);
33    exit(1);
34}
35
36
37int main(int argc, char *const *argv)
38{
39    int little = 1;
40    int bytes = 1;
41    int c;
42    int fd1, fd2;
43    const char *name1, *name2;
44    uint8_t buf1[BUFFER], buf2[BUFFER];
45    ssize_t got1, got2, len;
46    uint32_t diff;
47    int i, j;
48    static unsigned bin[32];
49
50    while ((c = getopt(argc, argv, "Blw")) != EOF) {
51        switch (c) {
52        case 'B':
53            little = 0;
54            break;
55        case 'l':
56            bytes = 4;
57            break;
58        case 'w':
59            bytes = 2;
60            break;
61        default:
62            usage(*argv);
63        }
64    }
65    if (argc-optind != 2)
66        usage(*argv);
67
68    name1 = argv[optind];
69    name2 = argv[optind+1];
70
71    fd1 = do_open(name1);
72    fd2 = do_open(name2);
73
74    while (1) {
75        memset(buf1, 0, BUFFER);
76        memset(buf2, 0, BUFFER);
77        got1 = read(fd1, buf1, BUFFER);
78        if (got1 < 0) {
79            perror(name1);
80            return 1;
81        }
82        got2 = read(fd2, buf2, BUFFER);
83        if (got2 < 0) {
84            perror(name2);
85            return 1;
86        }
87        if (got1 != got2)
88            fprintf(stderr, "%s < %s\n",
89                got1 < got2 ? name1 : name2,
90                got1 < got2 ? name2 : name1);
91        len = got1 < got2 ? got1 : got2;
92        if (!len)
93            break;
94        for (i = 0; i <= len; i += bytes) {
95            diff = 0;
96            switch (bytes) {
97            case 4:
98                diff |= (buf1[i+2] ^ buf2[i+2]) << 16;
99                diff |= (buf1[i+3] ^ buf2[i+3]) << 24;
100                /* fall through */
101            case 2:
102                diff |= (buf1[i+1] ^ buf2[i+1]) << 8;
103                /* fall through */
104            case 1:
105                diff |= buf1[i] ^ buf2[i];
106                break;
107            default:
108                abort();
109            }
110            for (j = 0; j != 32; j++)
111                if (diff & (1 << j))
112                    bin[j]++;
113        }
114    }
115
116    for (j = 0; j != 8*bytes; j++) {
117        if (little)
118            i = j;
119        else
120            i = 8*(bytes-1-(j >> 3))+(j & 7);
121        if (bin[i])
122            printf("%2d: %u\n", j, bin[i]);
123    }
124    return 0;
125}

Archive Download the corresponding diff file

Branches:
master



interactive