"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/xorriso/read_run.c" (30 Jan 2021, 84682 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.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 last Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.5.4.

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