"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/xorriso/iso_manip.c" (30 Jan 2021, 144132 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 "iso_manip.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 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2019 Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains functions which manipulate the libisofs tree model.
    9 */
   10 
   11 #ifdef HAVE_CONFIG_H
   12 #include "../config.h"
   13 #endif
   14 
   15 #include <ctype.h>
   16 #include <sys/types.h>
   17 #include <unistd.h>
   18 #include <stdlib.h>
   19 #include <stdio.h>
   20 #include <string.h>
   21 #include <sys/stat.h>
   22 #include <sys/time.h>
   23 #include <time.h>
   24 #include <errno.h>
   25 
   26 
   27 #include "xorriso.h"
   28 #include "xorriso_private.h"
   29 #include "xorrisoburn.h"
   30 
   31 #include "lib_mgt.h"
   32 #include "iso_img.h"
   33 #include "iso_tree.h"
   34 #include "iso_img.h"
   35 #include "iso_manip.h"
   36 #include "sort_cmp.h"
   37 #include "parse_exec.h"
   38 #include "write_run.h"
   39 
   40 
   41 
   42 /* @param flag bit0= give directory x-permission where is r-permission
   43                bit1= do not transfer ACL or xattr
   44                bit2= record dev,inode (only if enabled by xorriso)
   45                bit3= with bit0: pretend to have indeed a directory
   46                bit5= transfer ACL or xattr from eventual link target
   47 */
   48 int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
   49                                char *disk_path,  IsoNode *node, int flag)
   50 {
   51  mode_t mode;
   52  int ret= 1;
   53  size_t num_attrs= 0, *value_lengths= NULL;
   54  char **names= NULL, **values= NULL;
   55 
   56  mode= stbuf->st_mode;
   57 
   58  if((!(flag & 2)) && !(xorriso->do_aaip & 1))
   59    /* Will drop ACL. Update mode S_IRWXG by eventual group:: ACL entry */
   60    iso_local_get_perms_wo_acl(disk_path, &mode, flag & 32);
   61 
   62  if((flag & 1) && ((flag & 8) || S_ISDIR(mode))) {
   63    if(mode&S_IRUSR)
   64      mode|= S_IXUSR;
   65    if(mode&S_IRGRP)
   66      mode|= S_IXGRP;
   67    if(mode&S_IROTH)
   68      mode|= S_IXOTH;
   69  }
   70  iso_node_set_permissions(node, mode & 07777);
   71  iso_node_set_uid(node, stbuf->st_uid);
   72  iso_node_set_gid(node, stbuf->st_gid);
   73  iso_node_set_atime(node, stbuf->st_atime);
   74  iso_node_set_mtime(node, stbuf->st_mtime);
   75  iso_node_set_ctime(node, stbuf->st_ctime);
   76 
   77  if((xorriso->do_aaip & 5) && !(flag & 2)) {
   78    ret= iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
   79                             &values, ((xorriso->do_aaip & 1) && !(flag & 2))
   80                                      | ((!(xorriso->do_aaip & 4)) << 2)
   81                                      | (flag & 32));
   82    if(ret < 0) { 
   83      Xorriso_process_msg_queues(xorriso,0);
   84      Xorriso_report_iso_error(xorriso, disk_path, ret,
   85                               "Error when obtaining local ACL and xattr", 0,
   86                               "FAILURE", 1 | 2);
   87      ret= 0; goto ex;
   88    }
   89 
   90    /* Preserve namespace isofs, but not ACL or system xattr */
   91    ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
   92                            1 | 8 | 16);
   93    if(ret < 0) {
   94      Xorriso_process_msg_queues(xorriso,0);
   95      Xorriso_report_iso_error(xorriso, "", ret,
   96                               "Error when setting ACL and xattr to image node",
   97                               0, "FAILURE", 1);
   98      ret= 0; goto ex;
   99    }
  100  }
  101 
  102  if((flag & 4) && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
  103    ret= Xorriso_record_dev_inode(xorriso, disk_path, (dev_t) 0, (ino_t) 0,
  104                                  (void *) node, "", flag & 32);
  105    if(ret <= 0)
  106      goto ex;
  107  }
  108 
  109  ret= 1;
  110 ex:;
  111  Xorriso_process_msg_queues(xorriso,0);
  112  iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
  113                       &values, 1 << 15); /* free memory */
  114  return(ret);
  115 }
  116 
  117 
  118 int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume,
  119                         IsoDir *dir, char *disk_path, char *img_name,
  120                         char *nominal_source, char *nominal_target,
  121                         off_t size, IsoNode **node, int flag)
  122 {
  123  int ret;
  124  IsoDir *new_dir= NULL;
  125  IsoNode *part_node;
  126  int partno, total_parts;
  127  off_t offset;
  128  char *part_name= NULL;
  129 
  130  Xorriso_alloc_meM(part_name, char, SfileadrL);
  131 
  132  ret= iso_image_add_new_dir(volume, dir, img_name, &new_dir);
  133  if(ret < 0)
  134    goto ex;
  135  *node= (IsoNode *) new_dir;
  136  if(xorriso->update_flags & 1) {
  137    ret= Xorriso_mark_update_merge(xorriso, img_name, node, 1);
  138    if(ret <= 0)
  139      {ret= 0; goto ex;}
  140  }
  141  total_parts= size / xorriso->split_size;
  142  if(size % xorriso->split_size)
  143    total_parts++;
  144  for(partno= 1; partno<=total_parts; partno++) {
  145    offset = xorriso->split_size * (off_t) (partno-1);
  146    Splitpart__compose(part_name, partno, total_parts, offset,
  147                       xorriso->split_size, size, 0);
  148    ret= Xorriso_tree_graft_node(xorriso, volume,
  149                                 new_dir, disk_path, part_name,
  150                                 nominal_source, nominal_target,
  151                                 offset, xorriso->split_size,
  152                                 &part_node, 8);
  153    if(ret<=0)
  154      goto ex;
  155  }
  156  sprintf(xorriso->info_text, "Split into %d parts: ", total_parts);
  157  Text_shellsafe(nominal_target, xorriso->info_text, 1);
  158  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  159  ret= 1;
  160 ex:;
  161  Xorriso_free_meM(part_name);
  162  return(ret);
  163 }
  164 
  165 
  166 /* 
  167    @param flag bit0= ISO_NODE_NAME_NOT_UNIQUE exception mode:
  168                      Do not issue message. Return existing node into *node.
  169                bit1= if name truncation happens: copy truncated into img_name
  170                bit3= cut_out_node: offset and size are valid
  171                bit8= hide in iso_rr
  172                bit9= hide in joliet
  173               bit10= hide in hfsplus
  174 */
  175 int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
  176                             IsoDir *dir, char *disk_path, char *img_name,
  177                             char *nominal_source, char *nominal_target,
  178                             off_t offset, off_t cut_size,
  179                             IsoNode **node, int flag)
  180 {
  181  int ret, stbuf_valid= 0;
  182  struct stat stbuf;
  183  char *namept, *eff_name, *trunc_name= NULL;
  184  off_t size= 0;
  185 
  186  eff_name= img_name;
  187  if(lstat(disk_path, &stbuf) != -1) {
  188    stbuf_valid= 1;
  189    if(S_ISREG(stbuf.st_mode))
  190      size= stbuf.st_size;
  191  }
  192  if((int) strlen(eff_name) > xorriso->file_name_limit) {
  193    Xorriso_alloc_meM(trunc_name, char, SfileadrL);
  194    strncpy(trunc_name, eff_name, SfileadrL - 1);
  195    trunc_name[SfileadrL - 1]= 0;
  196    ret= iso_truncate_leaf_name(1, xorriso->file_name_limit, trunc_name, 0);
  197    if(ret < 0)
  198      goto ex;
  199    strcpy(xorriso->info_text, "File name had to be truncated and MD5 marked: ");
  200    Text_shellsafe(eff_name, xorriso->info_text, 1);
  201    strcat(xorriso->info_text, " -> ");
  202    Text_shellsafe(trunc_name, xorriso->info_text, 1);
  203    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
  204    eff_name= trunc_name;
  205    if(flag & 2)
  206      strcpy(img_name, trunc_name);
  207  }
  208  if(flag&8)  {
  209    if(cut_size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
  210      sprintf(xorriso->info_text,
  211              "File piece exceeds size limit of %.f bytes: %.f from ",
  212              (double) xorriso->file_size_limit, (double) cut_size);
  213      Text_shellsafe(disk_path, xorriso->info_text, 1);
  214      strcat(xorriso->info_text, "\n");
  215      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  216      return(0);
  217    }
  218    ret= iso_tree_add_new_cut_out_node(volume, dir, eff_name, disk_path,
  219                                       offset, cut_size, node);
  220    if(ret<0)
  221      goto ex;
  222  } else {
  223    if(xorriso->split_size > 0 && size > xorriso->split_size) {
  224      ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, eff_name,
  225                               nominal_source, nominal_target, size,
  226                               node, 0);
  227      if(ret<=0)
  228        goto ex;
  229    } else if(size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
  230      sprintf(xorriso->info_text,
  231              "File exceeds size limit of %.f bytes: ",
  232              (double) xorriso->file_size_limit);
  233      Text_shellsafe(disk_path, xorriso->info_text, 1);
  234      strcat(xorriso->info_text, "\n");
  235      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  236      return(0);
  237    } else {
  238      ret= iso_tree_add_new_node(volume, dir, eff_name, disk_path, node);
  239      if(ret<0)
  240        goto ex;
  241    }
  242  }
  243  if(flag & (256 | 512 | 1024)) {
  244    ret= Xorriso_set_hidden(xorriso, (void *) *node, "",  (flag >> 8) & 7, 0);
  245    if(ret <= 0)
  246      goto ex;
  247  }
  248  if(stbuf_valid && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
  249    ret= Xorriso_record_dev_inode(xorriso, disk_path,
  250                             stbuf.st_dev, stbuf.st_ino, (void *) *node, "", 1);
  251    if(ret <= 0)
  252      goto ex;
  253  }
  254  if(xorriso->update_flags & 1) {
  255    ret= Xorriso_mark_update_merge(xorriso, eff_name, *node, 1);
  256    if(ret <= 0)
  257      goto ex;
  258  }
  259 
  260 ex:;
  261  if(ret<0) {
  262    if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE && (flag & 1)) {
  263      iso_image_dir_get_node(volume, dir, eff_name, node, 0);
  264    } else {
  265      Xorriso_process_msg_queues(xorriso,0);
  266      if(ret == (int) ISO_RR_NAME_TOO_LONG ||
  267         ret == (int) ISO_RR_NAME_RESERVED ||
  268         ret == (int) ISO_RR_PATH_TOO_LONG)
  269        namept= nominal_target;
  270      else
  271        namept= nominal_source;
  272      Xorriso_report_iso_error(xorriso, namept, ret,
  273                               "Cannot add node to tree", 0, "FAILURE", 1|2);
  274    }
  275  } else {
  276    if(LIBISO_ISREG(*node))
  277      xorriso->pacifier_byte_count+= iso_file_get_size((IsoFile *) *node);
  278    ret= 1;
  279  }
  280  Xorriso_free_meM(trunc_name);
  281  return(ret);
  282 }
  283 
  284 
  285 /*
  286    @param boss_iter Opaque handle to be forwarded to actions in ISO image
  287                     Set to NULL if calling this function without having
  288                     a boss iterator object.
  289    @param node      Pointer to pointer to existing node,
  290                     *node is set to NULL, if the node gets removed.
  291    @param flag bit0= source is directory
  292                bit4= return 3 on rejection by exclusion or user
  293                bit6= do not delete eventually existing node from di_array
  294                bit7= no special handling of split file directories
  295    @return     1= no action was needed, 2= target removed,
  296                3= rejected with bit4, <=0 means error
  297 */
  298 int Xoriso_handle_collision(struct XorrisO *xorriso, void *boss_iter,
  299                             IsoNode **node, char *img_path,
  300                             char *full_img_path, char *disk_path,
  301                             char *show_path, int flag)
  302 {
  303  int ret, target_is_dir, target_is_split, source_is_dir;
  304 
  305  source_is_dir= flag & 1;
  306  target_is_dir= LIBISO_ISDIR(*node);
  307 
  308  target_is_split= 0;
  309  if(target_is_dir && !(flag & 128))
  310    target_is_split= Xorriso_is_split(xorriso, "", (void *) *node, 1 | 2);
  311 
  312  if(!((target_is_dir && !target_is_split) && source_is_dir)) {
  313    Xorriso_process_msg_queues(xorriso, 0);
  314 
  315    /* handle overwrite situation */;
  316    if(xorriso->do_overwrite == 1 ||
  317       (xorriso->do_overwrite == 2 && !(target_is_dir && !target_is_split))) {
  318      ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, img_path,
  319                       1 | 8 | (flag & 64));
  320      if(ret <= 0)
  321        return(ret);
  322      if(ret == 3) {
  323        sprintf(xorriso->info_text, "User revoked adding of: ");
  324        Text_shellsafe(show_path, xorriso->info_text, 1);
  325        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  326        return(3 * !!(flag & 16));
  327      }
  328      *node= NULL;
  329      return(2);
  330    }
  331 
  332    if (disk_path[0])
  333      Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  334    if(strcmp(full_img_path, img_path) == 0)
  335      sprintf(xorriso->info_text,
  336          "While grafting '%s' : file object exists and may not be overwritten",
  337          img_path);
  338    else
  339      sprintf(xorriso->info_text,
  340             "While grafting '%s' : '%s' exists and may not be overwritten",
  341             full_img_path, img_path);
  342    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  343    return(0);
  344  }
  345  return(1);
  346 }
  347 
  348 
  349 /* @param flag bit0= recursion is active
  350                bit1= do not report added files
  351                bit6= do not delete eventually existing node from di_array
  352                bit7= no special handling of split file directories
  353                bit8= hide in iso_rr
  354                bit9= hide in joliet
  355 */
  356 int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir,
  357                      char *img_dir_path, char *disk_dir_path,
  358                      struct LinkiteM *link_stack, int flag)
  359 {
  360  IsoImage *volume;
  361  IsoNode *node;
  362  int ret, source_is_dir, source_is_link, fret, was_failure= 0;
  363  int do_not_dive, hide_attrs;
  364  struct DirseQ *dirseq= NULL;
  365  char *name, *img_name, *srcpt, *stbuf_src= "";
  366  struct stat stbuf, hstbuf;
  367  dev_t dir_dev;
  368  struct LinkiteM *own_link_stack = NULL;
  369  char *sfe= NULL, *sfe2= NULL;
  370  char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
  371 
  372 #define Xorriso_add_handle_collisioN 1
  373 #define Xorriso_optimistic_add_treE 1
  374 
  375 #ifndef Xorriso_optimistic_add_treE
  376 #ifndef Xorriso_add_handle_collisioN
  377  int target_is_split= 0, target_is_dir;
  378 #endif
  379 #endif
  380 
  381  /* Avoiding large local memory objects in order to save stack space */
  382  sfe= malloc(5*SfileadrL);
  383  sfe2= malloc(5*SfileadrL);
  384  disk_path= malloc(2*SfileadrL);
  385  img_path= malloc(2*SfileadrL);
  386  link_target= calloc(SfileadrL, 1);
  387  if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
  388     link_target==NULL) {
  389    Xorriso_no_malloc_memory(xorriso, &sfe, 0);
  390    {ret= -1; goto ex;}
  391  }
  392 
  393  own_link_stack= link_stack;
  394 
  395  ret= Xorriso_get_volume(xorriso, &volume, 0);
  396  if(ret<=0)
  397    goto ex;
  398 
  399  stbuf_src= disk_dir_path;
  400  if(lstat(disk_dir_path, &stbuf)==-1)
  401    goto cannot_open_dir;
  402  dir_dev= stbuf.st_dev;
  403  if(S_ISLNK(stbuf.st_mode)) {
  404    if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
  405      {ret= 2; goto ex;}
  406    stbuf_src= disk_dir_path;
  407    if(stat(disk_dir_path, &stbuf)==-1)
  408      goto cannot_open_dir;
  409    if(dir_dev != stbuf.st_dev &&
  410       !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
  411      {ret= 2; goto ex;}
  412  }
  413  ret= Dirseq_new(&dirseq, disk_dir_path, 1);
  414  if(ret<0) {
  415    sprintf(xorriso->info_text,"Failed to create source filesystem iterator");
  416    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  417    {ret= -1; goto ex;}
  418  }
  419  if(ret==0) {
  420 cannot_open_dir:;
  421    Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
  422    sprintf(xorriso->info_text,"Cannot open as source directory: %s",
  423            Text_shellsafe(disk_dir_path, sfe, 0));
  424    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  425    {ret= 0; goto ex;}
  426  }
  427 
  428  if(Sfile_str(disk_path, disk_dir_path,0)<=0)
  429    {ret= -1; goto ex;}
  430  if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/')
  431    strcat(disk_path,"/");
  432  name= disk_path+strlen(disk_path);
  433  if(Sfile_str(img_path, img_dir_path, 0)<=0)
  434    {ret= -1; goto ex;}
  435  if(img_path[0] == 0)
  436    strcat(img_path, "/");
  437  else if(img_path[strlen(img_path) - 1] != '/')
  438    strcat(img_path, "/");
  439  img_name= img_path+strlen(img_path);
  440 
  441  while(1) { /* loop over directory content */
  442    stbuf_src= "";
  443    Linkitem_reset_stack(&own_link_stack, link_stack, 0);
  444    srcpt= disk_path;
  445    Xorriso_process_msg_queues(xorriso,0);
  446    ret= Dirseq_next_adr(dirseq,name,0); /* name is a pointer into disk_path */
  447    if(ret==0)
  448  break;
  449    if(ret<0) {
  450      sprintf(xorriso->info_text,"Failed to obtain next directory entry");
  451      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  452      {ret= -1; goto ex;}
  453    }
  454 
  455    /* Compare exclusions against disk_path resp. name */
  456    ret= Xorriso_path_is_excluded(xorriso, disk_path, 0); /* (is never param) */
  457    if(ret<0)
  458      {ret= -1; goto ex;}
  459    if(ret>0)
  460  continue;
  461    /* Check for mkisofs-style hidings */
  462    hide_attrs= (flag >> 8) & 3;
  463    if(hide_attrs != 3) {
  464      ret= Xorriso_path_is_hidden(xorriso, disk_path, 0);
  465      if(ret<0)
  466        goto ex;
  467      if(ret>=0)
  468        hide_attrs|= ret;
  469    }
  470 
  471    strcpy(img_name, name);
  472    if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0)
  473      {ret= 0; goto was_problem;}
  474    if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0)
  475      {ret= 0; goto was_problem;}
  476    stbuf_src= srcpt;
  477    if(lstat(srcpt, &stbuf)==-1) {
  478 cannot_lstat:;
  479      Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
  480      sprintf(xorriso->info_text,
  481              "Cannot determine attributes of source file %s",
  482              Text_shellsafe(srcpt, sfe, 0));
  483      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  484      ret= 0; goto was_problem;
  485    }
  486    source_is_dir= 0;
  487    source_is_link= S_ISLNK(stbuf.st_mode);
  488    if(xorriso->do_follow_links && source_is_link) {
  489      /* Xorriso_hop_link checks for wide link loops */
  490      ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
  491      if(ret<0)
  492        goto was_problem;
  493      if(ret==1) {
  494        ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
  495        if(ret<=0)
  496          goto was_problem;
  497        srcpt= link_target;
  498        stbuf_src= srcpt;
  499        if(lstat(srcpt, &stbuf)==-1)
  500          goto cannot_lstat;
  501      } else {
  502        if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
  503          {ret= 0; goto was_problem;} 
  504        ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
  505        if(ret<=0)
  506          goto was_problem;
  507      }
  508    } else if (S_ISLNK(stbuf.st_mode)) {
  509      ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
  510      if(ret<=0)
  511        goto was_problem;
  512    }
  513    do_not_dive= 0;
  514    if(S_ISDIR(stbuf.st_mode)) {
  515      source_is_dir= 1;
  516      if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
  517        do_not_dive= 1;
  518    }
  519 
  520 #ifdef Xorriso_optimistic_add_treE
  521 
  522    ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
  523                                 "", img_path, (off_t) 0, (off_t) 0,
  524                                 &node, 1 | (hide_attrs << 8));
  525    if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) {
  526      ret= Xoriso_handle_collision(xorriso, NULL, &node, img_path, img_path,
  527                                   srcpt, img_path,
  528                                   (!!source_is_dir) | (flag & (64 | 128)));
  529      if(ret <= 0)
  530        goto was_problem;
  531      if(node == NULL) {
  532        ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
  533                                     "", img_path, (off_t) 0, (off_t) 0,
  534                                     &node, (hide_attrs << 8));
  535        if(ret <= 0)
  536          node= NULL;
  537      }
  538    }
  539 
  540 #else /* Xorriso_optimistic_add_treE */
  541 
  542    /* does a node exist with this name ? */
  543    node= NULL;
  544    if(dir != NULL) {
  545      ret= iso_image_get_dir_node(volume, dir, img_name, &node);
  546    } else {
  547      ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
  548    }
  549    if(ret>0) {
  550      target_is_dir= LIBISO_ISDIR(node);
  551      target_is_split= 0;
  552      if(target_is_dir && !(flag & 128))
  553        target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2);
  554 
  555      if(!((target_is_dir && !target_is_split) && source_is_dir)) {
  556        Xorriso_process_msg_queues(xorriso,0);
  557 
  558        /* handle overwrite situation */;
  559        if(xorriso->do_overwrite==1 ||
  560           (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
  561          ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path,
  562                           1 | 8 | (flag & 64));
  563          if(ret<=0)
  564            goto was_problem;
  565          if(ret==3) {
  566            sprintf(xorriso->info_text, "User revoked adding of: %s",
  567                    Text_shellsafe(img_path, sfe, 0));
  568            Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  569            ret= 0; goto was_problem;
  570          }
  571          node= NULL;
  572        } else {
  573          Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
  574          sprintf(xorriso->info_text,
  575      "While grafting %s : file object exists and may not be overwritten by %s",
  576              Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
  577          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  578          ret= 0; goto was_problem;
  579        }
  580      }
  581    }
  582 
  583    if(node==NULL) {
  584      ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
  585                                   "", img_path, (off_t) 0, (off_t) 0,
  586                                   &node, (hide_attrs << 8));
  587    }
  588 
  589 #endif /* Xorriso_optimistic_add_treE */
  590 
  591    if(node==NULL) {
  592      Xorriso_process_msg_queues(xorriso,0);
  593      Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0);
  594      sprintf(xorriso->info_text, "Grafting failed:  %s = %s",
  595              Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
  596      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  597      ret= 0; goto was_problem;
  598    }
  599 
  600    xorriso->pacifier_count++;
  601    if((xorriso->pacifier_count%100)==0)
  602      Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
  603                                xorriso->pacifier_total, "", 0);
  604 
  605    Xorriso_set_change_pending(xorriso, 0);
  606    if(source_is_dir) {
  607      if(do_not_dive) {
  608        sprintf(xorriso->info_text, "Did not follow mount point : %s",
  609                Text_shellsafe(disk_path, sfe, 0));
  610        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  611      } else {
  612        ret= Xorriso_add_tree(xorriso, (IsoDir *) node,
  613                              img_path, disk_path, own_link_stack,
  614                              1 | (flag & (2 | 64 | 128)));
  615      }
  616      if(ret<=0)
  617        goto was_problem;
  618    }
  619 
  620  continue; /* regular bottom of loop */
  621 was_problem:;
  622    was_failure= 1;
  623    fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
  624    if(fret<0)
  625      goto ex;
  626  }
  627 
  628  ret= 1;
  629 ex:
  630  if(sfe!=NULL)
  631    free(sfe);
  632  if(sfe2!=NULL)
  633    free(sfe2);
  634  if(disk_path!=NULL)
  635    free(disk_path);
  636  if(img_path!=NULL)
  637    free(img_path);
  638  if(link_target!=NULL)
  639    free(link_target);
  640  Xorriso_process_msg_queues(xorriso,0);
  641  Linkitem_reset_stack(&own_link_stack, link_stack, 0);
  642  Dirseq_destroy(&dirseq, 0);
  643  if(ret<=0)
  644    return(ret);
  645  return(!was_failure);
  646 }
  647 
  648 
  649 /* @param flag bit0= cut_out mode : base on leaf parent directory
  650                bit1= do not check and perform hidings
  651 */
  652 int Xorriso_copy_implicit_properties(struct XorrisO *xorriso, IsoDir *dir,
  653            char *full_img_path, char *img_path, char *full_disk_path, int flag)
  654 {
  655  int ret, nfic, nic, nfdc, d, i;
  656  char *nfi= NULL, *ni= NULL, *nfd= NULL, *cpt;
  657  struct stat stbuf;
  658 
  659  Xorriso_alloc_meM(nfi, char, SfileadrL);
  660  Xorriso_alloc_meM(ni, char, SfileadrL);
  661  Xorriso_alloc_meM(nfd, char, SfileadrL);
  662 
  663  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi,
  664                                  1|2);
  665  if(ret<=0)
  666    goto ex;
  667  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, img_path, ni, 1|2);
  668  if(ret<=0)
  669    goto ex;
  670  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd,
  671                                  1|2|4);
  672  if(ret<=0)
  673    goto ex;
  674  nfic= Sfile_count_components(nfi, 0);
  675  nic= Sfile_count_components(ni, 0);
  676  nfdc= Sfile_count_components(nfd, 0);
  677  d= nfic-(flag&1)-nic;
  678  if(d<0)
  679    {ret= -1; goto ex;}
  680  if(d>nfdc)
  681    {ret= 0; goto ex;}
  682  for(i= 0; i<d; i++) {
  683    cpt= strrchr(nfd, '/');
  684    if(cpt==NULL)
  685      {ret= -1; goto ex;} /* should not happen */
  686    *cpt= 0;
  687  }
  688  if(nfd[0]==0)
  689    strcpy(nfd, "/");
  690  if(stat(nfd, &stbuf)==-1)
  691    {ret= 0; goto ex;}
  692  Xorriso_transfer_properties(xorriso, &stbuf, nfd, (IsoNode *) dir,
  693                              ((8 | 1) * ((flag&1) && d==0)) | 4 | 32);
  694  sprintf(xorriso->info_text, "Copied properties for ");
  695  Text_shellsafe(ni, xorriso->info_text, 1);
  696  sprintf(xorriso->info_text+strlen(xorriso->info_text), " from ");
  697  Text_shellsafe(nfd, xorriso->info_text, 1);
  698  if(!((flag&1) && d==0))
  699    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  700 
  701  if(!(flag & 2)) {
  702    /* Check for mkisofs-style hidings */
  703    ret= Xorriso_path_is_hidden(xorriso, nfd, 0);
  704    if(ret<0)
  705      goto ex;
  706    if(ret>=0) {
  707      /* Hide dir */
  708      ret= Xorriso_set_hidden(xorriso, (void *) dir, "", ret, 0);
  709      if(ret <= 0)
  710        goto ex;
  711    }
  712  }
  713  ret= 1;
  714 ex:
  715  Xorriso_free_meM(nfi);
  716  Xorriso_free_meM(ni);
  717  Xorriso_free_meM(nfd);
  718  return(ret);
  719 }
  720 
  721 
  722 /* @param bit0= copy link target properties rather than link properties
  723           bit1= give directory x-permission where is r-permission
  724           bit2= record dev,inode (only if enabled by xorriso)
  725 */
  726 int Xorriso_copy_properties(struct XorrisO *xorriso,
  727                             char *disk_path, char *img_path, int flag)
  728 {
  729  int ret;
  730  IsoNode *node;
  731  struct stat stbuf;
  732 
  733  ret= Xorriso_get_node_by_path(xorriso, img_path, NULL, &node, 0);
  734  if(ret<=0)
  735    return(ret);
  736  if(flag & 1) {
  737    if(stat(disk_path, &stbuf)==-1)
  738      return(0);
  739  } else {
  740    if(lstat(disk_path, &stbuf)==-1)
  741      return(0);
  742  }
  743  Xorriso_transfer_properties(xorriso, &stbuf, disk_path, node,
  744                            ((flag & 2) >> 1) | ((flag & 1) << 5) | (flag & 4));
  745  Xorriso_set_change_pending(xorriso, 0);
  746  return(1);
  747 }
  748 
  749 
  750 int Xorriso_add_symlink(struct XorrisO *xorriso, IsoDir *parent,
  751                         char *link_target, char *leaf_name,
  752                         char *nominal_path, int flag)
  753 {
  754  int ret= 0;
  755  IsoSymlink *link= NULL;
  756  IsoImage *volume;
  757 
  758  ret= Xorriso_get_volume(xorriso, &volume, 0);
  759  if(ret <= 0)
  760    return(ret);
  761  ret= iso_image_add_new_symlink(volume, parent, leaf_name, link_target, &link);
  762  Xorriso_process_msg_queues(xorriso,0);
  763  if(ret < 0) {
  764    Xorriso_report_iso_error(xorriso, nominal_path, ret,
  765                             "Cannot create symbolic link", 0, "FATAL", 1);
  766    ret= 0;
  767  }
  768  return(ret);
  769 }
  770 
  771 
  772 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
  773                     Set to NULL if calling this function from outside ISO world
  774    @param flag bit0= mkdir: graft in as empty directory, not as copy from disk
  775                bit1= do not report added files
  776                bit2= -follow, -not_*: this is not a command parameter
  777                bit3= use offset and cut_size for cut_out_node
  778                bit4= return 3 on rejection by exclusion or user
  779                bit5= if directory then do not add sub tree
  780                bit6= do not delete eventually existing node from di_array
  781                bit7= no special handling of split file directories
  782                bit8= hide in iso_rr
  783                bit9= hide in joliet
  784               bit10= ln -s: graft in as symbolic link.
  785                             Link target is handed over in parameter disk_path.
  786    @return <=0 = error , 1 = added simple node , 2 = added directory ,
  787                          3 = rejected 
  788 */
  789 int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, 
  790                      char *disk_path, char *img_path,
  791                      off_t offset, off_t cut_size, int flag)
  792 {
  793  IsoImage *volume;
  794  char *path= NULL, *apt, *npt, *cpt;
  795  char *disk_path_pt, *resolved_disk_path= NULL;
  796  IsoDir *dir= NULL, *hdir;
  797  IsoNode *node;
  798  int done= 0, is_dir= 0, l, ret, source_is_dir, resolve_link= 0;
  799  int hide_attrs;
  800  struct stat stbuf;
  801 
  802 #define Xorriso_graft_handle_collisioN 1
  803 #define Xorriso_optimistic_graft_iN 1
  804 
  805 #ifndef Xorriso_optimistic_graft_iN
  806 #ifndef Xorriso_graft_handle_collisioN
  807  int target_is_split, target_is_dir;
  808 #endif
  809 #endif
  810 
  811  Xorriso_alloc_meM(path, char, SfileadrL);
  812  Xorriso_alloc_meM(resolved_disk_path, char, SfileadrL);
  813 
  814  hide_attrs= (flag >> 8) & 3;
  815  if (disk_path == NULL && !(flag & 1)) {
  816    Xorriso_msgs_submit(xorriso, 0,
  817          "Program error: Xorriso_graft_in(): disk_path == NULL && !(flag & 1)",
  818          0, "ABORT", 0);
  819    {ret= -1; goto ex;}
  820  }
  821  if (disk_path == NULL) {
  822    disk_path= "";
  823  } else {
  824    ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4));
  825    if(ret<0)
  826      goto ex;
  827    if(ret>0)
  828      {ret= 3*!!(flag&16); goto ex;}
  829 
  830    /* Check for mkisofs-style hidings */
  831    if(hide_attrs != 3) {
  832      ret= Xorriso_path_is_hidden(xorriso, disk_path, 0);
  833      if(ret<0)
  834        goto ex;
  835      if(ret>=0)
  836        hide_attrs|= ret;
  837    }
  838  }
  839 
  840  for(cpt= img_path; 1; cpt++) {
  841    cpt= strstr(cpt,"/.");
  842    if(cpt==NULL)
  843  break;
  844    if(cpt[2]=='.') {
  845      if(cpt[3]=='/' || cpt[3]==0)
  846  break;
  847    } else if(cpt[2]=='/' || cpt[2]==0)
  848  break;
  849  }
  850  if(cpt!=NULL) {
  851    if(disk_path[0])
  852      Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  853    sprintf(xorriso->info_text,
  854            "Unsupported relative addressing in iso_rr_path ");
  855    Text_shellsafe(img_path, xorriso->info_text, 1);
  856    if(disk_path[0]) {
  857      strcat(xorriso->info_text, " (disk: ");
  858      Text_shellsafe(disk_path, xorriso->info_text, 1);
  859      strcat(xorriso->info_text, ")");
  860    }
  861    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  862    {ret= 0; goto ex;}
  863  }
  864 
  865  ret= Xorriso_get_volume(xorriso, &volume, 0);
  866  if(ret<=0)
  867    goto ex;
  868 
  869  strncpy(path, img_path, SfileadrL - 1);
  870  path[SfileadrL - 1]= 0;
  871  apt= npt= path;
  872 
  873  if(!(flag & (1 | 1024))) {
  874    if(disk_path[0] == 0) {
  875      Xorriso_msgs_submit(xorriso, 0, "/", 0, "ERRFILE", 0);
  876      sprintf(xorriso->info_text,
  877             "Will not graft-in the whole local filesystem by path '/'");
  878      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  879      {ret= 0; goto ex;}
  880    }
  881    ret= lstat(disk_path, &stbuf);
  882    if(ret!=-1) {
  883      if(S_ISDIR(stbuf.st_mode))
  884        is_dir= 1;
  885      else if((stbuf.st_mode&S_IFMT)==S_IFLNK &&
  886              (xorriso->do_follow_links ||
  887               (xorriso->do_follow_param && !(flag&4)))) {
  888        resolve_link= 1;
  889        ret= stat(disk_path, &stbuf);
  890        if(ret!=-1) {
  891          if(S_ISDIR(stbuf.st_mode))
  892            is_dir= 1;
  893        }
  894      }
  895    }
  896    if(ret == -1) {
  897      Xorriso_process_msg_queues(xorriso,0);
  898      Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  899      sprintf(xorriso->info_text,
  900             "Cannot determine attributes of source file ");
  901      Text_shellsafe(disk_path, xorriso->info_text, 1);
  902      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  903      {ret= 0; goto ex;}
  904    }
  905    if(S_ISDIR(stbuf.st_mode)) {
  906      is_dir= 1;
  907    } else {
  908      l= strlen(img_path);
  909      if(l>0)
  910        if(img_path[l-1]=='/')
  911          l= 0;
  912      if(l==0) {
  913        Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  914        sprintf(xorriso->info_text, "Source ");
  915        Text_shellsafe(disk_path, xorriso->info_text, 1);
  916        strcat(xorriso->info_text, " is not a directory. Target ");
  917        Text_shellsafe(img_path, xorriso->info_text, 1);
  918        strcat(xorriso->info_text, " would be.");
  919        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  920        {ret= 0; goto ex;}
  921      }
  922    }
  923  }
  924 
  925  dir= iso_image_get_root(volume);
  926  if(dir==NULL) {
  927    Xorriso_process_msg_queues(xorriso,0);
  928    sprintf(xorriso->info_text,
  929            "While grafting '%s' : no root node available", img_path);
  930    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  931    {ret= 0; goto ex;}
  932  }
  933  for(npt= apt; !done; apt= npt+1) {
  934    npt= strchr(apt, '/');
  935    if(npt==NULL) {
  936      npt= apt+strlen(apt);
  937      done= 1;
  938    } else
  939      *npt= 0;
  940    if(*apt==0) {
  941      *apt= '/';
  942      apt++;
  943      if(done)
  944        goto attach_source;
  945  continue;
  946    }
  947    source_is_dir= (is_dir || (flag&1) || !done);
  948 
  949 #ifdef Xorriso_optimistic_graft_iN
  950 
  951    /* Directories of the source path are likely to exist already as directory
  952       in the image.
  953       That will cause two lookups with optimistic, and only one with
  954       pessimistic.
  955       So optimism will pay off only with the leaf. I.e. if(done).
  956     */
  957    if(source_is_dir) { /* eventually create directory */
  958      ret= iso_image_dir_get_node(volume, dir, apt, &node, 0);
  959      if(ret == 1) {
  960        ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path,
  961                                     img_path, disk_path,
  962                                     disk_path[0] ? disk_path : img_path,
  963                                (!!source_is_dir) | (flag & (16 | 64 | 128)));
  964        if(ret <= 0 || ret == 3)
  965          goto ex;
  966        if(ret == 1 && node != NULL)
  967          dir= (IsoDir *) node;
  968      } else
  969        node= NULL;
  970      if(node == NULL) {
  971        ret= iso_image_add_new_dir(volume, dir, apt, &hdir);
  972        if(ret < 0) {
  973          Xorriso_process_msg_queues(xorriso,0);
  974          if(disk_path[0])
  975            Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
  976          Xorriso_report_iso_error(xorriso, img_path, ret,
  977                                   "Cannot create directory", 0, "FAILURE", 1);
  978          sprintf(xorriso->info_text,
  979                "While grafting '%s' : could not insert '%s'", img_path, path);
  980          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  981          {ret= 0; goto ex;}
  982        }
  983        if(xorriso->update_flags & 1) {
  984          ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1);
  985          if(ret <= 0)
  986            {ret= 0; goto ex;}
  987        }
  988 
  989        dir= hdir;
  990        Xorriso_set_change_pending(xorriso, 0);
  991        iso_node_set_ctime((IsoNode *) dir, time(NULL));
  992        iso_node_set_uid((IsoNode *) dir, geteuid());
  993        iso_node_set_gid((IsoNode *) dir, getegid());
  994 
  995        if(disk_path[0] && !done) {
  996          /* This not only copies disk directory properties
  997             but also sets eventual hide_attrs */
  998          Xorriso_copy_implicit_properties(xorriso, dir, img_path, path,
  999                                           disk_path, !!(flag&8));
 1000        }
 1001      }
 1002    }
 1003 
 1004    if(done) {
 1005 attach_source:;
 1006      if(flag&1) {
 1007        /* directory node was created above */;
 1008 
 1009      } else if(flag & 1024) {
 1010        ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0);
 1011        if(ret <= 0)
 1012          goto ex;
 1013        Xorriso_set_change_pending(xorriso, 0);
 1014 
 1015      } else if(is_dir) {
 1016        Xorriso_transfer_properties(xorriso, &stbuf, disk_path,
 1017                                    (IsoNode *) dir, 4 | 32);
 1018        if(!(flag&32)) {
 1019          ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
 1020                                flag & (2 | 64 | 128));
 1021          if(ret<=0)
 1022            goto ex;
 1023        }
 1024      } else {
 1025        if(resolve_link) {
 1026          ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
 1027          if(ret<=0)
 1028            goto ex;
 1029          disk_path_pt= resolved_disk_path;
 1030        } else
 1031          disk_path_pt= disk_path;
 1032 
 1033        ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
 1034                                     disk_path, img_path, offset, cut_size,
 1035                                     &node, 1 | (flag & 8) | (hide_attrs << 8));
 1036        if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) {
 1037          ret= Xoriso_handle_collision(xorriso, boss_iter, &node, img_path,
 1038                                       img_path, disk_path,
 1039                                       disk_path[0] ? disk_path : img_path,
 1040                                       (flag & (16 | 64 | 128)));
 1041          if(ret <= 0 || ret == 3)
 1042            goto ex;
 1043          ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
 1044                                       disk_path, img_path, offset, cut_size,
 1045                                       &node, (flag & 8) | (hide_attrs << 8));
 1046        }
 1047        if(ret<=0) {
 1048          sprintf(xorriso->info_text, "Grafting failed:  ");
 1049          Text_shellsafe(img_path, xorriso->info_text, 1);
 1050          strcat(xorriso->info_text, " = ");
 1051          Text_shellsafe(disk_path, xorriso->info_text, 1);
 1052          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1053          {ret= 0; goto ex;}
 1054        }
 1055        Xorriso_set_change_pending(xorriso, 0);
 1056 
 1057        /* <<< Why set the name once again ?
 1058        iso_image_set_node_name(volume, node, apt, 1);
 1059        */
 1060 
 1061        xorriso->pacifier_count++;
 1062        if(xorriso->pacifier_count%100 && !(flag&2))
 1063          Xorriso_pacifier_callback(xorriso, "files added",
 1064                                    xorriso->pacifier_count,
 1065                                    xorriso->pacifier_total, "", 0);
 1066      }
 1067    } else
 1068      *npt= '/';
 1069 
 1070 #else /* Xorriso_optimistic_graft_iN */
 1071 
 1072    node= NULL;
 1073    ret= iso_image_dir_get_node(volume, dir, apt, &node, 0);
 1074    if(ret == 1) {
 1075 
 1076 #ifdef Xorriso_graft_handle_collisioN
 1077 
 1078      ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, img_path,
 1079                                   disk_path,
 1080                                   disk_path[0] ? disk_path : img_path,
 1081                                  (!!source_is_dir) | (flag & (16 | 64 | 128)));
 1082      if(ret <= 0 || ret == 3)
 1083        goto ex;
 1084      if(ret == 2)
 1085        goto handle_path_node;
 1086 
 1087 #else /* Xorriso_graft_handle_collisioN */
 1088 
 1089      target_is_dir= LIBISO_ISDIR(node);
 1090 
 1091      target_is_split= 0;
 1092      if(target_is_dir && !(flag & 128))
 1093        target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2);
 1094 
 1095      if(!((target_is_dir && !target_is_split) && source_is_dir)) {
 1096        Xorriso_process_msg_queues(xorriso,0);
 1097 
 1098        /* handle overwrite situation */;
 1099        if(xorriso->do_overwrite==1 ||
 1100           (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
 1101          ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path,
 1102                           1 | 8 | (flag & 64));
 1103          if(ret<=0)
 1104            goto ex;
 1105          if(ret==3) {
 1106            sprintf(xorriso->info_text, "User revoked adding of: ");
 1107            if(disk_path[0])
 1108              Text_shellsafe(disk_path, xorriso->info_text, 1);
 1109            else
 1110              Text_shellsafe(img_path, xorriso->info_text, 1);
 1111            Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1112            {ret= 3*!!(flag&16); goto ex;}
 1113          }
 1114          node= NULL;
 1115          goto handle_path_node;
 1116        }
 1117 
 1118        if (disk_path[0])
 1119          Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
 1120        sprintf(xorriso->info_text,
 1121               "While grafting '%s' : '%s' exists and may not be overwritten",
 1122               img_path, path);
 1123        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1124        {ret= 0; goto ex;}
 1125      }
 1126 
 1127 #endif /* ! Xorriso_graft_handle_collisioN */
 1128 
 1129      dir= (IsoDir *) node;
 1130    }
 1131 
 1132 handle_path_node:;
 1133    if(node==NULL && source_is_dir) { /* make a directory */
 1134      ret= iso_image_add_new_dir(volume, dir, apt, &hdir);
 1135      if(ret<0) {
 1136        Xorriso_process_msg_queues(xorriso,0);
 1137        if(disk_path[0])
 1138          Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
 1139        Xorriso_report_iso_error(xorriso, img_path, ret,
 1140                                 "Cannot create directory", 0, "FAILURE", 1);
 1141        sprintf(xorriso->info_text,
 1142                "While grafting '%s' : could not insert '%s'", img_path, path);
 1143        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1144        {ret= 0; goto ex;}
 1145      }
 1146      if(xorriso->update_flags & 1) {
 1147        ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1);
 1148        if(ret <= 0)
 1149          {ret= 0; goto ex;}
 1150      }
 1151 
 1152      dir= hdir;
 1153      Xorriso_set_change_pending(xorriso, 0);
 1154      iso_node_set_ctime((IsoNode *) dir, time(NULL));
 1155      iso_node_set_uid((IsoNode *) dir, geteuid());
 1156      iso_node_set_gid((IsoNode *) dir, getegid());
 1157 
 1158      if(disk_path[0] && !done)
 1159        /* This not only copies disk directory properties
 1160           but also sets eventual hide_attrs */
 1161        Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, disk_path,
 1162                                        !!(flag&8));
 1163    }
 1164    if(done) {
 1165 attach_source:;
 1166      if(flag&1) {
 1167        /* directory node was created above */;
 1168 
 1169      } else if(flag & 1024) {
 1170        ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0);
 1171        if(ret <= 0)
 1172          goto ex;
 1173 
 1174      } else if(is_dir) {
 1175        Xorriso_transfer_properties(xorriso, &stbuf, disk_path,
 1176                                    (IsoNode *) dir, 4 | 32);
 1177        if(!(flag&32)) {
 1178          ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
 1179                                flag & (2 | 64 | 128));
 1180          if(ret<=0)
 1181            goto ex;
 1182        }
 1183      } else {
 1184        if(resolve_link) {
 1185          ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
 1186          if(ret<=0)
 1187            goto ex;
 1188          disk_path_pt= resolved_disk_path;
 1189        } else
 1190          disk_path_pt= disk_path;
 1191 
 1192        ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
 1193                                     disk_path, img_path, offset, cut_size,
 1194                                     &node, (flag&8) | (hide_attrs << 8));
 1195        if(ret<=0) {
 1196          sprintf(xorriso->info_text, "Grafting failed:  ");
 1197          Text_shellsafe(img_path, xorriso->info_text, 1);
 1198          strcat(xorriso->info_text, " = ");
 1199          Text_shellsafe(disk_path, xorriso->info_text, 1);
 1200          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1201          {ret= 0; goto ex;}
 1202        }
 1203        Xorriso_set_change_pending(xorriso, 0);
 1204        iso_image_set_node_name(volume, node, apt, 1);
 1205 
 1206        xorriso->pacifier_count++;
 1207        if(xorriso->pacifier_count%100 && !(flag&2))
 1208          Xorriso_pacifier_callback(xorriso, "files added",
 1209                                    xorriso->pacifier_count,
 1210                                    xorriso->pacifier_total, "", 0);
 1211      }
 1212    } else
 1213      *npt= '/';
 1214 
 1215 #endif /* ! Xorriso_optimistic_graft_iN */
 1216 
 1217  }
 1218 
 1219  Xorriso_process_msg_queues(xorriso,0);
 1220  ret= 1+!!is_dir;
 1221 ex:;
 1222  Xorriso_free_meM(path);
 1223  Xorriso_free_meM(resolved_disk_path);
 1224  return(ret);
 1225 }
 1226 
 1227 
 1228 /* @param flag bit0= -follow: disk_path is not a command parameter
 1229 */
 1230 int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path,
 1231                 off_t startbyte, off_t bytecount, char *iso_rr_path, int flag)
 1232 {
 1233  int ret;
 1234  char *eff_source= NULL, *eff_dest= NULL;
 1235  struct stat stbuf;
 1236 
 1237  Xorriso_alloc_meM(eff_source, char, SfileadrL);
 1238  Xorriso_alloc_meM(eff_dest, char, SfileadrL);
 1239 
 1240  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_source,
 1241                                  2|4);
 1242  if(ret<=0)
 1243    goto ex;
 1244  ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&1));
 1245  if(ret!=0)
 1246    {ret= 0; goto ex;}
 1247 
 1248  if(lstat(eff_source, &stbuf)==-1) {
 1249    Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
 1250    sprintf(xorriso->info_text, "-cut_out: Cannot determine type of ");
 1251    Text_shellsafe(eff_source, xorriso->info_text, 1); 
 1252    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1253    {ret= 0; goto ex;}
 1254  }
 1255 
 1256  if((stbuf.st_mode&S_IFMT) == S_IFLNK) {
 1257    if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
 1258      goto unsupported_type;
 1259    if(stat(eff_source, &stbuf)==-1) {
 1260      Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
 1261      sprintf(xorriso->info_text,
 1262              "-cut_out: Cannot determine link target type of ");
 1263      Text_shellsafe(eff_source, xorriso->info_text, 1); 
 1264      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 1265      {ret= 0; goto ex;}
 1266    }
 1267  }
 1268  if(S_ISREG(stbuf.st_mode)) {
 1269    if(stbuf.st_size<startbyte) {
 1270      Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
 1271      sprintf(xorriso->info_text,
 1272              "-cut_out: Byte offset %.f larger than file size %.f",
 1273              (double) startbyte, (double) stbuf.st_size); 
 1274      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
 1275      {ret= 0; goto ex;}
 1276    }
 1277  } else {
 1278 unsupported_type:;
 1279    Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
 1280    sprintf(xorriso->info_text, "-cut_out: Unsupported file type (%s) with ",
 1281            Ftypetxt(stbuf.st_mode, 0));
 1282    Text_shellsafe(eff_source, xorriso->info_text, 1); 
 1283    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1284    {ret= 0; goto ex;}
 1285  }
 1286 
 1287  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path, eff_dest,
 1288                                  2);
 1289  if(ret<=0)
 1290    goto ex;
 1291 
 1292  ret= Xorriso_graft_in(xorriso, NULL, eff_source, eff_dest,
 1293                        startbyte, bytecount, 8);
 1294 ex:;
 1295  Xorriso_free_meM(eff_source);
 1296  Xorriso_free_meM(eff_dest);
 1297  return(ret);
 1298 }
 1299 
 1300 
 1301 /* @param flag bit0= do not produce info message on success
 1302                bit1= do not raise protest if directory already exists
 1303    @return 1=success,
 1304            0=was already directory, -1=was other type, -2=other error
 1305 */
 1306 int Xorriso_mkdir(struct XorrisO *xorriso, char *path, int flag)
 1307 {
 1308  int ret;
 1309  char *eff_path= NULL;
 1310 
 1311  Xorriso_alloc_meM(eff_path, char, SfileadrL);
 1312 
 1313  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1);
 1314  if(ret<0)
 1315    {ret= -2; goto ex;}
 1316  if(ret>0) {
 1317    if(ret == 2 && (flag & 2))
 1318      {ret= 0; goto ex;}
 1319    sprintf(xorriso->info_text,"-mkdir: Address already existing ");
 1320    Text_shellsafe(eff_path, xorriso->info_text, 1);
 1321    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
 1322                        (ret==2 ? "WARNING" : "FAILURE"), 0);
 1323    {ret= -1 + (ret == 2); goto ex;}
 1324  }
 1325  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2);
 1326  if(ret<0)
 1327    {ret= -2; goto ex;}
 1328  ret= Xorriso_graft_in(xorriso, NULL, NULL, eff_path, (off_t) 0, (off_t) 0, 1);
 1329  if(ret<=0)
 1330    {ret= -2; goto ex;}
 1331  if(!(flag&1)) {
 1332    sprintf(xorriso->info_text, "Created directory in ISO image: ");
 1333    Text_shellsafe(eff_path, xorriso->info_text, 1);
 1334    strcat(xorriso->info_text, "\n");
 1335    Xorriso_info(xorriso, 0);
 1336  }
 1337  ret= 1;
 1338 ex:;
 1339  Xorriso_free_meM(eff_path);
 1340  return(ret);
 1341 }
 1342 
 1343 
 1344 /* @param boss_iter  If not NULL then this is an iterator suitable for
 1345                iso_dir_iter_remove()  which is then to be used instead
 1346                of iso_node_remove().
 1347    @param flag bit0= remove whole sub tree: rm -r
 1348                bit1= remove empty directory: rmdir  
 1349                bit2= recursion: do not reassure in mode 2 "tree"
 1350                bit3= this is for overwriting and not for plain removal
 1351                bit4= count deleted files in xorriso->pacifier_count
 1352                bit5= with bit0 only remove directory content, not the directory
 1353                bit6= do not delete eventually existing node from di_array
 1354    @return   <=0 = error
 1355                1 = removed simple node 
 1356                2 = removed directory or tree
 1357                3 = did not remove on user revocation
 1358 */
 1359 int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter, off_t boss_mem,
 1360                 char *path, int flag)
 1361 {
 1362  int ret, is_dir= 0, pl, not_removed= 0, fret;
 1363  IsoNode *victim_node= NULL, *node;
 1364  IsoDir *boss_node, *root_dir;
 1365  IsoDirIter *iter= NULL;
 1366  IsoImage *volume;
 1367  char *sub_name, *name;
 1368  char *sfe= NULL, *sub_path= NULL;
 1369  off_t mem;
 1370  IsoNode **node_array= NULL;
 1371  int node_count= 0, node_idx;
 1372 
 1373  /* Avoiding large local memory objects in order to save stack space */
 1374  sfe= malloc(5*SfileadrL);
 1375  sub_path= malloc(2*SfileadrL);
 1376  if(sfe==NULL || sub_path==NULL) {
 1377    Xorriso_no_malloc_memory(xorriso, &sfe, 0);
 1378    {ret= -1; goto ex;}
 1379  }
 1380 
 1381 #ifndef Libisofs_iso_dir_iter_sufficienT
 1382  /* Ticket 127: A80301 - A80302
 1383     I do not not deem IsoDirIter safe for node list manipulations.
 1384     The parameter boss_iter once was intended to allow such but
 1385     has now been downgraded to a mere check for eventual programming bugs.
 1386  */
 1387  if(boss_iter!=NULL) {
 1388    sprintf(xorriso->info_text,
 1389        "Program error: Xorriso_rmi() was requested to delete iterated node %s",
 1390        Text_shellsafe(path, sfe, 0));
 1391    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1392    ret= -1; goto ex;
 1393  }
 1394 #endif /* Libisofs_iso_dir_iter_sufficienT */
 1395 
 1396  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1397  if(ret<=0)
 1398    goto ex;
 1399  
 1400  if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
 1401    {ret= 0; goto ex;}
 1402  ret= Xorriso_node_from_path(xorriso, volume, path, &victim_node, 0);
 1403  if(ret<=0)
 1404    goto ex;
 1405  root_dir= iso_image_get_root(volume);
 1406  if(((void *) root_dir) == ((void *) victim_node) && !(flag & 1)) {
 1407    sprintf(xorriso->info_text, "May not delete root directory");
 1408    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1409    {ret= 0; goto ex;}
 1410  }
 1411 
 1412  if(LIBISO_ISDIR(victim_node))
 1413    is_dir= 1;
 1414  if(!is_dir) {
 1415    if(flag&2) { /* rmdir */
 1416      sprintf(xorriso->info_text, "%s in loaded ISO image is not a directory",
 1417              Text_shellsafe(path, sfe, 0));
 1418      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1419      ret= 0; goto ex;
 1420    }
 1421  } else {
 1422    if(flag&1) { /* rm -r */
 1423      if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
 1424         (flag&32) || ((void *) root_dir) == ((void *) victim_node)) {
 1425        /* Iterate over subordinates and delete them */
 1426        mem= boss_mem;
 1427 
 1428        ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
 1429                          &iter, &node_array, &node_count, &node_idx,
 1430                          &node, 1|2);
 1431        if(ret<=0) {
 1432 cannot_create_iter:;
 1433          Xorriso_cannot_create_iter(xorriso, ret, 0);
 1434          ret= -1; goto ex;
 1435        }
 1436        pl= strlen(path);
 1437        strcpy(sub_path, path);
 1438        if(pl==0 || sub_path[pl-1]!='/') {
 1439          sub_path[pl++]= '/';
 1440          sub_path[pl]= 0;
 1441        }
 1442        sub_name= sub_path+pl;
 1443        while(1) { 
 1444          ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
 1445                                 &node_array, &node_count, &node_idx, &node, 0);
 1446          if(ret<0)
 1447            goto ex;
 1448          if(ret==0 || xorriso->request_to_abort)
 1449        break;
 1450          name= (char *) iso_node_get_name(node);
 1451          if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
 1452            {ret= 0; goto rm_r_problem_handler;}
 1453          strcpy(sub_name, name);
 1454          ret= Xorriso_rmi(xorriso, iter, mem, sub_path,
 1455                           (flag & ( 1 | 2 | 8 | 16 | 64)) | 4);
 1456          if(ret==3 || ret<=0 || xorriso->request_to_abort) {
 1457 rm_r_problem_handler:;
 1458            not_removed= 1;
 1459            fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
 1460            if(fret<0)
 1461              goto dir_not_removed;
 1462          }
 1463        }
 1464        if(flag&32)
 1465          {ret= 2; goto ex;}
 1466 
 1467        if(not_removed) {
 1468 dir_not_removed:;
 1469          sprintf(xorriso->info_text, "Directory not removed: %s",
 1470                  Text_shellsafe(path, sfe, 0));
 1471          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1472          if(ret>0)
 1473            ret= 3;
 1474          goto ex;
 1475        }
 1476      }
 1477    } else {
 1478      if(!(flag&2)) { /* not rmdir */
 1479        sprintf(xorriso->info_text, "%s in loaded ISO image is a directory",
 1480                Text_shellsafe(path, sfe, 0));
 1481        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1482        ret= 0; goto ex;
 1483      }
 1484 
 1485      ret= iso_dir_get_children((IsoDir *) victim_node, &iter);
 1486      Xorriso_process_msg_queues(xorriso,0);
 1487      if(ret<0)
 1488        goto cannot_create_iter;
 1489      if(ret>0) {
 1490        if(iso_dir_iter_next(iter, &node) == 1) {
 1491          sprintf(xorriso->info_text,
 1492                  "Directory not empty on attempt to delete: %s",
 1493                  Text_shellsafe(path, sfe, 0));
 1494          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1495          ret= 0; goto ex;
 1496        }
 1497      }
 1498    }
 1499  }
 1500 
 1501  if(((void *) root_dir) == ((void *) victim_node))
 1502    {ret= 2; goto ex;}
 1503 
 1504  if(xorriso->request_to_abort)
 1505    {ret= 3; goto ex;}
 1506  boss_node= iso_node_get_parent(victim_node);
 1507  Xorriso_process_msg_queues(xorriso,0);
 1508  if(boss_node==NULL) {
 1509    sprintf(xorriso->info_text,
 1510            "Cannot find parent node of %s in loaded ISO image",
 1511            Text_shellsafe(path, sfe, 0));
 1512    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1513    ret= 0; goto ex;
 1514  }
 1515 
 1516  while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
 1517        && !xorriso->request_not_to_ask) {
 1518    /* ls -ld */
 1519    Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 1|2|8);
 1520    if(is_dir) /* du -s */
 1521      Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 2|4);
 1522    if(flag&8)
 1523      sprintf(xorriso->info_text,
 1524   "File exists. Remove ?  n= keep old, y= remove, x= abort, @= stop asking\n");
 1525    else
 1526      sprintf(xorriso->info_text,
 1527   "Remove above file ?  n= keep it, y= remove it, x= abort, @= stop asking\n");
 1528    Xorriso_info(xorriso, 4);
 1529    ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
 1530    if(ret<=0)
 1531      goto ex;
 1532    if(xorriso->request_to_abort) {
 1533      sprintf(xorriso->info_text,
 1534              "Removal operation aborted by user before file: %s",
 1535              Text_shellsafe(path, sfe, 0));
 1536      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1537      ret= 3; goto ex;
 1538    }
 1539    if(ret==3)
 1540  continue;
 1541    if(ret==6) /* yes */
 1542  break;
 1543    if(ret==4) { /* yes, do not ask again */
 1544      xorriso->request_not_to_ask= 1;
 1545  break;
 1546    }
 1547    if(ret==1) { /* no */
 1548      sprintf(xorriso->info_text, "Kept in existing state: %s",
 1549              Text_shellsafe(path, sfe, 0));
 1550      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1551      ret= 3; goto ex;
 1552    }
 1553  }
 1554 
 1555  if(!(flag & 64))
 1556    Xorriso_invalidate_di_item(xorriso, victim_node, 0);
 1557 
 1558 #ifdef Libisofs_iso_dir_iter_sufficienT
 1559 
 1560  if(boss_iter!=NULL) {
 1561    ret= iso_dir_iter_remove((IsoDirIter *) boss_iter);
 1562    if(ret<0)
 1563      ret= -1;
 1564  } else
 1565    ret= iso_node_remove(victim_node);
 1566 
 1567 #else /* ! Libisofs_iso_dir_iter_sufficienT */
 1568 
 1569  ret= iso_node_remove(victim_node);
 1570 
 1571 #endif /* Libisofs_iso_dir_iter_sufficienT */
 1572 
 1573  Xorriso_process_msg_queues(xorriso,0);
 1574  if(ret<0) {
 1575    Xorriso_report_iso_error(xorriso, path, ret, "Cannot remove node", 0,
 1576                             "FATAL", 1);
 1577    sprintf(xorriso->info_text,
 1578            "Internal failure to remove %s from loaded ISO image",
 1579            Text_shellsafe(path, sfe, 0));
 1580    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1581    ret= -1; goto ex;
 1582  }
 1583 
 1584  if(flag&16)
 1585    xorriso->pacifier_count++;
 1586  Xorriso_set_change_pending(xorriso, 0);
 1587  ret= 1+!!is_dir;
 1588 ex:;
 1589  if(sfe!=NULL)
 1590    free(sfe);
 1591  if(sub_path!=NULL)
 1592    free(sub_path);
 1593  Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
 1594                     &node_array, &node_count, &node_idx, &node, (1u<<31));
 1595  return(ret);
 1596 } 
 1597 
 1598 
 1599 int Xorriso_overwrite_dest(struct XorrisO *xorriso, void *boss_iter,
 1600                            char *eff_dest, int dest_ret, char *activity,
 1601                            int flag)
 1602 {
 1603  int ret;
 1604 
 1605  if(dest_ret==2 && xorriso->do_overwrite!=1) {
 1606    sprintf(xorriso->info_text, "%s: May not overwrite directory: ", activity);
 1607    Text_shellsafe(eff_dest, xorriso->info_text, 1);
 1608    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1609    return(0);
 1610  } else if (dest_ret==1 && !xorriso->do_overwrite) {
 1611    sprintf(xorriso->info_text, "%s: May not overwrite: ", activity);
 1612    Text_shellsafe(eff_dest, xorriso->info_text, 1);
 1613    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1614    return(0);
 1615  } else if(dest_ret>0) {
 1616    ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, eff_dest, 1|8);
 1617    if(ret<=0)
 1618      return(0);
 1619    if(ret==3) {
 1620      sprintf(xorriso->info_text, "%s: User revoked removal of: ", activity);
 1621      Text_shellsafe(eff_dest, xorriso->info_text, 1);
 1622      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1623      return(0);
 1624    }
 1625  }
 1626  return(1);
 1627 }
 1628 
 1629 
 1630 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
 1631                     Set to NULL if calling this function from outside ISO world
 1632    @param flag      bit0= silently ignore attempt of renaming to same path
 1633                           and return 2
 1634 */
 1635 int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
 1636                    char *origin, char *dest, int flag)
 1637 {
 1638  int ret, ol, dest_ret;
 1639  char *eff_dest= NULL, *dir_adr= NULL, *cpt;
 1640  char *leafname, *eff_origin= NULL, *old_leafname;
 1641  IsoImage *volume;
 1642  IsoDir *origin_dir, *dest_dir;
 1643  IsoNode *node, *iso_node;
 1644 
 1645  Xorriso_alloc_meM(eff_dest, char, SfileadrL);
 1646  Xorriso_alloc_meM(dir_adr, char, SfileadrL);
 1647  Xorriso_alloc_meM(eff_origin, char, SfileadrL);
 1648 
 1649 #ifndef Libisofs_iso_dir_iter_sufficienT
 1650  /* Ticket 127: A80301 - A80302
 1651     I do not not deem IsoDirIter safe for node list manipulations.
 1652     The parameter boss_iter once was intended to allow such but
 1653     has now been downgraded to a mere check for eventual programming bugs.
 1654  */
 1655  if(boss_iter!=NULL) {
 1656    sprintf(xorriso->info_text,
 1657      "Program error: Xorriso_rename() was requested to delete iterated node ");
 1658    Text_shellsafe(origin, xorriso->info_text, 1);
 1659    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1660    {ret= -1; goto ex;}
 1661  }
 1662 #endif /* Libisofs_iso_dir_iter_sufficienT */
 1663 
 1664  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
 1665  if(ret<=0)
 1666    goto ex;
 1667  dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1);
 1668  if(dest_ret<0)
 1669    {ret= dest_ret; goto ex;}
 1670  if(dest_ret==0) { /* obtain eff_dest address despite it does not exist */
 1671    ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2);
 1672    if(ret<=0)
 1673      goto ex;
 1674  }
 1675 
 1676  /* Prevent that destination is a subordinate of origin
 1677     (that would be a black hole plopping out of the universe) */
 1678  ol= strlen(eff_origin);
 1679  if(ol==0) {
 1680    sprintf(xorriso->info_text, "May not rename root directory");
 1681    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1682    {ret= 0; goto ex;}
 1683  } else if(strcmp(eff_origin, eff_dest)==0) {
 1684    if(flag & 1)
 1685      {ret= 2; goto ex;}
 1686    sprintf(xorriso->info_text, "Ignored attempt to rename ");
 1687    Text_shellsafe(eff_origin, xorriso->info_text, 1);
 1688    strcat(xorriso->info_text, " to itself");
 1689    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 1690    {ret= 0; goto ex;}
 1691  } else if(strncmp(eff_origin, eff_dest, ol)==0 &&
 1692            (eff_dest[ol]==0 || eff_dest[ol]=='/')) {
 1693    sprintf(xorriso->info_text, "May not rename ");
 1694    Text_shellsafe(eff_origin, xorriso->info_text, 1);
 1695    strcat(xorriso->info_text, " to its own sub address ");
 1696    Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2);
 1697    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1698    {ret= 0; goto ex;}
 1699  }
 1700 
 1701  /* Check whether destination exists and may be not overwritable */
 1702  ret= Xorriso_overwrite_dest(xorriso, boss_iter,
 1703                              eff_dest, dest_ret, "Renaming", 0);
 1704  if(ret <= 0)
 1705    goto ex;
 1706 
 1707  /* Ensure existence of destination directory */
 1708  strcpy(dir_adr, eff_dest);
 1709  cpt= strrchr(dir_adr, '/');
 1710  if(cpt==NULL)
 1711    cpt= dir_adr+strlen(dir_adr);
 1712  *cpt= 0;
 1713  if(dir_adr[0]!=0) {
 1714    ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr,
 1715                          (off_t) 0, (off_t) 0, 1);
 1716    if(ret<=0)
 1717      goto ex;
 1718  }
 1719 
 1720  /* Move node */
 1721  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1722  if(ret<=0)
 1723    goto ex;
 1724  Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0);
 1725  dest_dir= (IsoDir *) iso_node;
 1726  strcpy(dir_adr, eff_origin);
 1727  cpt= strrchr(dir_adr, '/');
 1728  if(cpt==NULL)
 1729    cpt= dir_adr+strlen(dir_adr);
 1730  *cpt= 0;
 1731  Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0);
 1732  origin_dir= (IsoDir *) iso_node;
 1733  Xorriso_node_from_path(xorriso, volume, eff_origin, &node, 0);
 1734  if(dest_dir==NULL || origin_dir==NULL || node==NULL) {
 1735    Xorriso_process_msg_queues(xorriso,0);
 1736    sprintf(xorriso->info_text,
 1737            "Internal error on rename: confirmed node turns out as NULL");
 1738    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1739    {ret= -1; goto ex;}
 1740  }
 1741  ret= iso_node_take(node);
 1742  if(ret<0) {
 1743    Xorriso_process_msg_queues(xorriso,0);
 1744    Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot take", 0, "FATAL",1);
 1745    sprintf(xorriso->info_text,
 1746            "Internal error on rename: failed to take node");
 1747    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1748    {ret= -1; goto ex;}
 1749  }
 1750  leafname= strrchr(eff_dest, '/');
 1751  if(leafname==NULL)
 1752    leafname= eff_dest;
 1753  else
 1754    leafname++;
 1755  
 1756  old_leafname= (char *) iso_node_get_name(node);
 1757  if(strcmp(leafname, old_leafname)!=0)
 1758    ret= iso_image_set_node_name(volume, node, leafname, 1);
 1759  else
 1760    ret= 1;
 1761  if(ret<0) {
 1762    Xorriso_process_msg_queues(xorriso,0);
 1763    Xorriso_report_iso_error(xorriso, eff_dest, ret, "Cannot set name", 0,
 1764                             "FAILURE", 1);
 1765    ret= iso_dir_add_node(origin_dir, node, 0);
 1766    Xorriso_process_msg_queues(xorriso,0);
 1767    if(ret < 0)
 1768      Xorriso_report_iso_error(xorriso, eff_origin, ret,
 1769                               "Cannot re-instate node at old path",
 1770                               0, "FAILURE", 1);
 1771    {ret= -1; goto ex;}
 1772  }
 1773  Xorriso_process_msg_queues(xorriso,0);
 1774  ret= iso_dir_add_node(dest_dir, node, 0);
 1775  if(ret<0) {
 1776    Xorriso_process_msg_queues(xorriso,0);
 1777    Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot add", 0, "FATAL", 1);
 1778    sprintf(xorriso->info_text,
 1779            "Internal error on rename: failed to insert node");
 1780    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1781    {ret= -1; goto ex;}
 1782  }
 1783  Xorriso_set_change_pending(xorriso, 0);
 1784  ret= 1;
 1785 ex:;
 1786  Xorriso_free_meM(eff_dest);
 1787  Xorriso_free_meM(dir_adr);
 1788  Xorriso_free_meM(eff_origin);
 1789  return(ret);
 1790 }
 1791 
 1792 
 1793 int Xorriso_cannot_clone(struct XorrisO *xorriso, char *eff_origin,
 1794                          char *eff_dest, int iso_error, int flag)
 1795 {
 1796  Xorriso_report_iso_error(xorriso, eff_dest, iso_error, "Cannot clone",
 1797                           0, "FAILURE", 1);
 1798  sprintf(xorriso->info_text, "Failed to clone ");
 1799  Text_shellsafe(eff_origin, xorriso->info_text, 1);
 1800  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1801  return(0);
 1802 }
 1803 
 1804 
 1805 /* @param flag bit0= for iso_tree_clone() : merge directories
 1806                bit1= do not issue NOTE message
 1807 */
 1808 int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter,
 1809                        char *origin, char *dest, int flag)
 1810 {
 1811  int ret, dest_ret, l;
 1812  char *eff_dest= NULL, *eff_origin= NULL, *dir_adr= NULL;
 1813  char *leafname;
 1814  IsoImage *volume;
 1815  IsoDir *new_parent;
 1816  IsoNode *origin_node, *dir_node, *new_node;
 1817 
 1818  Xorriso_alloc_meM(eff_dest, char, SfileadrL);
 1819  Xorriso_alloc_meM(eff_origin, char, SfileadrL);
 1820  Xorriso_alloc_meM(dir_adr, char, SfileadrL);
 1821 
 1822  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1823  if(ret <= 0)
 1824    goto ex;
 1825 
 1826  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
 1827  if(ret<=0)
 1828    goto ex;
 1829  ret= Xorriso_node_from_path(xorriso, volume, eff_origin, &origin_node, 0);
 1830  if(ret <= 0)
 1831    goto ex;
 1832 
 1833  dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1);
 1834  if(dest_ret<0)
 1835    {ret= dest_ret; goto ex;}
 1836  if(dest_ret > 0) {
 1837    if(eff_dest[0] == 0)
 1838      strcpy(eff_dest, "/");
 1839    sprintf(xorriso->info_text,
 1840            "Cloning: Copy address already exists: ");
 1841    Text_shellsafe(eff_dest, xorriso->info_text, 1);
 1842    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1843    {ret= 0; goto ex;}
 1844  } else {
 1845    /* obtain eff_dest address despite it does not exist */
 1846    ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2);
 1847    if(ret<=0)
 1848      goto ex;
 1849  }
 1850 
 1851  /* Obtain parent path and leaf name */
 1852  strcpy(dir_adr, eff_dest);
 1853  for(l= strlen(dir_adr); l > 0; ) {
 1854    if(dir_adr[l - 1] == '/')
 1855      dir_adr[--l]= 0;
 1856    else
 1857  break;
 1858  }
 1859  leafname= strrchr(dir_adr, '/');
 1860  if(leafname == NULL) {
 1861    leafname= dir_adr;
 1862    if (leafname[0] == 0) {
 1863      Xorriso_msgs_submit(xorriso, 0, "Empty file name as clone destination",
 1864                          0, "FAILURE", 0);
 1865      {ret= 0; goto ex;}
 1866    }
 1867  } else {
 1868    *leafname= 0;
 1869    leafname++;
 1870    if(dir_adr[0] != 0) {
 1871      /* Ensure existence of destination directory */
 1872      ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr,
 1873                            (off_t) 0, (off_t) 0, 1);
 1874      if(ret <= 0)
 1875        goto ex;
 1876    }
 1877  }
 1878 
 1879  ret= Xorriso_node_from_path(xorriso, volume, dir_adr, &dir_node, 0);
 1880  if(ret <= 0)
 1881    goto ex;
 1882  new_parent= (IsoDir *) dir_node;
 1883 
 1884  ret = iso_image_tree_clone(volume, origin_node, new_parent, leafname,
 1885                             &new_node, (flag & 1) | 2);
 1886  Xorriso_process_msg_queues(xorriso,0);
 1887  if(ret < 0) {
 1888    Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0);
 1889    {ret= 0; goto ex;}
 1890  }
 1891  Xorriso_set_change_pending(xorriso, 0);
 1892  if(!(flag & 2)) {
 1893    strcpy(xorriso->info_text, "Cloned in ISO image: ");
 1894    Text_shellsafe(eff_origin, xorriso->info_text, 1);
 1895    strcat(xorriso->info_text, " to ");
 1896    Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2);
 1897    strcat(xorriso->info_text, "\n");
 1898    Xorriso_info(xorriso, 0);
 1899  }
 1900  ret= 1;
 1901 ex:;
 1902  Xorriso_free_meM(eff_dest);
 1903  Xorriso_free_meM(eff_origin);
 1904  Xorriso_free_meM(dir_adr);
 1905  return(ret);
 1906 }
 1907 
 1908 
 1909 int Xorriso_clone_under(struct XorrisO *xorriso, char *origin, char *dest,
 1910                         int flag)
 1911 {
 1912  int ret, pass;
 1913  char *eff_dest= NULL, *eff_origin= NULL, *namept;
 1914  IsoDir *origin_dir, *dest_dir;
 1915  IsoDirIter *iter= NULL;
 1916  IsoNode *origin_node, *new_node;
 1917  IsoImage *volume;
 1918 
 1919  Xorriso_alloc_meM(eff_dest, char, SfileadrL);
 1920  Xorriso_alloc_meM(eff_origin, char, SfileadrL);
 1921 
 1922  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1923  if(ret <= 0)
 1924    goto ex;
 1925  ret= Xorriso_dir_from_path(xorriso, "Copy source", origin, &origin_dir, 0);
 1926  if(ret <= 0)
 1927    goto ex;
 1928  ret= Xorriso_dir_from_path(xorriso, "Copy destination", dest, &dest_dir, 0);
 1929  if(ret <= 0)
 1930    goto ex;
 1931 
 1932  for(pass= 0; pass < 2; pass++) {
 1933    ret= iso_dir_get_children(origin_dir, &iter);
 1934    if(ret < 0) {
 1935      Xorriso_cannot_create_iter(xorriso, ret, 0);
 1936      {ret= -1; goto ex;}
 1937    }
 1938    Xorriso_process_msg_queues(xorriso,0);
 1939 
 1940    while(iso_dir_iter_next(iter, &origin_node) == 1) {
 1941      namept= (char *) iso_node_get_name(origin_node);
 1942      sprintf(eff_origin, "%s/%s", origin, namept);
 1943      sprintf(eff_dest, "%s/%s", dest, namept);
 1944      if(pass == 0) {
 1945        ret= Xorriso_node_from_path(xorriso, volume, eff_dest, &new_node, 1);
 1946        if(ret < 0)
 1947          goto ex;
 1948        if(ret > 0) {
 1949          sprintf(xorriso->info_text, "Cloning: Copy address already exists: ");
 1950          Text_shellsafe(eff_dest, xorriso->info_text, 1);
 1951          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1952          ret= 0; goto ex;
 1953        }
 1954      } else {
 1955        ret = iso_image_tree_clone(volume, origin_node, dest_dir, namept,
 1956                                   &new_node, 1 | 2);
 1957        Xorriso_process_msg_queues(xorriso,0);
 1958        if(ret < 0) {
 1959          Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0);
 1960          ret= 0; goto ex;
 1961        }
 1962      }
 1963    }   
 1964    iso_dir_iter_free(iter);
 1965    iter= NULL;
 1966  }
 1967  Xorriso_set_change_pending(xorriso, 0);
 1968  ret= 1;
 1969 ex:;
 1970  if(iter != NULL)
 1971    iso_dir_iter_free(iter);
 1972  Xorriso_free_meM(eff_dest);
 1973  Xorriso_free_meM(eff_origin);
 1974  Xorriso_process_msg_queues(xorriso,0);
 1975  return(ret);
 1976 }
 1977 
 1978 
 1979 int Xorriso_set_st_mode(struct XorrisO *xorriso, char *in_path,
 1980                         mode_t mode_and, mode_t mode_or, int flag)
 1981 {
 1982  mode_t mode= 0;
 1983  int ret;
 1984  IsoNode *node;
 1985  char *path= NULL;
 1986 
 1987  Xorriso_alloc_meM(path, char, SfileadrL);
 1988  ret= Xorriso_get_node_by_path(xorriso, in_path, path, &node, 0);
 1989  if(ret<=0)
 1990    goto ex;
 1991  mode= iso_node_get_permissions(node);
 1992  mode= (mode & mode_and) | mode_or;
 1993  iso_node_set_permissions(node, mode);
 1994  iso_node_set_ctime(node, time(NULL));
 1995  sprintf(xorriso->info_text,"Permissions now: %-5.5o  ",
 1996          (unsigned int) (mode & 0xffff));
 1997  Text_shellsafe(path, xorriso->info_text, 1);
 1998  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 1999  Xorriso_set_change_pending(xorriso, 0);
 2000  Xorriso_process_msg_queues(xorriso,0);
 2001  ret= 1;
 2002 ex:;
 2003  Xorriso_free_meM(path);
 2004  return(ret);
 2005 }
 2006 
 2007 
 2008 int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid,
 2009                     int flag)
 2010 {
 2011  int ret;
 2012  IsoNode *node;
 2013 
 2014  ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
 2015  if(ret<=0)
 2016    return(ret);
 2017  iso_node_set_uid(node, uid);
 2018  iso_node_set_ctime(node, time(NULL));
 2019  Xorriso_set_change_pending(xorriso, 0);
 2020  Xorriso_process_msg_queues(xorriso,0);
 2021  return(1);
 2022 }
 2023 
 2024 
 2025 int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid,
 2026                     int flag)
 2027 {
 2028  int ret;
 2029  IsoNode *node;
 2030 
 2031  ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
 2032  if(ret<=0)
 2033    return(ret);
 2034  iso_node_set_gid(node, gid);
 2035  iso_node_set_ctime(node, time(NULL));
 2036  Xorriso_set_change_pending(xorriso, 0);
 2037  Xorriso_process_msg_queues(xorriso,0);
 2038  return(1);
 2039 }
 2040 
 2041 
 2042 /* @parm flag  bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */
 2043 int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t,
 2044                     int flag)
 2045 {
 2046  int ret;
 2047  IsoNode *node;
 2048 
 2049  ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
 2050  if(ret<=0)
 2051    return(ret);
 2052  if(flag&1)
 2053    iso_node_set_atime(node, t);
 2054  if(flag&2)
 2055    iso_node_set_ctime(node, t);
 2056  if(flag&4)
 2057    iso_node_set_mtime(node, t);
 2058  if(!(flag&(2|256)))
 2059    iso_node_set_ctime(node, time(NULL));
 2060  Xorriso_set_change_pending(xorriso, 0);
 2061  Xorriso_process_msg_queues(xorriso,0);
 2062  return(1);
 2063 }
 2064 
 2065 
 2066 /*
 2067   Apply the effect of mkisofs -r to a single node
 2068 */
 2069 int Xorriso_mkisofs_lower_r(struct XorrisO *xorriso, IsoNode *node, int flag)
 2070 {
 2071  mode_t perms;
 2072 
 2073  perms= iso_node_get_permissions(node);
 2074  iso_node_set_uid(node, (uid_t) 0);
 2075  iso_node_set_gid(node, (gid_t) 0);
 2076  perms|= S_IRUSR | S_IRGRP | S_IROTH;
 2077  perms&= ~(S_IWUSR | S_IWGRP | S_IWOTH);
 2078  if(perms & (S_IXUSR | S_IXGRP | S_IXOTH))
 2079    perms|= (S_IXUSR | S_IXGRP | S_IXOTH);
 2080  perms&= ~(S_ISUID | S_ISGID | S_ISVTX);
 2081  iso_node_set_permissions(node, perms);
 2082  return(1);
 2083 }
 2084 
 2085 
 2086 /* @param node      Opaque handle to IsoNode which is to be manipulated
 2087                     instead of path if it is not NULL.
 2088    @param path      is used as address if node is NULL.
 2089    @param access_text  "access" ACL in long text form
 2090    @param default_text "default" ACL in long text form
 2091    @param flag      bit0= do not warn of root directory if not capable of AAIP
 2092    @return          >0 success , <=0 failure
 2093 */
 2094 int Xorriso_setfacl(struct XorrisO *xorriso, void *in_node, char *path,
 2095                     char *access_text, char *default_text, int flag)
 2096 {
 2097  int ret;
 2098  IsoNode *node;
 2099 
 2100  node= (IsoNode *) in_node;
 2101  if(node == NULL) {
 2102    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2103    if(ret<=0)
 2104      goto ex;
 2105  }
 2106  ret= iso_node_set_acl_text(node, access_text, default_text, 4);
 2107  Xorriso_process_msg_queues(xorriso,0);
 2108  if(ret <= 0) {
 2109    Xorriso_report_iso_error(xorriso, "", ret,
 2110                             "Error when setting ACL to image node",
 2111                             0, "FAILURE", 1);
 2112    if(path != NULL && path[0] != 0) {
 2113      strcpy(xorriso->info_text, "Error with setting ACL of ");
 2114      Text_shellsafe(path, xorriso->info_text, 1);
 2115      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2116    }
 2117    ret= 0; goto ex;
 2118  }
 2119  Xorriso_set_change_pending(xorriso, 0);
 2120  ret= 1;
 2121 ex:;
 2122  return(ret);
 2123 }
 2124 
 2125 
 2126 /* @param in_node       Opaque handle to IsoNode which is to be manipulated
 2127                         instead of path if it is not NULL.
 2128    @param path          is used as address if node is NULL.
 2129    @param num_attrs     Number of attributes
 2130    @param names         Array of pointers to 0 terminated name strings
 2131    @param value_lengths Array of byte lengths for each attribute payload
 2132    @param values        Array of pointers to the attribute payload bytes
 2133    @param flag          bit0= Do not maintain eventual existing ACL of the node
 2134                         bit1= Do not clear the existing attribute list
 2135                         bit2= Delete the attributes with the given names
 2136                         bit3= Allow non-user attributes.
 2137                         bit4= do not warn of root if incapable of AAIP
 2138    @return              >0 success , <=0 failure
 2139 */
 2140 int Xorriso_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
 2141                      size_t in_num_attrs, char **in_names,
 2142                      size_t *in_value_lengths, char **in_values, int flag)
 2143 {
 2144  int ret, block_isofs= 0, in_original= 1;
 2145  size_t i, j, num_attrs;
 2146  IsoNode *node;
 2147  char **names, **values;
 2148  size_t *value_lengths;
 2149 
 2150  num_attrs= in_num_attrs;
 2151  names= in_names;
 2152  value_lengths= in_value_lengths;
 2153  values= in_values;
 2154 
 2155  node= (IsoNode *) in_node;
 2156  if(node == NULL) {
 2157    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2158    if(ret<=0)
 2159      goto ex;
 2160  }
 2161  if((xorriso->do_aaip & 1024) && !(flag & 8)) {
 2162    flag|= 8;
 2163    block_isofs= 1;
 2164    for(i= 0; i < in_num_attrs; i++) {
 2165      if(strncmp(in_names[i], "isofs.", 6) == 0) {
 2166        if(in_original) {
 2167          strcpy(xorriso->info_text,
 2168                 "Attempt to set xattr from namespace \"isofs\" to ");
 2169          Text_shellsafe(path, xorriso->info_text, 1);
 2170          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 2171          ret= Xorriso_eval_problem_status(xorriso, 0, 0);
 2172          if(ret < 0) {
 2173            ret= 0; goto ex;
 2174          }
 2175          /* Switch to copy mode and omit isofs names */
 2176          Xorriso_alloc_meM(names, char *, num_attrs);
 2177          Xorriso_alloc_meM(value_lengths, size_t, num_attrs);
 2178          Xorriso_alloc_meM(values, char *, num_attrs);
 2179          in_original= 0;
 2180          for(j= 0; j < i; j++) {
 2181            names[j]= in_names[j];
 2182            value_lengths[j]= in_value_lengths[j];
 2183            values[j]= in_values[j];
 2184          }
 2185          num_attrs= i;
 2186        }
 2187      } else if(!in_original) {
 2188        names[num_attrs]= in_names[i];
 2189        value_lengths[num_attrs]= in_value_lengths[i];
 2190        values[num_attrs]= in_values[i];
 2191        num_attrs++;
 2192      }
 2193    }
 2194  }
 2195  if(num_attrs <= 0) {
 2196    ret= 1; goto ex;
 2197  }
 2198 
 2199  ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
 2200                          (flag & (1 | 2 | 4 | 8)) | (block_isofs << 4));
 2201  Xorriso_process_msg_queues(xorriso,0);
 2202  if(ret <= 0) {
 2203    Xorriso_report_iso_error(xorriso, "", ret,
 2204                             "Error when setting ACL and xattr to image node",
 2205                             0, "FAILURE", 1);
 2206    if(path != NULL && path[0] != 0) {
 2207      strcpy(xorriso->info_text, "Error with setting xattr of ");
 2208      Text_shellsafe(path, xorriso->info_text, 1);
 2209      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2210    }
 2211    ret= 0; goto ex;
 2212  }
 2213  Xorriso_set_change_pending(xorriso, 0);
 2214  ret= 1;
 2215 ex:;
 2216  Xorriso_process_msg_queues(xorriso, 0);
 2217  if(!in_original) {
 2218    Xorriso_free_meM(names);
 2219    Xorriso_free_meM(value_lengths);
 2220    Xorriso_free_meM(values);
 2221  }
 2222  return(ret);
 2223 }
 2224 
 2225 
 2226 /*
 2227    @param flag bit0= use parameters dev,ino rather than disk_path
 2228                bit1= compare attribute rather than setting it
 2229                      return: 0=dev,ino match, 1=mismatch, 2=no node attribute
 2230                             -1=error
 2231                bit5= if not bit0:
 2232                      transfer dev,inode from eventual link target
 2233                bit7= omit dev check mit bit1
 2234 */
 2235 int Xorriso_record_dev_inode(struct XorrisO *xorriso, char *disk_path,
 2236                              dev_t dev, ino_t ino,
 2237                              void *in_node, char *iso_path, int flag)
 2238 {
 2239  size_t l, di_l= 0;
 2240  int i, ret;
 2241  dev_t hdev;
 2242  ino_t hino;
 2243  char buf[66], *bufpt, *wpt, *di= NULL;
 2244  static char *name= "isofs.di";
 2245  struct stat stbuf;
 2246 
 2247  if(!(flag & 1)) {
 2248    if(flag & 32) {
 2249      if(stat(disk_path, &stbuf) == -1)
 2250        return(-1);
 2251    } else {
 2252      if(lstat(disk_path, &stbuf) == -1)
 2253        return(-1);
 2254    }
 2255    dev= stbuf.st_dev;
 2256    ino= stbuf.st_ino;
 2257  }
 2258    
 2259  wpt= buf;
 2260  hdev= dev;
 2261  for(i= 0; hdev != 0; i++)
 2262    hdev= hdev >> 8;
 2263  l= i;
 2264  *(wpt++)= l;
 2265  for(i= 0; i < (int) l; i++)
 2266    *(wpt++)= dev >> (8 * (l - i - 1));
 2267  hino= ino;
 2268  for(i= 0; hino != 0; i++)
 2269    hino= hino >> 8;
 2270  l= i;
 2271  *(wpt++)= l;
 2272  for(i= 0; i < (int) l; i++)
 2273    *(wpt++)= ino >> (8 * (l - i - 1));
 2274  l= wpt - buf; 
 2275  bufpt= buf;
 2276 
 2277  if(flag & 2) {
 2278    /* Compare node attribute with bufpt,l */
 2279    ret= Xorriso_get_attr_value(xorriso, in_node, iso_path,
 2280                                "isofs.di", &di_l, &di, 0);
 2281    if(ret < 0)
 2282      goto ex;
 2283    if(ret == 0)
 2284      {ret= 2; goto ex;}
 2285    if(flag & 128) {
 2286      if(di_l <= 0)
 2287        {ret= 1; goto ex;}
 2288      hino= 0;
 2289      for(i= di[0] + 2; i < (int) di_l && i - di[0] - 2 < di[(int) di[0] + 1];
 2290          i++)
 2291        hino= (hino << 8) | ((unsigned char *) di)[i];
 2292      if(hino != ino)
 2293        {ret= 1; goto ex;} 
 2294    } else {
 2295      if(l != di_l)
 2296        {ret= 1; goto ex;}
 2297      for(i= 0; i < (int) l; i++)
 2298        if(di[i] != buf[i])
 2299          {ret= 1; goto ex;} 
 2300    }
 2301    ret= 0;
 2302  } else {
 2303    ret= Xorriso_setfattr(xorriso, in_node, iso_path,
 2304                          (size_t) 1, &name, &l, &bufpt, 2 | 8);
 2305  }
 2306 ex:;
 2307  if(di != NULL)
 2308    free(di);
 2309  return(ret);
 2310 }
 2311 
 2312 
 2313 /* @return  see Xorriso_update_interpreter()
 2314 */
 2315 int Xorriso_widen_hardlink(struct XorrisO *xorriso, void * boss_iter,
 2316                            IsoNode *node,
 2317                            char *abs_path, char *iso_prefix, char *disk_prefix,
 2318                            int flag)
 2319 {
 2320  int ret= 0, idx, low, high, i, do_widen= 0, compare_result= 0;
 2321  char *disk_path;
 2322 
 2323  Xorriso_alloc_meM(disk_path, char, SfileadrL);
 2324 
 2325  /* Lookup all di_array instances of node */
 2326  if(LIBISO_ISDIR(node))
 2327    {ret= 3; goto ex;}
 2328  ret= Xorriso_search_di_range(xorriso, node, &idx, &low, &high, 2);
 2329  if(ret <= 0)
 2330    {ret= 3; goto ex;}
 2331  /* Check and reset di_do_widen bits */
 2332  for(i= low; i <= high; i++) {
 2333    if(node != xorriso->di_array[i]) /* might be NULL */
 2334  continue;
 2335    if(xorriso->di_do_widen[i / 8] & (1 << (i % 8)))
 2336      do_widen= 1;
 2337    xorriso->di_do_widen[i / 8]&= ~(1 << (i % 8));
 2338  }
 2339  if(idx < 0 || !do_widen)
 2340    {ret= 3; goto ex;}
 2341 
 2342  ret= Xorriso_pfx_disk_path(xorriso, abs_path, iso_prefix, disk_prefix,
 2343                             disk_path, 0);
 2344  if(ret <= 0)
 2345    goto ex;
 2346  ret= Sfile_type(disk_path, 1);
 2347  if(ret < 0)
 2348    {ret= 3; goto ex;} /* does not exist on disk */
 2349 
 2350  /* >>> compare_result bit17 = is_split */;
 2351 
 2352  ret= Xorriso_update_interpreter(xorriso, boss_iter, NULL,
 2353                                  compare_result, disk_path, abs_path, 1);
 2354  if(ret <= 0)
 2355    goto ex;
 2356 ex:;
 2357  Xorriso_free_meM(disk_path);
 2358  return(ret);
 2359 }
 2360 
 2361 
 2362 int Xorriso_set_hidden(struct XorrisO *xorriso, void *in_node, char *path,
 2363                        int hide_state, int flag)
 2364 {
 2365  int ret, hide_attrs= 0;
 2366  IsoNode *node;
 2367 
 2368  node= (IsoNode *) in_node;
 2369  if(node == NULL) {
 2370    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2371    if(ret<=0)
 2372      return(ret);
 2373  }
 2374  if(hide_state) {
 2375    hide_attrs|= LIBISO_HIDE_BUT_WRITE;
 2376    if(hide_state & 1)
 2377      hide_attrs|= LIBISO_HIDE_ON_RR;
 2378    if(hide_state & 2)
 2379      hide_attrs|= LIBISO_HIDE_ON_JOLIET;
 2380    if(hide_state & 4)
 2381      hide_attrs|= LIBISO_HIDE_ON_HFSPLUS;
 2382  }
 2383  iso_node_set_hidden(node, hide_attrs);
 2384  return(1);
 2385 }
 2386 
 2387 
 2388 /* @param flag bit0= increase only upper estimation
 2389 */
 2390 int Xorriso_estimate_file_size(struct XorrisO *xorriso, struct FindjoB *job,
 2391                        char *basename, mode_t st_mode, off_t st_size, int flag)
 2392 {
 2393  off_t upper, lower, size;
 2394 
 2395   lower = 3 * strlen(basename) + 34; /* >>> + minimum RR ? */
 2396   upper = 3 * strlen(basename) + 2048;
 2397   if(S_ISREG(st_mode)) {
 2398     size= ((st_size + (off_t) 2047) / (off_t) 2048) * (off_t) 2048;
 2399     lower+= size;
 2400     upper+= size;
 2401   } else if(S_ISDIR(st_mode)) {
 2402     upper+= 4096;
 2403   }
 2404   job->estim_upper_size+= upper;
 2405   if(!(flag & 1))
 2406     job->estim_lower_size+= lower;
 2407   return(1);
 2408 }
 2409 
 2410 
 2411 /* @param flag  bit0= do not compare but print input and back converted name
 2412 */
 2413 int Xorriso_test_outchar(struct XorrisO *xorriso, void *node_pt,
 2414                          int name_space, int flag)
 2415 {
 2416  IsoNode *node;
 2417  char *result= NULL, *name, *back= NULL;
 2418  int ret, relax_mem;
 2419  size_t result_len, back_len, i;
 2420  struct isoburn_imgen_opts *sopts= NULL;
 2421 
 2422  relax_mem= xorriso->relax_compliance;
 2423 
 2424  node= (IsoNode *) node_pt;
 2425  ret= isoburn_igopt_new(&sopts, 0);
 2426  if(ret<=0) {
 2427    Xorriso_process_msg_queues(xorriso, 0);
 2428    ret= -1; goto ex;
 2429  } 
 2430  if(!(flag & 1))
 2431    xorriso->relax_compliance|= isoburn_igopt_omit_version_numbers;
 2432  ret= Xorriso_make_iso_write_opts(xorriso, NULL, sopts, 0);
 2433  if(ret <= 0) {
 2434    ret= -1; goto ex;
 2435  }
 2436 
 2437  if(iso_node_get_type(node) == LIBISO_DIR)
 2438    name_space |= 256;
 2439  name_space|= 512; /* no error messages */
 2440 
 2441  name= (char *) iso_node_get_name(node);
 2442  if(name == NULL) {
 2443    ret= 1; goto ex;
 2444  }
 2445  ret= isoburn_conv_name_chars(sopts, name, strlen(name), &result, &result_len,
 2446                               name_space);
 2447  if(ret <= 0) {
 2448    Xorriso_process_msg_queues(xorriso, 0);
 2449    if(flag & 1)
 2450      goto print_outname;
 2451    ret= 0; goto ex;
 2452  }
 2453    
 2454  /* Convert back and compare with original */
 2455  ret= isoburn_conv_name_chars(sopts, result, result_len, &back, &back_len,
 2456                               name_space | (1 << 15));
 2457  if(ret <= 0) {
 2458    Xorriso_process_msg_queues(xorriso, 0);
 2459    if(flag & 1)
 2460      goto print_outname;
 2461    ret= 0; goto ex;
 2462  }
 2463  if(flag & 1) {
 2464 print_outname:;
 2465    Text_shellsafe(name, xorriso->result_line, 0);
 2466    strcat(xorriso->result_line, "\n");
 2467    Xorriso_result(xorriso, 0);
 2468    if(back == NULL)
 2469      strcpy(xorriso->result_line, "(file name conversion error)");
 2470    else
 2471      Text_shellsafe(back, xorriso->result_line, 0);
 2472    strcat(xorriso->result_line, "\n");
 2473    Xorriso_result(xorriso, 0);
 2474    strcpy(xorriso->result_line, "--\n");
 2475    Xorriso_result(xorriso, 0);
 2476  } else {
 2477    for(i= 0; i < back_len; i++)
 2478      if(name[i] != back[i])
 2479        {ret= 0; goto ex;}
 2480    if(name[i] != 0)
 2481      {ret= 0; goto ex;}
 2482  }
 2483 
 2484  ret= 1;
 2485 ex:;
 2486  isoburn_igopt_destroy(&sopts, 0);
 2487  if(result != NULL)
 2488    free(result);
 2489  if(back != NULL)
 2490    free(back);
 2491  xorriso->relax_compliance= relax_mem;
 2492  return(ret);
 2493 }
 2494 
 2495 
 2496 int Xorriso_set_to_mtime(struct XorrisO *xorriso, char *show_path, 
 2497                          IsoNode *node, int flag)
 2498 {
 2499  time_t t;
 2500 
 2501  t= iso_node_get_mtime(node);
 2502  iso_node_set_atime(node, t);
 2503  iso_node_set_ctime(node, t);
 2504  Xorriso_set_change_pending(xorriso, 0);
 2505  return(1);
 2506 }
 2507 
 2508 
 2509 int Xorriso_cannot_create_iter(struct XorrisO *xorriso, int iso_error,int flag)
 2510 {
 2511  Xorriso_process_msg_queues(xorriso,0);
 2512  Xorriso_report_iso_error(xorriso, "", iso_error, "Cannot create iter", 0,
 2513                           "FATAL", 1);
 2514  sprintf(xorriso->info_text, "Cannot create IsoDirIter object");
 2515  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2516  return(1);
 2517 }
 2518 
 2519 
 2520 /* The caller shall make no assumptions about the meaning of iter, node_array,
 2521    node_count, node_idx ! They are just opaque handles for which the caller
 2522    provides the memory of proper type.
 2523    @param flag bit0= initialize iteration
 2524                bit1= action needs full freedom of object manipulation
 2525                bit2= action needs LBA sorted iteration
 2526                bit31= end iteration (mandatory !)
 2527 */
 2528 int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem,
 2529                        IsoDirIter **iter, 
 2530                        IsoNode ***node_array, int *node_count, int *node_idx,
 2531                        IsoNode **iterated_node, int flag)
 2532 {
 2533  int ret, i;
 2534  IsoNode *node;
 2535  off_t new_mem= 0;
 2536  char mem_text[80], limit_text[80];
 2537 
 2538  if(flag&1) {
 2539    *node_array= NULL;
 2540    *node_count= -1;
 2541    *node_idx= 0;
 2542    *iter= NULL;
 2543    ret= iso_dir_get_children(dir_node, iter);
 2544    if(ret<0) {
 2545 cannot_iter:;
 2546      Xorriso_cannot_create_iter(xorriso, ret, 0);
 2547      return(-1);
 2548    }
 2549    if((flag&2)|(flag&4)) {
 2550      /* copy list of nodes and prepare soft iterator */
 2551      *node_count= 0;
 2552      while(iso_dir_iter_next(*iter, &node) == 1)
 2553        (*node_count)++;
 2554      iso_dir_iter_free(*iter);
 2555      *iter= NULL;
 2556 
 2557      new_mem= ((*node_count)+1) * sizeof(IsoNode *);
 2558      if(new_mem > xorriso->temp_mem_limit) {
 2559        Sfile_scale((double) new_mem, mem_text, 5,1e4, 0);
 2560        Sfile_scale((double) xorriso->temp_mem_limit, limit_text, 5,1e4, 0);
 2561        sprintf(xorriso->info_text,
 2562            "Stacked directory snapshots exceed -temp_mem_limit (%s > %s)",
 2563            mem_text, limit_text);
 2564        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2565        *node_count= -1;
 2566        return(-1);
 2567      }
 2568      (*node_array)= (IsoNode **) calloc((*node_count)+1, sizeof(IsoNode *));
 2569      if(*node_array == NULL) {
 2570        sprintf(xorriso->info_text,
 2571                "Could not allocate inode list of %.f bytes",
 2572                ((double) (*node_count)+1) * (double) sizeof(IsoNode *));
 2573        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2574        *node_count= -1;
 2575        return(-1);
 2576      }
 2577      *mem= new_mem;
 2578      ret= iso_dir_get_children(dir_node, iter);
 2579      if(ret<0)
 2580        goto cannot_iter;
 2581      while(iso_dir_iter_next(*iter, &node) == 1 && *node_idx < *node_count) {
 2582        (*node_array)[*node_idx]= node;
 2583        iso_node_ref(node);
 2584        (*node_idx)++;
 2585      }
 2586      iso_dir_iter_free(*iter);
 2587      *iter= NULL;
 2588      *node_count= *node_idx;
 2589      *node_idx= 0;
 2590      if((flag&4) && *node_count>1)
 2591        qsort(*node_array, *node_count, sizeof(IsoNode *),
 2592              Xorriso__node_lba_cmp);
 2593    }
 2594  }
 2595 
 2596  if(flag&(1u<<31)) {
 2597    if(*node_count>=0 && *node_array!=NULL) {
 2598      for(i= 0; i<*node_count; i++)
 2599        iso_node_unref((*node_array)[i]);
 2600      free(*node_array);
 2601      *node_array= NULL;
 2602      *node_count= -1;
 2603      *node_idx= 0;
 2604    } else {
 2605      if(*iter!=NULL)
 2606        iso_dir_iter_free(*iter);
 2607      *iter= NULL;
 2608    }
 2609  }
 2610 
 2611  if(flag&(1|(1u<<31))) 
 2612    return(1);
 2613  if(*node_count>=0) {
 2614    /* return next node_array element */
 2615    if(*node_idx>=*node_count)
 2616      return(0);
 2617    *iterated_node= (*node_array)[*node_idx];
 2618    (*node_idx)++;
 2619  } else {
 2620    ret= iso_dir_iter_next(*iter, iterated_node);
 2621    return(ret == 1);
 2622  }
 2623  return(1);
 2624 }
 2625 
 2626 
 2627 /* @param flag bit0= not a command parameter (directory iteration or recursion)
 2628                bit1= do not count deleted files with rm and rm_r
 2629    @return <=0 error,
 2630              1=ok
 2631              2=ok, node has been deleted,
 2632              3=ok, do not dive into directory (e.g. because it is a split file)
 2633              4=ok, end findjob gracefully
 2634 */
 2635 int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
 2636                          IsoDirIter *boss_iter, off_t boss_mem,
 2637                          char *abs_path, char *show_path, 
 2638                          IsoNode *node, int depth, int flag)
 2639 {
 2640  int ret= 0, type, action= 0, hflag, deleted= 0, no_dive= 0, i, bless_idx;
 2641  int unbless= 0;
 2642  uid_t user= 0;
 2643  gid_t group= 0;
 2644  time_t date= 0;
 2645  mode_t mode_or= 0, mode_and= ~1;
 2646  char *target, *text_2, *iso_prefix, md5[16], *basename, bless_code[17];
 2647  char crtp[10];
 2648  struct FindjoB *subjob;
 2649  struct stat dir_stbuf, stbuf;
 2650  void *xinfo;
 2651  struct iso_hfsplus_xinfo_data *hfsplus_xinfo;
 2652  size_t value_length;
 2653  char *value;
 2654 
 2655  action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
 2656                                 &mode_and, &mode_or, &type, &date, &subjob, 0);
 2657  if(action<0)
 2658    action= 0;
 2659  job->match_count++;
 2660 
 2661  hflag= 16*!(flag&2);
 2662  ret= 1;
 2663  if(action==1) { /* rm (including rmdir) */
 2664    ret= Xorriso_fake_stbuf(xorriso, abs_path, &dir_stbuf, &node, 1);
 2665    if(ret>0) {
 2666      if(S_ISDIR(dir_stbuf.st_mode))
 2667        hflag= 2;
 2668      ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, hflag);
 2669      deleted= 1;
 2670    }
 2671  } else if(action==2) { /* rm_r */
 2672    ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag);
 2673    deleted= 1;
 2674  } else if(action==3) {
 2675 
 2676    /* >>> mv target */;
 2677 
 2678  } else if(action==4) { /* chown */
 2679    ret= Xorriso_set_uid(xorriso, abs_path, user, 0);
 2680  } else if(action==5) { /* chgrp */
 2681    ret= Xorriso_set_gid(xorriso, abs_path, group, 0);
 2682  } else if(action==6) { /* chmod */
 2683    ret= Xorriso_set_st_mode(xorriso, abs_path, mode_and, mode_or, 0);
 2684  } else if(action==7) { /* alter_date */
 2685    ret= Xorriso_set_time(xorriso, abs_path, date, type&7);
 2686  } else if(action==8) { /* lsdl */
 2687    ret= Xorriso_ls_filev(xorriso, "", 1, &abs_path, (off_t) 0, 1|2|8);
 2688  } else if(action>=9 && action<=13) { /* actions which have own findjobs */
 2689    Findjob_set_start_path(subjob, abs_path, 0);
 2690    ret= Xorriso_findi(xorriso, subjob, boss_iter, boss_mem, NULL,
 2691                       abs_path, &dir_stbuf, depth, 1);
 2692  } else if(action==14 || action==17 || action == 41) {
 2693                                           /* compare , update , update_merge */
 2694    Findjob_get_start_path(job, &iso_prefix, 0);
 2695    ret= Xorriso_find_compare(xorriso, (void *) boss_iter, (void *) node,
 2696                          abs_path, iso_prefix, target,
 2697                          (action == 17 || action == 41)
 2698                          | ((flag&1)<<1) | ((action == 41) << 2));
 2699    if(ret==2)
 2700      deleted= 1;
 2701    if(ret==3)
 2702      no_dive= 1;
 2703    if(ret>=0)
 2704      ret= 1;
 2705  } else if(action==16 || action==18) { /* not_in_iso , add_missing */
 2706    ;
 2707  } else if(action == 21) { /* report_damage */
 2708    ret= Xorriso_report_damage(xorriso, show_path, node, 0);
 2709  } else if(action == 22) {
 2710    ret= Xorriso_report_lba(xorriso, show_path, node,
 2711                            &job->last_data_file_block, 0);
 2712  } else if(action == 23) { /* internal: memorize path of last matching node */
 2713    ret= Findjob_set_found_path(job, show_path, 0);
 2714  } else if(action == 24) {
 2715    ret= Xorriso_getfacl(xorriso, (void *) node, show_path, NULL, 0);
 2716  } else if(action == 25) {
 2717    if(target == NULL || target[0] || text_2 == NULL || text_2[0])
 2718      ret= Xorriso_setfacl(xorriso, (void *) node, show_path, target, text_2,0);
 2719  } else if(action == 26) {
 2720    ret= Xorriso_getfattr(xorriso, (void *) node, show_path, NULL, 0);
 2721  } else if(action == 27) {
 2722    ret= Xorriso_path_setfattr(xorriso, (void *) node, show_path,
 2723                               target, strlen(text_2), text_2, 0);
 2724  } else if(action == 28) { /* set_filter */
 2725    ret= Xorriso_set_filter(xorriso, (void *) node, show_path, target, 1 | 2);
 2726  } else if(action == 29 || action == 52) { /* show_stream , show_stream_id */
 2727    ret= Xorriso_show_stream(xorriso, (void *) node, show_path, (action == 52));
 2728  } else if(action == 30) { /* internal: count */
 2729    xorriso->node_counter++;
 2730  } else if(action == 31) { /* internal: register */
 2731    if(xorriso->node_counter < xorriso->node_array_size) {
 2732      xorriso->node_array[xorriso->node_counter++]= (void *) node;
 2733      iso_node_ref(node); /* In case node gets deleted from tree during
 2734                             the lifetime of xorriso->node_array */
 2735    }
 2736  } else if(action == 32) { /* internal: widen_hardlinks disk_equiv */
 2737    Findjob_get_start_path(job, &iso_prefix, 0);
 2738    ret= Xorriso_widen_hardlink(xorriso, (void *) boss_iter, node, abs_path,
 2739                                iso_prefix, target, 0);
 2740    if(ret==2)
 2741      deleted= 1;
 2742  } else if(action == 33) { /* get_any_xattr */
 2743    ret= Xorriso_getfattr(xorriso, (void *) node, show_path, NULL, 8);
 2744  } else if(action == 34) { /* get_md5 */
 2745    ret= Xorriso_get_md5(xorriso, (void *) node, show_path, md5, 0);
 2746    if(ret >= 0)
 2747      ret= 1;
 2748  } else if(action == 35) { /* check_md5 */
 2749    ret= Xorriso_check_md5(xorriso, (void *) node, show_path, 2);
 2750    if(ret == 0)
 2751      xorriso->find_check_md5_result|= 1;
 2752    else if(ret < 0)
 2753      xorriso->find_check_md5_result|= 2;
 2754    else if(ret == 1)
 2755      xorriso->find_check_md5_result|= 8;
 2756    else if(ret == 2)
 2757      xorriso->find_check_md5_result|= 4;
 2758    if(ret >= 0)
 2759      ret= 1;
 2760  } else if(action == 36) { /* make_md5 */
 2761    ret= Xorriso_make_md5(xorriso, (void *) node, show_path, 0);
 2762    if(ret >= 0)
 2763      ret= 1;
 2764  } else if(action == 37) { /* mkisofs_r */
 2765    ret= Xorriso_mkisofs_lower_r(xorriso, node, 0);
 2766  } else if(action == 38) { /* sort_weight */
 2767    iso_node_set_sort_weight(node, type);
 2768    Xorriso_set_change_pending(xorriso, 0);
 2769  } else if(action == 39) { /* hide */
 2770    Xorriso_set_hidden(xorriso, node, NULL, type, 0);
 2771  } else if(action == 40) { /* estimate_size */
 2772    basename= strrchr(abs_path, '/');
 2773    if(basename != NULL)
 2774      basename++;
 2775    else
 2776      basename= abs_path;
 2777    ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
 2778    if(ret > 0)
 2779      ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode,
 2780                                      stbuf.st_size, 0);
 2781  } else if(action == 42) { /* rm_merge */
 2782    ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4);
 2783    if(ret == 2) {
 2784      ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag);
 2785      sprintf(xorriso->info_text, "Deleted ");
 2786      Text_shellsafe(show_path, xorriso->info_text, 1);
 2787      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 2788      deleted= 1;
 2789    }
 2790  } else if(action == 43) { /* clear_merge */
 2791    ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4);
 2792  } else if(action == 44) { /* list_extattr */
 2793    ret= Xorriso_list_extattr(xorriso, (void *) node, show_path, show_path,
 2794                              target, 0);
 2795  } else if(action == 45) { /* set_hfs_crtp */
 2796    ret= Xorriso_hfsplus_file_creator_type(xorriso, show_path, (void *) node, 
 2797                                           target, text_2, 0);
 2798 
 2799  } else if(action == 46) { /* get_hfs_crtp */
 2800    ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo);
 2801    if(ret < 0) {
 2802      Xorriso_process_msg_queues(xorriso, 0);
 2803      ret= 0;
 2804    } else if(ret == 1) {
 2805      hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo;
 2806      for(i= 0; i < 4; i++)
 2807        xorriso->result_line[i]= hfsplus_xinfo->creator_code[i];
 2808      xorriso->result_line[4]= ' ';
 2809      for(i= 0; i < 4; i++)
 2810        xorriso->result_line[5 + i]= hfsplus_xinfo->type_code[i];
 2811      xorriso->result_line[9]= ' ';
 2812      xorriso->result_line[10]= 0;
 2813      Text_shellsafe(show_path, xorriso->result_line, 1);
 2814      strcat(xorriso->result_line, "\n");
 2815      Xorriso_result(xorriso, 0);
 2816    }
 2817    ret= 1;
 2818  } else if(action == 47) { /* set_hfs_bless */
 2819    if(strcmp(target, "none") == 0 ||
 2820       strcmp(target, "n") == 0 || strcmp(target, "N") == 0) {
 2821      ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
 2822      if(ret < 0)
 2823        return(ret);
 2824      if(ret == 0)
 2825        return(1);
 2826      unbless= 1;
 2827    }
 2828    ret= Xorriso_hfsplus_bless(xorriso, show_path, (void *) node, target, 0);
 2829    /* If successful, end -find run gracefully */
 2830    if(ret > 0) {
 2831      if(unbless) {
 2832        sprintf(xorriso->info_text, "HFS blessing '%s' revoked from ",
 2833                                    bless_code);
 2834      } else {
 2835        sprintf(xorriso->info_text, "HFS blessing '%s' issued to ", target);
 2836      }
 2837      Text_shellsafe(show_path, xorriso->info_text, 1);
 2838      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2839    }
 2840    if(!unbless)
 2841      return(4);
 2842  } else if(action == 48) { /* get_hfs_bless */
 2843    ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
 2844    if (ret > 0) {
 2845      sprintf(xorriso->result_line, "%-16.16s ", bless_code);
 2846      Text_shellsafe(show_path, xorriso->result_line, 1);
 2847      strcat(xorriso->result_line, "\n");
 2848      Xorriso_result(xorriso, 0);
 2849    } else if(ret == 0)
 2850      ret= 1;
 2851  } else if(action == 49) {
 2852    /* internal: update creator, type, and blessings from persistent isofs.* */
 2853    ret= Xorriso_get_attr_value(xorriso, node, show_path, "isofs.hx",
 2854                                &value_length, &value, 0);
 2855    if(ret < 0) 
 2856      return(ret);
 2857    if(ret > 0) {
 2858      if(value_length >= 10) {
 2859        ret= Xorriso_hfsplus_file_creator_type(xorriso, show_path,
 2860                                              (void *) node,
 2861                                               value + 2, value + 6, 4);
 2862      } else
 2863        ret= 1;
 2864      free(value);
 2865      if(ret <= 0) 
 2866        return(ret);
 2867    }
 2868    ret= Xorriso_get_attr_value(xorriso, node, show_path, "isofs.hb",
 2869                                &value_length, &value, 0);
 2870    if(ret < 0) 
 2871      return(ret);
 2872    if(ret > 0) {
 2873      if(value_length >= 1) {
 2874        bless_code[0]= value[0];
 2875        bless_code[1]= 0;
 2876        ret= Xorriso_hfsplus_bless(xorriso, show_path, (void *) node,
 2877                                   bless_code, 0);
 2878      } else
 2879        ret= 1;
 2880      free(value);
 2881      if(ret <= 0)
 2882        return(ret);
 2883    }
 2884    ret= 1;
 2885    
 2886  } else if(action == 50) { /* print_outname */
 2887    ret= Xorriso_test_outchar(xorriso, (void *) node, type, 1);
 2888    if(ret <= 0)
 2889      return(ret);
 2890 
 2891  } else if(action == 51) { /* report_sections */
 2892    ret= Xorriso_report_lba(xorriso, show_path, node,
 2893                            &job->last_data_file_block, 1);
 2894 
 2895  } else if(action == 53) { /* internal: show_hfs_cmd */
 2896    ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
 2897    if (ret > 0) {
 2898      if(xorriso->show_hfs_cmd_flag & 2) {
 2899        sprintf(xorriso->result_line, "-hfs-bless-by %s ", bless_code);
 2900        Text_shellsafe(show_path, xorriso->result_line, 1);
 2901      } else {
 2902        sprintf(xorriso->result_line, "-find ");
 2903        Text_shellsafe(show_path, xorriso->result_line, 1);
 2904        sprintf(xorriso->result_line + strlen(xorriso->result_line),
 2905                " -exec set_hfs_bless %s --", bless_code);
 2906      }
 2907      ret= Xorriso_record_cmd_line(xorriso, xorriso->result_line,
 2908                                   xorriso->show_hfs_cmds,
 2909                                   &xorriso->show_hfs_cmd_count,
 2910                                   (xorriso->show_hfs_cmd_flag & 1));
 2911      if(ret <= 0)
 2912        return(ret);
 2913    } 
 2914    ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo);
 2915    if(ret < 0) {
 2916      Xorriso_process_msg_queues(xorriso, 0);
 2917      ret= 0;
 2918    } else if(ret == 1) {
 2919      hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo;
 2920      for(i= 0; i < 4; i++)
 2921        crtp[i]= hfsplus_xinfo->creator_code[i];
 2922      crtp[4]= ' ';
 2923      for(i= 0; i < 4; i++)
 2924        crtp[5 + i]= hfsplus_xinfo->type_code[i];
 2925      crtp[9]= 0;
 2926      if(xorriso->show_hfs_cmd_flag & 2) {
 2927        sprintf(xorriso->result_line, "-hfsplus-file-creator-type %s ", crtp);
 2928        Text_shellsafe(show_path, xorriso->result_line, 1);
 2929      } else {
 2930        sprintf(xorriso->result_line, "-find ");
 2931        Text_shellsafe(show_path, xorriso->result_line, 1);
 2932        sprintf(xorriso->result_line + strlen(xorriso->result_line),
 2933                " -exec set_hfs_crtp %s --", crtp);
 2934      }
 2935      ret= Xorriso_record_cmd_line(xorriso, xorriso->result_line,
 2936                                   xorriso->show_hfs_cmds,
 2937                                   &xorriso->show_hfs_cmd_count,
 2938                                   (xorriso->show_hfs_cmd_flag & 1));
 2939      if(ret <= 0)
 2940        return(ret);
 2941    }
 2942    ret= 1;
 2943 
 2944  } else if(action == 54 || action == 56) { /* internal: truncate_name */
 2945    ret= Xorriso_truncate_uniquely(xorriso, xorriso->file_name_limit,
 2946                                   node, abs_path, show_path,
 2947                                   2 * (action == 56));
 2948 
 2949  } else if(action == 55 || action == 57) {
 2950                             /* internal: unique_trunc_test length (in type) */
 2951    ret= Xorriso_truncate_uniquely(xorriso, type, node, abs_path, show_path,
 2952                                   1 | (2 * (action == 57)));
 2953 
 2954  } else if(action == 58) { /* internal: last_data_file_block */
 2955    ret= Xorriso_report_lba(xorriso, show_path, node,
 2956                            &job->last_data_file_block, 2);
 2957 
 2958  } else if(action == 59) { /* set_to_mtime */
 2959    ret= Xorriso_set_to_mtime(xorriso, show_path, node, 0);
 2960 
 2961  } else { /* includes : 15 in_iso */
 2962    Xorriso_esc_filepath(xorriso, show_path, xorriso->result_line, 0);
 2963    strcat(xorriso->result_line, "\n");
 2964    Xorriso_result(xorriso, 0);
 2965    ret= 1;
 2966  }
 2967  if(ret<=0)
 2968    return(ret);
 2969  if(deleted)
 2970    return(2);
 2971  if(no_dive)
 2972    return(3);
 2973  return(1);
 2974 }
 2975 
 2976 
 2977 /* flag bit0= perform -disk_path rather than -disk_name
 2978         bit0= use_pattern
 2979 */
 2980 int Exprtest_match_disk_name(struct XorrisO *xorriso, struct ExprtesT *ftest,
 2981                              IsoNode *node, int flag)
 2982 
 2983 {
 2984  int ret;
 2985  char *disk_path= NULL, *npt;
 2986  regmatch_t name_match;
 2987  char *arg1;
 2988  void *arg2;
 2989 
 2990  Xorriso_alloc_meM(disk_path, char, SfileadrL);
 2991 
 2992  ret= Xorriso_retrieve_disk_path(xorriso, node, disk_path, 0);
 2993  if(ret <= 0)
 2994    {ret= 0; goto ex;}
 2995  if(flag & 1) {
 2996    if(strcmp(disk_path, ftest->arg1) == 0)
 2997      {ret= 1; goto ex;}
 2998    {ret= 0; goto ex;}
 2999  }
 3000  arg1= (char *) ftest->arg1;
 3001  arg2= ftest->arg2;
 3002  npt= strrchr(disk_path, '/');
 3003  if(npt != NULL)
 3004    npt++;
 3005  else
 3006    npt= disk_path;
 3007  if(flag & 2) {
 3008    ret= ! regexec(arg2, npt, 1, &name_match, 0);
 3009  } else {
 3010    ret= (strcmp(arg1, npt) == 0);
 3011  }
 3012 ex:;
 3013  Xorriso_free_meM(disk_path);
 3014  return(ret);
 3015 }
 3016 
 3017 
 3018 int Exprtest_match(struct XorrisO *xorriso, struct ExprtesT *ftest,
 3019                    void *node_pt, char *name, char *path,
 3020                    struct stat *boss_stbuf, struct stat *stbuf, int flag)
 3021 /*
 3022 return:
 3023  <0 = error
 3024   0 = does not match
 3025   1 = does match
 3026   2 = immediate decision : does not match
 3027   3 = immediate decision : does match
 3028 */
 3029 {
 3030  int value=0, ret, start_lba, end_lba, bless_idx;
 3031  int lba_count, *file_end_lbas= NULL, *file_start_lbas= NULL, i, mask;
 3032  void *arg1, *arg2;
 3033  char ft, *decision, md5[16], bless_code[17];
 3034  regmatch_t name_match;
 3035  off_t damage_start, damage_end, size, *section_sizes= NULL;
 3036  void *xinfo_dummy;
 3037  IsoNode *node;
 3038  IsoStream *stream;
 3039  struct iso_hfsplus_xinfo_data *hfsplus_xinfo;
 3040 
 3041  if(ftest == NULL)
 3042    return(1);
 3043 
 3044  node= (IsoNode *) node_pt;
 3045  arg1= ftest->arg1;
 3046  arg2= ftest->arg2;
 3047 
 3048  if(node == NULL) {
 3049    switch(ftest->test_type) {
 3050    case 0: case 1: case 2: case 4: case 11: case 12: case 13:
 3051    case 22: case 23: case 25: case 26:
 3052      /* Tests which need no node parameter */
 3053    break;
 3054    default:
 3055      value= 0;
 3056      goto ex;
 3057    }
 3058  }
 3059 
 3060  switch(ftest->test_type) {
 3061  case 0: /* -false */
 3062    value= 0;
 3063 
 3064  break; case 1: /* -name *arg1 (regex in *arg2) */
 3065    if (ftest->boss->use_pattern) {
 3066       ret= regexec(arg2, name, 1, &name_match, 0);
 3067       value= !ret;
 3068    } else {
 3069       value= (strcmp((char *) arg1, name) == 0);
 3070    }
 3071 
 3072  break; case 2: /* -type *arg1 */
 3073    value= 1;
 3074    ft= *((char *) arg1);
 3075    if(ft!=0) {
 3076      if(S_ISBLK(stbuf->st_mode)) {
 3077        if(ft!='b')
 3078          value= 0;
 3079      } else if(S_ISCHR(stbuf->st_mode)) {
 3080        if(ft!='c')
 3081          value= 0;
 3082      } else if(S_ISDIR(stbuf->st_mode)) {
 3083        if(ft=='m') {
 3084          if(node != NULL)
 3085            value= 0;
 3086          else if(boss_stbuf==NULL)
 3087            value= 0;
 3088          else if(boss_stbuf->st_dev == stbuf->st_dev)
 3089            value= 0;
 3090        } else if(ft!='d')
 3091          value= 0;
 3092      } else if(S_ISFIFO(stbuf->st_mode)) {
 3093        if(ft!='p')
 3094          value= 0;
 3095      } else if(S_ISREG(stbuf->st_mode)) {
 3096        if(ft!='f' && ft!='-')
 3097          value= 0;
 3098      } else if(((stbuf->st_mode)&S_IFMT)==S_IFLNK) {
 3099        if(ft!='l')
 3100          value= 0;
 3101      } else if(((stbuf->st_mode)&S_IFMT)==S_IFSOCK) {
 3102        if(ft!='s')
 3103          value= 0;
 3104      } else if((flag & 1) && ((stbuf->st_mode) & S_IFMT) == Xorriso_IFBOOT) {
 3105        if(ft!='e' || node == NULL)
 3106          value= 0;
 3107      } else {
 3108        if(ft!='X')
 3109          value= 0;
 3110      }
 3111    }
 3112 
 3113  break; case 3: /* -damaged */;
 3114    value= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end,
 3115                                    0);
 3116    if(value > 0)
 3117      value= 1;
 3118 
 3119  break; case 4: /* -lba_range *arg1 *arg2 */
 3120    value= 1;
 3121    start_lba= *((int *) ftest->arg1);
 3122    end_lba= *((int *) ftest->arg2);
 3123    if(node == NULL) {
 3124      value= !(start_lba >= 0);
 3125      goto ex;
 3126    }
 3127    ret= Xorriso__start_end_lbas(node, &lba_count, &file_start_lbas,
 3128                                 &file_end_lbas, &section_sizes, &size, 0);
 3129    if(ret <= 0) {
 3130      if(ret < 0)
 3131        Xorriso_process_msg_queues(xorriso, 0);
 3132      if(start_lba >= 0)
 3133        value= 0;
 3134    } else {
 3135      for(i= 0; i < lba_count; i++) {
 3136        if(start_lba >= 0) {
 3137          if(file_end_lbas[i] < start_lba || file_start_lbas[i] > end_lba)
 3138            value= 0;
 3139        } else {
 3140          if(file_end_lbas[i] >= -start_lba && file_start_lbas[i] <= -end_lba)
 3141            value= 0;
 3142        }
 3143      }
 3144    }
 3145 
 3146  break; case 5: /* -has_acl */
 3147    ret = Xorriso_getfacl(xorriso, (void *) node, "", NULL, 2);
 3148    if(ret <= 0) {
 3149      value= -1;
 3150      Xorriso_process_msg_queues(xorriso, 0);
 3151      goto ex;
 3152    }
 3153    value= (ret == 1);
 3154 
 3155  break; case 6: /* -has_xattr */
 3156         case 14: /* -has_any_xattr */
 3157    ret = Xorriso_getfattr(xorriso, (void *) node, "", NULL,
 3158                           64 | (8 * (ftest->test_type == 14)));
 3159    if(ret < 0) {
 3160      value= -1;
 3161      Xorriso_process_msg_queues(xorriso, 0);
 3162      goto ex;
 3163    }
 3164    value= (ret > 0);
 3165 
 3166  break; case 7: /* -has_aaip */
 3167    ret= iso_node_get_xinfo(node, aaip_xinfo_func, &xinfo_dummy);
 3168    if(ret < 0) {
 3169      value= -1;
 3170      Xorriso_process_msg_queues(xorriso, 0);
 3171      goto ex;
 3172    }
 3173    value= (ret > 0);
 3174 
 3175  break; case 8: /* -has_filter */
 3176    value= 0;
 3177    if(LIBISO_ISREG(node)) {
 3178      stream= iso_file_get_stream((IsoFile *) node);
 3179      if(iso_stream_get_input_stream(stream, 0) != NULL)
 3180        value= 1;
 3181    }
 3182 
 3183  break; case 9: /* -wanted_node arg1 (for internal use) */
 3184    value= (((IsoNode *) arg1) == node);
 3185 
 3186  break; case 10: /* -pending_data */
 3187    value= 1;
 3188    if(!LIBISO_ISREG(node)) {
 3189      value= 0;
 3190    } else {
 3191      ret= Xorriso__file_start_lba(node, &start_lba, 0);
 3192      if(ret > 0 && start_lba >= 0)
 3193        value= 0;
 3194    }
 3195 
 3196  break; case 11: /* -decision */
 3197    value= 2;
 3198    decision= (char *) arg1;
 3199    if(strcmp(decision, "yes") == 0 || strcmp(decision, "true") == 0)
 3200      value= 3;
 3201 
 3202  break; case 12: /* -prune */
 3203    value= 1;
 3204    ftest->boss->prune= 1;
 3205 
 3206  break; case 13: /* -wholename *arg1 (regex in *arg2) */
 3207    if (ftest->boss->use_pattern) {
 3208      ret= regexec(arg2, path, 1, &name_match, 0);
 3209      value= !ret;
 3210    } else {
 3211      value= (strcmp(arg1, path) == 0);
 3212    }
 3213 
 3214  break; case 15: /* -has_md5 */
 3215    ret= Xorriso_get_md5(xorriso, node, path, md5, 1);
 3216    value= (ret > 0);
 3217 
 3218  break; case 16: /* -disk_name *arg1 (regex in *arg2) */
 3219    value= !! Exprtest_match_disk_name(xorriso, ftest, node,
 3220                                       2 * (ftest->boss->use_pattern));
 3221 
 3222  break; case 17: /* -hidden int *arg1 */
 3223    value= 1;
 3224    ret= iso_node_get_hidden(node);
 3225    mask= *((int *) arg1) & 3;
 3226    if((!!(mask & 1)) ^ (!!(ret & LIBISO_HIDE_ON_RR)))
 3227      value= 0;
 3228    if((!!(mask & 2)) ^ (!!(ret & LIBISO_HIDE_ON_JOLIET)))
 3229      value= 0;
 3230    if((!!(mask & 3)) ^ (!!(ret & LIBISO_HIDE_ON_HFSPLUS)))
 3231      value= 0;
 3232    
 3233  break; case 18: /* -has_hfs_crtp char *creator char *type */
 3234    ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo_dummy);
 3235    value= 0;
 3236    if(ret < 0) {
 3237      Xorriso_process_msg_queues(xorriso, 0);
 3238      ret= 0;
 3239    } else if(ret == 1) {
 3240      hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo_dummy;
 3241      if((strlen(arg1) == 1 ||
 3242          (strncmp(arg1, (char *) hfsplus_xinfo->creator_code, 4) == 0 &&
 3243           strlen(arg1) == 4)) &&
 3244         (strlen(arg2) == 1 || 
 3245          (strncmp(arg2, (char *) hfsplus_xinfo->type_code, 4) == 0 &&
 3246           strlen(arg2) == 4)))
 3247        value= 1;
 3248    }
 3249 
 3250  break; case 19: /* -has_hfs_bless int bless_index */
 3251    value= 0;
 3252    ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
 3253    if (ret > 0) {
 3254      if(*((int *) arg1) == (int) ISO_HFSPLUS_BLESS_MAX ||
 3255         *((int *) arg1) == bless_idx)
 3256        value= 1;
 3257    }
 3258 
 3259  break; case 20: /* -disk_path */
 3260    value= !! Exprtest_match_disk_name(xorriso, ftest, node,
 3261                                       1 | 2 * (ftest->boss->use_pattern));
 3262 
 3263  break; case 21: /* -bad_outname */
 3264    ret= Xorriso_test_outchar(xorriso, node, *((int *) arg1), 0);
 3265    if(ret < 0) {
 3266      value= -1;
 3267      goto ex;
 3268    }
 3269    value= !ret; /* Xorriso_test_outchar() returns 1 for good and 0 for bad */
 3270 
 3271  break; case 22: /* -use_pattern */
 3272    ftest->boss->use_pattern= (strcmp(arg1, "off") != 0);
 3273    value= 1;
 3274 
 3275  break; case 23: /* -or_use_pattern */
 3276    ftest->boss->use_pattern= (strcmp(arg1, "off") != 0);
 3277    value= 0;
 3278 
 3279  break; case 24: /* -name_limit_blocker */
 3280    ret= Xorriso_truncate_uniquely(xorriso, *((int *) arg1), node, path, path,
 3281                                   1 | 4);
 3282    value= (ret == 0);
 3283 
 3284  break; case 25: /* -maxdepth */
 3285    value= (ftest->boss->depth <= *((int *) arg1));
 3286 
 3287  break; case 26: /* -mindepth */
 3288    value= (ftest->boss->depth >= *((int *) arg1));
 3289 
 3290  break; default:
 3291 
 3292    /* >>> complain about unknown test type */;
 3293 
 3294    value= -1;
 3295 
 3296  }
 3297 
 3298 ex:;
 3299  if(ftest->invert && value<=1 && value>=0)
 3300    value= !value;
 3301  if(file_start_lbas != NULL)
 3302    free((char *) file_start_lbas);
 3303  if(file_end_lbas != NULL)
 3304    free((char *) file_end_lbas);
 3305  if(section_sizes != NULL)
 3306    free((char *) section_sizes);
 3307  return(value);
 3308 }
 3309 
 3310 
 3311 /* @return <0 = error , 0 = no match , 1 = match */
 3312 int Xorriso_findi_test(struct XorrisO *xorriso, struct FindjoB *job,
 3313                        IsoNode *node, char *name, char *path,
 3314                        struct stat *boss_stbuf, struct stat *stbuf,
 3315                        int depth, int flag)
 3316 {
 3317  int ret;
 3318 
 3319  job->prune= 0;
 3320  ret= Findjob_test_2(xorriso, job, node, name, path, boss_stbuf, stbuf, 1);
 3321  if(ret <= 0)
 3322    return(ret);
 3323  return(1);
 3324 }
 3325 
 3326 
 3327 int Xorriso_findi_headline(struct XorrisO *xorriso, struct FindjoB *job,
 3328                            int flag)
 3329 {
 3330  int action;
 3331 
 3332  action= Findjob_get_action(job, 0);
 3333  if(action == 21) {                                         /* report_damage */
 3334    sprintf(xorriso->result_line, "Report layout: %8s , %8s , %8s , %s\n",
 3335            "at byte", "Range", "Filesize", "ISO image path");
 3336    Xorriso_result(xorriso, 0);
 3337  } else if(action == 22 || action == 51) {    /* report_lba, report_sections */
 3338    sprintf(xorriso->result_line,
 3339            "Report layout: %2s , %8s , %8s , %8s , %s\n",
 3340            "xt", "Startlba", "Blocks", action == 22 ? "Filesize" : "Sectsize",
 3341            "ISO image path");
 3342    Xorriso_result(xorriso, 0);
 3343  }
 3344  return(1);
 3345 }
 3346 
 3347 
 3348 /* @param flag bit0= recursion
 3349                bit1= do not count deleted files with rm and rm_r
 3350                bit2= do not dive into split file directories
 3351                      (implicitly given with actions 14=compare and 17=update)
 3352    @return <=0 error, 1= ok , 2= dir node and path has been deleted
 3353                       4= end gracefully
 3354 */
 3355 int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job,
 3356                   void *boss_iter, off_t boss_mem,
 3357                   void *dir_node_generic, char *dir_path,
 3358                   struct stat *dir_stbuf, int depth, int flag)
 3359 {
 3360  int ret, action= 0, hflag, deleted= 0, no_dive= 0;
 3361  IsoDirIter *iter= NULL;
 3362  IsoDir *dir_node= NULL;
 3363  IsoNode *node, *iso_node;
 3364  IsoImage *volume= NULL;
 3365  struct stat stbuf;
 3366  char *name;
 3367  off_t mem;
 3368  IsoNode **node_array= NULL;
 3369  int node_count= 0, node_idx;
 3370  char *path= NULL, *abs_path= NULL;
 3371 
 3372  job->depth= depth;
 3373 
 3374  if(xorriso->request_to_abort)
 3375    {ret= 0; goto ex;}
 3376 
 3377  path= malloc(SfileadrL);
 3378  abs_path= malloc(SfileadrL);
 3379  if(path==NULL || abs_path==NULL) {
 3380    Xorriso_no_malloc_memory(xorriso, &path, 0);
 3381    {ret= -1; goto ex;}
 3382  }
 3383 
 3384  action= Findjob_get_action(job, 0);
 3385  if(action<0)
 3386    action= 0;
 3387  if(!(flag & 1)) {
 3388    Xorriso_findi_headline(xorriso, job, 0);
 3389    job->last_data_file_block= 0;
 3390  }
 3391 
 3392  dir_node= (IsoDir *) dir_node_generic;
 3393  if(dir_node==NULL) {
 3394    ret= Xorriso_get_volume(xorriso, &volume, 0);
 3395    if(ret<=0)
 3396      {ret= -1; goto ex;}
 3397    ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, dir_path, path, 1|2|4);
 3398    if(ret<=0)
 3399      goto ex;
 3400    ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 0);
 3401    dir_node= (IsoDir *) iso_node;
 3402    if(ret<=0)
 3403      {ret= 0; goto ex;}
 3404    ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1);
 3405    if(ret<=0)
 3406      goto ex;
 3407 
 3408    name= strrchr(dir_path, '/');
 3409    if(name==NULL)
 3410      name= dir_path;
 3411    else
 3412      name++;
 3413 
 3414    ret= Xorriso_findi_test(xorriso, job, iso_node, name, path, NULL, dir_stbuf,
 3415                            depth, 0);
 3416    if(ret<0)
 3417      goto ex;
 3418    if(job->prune)
 3419      no_dive= 1;
 3420    if(ret>0) {
 3421      iso_node_ref(iso_node); /* protect from real disposal */
 3422      ret= Xorriso_findi_action(xorriso, job,
 3423                                (IsoDirIter *) boss_iter, boss_mem,
 3424                                path, dir_path, iso_node, depth,
 3425                                flag&(1|2));
 3426      deleted= (iso_node_get_parent(iso_node) == NULL); /* still in tree ? */
 3427      iso_node_unref(iso_node); /* eventually do real disposal */
 3428      if(xorriso->request_to_abort)
 3429        {ret= 0; goto ex;}
 3430      if(ret == 4)
 3431        goto ex;
 3432      if(ret<=0)
 3433        goto ex;
 3434      if(ret==2 || deleted) {
 3435        /* re-determine dir_node in case it has a new persona */ 
 3436        ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 1);
 3437        if(ret==0) {
 3438          deleted= 1;
 3439          {ret= 2; goto ex;}
 3440        }
 3441        if(ret<0)
 3442          {ret= 0; goto ex;}
 3443        dir_node= (IsoDir *) iso_node;
 3444        ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1);
 3445        if(ret<=0)
 3446          goto ex;
 3447      }
 3448      if(ret==3)
 3449        no_dive= 1;
 3450    }
 3451  }
 3452  if(no_dive || !LIBISO_ISDIR((IsoNode *) dir_node))
 3453    {ret= 1; goto ex;}
 3454  if(action == 14 || action == 17 || (flag & 4))
 3455    if(Xorriso_is_split(xorriso, dir_path, (IsoNode *) dir_node, 1)>0)
 3456      {ret= 1; goto ex;}
 3457 
 3458  mem= boss_mem;
 3459  hflag= 1;
 3460  if(action==1 || action==2 || action==3 || action==17 || action == 28 ||
 3461     action == 32 || action == 41 || action == 42)
 3462    hflag|= 2; /* need freedom to manipulate image */
 3463  if(action==14 || action==17 || action == 28 || action == 35 || action == 36 ||
 3464     action == 41)
 3465    hflag|= 4; /* need LBA sorted iteration for good data reading performance */
 3466  ret= Xorriso_findi_iter(xorriso, dir_node, &mem,
 3467                          &iter, &node_array, &node_count, &node_idx,
 3468                          &node, hflag);
 3469  if(ret<=0)
 3470    goto ex;
 3471  job->depth++;
 3472  while(1) {
 3473    ret= Xorriso_findi_iter(xorriso, dir_node, &mem, &iter,
 3474                            &node_array, &node_count, &node_idx, &node, 0);
 3475    if(ret<0)
 3476      goto ex;
 3477    if(ret==0)
 3478  break;
 3479    name= (char *) iso_node_get_name(node);
 3480    ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
 3481    if(ret<=0)
 3482      goto ex;
 3483    ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
 3484    if(ret<0)
 3485      goto ex;
 3486    if(ret==0)
 3487  continue;
 3488 
 3489 /* ??? This seems to be redundant with the single test above
 3490    ??? Should i dive in unconditionally and leave out test and action here ?
 3491    ??? Then do above test unconditionally ?
 3492    --- Seems that the current configuration represents the special
 3493        handling of the find start path with mount points. Dangerous to change.
 3494 */
 3495 
 3496    ret= Xorriso_findi_test(xorriso, job, node, name, path, dir_stbuf, &stbuf,
 3497                            depth, 0);
 3498    if(ret<0)
 3499      goto ex;
 3500    if(job->prune)
 3501      no_dive= 1;
 3502    if(ret>0) {
 3503      ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, path, abs_path, 1|2|4);
 3504      if(ret<=0)
 3505        goto ex;
 3506      ret= Xorriso_findi_action(xorriso, job, iter, mem,
 3507                                abs_path, path, node, depth, 1|(flag&2));
 3508      if(xorriso->request_to_abort)
 3509        {ret= 0; goto ex;}
 3510      if(ret == 4)
 3511        goto ex;
 3512      if(ret==2) { /* node has been deleted */
 3513        /* re-determine node in case it has a new persona */ 
 3514        if(volume==NULL) {
 3515          ret= Xorriso_get_volume(xorriso, &volume, 0);
 3516          if(ret<=0)
 3517            {ret= -1; goto ex;}
 3518        }
 3519        ret= Xorriso_node_from_path(xorriso, volume, abs_path, &node, 1);
 3520        if(ret==0)
 3521  continue;
 3522        if(ret<0)
 3523          {ret= 0; goto ex;}
 3524        ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
 3525        if(ret<0)
 3526          goto ex;
 3527        if(ret==0)
 3528  continue;
 3529      }
 3530      no_dive= (ret==3);
 3531      if(ret<=0) {
 3532        if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 3533          goto ex;
 3534      }
 3535    }
 3536 
 3537    if(S_ISDIR(stbuf.st_mode) && !no_dive) {
 3538      ret= Xorriso_findi(xorriso, job, (void *) iter, mem,
 3539                         (void *) node, path, &stbuf, depth+1, flag|1);
 3540      if(ret<0)
 3541        goto ex;
 3542      if(xorriso->request_to_abort)
 3543        {ret= 0; goto ex;}
 3544      if(ret == 4)
 3545        goto ex;
 3546    }
 3547  }
 3548 
 3549  ret= 1;
 3550 ex:;
 3551  job->depth= depth;
 3552  if(path!=NULL)
 3553    free(path);
 3554  if(abs_path!=NULL)
 3555    free(abs_path);
 3556  Xorriso_process_msg_queues(xorriso,0);
 3557 
 3558  Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count,
 3559                     &node_idx, &node, (1u<<31));
 3560  if(ret<=0)
 3561    return(ret);
 3562  if(deleted)
 3563    return(2);
 3564  return(1);
 3565 }
 3566 
 3567 
 3568 /* @param flag bit0= do not dive into trees
 3569                bit1= do not perform job->action on resulting node array
 3570                bit2= do not free node_array after all actions are done
 3571 */
 3572 int Xorriso_findi_sorted(struct XorrisO *xorriso, struct FindjoB *job,
 3573                          off_t boss_mem, int filec, char **filev, int flag)
 3574 {
 3575  int i, ret, find_flag= 0;
 3576  struct FindjoB array_job, *proxy_job= NULL, *hindmost= NULL, *hmboss= NULL;
 3577  struct stat dir_stbuf;
 3578  IsoNode *node;
 3579  char *abs_path= NULL;
 3580  off_t mem_needed= 0;
 3581 
 3582  array_job.start_path= NULL;
 3583 
 3584  Xorriso_alloc_meM(abs_path, char, SfileadrL);
 3585 
 3586  if(job->action == 14 || job->action == 17)
 3587    find_flag|= 4;
 3588  if(job->action>=9 && job->action<=13) { /* actions which have own findjobs */
 3589    /* array_job replaces the hindmost job in the chain */
 3590    for(hindmost= job; hindmost->subjob != NULL; hindmost= hindmost->subjob)
 3591      hmboss= hindmost;
 3592    if(hmboss == NULL)
 3593      {ret= -1; goto ex;}
 3594    memcpy(&array_job, hindmost, sizeof(struct FindjoB));
 3595    hmboss->subjob= &array_job;
 3596    proxy_job= job;
 3597  } else {
 3598    memcpy(&array_job, job, sizeof(struct FindjoB));
 3599    proxy_job= &array_job;
 3600    hindmost= job;
 3601  }
 3602  array_job.start_path= NULL; /* is owned by the original, not by array_job */
 3603 
 3604  /* Count matching nodes */
 3605  Xorriso_destroy_node_array(xorriso, 0);
 3606  array_job.action= 30; /* internal: count */
 3607  for(i= 0; i < filec; i++) {
 3608    if(flag & 1) {
 3609      xorriso->node_counter++;
 3610  continue;
 3611    }
 3612    ret= Findjob_set_start_path(proxy_job, filev[i], 0);
 3613    if(ret <= 0)
 3614      goto ex;
 3615    ret= Xorriso_findi(xorriso, proxy_job, NULL, boss_mem, NULL,
 3616                       filev[i],  &dir_stbuf, 0, find_flag);
 3617    if(ret <= 0)
 3618      goto ex;
 3619  }
 3620  if(xorriso->node_counter <= 0)
 3621    {ret= 1; goto ex;}
 3622 
 3623  mem_needed= boss_mem + xorriso->node_counter * sizeof(IsoNode *);
 3624  if(!(flag &1)) {
 3625    ret= Xorriso_check_temp_mem_limit(xorriso, mem_needed, 0);
 3626    if(ret <= 0) {
 3627      /* Memory curbed : Perform unsorted find jobs */
 3628      if(hmboss != NULL)
 3629        hmboss->subjob= hindmost;
 3630      for(i= 0; i < filec; i++) {
 3631        ret= Findjob_set_start_path(job, filev[i], 0);
 3632        if(ret <= 0)
 3633          goto ex;
 3634        ret= Xorriso_findi(xorriso, job, NULL, boss_mem, NULL,
 3635                           filev[i], &dir_stbuf, 0, find_flag);
 3636        if(ret <= 0)
 3637          if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 3638            goto ex;
 3639      }
 3640      {ret= 1; goto ex;}
 3641    }
 3642  }
 3643 
 3644  /* Copy matching nodes into allocated array */
 3645  ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0, 0);
 3646  if(ret <= 0)
 3647    goto ex;
 3648  array_job.action= 31; /* internal: register */
 3649  xorriso->node_counter= 0;
 3650  for(i= 0; i < filec; i++) {
 3651    if(flag & 1) {
 3652      ret= Xorriso_get_node_by_path(xorriso, filev[i], NULL, &node, 0);
 3653      if(ret <= 0)
 3654        goto ex;
 3655      if(xorriso->node_counter < xorriso->node_array_size) {
 3656        xorriso->node_array[xorriso->node_counter++]= (void *) node;
 3657        iso_node_ref(node);
 3658      }
 3659  continue;
 3660    }
 3661    ret= Findjob_set_start_path(proxy_job, filev[i], 0);
 3662    if(ret <= 0)
 3663      goto ex;
 3664    ret= Xorriso_findi(xorriso, proxy_job, NULL, mem_needed, NULL,
 3665                       filev[i], &dir_stbuf, 0, find_flag);
 3666    if(ret <= 0)
 3667      goto ex;
 3668  }
 3669 
 3670  Xorriso_sort_node_array(xorriso, 0);
 3671  if(flag & 2)
 3672    {ret= 1; goto ex;}
 3673 
 3674  /* Perform job->action on xorriso->node_array */
 3675 
 3676  /* Headlines of actions report_damage , report_lba */;
 3677  Xorriso_findi_headline(xorriso, job, 0);
 3678 
 3679  for(i= 0; i < xorriso->node_counter; i++) {
 3680    node= xorriso->node_array[i];
 3681    ret= Xorriso_path_from_node(xorriso, node, abs_path, 0);
 3682    if(ret < 0)
 3683      goto ex;
 3684    if(ret == 0)
 3685  continue; /* node is deleted from tree meanwhile */
 3686 
 3687    ret= Xorriso_findi_action(xorriso, hindmost, NULL, (off_t) 0,
 3688                              abs_path, abs_path, node, 0, 1);
 3689    if(ret <= 0 || xorriso->request_to_abort)
 3690      if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 3691        goto ex;
 3692    if(ret == 4) /* end gracefully */
 3693  break;
 3694  }
 3695 
 3696  ret= 1;
 3697 ex:;
 3698  if(!(flag & (2 | 4)))
 3699    Xorriso_destroy_node_array(xorriso, 0);
 3700  if(hmboss != NULL)
 3701    hmboss->subjob= hindmost;
 3702  if(array_job.start_path != NULL)
 3703    free(array_job.start_path);
 3704  Xorriso_free_meM(abs_path);
 3705  return(ret);
 3706 }
 3707 
 3708 
 3709 int Xorriso_all_node_array(struct XorrisO *xorriso, int addon_nodes, int flag)
 3710 {  
 3711  int ret;
 3712  struct FindjoB *job= NULL;
 3713  struct stat dir_stbuf;
 3714 
 3715  ret= Findjob_new(&job, "/", 0);
 3716  if(ret<=0) {
 3717    Xorriso_no_findjob(xorriso, "xorriso", 0);
 3718    {ret= -1; goto ex;}
 3719  }
 3720  Findjob_set_action_target(job, 30, NULL, 0);
 3721  Xorriso_destroy_node_array(xorriso, 0);
 3722  ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
 3723                     &dir_stbuf, 0, 0);
 3724  if(ret <= 0)
 3725    goto ex;
 3726  ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, addon_nodes, 0);
 3727  if(ret <= 0)
 3728    goto ex;
 3729  Findjob_set_action_target(job, 31, NULL, 0);
 3730  ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
 3731                     &dir_stbuf, 0, 0);
 3732  if(ret <= 0)
 3733    goto ex;
 3734  ret= 1;
 3735 ex:;
 3736  Findjob_destroy(&job, 0);
 3737  return(ret);
 3738 }
 3739 
 3740 
 3741 int Xorriso_perform_acl_from_list(struct XorrisO *xorriso, char *file_path,
 3742                                   char *uid, char *gid, char *acl, int flag)
 3743 {
 3744  int ret, zero= 0;
 3745  uid_t uid_number;
 3746  gid_t gid_number;
 3747 
 3748  /* Set group and owner */
 3749  if(gid[0]) {
 3750    ret= Xorriso_convert_gidstring(xorriso, gid, &gid_number, 0);
 3751    if(ret<=0)
 3752      return(ret);
 3753    ret= Xorriso_set_gid(xorriso, file_path, gid_number, 0);
 3754    if(ret<=0)
 3755      return(ret);
 3756  }
 3757  if(uid[0]) {
 3758    ret= Xorriso_convert_uidstring(xorriso, uid, &uid_number, 0);
 3759    if(ret<=0)
 3760      return(ret);
 3761    ret= Xorriso_set_uid(xorriso, file_path, uid_number, 0);
 3762    if(ret<=0)
 3763      return(ret);
 3764  }
 3765  ret= Xorriso_option_setfacli(xorriso, acl, 1, &file_path, &zero, 0);
 3766  if(ret <= 0)
 3767    return(ret);
 3768  return(1);
 3769 }
 3770 
 3771 
 3772 /*
 3773   @param flag   bit0= do not perform setfattr but only check input
 3774 */
 3775 int Xorriso_path_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
 3776                         char *name, size_t value_length, char *value, int flag)
 3777 {
 3778  int ret, hflag;
 3779  size_t num_attrs= 1;
 3780  char *name_pt;
 3781 
 3782  hflag= 2;
 3783  name_pt= name;
 3784  if(name[0] == 0) {
 3785    sprintf(xorriso->info_text,
 3786            "-setfattr: Empty attribute name is not allowed");
 3787    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 3788    return(0);
 3789  } else if(strcmp(name, "--remove-all") == 0) {
 3790    if(value[0]) {
 3791      sprintf(xorriso->info_text,
 3792              "-setfattr: Value is not empty with pseudo name --remove-all");
 3793      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 3794      return(0);
 3795    }
 3796    num_attrs= 0;
 3797    hflag= 0;
 3798  } else if(name[0] == '-') {
 3799    name_pt++;
 3800    hflag|= 4;
 3801  } else if(name[0] == '=' || name[0] == '+') {
 3802    name_pt++;
 3803  }
 3804  if(flag & 1)
 3805    return(1);
 3806  ret= Xorriso_setfattr(xorriso, in_node, path,
 3807                        num_attrs, &name_pt, &value_length, &value, hflag);
 3808  return(ret);
 3809 }
 3810 
 3811 
 3812 /* Warning: The text content of lst gets mangled by 0s and unescaping.
 3813 */
 3814 int Xorriso_perform_attr_from_list(struct XorrisO *xorriso, char *path,
 3815                       struct Xorriso_lsT *lst_start, int flag)
 3816 {
 3817  int ret, eaten;
 3818  char *valuept, *ept, *line, **names= NULL, **values= NULL;
 3819  size_t num_attr= 0, *value_lengths= NULL, v_len;
 3820  struct Xorriso_lsT *lst;
 3821 
 3822  for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0))
 3823    num_attr++;
 3824  if(num_attr == 0) {
 3825    ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, NULL, NULL, NULL, 0);
 3826    goto ex;
 3827  }
 3828 
 3829  names= calloc(num_attr, sizeof(char *));
 3830  if(names == NULL) {
 3831    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 3832    ret= -1; goto ex;
 3833  }
 3834  value_lengths= calloc(num_attr, sizeof(size_t));
 3835  if(value_lengths== NULL) {
 3836    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 3837    ret= -1; goto ex;
 3838  }
 3839  values= calloc(num_attr, sizeof(char *));
 3840  if(values== NULL) {
 3841    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 3842    ret= -1; goto ex;
 3843  }
 3844 
 3845  num_attr= 0;
 3846  for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0)) {
 3847    line= Xorriso_lst_get_text(lst, 0);
 3848    ept= strchr(line, '=');
 3849    if(ept == NULL)
 3850  continue;
 3851    /* Split into name and content */;
 3852    *ept= 0;
 3853    valuept= ept + 1;
 3854 
 3855    /* Strip quotes from value */
 3856    v_len= strlen(valuept);
 3857    if(v_len < 2 || *valuept != '"' || *(valuept + v_len - 1) != '"')
 3858  continue;
 3859    *valuept= 0;
 3860    *(valuept + v_len - 1)= 0;
 3861    valuept++;
 3862    v_len-= 2;
 3863 
 3864    /* Unescape backslashes , values eventually with 0-bytes */
 3865    ret= Sfile_bsl_interpreter(line, strlen(line), &eaten, 0);
 3866    if(ret <= 0)
 3867  continue;
 3868    ret= Sfile_bsl_interpreter(valuept, (int) v_len, &eaten, 2);
 3869    if(ret <= 0)
 3870  continue;
 3871 
 3872    names[num_attr]= line;
 3873    values[num_attr]= valuept;
 3874    value_lengths[num_attr]= v_len - eaten;
 3875    num_attr++;
 3876  }
 3877  ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, names,
 3878                        value_lengths, values, 0);
 3879 ex:;
 3880  if(names != NULL)
 3881    free(names);
 3882  if(value_lengths != NULL)
 3883    free(value_lengths);
 3884  if(values != NULL)
 3885    free(values);
 3886  return(ret);
 3887 }
 3888 
 3889 
 3890 int Xorriso__mark_update_xinfo(void *data, int flag)
 3891 {
 3892  /* data is an int disguised as pointer. It does not point to memory. */
 3893  return(1);
 3894 }
 3895 
 3896 
 3897 int Xorriso__mark_update_cloner(void *old_data, void **new_data, int flag)
 3898 {
 3899  *new_data= NULL;
 3900  if(flag)
 3901    return(ISO_XINFO_NO_CLONE);
 3902  if(old_data == NULL)
 3903    return(0);
 3904  /* data is an int disguised as pointer. It does not point to memory. */
 3905  *new_data= old_data;
 3906  return(0);
 3907 }
 3908 
 3909 
 3910 /* @param flag bit0= found on disk
 3911                bit1= inquire visit-found status:
 3912                      1=not visited, 2=not found, 3=found
 3913                bit2= with bit1: delete xinfo before returning status
 3914 */
 3915 int Xorriso_mark_update_merge(struct XorrisO *xorriso, char *path,
 3916                               void *in_node, int flag)
 3917 {
 3918  int ret;
 3919  void *xipt= NULL;
 3920  IsoNode *node;
 3921 
 3922  if(in_node == NULL) {
 3923    ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
 3924    if(ret <= 0)
 3925      return(ret);
 3926  } else
 3927    node= (IsoNode *) in_node;
 3928  ret= iso_node_get_xinfo(node, Xorriso__mark_update_xinfo, &xipt);
 3929  if(ret < 0) {
 3930    Xorriso_process_msg_queues(xorriso,0);
 3931    Xorriso_report_iso_error(xorriso, "", ret,
 3932                             "Error when looking for update_merge xinfo",
 3933                             0, "FAILURE", 1);
 3934    return(0);
 3935  }
 3936  if(flag & 2) { /* Inquire status and optionally delete xinfo */
 3937    if(ret == 0)
 3938      return(1);
 3939    if(flag & 4) {
 3940      ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo);
 3941      if(ret < 0) {
 3942        Xorriso_process_msg_queues(xorriso,0);
 3943        Xorriso_report_iso_error(xorriso, "", ret,
 3944                                 "Error when removing update_merge xinfo",
 3945                                 0, "FAILURE", 1);
 3946        return(0);
 3947      }
 3948    }
 3949    if(((char *) &xipt)[0])
 3950      return(3);
 3951    return(2);
 3952  }
 3953  /* xipt is a byte value disguised as void pointer */
 3954  if(ret == 1) {
 3955    if(((char *) &xipt)[0])
 3956      return(1);
 3957    if(!(flag & 1))
 3958      return(1);
 3959  } else
 3960    ((char *) &xipt)[0]= 0;
 3961  if(flag & 1)
 3962    ((char *) &xipt)[0]= 1;
 3963  ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo);
 3964  if(ret < 0)
 3965    goto set_error;
 3966  ret= iso_node_add_xinfo(node, Xorriso__mark_update_xinfo, xipt);
 3967  if(ret <= 0) {
 3968 set_error:;
 3969    Xorriso_process_msg_queues(xorriso,0);
 3970    Xorriso_report_iso_error(xorriso, "", ret,
 3971                             "Error when trying to set update_merge xinfo",
 3972                             0, "FAILURE", 1);
 3973    return(0);
 3974  }
 3975  return(1);
 3976 }
 3977 
 3978 
 3979 /* flag bit0= in case of error talk of "overwrite" rather than "remove"
 3980 */
 3981 static int Xorriso_remove_hfsplus_crtp(struct XorrisO *xorriso, IsoNode *node,
 3982                                        char *path, int flag)
 3983 {
 3984  int ret;
 3985  char *msg, buf[10], *bufpt;
 3986  size_t l;
 3987  static char *name= "isofs.hx";
 3988 
 3989  ret= iso_node_remove_xinfo(node, iso_hfsplus_xinfo_func);
 3990  Xorriso_process_msg_queues(xorriso, 0);
 3991  if(ret < 0) {
 3992    if(flag & 1)
 3993      msg= "Cannot overwrite HFS+ creator and type of ISO node";
 3994    else
 3995      msg= "Cannot remove HFS+ creator and type of ISO node";
 3996    Xorriso_report_iso_error(xorriso, path, ret, msg, 0, "FAILURE", 1);
 3997    return(0);
 3998  }
 3999  /* Delete isofs.hx attribute */
 4000  bufpt= buf;
 4001 
 4002  /* >>> ??? check whether there is isofs.hx attached ? */;
 4003 
 4004  ret= Xorriso_setfattr(xorriso, node, path,
 4005                        (size_t) 1, &name, &l, &bufpt, 4 | 8);
 4006  return(ret);
 4007 }
 4008 
 4009 
 4010 static int Xorriso_set_hfsplus_crtp(struct XorrisO *xorriso, IsoNode *node,
 4011                                     char *path, char *creator, char *hfs_type,
 4012                                     int flag)
 4013 {
 4014  struct iso_hfsplus_xinfo_data *hfs_data= NULL;
 4015  char buf[10], *bufpt;
 4016  size_t l;
 4017  int ret;
 4018  static char *name= "isofs.hx";
 4019 
 4020  /* Register as non-persistent xinfo */
 4021  hfs_data= iso_hfsplus_xinfo_new(0);
 4022  if(hfs_data == NULL) {
 4023    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 4024    return(-1);
 4025  }
 4026  memcpy(hfs_data->creator_code, creator, 4);
 4027  memcpy(hfs_data->type_code, hfs_type, 4);
 4028  ret= iso_node_add_xinfo(node, iso_hfsplus_xinfo_func, (void *) hfs_data);
 4029  Xorriso_process_msg_queues(xorriso, 0);
 4030  if(ret < 0) {
 4031    Xorriso_report_iso_error(xorriso, path, ret,
 4032           "Cannot attach HFS+ creator and type to ISO node", 0, "FAILURE", 1);
 4033    goto failure;
 4034  } else if(ret == 0) {
 4035    strcat(xorriso->info_text,
 4036   "Program error: iso_node_add_xinfo refuses to attach HFS+ creator and type");
 4037    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4038    goto failure;
 4039  }
 4040 
 4041  /* Register as persistent attribute isofs.hx */
 4042  bufpt= buf;
 4043  l= 10;
 4044  buf[0]= 1;
 4045  buf[1]= 0;
 4046  memcpy(buf + 2, creator, 4);
 4047  memcpy(buf + 6, hfs_type, 4);
 4048  ret= Xorriso_setfattr(xorriso, node, path,
 4049                        (size_t) 1, &name, &l, &bufpt, 2 | 8);
 4050  if(ret <= 0)
 4051    goto failure;
 4052  Xorriso_set_change_pending(xorriso, 0);
 4053  return(1);
 4054 
 4055 failure:
 4056  if(hfs_data != NULL)
 4057    iso_hfsplus_xinfo_func(hfs_data, 1);
 4058  return(0);
 4059 }
 4060 
 4061 
 4062 /* @param flag bit0= only check creator and hfs_type for compliance.
 4063                bit1= with bit0: check for search rather than for setting
 4064                bit2= copy 2 times 4 bytes without any check
 4065 */
 4066 int Xorriso_hfsplus_file_creator_type(struct XorrisO *xorriso, char *path,
 4067                                       void *in_node, 
 4068                                       char *creator, char *hfs_type, int flag)
 4069 {
 4070  int ret;
 4071  IsoNode *node;
 4072 
 4073  if(in_node == NULL && !(flag & 1)) {
 4074    ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
 4075    if(ret <= 0)
 4076      return(ret);
 4077  } else
 4078    node= (IsoNode *) in_node;
 4079  if(flag & 4) {
 4080    ;
 4081  } else if((creator[0] == 0 && hfs_type[0] == 0) ||
 4082     strcmp(creator, "--delete") == 0) {
 4083    if(flag & 2) {
 4084      strcpy(xorriso->info_text,
 4085            "Attempt to use HFS+ file pseudo-creator '--delete' for searching");
 4086      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4087      strcpy(xorriso->info_text,
 4088              "Suitable are strings of length 4 or length 1");
 4089      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
 4090      return(0);
 4091    }
 4092    if(flag & 1)
 4093      return(1);
 4094    ret= Xorriso_remove_hfsplus_crtp(xorriso, node, path, 0);
 4095    if(ret < 0)
 4096      return(ret);
 4097    return(1);
 4098  } else if((strlen(creator) != 4 && !(strlen(creator) == 1 &&
 4099             (flag & 3) == 3)) ||
 4100            (strlen(hfs_type) != 4 && !(strlen(hfs_type) == 1 &&
 4101             (flag & 3) == 3))) {
 4102    if(flag & 2) {
 4103      strcpy(xorriso->info_text,
 4104       "HFS+ file creator code or type code for searching are not exactly 1 or 4 characters long");
 4105    } else {
 4106      strcpy(xorriso->info_text,
 4107       "HFS+ file creator code or type code are not exactly 4 characters long");
 4108    }
 4109    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4110    return(0);
 4111  }
 4112  if(flag & 1)
 4113    return(1);
 4114 
 4115  ret= Xorriso_remove_hfsplus_crtp(xorriso, node, path, 1);
 4116  if(ret <= 0)
 4117    return(ret);
 4118  ret= Xorriso_set_hfsplus_crtp(xorriso, node, path, creator, hfs_type, 0);
 4119  if(ret <= 0)
 4120    return(ret);
 4121  return(1);
 4122 }
 4123 
 4124 
 4125 /*
 4126   @param node
 4127        If node is NULL and path is empty, then the blessing will be
 4128        revoked from any node which bears it.
 4129   @param flag
 4130        Bitfield for control purposes.
 4131          bit0= Revoke blessing if node != NULL bears it.
 4132          bit1= Revoke any blessing of the node, regardless of parameter
 4133                blessing. If node is NULL, then revoke all blessings.
 4134          bit2= Only check parameter blessing.
 4135                Return blessing index + 1 instead of issuing the blessing.
 4136          bit3= With bit2:
 4137                Allow blessing "any" and map to index ISO_HFSPLUS_BLESS_MAX.
 4138                Elsewise, blessing "none" is mapped to ISO_HFSPLUS_BLESS_MAX.
 4139 */
 4140 int Xorriso_hfsplus_bless(struct XorrisO *xorriso, char *path,
 4141                           void *in_node, char *blessing, int flag)
 4142 {
 4143  int ret, bless_max;
 4144  IsoNode *node, **blessed_nodes;
 4145  IsoImage *volume= NULL;
 4146  enum IsoHfsplusBlessings bless_code = ISO_HFSPLUS_BLESS_MAX; /* = invalid */
 4147  char *hb = "";
 4148  size_t l= 0;
 4149  static char *name= "isofs.hb";
 4150 
 4151  if(strcmp(blessing, "ppc_bootdir") == 0 ||
 4152            strcmp(blessing, "p") == 0 || strcmp(blessing, "P") == 0) {
 4153    bless_code= ISO_HFSPLUS_BLESS_PPC_BOOTDIR;
 4154    hb= "p";
 4155  } else if(strcmp(blessing, "intel_bootfile") == 0 ||
 4156            strcmp(blessing, "i") == 0 || strcmp(blessing, "I") == 0) {
 4157    bless_code= ISO_HFSPLUS_BLESS_INTEL_BOOTFILE;
 4158    hb= "i";
 4159  } else if(strcmp(blessing, "show_folder") == 0 ||
 4160            strcmp(blessing, "s") == 0 || strcmp(blessing, "S") == 0) {
 4161    bless_code= ISO_HFSPLUS_BLESS_SHOWFOLDER;
 4162    hb= "s";
 4163  } else if(strcmp(blessing, "os9_folder") == 0 ||
 4164            strcmp(blessing, "9") == 0) {
 4165    bless_code= ISO_HFSPLUS_BLESS_OS9_FOLDER;
 4166    hb= "9";
 4167  } else if(strcmp(blessing, "osx_folder") == 0 ||
 4168          strcmp(blessing, "x") == 0 || strcmp(blessing, "X") == 0) {
 4169    bless_code= ISO_HFSPLUS_BLESS_OSX_FOLDER;
 4170    hb= "x";
 4171  } else if((!(flag & 8)) && (strcmp(blessing, "none") == 0 ||
 4172           strcmp(blessing, "n") == 0 || strcmp(blessing, "N") == 0)) {
 4173    bless_code= ISO_HFSPLUS_BLESS_MAX;
 4174    flag |= 2;
 4175  } else if((flag & 8) && (flag & 4) &&
 4176          (strcmp(blessing, "any") == 0 ||
 4177           strcmp(blessing, "a") == 0 || strcmp(blessing, "A") == 0)) {
 4178    bless_code= ISO_HFSPLUS_BLESS_MAX;
 4179  } else {
 4180    sprintf(xorriso->info_text, "Unknown blessing type ");
 4181    Text_shellsafe(blessing, xorriso->info_text, 1);
 4182    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4183    return(0);
 4184  }
 4185  if(flag & 4)
 4186    return(1 + bless_code);
 4187 
 4188  if(in_node == NULL && path[0]) {
 4189    ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
 4190    if(ret <= 0)
 4191      return(ret);
 4192  } else
 4193    node= (IsoNode *) in_node;
 4194  ret= Xorriso_get_volume(xorriso, &volume, 0);
 4195  if(ret <= 0)
 4196    return(ret);
 4197 
 4198  if(!(flag & 2)) {
 4199    /* Remove persistent bless mark from current bearer */
 4200    ret= iso_image_hfsplus_get_blessed(volume, &blessed_nodes, &bless_max, 0);
 4201    Xorriso_process_msg_queues(xorriso, 0);
 4202    if(ret < 0) {
 4203      Xorriso_report_iso_error(xorriso, "", ret,
 4204                               "Error when trying to bless a file",
 4205                               0, "FAILURE", 1);
 4206      return(0);
 4207    }
 4208    if((int) bless_code < bless_max) {
 4209      if(blessed_nodes[(int) bless_code] != NULL) {
 4210        ret= Xorriso_setfattr(xorriso, blessed_nodes[(int) bless_code], "",
 4211                              (size_t) 1, &name, &l, &hb, 4 | 8);
 4212        if(ret <= 0)
 4213          return(ret);
 4214      }
 4215    }
 4216  }
 4217 
 4218  /* Bless node */
 4219  ret= iso_image_hfsplus_bless(volume, bless_code, node, flag & 3);
 4220  Xorriso_process_msg_queues(xorriso, 0);
 4221  if(ret == 0 && path[0]) {
 4222    if((flag & 3)) {
 4223      sprintf(xorriso->info_text,
 4224              "Attempt to revoke blessing of unblessed file");
 4225    } else {
 4226      sprintf(xorriso->info_text,
 4227              "Multiple blessing to same file or inappropriate file type");
 4228    }
 4229    if(path[0]) {
 4230      strcat(xorriso->info_text, ": ");
 4231      Text_shellsafe(path, xorriso->info_text, 1);
 4232    }
 4233    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4234    return(0);
 4235  } else if (ret < 0) {
 4236    Xorriso_report_iso_error(xorriso, "", ret,
 4237                             "Error when trying to bless a file",
 4238                             0, "FAILURE", 1);
 4239    return(0);
 4240  }
 4241 
 4242  /* Attach persistent AAIP bless mark to node */
 4243  if(!(flag & 3)) {
 4244    l= 1;
 4245    ret= Xorriso_setfattr(xorriso, node, path, (size_t) 1, &name, &l, &hb,
 4246                          2 | 8);
 4247    if(ret <= 0)
 4248      return(ret);
 4249  }
 4250 
 4251  Xorriso_set_change_pending(xorriso, 0);
 4252  return(1);
 4253 }
 4254 
 4255 
 4256 int Xorriso_get_blessing(struct XorrisO *xorriso, IsoNode *node,
 4257                          int *bless_idx, char bless_code[17], int flag)
 4258 {
 4259  IsoNode **blessed_nodes;
 4260  int bless_max, ret, i;
 4261 
 4262  if(xorriso->in_volset_handle == NULL)
 4263    return(0);
 4264 
 4265  ret= iso_image_hfsplus_get_blessed((IsoImage *) xorriso->in_volset_handle,
 4266                                      &blessed_nodes, &bless_max, 0);
 4267  Xorriso_process_msg_queues(xorriso, 0);
 4268  if(ret < 0) {
 4269    Xorriso_report_iso_error(xorriso, "", ret,
 4270                             "Error when trying to inquire HFS+ file blessings",
 4271                             0, "FAILURE", 1);
 4272    return(-1);
 4273  }
 4274  for(i= 0; i < bless_max; i++) {
 4275    if(blessed_nodes[i] == node) {
 4276      switch (i) {
 4277      case ISO_HFSPLUS_BLESS_PPC_BOOTDIR:
 4278        strcpy(bless_code, "ppc_bootdir");
 4279      break; case ISO_HFSPLUS_BLESS_INTEL_BOOTFILE:
 4280        strcpy(bless_code, "intel_bootfile");
 4281      break; case ISO_HFSPLUS_BLESS_SHOWFOLDER:
 4282        strcpy(bless_code, "show_folder");
 4283      break; case ISO_HFSPLUS_BLESS_OS9_FOLDER:
 4284        strcpy(bless_code, "os9_folder");
 4285      break; case ISO_HFSPLUS_BLESS_OSX_FOLDER:
 4286        strcpy(bless_code, "osx_folder");
 4287      break; default:
 4288        strcpy(bless_code, "unknown_blessing");
 4289      }
 4290      *bless_idx= i;
 4291      return(1);
 4292    }
 4293  }
 4294  return(0);
 4295 }
 4296 
 4297 
 4298 /* @param flag bit0= use file addresses as search patterns
 4299 */
 4300 int Xorriso_apply_sort_file(struct XorrisO *xorriso, char *path, int flag)
 4301 {
 4302  int ret, linecount= 0, filec= 0, zero, i;
 4303  FILE *fp= NULL;
 4304  char *sret, *line= NULL, *spt, *tpt, *patterns[1], **filev= NULL;
 4305  char *sort_weight_args[4];
 4306  off_t mem= 0;
 4307  IsoImage *volume;
 4308    
 4309  Xorriso_alloc_meM(line, char, SfileadrL);
 4310  
 4311  ret= Xorriso_get_volume(xorriso, &volume, 0);
 4312  if(ret<=0)
 4313    goto ex;
 4314 
 4315  ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 2);
 4316  if(ret <= 0)
 4317    {ret= 0; goto ex;}
 4318  while(1) {
 4319    sret= Sfile_fgets_n(line, SfileadrL - 1, fp, 0);
 4320    if(sret == NULL) {
 4321      if(ferror(fp))
 4322        {ret= 0; goto ex;}
 4323  break;
 4324    }
 4325    linecount++;
 4326 
 4327    /* Find first space or tab */
 4328    spt= strchr(line, ' ');
 4329    tpt= strchr(line, '\t');
 4330    if(spt == NULL || (tpt != NULL && tpt < spt))
 4331      spt= tpt;
 4332    if(spt == NULL) {
 4333      sprintf(xorriso->info_text,
 4334              "No space or tab character found in line %d of sort weight file ",
 4335              linecount);
 4336      Text_shellsafe(path, xorriso->info_text, 1);
 4337      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 4338      ret= 0; goto ex;
 4339    }
 4340    *spt= 0;
 4341    
 4342    patterns[0]= spt + 1;
 4343    if(flag & 1) {
 4344      /* Obtain list of matching files */
 4345      ret= Xorriso_expand_pattern(xorriso, 1, patterns, 0,
 4346                                  &filec, &filev, &mem, 4);
 4347      if(ret <= 0)
 4348        {ret= 0; goto ex;}
 4349    } else {
 4350      filec= 1;
 4351    }
 4352 
 4353    /* Apply weight to file or directory tree */
 4354    for(i= 0; i < filec; i++) {
 4355      zero= 0;
 4356      if(flag & 1) {
 4357        sort_weight_args[0]= filev[i];
 4358      } else {
 4359        sort_weight_args[0]= patterns[0];
 4360      }
 4361      sort_weight_args[1]= "-exec";
 4362      sort_weight_args[2]= "sort_weight";
 4363      sort_weight_args[3]= line;
 4364      ret= Xorriso_option_find(xorriso, 4, sort_weight_args, &zero, 2);
 4365      if(ret <= 0)
 4366        {ret= 0; goto ex;}
 4367    }
 4368    if(flag & 1)
 4369      Sfile_destroy_argv(&filec, &filev, 0);
 4370  }
 4371  ret= 1;
 4372 ex:
 4373  if(fp != NULL)
 4374    fclose(fp);
 4375  Xorriso_free_meM(line);
 4376  Sfile_destroy_argv(&filec, &filev, 0);
 4377  return(ret);
 4378 }
 4379 
 4380 
 4381 /* @param flag bit0= tolerate truncated files of old length
 4382                      and mangle collisions
 4383 */
 4384 int Xorriso_set_file_name_limit(struct XorrisO *xorriso, int value, int flag)
 4385 {
 4386  int ret;
 4387  IsoImage *volume= NULL;
 4388  struct FindjoB *job= NULL;
 4389  struct stat dir_stbuf;
 4390    
 4391  ret= Xorriso_get_volume(xorriso, &volume, 1);
 4392  if(ret < 0)
 4393    goto ex;
 4394  if (ret == 1 && volume != NULL) {
 4395    /* Check whether there are non-refreshable truncated names */
 4396    ret= Findjob_new(&job, "/", 0);
 4397    if(ret<=0) {
 4398      Xorriso_no_findjob(xorriso, "xorriso", 0);
 4399      {ret= -1; goto ex;}
 4400    }
 4401    Findjob_set_action_type(job, 55 + 2 * (flag & 1), value, 0);
 4402    xorriso->find_unique_trunc_result= 2;
 4403    ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
 4404                       &dir_stbuf, 0, 0);
 4405    if(ret < 0)
 4406      goto ex;
 4407    xorriso->request_to_abort= 0;
 4408    if(xorriso->find_unique_trunc_result == 0 && !(flag & 1)) {
 4409      Xorriso_msgs_submit(xorriso, 0,
 4410          "-file_name_limit may not be changed because truncated files exist or collisions would occur",
 4411          0, "SORRY", 0);
 4412      ret= 0; goto ex;
 4413    }
 4414 
 4415    xorriso->file_name_limit= value;
 4416    iso_image_set_truncate_mode(volume, 1, value);
 4417 
 4418    /* truncations are necessary */;
 4419    if(xorriso->find_unique_trunc_result == 1) {
 4420      Findjob_set_action_type(job, 54 + 2 * (flag & 1),
 4421                              xorriso->file_name_limit, 0);
 4422      xorriso->find_unique_trunc_result= 2;
 4423      ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
 4424                         &dir_stbuf, 0, 0);
 4425      if(ret < 0)
 4426        goto ex;
 4427      if(xorriso->find_unique_trunc_result == 0) {
 4428 
 4429          /* >>> Did not work . What to do ? */;
 4430 
 4431      }
 4432    }
 4433  }
 4434  xorriso->file_name_limit= value;
 4435  ret= 1;
 4436 ex:;
 4437  Findjob_destroy(&job, 0);
 4438  return(ret);
 4439 }
 4440 
 4441 
 4442 /* @param flag bit0= test for uniqueness, do not change name
 4443                bit1= tolerate existing truncated names and mangle collisions
 4444                bit2= be silent about non-uniquely truncatables
 4445                      do not set xorriso->request_to_abort
 4446 */
 4447 int Xorriso_truncate_uniquely(struct XorrisO *xorriso, int length,
 4448                               IsoNode *node, char *abs_path, char *show_path,
 4449                               int flag)
 4450 {
 4451  int ret, l, i;
 4452  unsigned int mangleno;
 4453  char *