"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.6/xorriso/read_run.c" (30 May 2022, 87591 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. For more information about "read_run.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.4_vs_1.5.6.

    1 
    2 
    3 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    4 
    5    Copyright 2007-2022 Thomas Schmitt, <scdbackup@gmx.net>
    6 
    7    Provided under GPL version 2 or later.
    8 
    9    This file contains functions which are needed to read data
   10    from ISO image.
   11 */
   12 
   13 #ifdef HAVE_CONFIG_H
   14 #include "../config.h"
   15 #endif
   16 
   17 #include <ctype.h>
   18 #include <sys/types.h>
   19 #include <unistd.h>
   20 #include <stdlib.h>
   21 #include <stdio.h>
   22 #include <string.h>
   23 #include <sys/stat.h>
   24 #include <sys/time.h>
   25 #include <time.h>
   26 #include <errno.h>
   27 
   28 #include <fcntl.h>
   29 #include <utime.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 
   37 #include "lib_mgt.h"
   38 #include "drive_mgt.h"
   39 #include "iso_img.h"
   40 #include "iso_tree.h"
   41 #include "iso_manip.h"
   42 #include "read_run.h"
   43 #include "sort_cmp.h"
   44 #include "disk_ops.h"
   45 
   46 
   47 int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource)
   48 {
   49  struct XorrisO *xorriso;
   50 
   51  xorriso= (struct XorrisO *) iso_image_get_attached_data(image);
   52  if(xorriso==NULL)
   53    return(1);
   54  Xorriso_process_msg_queues(xorriso,0);
   55  xorriso->pacifier_count++;
   56  if(xorriso->pacifier_count%10)
   57    return(1);
   58  Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0,
   59                            "", 0);
   60  return(1);
   61 }
   62 
   63 
   64 /* @param flag bit0= open IsoNode *node_pt rather than looking up pathname
   65                bit1= dig out the most original stream for reading
   66 */
   67 int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname,
   68                           void *node_pt, void **stream, int flag)
   69 {
   70  int ret;
   71  char *eff_path= NULL;
   72  IsoNode *node= NULL;
   73  IsoFile *filenode= NULL;
   74  IsoStream *iso_stream= NULL, *input_stream;
   75 
   76  Xorriso_alloc_meM(eff_path, char, SfileadrL);
   77 
   78  *stream= NULL;
   79  if(flag&1) {
   80    node= (IsoNode *) node_pt;
   81  } else {
   82    ret= Xorriso_get_node_by_path(xorriso, pathname, eff_path, &node, 0);
   83    if(ret<=0)
   84      goto ex;
   85  }
   86  if(!LIBISO_ISREG(node)) {
   87    sprintf(xorriso->info_text,
   88            "Given path does not lead to a regular data file in the image");
   89    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   90    {ret= 0; goto ex;}
   91  }
   92 
   93  filenode= (IsoFile *) node;
   94  iso_stream= iso_file_get_stream(filenode);
   95  if(iso_stream==NULL) {
   96    Xorriso_process_msg_queues(xorriso,0);
   97    sprintf(xorriso->info_text,
   98            "Could not obtain source stream of file in the image for reading");
   99    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  100    {ret= 0; goto ex;}
  101  }
  102  if(flag & 2) {
  103    /* Dig out the most original stream */
  104    while(1) {
  105      input_stream= iso_stream_get_input_stream(iso_stream, 0);
  106      if(input_stream == NULL)
  107    break;
  108      iso_stream= input_stream;
  109    }
  110  }
  111  if(!iso_stream_is_repeatable(iso_stream)) {
  112    sprintf(xorriso->info_text,
  113            "The data production of the file in the image is one-time only");
  114    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  115    {ret= 0; goto ex;}
  116  }
  117  ret= iso_stream_open(iso_stream);
  118  if(ret<0) {
  119    sprintf(xorriso->info_text,
  120            "Could not open data file in the image for reading");
  121    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  122    {ret= 0; goto ex;}
  123  }
  124  Xorriso_process_msg_queues(xorriso,0);
  125  *stream= iso_stream;
  126 
  127 #ifdef NIX
  128  /* <<< */
  129  {
  130    unsigned int fs_id;
  131    dev_t dev_id;
  132    ino_t ino;
  133 
  134    iso_stream_get_id(iso_stream, &fs_id, &dev_id, &ino);
  135    fprintf(stderr, "xorriso_debug: iso_ino= %ld\n", (long int) ino);
  136  }
  137 #endif
  138 
  139  ret= 1;
  140 ex:;
  141  Xorriso_free_meM(eff_path);
  142  return(ret);
  143 }
  144 
  145 
  146 int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf,
  147                           int count, int flag)
  148 {
  149  int ret, rcnt= 0;
  150  IsoStream *stream_pt;
  151 
  152  stream_pt= (IsoStream *) stream;
  153 
  154  while(rcnt<count) {
  155    ret= iso_stream_read(stream_pt, (void *) (buf+rcnt), (size_t) (count-rcnt));
  156    if(ret==0) /* EOF */
  157  break;
  158    if(ret<0) { /* error */
  159      Xorriso_process_msg_queues(xorriso,0);
  160      Xorriso_report_iso_error(xorriso, "", ret, "Error on read",
  161                               0, "FAILURE", 1 | ((ret == -1)<<2) );
  162      return(-1);
  163    }
  164    rcnt+= ret;
  165  }
  166  return(rcnt);
  167 }
  168 
  169 
  170 int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag)
  171 {
  172  int ret;
  173 
  174  if(*stream==NULL)
  175    return(0);
  176  ret= iso_stream_close(*stream);
  177  if(ret==1)
  178    *stream= NULL;
  179  Xorriso_process_msg_queues(xorriso,0);
  180  return(ret);
  181 }
  182 
  183 
  184 /* @param flag bit0= in_node is valid, do not resolve img_path
  185                bit1= test mode: print DEBUG messages
  186    @return  <0 = error,
  187              0 = surely not identical regular files ,
  188              1 = surely identical
  189              2 = potentially depending on unknown disk file (e.g. -cut_out)
  190 */
  191 int Xorriso_restore_is_identical(struct XorrisO *xorriso, void *in_node,
  192                                  char *img_path, char *disk_path,
  193                                  char type_text[5], int flag)
  194 {
  195  int ret;
  196  unsigned int fs_id;
  197  dev_t dev_id;
  198  ino_t ino_id;
  199  IsoStream *stream;
  200  IsoImage *volume;
  201  IsoNode *node;
  202  struct stat stbuf;
  203  int dummy;
  204 
  205  memset(type_text, 0, 5);
  206  if(!Xorriso_change_is_pending(xorriso, 0))
  207    return(0);
  208  if(flag&1) {
  209    node= (IsoNode *) in_node;
  210  } else {
  211    ret= Xorriso_get_volume(xorriso, &volume, 0);
  212    if(ret<=0)
  213      return(-1);
  214    ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
  215    if(ret<=0)
  216      return(-1);
  217  }
  218  ret= Xorriso__file_start_lba(node, &dummy, 0);
  219  if(ret != 0) {
  220    Xorriso_process_msg_queues(xorriso, 0);
  221    return(0);
  222  }
  223  if(!LIBISO_ISREG(node))
  224    return(0);
  225  stream= iso_file_get_stream((IsoFile *) node);
  226  memcpy(type_text, stream->class->type, 4);
  227  iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
  228  if(flag&2) {
  229    sprintf(xorriso->info_text, "%s : fs=%d  dev=%.f  ino=%.f  (%s)",
  230            img_path, fs_id, (double) dev_id, (double) ino_id, type_text);
  231    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  232  }
  233  ret= stat(disk_path, &stbuf);
  234  if(ret==-1)
  235    return(0);
  236  if(flag&2) {
  237    sprintf(xorriso->info_text, "%s :       dev=%.f  ino=%.f",
  238            disk_path, (double) stbuf.st_dev, (double) stbuf.st_ino);
  239    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  240  }
  241  if(fs_id!=1)
  242    return(2);
  243 
  244  /* >>> obtain underlying dev_t ino_t of type "cout" */;
  245 
  246  if(strcmp(type_text, "fsrc")!=0)
  247    return(2);
  248  if(stbuf.st_dev==dev_id && stbuf.st_ino==ino_id)
  249    return(1);
  250  return(0);
  251 }
  252 
  253 
  254 int Xorriso_iso_file_to_fd(struct XorrisO *xorriso, char *path, int fd, 
  255                            int flag)
  256 {
  257  int ret, rret, wret, to_write, wanted;
  258  void *stream= NULL;
  259  char *buffer= NULL, *wpt;
  260  off_t todo;
  261  static int buffer_size= 64 * 1024;
  262 
  263  Xorriso_alloc_meM(buffer, char, buffer_size);
  264 
  265  ret= Xorriso_iso_file_open(xorriso, path, NULL, &stream, 0);
  266  if(ret <= 0)
  267    goto ex;
  268 
  269  todo= iso_stream_get_size((IsoStream *) stream);
  270  while(todo > 0) {
  271    if(todo < buffer_size)
  272      wanted= todo;
  273    else 
  274      wanted= buffer_size;
  275    rret = Xorriso_iso_file_read(xorriso, stream, buffer, wanted, 0);
  276    if(rret <= 0)
  277      {ret= -1; goto ex;}
  278    todo-= rret;
  279    wpt= buffer;
  280    for(to_write= rret; to_write > 0;) {
  281      wret= write(fd, wpt, to_write);
  282      if(wret <= 0) {
  283        if(wret == 0)
  284          sprintf(xorriso->info_text,
  285                  "Strange behavior of write(2): return == 0 with ");
  286        else
  287          sprintf(xorriso->info_text, "Write error with ");
  288        Text_shellsafe(path, xorriso->info_text, 1);
  289        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text,
  290                            wret == 0 ? 0 : errno, "FAILURE",0);
  291        ret= 0; goto ex;
  292      }
  293      to_write-= wret;
  294      wpt+= wret;
  295    }
  296  }
  297  ret= 1;
  298 ex:;
  299  if(stream != NULL)
  300    Xorriso_iso_file_close(xorriso, &stream, 0);
  301  Xorriso_free_meM(buffer);
  302  return(ret);
  303 }
  304 
  305 
  306 /* @param flag bit0= minimal transfer: access permissions only
  307                bit1= keep directory open: keep owner, allow rwx for owner
  308                      and push directory onto xorriso->perm_stack
  309 */
  310 int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path,
  311                                 IsoNode *node, int flag)
  312 {
  313  int ret, is_dir= 0, errno_copy= 0, local_attrs_set= 0, i, err_count;
  314  mode_t mode;
  315  uid_t uid, disk_uid;
  316  gid_t gid, disk_gid;
  317  struct utimbuf utime_buffer;
  318  struct stat stbuf;
  319  size_t num_attrs= 0, *value_lengths= NULL;
  320  char **names= NULL, **values= NULL;
  321  int *errnos= NULL;
  322 
  323  ret= lstat(disk_path, &stbuf);
  324  if(ret==-1) {
  325    sprintf(xorriso->info_text,
  326            "Cannot obtain properties of disk file ");
  327    Text_shellsafe(disk_path, xorriso->info_text, 1);
  328    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  329    {ret= 0; goto ex;}
  330  }
  331  disk_uid= uid= stbuf.st_uid;
  332  disk_gid= stbuf.st_gid;
  333 
  334  is_dir= S_ISDIR(stbuf.st_mode);
  335 
  336  mode= iso_node_get_permissions(node);
  337 
  338  if(xorriso->do_aaip & (2 | 8 | 16)) {
  339    ret= iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 
  340            (!!(xorriso->do_aaip & 2)) | (!(xorriso->do_aaip & (8 | 16))) << 2);
  341    if (ret < 0) {
  342      strcpy(xorriso->info_text, "Error with obtaining ACL and xattr for ");
  343      Text_shellsafe(disk_path, xorriso->info_text, 1);
  344      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  345      {ret= 0; goto ex;}
  346    }
  347    if(num_attrs > 0) {
  348      Xorriso_alloc_meM(errnos, int, num_attrs);
  349      ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
  350                                     values, errnos,
  351                                     ((!(xorriso->do_strict_acl & 1)) << 6) |
  352                                     ((!!(xorriso->do_aaip & 1024)) << 3) );
  353      if(ret < 0) {
  354 cannot_set_xattr:;
  355        errno_copy= errno;
  356        if(ret != (int) ISO_AAIP_NO_SET_LOCAL)
  357          errno_copy= 0;
  358        Xorriso_report_iso_error(xorriso, "", ret,
  359                                 "Error on iso_local_set_attrs",
  360                                 0, "FAILURE", 1 | ((ret == -1)<<2) );
  361        sprintf(xorriso->info_text, "Disk file ");
  362        Text_shellsafe(disk_path, xorriso->info_text, 1);
  363        err_count= 0;
  364        for(i= 0; (unsigned int) i < num_attrs; i++) {
  365          if(errnos[i] == 0)
  366        continue;
  367          if(err_count >= 3) {
  368            strcat(xorriso->info_text, " , and more");
  369        break;
  370          }
  371          err_count++;
  372          errno_copy= 0; /* Detail errno overrides final errno */
  373          if(names[i][0] == 0)
  374            sprintf(xorriso->info_text + strlen(xorriso->info_text), " , ACL ");
  375          else
  376            sprintf(xorriso->info_text + strlen(xorriso->info_text),
  377                    " , xattr %s ", names[i]);
  378          if(errnos[i] < 0)
  379            Text_shellsafe("Unknown error", xorriso->info_text, 1);
  380          else
  381            Text_shellsafe(strerror(errnos[i]), xorriso->info_text, 1);
  382        }
  383        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno_copy,
  384                            "FAILURE",0);
  385        {ret= 0; goto ex;}
  386      }
  387      local_attrs_set= 1;
  388    }
  389    Xorriso_process_msg_queues(xorriso,0);
  390  }
  391  if(!(xorriso->do_aaip & 2))
  392    mode= iso_node_get_perms_wo_acl(node);
  393 
  394  if(is_dir && (flag&2)) {
  395    ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node,
  396                            1 | ((!!(xorriso->do_aaip & 2)) << 3));
  397    if(ret<=0)
  398      {ret= 0; goto ex;}
  399    ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0);
  400    if(ret<=0) {
  401      Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  402      strcpy(xorriso->info_text,
  403             "Cannot memorize permissions for disk directory");
  404      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  405      {ret= -1; goto ex;}
  406    }
  407    mode|= S_IRUSR|S_IWUSR|S_IXUSR;
  408  }
  409  ret= chmod(disk_path, mode);
  410  if(ret==-1) {
  411 cannot_set_perm:;
  412    sprintf(xorriso->info_text,
  413            "Cannot change access permissions of disk file ");
  414    Text_shellsafe(disk_path, xorriso->info_text, 1);
  415    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  416    {ret= 0; goto ex;}
  417  }
  418 
  419  if(flag&1)
  420    {ret= 1; goto ex;}
  421 
  422  utime_buffer.actime= iso_node_get_atime(node);
  423  utime_buffer.modtime= iso_node_get_mtime(node);
  424  ret= utime(disk_path,&utime_buffer);
  425  if(ret==-1) {
  426    sprintf(xorriso->info_text,
  427            "Cannot change atime, mtime of disk file ");
  428    Text_shellsafe(disk_path, xorriso->info_text, 1);
  429    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  430    {ret= 0; goto ex;}
  431  }
  432  
  433  gid= iso_node_get_gid(node);
  434  if(!(S_ISDIR(stbuf.st_mode) && (flag&2)))
  435    uid= iso_node_get_uid(node);
  436 
  437  if(uid != disk_uid || gid != disk_gid) {
  438 
  439    ret= chown(disk_path, uid, gid); /* don't complain if it fails */
  440 
  441    /* Check whether xattr are still set and try to set them again if needed.
  442       E.g. Linux 3.16 removes security.capability on chown(2).
  443     */
  444    if(local_attrs_set && (xorriso->do_aaip & 1024)) {
  445      ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
  446                                     values, errnos,
  447                                     1 | ((!!(xorriso->do_aaip & 1024)) << 3) |
  448                                     128);
  449      if(ret < 0)
  450        goto cannot_set_xattr;
  451    }
  452 
  453    /* Check whether setuid or setgid bits got reset */
  454    ret= lstat(disk_path, &stbuf);
  455    if(ret != -1) {
  456      if((mode ^ stbuf.st_mode) & (S_ISUID | S_ISGID)) {
  457        ret= chmod(disk_path, mode);
  458        if(ret==-1)
  459          goto cannot_set_perm;
  460      }
  461    }
  462 
  463  }
  464  ret= 1;
  465 ex:;
  466  iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values,1 << 15);
  467  if(errnos != NULL)
  468    free(errnos);
  469  return(ret);
  470 }
  471 
  472 
  473 /* @param flag
  474                bit1= minimal transfer: access permissions only
  475                bit2= keep directory open: keep owner, allow rwx for owner
  476                      push to xorriso->perm_stack
  477 */
  478 int Xorriso_restore_implicit_properties(struct XorrisO *xorriso,
  479           char *full_disk_path, char *disk_path, char *full_img_path, int flag)
  480 {
  481  int ret, nfic, ndc, nfdc, d, i;
  482  char *nfi= NULL, *nd= NULL, *nfd= NULL, *cpt;
  483  struct stat stbuf;
  484  IsoNode *node;
  485 
  486  Xorriso_alloc_meM(nfi, char, SfileadrL);
  487  Xorriso_alloc_meM(nd, char, SfileadrL);
  488  Xorriso_alloc_meM(nfd, char, SfileadrL);
  489 
  490  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd,
  491                                  1|2|4);
  492  if(ret<=0)
  493    goto ex;
  494  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, nd, 1|2);
  495  if(ret<=0)
  496    goto ex;
  497  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi,
  498                                  1|2);
  499  if(ret<=0)
  500    goto ex;
  501  nfdc= Sfile_count_components(nfd, 0);
  502  ndc= Sfile_count_components(nd, 0);
  503  nfic= Sfile_count_components(nfi, 0);
  504  d= nfdc-ndc;
  505  if(d<0)
  506    {ret= -1; goto ex;}
  507  if(d>nfic)
  508    {ret= 0; goto ex;}
  509  for(i= 0; i<d; i++) {
  510    cpt= strrchr(nfi, '/');
  511    if(cpt==NULL)
  512      {ret= -1; goto ex;} /* should not happen */
  513    *cpt= 0;
  514  }
  515  if(nfi[0]==0)
  516    strcpy(nfi, "/");
  517  ret= Xorriso_fake_stbuf(xorriso, nfi, &stbuf, &node, 0);
  518  if(ret<=0)
  519    {ret= 0; goto ex;}
  520  ret= Xorriso_restore_properties(xorriso, nd, node, ((flag>>1)&3));
  521  if(ret<=0)
  522    goto ex;
  523  sprintf(xorriso->info_text, "Restored properties for ");
  524  Text_shellsafe(nd, xorriso->info_text, 1);
  525  strcat(xorriso->info_text, " from ");
  526  Text_shellsafe(nfi, xorriso->info_text, 1 | 2);
  527  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  528  ret= 1;
  529 ex:;
  530  Xorriso_free_meM(nfi);
  531  Xorriso_free_meM(nd);
  532  Xorriso_free_meM(nfd);
  533  return(ret);
  534 }
  535 
  536 
  537 /* If defined the position accounting will be done by lseek() and used to
  538  * verify the position accounting in struct Xorriso_sparse_statE.
  539  * # def ine Xorriso_check_sparsE yes
  540  */
  541 
  542 struct Xorriso_sparse_statE {
  543  int use_lseek;
  544  off_t cur_pos;
  545  off_t after_last_written;
  546  int warnings;
  547 };
  548 
  549 
  550 #ifdef Xorriso_check_sparsE
  551 
  552 static int Xorriso_sparse_warn(struct XorrisO *xorriso,
  553                                struct Xorriso_sparse_statE *sparse_state,
  554                                int occasion, char *msg, int flag)
  555 {
  556  if(sparse_state->warnings & (1 << occasion))
  557    return(1);
  558  sparse_state->warnings|= 1 << occasion;
  559  Xorriso_msgs_submit(xorriso, 0, msg, 0, "SORRY", 0);
  560  return(1);
  561 }
  562 
  563 #endif /* Xorriso_check_sparsE */
  564 
  565 
  566 static int Xorriso_sparse_init(struct XorrisO *xorriso,
  567                                struct Xorriso_sparse_statE **sparse_state,
  568                                int write_fd, int flag)
  569 {
  570  struct Xorriso_sparse_statE *o= NULL;
  571  off_t cur_pos;
  572  struct stat stbuf;
  573  int ret;
  574 
  575  *sparse_state= NULL;
  576 
  577  /* Check whether sparse writing is disabled */
  578  if(xorriso->sparse_min_gap <= 0)
  579    {ret= 0; goto ex;}
  580 
  581  /* Analyze write_fd */
  582  ret= fstat(write_fd, &stbuf);
  583  if(ret == -1)
  584    {ret= 0; goto ex;}
  585  if(!S_ISREG(stbuf.st_mode))
  586    {ret= 0; goto ex;}
  587  cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
  588  if(cur_pos < stbuf.st_size)
  589    {ret= 0; goto ex;}
  590 
  591  Xorriso_alloc_meM(o, struct Xorriso_sparse_statE, 1);
  592 
  593  /* Initialize sparse_state */
  594  o->use_lseek= 1;
  595  o->cur_pos= o->after_last_written= cur_pos;
  596  o->warnings= 0;
  597 
  598  ret= 1;
  599 ex:;
  600  if(ret >= 1)
  601    *sparse_state= o;
  602  else
  603    Xorriso_free_meM(o);
  604  return(ret);
  605 }
  606 
  607 
  608 static int Xorriso_sparse_zeroize(struct XorrisO *xorriso,
  609                                   struct Xorriso_sparse_statE *sparse_state,
  610                                   int write_fd, off_t start, off_t count,
  611                                   int flag)
  612 {
  613  int ret, buf_size= 32 * 1024, buf_fill, wret;
  614  off_t todo, seek_ret;
  615  char *buf= NULL;
  616 
  617  if(count <= 0)
  618    {ret= 2; goto ex;}
  619  Xorriso_alloc_meM(buf, char, buf_size);
  620 
  621  seek_ret= lseek(write_fd, start, SEEK_SET);
  622  if(seek_ret == -1)
  623    {ret= -1; goto ex;}
  624  sparse_state->cur_pos= seek_ret;
  625  for(todo= count; todo > 0; ) {
  626    if(buf_size < todo)
  627      buf_fill= buf_size;
  628    else
  629      buf_fill= todo;
  630    wret= write(write_fd, buf, buf_fill);
  631    if(wret <= 0)
  632      {ret= wret; goto ex;}
  633    todo-= wret;
  634    sparse_state->cur_pos+= wret;
  635  }
  636  ret= 1;
  637 ex:;
  638  Xorriso_free_meM(buf);
  639  return(ret);
  640 }
  641 
  642 
  643 /* @param flag bit0= this is the last buffer of the stream
  644 */
  645 static int Xorriso_sparse_write(struct XorrisO *xorriso,
  646                                 struct Xorriso_sparse_statE *sparse_state,
  647                                 int write_fd, char *buf, int count,
  648                                 int flag)
  649 {
  650  int wret, i, ret;
  651  off_t cur_pos= -1, seek_ret;
  652  static char zero[32]= {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
  653                         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
  654 
  655  if(sparse_state == NULL)
  656    goto do_write;
  657  if(!sparse_state->use_lseek)
  658    goto do_write;
  659  if(flag & 1)
  660    goto do_write;
  661 
  662 #ifdef Xorriso_check_sparsE
  663 
  664  cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
  665  if(cur_pos == -1)
  666    goto do_write;
  667  if(cur_pos != sparse_state->cur_pos) {
  668    Xorriso_sparse_warn(xorriso, sparse_state, 0,
  669                        "cur_pos deviation in Xorriso_sparse_write:intro", 0);
  670    sparse_state->cur_pos= cur_pos;
  671  }
  672 
  673 #else
  674   
  675  cur_pos= sparse_state->cur_pos;
  676 
  677 #endif
  678 
  679  /* Check for all zeros */
  680  if(count % 32)
  681    goto do_write;
  682  for(i= 0; i < count; i+= 32)
  683    if(memcmp(buf + i, zero, 32))
  684  break;
  685  if(i < count)
  686    goto do_write;
  687 
  688  /* Omit write() until next non-zero buffer or end of writing */
  689 
  690 #ifdef Xorriso_check_sparsE
  691 
  692  /* Only for debugging: Do real lseek() instead of write() */
  693  seek_ret= lseek(write_fd, cur_pos + count, SEEK_SET);
  694  if(seek_ret == -1)
  695    return(-1);
  696 
  697 #endif
  698 
  699  sparse_state->cur_pos= cur_pos + count;
  700  return(count);
  701 
  702 do_write:
  703  if(sparse_state != NULL) {
  704    /* Check whether the gap since after_last_written is too small.
  705       If so: fill the whole gap by writing zeros.
  706    */
  707    if(sparse_state->after_last_written < cur_pos) {
  708      if(xorriso->sparse_min_gap > cur_pos - sparse_state->after_last_written) {
  709        ret= Xorriso_sparse_zeroize(xorriso, sparse_state, write_fd,
  710                                 sparse_state->after_last_written,
  711                                 cur_pos - sparse_state->after_last_written, 0);
  712        if(ret < 0)
  713          return(ret);
  714        if(ret == 0) {
  715          seek_ret= lseek(write_fd, cur_pos, SEEK_SET);
  716          if(seek_ret == -1)
  717            return(-1);
  718          sparse_state->cur_pos= seek_ret;
  719        }
  720      }
  721    }
  722  }
  723 
  724 
  725  if(sparse_state != NULL) {
  726 
  727 #ifdef Xorriso_check_sparsE
  728 
  729    cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
  730    if(cur_pos != sparse_state->cur_pos) {
  731      Xorriso_sparse_warn(xorriso, sparse_state, 1,
  732                       "cur_pos deviation in Xorriso_sparse_write:do_write", 0);
  733      sparse_state->cur_pos= cur_pos;
  734    }
  735 
  736 #else
  737 
  738    /* lseek() has been delayed until now */
  739    if(sparse_state->after_last_written != sparse_state->cur_pos) {
  740      seek_ret= lseek(write_fd, sparse_state->cur_pos, SEEK_SET);
  741      if(seek_ret == -1)
  742        return(-1);
  743    }
  744 
  745 #endif /* ! Xorriso_check_sparsE */
  746 
  747  }
  748  wret= write(write_fd, buf, count);
  749  if(sparse_state != NULL && wret > 0 && cur_pos >= 0)
  750    sparse_state->cur_pos= sparse_state->after_last_written= cur_pos + wret;
  751  return(wret);
  752 }
  753 
  754 
  755 static int Xorriso_sparse_finish(struct XorrisO *xorriso,
  756                                  struct Xorriso_sparse_statE **sparse_state,
  757                                  int write_fd, int flag)
  758 {
  759  int ret;
  760  off_t cur_pos;
  761  struct Xorriso_sparse_statE *o;
  762 
  763  if(sparse_state == NULL)
  764    return(0);
  765  o= *sparse_state;
  766  if(o == NULL)
  767    return(1);
  768  if(write_fd == -1)
  769    {ret= 1; goto ex;}
  770 
  771 #ifdef Xorriso_check_sparsE
  772 
  773  cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
  774  if(cur_pos == -1)
  775    {ret= -1; goto ex;}
  776  if(cur_pos != o->cur_pos) {
  777    Xorriso_sparse_warn(xorriso, o, 2,
  778                        "cur_pos deviation in Xorriso_sparse_finish", 0);
  779    o->cur_pos= cur_pos;
  780  }
  781 
  782 #else
  783   
  784  cur_pos= o->cur_pos;
  785 
  786 #endif /* ! Xorriso_check_sparsE */
  787 
  788  if(o->after_last_written < cur_pos) {
  789    /* Check whether the gap since after_last_written is too small.
  790       If so: fill the whole gap by writing zeros, else: write a last zero byte.
  791    */
  792    if(xorriso->sparse_min_gap > cur_pos - o->after_last_written)
  793      ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, o->after_last_written,
  794                                  cur_pos - o->after_last_written, 0);
  795    else
  796      ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, cur_pos - 1, (off_t) 1,
  797                                  0);
  798    if(ret <= 0)
  799      goto ex;
  800  }
  801  ret= 1;
  802 ex:;
  803  Xorriso_free_meM(o);
  804  *sparse_state= NULL;
  805  return(ret);
  806 }
  807 
  808 
  809 /* @param flag bit0= Minimal transfer: access permissions only
  810                bit1= *_offset and bytes are valid for writing to regular file
  811                bit2= This is not a parameter. Do not report if ignored
  812                bit3= do not restore properties
  813                bit4= issue pacifier messages with long lasting copying
  814                bit7= return 4 if restore fails from denied permission
  815                      do not issue error message
  816    @return <0 severe error , 0 failure , 1 success ,
  817            2 regularly not installed (disallowed device, UNIX domain socket)
  818            4 with bit7: permission to restore was denied
  819 */
  820 int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
  821                               char *img_path, off_t img_offset,
  822                               char *disk_path, off_t disk_offset, off_t bytes,
  823                               int flag)
  824 {
  825  int ret= 0, write_fd= -1, wanted, wret, open_flags, l_errno= 0;
  826  int target_deleted= 0, buf_size= 32 * 1024;
  827  char *what= "[unknown filetype]";
  828  char *buf= NULL, type_text[5], *temp_path= NULL, *buf_pt, *reason;
  829  char *link_target, *open_path_pt= NULL;
  830  off_t todo= 0, size, seek_ret, last_p_count= 0, already_done, read_count= 0;
  831  void *data_stream= NULL;
  832  mode_t mode;
  833  dev_t dev= 0;
  834  struct stat stbuf;
  835  struct utimbuf utime_buffer;
  836  IsoImage *volume;
  837  IsoBoot *bootcat;
  838  uint32_t lba;
  839  char *catcontent = NULL;
  840  off_t catsize, iso_node_size, wanted_size, cap;
  841  char disk_md5[16], iso_md5[16];
  842  void *ctx= NULL;
  843  int use_md5= 0, i, sparse_ret= 3;
  844  struct Xorriso_sparse_statE *sparse_state= NULL;
  845 
  846  Xorriso_alloc_meM(buf, char, buf_size);
  847  Xorriso_alloc_meM(temp_path, char, SfileadrL);
  848 
  849  if(!(flag & 2))
  850    img_offset= bytes= 0;
  851  if(LIBISO_ISDIR(node)) {
  852    what= "directory";
  853    ret= mkdir(disk_path, 0777);
  854    l_errno= errno;
  855 
  856  } else if(LIBISO_ISREG(node) || ISO_NODE_IS_BOOTCAT(node)) {
  857    if(ISO_NODE_IS_BOOTCAT(node)) {
  858      what= "boot catalog";
  859    } else {
  860      what= "regular file";
  861      ret= Xorriso_iso_file_open(xorriso, img_path, (void *) node, &data_stream,
  862                                 1);
  863      if(ret<=0)
  864        goto ex;
  865      if((xorriso->do_md5 & 65) == 65 && !(flag & 2)) {
  866        ret= Xorriso_is_plain_image_file(xorriso, (void *) node, img_path, 0);
  867        if(ret > 0) {
  868          ret= Xorriso_get_md5(xorriso, (void *) node, img_path, iso_md5, 1);
  869          if(ret > 0)
  870            ret= Xorriso_md5_start(xorriso, &ctx, 0);
  871          if(ret > 0) {
  872            use_md5= 1;
  873          } else if(xorriso->do_md5 & 128) {
  874            sprintf(xorriso->info_text,
  875                    "Cannot obtain any recorded MD5 of file ");
  876            Text_shellsafe(img_path, xorriso->info_text, 1);
  877            Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
  878            ret= Xorriso_eval_problem_status(xorriso, 0, 1 | 2);
  879            if(ret < 0)
  880              {ret= 0; goto ex;}
  881          }
  882        }
  883      }
  884    }
  885    open_path_pt= disk_path;
  886    ret= stat(open_path_pt, &stbuf);
  887    if(ret == -1 && errno == EACCES && (flag & 128))
  888      {ret= 4; goto ex;}
  889    if(flag&2) {
  890      if(ret != -1) {
  891        wanted_size= disk_offset + bytes;
  892        iso_node_size= iso_file_get_size((IsoFile *) node);
  893        if(wanted_size > disk_offset + iso_node_size)
  894          wanted_size= disk_offset + iso_node_size;
  895        cap= wanted_size;
  896        ret= Xorriso_determine_capacity(xorriso, open_path_pt, &cap, &reason,
  897                                        3);
  898        if(ret <= 0 || (cap <= 0 && !S_ISREG(stbuf.st_mode))) {
  899          if(ret > 0)
  900            reason= "has addressable range 0";
  901          sprintf(xorriso->info_text,
  902                  "Restore offset demanded. But target file (%s) ",
  903                  Ftypetxt(stbuf.st_mode, 0));
  904          Text_shellsafe(disk_path, xorriso->info_text, 1);
  905          strcat(xorriso->info_text, reason);
  906          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);            l_errno= 0;
  907          goto cannot_restore;
  908        }
  909        if(cap < wanted_size && !S_ISREG(stbuf.st_mode)) {
  910 
  911          /* >>> non-regular file might be too small to take the interval */;
  912 
  913        }
  914      }
  915    } else {
  916      /* If source and target are the same disk file then do not copy content */
  917      ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path,
  918                                        disk_path, type_text, 1);
  919      if(ret<0)
  920        goto ex;
  921      if(ret==1) {
  922        /* preliminarily emulate touch (might get overridden later) */
  923        utime_buffer.actime= stbuf.st_atime;
  924        utime_buffer.modtime= time(0);
  925        utime(disk_path,&utime_buffer);
  926        goto restore_properties;
  927      }
  928      if(ret==2) {
  929        /* Extract to temporary file and rename only after copying */
  930        ret= Xorriso_make_tmp_path(xorriso, disk_path, temp_path, &write_fd,
  931                                   128);
  932        if(ret <= 0 || ret == 4)
  933          goto ex;
  934        open_path_pt= temp_path;
  935      }
  936    }
  937    if(write_fd==-1) {
  938      open_flags= O_WRONLY|O_CREAT;
  939      if(disk_offset==0 || !(flag&2))
  940        open_flags|= O_EXCL;
  941      write_fd= open(open_path_pt, open_flags | O_BINARY, S_IRUSR | S_IWUSR);
  942      l_errno= errno;
  943      if(write_fd == -1 && errno == EACCES && (flag & 128))
  944        {ret= 4; goto ex;}
  945      if(write_fd==-1)
  946        goto cannot_restore;
  947    }
  948    if(ISO_NODE_IS_BOOTCAT(node)) {
  949      ret= Xorriso_get_volume(xorriso, &volume, 0);
  950      if(ret<=0)
  951        goto ex;
  952      ret= iso_image_get_bootcat(volume, &bootcat, &lba, &catcontent, &catsize);
  953      if(ret < 0)
  954        goto ex;
  955      todo= size= catsize;
  956    } else {
  957      todo= size= iso_file_get_size((IsoFile *) node);
  958    }
  959    if(flag&2) {
  960      if(bytes<size)
  961        todo= size= bytes;
  962      seek_ret= lseek(write_fd, disk_offset, SEEK_SET);
  963      l_errno= errno;
  964      if(seek_ret == -1) {
  965        sprintf(xorriso->info_text,
  966                "Cannot address byte %.f in filesystem path ",
  967                (double) disk_offset);
  968        Text_shellsafe(open_path_pt, xorriso->info_text, 1);
  969        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
  970        goto cannot_restore;
  971      }
  972    }
  973    if(ISO_NODE_IS_FILE(node))
  974      Xorriso_sparse_init(xorriso, &sparse_state, write_fd, 0);
  975 
  976    while(todo>0) {
  977      wanted= buf_size;
  978      if(wanted>todo)
  979        wanted= todo;
  980      if(ISO_NODE_IS_BOOTCAT(node)) {
  981        ret= todo;
  982        buf_pt= catcontent;
  983      } else {
  984        ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0);
  985        buf_pt= buf;
  986      }
  987      if(ret<=0) {
  988        if(xorriso->extract_error_mode == 0 &&
  989           Xorriso_is_plain_image_file(xorriso, node, "", 0)) {
  990          close(write_fd);
  991          write_fd= -1;
  992          already_done= (size - todo) / (off_t) 2048;
  993          already_done*= (off_t) 2048;
  994          sprintf(xorriso->info_text,
  995                  "Starting best_effort handling on ISO file ");
  996          Text_shellsafe(img_path, xorriso->info_text, 1);
  997          sprintf(xorriso->info_text + strlen(xorriso->info_text),
  998                  " at byte %.f", (double) already_done);
  999          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1000          ret= Xorriso_read_file_data(xorriso, node, img_path, open_path_pt,
 1001                            already_done, already_done, size - already_done, 2);
 1002          if(ret >= 0)
 1003            xorriso->pacifier_byte_count+= todo;
 1004          if(ret > 0)
 1005            todo= 0;
 1006          else
 1007            todo= -1;
 1008        }
 1009        if(ret <= 0) {
 1010          sprintf(xorriso->info_text, "Cannot read all bytes from ISO file ");
 1011          Text_shellsafe(img_path, xorriso->info_text, 1);
 1012          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1013        }
 1014    break;
 1015      }
 1016      read_count+= ret;
 1017      if(use_md5)
 1018        Xorriso_md5_compute(xorriso, ctx, buf_pt, ret, 0);
 1019 
 1020      if(img_offset > read_count - ret) {
 1021        /* skip the desired amount of bytes */
 1022        if(read_count <= img_offset)
 1023    continue;
 1024        buf_pt= buf_pt + (img_offset - (read_count - ret));
 1025        ret= read_count - img_offset;
 1026      }
 1027 
 1028      if(sparse_state == NULL)
 1029        wret= write(write_fd, buf_pt, ret);
 1030      else
 1031        wret= Xorriso_sparse_write(xorriso, sparse_state, write_fd, buf_pt, ret,
 1032                                   0);
 1033      if(wret>=0) {
 1034        todo-= wret;
 1035        xorriso->pacifier_byte_count+= wret;
 1036        if((flag&16) &&
 1037           xorriso->pacifier_byte_count - last_p_count >= 128*1024) {
 1038          Xorriso_pacifier_callback(xorriso, "files restored",
 1039                              xorriso->pacifier_count,
 1040                              xorriso->pacifier_total, "", 2 | 4 | 8);
 1041          last_p_count= xorriso->pacifier_byte_count;
 1042        }
 1043      }
 1044      if(wret != ret) {
 1045        sprintf(xorriso->info_text,
 1046                "Cannot write all bytes to disk filesystem path ");
 1047        Text_shellsafe(open_path_pt,  xorriso->info_text, 1);
 1048        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 1049    break;
 1050      }
 1051    }
 1052   
 1053    if(use_md5) {
 1054      ret= Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
 1055      if(ret <= 0) {
 1056        sprintf(xorriso->info_text,
 1057         "Internal problem with obtaining computed MD5 for extracted data of ");
 1058        goto bad_md5;
 1059      } else {
 1060        for(i= 0; i < 16; i++)
 1061          if(iso_md5[i] != disk_md5[i])
 1062        break;
 1063        if(i < 16) {
 1064          sprintf(xorriso->info_text,
 1065                  "MD5 of extracted data does not match recorded MD5 of file ");
 1066 bad_md5:;
 1067          Text_shellsafe(img_path, xorriso->info_text, 1);
 1068          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 1069          ret= Xorriso_eval_problem_status(xorriso, 0, 1 | 2);
 1070          if(ret < 0)
 1071            {ret= 0; goto ex;}
 1072        }
 1073      }
 1074    }
 1075 
 1076    if(write_fd != -1) {
 1077      sparse_ret= Xorriso_sparse_finish(xorriso, &sparse_state, write_fd, 0);
 1078      close(write_fd);
 1079    }
 1080    write_fd= -1;
 1081    if(todo > 0 && xorriso->extract_error_mode == 2) {
 1082      unlink(open_path_pt);
 1083      target_deleted= 1;
 1084    }
 1085    if(! ISO_NODE_IS_BOOTCAT(node))
 1086      Xorriso_iso_file_close(xorriso, &data_stream, 0);
 1087    data_stream= NULL;
 1088    if(temp_path==open_path_pt && !target_deleted) {
 1089      ret= rename(temp_path, disk_path);
 1090      if(ret==-1) {
 1091        sprintf(xorriso->info_text, "Cannot rename temporary path ");
 1092        Text_shellsafe(temp_path, xorriso->info_text, 1);
 1093        strcat(xorriso->info_text, " to final disk path ");
 1094        Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
 1095        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 1096        unlink(temp_path);
 1097        ret= 0; goto ex;
 1098      }
 1099    }
 1100    ret= -(todo > 0);
 1101    l_errno= 0;
 1102    if(sparse_ret <= 0) {
 1103      strcpy(xorriso->info_text, "Could not finalize sparse extraction of ");
 1104      Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
 1105      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text,
 1106                          sparse_ret < 0 ? errno : 0, "FAILURE", 0);
 1107    }
 1108 
 1109  } else if(LIBISO_ISLNK(node)) {
 1110    what= "symbolic link";
 1111    link_target= (char *) iso_symlink_get_dest((IsoSymlink *) node);
 1112    ret= symlink(link_target, disk_path);
 1113    l_errno= errno;
 1114 
 1115  } else if(LIBISO_ISCHR(node)) {
 1116    what= "character device";
 1117    if(xorriso->allow_restore!=2) {
 1118 ignored:;
 1119      if(!(flag&4)) {
 1120        sprintf(xorriso->info_text, "Ignored file type: %s ", what);
 1121        Text_shellsafe(img_path, xorriso->info_text, 1);
 1122        strcat(xorriso->info_text, " = ");
 1123        Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
 1124        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1125      }
 1126      {ret= 2; goto ex;}
 1127    }
 1128    mode= S_IFCHR | 0777;
 1129    ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0);
 1130    if(ret<=0)
 1131      goto ex;
 1132    if(dev == (dev_t) 1) {
 1133 probably_damaged:;
 1134      sprintf(xorriso->info_text,
 1135              "Most probably damaged device file not restored: mknod ");
 1136      Text_shellsafe(disk_path, xorriso->info_text, 1);
 1137      sprintf(xorriso->info_text + strlen(xorriso->info_text), 
 1138              " %s 0 1", LIBISO_ISCHR(node) ? "c" : "b");
 1139      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1140      ret= 0; goto ex;
 1141    }
 1142    ret= mknod(disk_path, mode, dev);
 1143    l_errno= errno;
 1144 
 1145  } else if(LIBISO_ISBLK(node)) {
 1146    what= "block device";
 1147    if(xorriso->allow_restore!=2)
 1148      goto ignored;
 1149    mode= S_IFBLK | 0777;
 1150    ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0);
 1151    if(ret<=0)
 1152      goto ex;
 1153    if(dev == (dev_t) 1)
 1154      goto probably_damaged;
 1155    ret= mknod(disk_path, mode, dev);
 1156    l_errno= errno;
 1157 
 1158  } else if(LIBISO_ISFIFO(node)) {
 1159    what= "named pipe";
 1160    mode= S_IFIFO | 0777;
 1161    ret= mknod(disk_path, mode, dev);
 1162    l_errno= errno;
 1163 
 1164  } else if(LIBISO_ISSOCK(node)) {
 1165    what= "unix socket";
 1166    /* Restoring a socket file is not possible. One rather needs to restart
 1167       the service which temporarily created the socket. */
 1168    goto ignored;
 1169 
 1170  } else {
 1171    sprintf(xorriso->info_text, "Cannot restore file type '%s'", what);
 1172    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 1173    ret= 0; goto ex;
 1174 
 1175  }
 1176  if(ret == -1 && l_errno == EACCES && (flag & 128))
 1177    {ret= 4; goto ex;}
 1178  if(ret==-1) {
 1179 cannot_restore:;
 1180    sprintf(xorriso->info_text,
 1181            "Cannot restore %s to disk filesystem: ", what);
 1182    Text_shellsafe(img_path, xorriso->info_text, 1);
 1183    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, l_errno, "FAILURE", 0);
 1184    ret= 0; goto ex;
 1185  }
 1186 
 1187 restore_properties:;
 1188  if((flag&8) || LIBISO_ISLNK(node))
 1189    ret= 1;
 1190  else
 1191    ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1);
 1192  if(todo < 0)
 1193    ret= 0;
 1194 ex:;
 1195  if(write_fd != -1) {
 1196    close(write_fd);
 1197    if(ret <= 0 && xorriso->extract_error_mode == 2 && open_path_pt != NULL)
 1198      unlink(open_path_pt);
 1199  }
 1200  Xorriso_free_meM(buf);
 1201  Xorriso_free_meM(temp_path);
 1202  if(catcontent != NULL)
 1203    free(catcontent);
 1204  if(data_stream!=NULL)
 1205    Xorriso_iso_file_close(xorriso, &data_stream, 0);
 1206  if(ctx != NULL)
 1207    Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
 1208  if(sparse_state != NULL)
 1209    Xorriso_sparse_finish(xorriso, &sparse_state, -1, 0);
 1210  Xorriso_process_msg_queues(xorriso,0);
 1211  return(ret);
 1212 }
 1213 
 1214 
 1215 /* Handle overwrite situation in disk filesystem.
 1216    @param node  intended source of overwriting or NULL
 1217    @param flag
 1218                bit4= return 3 on rejection by exclusion or user
 1219                bit6= permission to call Xorriso_make_accessible()
 1220 */
 1221 int Xorriso_restore_overwrite(struct XorrisO *xorriso,
 1222                               IsoNode *node, char *img_path,
 1223                               char *path, char *nominal_path,
 1224                               struct stat *stbuf, int flag)
 1225 {
 1226  int ret;
 1227  char type_text[5];
 1228 
 1229  Xorriso_process_msg_queues(xorriso,0);
 1230  if(xorriso->do_overwrite==1 ||
 1231     (xorriso->do_overwrite==2 && !S_ISDIR(stbuf->st_mode))) {
 1232 
 1233    ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path,
 1234                                      path, type_text, (node!=NULL));
 1235    if(ret<0)
 1236      return(ret);
 1237    if(ret>0) /* will be handled properly by restore functions */
 1238      ret= Xorriso_reassure_restore(xorriso, path, 8);
 1239    else
 1240      ret= Xorriso_rmx(xorriso, (off_t) 0, path, 8 | (flag & 64));
 1241    if(ret<=0)
 1242      return(ret);
 1243    if(ret==3) {
 1244      sprintf(xorriso->info_text, "User revoked restoring of (ISO) file: ");
 1245      Text_shellsafe(img_path, xorriso->info_text, 1);
 1246      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1247      return(3*!!(flag&16));
 1248    }
 1249    return(1);
 1250  }
 1251  Xorriso_msgs_submit(xorriso, 0, nominal_path, 0, "ERRFILE", 0);
 1252  sprintf(xorriso->info_text, "While restoring ");
 1253  Text_shellsafe(nominal_path, xorriso->info_text, 1);
 1254  strcat(xorriso->info_text, " : ");
 1255  if(strcmp(nominal_path, path) == 0)
 1256    strcat(xorriso->info_text, "file object");
 1257  else
 1258    Text_shellsafe(path, xorriso->info_text, 1 | 2);
 1259  strcat(xorriso->info_text, " exists and may not be overwritten");
 1260  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1261  return(0);
 1262 }
 1263 
 1264 
 1265 /*
 1266    @return <0 error,
 1267            bit0= hardlink created
 1268            bit1= siblings with target NULL found
 1269            bit2= siblings with non-NULL target found
 1270 */
 1271 int Xorriso_restore_target_hl(struct XorrisO *xorriso, IsoNode *node,
 1272                            char *disk_path, int *node_idx, int flag)
 1273 {
 1274  int ret, min_hl, max_hl, i, null_target_sibling= 0, link_sibling= 0;
 1275 
 1276  if(xorriso->hln_targets == NULL)
 1277    return(0);
 1278  ret= Xorriso_search_hardlinks(xorriso, node, node_idx, &min_hl, &max_hl, 1);
 1279  if(ret < 0)
 1280    return(ret);
 1281  if(ret == 0 || *node_idx < 0 || min_hl == max_hl)
 1282    return(0);
 1283  for(i= min_hl; i <= max_hl; i++) {
 1284    if(xorriso->hln_targets[i] == NULL) {
 1285      if(i != *node_idx)
 1286        null_target_sibling= 1;
 1287  continue;
 1288    }
 1289    link_sibling= 1;
 1290    ret= Xorriso_restore_make_hl(xorriso, xorriso->hln_targets[i], disk_path,
 1291                                 !!xorriso->do_auto_chmod);
 1292    if(ret > 0)
 1293      return(1);
 1294  }
 1295  return((null_target_sibling << 1) | (link_sibling << 2));
 1296 }
 1297 
 1298 
 1299 /*
 1300    @return <0 error,
 1301            bit0= hardlink created
 1302            bit2= siblings lower index found
 1303 */
 1304 int Xorriso_restore_prefix_hl(struct XorrisO *xorriso, IsoNode *node,
 1305                               char *disk_path, int node_idx, int flag)
 1306 {
 1307  int ret, min_hl, max_hl, i, link_sibling= 0, hflag;
 1308  char *old_path= NULL, *img_path= NULL;
 1309  struct Xorriso_lsT *img_prefixes= NULL, *disk_prefixes= NULL;
 1310 
 1311  Xorriso_alloc_meM(old_path, char, SfileadrL);
 1312  Xorriso_alloc_meM(img_path, char, SfileadrL);
 1313 
 1314  ret= Xorriso_search_hardlinks(xorriso, node, &node_idx, &min_hl, &max_hl,
 1315                                2 | 4);
 1316  if(ret < 0)
 1317    goto ex;
 1318  if(ret == 0 || min_hl == max_hl)
 1319    {ret= 0; goto ex;}
 1320 
 1321  for(i= min_hl; i < node_idx; i++) {
 1322    link_sibling= 1;
 1323    ret= Xorriso_path_from_node(xorriso, xorriso->node_array[i], img_path, 0);
 1324    if(ret < 0)
 1325      goto ex;
 1326    if(ret == 0)
 1327  continue; /* Node is deleted from tree (Should not happen here) */
 1328    hflag= 1;
 1329    if(i == min_hl) {
 1330      hflag= 0;
 1331    } else if(xorriso->node_array[i] != xorriso->node_array[i - 1]) {
 1332      hflag= 0;
 1333    }
 1334    if(hflag == 0) {
 1335      img_prefixes= xorriso->node_img_prefixes;
 1336      disk_prefixes= xorriso->node_disk_prefixes;
 1337    }
 1338    ret= Xorriso_make_restore_path(xorriso, &img_prefixes, &disk_prefixes,
 1339                                   img_path, old_path, hflag);
 1340    if(ret <= 0)
 1341      goto ex;
 1342    ret= Xorriso_restore_make_hl(xorriso, old_path, disk_path,
 1343                                 !!xorriso->do_auto_chmod);
 1344    if(ret > 0)
 1345      {ret= 1; goto ex;}
 1346  }
 1347  ret= link_sibling << 2;
 1348 ex:;
 1349  Xorriso_free_meM(old_path);
 1350  Xorriso_free_meM(img_path);
 1351  return(ret);
 1352 }
 1353 
 1354 
 1355 /* @return <0 = error , 0 = availmem exhausted first time , 1 = ok
 1356                         2 = availmem exhausted repeated
 1357 */ 
 1358 int Xorriso_register_node_target(struct XorrisO *xorriso, int node_idx,
 1359                                  char *disk_path, int flag)
 1360 {
 1361  int l;
 1362 
 1363  if(xorriso->node_targets_availmem == 0)
 1364    return(2);
 1365  if(xorriso->hln_targets == NULL || node_idx < 0 ||
 1366     node_idx >= xorriso->hln_count)
 1367    return(0);
 1368  if(xorriso->hln_targets[node_idx] != NULL) {
 1369    xorriso->node_targets_availmem+= strlen(xorriso->hln_targets[node_idx]) +1;
 1370    free(xorriso->hln_targets[node_idx]);
 1371  }
 1372  l= strlen(disk_path);
 1373  if(xorriso->node_targets_availmem <= l + 1) {
 1374    sprintf(xorriso->info_text,
 1375  "Hardlink target buffer exceeds -temp_mem_limit. Hardlinks may get divided.");
 1376    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1377    xorriso->node_targets_availmem= 0;
 1378    return(0);
 1379  }
 1380  xorriso->hln_targets[node_idx]= strdup(disk_path);
 1381  if(xorriso->hln_targets[node_idx] == NULL) {
 1382    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 1383    return(-1);
 1384  }
 1385  xorriso->node_targets_availmem-= (l + 1);
 1386  return(1);
 1387 }
 1388 
 1389 
 1390 /*
 1391    @param flag bit0= offset and bytes is valid for writing to regular file
 1392                bit1= do not report copied files
 1393                bit2= -follow, -not_*: this is not a command parameter
 1394                bit3= keep directory open: keep owner, allow rwx for owner
 1395                bit4= do not look for hardlinks even if enabled
 1396                bit6= this is a copy action: do not fake times and ownership
 1397                bit7= return 4 if restore fails from denied permission
 1398                      do not issue error message
 1399               bit10= do not restore properties
 1400    @return <=0 = error , 1 = added leaf file object , 2 = added directory ,
 1401              3= regularly not installed (disallowed device, UNIX domain socket)
 1402              4 = with bit7: permission to restore was denied
 1403 */
 1404 int Xorriso_restore_disk_object(struct XorrisO *xorriso,
 1405                                 char *img_path, IsoNode *node,
 1406                                 char *disk_path,
 1407                                 off_t offset, off_t bytes, int flag)
 1408 {
 1409  int ret, i, split_count= 0, partno, total_parts, leaf_is_split= 0;
 1410  int record_hl_path= 0, node_idx, cannot_register= 0, no_props;
 1411  off_t total_bytes;
 1412  char *part_name, *part_path= NULL, *img_path_pt= NULL;
 1413  IsoImage *volume;
 1414  IsoNode *part_node, *first_part_node= NULL;
 1415  struct SplitparT *split_parts= NULL;
 1416  struct stat stbuf;
 1417 
 1418  Xorriso_alloc_meM(part_path, char, SfileadrL);
 1419 
 1420  no_props= !!(flag & 1024);
 1421 
 1422  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1423  if(ret<=0)
 1424    goto ex;
 1425 
 1426  if(LIBISO_ISDIR(node) && xorriso->do_concat_split)
 1427    leaf_is_split= Xorriso_identify_split(xorriso, img_path, node,
 1428                                     &split_parts, &split_count, &stbuf, 1 | 4);
 1429  if(leaf_is_split) {
 1430    /* map all files in directory img_path into regular file disk_path */
 1431 
 1432    for(i=0 ; i<split_count; i++) {
 1433      Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
 1434                     &offset, &bytes, &total_bytes, 0);
 1435 
 1436      strcpy(part_path, img_path);
 1437      if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
 1438        Xorriso_much_too_long(xorriso, strlen(img_path)+strlen(part_name)+1, 2);
 1439        goto restoring_failed;
 1440      }
 1441      ret= Xorriso_node_from_path(xorriso, volume, part_path, &part_node, 0);
 1442      if(ret<=0)
 1443        goto restoring_failed;
 1444      if(i==0)
 1445        first_part_node= part_node;
 1446      if(offset+bytes>total_bytes)
 1447              bytes= total_bytes-offset;
 1448      ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, (off_t) 0,
 1449                disk_path, offset, bytes,
 1450                (!!(flag&64)) | 2 | (flag & (4 | 128)) | 8 | ( 16 * !(flag&2)));
 1451      if(ret<=0)
 1452        goto restoring_failed;
 1453      if(ret == 4)
 1454        goto ex;
 1455    }
 1456    if(first_part_node != NULL && !no_props)
 1457      Xorriso_restore_properties(xorriso, disk_path, first_part_node,
 1458                                 !!(flag&64));
 1459    goto went_well;
 1460  }
 1461 
 1462 #ifdef Osirrox_not_yeT
 1463 
 1464  if(resolve_link) {
 1465    ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
 1466    if(ret<=0)
 1467      goto ex;
 1468    disk_path_pt= resolved_disk_path;
 1469  } else
 1470 
 1471 #endif /* Osirrox_not_yeT */
 1472 
 1473    img_path_pt= img_path;
 1474 
 1475  if(!((xorriso->ino_behavior & 4) || (flag & (1 | 16)) || LIBISO_ISDIR(node))){
 1476    /* Try to restore as hardlink */
 1477    ret= Xorriso_restore_target_hl(xorriso, node, disk_path, &node_idx,
 1478                                   !!xorriso->do_auto_chmod);
 1479    if(ret < 0) {
 1480      goto ex;
 1481    } else if(ret & 1) {
 1482      /* Success, hardlink was created */
 1483      goto went_well;
 1484    } else if(ret & 2) {
 1485      /* Did not establish hardlink. Hardlink siblings with target NULL found.*/
 1486      record_hl_path= 1;
 1487    }
 1488    if(ret & 4) {
 1489      /* Found siblings with non-NULL target, but did not link. */
 1490      ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
 1491      if(ret < 0)
 1492        {ret= 0; goto ex;}
 1493    }
 1494  }
 1495 
 1496  ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, (off_t) 0,
 1497                                 disk_path, offset, bytes,
 1498      (flag&(4 | 8 | 128)) | (!!(flag&64)) | ((flag&1)<<1) | ( 16 * !(flag&2))
 1499      | (no_props << 3));
 1500  if(ret == 4)
 1501    goto ex;
 1502  if(ret > 0 && (flag & 8) && !no_props)
 1503    ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64));
 1504  if(ret<=0) {
 1505 restoring_failed:;
 1506    sprintf(xorriso->info_text, "Restoring failed:  ");
 1507    Text_shellsafe(img_path, xorriso->info_text, 1);
 1508    strcat(xorriso->info_text, " = ");
 1509    Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
 1510    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 1511    {ret= 0; goto ex;}
 1512  }
 1513  if(ret==2)
 1514    {ret= 3; goto ex;}
 1515  if(record_hl_path) { /* Start of a disk hardlink family */
 1516    ret= Xorriso_register_node_target(xorriso, node_idx, disk_path, 0);
 1517    if(ret < 0)
 1518      goto ex;
 1519    if(ret == 0)
 1520      cannot_register= 1;
 1521  }
 1522 
 1523 went_well:;
 1524  xorriso->pacifier_count++;
 1525  if(!(flag&2))
 1526    Xorriso_pacifier_callback(xorriso, "files restored",
 1527                              xorriso->pacifier_count,
 1528                              xorriso->pacifier_total, "", 4 | 8);
 1529  ret= 1;
 1530 ex:;
 1531  if(split_parts!=NULL) 
 1532    Splitparts_destroy(&split_parts, split_count, 0);
 1533  Xorriso_free_meM(part_path);
 1534  if(ret > 0 && cannot_register)
 1535    ret= 0;
 1536  return(ret);
 1537 }
 1538 
 1539 
 1540 /* @param flag bit0= source is a directory and not to be restored as split file
 1541            >>> bit6= permission to call Xorriso_make_accessible()
 1542    @return <=0 error , 1=collision handled , 2=no collision , 3=revoked by user
 1543 */
 1544 int Xorriso_handle_collision(struct XorrisO *xorriso,
 1545                              IsoNode *node, char *img_path,
 1546                              char *disk_path, char *nominal_disk_path,
 1547                              int *stbuf_ret, int flag)
 1548 {
 1549  int ret, target_is_dir= 0, target_is_link= 0, stat_ret, made_accessible= 0;
 1550  struct stat target_stbuf, lt_stbuf;
 1551  struct PermiteM *perm_stack_mem;
 1552 
 1553  perm_stack_mem= xorriso->perm_stack;
 1554 
 1555  /* does a disk file exist with this name ? */
 1556  *stbuf_ret= lstat(disk_path, &target_stbuf);
 1557  if(*stbuf_ret==-1) {
 1558    if((flag & 64) && errno == EACCES) {
 1559      ret= Xorriso_make_accessible(xorriso, disk_path, 0);
 1560      if(ret < 0)
 1561        goto ex;
 1562      made_accessible= 1;
 1563      *stbuf_ret= lstat(disk_path, &target_stbuf);
 1564    }
 1565    if(*stbuf_ret==-1)
 1566      {ret= 2; goto ex;}
 1567  }
 1568  target_is_link= S_ISLNK(target_stbuf.st_mode);
 1569  if(target_is_link) {
 1570    stat_ret= stat(disk_path, &lt_stbuf);
 1571    if(stat_ret == -1) {
 1572      if((flag & 64) && errno == EACCES && !made_accessible) {
 1573        ret= Xorriso_make_accessible(xorriso, disk_path, 0);
 1574        if(ret < 0)
 1575          goto ex;
 1576        made_accessible= 1;
 1577        stat_ret= stat(disk_path, &lt_stbuf);
 1578      }
 1579    }
 1580    if(stat_ret != -1)
 1581      target_is_dir= S_ISDIR(lt_stbuf.st_mode);
 1582  } else {
 1583    target_is_dir= S_ISDIR(target_stbuf.st_mode);
 1584  }
 1585  if(target_is_dir && (!target_is_link) && !(flag&1)) {
 1586    strcpy(xorriso->info_text, "Attempt to replace DISK directory ");
 1587    Text_shellsafe(nominal_disk_path,
 1588                   xorriso->info_text+strlen(xorriso->info_text), 0);
 1589    strcat(xorriso->info_text, " by ISO file ");
 1590    Text_shellsafe(img_path, xorriso->info_text+strlen(xorriso->info_text), 0);
 1591    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1592    ret= 0; goto ex;
 1593  }
 1594 
 1595  if(!(target_is_dir && (flag&1))) {
 1596    Xorriso_process_msg_queues(xorriso,0);
 1597    ret= Xorriso_restore_overwrite(xorriso, node, img_path, disk_path,
 1598                            nominal_disk_path, &target_stbuf, 16 | (flag & 64));
 1599    if(ret==3)
 1600      {ret= 3; goto ex;}
 1601    if(ret<=0) 
 1602      goto ex;
 1603    *stbuf_ret= -1; /* It might still exist but will be handled properly */
 1604  }
 1605  ret= 1;
 1606 ex:;
 1607  if(made_accessible)
 1608    Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 1609  return(ret);
 1610 }
 1611 
 1612 
 1613 /* @param flag bit0= recursion is active
 1614                bit1= do not report restored files
 1615                bit6= this is a copy action: do not fake times and ownership
 1616                bit7+8=
 1617                      0= direct operation
 1618                      1= create only directories,
 1619                         count nodes in xorriso->node_counter
 1620                      2= only register non-directory nodes in
 1621                         xorriso->node_array
 1622                      3= count nodes in xorriso->node_counter,
 1623                         create no directory
 1624 */
 1625 int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir,
 1626                          char *img_dir_path, char *disk_dir_path,
 1627                          off_t boss_mem,
 1628                          struct LinkiteM *link_stack, int flag)
 1629 {
 1630  IsoImage *volume;
 1631  IsoNode *node;
 1632  IsoDirIter *iter= NULL;
 1633  IsoNode **node_array= NULL;
 1634  int node_count= 0, node_idx;
 1635  int ret, source_is_dir, fret, was_failure= 0;
 1636  int do_not_dive, source_is_split= 0, len_dp, len_ip, stbuf_ret, hflag, hret;
 1637  char *name, *disk_name, *leaf_name, *srcpt, *stbuf_src= "";
 1638  struct LinkiteM *own_link_stack;
 1639  char *sfe= NULL, *sfe2= NULL;
 1640  char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
 1641  off_t mem;
 1642  struct PermiteM *perm_stack_mem;
 1643  struct stat stbuf;
 1644  int dir_create= 0, node_register= 0, do_node_count= 0, normal_mode= 0;
 1645 
 1646  perm_stack_mem= xorriso->perm_stack;
 1647  switch((flag >> 7) & 3) {
 1648  case 0: normal_mode= 1;
 1649  break; case 1: dir_create= 1;
 1650  break; case 2: node_register= 1;
 1651  break; case 3: do_node_count= 1;
 1652  }
 1653 
 1654  /* Avoiding large local memory objects in order to save stack space */
 1655  sfe= malloc(5*SfileadrL);
 1656  sfe2= malloc(5*SfileadrL);
 1657  disk_path= malloc(2*SfileadrL);
 1658  img_path= malloc(2*SfileadrL);
 1659  link_target= malloc(SfileadrL);
 1660  if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
 1661     link_target==NULL) {
 1662    Xorriso_no_malloc_memory(xorriso, &sfe, 0);
 1663    {ret= -1; goto ex;}
 1664  }
 1665 
 1666  own_link_stack= link_stack;
 1667 
 1668  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1669  if(ret<=0)
 1670    goto ex;
 1671 
 1672  stbuf_src= img_dir_path;
 1673  node= (IsoNode *) dir;
 1674  ret= Xorriso_fake_stbuf(xorriso, stbuf_src, &stbuf, &node, 1);
 1675  if(ret<=0) {
 1676    Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
 1677    sprintf(xorriso->info_text,"Cannot open as (ISO) source directory: %s",
 1678            Text_shellsafe(img_dir_path, sfe, 0));
 1679    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1680    {ret= 0; goto ex;}
 1681  }
 1682 
 1683 #ifdef Osirrox_not_yeT
 1684 
 1685  dev_t dir_dev;
 1686  dir_dev= stbuf.st_dev;
 1687 
 1688  if(S_ISLNK(stbuf.st_mode)) {
 1689    if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
 1690      {ret= 2; goto ex;}
 1691    stbuf_src= disk_dir_path;
 1692    if(stat(disk_dir_path, &stbuf)==-1)
 1693      goto cannot_open_dir;
 1694    if(dir_dev != stbuf.st_dev &&
 1695       !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
 1696      {ret= 2; goto ex;}
 1697  }
 1698 
 1699 #endif /* Osirrox_not_yeT */
 1700 
 1701  if(!S_ISDIR(stbuf.st_mode)) {
 1702    Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
 1703    sprintf(xorriso->info_text,"Is not a directory in ISO image: %s",
 1704            Text_shellsafe(img_dir_path, sfe, 0));
 1705    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1706    {ret= 0; goto ex;}
 1707  }
 1708 
 1709  mem= boss_mem;
 1710  ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
 1711                          &node_idx, &node,
 1712                          1 | 4 * (normal_mode && (xorriso->ino_behavior & 4)));
 1713  if(ret<=0)
 1714    goto ex;
 1715 
 1716  if(Sfile_str(img_path, img_dir_path,0)<=0) {
 1717 much_too_long:;
 1718    Xorriso_much_too_long(xorriso, SfileadrL, 2);
 1719    {ret= 0; goto ex;}
 1720  }
 1721  if(img_path[0]==0 || img_path[strlen(img_path)-1]!='/')
 1722    strcat(img_path,"/");
 1723  name= img_path+strlen(img_path);
 1724  if(Sfile_str(disk_path, disk_dir_path, 0)<=0)
 1725    goto much_too_long;
 1726  if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/')
 1727    strcat(disk_path,"/");
 1728  disk_name= disk_path+strlen(disk_path);
 1729 
 1730  len_dp= strlen(disk_path);
 1731  len_ip= strlen(img_path);
 1732 
 1733  while(1) { /* loop over ISO directory content */
 1734    stbuf_src= "";
 1735 
 1736 #ifdef Osirrox_not_yeT
 1737 
 1738    Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 1739 
 1740 #endif
 1741 
 1742    srcpt= img_path;
 1743    Xorriso_process_msg_queues(xorriso,0);
 1744    ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
 1745                            &node_idx, &node, 0);
 1746    if(ret<0)
 1747      goto ex;
 1748    if(ret==0 || xorriso->request_to_abort)
 1749  break;
 1750    leaf_name=  (char *) iso_node_get_name(node);
 1751    if(Xorriso_much_too_long(xorriso, len_dp + strlen(leaf_name)+1, 0)<=0)
 1752      {ret= 0; goto was_problem;}
 1753    if(Xorriso_much_too_long(xorriso, len_ip + strlen(leaf_name)+1, 0)<=0)
 1754      {ret= 0; goto was_problem;}
 1755    /* name and disk_name are pointers into img_path and disk_path */
 1756    strcpy(name, leaf_name);
 1757    strcpy(disk_name,  leaf_name);
 1758    ret= Xorriso_path_is_excluded(xorriso, disk_path, 2);
 1759    if(ret < 0)
 1760      goto was_problem;
 1761    if(ret > 0)
 1762  continue;
 1763 
 1764    stbuf_src= srcpt;
 1765    ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 1);
 1766    if(ret<=0)
 1767      goto was_problem;
 1768    source_is_dir= 0;
 1769 
 1770 #ifdef Osirrox_not_yeT
 1771 
 1772    /* ??? Link following in the image would cause severe problems
 1773           with Xorriso_path_from_node() */
 1774 
 1775    int source_is_link;
 1776 
 1777    source_is_link= S_ISLNK(stbuf.st_mode);
 1778    if(xorriso->do_follow_links && source_is_link) {
 1779      /* Xorriso_hop_link checks for wide link loops */
 1780      ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
 1781      if(ret<0)
 1782        goto was_problem;
 1783      if(ret==1) {
 1784        ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
 1785        if(ret<=0)
 1786          goto was_problem;
 1787        srcpt= link_target;
 1788        stbuf_src= srcpt;
 1789        if(lstat(srcpt, &stbuf)==-1)
 1790          goto cannot_lstat;
 1791      } else {
 1792        if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
 1793          {ret= 0; goto was_problem;} 
 1794      }
 1795    } else if (S_ISLNK(stbuf.st_mode)) {
 1796      ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
 1797      if(ret<=0)
 1798        goto was_problem;
 1799    }
 1800 
 1801 #endif /* Osirrox_not_yeT */
 1802 
 1803    do_not_dive= 0;
 1804    if(S_ISDIR(stbuf.st_mode))
 1805      source_is_dir= 1;
 1806    source_is_split= 0;
 1807    if(source_is_dir)
 1808      source_is_split= Xorriso_is_split(xorriso, img_path, node, 1 | 2 | 4);
 1809    if(source_is_split)
 1810      do_not_dive= 1;
 1811 
 1812    if(source_is_dir || !(dir_create || do_node_count || node_register)) {
 1813      ret= Xorriso_handle_collision(xorriso, node, img_path,
 1814                                    disk_path, disk_path, &stbuf_ret,
 1815                                    (source_is_dir && !source_is_split));
 1816      if(ret<=0 || ret==3)
 1817        goto was_problem;
 1818    } else {
 1819      stbuf_ret= -1;
 1820    }
 1821 
 1822    if(stbuf_ret!=-1) { /* (Can only happen with directory) */
 1823      Xorriso_auto_chmod(xorriso, disk_path, 0);
 1824    } else {
 1825      hflag= 4 | (flag & (2|64));
 1826      if(source_is_dir && !do_not_dive)
 1827        hflag|= 8; /* keep directory open for user */
 1828      if((dir_create || do_node_count) && !source_is_dir) {
 1829        xorriso->node_counter++;
 1830      } else if(node_register && !source_is_dir) {
 1831        if(xorriso->node_counter < xorriso->node_array_size) {
 1832          xorriso->node_array[xorriso->node_counter++]= (void *) node;
 1833          iso_node_ref(node);
 1834        }
 1835      } else if(node_register || do_node_count) {
 1836        ret= 1;
 1837      } else {
 1838        ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
 1839                                         (off_t) 0, (off_t) 0, hflag);
 1840        if(ret == 3) /* intentionally not restored */
 1841          do_not_dive= 1;
 1842      }
 1843      if(ret<=0)
 1844        goto was_problem;
 1845    }
 1846    if(source_is_dir && !do_not_dive) {
 1847      ret= Xorriso_restore_tree(xorriso, (IsoDir *) node,
 1848                                img_path, disk_path, mem,
 1849                                own_link_stack, 1 | (flag & (2 | (3 << 7))));
 1850      /* eventually restore exact access permissions of directory */
 1851      hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
 1852                          !!(flag&64));
 1853      if(hret<=0 && hret<ret)
 1854        ret= hret;
 1855      if(ret<=0)
 1856        goto was_problem;
 1857    }
 1858 
 1859  continue; /* regular bottom of loop */
 1860 was_problem:;
 1861    was_failure= 1;
 1862    fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
 1863    if(fret<0)
 1864      goto ex;
 1865    Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
 1866  }
 1867 
 1868  ret= 1;
 1869 ex:
 1870  Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
 1871  if(sfe!=NULL)
 1872    free(sfe);
 1873  if(sfe2!=NULL)
 1874    free(sfe2);
 1875  if(disk_path!=NULL)
 1876    free(disk_path);
 1877  if(img_path!=NULL)
 1878    free(img_path);
 1879  if(link_target!=NULL)
 1880    free(link_target);
 1881  Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
 1882                     &node_idx, &node, (1u<<31));
 1883 
 1884  Xorriso_process_msg_queues(xorriso,0);
 1885 
 1886 #ifdef Osirrox_not_yeT
 1887 
 1888  Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 1889 
 1890 #endif
 1891 
 1892  if(ret<=0)
 1893    return(ret);
 1894  return(!was_failure);
 1895 }
 1896 
 1897 
 1898 /*
 1899    @param flag
 1900            >>> bit0= mkdir: graft in as empty directory, not as copy from iso
 1901                bit1= do not report copied files
 1902                bit2= -follow, -not_*: this is not a command parameter
 1903                bit3= use offset and cut_size for -paste_in
 1904                bit4= return 3 on rejection by exclusion or user
 1905                bit5= if directory then do not add sub tree
 1906                bit6= this is a copy action: do not fake times and ownership
 1907                bit7+8= operation mode
 1908                      0= direct operation
 1909                      1= create only directories,
 1910                         count nodes in xorriso->node_counter
 1911                      2= only register non-directory nodes in
 1912                         xorriso->node_array
 1913                      3= count nodes in xorriso->node_counter,
 1914                         create no directory
 1915                bit9= with operation mode 1 do net register prefixes
 1916               bit10= with bit3: do not restore properties to leaf file
 1917    @return <=0 = error , 1 = added leaf file object , 2 = added directory ,
 1918                          3 = rejected 
 1919 */
 1920 int Xorriso_restore(struct XorrisO *xorriso,  
 1921                     char *img_path, char *disk_path,
 1922                     off_t offset, off_t bytes, int flag)
 1923 {
 1924  IsoImage *volume;
 1925  char *path= NULL, *apt, *npt;
 1926  IsoNode *node= NULL;
 1927  int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret;
 1928  int dir_create= 0, node_count= 0, node_register= 0, path_size;
 1929  int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0, no_props;
 1930  struct stat stbuf;
 1931  struct PermiteM *perm_stack_mem;
 1932 
 1933  perm_stack_mem= xorriso->perm_stack;
 1934 
 1935  path_size= SfileadrL;
 1936  Xorriso_alloc_meM(path, char, path_size);
 1937 
 1938  switch((flag >> 7) & 3) {
 1939  case 1: dir_create= 1;
 1940  break; case 2: node_register= 1;
 1941  break; case 3: node_count= 1;
 1942  }
 1943  no_props= (!!(flag & 8)) * (flag & 1024);
 1944 
 1945  if(dir_create && !(flag & (1 << 9))) {
 1946    ret= Xorriso_lst_append_binary(&(xorriso->node_disk_prefixes),
 1947                                   disk_path, strlen(disk_path) + 1, 0);
 1948    if(ret <= 0)
 1949      goto ex; 
 1950    ret= Xorriso_lst_append_binary(&(xorriso->node_img_prefixes),
 1951                                   img_path, strlen(img_path) + 1, 0);
 1952    if(ret <= 0)
 1953      goto ex; 
 1954  }
 1955 
 1956  ret= Xorriso_path_is_excluded(xorriso, disk_path, 4 | 2 | !(flag & 4));
 1957  if(ret < 0)
 1958    {ret= 0; goto ex;}
 1959  if(ret > 0) {
 1960    if(!(flag & 4)) {
 1961      strcpy(xorriso->info_text,
 1962             "Excluded from restoring by -not_path or -not_leaf :");
 1963      Text_shellsafe(disk_path, xorriso->info_text, 1);
 1964      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 1965    }
 1966    {ret= 3*!!(flag&16); goto ex;}
 1967  }
 1968 
 1969  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1970  if(ret<=0)
 1971    goto ex;
 1972 
 1973  strncpy(path, disk_path, path_size - 1);
 1974  path[path_size - 1]= 0;
 1975  apt= npt= path;
 1976 
 1977  if(!(flag&1)) {
 1978    ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 0);
 1979    if(ret>0) {
 1980      if(S_ISDIR(stbuf.st_mode))
 1981        is_dir= 1;
 1982 
 1983 #ifdef Osirrox_not_yeT
 1984 
 1985      /* ??? this would cause severe problems with Xorriso_path_from_node() */
 1986 
 1987      else if((stbuf.st_mode&S_IFMT)==S_IFLNK &&
 1988              (xorriso->do_follow_links ||
 1989               (xorriso->do_follow_param && !(flag&4)))) {
 1990        resolve_link= 1;
 1991        ret= Xorriso_iso_lstat(xorriso, img_path, &stbuf, 1|2);
 1992        if(ret!=-1) {
 1993          if(S_ISDIR(stbuf.st_mode))
 1994            is_dir= 1;
 1995        }
 1996      }
 1997 #endif /* Osirrox_not_yeT */
 1998 
 1999    } else {
 2000      Xorriso_process_msg_queues(xorriso,0);
 2001      Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
 2002      sprintf(xorriso->info_text,
 2003             "Cannot determine attributes of (ISO) source file ");
 2004      Text_shellsafe(img_path, xorriso->info_text, 1);
 2005      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2006      ret= 0; goto ex;
 2007    }
 2008    if(is_dir && xorriso->do_concat_split)
 2009      leaf_is_split= Xorriso_is_split(xorriso, img_path, node, 1 | 2 | 4);
 2010  }
 2011  for(npt= apt; !done; apt= npt+1) {
 2012    npt= strchr(apt, '/');
 2013    if(npt==NULL) {
 2014      npt= apt+strlen(apt);
 2015      done= 1;
 2016    } else
 2017      *npt= 0;
 2018    if(*apt==0) {
 2019      *apt= '/';
 2020      apt++;
 2021      if(done)
 2022        goto attach_source;
 2023  continue;
 2024    }
 2025    source_is_dir= (is_dir || (flag&1) || !done);
 2026    source_is_split= done && leaf_is_split;
 2027 
 2028    stbuf_ret= -1;
 2029    if((flag&8) && done) {
 2030 
 2031      /* ??? move down from Xorriso_paste_in() :
 2032             check whether target does not exist or both are suitable */;
 2033 
 2034    } else if(source_is_dir || !(dir_create || node_count || node_register)) {
 2035      ret= Xorriso_handle_collision(xorriso, node, img_path, path, disk_path,
 2036                               &stbuf_ret, (source_is_dir && !source_is_split));
 2037      if(ret<=0 || ret==3)
 2038        goto ex;
 2039    }
 2040 
 2041    new_dir_made= 0;
 2042    if(stbuf_ret==-1 && (source_is_dir && !source_is_split) &&
 2043       !(node_count || node_register)) {
 2044                                                          /* make a directory */
 2045      ret= mkdir(path, 0777);
 2046      if(ret==-1) {
 2047        Xorriso_process_msg_queues(xorriso,0);
 2048        Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
 2049        sprintf(xorriso->info_text,
 2050               "While restoring '%s' : could not insert '%s'", disk_path, path);
 2051        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 2052        {ret= 0; goto ex;}
 2053      }
 2054      if(!done) {
 2055        /* keep rwx for the owner */
 2056        Xorriso_restore_implicit_properties(xorriso, disk_path, path,
 2057                                            img_path, 4);
 2058      }
 2059      new_dir_made= 1;
 2060    } else if((source_is_dir && !source_is_split)) {
 2061      if(!(node_count || node_register))
 2062        Xorriso_auto_chmod(xorriso, path, 0);
 2063    }
 2064    if(done) {
 2065 attach_source:;
 2066 
 2067      if(flag&1) {
 2068        /* directory was created above */;
 2069 
 2070      } else if(is_dir && !source_is_split) {
 2071 
 2072        if(!node_register) {
 2073          if(new_dir_made) { /* keep open and push to Permstack */
 2074            ret= Xorriso_restore_properties(xorriso, disk_path, node,
 2075                                       2 | !!(flag&64));
 2076            if(ret <= 0) {
 2077              hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 2078              if(hret < 0)
 2079                goto ex;
 2080            }
 2081          }
 2082        }
 2083        if(!(flag&32)) {
 2084          ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, img_path, path,
 2085                                   (off_t) 0, NULL, flag & (2 | 64 | (3 << 7)));
 2086          if(ret <= 0) {
 2087            hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 2088            if(hret < 0)
 2089              goto ex;
 2090          }
 2091          if(new_dir_made && !(flag&64))
 2092            /* set timestamps which Permstack_pop() will not set */
 2093            Xorriso_restore_properties(xorriso, disk_path, node, 2);
 2094        }
 2095      } else {
 2096        if(dir_create || node_count) {
 2097          xorriso->node_counter++;
 2098        } else if(node_register) {
 2099          if(xorriso->node_counter < xorriso->node_array_size) {
 2100            xorriso->node_array[xorriso->node_counter++]= (void *) node;
 2101            iso_node_ref(node);
 2102          }
 2103        } else {
 2104          ret= Xorriso_restore_disk_object(xorriso, img_path, node, path,
 2105                      offset, bytes, (flag & (2|4|64)) | no_props | !!(flag&8));
 2106          if(ret <= 0) {
 2107            hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 2108            if(hret < 0)
 2109              goto ex;
 2110          }
 2111        }
 2112      }
 2113    } else
 2114      *npt= '/';
 2115  }
 2116  Xorriso_process_msg_queues(xorriso,0);
 2117  ret= 1 + (is_dir && !leaf_is_split); 
 2118 ex:;
 2119  /* restore exact access permissions of stacked paths */
 2120  hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
 2121                      2 | !!(flag&64));
 2122  if(hret<=0 && hret<ret)
 2123    ret= hret;
 2124  Xorriso_free_meM(path);
 2125  return(ret);
 2126 }
 2127 
 2128 
 2129 int Xorriso_restore_node_array(struct XorrisO *xorriso, int flag)
 2130 {
 2131  int i, ret, fret, hflag, stbuf_ret, faulty_family= 0;
 2132  struct PermiteM *perm_stack_mem;
 2133  char *img_path= NULL, *disk_path= NULL;
 2134  IsoNode *node;
 2135  struct Xorriso_lsT *img_prefixes= NULL, *disk_prefixes= NULL;
 2136 
 2137  perm_stack_mem= xorriso->perm_stack;
 2138 
 2139  Xorriso_alloc_meM(img_path, char, SfileadrL);
 2140  Xorriso_alloc_meM(disk_path, char, SfileadrL);
 2141 
 2142  Xorriso_sort_node_array(xorriso, 0);
 2143 
 2144  disk_path[0]= 0;
 2145  for(i= 0; i < xorriso->node_counter; i++) {
 2146    node= (IsoNode *) xorriso->node_array[i];
 2147    ret= Xorriso_path_from_node(xorriso, node, img_path, 0);
 2148    if(ret < 0)
 2149      goto ex;
 2150    if(ret == 0)
 2151  continue; /* Node is deleted from tree (Should not happen here) */
 2152    hflag= 1;
 2153    if(i == 0) {
 2154      hflag= 0;
 2155    } else if(node != xorriso->node_array[i - 1]) {
 2156      hflag= 0;
 2157    }
 2158    if(hflag == 0) {
 2159      img_prefixes= xorriso->node_img_prefixes;
 2160      disk_prefixes= xorriso->node_disk_prefixes;
 2161    }
 2162    ret= Xorriso_make_restore_path(xorriso, &img_prefixes, &disk_prefixes,
 2163                                   img_path, disk_path, hflag);
 2164    if(ret<=0)
 2165      goto was_problem;
 2166 
 2167    /* (Exclusion must already be handled when the node array gets filled,
 2168        because of no distinction between parameter and tree passenger here.)
 2169     */
 2170 
 2171    ret= Xorriso_handle_collision(xorriso, node, img_path, disk_path, disk_path,
 2172                                  &stbuf_ret, 64);
 2173    if(ret<=0 || ret==3)
 2174      goto was_problem;
 2175    if(xorriso->hln_array != NULL && !(xorriso->ino_behavior & 16)) {
 2176      /* Eventual lookup of hardlinks will be done in
 2177         Xorriso_restore_disk_object() */;
 2178    } else if(i > 0 && !(xorriso->ino_behavior & 4)) {
 2179      if(Xorriso__findi_sorted_ino_cmp(&(xorriso->node_array[i-1]),
 2180                                       &(xorriso->node_array[i])) == 0) {
 2181        if(faulty_family) {
 2182          sprintf(xorriso->info_text, "Hardlinking omitted with ");
 2183          Text_shellsafe(disk_path, xorriso->info_text, 1);
 2184          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 2185        } else {
 2186          /* Try to install hardlink to a sibling */
 2187          ret= Xorriso_restore_prefix_hl(xorriso, node, disk_path, i, 0);
 2188          if(ret < 0) {
 2189            goto was_problem;
 2190          } else if(ret & 1) {
 2191            /* Success, hardlink was created */
 2192            xorriso->pacifier_count++;
 2193  continue;
 2194          }
 2195          if(ret & 4) {
 2196            /* Found elder siblings, but did not link. */
 2197            ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
 2198            if(ret < 0)
 2199              {ret= 0; goto ex;}
 2200          }
 2201        }
 2202      } else
 2203        faulty_family= 0;
 2204    }
 2205 
 2206    ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
 2207                                     (off_t) 0, (off_t) 0,
 2208                                     4 | (xorriso->ino_behavior & 16) | 128);
 2209    if(ret<=0)
 2210      goto was_problem;
 2211    if(ret == 4) {
 2212      /* Failed from lack of permission */
 2213      ret= Xorriso_make_accessible(xorriso, disk_path, 0);
 2214      if(ret < 0)
 2215        goto ex;
 2216      ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
 2217                        (off_t) 0, (off_t) 0, 4 | (xorriso->ino_behavior & 16));
 2218      if(ret<=0)
 2219        goto was_problem;
 2220      Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 2221    }
 2222 
 2223  continue; /* regular bottom of loop */
 2224 was_problem:;
 2225    faulty_family= 1;
 2226    fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
 2227    if(fret<0)
 2228      goto ex;
 2229    Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 2230  }
 2231  ret= 1;
 2232 ex:;
 2233  Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 2234  Xorriso_free_meM(img_path);
 2235  Xorriso_free_meM(disk_path);
 2236  return(ret);
 2237 }
 2238 
 2239 
 2240 /* @param flag bit0= -follow, -not: disk_path is not a command parameter
 2241 */
 2242 int Xorriso_paste_in(struct XorrisO *xorriso, char *disk_path,
 2243                 off_t startbyte, off_t bytecount, char *iso_rr_path, int flag)
 2244 {
 2245  int ret, no_props= 0;
 2246  off_t wanted_size, cap;
 2247  char *eff_source= NULL, *eff_dest= NULL, *reason;
 2248  struct stat stbuf, disk_stbuf;
 2249  IsoNode *node;
 2250 
 2251  Xorriso_alloc_meM(eff_source, char, SfileadrL);
 2252  Xorriso_alloc_meM(eff_dest, char, SfileadrL);
 2253 
 2254  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest,
 2255                                  2|4);
 2256  if(ret<=0)
 2257    goto ex;
 2258  ret= Xorriso_path_is_excluded(xorriso, disk_path, 4 | 2 | !(flag & 1));
 2259  if(ret > 0 && !(flag & 1)) {
 2260    strcpy(xorriso->info_text,
 2261           "Excluded from restoring by -not_path or -not_leaf :");
 2262    Text_shellsafe(disk_path, xorriso->info_text, 1);
 2263    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 2264  }
 2265  if(ret!=0)
 2266    {ret= 0; goto ex;}
 2267 
 2268  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path,
 2269                                  eff_source, 2);
 2270  if(ret<=0)
 2271    goto ex;
 2272  ret= Xorriso_fake_stbuf(xorriso, eff_source, &stbuf, &node, 4);
 2273  if(ret<=0)
 2274    {ret= 0; goto ex;}
 2275  if(!S_ISREG(stbuf.st_mode)) {
 2276    Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0);
 2277    sprintf(xorriso->info_text, "-paste_in: ISO file ");
 2278    Text_shellsafe(eff_source, xorriso->info_text, 1);
 2279    strcat(xorriso->info_text, " is not a data file");
 2280    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2281    {ret= 0; goto ex;}
 2282  }
 2283  
 2284  /* >>> ??? flag bit to obtain startbyte and bytecount from file name */;
 2285 
 2286  ret= lstat(eff_dest, &disk_stbuf);
 2287  if(ret != -1) {
 2288    no_props= 1 << 10;
 2289    wanted_size= startbyte + bytecount;
 2290    if(wanted_size > stbuf.st_size)
 2291      wanted_size= stbuf.st_size;
 2292    cap= wanted_size;
 2293    ret= Xorriso_determine_capacity(xorriso, eff_dest, &cap, &reason, 3);
 2294    if(ret <= 0 || (cap <= 0 && !S_ISREG(disk_stbuf.st_mode))) {
 2295      Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0);
 2296      if(ret > 0)
 2297        reason= "has addressable range 0";
 2298      sprintf(xorriso->info_text, "-paste_in: DISK file (%s) ",
 2299              Ftypetxt(disk_stbuf.st_mode, 0));
 2300      Text_shellsafe(eff_dest, xorriso->info_text, 1); 
 2301      sprintf(xorriso->info_text + strlen(xorriso->info_text),
 2302              " exists but %s", reason);
 2303      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2304      {ret= 0; goto ex;}
 2305    }
 2306    if(cap < wanted_size && !S_ISREG(disk_stbuf.st_mode)) {
 2307 
 2308      /* >>> non-regular file might be too small to take the interval */;
 2309 
 2310    }
 2311  }
 2312 
 2313  ret= Xorriso_restore(xorriso, eff_source, eff_dest, startbyte, bytecount,
 2314                       8 | no_props);
 2315 ex:;
 2316  Xorriso_free_meM(eff_source);
 2317  Xorriso_free_meM(eff_dest);
 2318  return(ret);
 2319 }
 2320 
 2321 
 2322 int Xorriso_extract_cut(struct XorrisO *xorriso,
 2323                         char *img_path, char *disk_path,
 2324                         off_t img_offset, off_t bytes, int flag)
 2325 {
 2326  int ret, stbuf_ret, read_raw;
 2327  double mem_lut= 0.0;
 2328  char *eff_img_path= NULL, *eff_disk_path= NULL;
 2329  IsoImage *volume;
 2330  IsoNode *node;
 2331 
 2332  Xorriso_alloc_meM(eff_img_path, char, SfileadrL);
 2333  Xorriso_alloc_meM(eff_disk_path, char, SfileadrL);
 2334 
 2335  ret= Xorriso_get_volume(xorriso, &volume, 0); 
 2336  if(ret<=0)
 2337    goto ex;
 2338  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi,
 2339                                  img_path, eff_img_path, 0);
 2340  if(ret<=0)
 2341    goto ex;
 2342  ret= Xorriso_node_from_path(xorriso, volume, eff_img_path, &node, 0);
 2343  if(ret<=0)
 2344    goto ex;
 2345  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx,
 2346                                  disk_path, eff_disk_path, 2 | 4);
 2347  if(ret<=0)
 2348    goto ex;
 2349  ret= Xorriso_path_is_excluded(xorriso, eff_disk_path, 1 | 2 | 4);
 2350  if(ret < 0)
 2351    goto ex;
 2352  if(ret > 0) {
 2353    strcpy(xorriso->info_text,
 2354           "Excluded from restoring by -not_path or -not_leaf :");
 2355    Text_shellsafe(eff_disk_path, xorriso->info_text, 1);
 2356    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 2357    {ret= 0; goto ex;}
 2358  }
 2359 
 2360  /* If it is a non-filtered stream from the ISO image
 2361     and img_offset is a multiple of 2048
 2362     then use Xorriso_read_file_data() for random access offset.
 2363  */
 2364  if(!LIBISO_ISREG(node)) {
 2365    Xorriso_msgs_submit(xorriso, 0, eff_disk_path, 0, "ERRFILE", 0);
 2366    sprintf(xorriso->info_text, "-extract_cut: ISO file ");
 2367    Text_shellsafe(eff_img_path, xorriso->info_text, 1);
 2368    strcat(xorriso->info_text, " is not a data file");
 2369    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2370    {ret= 0; goto ex;}
 2371  }
 2372  ret= Xorriso_handle_collision(xorriso, node, img_path, eff_disk_path,
 2373                                disk_path, &stbuf_ret, 0);
 2374  if(ret<=0 || ret==3)
 2375    {ret= 0; goto ex;}
 2376 
 2377  Xorriso_pacifier_reset(xorriso, 0);
 2378  mem_lut= xorriso->last_update_time;
 2379  read_raw= 0;
 2380  if((img_offset % 2048) == 0) {
 2381    ret= Xorriso_is_plain_image_file(xorriso, node, "", 0);
 2382    if(ret > 0)
 2383      read_raw= 1;
 2384  }
 2385  if (read_raw) {
 2386    ret= Xorriso_read_file_data(xorriso, node, eff_img_path, eff_disk_path,
 2387                                img_offset, (off_t) 0, bytes, 0);
 2388    if(ret<=0)
 2389      goto ex;
 2390  } else {
 2391    ret= Xorriso_tree_restore_node(xorriso, node, eff_img_path, img_offset,
 2392                                   eff_disk_path, (off_t) 0, bytes, 2 | 8);
 2393    if(ret<=0)
 2394      goto ex;
 2395  }
 2396 
 2397  ret= Xorriso_restore_properties(xorriso, eff_disk_path, node, 0);
 2398  if(ret<=0)
 2399    goto ex;
 2400 
 2401  if(mem_lut != xorriso->last_update_time)
 2402    Xorriso_pacifier_callback(xorriso, "blocks read",
 2403                              xorriso->pacifier_count, 0, "", 1 | 8 | 16 | 32);
 2404  ret= 1;
 2405 ex:;
 2406  Xorriso_free_meM(eff_img_path);
 2407  Xorriso_free_meM(eff_disk_path);
 2408  return(ret);
 2409 }
 2410 
 2411 
 2412 /* @param flag bit0= ignore node and img_path, operate on whole medium
 2413                bit1= for Xorriso_check_interval(): no pacifier messages
 2414 */
 2415 int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node,
 2416                            char *img_path, char *disk_path,
 2417                            off_t img_offset, off_t disk_offset,
 2418                            off_t bytes, int flag)
 2419 {
 2420  int ret, i, lba_count= 0, *start_lbas= NULL, *end_lbas= NULL, read_chunk= 16;
 2421  int lba, count, blocks, quality, spot, bad_extract= 0;
 2422  int data_to_skip= 0;
 2423  uint32_t indev_blocks;
 2424  off_t size= 0, file_base_bytes= 0, file_processed_bytes= 0, img_adr;
 2425  off_t new_file_base_bytes, upto_file_bytes, start_byte= 0;
 2426  off_t *section_sizes = NULL;
 2427  struct SpotlisT *spotlist= NULL;
 2428  struct CheckmediajoB *job= NULL;
 2429 
 2430  upto_file_bytes= img_offset + bytes;
 2431  data_to_skip= img_offset % (off_t) 2048;
 2432 
 2433  if(flag & 1) {
 2434    lba_count= 1;
 2435    Xorriso_alloc_meM(start_lbas, int, 1);
 2436    Xorriso_alloc_meM(end_lbas, int, 1);
 2437    Xorriso_alloc_meM(section_sizes, off_t, 1);
 2438    start_lbas[0]= 0;
 2439    ret= Xorriso_obtain_indev_readsize(xorriso, &indev_blocks, 0);
 2440    if(ret > 0)
 2441      end_lbas[0]= indev_blocks - 1;
 2442    else
 2443      end_lbas[0]= 0x7ffffffe;
 2444    size= ((off_t) end_lbas[0]) * 2048;
 2445    section_sizes[0]= size;
 2446  } else {
 2447    ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
 2448                                 &section_sizes,  &size, 0);
 2449    if(ret <= 0) {
 2450      Xorriso_process_msg_queues(xorriso,0);
 2451      sprintf(xorriso->info_text, "File object ");
 2452      Text_shellsafe(img_path, xorriso->info_text, 1);
 2453      strcat(xorriso->info_text,
 2454             " is currently not a data file from the loaded image");
 2455      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2456      goto ex;
 2457    }
 2458  }
 2459  if(img_offset + bytes < size && bytes > 0)
 2460    size= img_offset + bytes;
 2461 
 2462  ret= Checkmediajob_new(&job, 0);
 2463  if(ret <= 0)
 2464    goto ex;
 2465  if(xorriso->check_media_default != NULL)
 2466    Checkmediajob_copy(xorriso->check_media_default, job, 0);
 2467  job->min_lba= -1;
 2468  job->max_lba= -1;
 2469  job->sector_map_path[0]= 0;
 2470 
 2471  ret= Spotlist_new(&spotlist, 0);
 2472  if(ret <= 0)
 2473    {ret= -1; goto ex;}
 2474 
 2475  if(Sfile_str(job->data_to_path, disk_path, 0) <= 0)
 2476    {ret= -1; goto ex;}
 2477  ret= Xorriso_open_job_data_to(xorriso, job, 0);
 2478  if(ret <= 0)
 2479    goto ex;
 2480 
 2481  for(i= 0; i < lba_count && file_base_bytes < upto_file_bytes; i++) {
 2482    lba= start_lbas[i];
 2483    count= end_lbas[i] + 1 - start_lbas[i];
 2484    new_file_base_bytes= file_base_bytes + ((off_t) count) * (off_t) 2048;
 2485 
 2486    /* skip intervals before img_offset */
 2487    if(new_file_base_bytes <= img_offset) {
 2488      file_base_bytes= new_file_base_bytes;
 2489  continue;
 2490    }
 2491    /* Eventually adjust first interval start */
 2492    img_adr= ((off_t) lba) * (off_t) 2048;
 2493    if(file_base_bytes < img_offset) {
 2494      img_adr+= img_offset - file_base_bytes;
 2495      lba= img_adr / (off_t) 2048;
 2496      count= end_lbas[i] + 1 - lba;
 2497      file_base_bytes= img_offset;
 2498    }
 2499 
 2500    /* Omit surplus blocks */
 2501    if(new_file_base_bytes > upto_file_bytes)
 2502      count-= (new_file_base_bytes - upto_file_bytes) / (off_t) 2048;
 2503    /* Adjust job */
 2504    job->data_to_offset= file_processed_bytes - img_adr + disk_offset;
 2505    job->data_to_limit= size - file_base_bytes;
 2506    job->data_to_skip= data_to_skip;
 2507    data_to_skip= 0;
 2508    file_processed_bytes+= ((off_t) count) * (off_t) 2048;
 2509    ret= Xorriso_check_interval(xorriso, spotlist, job, lba, count, read_chunk,
 2510                                0, (flag & 2));
 2511    if(ret <= 0)
 2512      goto ex;
 2513    if (ret == 2) {
 2514      sprintf(xorriso->info_text, "Attempt aborted to extract data from ");
 2515      Text_shellsafe(img_path, xorriso->info_text, 1);
 2516      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2517      ret= 0; goto ex;
 2518    }
 2519    file_base_bytes= new_file_base_bytes;
 2520  } 
 2521 
 2522  /* Use spotlist to evaluate damage */
 2523  file_base_bytes= 0;
 2524  count= Spotlist_count(spotlist, 0);
 2525  for(spot= 0; spot < count; spot++) {
 2526    ret= Spotlist_get_item(spotlist, spot, &lba, &blocks, &quality, 0);
 2527    if(ret <= 0)
 2528  continue;
 2529    if(quality < Xorriso_read_quality_valiD) {
 2530      for(i= 0; i < lba_count; i++) {
 2531        if(start_lbas[i] <= lba && end_lbas[i] >= lba) {
 2532          start_byte= (lba - start_lbas[i]) * (off_t) 2048 + file_base_bytes;
 2533      break;
 2534        }
 2535        file_base_bytes+= ((off_t) (end_lbas[i] + 1 - start_lbas[i]))
 2536                           * (off_t) 2048;
 2537      }
 2538      if(i < lba_count) {
 2539        sprintf(xorriso->info_text, "Bad extract  : %14.f , %14.f , ",
 2540                (double) start_byte, ((double) blocks) * 2048.0);
 2541        Text_shellsafe(disk_path, xorriso->info_text, 1);
 2542        strcat(xorriso->info_text, "\n");
 2543        Xorriso_info(xorriso, 0);
 2544        bad_extract= 1;
 2545      }
 2546    }
 2547  }
 2548 
 2549  ret= !bad_extract;
 2550 ex:;
 2551  if(start_lbas != NULL)
 2552    free((char *) start_lbas);
 2553  if(end_lbas != NULL)
 2554    free((char *) end_lbas);
 2555  if(section_sizes != NULL)
 2556    free((char *) section_sizes);
 2557  Spotlist_destroy(&spotlist, 0);
 2558  Checkmediajob_destroy(&job, 0);
 2559  return(ret);
 2560 }
 2561 
 2562 
 2563 int Xorriso_extract_boot_images(struct XorrisO *xorriso, char *disk_dir_path,
 2564                                 int flag)
 2565 {
 2566  int ret, img_count= 0, i, was_problem= 0;
 2567  char **imgs= NULL, *eff_path= NULL, *cpt, *eff_namept;
 2568  struct stat stbuf;
 2569  off_t byte_offset, byte_size;
 2570 
 2571  Xorriso_alloc_meM(eff_path, char, SfileadrL);
 2572  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_dir_path,
 2573                                  eff_path, 2 | 4);
 2574  if(ret <= 0)
 2575    goto ex;
 2576  if(strlen(eff_path) > SfileadrL - 80) {
 2577    sprintf(xorriso->info_text,
 2578            "-extract_boot_images: disk_path is too long (%lu)\n",
 2579            (unsigned long int) strlen(eff_path));
 2580    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2581    ret= 0; goto ex;
 2582  }
 2583  ret= stat(eff_path, &stbuf);
 2584  if(ret == 0) {
 2585    if(!S_ISDIR(stbuf.st_mode)) {
 2586      sprintf(xorriso->info_text,
 2587              "-extract_boot_images: disk_path is not a directory : ");
 2588      Text_shellsafe(eff_path, xorriso->info_text, 1);
 2589      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2590      ret= 0; goto ex;
 2591    }
 2592  } else {
 2593    ret= mkdir(eff_path, 0777);
 2594    if(ret == -1) {
 2595      sprintf(xorriso->info_text,
 2596              "-extract_boot_images: cannot create directory : ");
 2597      Text_shellsafe(eff_path, xorriso->info_text, 1);
 2598      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2599      ret= 0; goto ex;
 2600    }
 2601  }
 2602  strcat(eff_path, "/");
 2603  eff_namept= eff_path + strlen(eff_path);
 2604 
 2605  ret= Xorriso_list_boot_images(xorriso, &imgs, &img_count, 0);
 2606  if(ret <= 0)
 2607    goto ex;
 2608 
 2609  /* Interpret list and create files */
 2610  for(i= 0; i < img_count; i++) {
 2611    ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
 2612    if(ret < 0)
 2613      {ret= 0; goto ex;}
 2614    cpt= strchr(imgs[i], '/');
 2615    if(cpt == NULL)
 2616  continue;
 2617    *cpt= 0;
 2618    cpt+= 2;
 2619    ret= Sfile_text_to_off_t(cpt, &byte_offset, 0);
 2620    if(ret <= 0)
 2621  continue;
 2622    cpt+= ret;
 2623    if(*cpt == 0)
 2624  continue;
 2625    cpt++;
 2626    ret= Sfile_text_to_off_t(cpt, &byte_size, 0);
 2627    if(ret <= 0)
 2628  continue;
 2629 
 2630    strcpy(eff_namept, imgs[i]);
 2631    sprintf(xorriso->info_text, "%s : offset=%.f size=%.f\n",
 2632            eff_path, (double) byte_offset, (double) byte_size);
 2633    Xorriso_info(xorriso, 0);
 2634 
 2635    ret= stat(eff_path, &stbuf);
 2636    if(ret != -1) {
 2637      sprintf(xorriso->info_text,
 2638              "-extract_boot_images: File already exists on disk: ");
 2639      Text_shellsafe(eff_path, xorriso->info_text, 1);
 2640      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2641  continue;
 2642    }
 2643    ret= Xorriso_read_file_data(xorriso, NULL, NULL, eff_path,
 2644                                byte_offset, (off_t) 0, byte_size, 1);
 2645    if(ret <= 0)
 2646      was_problem= 1;
 2647  }
 2648  ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
 2649  if(ret < 0 || was_problem)
 2650    {ret= 0; goto ex;}
 2651  
 2652  ret= 1;
 2653 ex:;
 2654  Xorriso_free_meM(eff_path);
 2655  Xorriso_list_boot_images(xorriso, &imgs, &img_count, 1 << 15);
 2656  return(ret);
 2657 }
 2658 
 2659 
 2660 /* @param node      Opaque handle to IsoNode which is to be inquired instead of                     path if it is not NULL.
 2661    @param path      is used as address if node is NULL.
 2662    @param flag      bit0= do not report to result but only indicate outcome
 2663                           by return value
 2664                     bit1= silently ignore nodes without MD5
 2665                     bit2= do not only report mismatches but also matches
 2666    @return          3= not a data file
 2667                     2= no MD5 attached to node
 2668                     1= ok, MD5 compared and matching
 2669                     0= not ok, MD5 mismatch
 2670                    <0= other error
 2671 */
 2672 int Xorriso_check_md5(struct XorrisO *xorriso, void *in_node, char *path,
 2673                       int flag)
 2674 {
 2675  int ret, wanted, rret, buffer_size= 64 * 1024;
 2676  IsoImage *image;
 2677  IsoNode *node;
 2678  IsoFile *file;
 2679  char node_md5[16], data_md5[16], *buffer= NULL;
 2680  void *stream= NULL, *ctx= NULL;
 2681  off_t todo;
 2682 
 2683  Xorriso_alloc_meM(buffer, char, 64 * 1024);
 2684 
 2685  node= (IsoNode *) in_node;
 2686  if(node == NULL) {
 2687    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2688    if(ret<=0)
 2689      {ret= -1; goto ex;}
 2690  }
 2691  if(!LIBISO_ISREG(node)) {
 2692    strcpy(xorriso->info_text, "-check_md5: Not a data file: ");
 2693    Text_shellsafe(path, xorriso->info_text, 1);
 2694    if(!(flag & 2))
 2695      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2696    ret= 3; goto ex;
 2697  }
 2698  file= (IsoFile *) node;
 2699 
 2700  /* obtain MD5 */
 2701  ret= Xorriso_get_volume(xorriso, &image, 0);
 2702  if(ret <= 0)
 2703    {ret= -1; goto ex;}
 2704  ret= iso_file_get_md5(image, file, node_md5, 0);
 2705  Xorriso_process_msg_queues(xorriso,0);
 2706  if(ret < 0)
 2707    {ret= -1; goto ex;}
 2708  if(ret == 0) {
 2709    strcpy(xorriso->info_text, "-check_md5: No MD5 recorded with file: ");
 2710    Text_shellsafe(path, xorriso->info_text, 1);
 2711    if(!(flag & 2))
 2712      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2713    ret= 2; goto ex;
 2714  }
 2715 
 2716  /* Read file and compute MD5 */;
 2717  ret= Xorriso_iso_file_open(xorriso, path, (void *) node, &stream, 1 | 2);
 2718  if(ret <= 0)
 2719    {ret= -1; goto ex;}
 2720  ret= iso_md5_start(&ctx);
 2721  if(ret < 0)
 2722      goto ex;
 2723  todo= iso_stream_get_size(stream);
 2724  while(todo > 0) {
 2725    if(todo < buffer_size)
 2726      wanted= todo;
 2727    else
 2728      wanted= buffer_size;
 2729    rret = Xorriso_iso_file_read(xorriso, stream, buffer, wanted, 0);
 2730    if(rret <= 0)
 2731      {ret= -1; goto ex;}
 2732    todo-= rret;
 2733    ret = iso_md5_compute(ctx, buffer, rret);
 2734    if(ret < 0)
 2735      goto ex;
 2736    xorriso->pacifier_count+= rret; 
 2737    xorriso->pacifier_byte_count+= rret;
 2738    Xorriso_pacifier_callback(xorriso, "content bytes read",
 2739                              xorriso->pacifier_count, 0, "", 8);
 2740    ret= Xorriso_check_for_abort(
 2741              xorriso,
 2742              xorriso->check_media_default != NULL 
 2743                 ? xorriso->check_media_default->abort_file_path
 2744                 : "/var/opt/xorriso/do_abort_check_media",
 2745              Sfile_microtime(0), &xorriso->last_abort_file_time, 0);
 2746    if(ret == 1)
 2747      {ret= -2; goto ex;}
 2748  }
 2749  ret= iso_md5_end(&ctx, data_md5);
 2750  if(ret < 0)
 2751      goto ex;
 2752 
 2753  /* Report outcome */
 2754  Xorriso_process_msg_queues(xorriso,0);
 2755  if(! iso_md5_match(node_md5, data_md5)) {
 2756    sprintf(xorriso->result_line, "MD5 MISMATCH: ");
 2757    Text_shellsafe(path, xorriso->result_line, 1);
 2758    strcat(xorriso->result_line, "\n");
 2759    if(!(flag & 1))
 2760      Xorriso_result(xorriso,0);
 2761    ret= 0;
 2762  } else {
 2763    sprintf(xorriso->result_line, "md5 match   : ");
 2764    Text_shellsafe(path, xorriso->result_line, 1);
 2765    strcat(xorriso->result_line, "\n");
 2766    if(flag & 4)
 2767      Xorriso_result(xorriso,0);
 2768    ret= 1;
 2769  }
 2770 
 2771 ex:;
 2772  Xorriso_process_msg_queues(xorriso,0);
 2773  Xorriso_iso_file_close(xorriso, &stream, 0);
 2774  if(ctx != NULL)
 2775    iso_md5_end(&ctx, data_md5);
 2776  Xorriso_free_meM(buffer);
 2777  if(ret < 0) {
 2778    if(ret == -2)
 2779      sprintf(xorriso->result_line, "Aborted at: ");
 2780    else
 2781      sprintf(xorriso->result_line, "NOT READABLE: ");
 2782    Text_shellsafe(path, xorriso->result_line, 1);
 2783    strcat(xorriso->result_line, "\n");
 2784    if(!(flag & 1))
 2785      Xorriso_result(xorriso,0);
 2786    if(ret == -2)
 2787      xorriso->request_to_abort= 1;
 2788  }
 2789  return(ret);
 2790 }
 2791