• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

libisoburn-0.5.6.pl00/test/compare_file.c

Go to the documentation of this file.
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 

Generated on Tue Aug 17 2010 13:01:43 for libisoburn by  doxygen 1.7.1