"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/xorriso/iso_tree.c" (30 Jan 2021, 77300 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_tree.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 access nodes of the
    9    libisofs tree model.
   10 */
   11 
   12 #ifdef HAVE_CONFIG_H
   13 #include "../config.h"
   14 #endif
   15 
   16 #include <ctype.h>
   17 #include <sys/types.h>
   18 #include <unistd.h>
   19 #include <stdlib.h>
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <sys/stat.h>
   23 #include <sys/time.h>
   24 #include <time.h>
   25 #include <errno.h>
   26 
   27 #include <pwd.h>
   28 #include <grp.h>
   29 
   30 
   31 #include "xorriso.h"
   32 #include "xorriso_private.h"
   33 #include "xorrisoburn.h"
   34 
   35 #include "lib_mgt.h"
   36 #include "iso_img.h"
   37 #include "iso_tree.h"
   38 #include "iso_manip.h"
   39 #include "sort_cmp.h"
   40 
   41 
   42 /* @param eff_path  returns resulting effective path.
   43                     Must provide at least SfileadrL bytes of storage.
   44    @param flag bit0= do not produce problem events (unless faulty path format)
   45                bit1= do not use libisofs (work literally or in disk world)
   46                bit2= (implies bit1) this is an address in the disk world
   47                bit3= return root directory as "/" and not as ""
   48                bit4= (with bit2) determine type of disk file eff_path
   49                      and return 0 if not existing
   50                bit5= (with bit3) this is not a parameter
   51                bit6= insist in having an ISO image, even with bits1+2
   52    @return -1 = faulty path format, 0 = not found ,
   53             1 = found simple node , 2 = found directory
   54 */
   55 int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd,
   56                                char *img_path, char eff_path[], int flag)
   57 {
   58  int ret, is_dir= 0, done= 0;
   59  IsoImage *volume;
   60  IsoDir *dir= NULL;
   61  IsoNode *node= NULL;
   62  char *path= NULL, *apt, *npt, *cpt, *link_target= NULL;
   63 
   64  Xorriso_alloc_meM(path, char, SfileadrL);
   65  Xorriso_alloc_meM(link_target, char, SfileadrL);
   66 
   67  if(flag & 4)
   68    flag|= 2;
   69  if((flag&64) || !(flag&2)) {
   70    ret= Xorriso_get_volume(xorriso, &volume, 0);
   71    if(ret<=0)
   72      goto ex;
   73  }
   74 
   75  eff_path[0]= 0;
   76  if(img_path[0]==0) {
   77    if(flag&8)
   78      strcpy(eff_path, "/");
   79    {ret= 2; goto ex;} /* root directory */
   80  }
   81 
   82  apt= npt= path;
   83  if(img_path[0]!='/') {
   84    strcpy(path, wd);
   85    ret= Sfile_add_to_path(path, img_path, 0);
   86    if(ret<=0)
   87      goto much_too_long;
   88  } else
   89    if(Sfile_str(path, img_path, 0)<=0)
   90      {ret= -1; goto ex;}
   91 
   92  if(path[0]!='/') {
   93    sprintf(xorriso->info_text,
   94         "Internal error: Unresolvable relative addressing in iso_rr_path '%s'",
   95         img_path);
   96    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FATAL", 0);
   97    {ret= -1; goto ex;}
   98  } else if(path[1]==0) {
   99    if(flag&8)
  100      strcpy(eff_path, "/");
  101    {ret= 2; goto ex;} /* root directory */
  102  }
  103 
  104  if(apt[0] == '.')
  105    if(apt[1] == 0 || apt[1] == '/')
  106      is_dir= 1;
  107  for(npt= apt; !done; apt= npt+1) {
  108    npt= strchr(apt, '/');
  109    if(npt==NULL) {
  110      npt= apt+strlen(apt);
  111      done= 1;
  112    } else
  113      *npt= 0;
  114    if(*apt==0) {
  115      *apt= '/';
  116      apt++;
  117      if(done)
  118  break;
  119  continue;
  120    }
  121    if(strcmp(apt,".")==0)
  122  continue;
  123    if(strcmp(apt,"..")==0) {
  124      if(!(flag&2)) {
  125        node= (IsoNode *) dir;
  126        if(node==NULL) {
  127 bonked_root:;
  128          sprintf(xorriso->info_text,
  129                  "Relative addressing in path exceeds root directory: ");
  130          Text_shellsafe(img_path, xorriso->info_text, 1);
  131          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  132          {ret= -1; goto ex;}
  133        }
  134        dir= iso_node_get_parent(node);
  135 
  136        /* >>> Get absolute path of node as eff_path, to avoid link problems */; 
  137 
  138      }
  139      if(flag & 4) {
  140        /* Linux-ish local filesystem semantics:
  141           If the parent is a symbolic link, do not ascend to its parent,
  142           but to the parent of the link target.
  143           >>> ??? Are there systems which do it differently ?
  144        */
  145        if(Sfile_type(eff_path, 0) == 3) {
  146          ret= Xorriso_resolve_link(xorriso, eff_path, link_target, 2);
  147          if(ret <= 0)
  148            {ret= -1; goto ex;}
  149          strcpy(eff_path, link_target);
  150        }
  151      }
  152 
  153      /* truncate eff_path */;
  154      cpt= strrchr(eff_path, '/');
  155      if(cpt==NULL) /* ??? if not flag&2 then this is a bug */
  156        goto bonked_root;
  157      *cpt= 0;
  158      is_dir= 1;
  159  continue;
  160    }
  161    is_dir= 0;
  162    ret= Sfile_add_to_path(eff_path, apt, 0);
  163    if(ret<=0) {
  164 much_too_long:;
  165      sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
  166              (int) (strlen(eff_path)+strlen(apt)+1));
  167      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  168      {ret= -1; goto ex;}
  169    }
  170    if(!(flag&2)) {
  171      dir= (IsoDir *) node;
  172      ret= Xorriso_node_from_path(xorriso, volume, eff_path, &node, flag&1);
  173      if(ret<=0) 
  174        {ret= 0; goto ex;}
  175      if(dir==NULL) /* could be false with  "/dir/.." */
  176        dir= iso_node_get_parent(node);
  177      is_dir= LIBISO_ISDIR(node);
  178    }
  179  }
  180  if(flag&16) {
  181    ret= Sfile_type(eff_path,
  182     1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32)))
  183                   ));
  184    if(ret<0)
  185      {ret= 0; goto ex;}
  186    if(ret==2)
  187      is_dir= 1;
  188    else
  189      is_dir= 0;
  190  }
  191  ret= 1+!!is_dir;
  192 ex:;
  193  Xorriso_free_meM(path);
  194  Xorriso_free_meM(link_target);
  195  return(ret);
  196 }
  197 
  198 
  199 int Xorriso_get_node_by_path(struct XorrisO *xorriso,
  200                              char *in_path, char *eff_path,
  201                              IsoNode **node, int flag)
  202 {
  203  int ret;
  204  char *path= NULL;
  205  IsoImage *volume;
  206 
  207  Xorriso_alloc_meM(path, char, SfileadrL);
  208 
  209  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, in_path, path, 0);
  210  if(ret<=0)
  211    goto ex;
  212  if(eff_path!=NULL)
  213    strcpy(eff_path, path);
  214  ret= Xorriso_get_volume(xorriso, &volume, 0);
  215  if(ret<=0)
  216    goto ex;
  217  ret= Xorriso_node_from_path(xorriso, volume, path, node, 0);
  218  if(ret<=0)
  219    {ret= 0; goto ex;}
  220  ret= 1;
  221 ex:;
  222  Xorriso_free_meM(path);
  223  return(ret);
  224 }
  225 
  226 
  227 /* @param flag
  228 */
  229 int Xorriso_node_get_dev(struct XorrisO *xorriso, IsoNode *node,
  230                          char *path, dev_t *dev, int flag)
  231 {
  232  *dev= iso_special_get_dev((IsoSpecial *) node);
  233  return(1);
  234 }
  235 
  236 
  237 /* @param flag bit0= *node is already valid
  238                bit1= add extra block for size estimation
  239                bit2= complain loudely if path is missing in image
  240                bit3= stbuf is to be used without eventual ACL
  241                bit4= try to obtain a better st_nlink count if hardlinks
  242                      are enabled
  243                bit5= do not look for truncated versions of path component
  244 */
  245 int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf,
  246                        IsoNode **node, int flag)
  247 {
  248  int ret, min_hl, max_hl, node_idx, i;
  249  IsoImage *volume;
  250  IsoBoot *bootcat;
  251  uint32_t lba;
  252  char *catcontent = NULL;
  253  off_t catsize;
  254  dev_t dev_number;
  255 
  256  memset((char *) stbuf, 0, sizeof(struct stat));
  257  if(!(flag&1)) {
  258    ret= Xorriso_get_volume(xorriso, &volume, 0);
  259    if(ret<=0)
  260      return(-1);
  261    ret= Xorriso_node_from_path(xorriso, volume, path, node,
  262                                ((flag >> 4) & 2) | !(flag&4));
  263    if(ret<=0)
  264      *node= NULL;
  265  }
  266  if(*node==NULL)
  267    return(0);
  268 
  269  /* >>> stbuf->st_dev */
  270  /* >>> stbuf->st_ino */
  271 
  272  if(flag & 8)
  273    stbuf->st_mode= iso_node_get_perms_wo_acl(*node) & 07777;
  274  else
  275    stbuf->st_mode= iso_node_get_permissions(*node) & 07777;
  276  if(LIBISO_ISDIR(*node))
  277    stbuf->st_mode|= S_IFDIR;
  278  else if(LIBISO_ISREG(*node))
  279    stbuf->st_mode|= S_IFREG;
  280  else if(LIBISO_ISLNK(*node))
  281    stbuf->st_mode|= S_IFLNK;
  282  else if(LIBISO_ISCHR(*node)) {
  283    stbuf->st_mode|= S_IFCHR;
  284    Xorriso_node_get_dev(xorriso, *node, path, &dev_number, 0);
  285    stbuf->st_rdev= dev_number;
  286  } else if(LIBISO_ISBLK(*node)) {
  287    stbuf->st_mode|= S_IFBLK;
  288    /* ts B11124:
  289       Debian mips and mipsel have sizeof(stbuf.st_rdev) == 4
  290       whereas sizeof(dev_t) is 8.
  291       This workaround assumes that the returned numbers fit into 4 bytes.
  292       The may stem from the local filesystem or from the ISO image.
  293       At least there will be no memory corruption but only an integer rollover.
  294    */ 
  295    Xorriso_node_get_dev(xorriso, *node, path, &dev_number, 0);
  296    stbuf->st_rdev= dev_number;
  297  } else if(LIBISO_ISFIFO(*node))
  298    stbuf->st_mode|= S_IFIFO;
  299  else if(LIBISO_ISSOCK(*node))
  300    stbuf->st_mode|= S_IFSOCK;
  301  else if(LIBISO_ISBOOT(*node))
  302    stbuf->st_mode|= Xorriso_IFBOOT;
  303 
  304  /* >>> With directories this should be : number of subdirs + 2 */
  305  /* >>> ??? How to obtain RR hardlink number for other types ? */
  306  /* This may get overridden farther down */
  307  stbuf->st_nlink= 1;
  308 
  309  stbuf->st_uid= iso_node_get_uid(*node);
  310  stbuf->st_gid= iso_node_get_gid(*node);
  311 
  312  if(LIBISO_ISREG(*node))
  313    stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2));
  314  else if(LIBISO_ISBOOT(*node)) {
  315    ret= Xorriso_get_volume(xorriso, &volume, 0);
  316    if(ret <= 0)
  317      return(-1);
  318    ret= iso_image_get_bootcat(volume, &bootcat, &lba, &catcontent, &catsize);
  319    if(catcontent != NULL)
  320      free(catcontent);
  321    if(ret < 0) {
  322      Xorriso_process_msg_queues(xorriso,0);
  323      return(-1);
  324    }
  325    stbuf->st_size= catsize;
  326  } else
  327    stbuf->st_size= 0;
  328 
  329  stbuf->st_blksize= 2048;
  330  stbuf->st_blocks= stbuf->st_size / (off_t) 2048;
  331  if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size)
  332    stbuf->st_blocks++; 
  333 
  334  stbuf->st_atime= iso_node_get_atime(*node);
  335  stbuf->st_mtime= iso_node_get_mtime(*node);
  336  stbuf->st_ctime= iso_node_get_ctime(*node);
  337 
  338  if(LIBISO_ISDIR(*node) || (xorriso->ino_behavior & 1) || (!(flag & 16)) ||
  339     xorriso->hln_array == NULL)
  340    return(1);
  341 
  342  /* Try to obtain a better link count */
  343  ret= Xorriso_search_hardlinks(xorriso, *node, &node_idx, &min_hl, &max_hl, 0);
  344  if(ret < 0)
  345    return(ret);
  346  if(ret > 0 && node_idx >= 0) {
  347    for(i= min_hl; i <= max_hl; i++) {
  348      if(i == node_idx)
  349    continue;
  350      /* Check whether node is still valid */
  351      if(iso_node_get_parent(xorriso->hln_array[i]) != NULL)
  352        stbuf->st_nlink++;
  353    }
  354  }
  355  return(1);
  356 }
  357 
  358 
  359 /* @param flag >>>  bit0= follow links (i.e. stat() rather than lstat()
  360                bit1= do not return -2 on severe errors
  361                bit2= complain loudely if path is missing in image
  362 */
  363 int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf,
  364                       int flag)
  365 {
  366  int ret;
  367  IsoNode *node;
  368 
  369  if(flag&1) {
  370 
  371    /* >>> follow link in ISO image */;
  372 
  373  }
  374 
  375  ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, flag&4);
  376  if(ret>0)
  377    return(0);
  378  if(ret<0 && !(flag&2))
  379    return(-2);
  380  return(-1);
  381 }
  382 
  383 
  384 int Xorriso_node_is_valid(struct XorrisO *xorriso, IsoNode *in_node, int flag)
  385 {
  386  IsoNode *node, *parent;
  387 
  388  for(node= in_node; 1; node= parent) {
  389    parent= (IsoNode *) iso_node_get_parent(node);
  390    if(parent == node)
  391  break;
  392    if(parent == NULL)
  393      return(0); /* Node is not in the tree (any more) */
  394  }
  395  return(1);
  396 }
  397 
  398 
  399 int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *in_node,
  400                            char path[SfileadrL], int flag)
  401 {
  402  int ret, i, comp_count= 0;
  403  IsoNode *node, *parent, **components= NULL;
  404  char *wpt, *npt;
  405 
  406  for(node= in_node; 1; node= parent) {
  407    parent= (IsoNode *) iso_node_get_parent(node);
  408    if(parent == node)
  409  break;
  410    if(parent == NULL)
  411      return(0); /* Node is not in the tree (any more) */
  412    comp_count++;
  413  }
  414  if(comp_count == 0) {
  415    strcpy(path, "/");
  416    return(1);
  417  }
  418  components= calloc(comp_count, sizeof(IsoNode *));
  419  if(components == NULL) {
  420    Xorriso_no_malloc_memory(xorriso, NULL, 0);
  421    ret= -1; goto ex;
  422  }
  423  i= comp_count;
  424  for(node= in_node; 1; node= parent) {
  425    parent= (IsoNode *) iso_node_get_parent(node);
  426    if(parent == node)
  427  break;
  428    components[--i]= node;
  429  }
  430 
  431  wpt= path;
  432  for(i= 0; i < comp_count; i++) {
  433    npt= (char *) iso_node_get_name(components[i]);
  434    if((wpt - path) + strlen(npt) + 1 >= SfileadrL) {
  435 
  436      /* >>> path is getting much too long */;
  437 
  438      ret= -1; goto ex;
  439    }
  440    *(wpt++)= '/';
  441    strcpy(wpt, npt);
  442    wpt+= strlen(npt);
  443    *wpt= 0;
  444  }
  445  ret= 1;
  446 ex:;
  447  if(components != NULL)
  448    free(components);
  449  return(ret);
  450 }
  451 
  452 
  453 /* <<< The lookup from node pointer will be done by Xorriso_path_from_node()
  454        (Currently it runs a full tree traversal)
  455        Parameter node and flag bit0 will vanish then
  456 */
  457 /* @param flag bit0= use lba rather than node pointer
  458 */
  459 int Xorriso_path_from_lba(struct XorrisO *xorriso, IsoNode *node, int lba,
  460                           char path[SfileadrL], int flag)
  461 {
  462  int ret;
  463  struct FindjoB *job= NULL;
  464  struct stat dir_stbuf;
  465  char *found_path;
  466 
  467  path[0]= 0;
  468  if((flag & 1) && lba <= 0)
  469    return(0);
  470 
  471  ret= Findjob_new(&job, "/", 0);
  472  if(ret <= 0) {
  473    Xorriso_no_findjob(xorriso, "path_from_node", 0);
  474    return(ret);
  475  }
  476  if(flag & 1)
  477    Findjob_set_lba_range(job, lba, 1, 0);
  478  else
  479    Findjob_set_wanted_node(job, (void *) node, 0);
  480  Findjob_set_action_found_path(job, 0);
  481  ret= Xorriso_findi(xorriso, job, NULL,  (off_t) 0,
  482                     NULL, "/", &dir_stbuf, 0, 0);
  483  if(ret > 0) {
  484    ret= 1;
  485    Findjob_get_found_path(job, &found_path, 0);
  486    if(found_path == NULL)
  487      ret= 0;
  488    else if(Sfile_str(path, found_path, 0) <= 0)
  489      ret= -1;
  490  }
  491  Findjob_destroy(&job, 0);
  492  return(ret);
  493 }
  494 
  495 
  496 /* @param flag bit0= in_node is valid, do not resolve iso_adr
  497                bit2= recognize and parse split parts despite
  498                      xorriso->split_size <= 0
  499 */
  500 int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr,
  501                            void *in_node,
  502                            struct SplitparT **parts, int *count,
  503                            struct stat *total_stbuf,  int flag)
  504 {
  505  int ret, i, incomplete= 0, overlapping= 0;
  506  int partno, total_parts, first_total_parts= -1;
  507  off_t offset, bytes, total_bytes, first_total_bytes= -1, first_bytes= -1;
  508  off_t size, covered;
  509 
  510  IsoImage *volume;
  511  IsoDir *dir_node;
  512  IsoDirIter *iter= NULL;
  513  IsoNode *node;
  514  char *name;
  515  struct stat stbuf, first_stbuf;
  516 
  517  *count= 0;
  518  *parts= NULL;
  519 
  520  if(xorriso->split_size <= 0 && !(flag & 4))
  521    return(0);
  522 
  523  if(flag&1) {
  524    node= (IsoNode *) in_node;
  525  } else {
  526    ret= Xorriso_get_volume(xorriso, &volume, 0);
  527    if(ret<=0)
  528      return(-1);
  529    ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1);
  530    if(ret<=0)
  531      return(-1);
  532  }
  533  if(!LIBISO_ISDIR(node))
  534    return(0);
  535  dir_node= (IsoDir *) node;
  536 
  537  ret= iso_dir_get_children(dir_node, &iter);
  538  if(ret<0) {
  539 cannot_iter:;
  540    Xorriso_cannot_create_iter(xorriso, ret, 0);
  541    return(-1);
  542  }
  543 
  544  for(i= 0; iso_dir_iter_next(iter, &node) == 1; i++) {
  545    name= (char *) iso_node_get_name(node);
  546    ret= Splitpart__parse(name, &partno, &total_parts,
  547                          &offset, &bytes, &total_bytes, 0);
  548    if(ret<=0)
  549      {ret= 0; goto ex;}
  550    if(i==0) {
  551      first_total_parts= total_parts;
  552      first_bytes= bytes;
  553      first_total_bytes= total_bytes;
  554      Xorriso_fake_stbuf(xorriso, "", &first_stbuf, &node, 1);
  555      size= first_stbuf.st_size;
  556    } else {
  557      if(first_total_parts!=total_parts || first_total_bytes!=total_bytes ||
  558         (first_bytes!=bytes && partno!=total_parts))
  559        {ret= 0; goto ex;}
  560      Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
  561      if(first_stbuf.st_mode != stbuf.st_mode ||
  562         first_stbuf.st_uid != stbuf.st_uid ||
  563         first_stbuf.st_gid != stbuf.st_gid ||
  564         first_stbuf.st_mtime != stbuf.st_mtime ||
  565         first_stbuf.st_ctime != stbuf.st_ctime)
  566        {ret= 0; goto ex;} 
  567      size= stbuf.st_size;
  568    }
  569    /* check for plausible size */
  570    if(!((partno != total_parts && size == bytes) ||
  571         (partno == total_parts && size <= bytes)))
  572      {ret= 0; goto ex;} 
  573    if(offset != first_bytes * (off_t) (partno - 1))
  574      {ret= 0; goto ex;}
  575    (*count)++;
  576  }
  577  if(*count <= 0 || *count != first_total_parts)
  578    {ret= 0; goto ex;}
  579 
  580  ret= Splitparts_new(parts, (*count)+1, 0); /* (have one end marker item) */
  581  if(ret<=0)
  582    return(ret);
  583 
  584  iso_dir_iter_free(iter);
  585  ret= iso_dir_get_children(dir_node, &iter);
  586  if(ret<0)
  587    goto cannot_iter;
  588  for(i= 0; i<*count; i++) {
  589    ret= iso_dir_iter_next(iter, &node);
  590    if(ret!=1)
  591  break;
  592    name= (char *) iso_node_get_name(node);
  593    ret= Splitpart__parse(name, &partno, &total_parts,
  594                          &offset, &bytes, &total_bytes, 0);
  595    if(ret<=0)
  596      {ret= 0; goto ex;}
  597    ret= Splitparts_set(*parts, i, name, partno, total_parts, offset, bytes,
  598                        total_bytes, 0);
  599    if(ret<=0)
  600      goto ex;
  601  }
  602 
  603  Splitparts_sort(*parts, *count, 0);
  604 
  605  covered= 0;
  606  for(i= 0; i<*count; i++) {
  607    Splitparts_get(*parts, i, &name, &partno, &total_parts, &offset, &bytes,
  608                   &total_bytes, 0);
  609    if(offset>covered)
  610      incomplete= 1;
  611    else if(offset<covered)
  612      overlapping= 1;
  613    if(offset+bytes > covered)
  614      covered= offset+bytes;
  615  }
  616  if(total_bytes>covered)
  617    incomplete= 1;
  618  memcpy(total_stbuf, &first_stbuf, sizeof(struct stat));
  619  total_stbuf->st_size= total_bytes;
  620  ret= !(overlapping || incomplete);
  621 ex:;
  622  if(iter!=NULL)
  623    iso_dir_iter_free(iter);
  624  return(ret);
  625 }
  626 
  627 
  628 /* @param flag bit0= node is valid, do not resolve path
  629                bit1= insist in complete collection of part files
  630                bit2= recognize and parse split parts despite
  631                      xorriso->split_size <= 0
  632 */
  633 int Xorriso_is_split(struct XorrisO *xorriso, char *path, void *node,
  634                      int flag)
  635 {
  636  struct SplitparT *split_parts= NULL;
  637  int split_count= 0, ret;
  638  struct stat stbuf;
  639 
  640  ret= Xorriso_identify_split(xorriso, path, node, &split_parts,
  641                              &split_count, &stbuf, flag & 7);
  642  if(split_parts!=NULL)
  643    Splitparts_destroy(&split_parts, split_count, 0);
  644  return(ret>0);
  645 }
  646 
  647 
  648 /* @param node      Opaque handle to IsoNode which is to be inquired instead of                     path if it is not NULL.
  649    @param path      is used as address if node is NULL.
  650    @param acl_text  if acl_text is not NULL, then *acl_text will be set to the
  651                     ACL text (without comments) of the file object. In this
  652                     case it finally has to be freed by the caller.
  653    @param flag      bit0= do not report to result but only retrieve ACL text
  654                     bit1= check for existence of true ACL (not fabricated),
  655                           do not allocate and set acl_text but return 1 or 2
  656                     bit2-3: what ALC to retrieve:
  657                           0= "access" and "default", mark "default:"
  658                           1= "access" only
  659                           2= "default" only, do not mark "default:"
  660                     bit4= get "access" ACL only if not trivial
  661    @return          2 ok, no ACL available, eventual *acl_text will be NULL
  662                     1 ok, ACL available, eventual *acl_text stems from malloc()
  663                   <=0 error
  664 */
  665 int Xorriso_getfacl(struct XorrisO *xorriso, void *in_node, char *path,
  666                     char **acl_text, int flag)
  667 {
  668  int ret, d_ret, result_len= 0, pass, what;
  669  IsoNode *node;
  670  char *text= NULL, *d_text= NULL, *cpt, *npt;
  671  uid_t uid;
  672  gid_t gid;
  673  struct passwd *pwd;
  674  struct group *grp;
  675 
  676  what= (flag >> 2) & 3;
  677  if(acl_text != NULL)
  678    *acl_text= NULL;
  679 
  680  node= (IsoNode *) in_node;
  681  if(node == NULL) {
  682    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
  683    if(ret<=0)
  684      goto ex;
  685  }
  686  ret= iso_node_get_acl_text(node, &text, &d_text, flag & 16);
  687  d_ret= (d_text != NULL);
  688  if(ret < 0 || d_ret < 0) {
  689    if(path != NULL && path[0] != 0) {
  690      strcpy(xorriso->info_text, "Error with obtaining ACL of ");
  691      Text_shellsafe(path, xorriso->info_text, 1);
  692      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  693    }
  694    ret= 0; goto ex;
  695  }
  696  if(flag & 2) {
  697    ret= 1 + (ret != 1 && d_ret == 0);
  698    goto ex;
  699  }
  700  if((ret == 0 || ret == 2) && d_ret == 0) {
  701    if(flag & 1) {
  702      ret= 1 + (ret == 0);
  703      goto ex;
  704    }
  705    strcpy(xorriso->info_text, "No ACL associated with ");
  706    Text_shellsafe(path, xorriso->info_text, 1);
  707    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  708    if(ret == 0)
  709      {ret= 2; goto ex;}
  710  }
  711 
  712  if(!(flag & 1)) {
  713    ret= Xorriso_getfname(xorriso, path, 0);
  714    if(ret <= 0)
  715      goto ex;
  716    uid= iso_node_get_uid(node);
  717    pwd= getpwuid(uid);
  718    if(pwd == NULL)
  719      sprintf(xorriso->result_line, "# owner: %.f\n", (double) uid);
  720    else
  721      sprintf(xorriso->result_line, "# owner: %s\n", pwd->pw_name);
  722    Xorriso_result(xorriso, 0);
  723    gid= iso_node_get_gid(node);
  724    grp= getgrgid(gid);
  725    if(grp == NULL)
  726      sprintf(xorriso->result_line, "# group: %.f\n", (double) gid);
  727    else
  728      sprintf(xorriso->result_line, "# group: %s\n", grp->gr_name);
  729    Xorriso_result(xorriso, 0);
  730  }
  731 
  732  for(pass= 0; pass < 1 + (acl_text != NULL && !(flag & 2)); pass++) {
  733    if(pass) {
  734      if(result_len == 0) 
  735  break;
  736      *acl_text= calloc(result_len + 1, 1);
  737      if(*acl_text == NULL) {
  738        Xorriso_no_malloc_memory(xorriso, NULL, 0);
  739        ret= -1; goto ex;
  740      }
  741    }
  742    if(text != NULL && what <= 1) {
  743      for(npt= cpt= text; npt != NULL; cpt= npt + 1) {
  744        npt= strchr(cpt, '\n');
  745        if(npt != NULL)
  746          *npt= 0;
  747        if(*cpt == 0) {
  748          if(d_text != NULL || pass) {
  749            if(npt != NULL)
  750              *npt= '\n';
  751      continue;
  752          }
  753        } else
  754          result_len+= strlen(cpt) + 1;
  755        if(pass) {
  756          sprintf(*acl_text + strlen(*acl_text), "%s\n", cpt);
  757        } else if(!(flag & 1)) {
  758          if(Sfile_str(xorriso->result_line, cpt, 0) <= 0)
  759            goto too_long;
  760          strcat(xorriso->result_line, "\n");
  761          Xorriso_result(xorriso, 0);
  762        }
  763        if(npt != NULL)
  764          *npt= '\n';
  765      }
  766    }
  767    if(d_text != NULL && (what == 0 || what == 2)) {
  768      for(npt= cpt= d_text; npt != NULL; cpt= npt + 1) {
  769        npt= strchr(cpt, '\n');
  770        if(npt != NULL)
  771          *npt= 0;
  772        if(*cpt != 0) {
  773          if(pass) {
  774            if(what == 0)
  775              sprintf(*acl_text + strlen(*acl_text), "default:%s\n", cpt);
  776            else
  777              sprintf(*acl_text + strlen(*acl_text), "%s\n", cpt);
  778          } else {
  779            xorriso->result_line[0]= 0;
  780            if(what == 0)
  781              if(Sfile_str(xorriso->result_line, "default:", 0) <= 0)
  782                goto too_long;
  783            if(Sfile_str(xorriso->result_line, cpt, 1) <= 0)
  784              goto too_long;
  785            result_len+= strlen(cpt) + 9;
  786          }
  787        } else
  788          xorriso->result_line[0]= 0;
  789        if(pass== 0 && !(flag & 1)) {
  790          strcat(xorriso->result_line, "\n");
  791          Xorriso_result(xorriso, 0);
  792        }
  793        if(npt != NULL)
  794          *npt= '\n';
  795      }
  796    }
  797  }
  798  if(result_len == 0) {
  799    if(acl_text != NULL)
  800      *acl_text= NULL;
  801    ret= 2; 
  802  } else {
  803    ret= 1;
  804  }
  805 ex:;
  806  iso_node_get_acl_text(node, &text, &d_text, 1 << 15);
  807  return(ret);
  808 too_long:
  809  Xorriso_msgs_submit(xorriso, 0, "Oversized ACL", 0, "FAILURE", 0);
  810  ret= 0;
  811  goto ex;
  812 }
  813 
  814 
  815 /*
  816    @param flag      bit0= do not report to result but only retrieve attr text
  817                     bit1= path is disk_path
  818                     bit3= do not ignore non-user attributes
  819                     bit4= ignore isofs. attributes despite bit3
  820                     bit5= in case of symbolic link on disk: inquire link target
  821                     bit6= check for existence of xattr, return 0 or 1
  822                           (depends also on bit3)
  823 */
  824 int Xorriso_getfattr(struct XorrisO *xorriso, void *in_node, char *path,
  825                      char **attr_text, int flag)
  826 {
  827  int ret= 1, i, bsl_mem, result_len= 0, pass;
  828  size_t num_attrs= 0, *value_lengths= NULL;
  829  char **names= NULL, **values= NULL, *bsl;
  830 
  831  if(attr_text != NULL)
  832    *attr_text= NULL;
  833  if((xorriso->do_aaip & 1024) && !(flag & 8))
  834    flag|= 8 | 16;
  835  ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
  836                         &value_lengths, &values, flag & (2 | 8 | 32));
  837  if(ret <= 0)
  838    goto ex;
  839  if(flag & 64) {
  840    ret= (num_attrs > 0);
  841    goto ex;
  842  }
  843  if(num_attrs == 0)
  844    {ret= 2; goto ex;}
  845 
  846  if(!(flag & 1)) {
  847    ret= Xorriso_getfname(xorriso, path, 0);
  848    if(ret <= 0)
  849      goto ex;
  850  }
  851  for(pass= 0; pass < 1 + (attr_text != NULL); pass++) {
  852    if(pass) {
  853      *attr_text= calloc(result_len + 1, 1);
  854      if(*attr_text == NULL) {
  855        Xorriso_no_malloc_memory(xorriso, NULL, 0);
  856        ret= -1; goto ex;
  857      }
  858    }
  859    for(i= 0; i < (int) num_attrs; i++) {
  860      if(flag & 16)
  861        if(strncmp(names[i], "isofs.", 6) == 0)
  862    continue;
  863      if(strlen(names[i]) + value_lengths[i] >= SfileadrL) {
  864        sprintf(xorriso->result_line, "# oversized: name %d , value %d bytes\n",
  865                (int) strlen(names[i]), (int) value_lengths[i]);
  866      } else {
  867        ret= Sfile_bsl_encoder(&bsl, names[i], strlen(names[i]), 8);
  868        if(ret <= 0) 
  869          {ret= -1; goto ex;}
  870        strcpy(xorriso->result_line, bsl);
  871        free(bsl);
  872        ret= Sfile_bsl_encoder(&bsl, values[i], value_lengths[i], 8);
  873        if(ret <= 0) 
  874          {ret= -1; goto ex;}
  875        sprintf(xorriso->result_line + strlen(xorriso->result_line),
  876                "=\"%s\"\n", bsl);
  877        free(bsl);
  878      }
  879      /* temporarily disable -backslash_codes with result output */
  880      result_len+= strlen(xorriso->result_line);
  881      if(pass) {
  882        strcat(*attr_text, xorriso->result_line);
  883      } else if(!(flag & 1)) {
  884        bsl_mem= xorriso->bsl_interpretation;
  885        xorriso->bsl_interpretation= 0;
  886        Xorriso_result(xorriso, 0);
  887        xorriso->bsl_interpretation= bsl_mem;
  888      }
  889    }
  890  }
  891  if((flag & 16) && attr_text != NULL)
  892    if(*attr_text != NULL)
  893      if((*attr_text)[0] == 0) {
  894        free(*attr_text);
  895        *attr_text= NULL;
  896        ret= 2;
  897        goto ex;
  898      }
  899  if(!(flag & 1)) {
  900    strcpy(xorriso->result_line, "\n");
  901    Xorriso_result(xorriso, 0);
  902  }
  903  ret= 1;
  904 ex:;
  905  Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
  906                    &value_lengths, &values, 1 << 15);
  907  return(ret);
  908 }
  909 
  910 
  911 /*
  912    @param flag      bit0= with mode "e" : Use echo -e encoding but
  913                           do not put out commands and quotation marks.
  914                           Rather apply double backslash.
  915 */
  916 int Xorriso_append_extattr_comp(struct XorrisO *xorriso,
  917                                 char *comp, size_t comp_len,
  918                                 char *mode, int flag)
  919 {
  920  int ret;
  921  size_t line_limit;
  922  char *line, *wpt, *bsl = NULL;
  923  unsigned char *upt, *uval;
  924 
  925  line= xorriso->result_line;
  926  line_limit= sizeof(xorriso->result_line);
  927  uval= (unsigned char *) comp;
  928 
  929  if(*mode == 'q') {
  930    Text_shellsafe(comp, line, 1);
  931  } else if(*mode == 'e' || mode[0] == 0) {
  932    for(upt= uval; (size_t) (upt - uval) < comp_len; upt++)
  933      if(*upt <= 037 || *upt >= 0177)
  934    break;
  935   if((size_t) (upt - uval) < comp_len || (flag & 1)) {
  936      /* Use "$(echo -e '\0xyz')" */;
  937      if(!(flag & 1))
  938        strcat(line, "\"$(echo -e '");
  939      wpt= line + strlen(line);
  940      for(upt= uval; (size_t) (upt - uval) < comp_len; upt++) {
  941        if(wpt - line + 5 + 3 + 1 > (ssize_t) line_limit)
  942                                                    /* "\\0xyz" + "')\"" + 0 */
  943          goto too_much;
  944        if(*upt <= 037 || *upt >= 0177 || *upt == '\\' || *upt == '\'') {
  945          if(flag & 1)
  946            *(wpt++)= '\\';
  947          sprintf((char *) wpt, "\\0%-3.3o", *upt);
  948          wpt+= strlen(wpt);
  949        } else {
  950          *(wpt++)= *upt;
  951        }
  952      }
  953      *wpt= 0;
  954      if(!(flag & 1))
  955        strcpy(wpt, "')\"");
  956    } else {
  957      Text_shellsafe(comp, line, 1);
  958    }
  959  } else if(*mode == 'b') { 
  960    ret= Sfile_bsl_encoder(&bsl, comp, comp_len, 8);
  961    if(ret <= 0) 
  962      {ret= -1; goto ex;}
  963    if(strlen(line) + strlen(bsl) + 1 > line_limit)
  964      goto too_much;
  965    strcat(line, bsl);
  966    free(bsl);
  967    bsl= NULL;
  968  } else if(*mode == 'r') {
  969    if(strlen(line) + strlen(comp) + 1 > line_limit)
  970      goto too_much;
  971    strcat(line, comp);
  972  }
  973  ret= 1;
  974 ex:;
  975  if(bsl != NULL)
  976    free(bsl);
  977  return(ret);
  978 too_much:;
  979  Xorriso_msgs_submit(xorriso, 0, "Oversized BSD-style file attribute",
  980                      0, "FAILURE", 0);
  981  ret= -1;
  982  goto ex;
  983 }
  984 
  985 
  986 /*
  987    @param flag      bit1= path is disk_path
  988                     bit3= do not ignore eventual non-user attributes.
  989                     bit5= in case of symbolic link on disk: inquire link target
  990 */
  991 int Xorriso_list_extattr(struct XorrisO *xorriso, void *in_node, char *path,
  992                          char *show_path, char *mode, int flag)
  993 {
  994  int ret= 1, i, bsl_mem;
  995  size_t num_attrs= 0, *value_lengths= NULL;
  996  char **names= NULL, **values= NULL, *cpt, *space_pt, *name_pt, *path_pt;
  997  char *line;
  998  unsigned char *upt, *uval;
  999 
 1000  line= xorriso->result_line;
 1001  ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
 1002                         &value_lengths, &values, flag & (2 | 8 | 32));
 1003  if(ret <= 0)
 1004    goto ex;
 1005  if(flag & 64) {
 1006    ret= (num_attrs > 0);
 1007    goto ex;
 1008  }
 1009  if(num_attrs == 0)
 1010    {ret= 2; goto ex;}
 1011 
 1012  strcpy(line, "n=");
 1013  path_pt= show_path + (show_path[0] == '/');
 1014  if(path_pt[0] == 0)
 1015    path_pt= ".";
 1016  ret= Xorriso_append_extattr_comp(xorriso, path_pt, strlen(path_pt), mode, 0);
 1017  if(ret <= 0)
 1018    goto ex;
 1019  strcat(line, "\n");
 1020  Xorriso_result(xorriso, 0);
 1021  for(i= 0; i < (int) num_attrs; i++) {
 1022    line[0]= 0;
 1023    uval= (unsigned char *) values[i];
 1024 
 1025    if(strlen(names[i]) + value_lengths[i] >= SfileadrL) {
 1026      sprintf(line,
 1027         "echo 'OMITTED: Oversized: name %d bytes, value %d bytes in file '\"$n\" >&2\n",
 1028         (int) strlen(names[i]), (int) value_lengths[i]);
 1029      Xorriso_result(xorriso, 0);
 1030  continue;
 1031    }
 1032 
 1033    /* Form:  $c space name value $n */
 1034 
 1035    /* Split namespace from name */
 1036    cpt= strchr(names[i], '.');
 1037    if(cpt == NULL) {
 1038      space_pt= "user";
 1039      name_pt= names[i];
 1040    } else {
 1041      *cpt= 0;
 1042      space_pt= names[i];
 1043      name_pt= cpt + 1;
 1044    }
 1045 
 1046    /* FreeBSD setextattr cannot set 0-bytes */
 1047    for(upt= uval; (size_t) (upt - uval) < value_lengths[i]; upt++)
 1048      if(*upt == 0
 1049        )
 1050    break;
 1051    if((size_t) (upt - uval) < value_lengths[i]) { 
 1052      strcpy(line, "echo 'OMITTED: Value contains 0-bytes : space \"'\"");
 1053      ret= Xorriso_append_extattr_comp(xorriso, space_pt, strlen(space_pt),
 1054                                       "e", 1);
 1055      if(ret <= 0)
 1056        goto ex;
 1057      strcat(line, "\"'\" , name \"'\"");
 1058      ret= Xorriso_append_extattr_comp(xorriso, name_pt, strlen(name_pt),
 1059                                       "e", 1);
 1060      if(ret <= 0)
 1061        goto ex;
 1062      strcat(line, "\"'\" in file '\"");
 1063      ret= Xorriso_append_extattr_comp(xorriso, path_pt, strlen(path_pt),
 1064                                       "e", 1);
 1065      if(ret <= 0)
 1066        goto ex;
 1067      strcat(line, "\" >&2\n");
 1068 
 1069      /* temporarily disable -backslash_codes with result output */
 1070      bsl_mem= xorriso->bsl_interpretation;
 1071      xorriso->bsl_interpretation= 0;
 1072      Xorriso_result(xorriso, 0);
 1073      xorriso->bsl_interpretation= bsl_mem;
 1074      strcpy(line, "# ");
 1075    }
 1076 
 1077    strcat(line, "$c ");
 1078    ret= Xorriso_append_extattr_comp(xorriso, space_pt, strlen(space_pt),
 1079                                     mode, 0);
 1080    if(ret <= 0)
 1081      goto ex;
 1082    strcat(line, " ");
 1083    ret= Xorriso_append_extattr_comp(xorriso,name_pt, strlen(name_pt), mode, 0);
 1084    if(ret <= 0)
 1085      goto ex;
 1086    strcat(line, " ");
 1087    ret= Xorriso_append_extattr_comp(xorriso, values[i], value_lengths[i],
 1088                                     mode, 0);
 1089    if(ret <= 0)
 1090      goto ex;
 1091    strcat(line, " \"$n\"\n");
 1092 
 1093    /* temporarily disable -backslash_codes with result output */
 1094    bsl_mem= xorriso->bsl_interpretation;
 1095    xorriso->bsl_interpretation= 0;
 1096    Xorriso_result(xorriso, 0);
 1097    xorriso->bsl_interpretation= bsl_mem;
 1098  }
 1099  strcpy(line, "\n");
 1100  Xorriso_result(xorriso, 0);
 1101  ret= 1;
 1102 ex:;
 1103  Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
 1104                    &value_lengths, &values, 1 << 15);
 1105  return(ret);
 1106 }
 1107 
 1108 
 1109 /*
 1110  @param flag
 1111        Bitfield for control purposes
 1112             bit0=  get default ACL rather than access ACL
 1113             bit4=  set *text = NULL and return 2
 1114                    if the ACL matches st_mode permissions.
 1115             bit5=  in case of symbolic link: inquire link target
 1116             bit15= free text and return 1
 1117  @return
 1118        1 ok
 1119        2 ok, trivial ACL found while bit4 is set, *text is NULL
 1120        0 no ACL manipulation adapter available / ACL not supported by fs
 1121       -1 failure of system ACL service (see errno)
 1122       -2 attempt to inquire ACL of a symbolic link without bit4 or bit5
 1123          resp. with no suitable link target
 1124 */
 1125 int Xorriso_local_getfacl(struct XorrisO *xorriso, char *disk_path,
 1126                           char **text, int flag)
 1127 {
 1128  int ret, skip= 0, colons= 0, countdown= 0;
 1129  char *acl= NULL, *cpt, *wpt;
 1130 
 1131  if(flag & (1 << 15)) {
 1132    if(*text != NULL)
 1133      free(*text);
 1134    *text= NULL;
 1135    return(1);
 1136  }
 1137  *text= NULL;
 1138  ret= iso_local_get_acl_text(disk_path, &acl, flag & (1 | 16 | 32));
 1139  Xorriso_process_msg_queues(xorriso,0);
 1140  if(ret < 0 || ret == 2)
 1141    return(ret);
 1142  if(acl == NULL)
 1143    return(0);
 1144  *text= strdup(acl);
 1145  iso_local_get_acl_text(disk_path, &acl, 1 << 15);
 1146  if(*text == NULL) {
 1147    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 1148    return(-1);
 1149  }
 1150 
 1151  /* Garbage collection about trailing remarks after 3 permission chars */
 1152  wpt= *text;
 1153  for(cpt= *text; *cpt; cpt++) {
 1154    if(skip) {
 1155      if(*cpt == '\n')
 1156        skip= 0;
 1157      else
 1158  continue;
 1159    }
 1160    if(*cpt == ':' && !countdown) {
 1161      colons++;
 1162      if(colons == 2) {
 1163        countdown= 4;
 1164        colons= 0;
 1165      }
 1166    }
 1167    if(countdown > 0) {
 1168      countdown--;
 1169      if(countdown == 0)
 1170        skip= 1;
 1171    }
 1172    *wpt= *cpt;
 1173    wpt++;
 1174  }
 1175  *wpt= 0;
 1176 
 1177  return(1);
 1178 }
 1179 
 1180 
 1181 /*
 1182    @param flag
 1183                bit1= path is disk_path
 1184                bit3= do not ignore eventual non-user attributes.
 1185                bit5= in case of symbolic link on disk: inquire link target
 1186               bit15= free memory
 1187 */
 1188 int Xorriso_get_attrs(struct XorrisO *xorriso, void *in_node, char *path,
 1189                       size_t *num_attrs, char ***names,
 1190                       size_t **value_lengths, char ***values, int flag)
 1191 {
 1192  int ret, i, widx;
 1193  IsoNode *node;
 1194 
 1195  if(flag & (1 << 15)) {
 1196    if(flag & 2) {
 1197      iso_local_get_attrs(NULL, num_attrs, names, value_lengths, values,
 1198                          1 << 15);
 1199    } else {
 1200      iso_node_get_attrs(NULL, num_attrs, names, value_lengths, values,
 1201                         1 << 15);
 1202    }
 1203    return(1);
 1204  }
 1205 
 1206  *num_attrs= 0;
 1207  if(flag & 2) {
 1208    ret= iso_local_get_attrs(path, num_attrs, names, value_lengths, values,
 1209                             flag & (8 | 32));
 1210    if(ret < 0) {
 1211      strcpy(xorriso->info_text, "Error with reading xattr of disk file ");
 1212      Text_shellsafe(path, xorriso->info_text, 1);
 1213      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1214    }
 1215  } else {
 1216    node= (IsoNode *) in_node;
 1217    if(node == NULL) {
 1218      ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 1219      if(ret<=0)
 1220        goto ex;
 1221    }
 1222    ret= iso_node_get_attrs(node, num_attrs, names, value_lengths, values,
 1223                            0);
 1224    if(ret < 0) {
 1225      Xorriso_report_iso_error(xorriso, "", ret,
 1226                     "Error when obtaining xattr of ISO node", 0, "FAILURE", 1);
 1227      goto ex;
 1228    }
 1229 
 1230    if(!(flag & 8)) {
 1231      /* Filter away any non-userspace xattr */;
 1232      widx= 0;
 1233      for(i= 0; i < (int) *num_attrs; i++) {
 1234        if(strncmp((*names)[i], "user.", 5) != 0) {
 1235          free((*names)[i]);
 1236          (*names)[i]= NULL;
 1237          if((*values)[i] != NULL) {
 1238            free((*values)[i]);
 1239            (*values)[i]= NULL;
 1240          }
 1241        } else {
 1242          if(widx != i) {
 1243            (*names)[widx]= (*names)[i];
 1244            (*value_lengths)[widx]= (*value_lengths)[i];
 1245            (*values)[widx]= (*values)[i];
 1246            (*names)[i]= NULL;
 1247            (*value_lengths)[i]= 0;
 1248            (*values)[i]= NULL;
 1249          }
 1250          widx++;
 1251        }
 1252      }
 1253      *num_attrs= widx;
 1254    }
 1255  }
 1256  ret= 1;
 1257 ex:;
 1258  Xorriso_process_msg_queues(xorriso,0);
 1259  return(ret);
 1260 }
 1261 
 1262 
 1263 int Xorriso_get_attr_value(struct XorrisO *xorriso, void *in_node, char *path,
 1264                       char *name, size_t *value_length, char **value, int flag)
 1265 {
 1266  int ret;
 1267  size_t num_attrs= 0, *value_lengths= NULL, i;
 1268  char **names = NULL, **values= NULL;
 1269 
 1270  *value= NULL;
 1271  *value_length= 0;
 1272  ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
 1273                         &value_lengths, &values, 8);
 1274  if(ret <= 0)
 1275    goto ex;
 1276 
 1277  for(i= 0; i < num_attrs; i++) {
 1278    if(strcmp(name, names[i]) != 0)
 1279  continue;
 1280    *value= calloc(value_lengths[i] + 1, 1);
 1281    if(*value == NULL)
 1282      {ret= -1; goto ex;}
 1283    memcpy(*value, values[i], value_lengths[i]);
 1284    (*value)[value_lengths[i]]= 0;
 1285    *value_length= value_lengths[i];
 1286    ret= 1; goto ex;
 1287  }
 1288  ret= 0;
 1289 ex:
 1290  Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
 1291                         &value_lengths, &values, 1 << 15);
 1292  return(ret);
 1293 }
 1294 
 1295 
 1296 int Xorriso_stream_type(struct XorrisO *xorriso, IsoNode *node,
 1297                         IsoStream *stream, char type_text[], int flag)
 1298 {
 1299  int ret, lba, stream_type, block_size_log2;
 1300  uint8_t zisofs_algo[2], algo_num;
 1301  char text[5];
 1302 
 1303  strncpy(text, stream->class->type, 4);
 1304  text[4]= 0;
 1305  if(strcmp(text, "fsrc") == 0) {
 1306    ret= Xorriso__file_start_lba(node, &lba, 0);
 1307    if(ret > 0 && lba > 0)
 1308      strcpy(type_text, "image");
 1309    else
 1310      strcpy(type_text, "disk");
 1311  } else if(strcmp(text, "ziso") == 0 || strcmp(text, "osiz") == 0) {
 1312    if(strcmp(text, "ziso") == 0)
 1313      strcpy(type_text, "--zisofs");
 1314    else
 1315      strcpy(type_text, "--zisofs-decode");
 1316    ret= iso_stream_get_zisofs_par(stream, &stream_type, zisofs_algo, &algo_num,
 1317                                   &block_size_log2, 0);
 1318    if(ret == 1)
 1319      sprintf(type_text + strlen(type_text), ":%c%c:%dk",
 1320              zisofs_algo[0], zisofs_algo[1], 1 << (block_size_log2 - 10));
 1321  } else if(strcmp(text, "gzip") == 0) {
 1322    strcpy(type_text, "--gzip");
 1323  } else if(strcmp(text, "pizg") == 0) {
 1324    strcpy(type_text, "--gunzip");
 1325  } else if(strcmp(text, "cout") == 0 || strcmp(text, "boot") == 0 ||
 1326            strcmp(text, "user") == 0 || strcmp(text, "extf") == 0) {
 1327    strcpy(type_text, text);
 1328  } else {
 1329    Text_shellsafe(text, type_text, 0);
 1330  }
 1331  return(1);
 1332 } 
 1333 
 1334 
 1335 /*
 1336    @param flag      bit0= do not report to result but only retrieve md5 text
 1337    @return          1= ok, 0= no md5 available, <0= other error
 1338 */
 1339 int Xorriso_get_md5(struct XorrisO *xorriso, void *in_node, char *path,
 1340                     char md5[16], int flag)
 1341 {
 1342  int ret= 1, i;
 1343  char *wpt;
 1344  IsoImage *image;
 1345  IsoNode *node;
 1346 
 1347  ret= Xorriso_get_volume(xorriso, &image, 0);
 1348  if(ret <= 0)
 1349    goto ex;
 1350  node= (IsoNode *) in_node;
 1351  if(node == NULL) {
 1352    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 1353    if(ret<=0)
 1354      goto ex;
 1355  }
 1356  if(!LIBISO_ISREG(node))
 1357    return(0);
 1358  ret= iso_file_get_md5(image, (IsoFile *) node, md5, 0);
 1359  Xorriso_process_msg_queues(xorriso,0);
 1360  if(ret <= 0)
 1361    goto ex;
 1362  if(flag & 1)
 1363    {ret= 1; goto ex;}
 1364 
 1365  wpt= xorriso->result_line;
 1366  for(i= 0; i < 16; i++) {
 1367    sprintf(wpt, "%2.2x", ((unsigned char *) md5)[i]);
 1368    wpt+= 2;
 1369  }
 1370  strcpy(wpt, "  ");
 1371  wpt+= 2;
 1372  Xorriso_getfname(xorriso, path, 1 | 2);
 1373  ret= 1;
 1374 ex:;
 1375  return(ret);
 1376 }
 1377 
 1378 
 1379 int Xorriso_make_md5(struct XorrisO *xorriso, void *in_node, char *path,
 1380                      int flag)
 1381 {
 1382  int ret;
 1383  off_t size;
 1384  IsoNode *node;
 1385  
 1386  node= (IsoNode *) in_node;
 1387  if(node == NULL) {
 1388    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 1389    if(ret <= 0)
 1390      return(ret);
 1391  }
 1392  if(!LIBISO_ISREG(node))
 1393    return(0);
 1394  ret= iso_file_make_md5((IsoFile *) node, 0);
 1395  size= iso_file_get_size((IsoFile *) node);
 1396  xorriso->pacifier_count+= size;
 1397  xorriso->pacifier_byte_count+= size;
 1398  Xorriso_pacifier_callback(xorriso, "content bytes read",
 1399                            xorriso->pacifier_count, 0, "", 8);
 1400  Xorriso_process_msg_queues(xorriso, 0);
 1401  if(ret < 0) {
 1402    Xorriso_report_iso_error(xorriso, "", ret,
 1403                             "Error when computing MD5", 0, "FAILURE", 1);
 1404    return(0);
 1405  }
 1406  Xorriso_set_change_pending(xorriso, 1);
 1407  return(1);
 1408 }
 1409 
 1410 
 1411 /* @param flag bit0= do not only sum up sizes but also print subdirs
 1412 
 1413                bit2= do not report result by Xorriso_result()
 1414 */
 1415 int Xorriso_show_du_subs(struct XorrisO *xorriso, IsoDir *dir_node,
 1416                       char *abs_path, char *rel_path, off_t *size,
 1417                       off_t boss_mem, int flag)
 1418 {
 1419  int i, ret, no_sort= 0, filec= 0, l;
 1420  IsoDirIter *iter= NULL;
 1421  IsoNode *node, **node_array= NULL;
 1422  char *name;
 1423  off_t sub_size, report_size, mem= 0;
 1424  char *path= NULL, *show_path= NULL, *sfe= NULL;
 1425 
 1426  Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
 1427  Xorriso_alloc_meM(path, char, SfileadrL);
 1428  Xorriso_alloc_meM(show_path, char, SfileadrL);
 1429 
 1430  *size= 0;
 1431  ret= iso_dir_get_children(dir_node, &iter);
 1432  if(ret<0) {
 1433 cannot_create_iter:;
 1434    Xorriso_cannot_create_iter(xorriso, ret, 0);
 1435    {ret= -1; goto ex;}
 1436  }
 1437  for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
 1438    sub_size= 0;
 1439    name= (char *) iso_node_get_name(node);
 1440    strcpy(show_path, rel_path);
 1441    if(Sfile_add_to_path(show_path, name, 0)<=0)
 1442        goto much_too_long;
 1443    if(LIBISO_ISDIR(node)) {
 1444      strcpy(path, abs_path);
 1445      if(Sfile_add_to_path(path, name, 0)<=0) {
 1446 much_too_long:;
 1447        Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
 1448        {ret= -1; goto ex;}
 1449      }
 1450      filec++;
 1451      l= strlen(rel_path)+1;
 1452      mem+= l;
 1453      if(l % sizeof(char *))
 1454        mem+= sizeof(char *)-(l % sizeof(char *));
 1455      if(flag&1) /* diving and counting is done further below */
 1456  continue;
 1457      ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
 1458                                path, show_path, &sub_size, boss_mem, 0);
 1459      if(ret<0)
 1460        goto ex;
 1461      if(ret==0)
 1462  continue;
 1463    }
 1464 
 1465    if(LIBISO_ISREG(node)) {
 1466      sub_size+= iso_file_get_size((IsoFile *) node)+2048;
 1467 /*
 1468      sub_size+= iso_file_get_size((IsoFile *) node)+strlen(name)+1;
 1469 */
 1470    }
 1471 
 1472    if(sub_size>0)
 1473      (*size)+= sub_size;
 1474    Xorriso_process_msg_queues(xorriso,0);
 1475  }
 1476 
 1477  if(filec<=0 || !(flag&1))
 1478    {ret= 1; goto ex;}
 1479 
 1480  /* Reset iteration */
 1481  iso_dir_iter_free(iter);
 1482  iter= NULL;
 1483  Xorriso_process_msg_queues(xorriso,0);
 1484 
 1485  ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array,
 1486                                 boss_mem, 1|2|4);
 1487  if(ret<0)
 1488    goto ex;
 1489  if(ret==0) {
 1490    no_sort= 1;
 1491    ret= iso_dir_get_children(dir_node, &iter);
 1492    if(ret<0)
 1493      goto cannot_create_iter;
 1494  }
 1495 
 1496  for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
 1497    if(no_sort) {
 1498      ret= iso_dir_iter_next(iter, &node);
 1499      if(ret!=1)
 1500  break;
 1501      if(!LIBISO_ISDIR(node))
 1502  continue;
 1503    } else
 1504      node= node_array[i];
 1505 
 1506    sub_size= 0;
 1507    name= (char *) iso_node_get_name(node);
 1508    strcpy(show_path, rel_path);
 1509    if(Sfile_add_to_path(show_path, name, 0)<=0)
 1510      goto much_too_long;
 1511    strcpy(path, abs_path);
 1512    if(Sfile_add_to_path(path, name, 0)<=0)
 1513      goto much_too_long;
 1514    ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
 1515                              path, show_path, &sub_size, boss_mem+mem, flag&1);
 1516    if(ret<0)
 1517      goto ex;
 1518 
 1519    if(LIBISO_ISREG(node)) {
 1520      sub_size+= iso_file_get_size((IsoFile *) node)+2048;
 1521 /*
 1522      sub_size+= iso_tree_node_get_size((IsoFile *) node)+strlen(name)+1;
 1523 */
 1524    }
 1525    if(sub_size>0)
 1526      (*size)+= sub_size;
 1527    report_size= sub_size/1024;
 1528    if(report_size*1024<sub_size)
 1529       report_size++;
 1530    if(!(flag & 4)) {
 1531      if(xorriso->sh_style_result)
 1532        sprintf(xorriso->result_line, "%-7.f ",(double) (report_size));
 1533      else
 1534        sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
 1535      sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
 1536              Xorriso_esc_filepath(xorriso, show_path, sfe, 0));
 1537      Xorriso_result(xorriso, 0);
 1538    }
 1539  }
 1540  ret= 1;
 1541 ex:;
 1542  Xorriso_free_meM(sfe);
 1543  Xorriso_free_meM(path);
 1544  Xorriso_free_meM(show_path);
 1545  if(iter!=NULL)
 1546    iso_dir_iter_free(iter);
 1547  if(node_array!=NULL)
 1548    free((char *) node_array);
 1549  Xorriso_process_msg_queues(xorriso,0);
 1550  return(ret);
 1551 }
 1552 
 1553 
 1554 int Xorriso_sorted_dir_i(struct XorrisO *xorriso, IsoDir *dir_node,
 1555                          int *filec, char ***filev, off_t boss_mem, int flag)
 1556 {
 1557  int i,j,ret;
 1558  IsoDirIter *iter= NULL;
 1559  IsoNode *node;
 1560  char *name;
 1561  off_t mem;
 1562 
 1563  (*filec)= 0;
 1564  (*filev)= NULL;
 1565 
 1566  ret= iso_dir_get_children(dir_node, &iter);
 1567  if(ret<0) {
 1568 cannot_iter:;
 1569    Xorriso_cannot_create_iter(xorriso, ret, 0);
 1570    {ret= -1; goto ex;}
 1571  }
 1572  mem= 0;
 1573  for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
 1574    name= (char *) iso_node_get_name(node);
 1575    mem+= sizeof(char *)+strlen(name)+8;
 1576    (*filec)++;
 1577  }
 1578  iso_dir_iter_free(iter);
 1579  iter= NULL;
 1580  if(*filec==0)
 1581    {ret= 1; goto ex;}
 1582 
 1583  ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
 1584  if(ret<=0)
 1585    goto ex;
 1586  (*filev)= (char **) calloc(*filec, sizeof(char *));
 1587  if(*filev==NULL)
 1588    {ret= -1; goto ex; }
 1589  ret= iso_dir_get_children(dir_node, &iter);
 1590  if(ret<0) 
 1591    goto cannot_iter;
 1592  for(i= 0; i<*filec; i++) {
 1593    ret= iso_dir_iter_next(iter, &node);
 1594    if(ret!=1)
 1595  break;
 1596    name= (char *) iso_node_get_name(node);
 1597    (*filev)[i]= strdup(name);
 1598    if((*filev)[i]==NULL) {
 1599      for(j= 0; j<i; j++)
 1600        if((*filev)[j]!=NULL)
 1601          free((*filev)[j]);
 1602      free((char *) (*filev));
 1603      ret= -1; goto ex;
 1604    }
 1605  }
 1606  Sort_argv(*filec, *filev, 0);
 1607  ret= 1;
 1608 ex:;
 1609  if(iter!=NULL)
 1610    iso_dir_iter_free(iter);
 1611  return(ret);
 1612 }
 1613 
 1614 
 1615 int Xorriso_node_eff_hidden(struct XorrisO *xorriso, IsoNode *node, int flag)
 1616 {
 1617  int hidden_state= 0, ret;
 1618  IsoNode *current, *parent;
 1619 
 1620  current= node;
 1621  for(current= node; hidden_state != 7;) {
 1622    ret= iso_node_get_hidden(current);
 1623    if(ret & LIBISO_HIDE_ON_RR)
 1624      hidden_state|= 1;
 1625    if(ret & LIBISO_HIDE_ON_JOLIET)
 1626      hidden_state|= 2;
 1627    if(ret & LIBISO_HIDE_ON_HFSPLUS)
 1628      hidden_state|= 4;
 1629    parent= (IsoNode *) iso_node_get_parent(current);
 1630    if(parent == current)
 1631  break;
 1632    current= parent;
 1633  }
 1634  return(hidden_state);
 1635 }
 1636 
 1637 
 1638 /* @param flag bit0= do not truncate components which contain any of "*?["
 1639 */
 1640 int Xorriso_truncate_path_comps(struct XorrisO *xorriso, char *path,
 1641                                 char *buffer, char **resultpt, int flag)
 1642 {
 1643  char *rpt, *basrpt, *wpt, *baswpt, *cpt;
 1644  int ended, ret, skip;
 1645 
 1646  *resultpt= path;
 1647 
 1648  /* Check component lengths */
 1649  rpt= path;
 1650  if(*rpt == '/')
 1651    rpt++;
 1652  for(ended= 0; !ended;) {
 1653    basrpt= rpt;
 1654    rpt= strchr(basrpt, '/');
 1655    if(rpt == NULL) {
 1656      rpt= basrpt + strlen(basrpt);
 1657      ended= 1;
 1658    }
 1659    skip= 0;
 1660    if(flag & 1) {
 1661      for(cpt= basrpt; cpt < rpt; cpt++) {
 1662        if(strchr("*?[", *cpt) != NULL) {
 1663          skip= 1;
 1664      break;
 1665        }
 1666      }
 1667    }
 1668    if((!skip) && rpt - basrpt > xorriso->file_name_limit) {
 1669      ended= 0;
 1670  break;
 1671    }
 1672    if(*rpt == '/')
 1673      rpt++;
 1674  }    
 1675  if(ended)
 1676    return(1); /* All short enough */
 1677 
 1678  /* Some truncation is needed */ 
 1679  buffer[0]= 0;
 1680  wpt= buffer;
 1681  if(path[0] == '/')
 1682    *(wpt++)= '/';
 1683  rpt= path;
 1684  if(*rpt == '/')
 1685    rpt++;
 1686  for(ended= 0; !ended;) {
 1687    basrpt= rpt;
 1688    baswpt= wpt;
 1689    rpt= strchr(basrpt, '/');
 1690    if(rpt == NULL) {
 1691      rpt= basrpt + strlen(basrpt);
 1692      ended= 1;
 1693    }
 1694    skip= 0;
 1695    for(cpt= basrpt; cpt < rpt; cpt++) {
 1696      *(wpt++)= *cpt;
 1697      if((flag & 1) && strchr("*?[", *cpt) != NULL)
 1698        skip= 1;
 1699    }
 1700    *wpt= 0;
 1701    if((!skip) && rpt - basrpt > xorriso->file_name_limit) {
 1702       ret= iso_truncate_leaf_name(1, xorriso->file_name_limit, baswpt, 0);
 1703       Xorriso_process_msg_queues(xorriso, 0);
 1704       if(ret < 0)
 1705         return(0);
 1706       wpt= baswpt + strlen(baswpt);
 1707    }
 1708    if(!ended) {
 1709      *(wpt++)= '/';
 1710      rpt++;
 1711    }
 1712  }
 1713  *resultpt= buffer;
 1714  return(1);
 1715 }
 1716 
 1717 
 1718 /* @param flag bit0= long format
 1719                bit1= do not print count of nodes
 1720                bit2= du format
 1721                bit3= print directories as themselves (ls -d)
 1722                bit5= do not look for truncated versions of path component
 1723 */
 1724 int Xorriso_ls_filev(struct XorrisO *xorriso, char *wd,
 1725                      int filec, char **filev, off_t boss_mem, int flag)
 1726 {
 1727  int i, ret, was_error= 0, dfilec= 0, pass, passes, hidden_state= 0;
 1728  IsoNode *node;
 1729  IsoImage *volume;
 1730  char *path= NULL, *link_target= NULL, *rpt, **dfilev= NULL;
 1731  char *a_text= NULL, *d_text= NULL, *namept;
 1732  off_t size;
 1733  struct stat stbuf;
 1734 
 1735  Xorriso_alloc_meM(path, char, SfileadrL);
 1736  Xorriso_alloc_meM(link_target, char, SfileadrL);
 1737 
 1738  rpt= xorriso->result_line;
 1739 
 1740  ret= Xorriso_get_volume(xorriso, &volume, 0);
 1741  if(ret<=0)
 1742    goto ex;
 1743 
 1744  Sort_argv(filec, filev, 0);
 1745 
 1746  /* Count valid nodes, warn of invalid ones */
 1747  for(i= 0; i<filec; i++) {
 1748    ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
 1749    if(ret<=0) {
 1750      was_error++;
 1751  continue;
 1752    }
 1753    ret= Xorriso_node_from_path(xorriso, volume, path, &node,
 1754                                1 | ((flag >> 4) & 2));
 1755    if(ret<=0) {
 1756      sprintf(xorriso->info_text, "Not found in ISO image: ");
 1757      Text_shellsafe(path, xorriso->info_text, 1);
 1758      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 1759      was_error++;
 1760  continue;
 1761    }
 1762  }
 1763 
 1764  if((flag&8) && !(flag&(2|4))) {
 1765    sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec-was_error);
 1766    Xorriso_info(xorriso,1);
 1767    if(filec-was_error<=0)
 1768      {ret= !was_error; goto ex;}
 1769  }
 1770 
 1771  passes= 1+!(flag&(4|8));
 1772  for(pass= 0; pass<passes; pass++)
 1773  for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
 1774    rpt[0]= 0;
 1775    ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
 1776    if(ret<=0)
 1777  continue;
 1778    ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, ((flag&4) >> 1) | 16);
 1779    if(ret<=0)
 1780  continue;
 1781    if(LIBISO_ISDIR(node)  && !(flag&(4|8))) {
 1782      if(pass==0)
 1783  continue;
 1784      if(filec>1) {
 1785        strcpy(xorriso->result_line, "\n");
 1786        Xorriso_result(xorriso,0);
 1787        Xorriso_esc_filepath(xorriso, filev[i], xorriso->result_line, 0);
 1788        strcat(xorriso->result_line, ":\n");
 1789        Xorriso_result(xorriso,0);
 1790      }
 1791      ret= Xorriso_sorted_dir_i(xorriso, 
 1792                                (IsoDir *) node, &dfilec, &dfilev, boss_mem, 0);
 1793      if(ret<=0) {
 1794 
 1795        /* >>> libisofs iterator loop and single item Xorriso_lsx_filev() */;
 1796 
 1797      } else {
 1798        if(flag&1) {
 1799          sprintf(xorriso->result_line, "total %d\n", dfilec);
 1800          Xorriso_result(xorriso,0);
 1801        }
 1802        Xorriso_ls_filev(xorriso, path,
 1803                         dfilec, dfilev, boss_mem, (flag & 1) | 2 | 8);
 1804      }
 1805      if(dfilec>0)
 1806        Sfile_destroy_argv(&dfilec, &dfilev, 0);
 1807  continue;
 1808    } else
 1809      if(pass>0)
 1810  continue;
 1811    link_target[0]= 0;
 1812    if((flag&5)==1) { /* -ls_l */
 1813      iso_node_get_acl_text(node, &a_text, &d_text, 16);
 1814      hidden_state= Xorriso_node_eff_hidden(xorriso, node, 0);
 1815      ret= Xorriso_format_ls_l(xorriso, &stbuf,
 1816                               1 | ((a_text != NULL || d_text != NULL) << 1) |
 1817                               (hidden_state << 2));
 1818      iso_node_get_acl_text(node, &a_text, &d_text, 1 << 15);
 1819      if(ret<=0)
 1820  continue;
 1821      if(LIBISO_ISLNK(node)) {
 1822        if(Sfile_str(link_target, (char *) iso_symlink_get_dest(
 1823                                                    (IsoSymlink *) node), 0)<=0)
 1824          link_target[0]= 0;
 1825      }
 1826    } else if(flag&4) { /* -du or -dus */
 1827      size= stbuf.st_size;
 1828      if(S_ISDIR(stbuf.st_mode)) {
 1829        ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
 1830                                  path, filev[i], &size, boss_mem, flag&1);
 1831        if(ret<0)
 1832          {ret= -1; goto ex;}
 1833        if(ret==0)
 1834  continue;
 1835      }
 1836      if(xorriso->sh_style_result)
 1837        sprintf(rpt, "%-7.f ",(double) (size/1024));
 1838      else
 1839        sprintf(rpt, "%7.f ",(double) (size/1024));
 1840    }
 1841    Xorriso_truncate_path_comps(xorriso, filev[i], path, &namept, 0);
 1842    if(link_target[0] && (flag&5)==1) {
 1843      Xorriso_esc_filepath(xorriso, namept, xorriso->result_line, 1);
 1844      strcat(xorriso->result_line, " -> ");
 1845      Xorriso_esc_filepath(xorriso, link_target, xorriso->result_line, 1 | 2);
 1846    } else {
 1847      Xorriso_esc_filepath(xorriso, namept, xorriso->result_line, 1);
 1848    }
 1849    strcat(xorriso->result_line, "\n");
 1850    Xorriso_result(xorriso, 0);
 1851  }
 1852  ret= !was_error;
 1853 ex:;
 1854  Xorriso_free_meM(path);
 1855  Xorriso_free_meM(link_target);
 1856  return(ret);
 1857 }
 1858 
 1859 
 1860 /*
 1861    @return: <=0 = error, 1= directory tree, 2= path leads to non-directory 
 1862 */
 1863 int Xorriso_get_dus(struct XorrisO *xorriso, char *iso_rr_path, off_t *size,
 1864                     off_t boss_mem, int flag)
 1865 {
 1866  int ret;
 1867  IsoNode *node;
 1868  char *path= NULL;
 1869  struct stat stbuf;
 1870 
 1871  Xorriso_alloc_meM(path, char, SfileadrL);
 1872 
 1873  ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, iso_rr_path, path,
 1874                            1 | 2 | 4);
 1875  if(ret <= 0)
 1876    goto ex;
 1877  ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, 0);
 1878  if(ret <= 0)
 1879    goto ex;
 1880  if(!S_ISDIR(stbuf.st_mode)) {
 1881    *size= stbuf.st_size;
 1882    ret= 2; goto ex;
 1883  }
 1884  ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node, path, iso_rr_path, size,
 1885                            boss_mem, 4);
 1886  if(ret <= 0)
 1887    goto ex;
 1888  ret= 1;
 1889 ex:
 1890  Xorriso_free_meM(path);
 1891  return(ret);
 1892 }
 1893 
 1894 
 1895 /* This function needs less buffer memory than Xorriso_ls_filev() but cannot
 1896    perform structured pattern matching as done by Xorriso_expand_pattern()
 1897    for subsequent Xorriso_ls_filev().
 1898    @param flag bit0= long format
 1899                bit1= only check for directory existence
 1900                bit2= do not apply search pattern but accept any file
 1901                bit3= just count nodes and return number
 1902 */
 1903 int Xorriso_ls(struct XorrisO *xorriso, int flag)
 1904 {
 1905  int ret, i, filec= 0, failed_at, no_sort= 0;
 1906  IsoNode *node, **node_array= NULL;
 1907  IsoDir *dir_node;
 1908  IsoDirIter *iter= NULL;
 1909  char *link_target= NULL, *npt, *rpt;
 1910  struct stat stbuf;
 1911 
 1912  Xorriso_alloc_meM(link_target, char, SfileadrL);
 1913 
 1914  rpt= xorriso->result_line;
 1915 
 1916  ret= Xorriso_dir_from_path(xorriso, "Working directory", xorriso->wdi,
 1917                             &dir_node, 0);
 1918  if(ret <= 0)
 1919    goto ex;
 1920  ret= iso_dir_get_children(dir_node, &iter);
 1921  if(ret<0) {
 1922 cannot_create_iter:;
 1923    Xorriso_cannot_create_iter(xorriso, ret, 0);
 1924    {ret= -1; goto ex;}
 1925  }
 1926  Xorriso_process_msg_queues(xorriso,0);
 1927 
 1928  for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
 1929    npt= (char *) iso_node_get_name(node);
 1930    if(!(flag&4)) {
 1931      ret= Xorriso_regexec(xorriso, npt, &failed_at, 0);
 1932      if(ret)
 1933  continue; /* no match */
 1934    }
 1935    filec++;
 1936  }
 1937  /* Reset iteration */
 1938  iso_dir_iter_free(iter);
 1939  iter= NULL;
 1940  Xorriso_process_msg_queues(xorriso,0);
 1941  if(flag&8)
 1942    {ret= filec; goto ex;}
 1943  sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec);
 1944  Xorriso_info(xorriso,1);
 1945 
 1946  ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array, 0,
 1947                                 flag&4);
 1948  if(ret<0)
 1949    goto ex;
 1950  if(ret==0) {
 1951    no_sort= 1;
 1952    ret= iso_dir_get_children(dir_node, &iter);
 1953    if(ret<0)
 1954      goto cannot_create_iter;
 1955  }
 1956 
 1957  for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
 1958    if(no_sort) {
 1959      ret= iso_dir_iter_next(iter, &node);
 1960      if(ret!=1)
 1961  break;
 1962      npt= (char *) iso_node_get_name(node);
 1963      if(!(flag&4)) {
 1964        ret= Xorriso_regexec(xorriso, npt, &failed_at, 0);
 1965        if(ret)
 1966  continue; /* no match */
 1967      }
 1968    } else
 1969      node= node_array[i];
 1970 
 1971    npt= (char *) iso_node_get_name(node);
 1972    link_target[0]= 0;
 1973    if(LIBISO_ISLNK(node)) {
 1974      if(Sfile_str(link_target, (char *) iso_symlink_get_dest(
 1975                                                    (IsoSymlink *) node), 0)<=0)
 1976        link_target[0]= 0;
 1977    }
 1978    rpt[0]= 0;
 1979    if(flag&1) {
 1980      ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
 1981      if(ret<=0)
 1982  continue;
 1983      ret= Xorriso_format_ls_l(xorriso, &stbuf, 1);
 1984      if(ret<=0)
 1985  continue;
 1986    }
 1987    if(link_target[0] && (flag&1)) {
 1988      Xorriso_esc_filepath(xorriso, npt, xorriso->result_line, 1); 
 1989      strcat(xorriso->result_line, " -> ");
 1990      Xorriso_esc_filepath(xorriso, link_target, xorriso->result_line, 1 | 2);
 1991    } else {
 1992      Xorriso_esc_filepath(xorriso, npt, xorriso->result_line, 1);
 1993    }
 1994    strcat(xorriso->result_line, "\n");
 1995    Xorriso_result(xorriso, 0);
 1996  }
 1997 
 1998  ret= 1;
 1999 ex:;
 2000  if(iter!=NULL)
 2001    iso_dir_iter_free(iter);
 2002  Xorriso_process_msg_queues(xorriso,0);
 2003  if(node_array!=NULL)
 2004    free((char *) node_array);
 2005  Xorriso_free_meM(link_target);
 2006  return(ret);
 2007 }
 2008 
 2009 
 2010 /* @param flag bit0= count results rather than storing them
 2011                bit1= this is a recursion
 2012                bit2= prepend wd (automatically done if wd[0]!=0)
 2013 */
 2014 int Xorriso_obtain_pattern_files_i(
 2015        struct XorrisO *xorriso, char *wd, IsoDir *dir,
 2016        int *filec, char **filev, int count_limit, off_t *mem,
 2017        int *dive_count, int flag)
 2018 {
 2019  int ret, failed_at;
 2020  IsoDirIter *iter= NULL;
 2021  IsoNode *node;
 2022  char *name;
 2023  char *adr= NULL;
 2024 
 2025  adr= malloc(SfileadrL);
 2026  if(adr==NULL) {
 2027    Xorriso_no_malloc_memory(xorriso, &adr, 0);
 2028    {ret= -1; goto ex;}
 2029  }
 2030 
 2031  if(!(flag&2))
 2032    *dive_count= 0;
 2033  else
 2034    (*dive_count)++;
 2035  ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit,
 2036                                      mem, (flag&1)|2);
 2037  if(ret!=2)
 2038    goto ex;
 2039 
 2040  ret= iso_dir_get_children(dir, &iter);
 2041  if(ret<0) {
 2042    Xorriso_cannot_create_iter(xorriso, ret, 0);
 2043    {ret= -1; goto ex;}
 2044  }
 2045  while(iso_dir_iter_next(iter, &node) == 1) {
 2046    name= (char *) iso_node_get_name(node);
 2047    ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4);
 2048    if(ret<=0)
 2049      goto ex;
 2050    ret= Xorriso_regexec(xorriso, adr, &failed_at, 1);
 2051    if(ret) { /* no match */
 2052      if(failed_at <= *dive_count) /* no hope for a match */
 2053  continue;
 2054 
 2055      if(!LIBISO_ISDIR(node)) {
 2056 
 2057        /* >>> How to deal with softlinks ? */
 2058 
 2059  continue;
 2060      }
 2061      /* dive deeper */
 2062      ret= Xorriso_obtain_pattern_files_i(
 2063                           xorriso, adr, (IsoDir *) node,
 2064                           filec, filev, count_limit, mem, dive_count, flag|2);
 2065      if(ret<=0)
 2066        goto ex;
 2067    } else {
 2068      ret= Xorriso_register_matched_adr(xorriso, adr, count_limit,
 2069                                        filec, filev, mem, (flag&1)|2);
 2070      if(ret<=0)
 2071        goto ex;
 2072    }
 2073  } 
 2074  ret= 1;
 2075 ex:;
 2076  if(adr!=NULL)
 2077    free(adr);
 2078  if(flag&2)
 2079    (*dive_count)--;
 2080  if(iter != NULL)
 2081    iso_dir_iter_free(iter);
 2082  return(ret);
 2083 }
 2084 
 2085 
 2086 /* @param flag bit0= a match count !=1 is a FAILURE event
 2087                bit1= with bit0 tolerate 0 matches if pattern is a constant
 2088                bit2= do not issue debug messages about temporary memory needs
 2089                bit3= do not add unresolved pattern to filev
 2090 */
 2091 int Xorriso_expand_pattern(struct XorrisO *xorriso,
 2092                            int num_patterns, char **patterns, int extra_filec,
 2093                            int *filec, char ***filev, off_t *mem, int flag)
 2094 {
 2095  int ret, count= 0, abs_adr= 0, i, was_count, was_filec;
 2096  int nonconst_mismatches= 0, dive_count= 0;
 2097  IsoImage *volume;
 2098  IsoDir *dir= NULL, *root_dir;
 2099  IsoNode *iso_node;
 2100 
 2101  *filec= 0;
 2102  *filev= NULL;
 2103 
 2104  xorriso->search_mode= 3;
 2105  xorriso->structured_search= 1;
 2106 
 2107  ret= Xorriso_get_volume(xorriso, &volume, 0);
 2108  if(ret<=0)
 2109    return(ret);
 2110  root_dir= iso_image_get_root(volume);
 2111  if(root_dir==NULL) {
 2112    Xorriso_process_msg_queues(xorriso,0);
 2113    sprintf(xorriso->info_text,
 2114            "While expanding pattern : Cannot obtain root node of ISO image");
 2115    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2116    ret= -1; goto ex;
 2117  }
 2118 
 2119  for(i= 0; i<num_patterns; i++) {
 2120    ret=  Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 0);
 2121    if(ret<=0)
 2122      return(ret);
 2123    if(ret==2)
 2124      abs_adr= 4;
 2125    if(patterns[i][0]=='/' || abs_adr) {
 2126      dir= root_dir;
 2127      abs_adr= 4;
 2128    } else {
 2129      /* This is done so late to allow the following:
 2130         It is not an error if xorriso->wdi does not exist yet, but one may
 2131         not use it as base for relative address searches.
 2132      */
 2133      ret= Xorriso_node_from_path(xorriso, volume, xorriso->wdi, &iso_node, 1);
 2134      dir= (IsoDir *) iso_node;
 2135      if(ret<=0) {
 2136        Xorriso_process_msg_queues(xorriso,0);
 2137        sprintf(xorriso->info_text, "While expanding pattern ");
 2138        Text_shellsafe(patterns[i], xorriso->info_text, 1);
 2139        strcat(xorriso->info_text,
 2140               " : Working directory does not exist in ISO image");
 2141        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2142        ret= 0; goto ex;
 2143      }
 2144      if(!LIBISO_ISDIR((IsoNode *) dir)) {
 2145        sprintf(xorriso->info_text,
 2146            "Working directory path does not lead to a directory in ISO image");
 2147        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2148        ret= 0; goto ex;
 2149      }
 2150    }
 2151 
 2152    /* count the matches */
 2153    was_count= count;
 2154    ret= Xorriso_obtain_pattern_files_i(xorriso, "", dir, &count, NULL, 0,
 2155                                        mem, &dive_count, 1 | abs_adr);
 2156    if(ret<=0)
 2157      goto ex;
 2158    if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1 &&
 2159       !(flag & 8)) {
 2160      count++;
 2161      Xorriso_eval_nonmatch(xorriso, patterns[i], &nonconst_mismatches, mem, 0);
 2162    }
 2163  }
 2164 
 2165  ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches,
 2166                                num_patterns, patterns, (flag&1)|2);
 2167  if(ret<=0)
 2168    goto ex;
 2169  count+= extra_filec;
 2170  (*mem)+= extra_filec * sizeof(char *);
 2171  if(count<=0)
 2172    {ret= !!(flag & 8); goto ex;}
 2173  ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, !!(flag & 4));
 2174  if(ret<=0)
 2175    goto ex;
 2176  /* now store addresses */
 2177  for(i= 0; i<num_patterns; i++) {
 2178    ret=  Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 0);
 2179    if(ret<=0)
 2180      return(ret);
 2181    if(ret==2)
 2182      abs_adr= 4;
 2183 
 2184    was_filec= *filec;
 2185    ret= Xorriso_obtain_pattern_files_i(xorriso, "", dir, filec, *filev, count,
 2186                                        mem, &dive_count, abs_adr);
 2187    if(ret<=0)
 2188      goto ex;
 2189    if(was_filec == *filec && strcmp(patterns[i],"*")!=0 && (flag&3) != 1 &&
 2190       !(flag & 8)) {
 2191      (*filev)[*filec]= strdup(patterns[i]);
 2192      if((*filev)[*filec]==NULL) {
 2193        (*mem)= strlen(patterns[i])+1;
 2194        Xorriso_no_pattern_memory(xorriso, *mem, 0);
 2195        ret= -1; goto ex;
 2196      }
 2197      (*filec)++;
 2198    } 
 2199  }
 2200  ret= 1;
 2201 ex:;
 2202  if(ret<=0) {
 2203    Sfile_destroy_argv(&count, filev, 0);
 2204    *filec= 0;
 2205  }
 2206  return(ret);
 2207 }
 2208 
 2209 
 2210 int Xorriso__start_end_lbas(IsoNode *node,
 2211                             int *lba_count, int **start_lbas, int **end_lbas,
 2212                             off_t **section_sizes, off_t *size, int flag)
 2213 {
 2214  int section_count= 0, ret, i;
 2215  struct iso_file_section *sections= NULL;
 2216 
 2217  *lba_count= 0;
 2218  *start_lbas= *end_lbas= NULL;
 2219  *section_sizes= NULL;
 2220  *size= 0;
 2221  if(!LIBISO_ISREG(node))
 2222    return(0);
 2223  *size= iso_file_get_size((IsoFile *) node);
 2224  ret= iso_file_get_old_image_sections((IsoFile *) node, &section_count,
 2225                                       &sections, 0);
 2226  if(ret < 0)
 2227    {ret= -1; goto ex;}
 2228  if(ret != 1 || section_count <= 0)
 2229    {ret= 0; goto ex;}
 2230  *start_lbas= calloc(section_count, sizeof(int));
 2231  *end_lbas= calloc(section_count, sizeof(int));
 2232  *section_sizes= calloc(section_count, sizeof(off_t));
 2233  if(*start_lbas == NULL || *end_lbas == NULL || *section_sizes == NULL)
 2234    {ret= -1; goto ex;}
 2235  for(i= 0; i < section_count; i++) {
 2236    (*start_lbas)[i]= sections[i].block;
 2237    (*end_lbas)[i]= sections[i].block + sections[i].size / 2048 - 1;
 2238    if(sections[i].size % 2048)
 2239      (*end_lbas)[i]++;
 2240    (*section_sizes)[i]= sections[i].size;
 2241  }
 2242  *lba_count= section_count;
 2243  ret= 1;
 2244 ex:;
 2245  if(sections != NULL)
 2246    free((char *) sections);
 2247  if(ret <= 0) {
 2248    if((*start_lbas) != NULL)
 2249      free((char *) *start_lbas);
 2250    if((*end_lbas) != NULL)
 2251      free((char *) *end_lbas);
 2252    *start_lbas= *end_lbas= NULL;
 2253    *lba_count= 0;
 2254  }
 2255  return(ret);
 2256 }
 2257 
 2258 
 2259 int Xorriso__file_start_lba(IsoNode *node,
 2260                            int *lba, int flag)
 2261 {
 2262  int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, i, ret;
 2263  off_t size, *section_sizes= NULL;
 2264 
 2265  *lba= -1;
 2266  ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
 2267                               &section_sizes, &size, 0);
 2268  if(ret <= 0)
 2269    return(ret);
 2270  for(i= 0; i < lba_count; i++) {
 2271    if(*lba < 0 || start_lbas[i] < *lba)
 2272      *lba= start_lbas[i];
 2273  }
 2274  if(start_lbas != NULL)
 2275    free((char *) start_lbas);
 2276  if(end_lbas != NULL)
 2277    free((char *) end_lbas);
 2278  if(section_sizes != NULL)
 2279    free((char *) section_sizes);
 2280  if(*lba < 0)
 2281    return(0);
 2282  return(1);
 2283 }
 2284 
 2285 
 2286 /* flag bit0= examine sub directories rather than data files
 2287 */
 2288 int Xorriso_dir_disk_path(struct XorrisO *xorriso, IsoNode *dir_node,
 2289                           char disk_path[SfileadrL], int flag)
 2290 {
 2291  int ret;
 2292  char *npt;
 2293  IsoNode *node;
 2294  IsoDir *dir;
 2295  IsoDirIter *iter= NULL;
 2296 
 2297  dir= (IsoDir *) dir_node;
 2298  ret= iso_dir_get_children(dir, &iter);
 2299  if(ret<0) {
 2300    Xorriso_cannot_create_iter(xorriso, ret, 0);
 2301    {ret= -1; goto ex;}
 2302  }
 2303  while(1) {
 2304    ret= iso_dir_iter_next(iter, &node);
 2305    if(ret < 0) {
 2306      Xorriso_report_iso_error(xorriso, "", ret,
 2307                "Error when iterating over directory", 0, "FAILURE", 1);
 2308      ret= -1; goto ex;
 2309    }
 2310    if(ret == 0)
 2311  break;
 2312      
 2313    if(LIBISO_ISDIR(node) && (flag & 1)) {
 2314      ret= Xorriso_dir_disk_path(xorriso, node, disk_path, flag);
 2315      if(ret < 0)
 2316        goto ex;
 2317      if(ret == 0)
 2318  continue;
 2319    } else if(LIBISO_ISREG(node) && !(flag & 1)) {
 2320      ret= Xorriso_retrieve_disk_path(xorriso, node, disk_path, 0);
 2321      if(ret < 0)
 2322        goto ex;
 2323      if(ret == 0)
 2324  continue;
 2325    } else
 2326  continue;
 2327    /* Use its parent dir as answer */
 2328    npt= strrchr(disk_path, '/');
 2329    if(npt == NULL || npt == disk_path)
 2330      strcpy(disk_path, "/");
 2331    else
 2332      *npt= 0;
 2333    ret= 1; goto ex;
 2334  }
 2335  if(!(flag & 1))
 2336    ret= Xorriso_dir_disk_path(xorriso, dir_node, disk_path, 1);
 2337  else
 2338    ret= 0;
 2339 ex:
 2340  if(iter != NULL)
 2341    iso_dir_iter_free(iter);
 2342  return(ret);
 2343 }
 2344 
 2345 
 2346 int Xorriso_retrieve_disk_path(struct XorrisO *xorriso, IsoNode *node,
 2347                                char disk_path[SfileadrL], int flag)
 2348 {
 2349  IsoFile *file;
 2350  IsoStream *stream= NULL, *input_stream;
 2351  char type_text[80], *source_path = NULL;
 2352  int ret;
 2353 
 2354  if(LIBISO_ISDIR(node)) {
 2355    ret= Xorriso_dir_disk_path(xorriso, node, disk_path, 0);
 2356    return(ret);
 2357  }
 2358 
 2359  if(!LIBISO_ISREG(node)) 
 2360    return(0);
 2361 
 2362  /* Obtain most fundamental input stream */
 2363  file= (IsoFile *) node;
 2364  input_stream= iso_file_get_stream(file);
 2365  if(input_stream == NULL)
 2366    return(0);
 2367  while(1) {
 2368    stream= input_stream;
 2369    input_stream= iso_stream_get_input_stream(stream, 0);
 2370    if(input_stream == NULL)
 2371  break;
 2372  }
 2373 
 2374  /* Obtain disk path if applicable */
 2375  type_text[0]= 0;
 2376  Xorriso_stream_type(xorriso, node, stream, type_text, 0);
 2377  if(strcmp(type_text, "disk") != 0 && strcmp(type_text, "cout") != 0)
 2378    return(0); /* among othersi rejected: "image" */
 2379  source_path= iso_stream_get_source_path(stream, 0);
 2380  if(source_path == NULL)
 2381    return(0);
 2382  if(strlen(source_path) >= SfileadrL) {
 2383    free(source_path);
 2384    return(0);
 2385  }
 2386  strcpy(disk_path, source_path);
 2387  free(source_path);
 2388  return(1);
 2389 }
 2390 
 2391 
 2392 /* @param flag bit0= show numbers from iso_stream_get_id
 2393  */
 2394 int Xorriso_show_stream(struct XorrisO *xorriso, void *in_node,
 2395                         char *path, int flag)
 2396 {
 2397  int ret;
 2398  IsoNode *node;
 2399  IsoFile *file;
 2400  IsoStream *stream= NULL, *input_stream;
 2401  IsoExternalFilterCommand *cmd;
 2402  char type_text[80], *source_path= NULL;
 2403  unsigned int fs_id;
 2404  dev_t dev_id;
 2405  ino_t ino_id;
 2406 
 2407  node= (IsoNode *) in_node;
 2408  if(node == NULL) {
 2409    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2410    if(ret <= 0)
 2411      goto ex;
 2412  }
 2413  if(!LIBISO_ISREG(node)) 
 2414    {ret= 2; goto ex;}
 2415  file= (IsoFile *) node;
 2416  input_stream= iso_file_get_stream(file);
 2417  Text_shellsafe(path, xorriso->result_line, 0);
 2418  while(1) {
 2419    stream= input_stream;
 2420    input_stream= iso_stream_get_input_stream(stream, 0);
 2421    if(input_stream == NULL)
 2422  break;
 2423    strcat(xorriso->result_line, " < ");
 2424    Xorriso_stream_type(xorriso, node, stream, type_text, 0);
 2425    strcat(xorriso->result_line, type_text);
 2426    if(flag & 1) {
 2427      iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
 2428      sprintf(xorriso->result_line + strlen(xorriso->result_line),
 2429              "[%u,%lu,%lu]", fs_id, (unsigned long) dev_id,
 2430                              (unsigned long) ino_id);
 2431    }
 2432    ret= iso_stream_get_external_filter(stream, &cmd, 0);
 2433    if(ret < 0) {
 2434      Xorriso_process_msg_queues(xorriso,0);
 2435      Xorriso_report_iso_error(xorriso, "", ret,
 2436                "Error when inquiring filter command of node", 0, "FAILURE", 1);
 2437      ret= 0; goto ex;
 2438    }
 2439    if(ret > 0) {
 2440      strcat(xorriso->result_line, ":");
 2441      Text_shellsafe(cmd->name, xorriso->result_line, 1);
 2442    }
 2443    if(strlen(xorriso->result_line) > SfileadrL) {
 2444      Xorriso_result(xorriso, 0);
 2445      xorriso->result_line[0]= 0;
 2446    }
 2447  }
 2448  strcat(xorriso->result_line, " < ");
 2449  Xorriso_stream_type(xorriso, node, stream, type_text, 0);
 2450  strcat(xorriso->result_line, type_text);
 2451  if(flag & 1) {
 2452    iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
 2453    sprintf(xorriso->result_line + strlen(xorriso->result_line), "[%u,%lu,%lu]",
 2454            fs_id, (unsigned long) dev_id, (unsigned long) ino_id);
 2455  }
 2456 
 2457  source_path= iso_stream_get_source_path(stream, 0);
 2458  if(source_path != NULL) {
 2459    strcat(xorriso->result_line, ":");
 2460    Text_shellsafe(source_path, xorriso->result_line, 1);
 2461  }
 2462  
 2463  strcat(xorriso->result_line, "\n");
 2464  Xorriso_result(xorriso, 0);
 2465  ret= 1;
 2466 ex:;
 2467  if(source_path != NULL)
 2468    free(source_path);
 2469  return(ret); 
 2470 }
 2471 
 2472 
 2473 /* @param damage_start Returns first damaged byte address
 2474    @param damage_end   Returns first byte address after last damaged byte
 2475    @return <0 error, 0=undamaged , 1=damaged
 2476 */
 2477 int Xorriso_file_eval_damage(struct XorrisO *xorriso, IsoNode *node,
 2478                              off_t *damage_start, off_t *damage_end,
 2479                              int flag)
 2480 {
 2481  int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, sect;
 2482  int i, sectors, sector_size, ret;
 2483  off_t sect_base= 0, size= 0, byte, *section_sizes= NULL;
 2484  struct SectorbitmaP *map;
 2485 
 2486  *damage_start= *damage_end= -1;
 2487  map= xorriso->in_sector_map;
 2488  if(map == NULL)
 2489    return(0);
 2490  Sectorbitmap_get_layout(map, &sectors, &sector_size, 0);
 2491  sector_size/= 2048;
 2492 
 2493  ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
 2494                               &section_sizes, &size, 0);
 2495  if(ret <= 0) {
 2496    Xorriso_process_msg_queues(xorriso, 0);
 2497    return(ret);
 2498  }
 2499  for(sect= 0; sect < lba_count; sect++) {
 2500    for(i= start_lbas[sect]; i <= end_lbas[sect]; i+= sector_size) {
 2501      if(Sectorbitmap_is_set(map, i / sector_size, 0) == 0) {
 2502        byte= ((off_t) 2048) * ((off_t) (i - start_lbas[sect])) + sect_base;
 2503        if(*damage_start < 0 || byte < *damage_start)
 2504          *damage_start= byte;
 2505        if(byte + (off_t) 2048 > *damage_end)
 2506          *damage_end= byte + (off_t) 2048;
 2507      }
 2508    }
 2509    sect_base+= ((off_t) 2048) *
 2510                ((off_t) (end_lbas[sect] - start_lbas[sect] + 1));
 2511  }
 2512  if(*damage_end > size)
 2513    *damage_end= size;
 2514  if(start_lbas != NULL)
 2515    free((char *) start_lbas);
 2516  if(end_lbas != NULL)
 2517    free((char *) end_lbas);
 2518  if(section_sizes != NULL)
 2519    free((char *) section_sizes);
 2520  if(*damage_start < 0)
 2521    return(0);
 2522  return(1);
 2523 }
 2524 
 2525 
 2526 /* @param flag  bit0= report_sections : section size rather than total size
 2527                 bit1= last_data_file_block : looking for highest data file block
 2528 */
 2529 int Xorriso_report_lba(struct XorrisO *xorriso, char *show_path,
 2530                        IsoNode *node, uint32_t *last_block, int flag)
 2531 {
 2532  int ret, *start_lbas= NULL, *end_lbas= NULL, lba_count, i;
 2533  off_t size, *section_sizes= NULL;
 2534 
 2535  ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
 2536                               &section_sizes, &size, 0);
 2537  if(ret < 0) {
 2538    Xorriso_process_msg_queues(xorriso, 0);
 2539    {ret= -1; goto ex;}
 2540  }
 2541  if(ret == 0)
 2542    {ret= 1; goto ex;} /* it is ok to ignore other types */
 2543  for(i= 0; i < lba_count; i++) {
 2544    if(flag & 1)
 2545      size= section_sizes[i];
 2546    if(flag & 2) {
 2547      if(end_lbas[i] > 0 && (uint32_t) end_lbas[i] > *last_block)
 2548        *last_block= end_lbas[i];
 2549    } else {
 2550      sprintf(xorriso->result_line,
 2551              "File data lba: %2d , %8d , %8d , %8.f , ",
 2552              i, start_lbas[i], end_lbas[i] + 1 - start_lbas[i], (double) size);
 2553      Text_shellsafe(show_path, xorriso->result_line, 1);
 2554      strcat(xorriso->result_line, "\n");
 2555      Xorriso_result(xorriso, 0);
 2556    }
 2557  }
 2558  ret= 1;
 2559 ex:;
 2560  if(start_lbas != NULL)
 2561    free((char *) start_lbas);
 2562  if(end_lbas != NULL)
 2563    free((char *) end_lbas);
 2564  if(section_sizes != NULL)
 2565    free((char *) section_sizes);
 2566  return(ret);
 2567 }
 2568 
 2569 
 2570 int Xorriso_report_damage(struct XorrisO *xorriso, char *show_path,
 2571                           IsoNode *node, int flag)
 2572 {
 2573  int ret;
 2574  off_t size= 0, damage_start, damage_end;
 2575 
 2576  ret= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end, 0);
 2577  if(ret < 0)
 2578    return(0);
 2579 
 2580  if(LIBISO_ISREG(node))
 2581    size= iso_file_get_size((IsoFile *) node);
 2582  if(ret > 0) {
 2583    sprintf(xorriso->result_line, "File damaged : %8.f , %8.f , %8.f , ",
 2584            (double) damage_start, (double) (damage_end - damage_start) ,
 2585            (double) size);
 2586  } else {
 2587    sprintf(xorriso->result_line, "File seems ok: %8.f , %8.f , %8.f , ",
 2588            -1.0, -1.0, (double) size);
 2589  }
 2590  Text_shellsafe(show_path, xorriso->result_line, 1);
 2591  strcat(xorriso->result_line, "\n");
 2592  Xorriso_result(xorriso, 0);
 2593  return(1);
 2594 }
 2595 
 2596 
 2597 /* @param flag bit0= do not accept hln_targets[i] != NULL as *node_idx
 2598                bit1= use *node_idx as found index rather than searching it
 2599                bit2= with bit1: use xorriso->node_array rather than hln_array
 2600 */
 2601 int Xorriso_search_hardlinks(struct XorrisO *xorriso, IsoNode *node,
 2602                              int *node_idx, int *min_hl, int *max_hl, int flag)
 2603 {
 2604  int idx, ret, i, node_count;
 2605  void *np, **node_array;
 2606 
 2607  node_array= xorriso->hln_array;
 2608  node_count= xorriso->hln_count;
 2609  *min_hl= *max_hl= -1;
 2610  np= node;
 2611  if(flag & 2) {
 2612    idx= *node_idx;
 2613    if(flag & 4) {
 2614      node_array= xorriso->node_array;
 2615      node_count= xorriso->node_counter;
 2616    }
 2617  } else {
 2618    *node_idx= -1;
 2619    ret= Xorriso_search_in_hln_array(xorriso, np, &idx, 0);
 2620    if(ret <= 0)
 2621      return(ret);
 2622  }
 2623  for(i= idx - 1; i >= 0 ; i--)
 2624    if(Xorriso__findi_sorted_ino_cmp(&(node_array[i]), &np) != 0)
 2625  break;
 2626  *min_hl= i + 1;
 2627  for(i= idx + 1; i < node_count; i++) 
 2628    if(Xorriso__findi_sorted_ino_cmp(&(node_array[i]), &np) != 0)
 2629  break;
 2630  *max_hl= i - 1;
 2631 
 2632  /* Search for *node_idx */
 2633  if(flag & 2)
 2634    return(1);
 2635  for(i= *min_hl; i <= *max_hl; i++)
 2636    if(node_array[i] == np) {
 2637      if((flag & 1) && xorriso->hln_targets != NULL && !(flag & 4))
 2638        if(xorriso->hln_targets[i] != NULL)
 2639  continue;
 2640      *node_idx= i;
 2641  break;
 2642    }
 2643  return(1);
 2644 }
 2645 
 2646 
 2647 /* @param flag bit0=do not complain about non existent node
 2648                bit1= do not try to find truncated name first
 2649  */
 2650 int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
 2651                            char *path, IsoNode **node, int flag)
 2652 {
 2653  int ret;
 2654  char *path_pt;
 2655 
 2656  path_pt= path;
 2657  if(path[0]==0)
 2658    path_pt= "/";
 2659  if(volume == NULL) {
 2660    ret= Xorriso_get_volume(xorriso, &volume, 0);
 2661    if(ret <= 0)
 2662      return(ret);
 2663  }
 2664  *node= NULL;
 2665  ret= 2;
 2666  if(!(flag & 2))
 2667    ret= iso_image_path_to_node(volume, path_pt, node);
 2668  if(ret == 2)
 2669    ret= iso_tree_path_to_node(volume, path_pt, node);
 2670  Xorriso_process_msg_queues(xorriso,0);
 2671  if(ret<=0 || (*node)==NULL) {
 2672    if(!(flag&1)) {
 2673      sprintf(xorriso->info_text, "Cannot find path ");
 2674      Text_shellsafe(path_pt, xorriso->info_text, 1);
 2675      strcat(xorriso->info_text, " in loaded ISO image");
 2676      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2677    }
 2678    return(0);
 2679  }
 2680  return(1);
 2681 }
 2682 
 2683 
 2684 /* @param flag bit0=do not complain about non existent node
 2685                bit1= do not try to find truncated name first
 2686  */
 2687 int Xorriso_dir_from_path(struct XorrisO *xorriso, char *purpose,
 2688                           char *path, IsoDir **dir_node, int flag)
 2689 {
 2690  IsoImage *volume;
 2691  IsoNode *node;
 2692  int ret, is_dir= 0;
 2693 
 2694  ret= Xorriso_get_volume(xorriso, &volume, 0);
 2695  if(ret<=0)
 2696    return(ret);
 2697 
 2698  ret= Xorriso_node_from_path(xorriso, volume, path, &node, flag & 3);
 2699  if(ret<=0)
 2700    goto wdi_is_not_a_dir;
 2701  if(LIBISO_ISDIR(node))
 2702    is_dir= 1;
 2703  if(!is_dir) {
 2704 wdi_is_not_a_dir:;
 2705    sprintf(xorriso->info_text,
 2706            "%s path does not lead to a directory in ISO image", purpose); 
 2707    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2708    return(0);
 2709  }
 2710  *dir_node= (IsoDir *) node;
 2711  return(1);
 2712 }
 2713 
 2714 
 2715 /*
 2716   @param flag bit0= do not remove leading slash
 2717               bit1= append flatly to result_line and put out
 2718 */
 2719 int Xorriso_getfname(struct XorrisO *xorriso, char *path, int flag)
 2720 {
 2721  int ret, path_offset= 0, bsl_mem;
 2722  char *bsl_path= NULL;
 2723 
 2724  if(path[0] == '/' && !(flag & 1))
 2725    path_offset= 1;
 2726 
 2727  /* backslash escaped path rather than shellsafe path */
 2728  ret= Sfile_bsl_encoder(&bsl_path, path + path_offset,
 2729                         strlen(path + path_offset), 8);
 2730  if(ret <= 0)
 2731    return(-1);
 2732  if(flag & 2) {
 2733    sprintf(xorriso->result_line + strlen(xorriso->result_line),
 2734            "%s\n", bsl_path[0] ? bsl_path : ".");
 2735  } else {
 2736    sprintf(xorriso->result_line, "# file: %s\n", bsl_path[0] ? bsl_path : ".");
 2737  }
 2738  free(bsl_path);
 2739  bsl_path= NULL;
 2740  /* temporarily disable -backslash_codes with result output */
 2741  bsl_mem= xorriso->bsl_interpretation;
 2742  xorriso->bsl_interpretation= 0;
 2743  Xorriso_result(xorriso, 0);
 2744  xorriso->bsl_interpretation= bsl_mem;
 2745  return(1);
 2746 }
 2747 
 2748 
 2749 int Xorriso_is_plain_image_file(struct XorrisO *xorriso, void *in_node,
 2750                                 char *path, int flag)
 2751 {
 2752  int ret, lba;
 2753  IsoStream *stream;
 2754  IsoNode *node;
 2755 
 2756  node= (IsoNode *) in_node;
 2757  if(node == NULL) {
 2758    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
 2759    if(ret<=0)
 2760      return(ret);
 2761  }
 2762 
 2763  ret= Xorriso__file_start_lba(node, &lba, 0);
 2764  if(ret > 0) { /* Stream source is from loaded image */
 2765    stream= iso_file_get_stream((IsoFile *) node);
 2766    if(stream != NULL)
 2767      if(iso_stream_get_input_stream(stream, 0) == NULL)
 2768        return(1);
 2769  }
 2770  return(0);
 2771 }
 2772