00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
00090
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
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
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