root/tools/bdiffm/bdiffm.c

Revision 643, 3.5 kB (checked in by dp, 2 years ago)

set svn:keywords to id and rev

  • Property svn:keywords set to id rev
Line 
1 /* $Id$
2  *
3  * bdiffm - display binary diff matrix for n files.
4  *
5  */
6 #define _GNU_SOURCE
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <math.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/mman.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <stdint.h>
19
20 #define byte unsigned char
21
22 #define max(a, b) ((a > b) ? (a) : (b))
23
24 #define CL_RESET 0
25 #define CL_RED 31
26 #define CL_GREEN 32
27 #define CL_YELLOW 33
28 #define CL_WHITE 37
29
30 typedef struct _FileInfo
31 {
32         uint32_t                m_number;
33         const char      *m_filename;
34         uint32_t                m_size;
35         void            *m_data;
36 } FileInfo;
37
38 void pcolor(uint32_t c)
39 {
40         if( isatty(STDOUT_FILENO) )
41         {
42                 if( c == CL_RESET )
43                         printf("\033[0m");
44                 else
45                         printf("\033[%d;1m", c);
46         }
47 }
48
49 int32_t percent(float p)
50 {
51         return (int32_t)(p * 100);
52 }
53
54 uint32_t getRevision()
55 {
56         char revision[] = "$Rev$";
57         char *p = revision;
58        
59         while( *p && !isdigit(*p) )
60                 p++;
61        
62         if( !(*p) )
63                 return 0; /* unknown */
64         else
65                 return atoi(p);
66 }
67
68 float getSimilarity(FileInfo *a, FileInfo *b)
69 {
70         uint32_t diffBytes, i;
71        
72         if( a->m_size > b->m_size )
73                 diffBytes = a->m_size - b->m_size;
74         else
75                 diffBytes = b->m_size - a->m_size;
76        
77         if( max(a->m_size, b->m_size) == 0 )
78                 return 0;
79        
80         for( i = 0; i < a->m_size && i < b->m_size; i++ )
81                 if( *((byte *)a->m_data + i) != *((byte *)b->m_data + i) )
82                         diffBytes++;
83        
84         return (1.0 - ((float)diffBytes / max(a->m_size, b->m_size)));
85 }
86
87 void displayMatrix(uint32_t count, FileInfo *files)
88 {
89
90         uint32_t i, j;
91         float similarity;
92        
93         printf("    |");
94         for( i = 0; i < count; i++ )
95                 printf("    %02d", i + 1);
96         printf("\n");
97        
98         printf("----+");
99         for( i = 0; i < count; i++ )
100                 printf("------");
101         printf("\n");
102
103        
104         for( i = 0; i < count; i++ )
105         {
106                 printf(" %02d |", i + 1);
107                 for( j = 0; j < i; j++ )
108                         printf("      ");
109                 for( j = i; j < count; j++ )
110                 {
111                         if( i == j )
112                         {
113                                 similarity = 1.0;
114                                 pcolor(CL_WHITE);
115                         }
116                         else
117                         {
118                                 similarity = getSimilarity(&files[i], &files[j]);
119                                 if( similarity >= 0.75 )
120                                         pcolor(CL_GREEN);
121                                 else if( similarity >= 0.50 )
122                                         pcolor(CL_YELLOW);
123                                 else
124                                         pcolor(CL_RED);
125                         }
126
127                         printf("  %3d%%", percent(similarity));
128                        
129                         pcolor(CL_RESET);
130                 }
131                
132                 printf("\n");
133         }
134        
135         printf("\n");
136 }
137
138 int32_t main(int32_t argc, char **argv)
139 {
140         uint32_t                fileCount = 0, i;
141         int32_t         fd;
142         FileInfo        *files;
143         struct stat     statInfo;
144         const char      *currentFile;
145        
146         printf("bdiffm version %d built %s %s\n", getRevision(), __DATE__, __TIME__);
147        
148         if( argc < 2 )
149         {
150                 printf("usage: %s FILE_1 FILE_2 ... FILE_n\n", argv[0]);
151                 return -1;
152         }
153
154         files = (FileInfo *)malloc(sizeof(FileInfo) * (argc - 1));
155
156         for( i = 0; i < (argc - 1); i++ )
157         {
158                 currentFile = argv[i + 1];
159                
160                 fd = open(currentFile, 0);
161                
162                 if( fd == -1 )
163                 {
164                         printf("%s: Unable to open %s: %s\n", argv[0], currentFile, strerror(errno));
165                         return -1;
166                 }
167
168                 stat(currentFile, &statInfo);
169
170                 files[i].m_number = i + 1;
171                 files[i].m_filename = currentFile;
172                 files[i].m_size = (uint32_t)statInfo.st_size;
173                 files[i].m_data = mmap(0, files[i].m_size, PROT_READ, MAP_PRIVATE, fd, 0);
174                
175                 if( (int32_t)files[i].m_data == -1 )
176                 {
177                         printf("%s: Unable to mmap %s: %s\n", argv[0], currentFile, strerror(errno));
178                         return -1;
179                 }
180                
181                 printf("%02d  %-50s  0x%08x  0x%08x\n", files[i].m_number, files[i].m_filename, files[i].m_size, (uint32_t)files[i].m_data);
182                
183                 fileCount++;
184
185                 close(fd);
186         }
187        
188         printf("\nComparing %d files.\n\n", fileCount);
189        
190         displayMatrix(fileCount, files);
191
192         for( i = 0; i < (argc - 1); i++ )
193                 munmap(files[i].m_data, files[i].m_size);
194        
195
196         free(files);
197
198         return 0;
199 }
Note: See TracBrowser for help on using the browser.