"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/cmp_update.c" (8 Jul 2020, 33762 Bytes) of package /linux/misc/libisoburn-1.5.4.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. For more information about "cmp_update.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.5.2.

    1 
    2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2019  Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains the implementation of actions which compare or update
    9    files between disk filesystem and ISO filesystem.
   10 */
   11 
   12 #ifdef HAVE_CONFIG_H
   13 #include "../config.h"
   14 #endif
   15 
   16 #include <ctype.h>
   17 #include <sys/types.h>
   18 #include <unistd.h>
   19 #include <stdlib.h>
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <sys/stat.h>
   23 #include <sys/time.h>
   24 #include <time.h>
   25 #include <fcntl.h>
   26 #include <errno.h>
   27 #include <pwd.h>
   28 #include <grp.h>
   29 
   30 /* O_BINARY is needed for Cygwin but undefined elsewhere */
   31 #ifndef O_BINARY
   32 #define O_BINARY 0
   33 #endif
   34 
   35 #include "xorriso.h"
   36 #include "xorriso_private.h"
   37 #include "xorrisoburn.h"
   38 
   39 
   40 /*
   41    @param result  Bitfield indicationg type of mismatch
   42               bit11= cannot open regular disk file
   43               bit12= cannot open iso file
   44               bit13= early eof of disk file
   45               bit14= early eof of iso file
   46               bit15= content bytes differ
   47    @param flag bit0= mtimes of both file objects are equal
   48               bit29= do not issue pacifier messages
   49               bit31= do not issue result messages
   50    @return    >0 ok , <=0 error
   51 */
   52 int Xorriso_compare_2_contents(struct XorrisO *xorriso, char *common_adr,
   53                                char *disk_adr, off_t disk_size,
   54                                off_t offset, off_t bytes,
   55                                char *iso_adr, off_t iso_size,
   56                                int *result, int flag)
   57 {
   58  int fd1= -1, ret, r1, r2, done, wanted, i, was_error= 0, use_md5= 0;
   59  void *stream2= NULL;
   60  off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1;
   61  char *respt, *buf1= NULL, *buf2= NULL, offset_text[80];
   62  char disk_md5[16], iso_md5[16];
   63  void *ctx= NULL;
   64  int buf_size= 32 * 1024;
   65  double dcount;
   66 
   67  Xorriso_alloc_meM(buf1, char, buf_size);
   68  Xorriso_alloc_meM(buf2, char, buf_size);
   69 
   70  respt= xorriso->result_line;
   71 
   72  fd1= open(disk_adr, O_RDONLY | O_BINARY);
   73  if(fd1==-1) {
   74    sprintf(respt, "- %s (DISK) : cannot open() : %s\n",
   75            disk_adr, strerror(errno));
   76 cannot_address:;
   77    if(!(flag&(1u<<31)))
   78      Xorriso_result(xorriso,0);
   79    (*result)|= 2048;
   80    {ret= 0; goto ex;}
   81  }
   82  if(offset>0)
   83    if(lseek(fd1, offset, SEEK_SET)==-1) {
   84      sprintf(respt, "- %s (DISK) : cannot lseek(%.f) : %s\n",
   85              disk_adr, (double) offset, strerror(errno));
   86      close(fd1);
   87      goto cannot_address;
   88    }
   89 
   90  if(xorriso->do_md5 & 16) {
   91    use_md5= 1;
   92    ret= Xorriso_is_plain_image_file(xorriso, NULL, iso_adr, 0);
   93    if(ret <= 0) 
   94      ret= 0; /* (reverse) filtered files are likely not to match their MD5 */
   95    else
   96      ret= Xorriso_get_md5(xorriso, NULL, iso_adr, iso_md5, 1);
   97    if(ret <= 0)
   98      use_md5= 0;
   99    else {
  100      ret= Xorriso_md5_start(xorriso, &ctx, 0);
  101      if(ret <= 0)
  102        use_md5= 0;
  103    }
  104  }
  105  if (! use_md5) {
  106    ret= Xorriso_iso_file_open(xorriso, iso_adr, NULL, &stream2, 0);
  107    if(ret<=0) {
  108      sprintf(respt, "- %s  (ISO) : cannot open() file in ISO image\n",iso_adr);
  109      if(!(flag&(1u<<31)))
  110        Xorriso_result(xorriso,0);
  111      close(fd1);
  112      (*result)|= 4096;
  113      {ret= 0; goto ex;}
  114    }
  115  }
  116 
  117  done= 0;
  118  while(!done) {
  119 
  120    wanted= buf_size;
  121    if(r1count+offset+wanted>disk_size)
  122      wanted= disk_size-r1count-offset;
  123    if(r1count+wanted>bytes)
  124      wanted= bytes-r1count;
  125    r1= 0;
  126    while(wanted>0) {
  127      ret= read(fd1, buf1, wanted);
  128      if(ret<=0)
  129    break;
  130      wanted-= ret;
  131      r1+= ret;
  132    }
  133 
  134    wanted= buf_size;
  135    if(r2count+wanted>iso_size)
  136      wanted= iso_size-r2count;
  137 /*
  138    if(r2count+wanted>bytes)
  139      wanted= bytes-r2count;
  140 */
  141    if(use_md5)
  142      r2= r1;
  143    else if(wanted>0)
  144      r2= Xorriso_iso_file_read(xorriso, stream2, buf2, wanted, 0);
  145    else
  146      r2= 0;
  147 
  148    if(r1<0 || r2<0)
  149      was_error= 1;
  150 
  151    if(r1<=0 && r2<=0)
  152  break;
  153    if(r1<=0) {
  154      if(r1<0)
  155        r1= 0;
  156      if(disk_size > r1count + r1 + offset) {
  157        sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n",
  158                disk_adr, (double) r1count);
  159        if(!(flag&(1u<<31)))
  160          Xorriso_result(xorriso,0);
  161        (*result)|= 8196;
  162      }
  163      (*result)|= (1<<15);
  164    }
  165    r1count+= r1;
  166    if(r2<=0 || r2<r1) {
  167      if(r2<0)
  168        r2= 0;
  169      if(iso_size > r2count + r2) {
  170        sprintf(respt, "- %s  (ISO) : early EOF after %.f bytes\n",
  171                iso_adr, (double) r2count);
  172        if(!(flag&(1u<<31)))
  173          Xorriso_result(xorriso,0);
  174        (*result)|= (1<<14);
  175      }
  176      (*result)|= (1<<15);
  177      done= 1;
  178    }
  179    if(r2>r1) {
  180      if(disk_size > r1count + r1 + offset) {
  181        sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n",
  182                disk_adr, (double) r1count);
  183        if(!(flag&(1u<<31)))
  184          Xorriso_result(xorriso,0);
  185        (*result)|= 8196;
  186      }
  187      (*result)|= (1<<15);
  188      done= 1;
  189    }
  190    r2count+= r2;
  191    if(r1>r2)
  192      r1= r2;
  193 
  194    if(use_md5) {
  195      Xorriso_md5_compute(xorriso, ctx, buf1, r1, 0);
  196    } else {
  197      for(i= 0; i<r1; i++) {
  198        if(buf1[i]!=buf2[i]) {
  199          if(first_diff<0)
  200            first_diff= r1count - r1 + i;
  201          diffcount++;
  202        }
  203      }
  204    }
  205    if(!(flag&(1<<29))) {
  206      xorriso->pacifier_count+= r1;
  207      xorriso->pacifier_byte_count+= r1;
  208      if(flag&(1u<<31))
  209        Xorriso_pacifier_callback(xorriso, "content bytes read",
  210                                  xorriso->pacifier_count, 0, "", 8);
  211      else
  212        Xorriso_pacifier_callback(xorriso, "bytes", xorriso->pacifier_count, 0,
  213                                  "", 8 | 1<<6);
  214    }
  215  }
  216 
  217  if(use_md5) {
  218    ret= Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
  219    if(ret <= 0) {
  220      *result |= (1 << 15);
  221      ret= -1; goto ex;
  222    }
  223    for(i= 0; i < 16; i++)
  224      if(iso_md5[i] != disk_md5[i])
  225    break;
  226    if(i < 16 ) {
  227      offset_text[0]= 0;
  228      if(offset>0)
  229        sprintf(offset_text, "%.f+", (double) offset);
  230      sprintf(respt, "%s %s  :  differs by MD5 sums.\n",
  231              common_adr, (flag&1 ?  "CONTENT": "content"));
  232      if(!(flag&(1u<<31)))
  233        Xorriso_result(xorriso,0);
  234      (*result)|= (1<<15);
  235    }
  236  } else if(diffcount>0 || r1count!=r2count) {
  237    if(first_diff<0)
  238      first_diff= (r1count>r2count ? r2count : r1count);
  239    offset_text[0]= 0;
  240    if(offset>0)
  241      sprintf(offset_text, "%.f+", (double) offset);
  242    if(r1count > r2count)
  243      dcount= diffcount + (r1count - r2count);
  244    else
  245      dcount= diffcount + (r2count - r1count);
  246    sprintf(respt, "%s %s  :  differs by at least %.f bytes. First at %s%.f\n",
  247            common_adr, (flag&1 ?  "CONTENT": "content"),
  248            dcount, offset_text, (double) first_diff);
  249    if(!(flag&(1u<<31)))
  250      Xorriso_result(xorriso,0);
  251    (*result)|= (1<<15);
  252  }
  253  if(fd1!=-1)
  254    close(fd1);
  255  if(! use_md5)
  256    Xorriso_iso_file_close(xorriso, &stream2, 0);
  257  if(was_error)
  258    {ret= -1; goto ex;}
  259  ret= 1;
  260 ex:;
  261  if(ctx != NULL)
  262    Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
  263  Xorriso_free_meM(buf1);
  264  Xorriso_free_meM(buf2);
  265  return(ret);
  266 }
  267 
  268 
  269 /*
  270    @param result  Bitfield indicationg type of mismatch
  271                bit0= disk_adr not existing
  272                bit1= iso_adr not existing
  273                bit2= access permissions
  274                bit3= file type 
  275                bit4= user id
  276                bit5= group id
  277                bit6= minor, major with device file
  278                bit7= size
  279                bit8= mtime
  280                bit9= atime
  281               bit10= ctime
  282               bit11= cannot open regular disk file
  283               bit12= cannot open iso file
  284               bit13= early eof of disk file
  285               bit14= early eof of iso file
  286               bit15= content bytes differ
  287               bit16= symbolic link on disk pointing to dir, dir in iso
  288               bit17= file chunks detected and compared
  289               bit18= incomplete chunk collection encountered
  290               bit19= ACL differs (this condition sets also bit2)
  291               bit20= xattr differ
  292               bit21= mismatch of recorded dev,inode
  293               bit22= no recorded dev,inode found in node
  294               bit23= timestamps younger than xorriso->isofs_st_in
  295               bit24= hardlink split
  296               bit25= hardlink fusion
  297    @param flag bit0= compare atime
  298                bit1= compare ctime
  299                bit2= check only existence of both file objects
  300                      count one or both missing as "difference"
  301               bit26= do not issue message about missing disk file
  302               bit27= for Xorriso_path_is_excluded(): bit0
  303               bit28= examine eventual disk_path link target rather than link
  304               bit29= do not issue pacifier messages
  305               bit30= omit adr_common_tail in report messages
  306               bit31= do not issue result messages
  307    @return     1=files match properly , 0=difference detected , -1=error
  308 */
  309 int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
  310                             char *iso_adr, char *adr_common_tail,
  311                             int *result, int flag)
  312 {
  313  struct stat s1, s2, stbuf;
  314  int ret, missing= 0, is_split= 0, i, was_error= 0, diff_count= 0;
  315  int content_shortcut= 0, mask;
  316  char *respt;
  317  char *a= NULL;
  318  char ttx1[40], ttx2[40];
  319  char *a1_acl= NULL, *a2_acl= NULL, *d1_acl= NULL, *d2_acl= NULL;
  320  char *attrlist1= NULL, *attrlist2= NULL;
  321  struct SplitparT *split_parts= NULL;
  322  int split_count= 0;
  323  time_t stamp;
  324 
  325  char *part_path= NULL, *part_name;
  326  int partno, total_parts= 0;
  327  off_t offset, bytes, total_bytes;
  328 
  329  Xorriso_alloc_meM(a, char, 5*SfileadrL);
  330  Xorriso_alloc_meM(part_path, char, SfileadrL);
  331  
  332  *result= 0;
  333  respt= xorriso->result_line;
  334 
  335  if(!(xorriso->disk_excl_mode&8)) {
  336    ret= Xorriso_path_is_excluded(xorriso, disk_adr, 2 | !!(flag&(1<<27)));
  337    if(ret>0) {
  338      strcpy(respt, "? ");
  339      Text_shellsafe(disk_adr, respt, 1);
  340      sprintf(respt + strlen(respt), " (DISK) : excluded by %s\n",
  341              (ret==1 ? "-not_paths" : "-not_leaf"));
  342      if(! (flag & ((1u << 31) | (1 << 26))))
  343        Xorriso_result(xorriso,0);
  344      missing= 1;
  345      (*result)|= 1;
  346    }
  347  }
  348  if(!missing) {
  349    if(flag&(1<<28))
  350      ret= stat(disk_adr, &s1);
  351    else
  352      ret= lstat(disk_adr, &s1);
  353    if(ret==-1) {
  354      strcpy(respt, "? ");
  355      Text_shellsafe(disk_adr, respt, 1);
  356      sprintf(respt + strlen(respt),
  357              " (DISK) : cannot lstat() : %s\n", strerror(errno));
  358      if(! (flag & ((1u << 31) | (1 << 26))))
  359        Xorriso_result(xorriso,0);
  360      missing= 1;
  361      (*result)|= 1;
  362    }
  363  }
  364  if(missing)
  365    strcpy(a, "?");
  366  else
  367    strcpy(a, Ftypetxt(s1.st_mode, 1));  
  368  strcat(a, " ");
  369  if(adr_common_tail[0])
  370    Text_shellsafe(adr_common_tail, a, 1);
  371  else {
  372    Text_shellsafe(disk_adr, a+strlen(a), 0);
  373    strcat(a, " (DISK)");
  374 /*
  375    strcat(a, "'.'");
  376 */
  377  }
  378  strcat(a, " :");
  379  if(flag&(1<<30))
  380    a[0]= 0;
  381 
  382  ret= Xorriso_iso_lstat(xorriso, iso_adr, &s2, 0);
  383  if(ret<0) {
  384    strcpy(respt, "? ");
  385    Text_shellsafe(iso_adr, respt, 1);
  386    strcat(respt, "  (ISO) : cannot find this file in ISO image\n");
  387    if(!(flag&(1u<<31)))
  388      Xorriso_result(xorriso,0);
  389    missing= 1;
  390    (*result)|= 2;
  391  }
  392 
  393  if((flag&4)||missing)
  394    {ret= !missing; goto ex;}
  395 
  396 
  397  /* Splitfile parts */
  398  if((S_ISREG(s1.st_mode) || S_ISBLK(s1.st_mode)) && S_ISDIR(s2.st_mode)) {
  399    is_split= Xorriso_identify_split(xorriso, iso_adr, NULL, &split_parts,
  400                                     &split_count, &s2, 0);
  401    if(is_split>0)
  402      (*result)|= (1<<17);
  403    else
  404      is_split= 0;
  405  }
  406 
  407  /* Attributes */
  408  if(s1.st_mode != s2.st_mode) {
  409    if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) {
  410      sprintf(respt, "%s st_mode  :  %7.7o  <>  %7.7o\n",
  411              a, (unsigned int) (s1.st_mode & ~S_IFMT),
  412                 (unsigned int) (s2.st_mode & ~S_IFMT));
  413      if(!(flag&(1u<<31)))
  414        Xorriso_result(xorriso,0);
  415      (*result)|= 4;
  416    }
  417 
  418    if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) {
  419      sprintf(respt, "%s type     :  %s  <>  %s\n",
  420              a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0));
  421      if(!(flag&(1u<<31)))
  422        Xorriso_result(xorriso,0);
  423      (*result)|= 8;
  424      if((s1.st_mode&S_IFMT) == S_IFLNK) {
  425        /* check whether link target type matches */
  426        ret= stat(disk_adr, &stbuf);
  427        if(ret!=-1)
  428          if(S_ISDIR(stbuf.st_mode) && S_ISDIR(s2.st_mode))
  429            (*result)|= (1<<16);
  430      }
  431    }
  432  }
  433 
  434  /* ACL */
  435  if(xorriso->do_aaip & 3) {
  436    Xorriso_local_getfacl(xorriso, disk_adr, &a1_acl,
  437                          16 | ((flag & (1 << 28)) >> 23));
  438    if(S_ISDIR(s1.st_mode))
  439      Xorriso_local_getfacl(xorriso, disk_adr, &d1_acl, 1);
  440    ret= Xorriso_getfacl(xorriso, NULL, iso_adr, &a2_acl, 1 | 4 | 16);
  441    if(ret < 0)
  442      goto ex;
  443    if(S_ISDIR(s1.st_mode)) {
  444      ret= Xorriso_getfacl(xorriso, NULL, iso_adr, &d2_acl, 1 | 8);
  445      if(ret < 0)
  446        goto ex;
  447    }
  448    ret= Compare_text_lines(a1_acl, a2_acl, &diff_count, 0);
  449    if(ret < 0)
  450      goto ex;
  451    if(ret == 0)
  452      (*result)|= 4 | (1 << 19);
  453    ret= Compare_text_lines(d1_acl, d2_acl, &diff_count, 1);
  454    if(ret < 0)
  455      goto ex;
  456    if(ret == 0)
  457      (*result)|= 4 | (1 << 19);
  458    if((*result) & (1 << 19)) {
  459      sprintf(respt, "%s ACL      :  %d difference%s\n",
  460              a, diff_count, diff_count == 1 ? "" : "s");
  461      if(!(flag&(1u<<31)))
  462        Xorriso_result(xorriso,0);
  463    }
  464  }
  465 
  466  /* xattr */
  467  if(xorriso->do_aaip & 12) {
  468    ret= Xorriso_getfattr(xorriso, NULL, disk_adr, &attrlist1,
  469                          1 | 2 | ((flag & (1 << 28)) >> 23));
  470    if(ret < 0)
  471      goto ex;
  472    ret= Xorriso_getfattr(xorriso, NULL, iso_adr, &attrlist2, 1);
  473    if(ret < 0)
  474      goto ex;
  475    ret= Compare_text_lines(attrlist1, attrlist2, &diff_count, 0);
  476    if(ret < 0)
  477      goto ex;
  478    if(ret == 0) {
  479      (*result)|= (1 << 20);
  480      sprintf(respt, "%s xattr    :  %d difference%s\n",
  481              a, diff_count, diff_count == 1 ? "" : "s");
  482      if(!(flag&(1u<<31)))
  483        Xorriso_result(xorriso,0);
  484    }
  485  }
  486 
  487  if(s1.st_uid != s2.st_uid) {
  488    sprintf(respt, "%s st_uid   :   %lu  <>  %lu\n", a,
  489            (unsigned long) s1.st_uid, (unsigned long) s2.st_uid);
  490    if(!(flag&(1u<<31)))
  491      Xorriso_result(xorriso,0);
  492    (*result)|= 16;
  493  }
  494  if(s1.st_gid != s2.st_gid) {
  495    sprintf(respt, "%s st_gid   :   %lu  <>  %lu\n", a,
  496            (unsigned long) s1.st_gid, (unsigned long) s2.st_gid);
  497    if(!(flag&(1u<<31)))
  498      Xorriso_result(xorriso,0);
  499    (*result)|= 32;
  500  }
  501  if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) ||
  502     (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) {
  503    if(s1.st_rdev != s2.st_rdev) {
  504      sprintf(respt, "%s %s st_rdev  :  %lu  <>  %lu\n", a,
  505             (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"),
  506             (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev);
  507      if(!(flag&(1u<<31)))
  508        Xorriso_result(xorriso,0);
  509      (*result)|= 64;
  510    }
  511  }
  512  if((!(xorriso->do_aaip & 32)) &&
  513     S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) {
  514    sprintf(respt, "%s st_size  :  %.f  <>  %.f      diff= %.f\n",
  515           a, (double) s1.st_size, (double) s2.st_size,
  516           ((double) s1.st_size) - (double) s2.st_size);
  517    if(!(flag&(1u<<31)))
  518      Xorriso_result(xorriso,0);
  519    (*result)|= 128;
  520  }
  521  if(s1.st_mtime != s2.st_mtime) {
  522    sprintf(respt, "%s st_mtime :  %s  <>  %s      diff= %.f s\n",
  523            a, Ftimetxt(s1.st_mtime, ttx1, 0),
  524               Ftimetxt(s2.st_mtime, ttx2, 0),
  525               ((double) s1.st_mtime) - (double) s2.st_mtime);
  526    if(!(flag&(1u<<31)))
  527      Xorriso_result(xorriso,0);
  528    (*result)|= 256;
  529  }
  530  if(flag&1) {
  531    if(s1.st_atime != s2.st_atime) {
  532      sprintf(respt, "%s st_atime :  %s  <>  %s      diff= %.f s\n",
  533              a, Ftimetxt(s1.st_atime, ttx1, 0), 
  534                 Ftimetxt(s2.st_atime, ttx2, 0),
  535                 ((double) s1.st_atime) - (double) s2.st_atime);
  536      if(!(flag&(1u<<31)))
  537        Xorriso_result(xorriso,0);
  538      (*result)|= 512;
  539    }
  540  }
  541  if(flag&2) {
  542    if(s1.st_ctime != s2.st_ctime) {
  543      sprintf(respt, "%s st_ctime :  %s  <>  %s      diff= %.f s\n",
  544              a, Ftimetxt(s1.st_ctime, ttx1, 0),
  545                 Ftimetxt(s2.st_ctime, ttx2, 0),
  546                 ((double) s1.st_ctime) - (double) s2.st_ctime);
  547      if(!(flag&(1u<<31)))
  548        Xorriso_result(xorriso,0);
  549      (*result)|= 1024;
  550    }
  551  }
  552  if(xorriso->isofs_st_in > 0 &&
  553     (xorriso->isofs_st_in <= s2.st_mtime ||
  554      ((flag & 1) && xorriso->isofs_st_in <= s2.st_atime) ||
  555      ((flag & 2) && xorriso->isofs_st_in <= s2.st_ctime)))
  556    (*result)|= 1 << 23;
  557 
  558  if((xorriso->do_aaip & 32) || !(xorriso->ino_behavior & 2)) {
  559    /* dev,inode comparison.
  560       For skipping content comparison or for hardlink detection.
  561    */
  562    ret= Xorriso_record_dev_inode(xorriso, "", s1.st_dev, s1.st_ino, NULL,
  563        iso_adr, 1 | 2 | ((flag & (1 << 28)) >> 23) | (xorriso->do_aaip & 128));
  564    if(ret < 0) {
  565      ret= -1; goto ex;
  566    } else if(ret == 0) { /* match */
  567      if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
  568        if(xorriso->do_aaip & 32)
  569          content_shortcut= 1;
  570        if((*result) & (8 | 128 | 256 | 512 | 1024 | (1 << 23))) {
  571          (*result)|= (1 << 15); /* content bytes differ */
  572          if(((*result) & (1 << 23)) &&
  573             !((*result) & (8 | 128 | 256 | 512 | 1024))) {
  574            sprintf(respt,
  575             "%s content  :  node timestamp younger than image timestamp\n", a);
  576            if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  577              Xorriso_result(xorriso,0);
  578            stamp= s2.st_mtime;
  579            if((flag & 1) && s2.st_atime >= stamp)
  580              stamp= s2.st_atime;
  581            if((flag & 2) && s2.st_ctime >= stamp)
  582              stamp= s2.st_ctime;
  583            sprintf(respt, "%s content  :  %s  >  %s    diff= %.f s\n",
  584                    a, Ftimetxt(stamp, ttx1, 3 << 1),
  585                    Ftimetxt(xorriso->isofs_st_in, ttx2, 3 << 1),
  586                    ((double) stamp) - (double) xorriso->isofs_st_in);
  587            if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  588              Xorriso_result(xorriso,0);
  589          }
  590          sprintf(respt,
  591           "%s content  :  assuming inequality due to size or timestamps\n", a);
  592          if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  593            Xorriso_result(xorriso,0);
  594        }
  595      }
  596    } else if(ret == 1) { /* mismatch */
  597      (*result)|= (1 << 21);
  598      sprintf(respt, "%s dev_ino  :  differing\n", a);
  599      if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  600        Xorriso_result(xorriso,0);
  601 
  602      if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
  603        if(xorriso->do_aaip & 32)
  604          content_shortcut= 1;
  605        (*result)|= (1 << 15); /* content bytes differ */
  606        sprintf(respt,
  607              "%s content  :  assuming inequality after dev_ino mismatch\n", a);
  608        if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  609          Xorriso_result(xorriso,0);
  610      }
  611    } else {
  612      sprintf(respt, "%s dev_ino  :  no dev_ino stored with image node\n", a);
  613      if((xorriso->do_aaip & 32) && !(flag&(1u<<31)))
  614        Xorriso_result(xorriso,0);
  615      (*result)|= (1 << 22);
  616    }
  617  }
  618 
  619  if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode) && !content_shortcut) {
  620    /* Content */
  621    if(is_split) { 
  622      for(i= 0; i<split_count; i++) {
  623        Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
  624                       &offset, &bytes, &total_bytes, 0);
  625        strcpy(part_path, iso_adr);
  626        if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
  627          Xorriso_much_too_long(xorriso, strlen(iso_adr)+strlen(part_name)+1,
  628                                2);
  629          {ret= -1; goto ex;}
  630        }
  631        ret= Xorriso_iso_lstat(xorriso, part_path, &stbuf, 0);
  632        if(ret<0)
  633      continue;
  634        ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size,
  635                                        offset, bytes,
  636                                        part_path, stbuf.st_size, result,
  637                        (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1u<<31))));
  638        if(ret<0)
  639          was_error= 1;
  640      }
  641      if(total_parts>0 && split_count!=total_parts) {
  642        sprintf(xorriso->info_text,
  643                "- %s/* (ISO) : Not all split parts present (%d of %d)\n",
  644                iso_adr, split_count, total_parts);
  645        if(!(flag&(1u<<31)))
  646          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 1);
  647        (*result)|= 1<<18;
  648      }
  649    } else {
  650      ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size,
  651                                      (off_t) 0, s1.st_size,
  652                                      iso_adr, s2.st_size, result,
  653                        (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1u<<31))));
  654      if(ret<0)
  655        was_error= 1;
  656    }
  657 
  658  }
  659  if(was_error)
  660    ret= -1;
  661  else {
  662    mask= ~((1 << 17) | (1 << 18) | (1 << 22) | (1 << 23));
  663    if(xorriso->do_aaip & 32)
  664      mask|= 1 << 22;
  665    ret= (((*result) & mask)==0);
  666  }
  667 ex:;
  668  if(split_parts!=NULL)
  669    Splitparts_destroy(&split_parts, split_count, 0);
  670  Xorriso_local_getfacl(xorriso, disk_adr, &a1_acl, 1 << 15);
  671  Xorriso_local_getfacl(xorriso, disk_adr, &d1_acl, 1 << 15);
  672  if(a2_acl != NULL)
  673    free(a2_acl);
  674  if(d2_acl != NULL)
  675    free(d2_acl);
  676  if(attrlist1 != NULL)
  677    free(attrlist1);
  678  if(attrlist2 != NULL)
  679    free(attrlist2);
  680  Xorriso_free_meM(part_path);
  681  Xorriso_free_meM(a);
  682  return(ret);
  683 }
  684 
  685 
  686 int Xorriso_pfx_disk_path(struct XorrisO *xorriso, char *iso_path,
  687                           char *iso_prefix, char *disk_prefix,
  688                           char disk_path[SfileadrL], int flag)
  689 {
  690  int ret;
  691  char *adrc= NULL;
  692 
  693  Xorriso_alloc_meM(adrc, char, SfileadrL);
  694 
  695  if(strncmp(iso_path, iso_prefix, strlen(iso_prefix))!=0)
  696    {ret= -1; goto ex;}
  697  if(strlen(disk_prefix) + strlen(iso_path) - strlen(iso_prefix)+1 >= SfileadrL)
  698    {ret= -1; goto ex;}
  699  if(iso_path[strlen(iso_prefix)] == '/')
  700    strcpy(adrc, iso_path + strlen(iso_prefix) + 1);
  701  else
  702    strcpy(adrc, iso_path + strlen(iso_prefix));
  703  ret= Xorriso_make_abs_adr(xorriso, disk_prefix, adrc, disk_path, 4 | 8);
  704  if(ret <= 0)
  705    goto ex;
  706  ret= 1;
  707 ex:;
  708  Xorriso_free_meM(adrc);
  709  return(ret);
  710 }
  711 
  712 
  713 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
  714                     Set to NULL if calling this function from outside ISO world
  715    @param flag bit0= update rather than compare
  716                bit1= find[ix] is in recursion
  717                bit2= update_merge : do not delete but mark visited and found
  718    @return <=0 error, 1= ok , 2= iso_path was deleted
  719              3=ok, do not dive into directory (e.g. because it is a split file)
  720 */
  721 int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, void *node,
  722                          char *iso_path, char *iso_prefix, char *disk_prefix,
  723                          int flag)
  724 {
  725  int ret, result, uret, follow_links, deleted= 0;
  726  char *disk_path= NULL;
  727 
  728  Xorriso_alloc_meM(disk_path, char, SfileadrL);
  729 
  730  ret= Xorriso_pfx_disk_path(xorriso, iso_path, iso_prefix, disk_prefix,
  731                             disk_path, 0);
  732  if(ret <= 0)
  733    goto ex;
  734 
  735  /* compare exclusions against disk_path resp. leaf name */
  736  if(xorriso->disk_excl_mode&8)
  737    ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&2));
  738  else
  739    ret= 0;
  740  if(ret<0)
  741    goto ex;
  742  if(ret>0)
  743    {ret= 3; goto ex;}
  744 
  745  follow_links= (xorriso->do_follow_links ||
  746                (xorriso->do_follow_param && !(flag&2))) <<28;
  747  ret= Xorriso_compare_2_files(xorriso, disk_path, iso_path, "", &result,
  748                         2 | follow_links | ((!!(flag & 4)) << 26)
  749                         | ((!(flag&2))<<27) | (((unsigned)(flag&1))<<31));
  750                                             /* was once: | ((!(flag&1))<<29) */
  751  if(ret<xorriso->find_compare_result)
  752    xorriso->find_compare_result= ret;
  753  if(flag&1) {
  754    if(ret<0)
  755      if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
  756        goto ex;
  757    if(ret > 0)
  758      result= 0;
  759    uret= Xorriso_update_interpreter(xorriso, boss_iter, node, result,
  760                                     disk_path, iso_path,
  761                                     ((flag & 2) << 1) | ((flag & 4) >> 1));
  762    if(uret<=0)
  763      ret= 0;
  764    if(uret==2)
  765      deleted= 1;
  766  }
  767  if(ret<0)
  768    goto ex;
  769  if(deleted)
  770    {ret= 2; goto ex;}
  771  if(result&(1<<17))
  772    {ret= 3; goto ex;}
  773 ex:;
  774  Xorriso_free_meM(disk_path);
  775  return(ret);
  776 }
  777 
  778 
  779 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
  780                     Set to NULL if calling this function from outside ISO world
  781    @param flag      bit0= widen hardlink sibling:
  782                           Do not call Xorriso_hardlink_update()
  783                           Overwrite exactly if normal mode would not,
  784                           else do nothing
  785                     bit1= do not delete files which are not found under
  786                           disk_path, but rather mark visited files and mark
  787                           files which were found.
  788                     bit2= -follow: this is not a command parameter 
  789    @return <=0 error, 1= ok , 2= iso_rr_path node object has been deleted ,
  790                       3= no action taken
  791 */
  792 int Xorriso_update_interpreter(struct XorrisO *xorriso,
  793                                void *boss_iter, void *node,
  794                                int compare_result, char *disk_path,
  795                                char *iso_rr_path, int flag)
  796 {
  797  int ret= 1, deleted= 0, is_split= 0, i, loop_count, late_hardlink_update= 0;
  798  struct stat stbuf;
  799  struct SplitparT *split_parts= NULL;
  800  int split_count= 0;
  801  char *part_path= NULL, *part_name;
  802  int partno, total_parts, new_total_parts, added_overwrote= 0;
  803  off_t offset, bytes, total_bytes, disk_size, first_bytes, du_size;
  804 
  805  if((compare_result&3)==3) {
  806    sprintf(xorriso->info_text, "Missing on disk and in ISO: disk_path ");
  807    Text_shellsafe(disk_path, xorriso->info_text, 1);
  808    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
  809    xorriso->find_compare_result= -1;
  810    ret= 3; goto ex;
  811  }
  812 
  813  Xorriso_alloc_meM(part_path, char, SfileadrL);
  814 
  815  if((flag & 2) && !(compare_result & 2)) {
  816    ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, node,
  817                                   !(compare_result & 1));
  818    if(ret <= 0)
  819      goto ex;
  820  }
  821  if(compare_result == 0)
  822    {ret= 1; goto ex;}
  823 
  824  if(compare_result&((1<<11)|(1<<13))) {
  825    if(flag & 1)
  826      {ret= 3; goto ex;}
  827    /* cannot open regular disk file, early eof of disk file */
  828    sprintf(xorriso->info_text, "Problems with reading disk file ");
  829    Text_shellsafe(disk_path, xorriso->info_text, 1);
  830    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
  831    xorriso->find_compare_result= -1;
  832    ret= 1; goto ex;
  833  }
  834  xorriso->info_text[0]= 0;
  835  is_split= !!(compare_result & (1<<17));
  836 
  837  if((!(xorriso->ino_behavior & 2)) && (compare_result & (2 | (3 << 21))) &&
  838     !(flag & 1)) {
  839    if(compare_result & 2) {
  840      /* File is not yet in image */
  841      late_hardlink_update= 1;
  842    } else {
  843      /* Hard link relation has changed resp. was not recorded. */
  844      ret= Xorriso_hardlink_update(xorriso, &compare_result,
  845                             disk_path, iso_rr_path,
  846                             (flag & 4) | ((compare_result >> 21) & 2));
  847      if(ret < 0)
  848        goto ex;
  849      if(ret == 2)
  850        {ret= 1; goto ex;}
  851    }
  852  }
  853 
  854  if(compare_result&(8|64)) {
  855    /* file type, minor+major with device file */
  856    if(flag & 1)
  857      {ret= 3; goto ex;}
  858    ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */
  859    if(ret>0) {
  860      deleted= 1; 
  861      ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
  862                            (off_t) 0, (off_t) 0, 2|(flag&4));
  863      if(ret <= 0)
  864        goto ex;
  865      if(flag & 2) {
  866        ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, NULL, 1);
  867        if(ret <= 0)
  868          goto ex;
  869      }
  870    }
  871    sprintf(xorriso->info_text, "Deleted and re-added ");
  872 
  873  } else if(compare_result&(1)) {
  874 delete:;
  875    /* disk_adr not existing */
  876    if(!(flag & 2)) {
  877      ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1);
  878      deleted= 1;
  879      sprintf(xorriso->info_text, "Deleted ");
  880    }
  881 
  882  } else if(compare_result&(2|128|(1<<12)|(1<<14)|(1<<15))) {
  883    /* iso_adr not existing, size, cannot open iso file, early eof of iso file
  884       content bytes differ */
  885 
  886    if(flag & 1)
  887      {ret= 3; goto ex;}
  888 overwrite:;
  889    if(is_split) {
  890      ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
  891                                  &split_parts, &split_count, &stbuf, 0);
  892      if(ret<=0)
  893        {ret= -1; goto ex;}  /* (should not happen) */
  894      ret= lstat(disk_path, &stbuf);
  895      if(ret==-1)
  896        goto delete;
  897      disk_size= stbuf.st_size;
  898      Splitparts_get(split_parts, 0, &part_name, &partno, &total_parts,
  899                     &offset, &first_bytes, &total_bytes, 0);
  900      new_total_parts= disk_size/first_bytes;
  901      if(disk_size % first_bytes)
  902        new_total_parts++;
  903 
  904      loop_count= split_count;
  905      /* If disk file grew over part limit and all parts are present:
  906         add new parts */
  907      if(new_total_parts > total_parts && split_count == total_parts)
  908        loop_count= new_total_parts;
  909 
  910      for(i= 0; i<loop_count; i++) {
  911        if(i<split_count) {
  912          /* Delete old part */
  913          Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
  914                        &offset, &bytes, &total_bytes, 0);
  915          strcpy(part_path, iso_rr_path);
  916          if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
  917            Xorriso_much_too_long(xorriso,
  918                                  strlen(iso_rr_path)+strlen(part_path)+1, 2);
  919            {ret= -1; goto ex;}
  920          }
  921          ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, part_path, 1);
  922          if(ret<=0)
  923            goto ex;
  924          deleted= 1;
  925        } else {
  926          partno= i+1;
  927          offset= i*first_bytes;
  928          bytes= first_bytes;
  929        }
  930        if(disk_size<=offset)
  931      continue;
  932        /* Insert new part */
  933        if(strlen(part_path)+160>SfileadrL) {
  934          Xorriso_much_too_long(xorriso, strlen(part_path)+160, 2);
  935          ret= 0; goto ex;
  936        }
  937        Splitpart__compose(part_path+strlen(iso_rr_path)+1, partno,
  938                           new_total_parts, offset, first_bytes, disk_size, 0);
  939        ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, part_path,
  940                              offset, bytes, 2|(flag&4)|8|128);
  941        if(ret<=0)
  942          goto ex;
  943      }
  944      /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */
  945      ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2 | 4);
  946      if(ret<=0)
  947        goto ex;
  948    } else {
  949      ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
  950                            (off_t) 0, (off_t) 0, 2|(flag&4));
  951      if(ret>0 && !(compare_result&2))
  952        deleted= 1;
  953    }
  954    if(late_hardlink_update) {
  955      /* Handle eventual hardlink siblings of newly created file */
  956      ret= Xorriso_hardlink_update(xorriso, &compare_result,
  957                                   disk_path, iso_rr_path, 1 | (flag & 4));
  958      if(ret < 0)
  959        goto ex;
  960    }
  961    if(flag & 2) {
  962      ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, NULL, 1);
  963      if(ret <= 0)
  964        goto ex;
  965    }
  966    if(flag & 1) {
  967      sprintf(xorriso->info_text, "Widened hard link ");
  968    } else {
  969      sprintf(xorriso->info_text, "Added/overwrote ");
  970      added_overwrote= 1;
  971    }
  972 
  973  } else if(compare_result&(4|16|32|256|512|1024|(1<<19)|(1<<20)|(1<<22))) {
  974    /* access permissions, user id, group id, mtime, atime, ctime, ACL, xattr,
  975       dev_ino missing */
  976 
  977    if(flag & 1)
  978      goto overwrite;
  979 
  980    if(is_split) {
  981      ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
  982                                  &split_parts, &split_count, &stbuf, 0);
  983      if(ret<=0)
  984        {ret= -1; goto ex;}  /* (should not happen) */
  985      for(i= 0; i<split_count; i++) {
  986        Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
  987                      &offset, &bytes, &total_bytes, 0);
  988        strcpy(part_path, iso_rr_path);
  989        if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
  990          Xorriso_much_too_long(xorriso,
  991                                strlen(iso_rr_path)+strlen(part_path)+1, 2);
  992          {ret= -1; goto ex;}
  993        }
  994        ret= Xorriso_copy_properties(xorriso, disk_path, part_path,
  995                                     4 * !(compare_result & (1<<21))); 
  996                              /* do not update eventually mismatching dev_ino */
  997        if(ret<=0)
  998          goto ex;
  999      }
 1000      /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */
 1001      ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2 | 4); 
 1002      if(ret<=0)
 1003        goto ex;
 1004    } else
 1005      ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 4); 
 1006    sprintf(xorriso->info_text, "Adjusted attributes of ");
 1007 
 1008  } else if(flag & 1) {
 1009      goto overwrite;
 1010  } else
 1011    ret= 1;
 1012  if(ret>0 && xorriso->info_text[0]) {
 1013    Text_shellsafe(iso_rr_path, xorriso->info_text, 1);
 1014    if(added_overwrote) {
 1015      ret= Xorriso_iso_lstat(xorriso, iso_rr_path, &stbuf, 0);
 1016      if(ret == 0 && S_ISREG(stbuf.st_mode)) {
 1017        strcat(xorriso->info_text, "  (");
 1018        Sfile_scale((double) stbuf.st_size,
 1019                    xorriso->info_text + strlen(xorriso->info_text), 5, 1e4,
 1020                    1 | 2);
 1021        strcat(xorriso->info_text, ")");
 1022      } else if (ret == 0 && S_ISDIR(stbuf.st_mode)) {
 1023        ret= Xorriso_get_dus(xorriso, iso_rr_path, &du_size, (off_t) 0, 0);
 1024        if(ret > 0 && du_size > 0) {
 1025          strcat(xorriso->info_text, "  (");
 1026          Sfile_scale((double) du_size,
 1027                      xorriso->info_text + strlen(xorriso->info_text), 5, 1e4,
 1028                      1 | 2);
 1029          strcat(xorriso->info_text, ")");
 1030        }
 1031      }
 1032    }
 1033    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1034  }
 1035  ret= 1;
 1036 ex:;
 1037  if(split_parts!=NULL)
 1038    Splitparts_destroy(&split_parts, split_count, 0);
 1039  Xorriso_free_meM(part_path);
 1040  if(ret<=0)
 1041    return(ret);
 1042  if(deleted)
 1043    return(2);
 1044  return(ret);
 1045 }
 1046