|
libisoburn 0.5.6
|
00001 /* 00002 Compare two copies of a file object in as many aspects as i can imagine 00003 to make sense. (E.g.: comparing atime makes no sense.) 00004 00005 To compare tree /media/dvd and /original/dir : 00006 find /media/dvd -exec compare_file '{}' /media/dvd /original/dir ';' 00007 00008 Copyright 2008 - 2010 Thomas Schmitt, <scdbackup@gmx.net> 00009 00010 Provided under GPL version 2 or later. 00011 00012 00013 cc -g -o compare_file compare_file.c 00014 */ 00015 00016 #include <ctype.h> 00017 #include <sys/types.h> 00018 #include <unistd.h> 00019 #include <stdlib.h> 00020 #include <stdio.h> 00021 #include <sys/stat.h> 00022 #include <errno.h> 00023 #include <fcntl.h> 00024 #include <string.h> 00025 #include <time.h> 00026 00027 00028 /* @param flag bit0= single letters */ 00029 char *Ftypetxt(mode_t st_mode, int flag) 00030 { 00031 if(flag&1) 00032 goto single_letters; 00033 if(S_ISDIR(st_mode)) 00034 return("directory"); 00035 else if(S_ISREG(st_mode)) 00036 return("regular_file"); 00037 else if(S_ISLNK(st_mode)) 00038 return("symbolic_link"); 00039 else if(S_ISBLK(st_mode)) 00040 return("block_device"); 00041 else if(S_ISCHR(st_mode)) 00042 return("char_device"); 00043 else if(S_ISFIFO(st_mode)) 00044 return("name_pipe"); 00045 else if(S_ISSOCK(st_mode)) 00046 return("unix_socket"); 00047 return("unknown"); 00048 single_letters:; 00049 if(S_ISDIR(st_mode)) 00050 return("d"); 00051 else if(S_ISREG(st_mode)) 00052 return("-"); 00053 else if(S_ISLNK(st_mode)) 00054 return("l"); 00055 else if(S_ISBLK(st_mode)) 00056 return("b"); 00057 else if(S_ISCHR(st_mode)) 00058 return("c"); 00059 else if(S_ISFIFO(st_mode)) 00060 return("p"); 00061 else if(S_ISSOCK(st_mode)) 00062 return("s"); 00063 return("?"); 00064 } 00065 00066 00067 char *Ftimetxt(time_t t, char timetext[40], int flag) 00068 { 00069 char *rpt; 00070 struct tm tms, *tmpt; 00071 static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 00072 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 00073 00074 tmpt= localtime_r(&t, &tms); 00075 rpt= timetext; 00076 rpt[0]= 0; 00077 if(tmpt==0) 00078 sprintf(rpt+strlen(rpt), "%12.f", (double) t); 00079 else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0) 00080 sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d", 00081 months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); 00082 else 00083 sprintf(rpt+strlen(rpt), "%3s %2d %4.4d", 00084 months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year); 00085 return(timetext); 00086 } 00087 00088 00089 /* @param flag bit0= compare atime 00090 bit1= compare ctime 00091 */ 00092 int Compare_2_files(char *adr1, char *adr2, char *adrc, int flag) 00093 { 00094 struct stat s1, s2; 00095 int ret, differs= 0, r1, r2, fd1= -1, fd2= -1, i, done; 00096 char buf1[4096], buf2[4096], a[4096], ttx1[40], ttx2[40]; 00097 off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1; 00098 00099 ret= lstat(adr1, &s1); 00100 if(ret==-1) { 00101 printf("? %s : cannot lstat() : %s\n", adr1, strerror(errno)); 00102 return(0); 00103 } 00104 strcpy(a, Ftypetxt(s1.st_mode, 1)); 00105 strcat(a, " "); 00106 if(adrc[0]) 00107 strcat(a, adrc); 00108 else 00109 strcat(a, "."); 00110 00111 ret= lstat(adr2, &s2); 00112 if(ret==-1) { 00113 printf("? %s : cannot lstat() : %s\n", adr2, strerror(errno)); 00114 return(0); 00115 } 00116 00117 /* Attributes */ 00118 if(s1.st_mode != s2.st_mode) { 00119 if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) 00120 printf("%s : st_mode : %7.7o <> %7.7o\n", a, 00121 (unsigned int) (s1.st_mode & ~S_IFMT), 00122 (unsigned int) (s2.st_mode & ~S_IFMT)); 00123 if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) 00124 printf("%s : type : %s <> %s\n", 00125 a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0)); 00126 differs= 1; 00127 } 00128 if(s1.st_uid != s2.st_uid) { 00129 printf("%s : st_uid : %lu <> %lu\n", 00130 a, (unsigned long) s1.st_uid, (unsigned long) s2.st_uid); 00131 differs= 1; 00132 } 00133 if(s1.st_gid != s2.st_gid) { 00134 printf("%s : st_gid : %lu <> %lu\n", 00135 a, (unsigned long) s1.st_gid, (unsigned long) s2.st_gid); 00136 differs= 1; 00137 } 00138 if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) || 00139 (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) { 00140 if(s1.st_rdev != s2.st_rdev) { 00141 printf("%s : %s st_rdev : %lu <> %lu\n", a, 00142 (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"), 00143 (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev); 00144 differs= 1; 00145 } 00146 } 00147 if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) { 00148 printf("%s : st_size : %.f <> %.f diff= %.f\n", 00149 a, (double) s1.st_size, (double) s2.st_size, 00150 ((double) s1.st_size) - (double) s2.st_size); 00151 differs= 1; 00152 } 00153 if(s1.st_mtime != s2.st_mtime) { 00154 printf("%s : st_mtime : %s <> %s diff= %.f s\n", 00155 a, Ftimetxt(s1.st_mtime, ttx1, 0), 00156 Ftimetxt(s2.st_mtime, ttx2, 0), 00157 ((double) s1.st_mtime) - (double) s2.st_mtime); 00158 differs= 1; 00159 } 00160 if(flag&1) { 00161 if(s1.st_atime != s2.st_atime) { 00162 printf("%s : st_atime : %s <> %s diff= %.f s\n", 00163 a, Ftimetxt(s1.st_atime, ttx1, 0), 00164 Ftimetxt(s2.st_atime, ttx2, 0), 00165 ((double) s1.st_atime) - (double) s2.st_atime); 00166 differs= 1; 00167 } 00168 } 00169 if(flag&2) { 00170 if(s1.st_ctime != s2.st_ctime) { 00171 printf("%s : st_ctime : %s <> %s diff= %.f s\n", 00172 a, Ftimetxt(s1.st_ctime, ttx1, 0), 00173 Ftimetxt(s2.st_ctime, ttx2, 0), 00174 ((double) s1.st_ctime) - (double) s2.st_ctime); 00175 differs= 1; 00176 } 00177 } 00178 if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)) { 00179 fd1= open(adr1, O_RDONLY); 00180 if(fd1==-1) { 00181 printf("- %s : cannot open() : %s\n", adr1, strerror(errno)); 00182 return(0); 00183 } 00184 fd2= open(adr2, O_RDONLY); 00185 if(fd2==-1) { 00186 printf("- %s : cannot open() : %s\n", adr2, strerror(errno)); 00187 close(fd1); 00188 return(0); 00189 } 00190 00191 /* Content */ 00192 done= 0; 00193 while(!done) { 00194 r1= read(fd1, buf1, sizeof(buf1)); 00195 r2= read(fd2, buf2, sizeof(buf2)); 00196 if((r1==EOF && r2==EOF) || (r1==0 && r2==0)) 00197 break; 00198 if(r1==EOF || r1==0) { 00199 if(r1==EOF) 00200 r1= 0; 00201 if(s1.st_size > r1count + r1) 00202 printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count); 00203 differs= 1; 00204 } 00205 r1count+= r1; 00206 if(r2==EOF || r2<r1) { 00207 if(r2==EOF) 00208 r2= 0; 00209 if(s2.st_size > r2count + r2) 00210 printf("- %s : early EOF after %.f bytes\n", adr2, (double) r2count); 00211 differs= 1; 00212 done= 1; 00213 } 00214 if(r2>r1) { 00215 if(s1.st_size > r1count + r1) 00216 printf("- %s : early EOF after %.f bytes\n", adr1, (double) r1count); 00217 differs= 1; 00218 done= 1; 00219 } 00220 r2count+= r2; 00221 if(r1>r2) 00222 r1= r2; 00223 for(i= 0; i<r1; i++) { 00224 if(buf1[i]!=buf2[i]) { 00225 if(first_diff<0) 00226 first_diff= i; 00227 diffcount++; 00228 } 00229 } 00230 } 00231 if(diffcount>0 || r1count!=r2count) { 00232 if(first_diff<0) 00233 first_diff= (r1count>r2count ? r2count : r1count); 00234 printf("%s : %s : differs by at least %.f bytes. First at %.f\n", a, 00235 (s1.st_mtime==s2.st_mtime ? "CONTENT":"content"), 00236 (double) (diffcount + abs(r1count-r2count)), (double) first_diff); 00237 differs= 1; 00238 } 00239 } 00240 if(fd1!=-1) 00241 close(fd1); 00242 if(fd2!=-1) 00243 close(fd2); 00244 return(!differs); 00245 } 00246 00247 00248 int main(int argc, char **argv) 00249 { 00250 int ret, i, with_ctime= 1; 00251 char adr1[4096], adr2[4096], adrc[4096]; 00252 00253 if(argc<4) { 00254 fprintf(stderr, "usage: %s path prefix1 prefix2\n", argv[0]); 00255 exit(2); 00256 } 00257 for(i= 4; i<argc; i++) { 00258 if(strcmp(argv[i], "-no_ctime")==0) 00259 with_ctime= 0; 00260 else { 00261 fprintf(stderr, "%s : Option not recognized: '%s'\n", argv[0], argv[i]); 00262 exit(1); 00263 } 00264 } 00265 00266 if(strncmp(argv[1], argv[2], strlen(argv[2]))!=0) { 00267 fprintf(stderr, "%s: path '%s' does not match prefix1 '%s'\n", 00268 argv[0], argv[1], argv[2]); 00269 exit(2); 00270 } 00271 strcpy(adr1, argv[1]); 00272 strcpy(adrc, argv[1]+strlen(argv[2])); 00273 sprintf(adr2, "%s%s%s", 00274 argv[3], (adrc[0]=='/' || adrc[0]==0 ? "" : "/"), adrc); 00275 00276 ret= Compare_2_files(adr1, adr2, adrc, (with_ctime<<1)); 00277 exit(ret<=0); 00278 } 00279
1.7.3