"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