"Fossies" - the Fresh Open Source Software Archive 
Member "libisoburn-1.5.6/test/compare_file.c" (8 Jul 2020, 8501 Bytes) of package /linux/misc/libisoburn-1.5.6.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the last
Fossies "Diffs" side-by-side code changes report for "compare_file.c":
1.5.0_vs_1.5.2.
1 /*
2 Compare two copies of a file object in as many aspects as i can imagine
3 to make sense. (E.g.: comparing atime makes no sense.)
4
5 To compare tree /media/dvd and /original/dir :
6 find /media/dvd -exec compare_file '{}' /media/dvd /original/dir ';'
7
8 Copyright 2008 - 2015 Thomas Schmitt, <scdbackup@gmx.net>
9
10 Provided under GPL version 2 or later.
11
12
13 cc -g -o compare_file compare_file.c
14 */
15
16 #ifdef HAVE_CONFIG_H
17 #include "../config.h"
18 #endif
19
20 #include <ctype.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <time.h>
30
31 /* O_BINARY is needed for Cygwin but undefined elsewhere */
32 #ifndef O_BINARY
33 #define O_BINARY 0
34 #endif
35
36 /* @param flag bit0= single letters */
37 char *Ftypetxt(mode_t st_mode, int flag)
38 {
39 if(flag&1)
40 goto single_letters;
41 if(S_ISDIR(st_mode))
42 return("directory");
43 else if(S_ISREG(st_mode))
44 return("regular_file");
45 else if(S_ISLNK(st_mode))
46 return("symbolic_link");
47 else if(S_ISBLK(st_mode))
48 return("block_device");
49 else if(S_ISCHR(st_mode))
50 return("char_device");
51 else if(S_ISFIFO(st_mode))
52 return("name_pipe");
53 else if(S_ISSOCK(st_mode))
54 return("unix_socket");
55 return("unknown");
56 single_letters:;
57 if(S_ISDIR(st_mode))
58 return("d");
59 else if(S_ISREG(st_mode))
60 return("-");
61 else if(S_ISLNK(st_mode))
62 return("l");
63 else if(S_ISBLK(st_mode))
64 return("b");
65 else if(S_ISCHR(st_mode))
66 return("c");
67 else if(S_ISFIFO(st_mode))
68 return("p");
69 else if(S_ISSOCK(st_mode))
70 return("s");
71 return("?");
72 }
73
74
75 char *Ftimetxt(time_t t, char timetext[40], int flag)
76 {
77 char *rpt;
78 struct tm tms, *tmpt;
79 static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
80 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
81
82 tmpt= localtime_r(&t, &tms);
83 rpt= timetext;
84 rpt[0]= 0;
85 if(tmpt==0)
86 sprintf(rpt+strlen(rpt), "%12.f", (double) t);
87 else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0)
88 sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d",
89 months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min);
90 else
91 sprintf(rpt+strlen(rpt), "%3s %2d %4.4d",
92 months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year);
93 return(timetext);
94 }
95
96
97 /* @param flag bit0= compare atime
98 bit1= compare ctime
99 */
100 int Compare_2_files(char *adr1, char *adr2, char *adrc, int flag)
101 {
102 struct stat s1, s2;
103 int ret, differs= 0, r1, r2, fd1= -1, fd2= -1, i, done;
104 char buf1[4096], buf2[4096], a[4096], ttx1[40], ttx2[40];
105 off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1;
106 double dcount;
107
108 ret= lstat(adr1, &s1);
109 if(ret==-1) {
110 printf("? %s : cannot lstat() : %s\n", adr1, strerror(errno));
111 return(0);
112 }
113 strcpy(a, Ftypetxt(s1.st_mode, 1));
114 strcat(a, " ");
115 if(adrc[0]) {
116 if(strlen(a) + strlen(adrc) < 4096)
117 strcat(a, adrc);
118 } else {
119 strcat(a, ".");
120 }
121
122 ret= lstat(adr2, &s2);
123 if(ret==-1) {
124 printf("? %s : cannot lstat() : %s\n", adr2, strerror(errno));
125 return(0);
126 }
127
128 /* Attributes */
129 if(s1.st_mode != s2.st_mode) {
130 if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT))
131 printf("%s : st_mode : %7.7o <> %7.7o\n", a,
132 (unsigned int) (s1.st_mode & ~S_IFMT),
133 (unsigned int) (s2.st_mode & ~S_IFMT));
134 if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT))
135 printf("%s : type : %s <> %s\n",
136 a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0));
137 differs= 1;
138 }
139 if(s1.st_uid != s2.st_uid) {
140 printf("%s : st_uid : %lu <> %lu\n",
141 a, (unsigned long) s1.st_uid, (unsigned long) s2.st_uid);
142 differs= 1;
143 }
144 if(s1.st_gid != s2.st_gid) {
145 printf("%s : st_gid : %lu <> %lu\n",
146 a, (unsigned long) s1.st_gid, (unsigned long) s2.st_gid);
147 differs= 1;
148 }
149 if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) ||
150 (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) {
151 if(s1.st_rdev != s2.st_rdev) {
152 printf("%s : %s st_rdev : %lu <> %lu\n", a,
153 (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"),
154 (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev);
155 differs= 1;
156 }
157 }
158 if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) {
159 printf("%s : st_size : %.f <> %.f diff= %.f\n",
160 a, (double) s1.st_size, (double) s2.st_size,
161 ((double) s1.st_size) - (double) s2.st_size);
162 differs= 1;
163 }
164 if(s1.st_mtime != s2.st_mtime) {
165 printf("%s : st_mtime : %s <> %s diff= %.f s\n",
166 a, Ftimetxt(s1.st_mtime, ttx1, 0),
167 Ftimetxt(s2.st_mtime, ttx2, 0),
168 ((double) s1.st_mtime) - (double) s2.st_mtime);
169 differs= 1;
170 }
171 if(flag&1) {
172 if(s1.st_atime != s2.st_atime) {
173 printf("%s : st_atime : %s <> %s diff= %.f s\n",
174 a, Ftimetxt(s1.st_atime, ttx1, 0),
175 Ftimetxt(s2.st_atime, ttx2, 0),
176 ((double) s1.st_atime) - (double) s2.st_atime);
177 differs= 1;
178 }
179 }
180 if(flag&2) {
181 if(s1.st_ctime != s2.st_ctime) {
182 printf("%s : st_ctime : %s <> %s diff= %.f s\n",
183 a, Ftimetxt(s1.st_ctime, ttx1, 0),
184 Ftimetxt(s2.st_ctime, ttx2, 0),
185 ((double) s1.st_ctime) - (double) s2.st_ctime);
186 differs= 1;
187 }
188 }
189 if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)) {
190 fd1= open(adr1, O_RDONLY | O_BINARY);
191 if(fd1==-1) {
192 printf("- %s : cannot open() : %s\n", adr1, strerror(errno));
193 return(0);
194 }
195 fd2= open(adr2, O_RDONLY | O_BINARY);
196 if(fd2==-1) {
197 printf("- %s : cannot open() : %s\n", adr2, strerror(errno));
198 close(fd1);
199 return(0);
200 }
201
202 /* Content */
203 done= 0;
204 while(!done) {
205 r1= read(fd1, buf1, sizeof(buf1));
206 r2= read(fd2, buf2, sizeof(buf2));
207 if((r1==EOF && r2==EOF) || (r1==0 && r2==0))
208 break;
209 if(r1==EOF || r1==0) {
210 if(r1==EOF)
211 r1= 0;
212 if(s1.st_size > r1count + r1)
213 printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count);
214 differs= 1;
215 }
216 r1count+= r1;
217 if(r2==EOF || r2<r1) {
218 if(r2==EOF)
219 r2= 0;
220 if(s2.st_size > r2count + r2)
221 printf("- %s : early EOF after %.f bytes\n", adr2, (double) r2count);
222 differs= 1;
223 done= 1;
224 }
225 if(r2>r1) {
226 if(s1.st_size > r1count + r1)
227 printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count);
228 differs= 1;
229 done= 1;
230 }
231 r2count+= r2;
232 if(r1>r2)
233 r1= r2;
234 for(i= 0; i<r1; i++) {
235 if(buf1[i]!=buf2[i]) {
236 if(first_diff<0)
237 first_diff= i;
238 diffcount++;
239 }
240 }
241 }
242 if(diffcount>0 || r1count!=r2count) {
243 if(first_diff<0)
244 first_diff= (r1count>r2count ? r2count : r1count);
245 if(r1count > r2count)
246 dcount= diffcount + (r1count - r2count);
247 else
248 dcount= diffcount + (r2count - r1count);
249 printf("%s : %s : differs by at least %.f bytes. First at %.f\n", a,
250 (s1.st_mtime==s2.st_mtime ? "CONTENT":"content"),
251 dcount, (double) first_diff);
252 differs= 1;
253 }
254 }
255 if(fd1!=-1)
256 close(fd1);
257 if(fd2!=-1)
258 close(fd2);
259 return(!differs);
260 }
261
262
263 int main(int argc, char **argv)
264 {
265 int ret, i, with_ctime= 1;
266 char adr1[4096], adr2[4096], adrc[4096];
267
268 if(sizeof(off_t) < 8) {
269 fprintf(stderr,
270 "%s : FATAL : Compile time misconfiguration. sizeof(off_t) too small.\n\n",
271 argv[0]);
272 exit(4);
273 }
274 if(argc<4) {
275 fprintf(stderr, "usage: %s path prefix1 prefix2\n", argv[0]);
276 exit(2);
277 }
278 for(i= 4; i<argc; i++) {
279 if(strcmp(argv[i], "-no_ctime")==0)
280 with_ctime= 0;
281 else {
282 fprintf(stderr, "%s : Option not recognized: '%s'\n", argv[0], argv[i]);
283 exit(2);
284 }
285 }
286
287 if(strncmp(argv[1], argv[2], strlen(argv[2]))!=0) {
288 fprintf(stderr, "%s: path '%s' does not match prefix1 '%s'\n",
289 argv[0], argv[1], argv[2]);
290 exit(2);
291 }
292 if(strlen(argv[1]) >= 4096) {
293 fprintf(stderr, "path exceeds size limit of 4095\n");
294 exit(3);
295 }
296 if(strlen(argv[1]) - strlen(argv[2]) > 4000) {
297 fprintf(stderr, "common address part exceeds size limit of 4000\n");
298 exit(3);
299 }
300 if(strlen(argv[3]) + 1 + strlen(argv[1]) - strlen(argv[2]) >= 4096) {
301 fprintf(stderr, "prefix2 exceeds size limit of 4095\n");
302 exit(3);
303 }
304 strcpy(adr1, argv[1]);
305 strcpy(adrc, argv[1]+strlen(argv[2]));
306 strcpy(adr2, argv[3]);
307 if(adrc[0] == '/' || adrc[0] == 0)
308 strcat(adr2, "/");
309 strcat(adr2, adrc);
310
311 ret= Compare_2_files(adr1, adr2, adrc, (with_ctime<<1));
312 exit(ret<=0);
313 }
314