"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.6/xorriso/disk_ops.c" (15 Mar 2023, 65413 Bytes) of package /linux/misc/libisoburn-1.5.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "disk_ops.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.4_vs_1.5.6.

    1 
    2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2023 Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains the implementation of actions on onjects of disk
    9    filesystems.
   10 */
   11 
   12 #ifdef HAVE_CONFIG_H
   13 #include "../config.h"
   14 #endif
   15 
   16 #include <ctype.h>
   17 #include <sys/types.h>
   18 #include <unistd.h>
   19 #include <stdlib.h>
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <sys/stat.h>
   23 #include <sys/time.h>
   24 #include <time.h>
   25 #include <fcntl.h>
   26 #include <errno.h>
   27 #include <pwd.h>
   28 #include <grp.h>
   29 
   30 /* O_BINARY is needed for Cygwin but undefined elsewhere */
   31 #ifndef O_BINARY
   32 #define O_BINARY 0
   33 #endif
   34 
   35 
   36 #include "xorriso.h"
   37 #include "xorriso_private.h"
   38 #include "xorrisoburn.h"
   39 
   40 
   41 
   42 /* @param flag bit0= simple readlink(): no normalization, no multi-hop
   43                bit1= this is potentially a recursion
   44 */
   45 int Xorriso_resolve_link(struct XorrisO *xorriso, char *link_path,
   46                          char result_path[SfileadrL], int flag)
   47 {
   48  ssize_t l;
   49  struct stat stbuf;
   50  int link_count= 0, ret, show_errno= 0;
   51  char *buf= NULL, *dirbuf= NULL, *lpt, *spt;
   52  static int link_limit= 100;
   53 
   54  if(flag & 1) {
   55    xorriso->resolve_link_rec_count++;
   56    if(xorriso->resolve_link_rec_count > xorriso->resolve_link_rec_limit) {
   57      Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
   58      sprintf(xorriso->info_text, "Too many link recursions before : ");
   59      Text_shellsafe(link_path, xorriso->info_text, 1);
   60      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
   61                          "FAILURE", 0);
   62      {ret= 0; goto ex;}
   63    }
   64  } else
   65    xorriso->resolve_link_rec_count= 0;
   66 
   67  Xorriso_alloc_meM(buf, char, SfileadrL);
   68  Xorriso_alloc_meM(dirbuf, char, SfileadrL);
   69 
   70  if(!(flag&1))
   71    if(stat(link_path, &stbuf)==-1)
   72      if(errno==ELOOP) {
   73        show_errno= errno;
   74        goto too_many_hops;
   75      }
   76  lpt= link_path;
   77  while(1) {
   78    l= readlink(lpt, buf, SfileadrL-1);
   79    if(l==-1) {
   80 handle_error:;
   81      Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
   82      sprintf(xorriso->info_text, "Cannot obtain link target of : ");
   83      Text_shellsafe(link_path, xorriso->info_text, 1);
   84      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
   85 handle_abort:;
   86      if(strcmp(lpt, link_path)!=0) {
   87        sprintf(xorriso->info_text,
   88                "Problem occurred with intermediate path : ");
   89        Text_shellsafe(lpt, xorriso->info_text, 1);
   90        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   91      }
   92      {ret= 0; goto ex;}
   93    }
   94    buf[l]= 0;
   95    if(l==0) {
   96      Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
   97      sprintf(xorriso->info_text, "Empty link target with : ");
   98      Text_shellsafe(link_path, xorriso->info_text, 1);
   99      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  100      goto handle_abort;
  101    }
  102 
  103    if(flag&1) {
  104      strcpy(result_path, buf);
  105      {ret= 1; goto ex;}
  106    }
  107 
  108    /* normalize relative to disk_path */
  109    if(Sfile_str(dirbuf, lpt, 0)<=0)
  110      {ret= -1; goto ex;}
  111    while(1) {
  112      spt= strrchr(dirbuf,'/');
  113      if(spt!=NULL) {
  114        *spt= 0;
  115        if(*(spt+1)!=0)
  116    break;
  117      } else
  118    break;
  119    }
  120    ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4);
  121    if(ret<=0) {
  122      goto ex;
  123    }
  124 
  125    if(lstat(result_path, &stbuf)==-1) {
  126      lpt= result_path;
  127      goto handle_error;
  128    }
  129    if(!S_ISLNK(stbuf.st_mode))
  130  break;
  131    
  132    lpt= result_path;
  133    link_count++;
  134    if(link_count>link_limit) {
  135 too_many_hops:;
  136      Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
  137      sprintf(xorriso->info_text, "Too many link hops with : ");
  138      Text_shellsafe(link_path, xorriso->info_text, 1);
  139      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
  140                          "FAILURE", 0);
  141      {ret= 0; goto ex;}
  142    }
  143  }
  144  ret= 1;
  145 ex:;
  146  Xorriso_free_meM(buf);
  147  Xorriso_free_meM(dirbuf);
  148  if(xorriso->resolve_link_rec_count > 0)
  149    xorriso->resolve_link_rec_count--;
  150  return(ret);
  151 }
  152 
  153 
  154 int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string,
  155                               uid_t *uid, int flag)
  156 {
  157  double num= 0.0;
  158  char text[80];
  159  struct passwd *pwd;
  160 
  161  sscanf(uid_string, "%lf", &num);
  162  sprintf(text,"%.f",num);
  163  if(strcmp(text,uid_string)==0) {
  164    *uid= num;
  165    return(1);
  166  }
  167  pwd= getpwnam(uid_string);
  168  if(pwd==NULL) {
  169    sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string);
  170    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
  171    return(0);
  172  }
  173  *uid= pwd->pw_uid;
  174  return(1);
  175 }
  176 
  177 
  178 int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string,
  179                               gid_t *gid, int flag)
  180 {
  181  double num= 0.0;
  182  char text[80];
  183  struct group *grp;
  184 
  185  sscanf(gid_string, "%lf", &num);
  186  sprintf(text,"%.f",num);
  187  if(strcmp(text,gid_string)==0) {
  188    *gid= num;
  189    return(1);
  190  }
  191  grp= getgrnam(gid_string);
  192  if(grp==NULL) {
  193    sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string);
  194    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
  195    return(0);
  196  }
  197  *gid= grp->gr_gid;
  198  return(1);
  199 }
  200  
  201 
  202 int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode,
  203                               mode_t *mode_and, mode_t *mode_or, int flag)
  204 {
  205  int who_val= 0;
  206  char *mpt, *vpt, *opt;
  207  unsigned int num= 0;
  208  mode_t mode_val,mask;
  209 
  210  *mode_and= ~0;
  211  *mode_or= 0;
  212  if(mode[0]=='0') {
  213    *mode_and= 0;
  214    sscanf(mode,"%o",&num);
  215    *mode_or= num;
  216  } else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL
  217            || strchr(mode,'=')!=NULL) {
  218    /* [ugoa][+-][rwxst] */;
  219    for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) {
  220      if(*mpt==',')
  221        mpt++;
  222      if(strlen(mpt)<2)
  223        goto unrecognizable;
  224      who_val= 0;
  225      for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) {
  226        if(*vpt=='u')
  227          who_val|= 4;
  228        else if(*vpt=='g')
  229          who_val|= 2;
  230        else if(*vpt=='o')
  231          who_val|= 1;
  232        else if(*vpt=='a')
  233          who_val|= 7;
  234        else
  235          goto unrecognizable;
  236      }
  237      opt= vpt;
  238      mode_val= 0;
  239      for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) {
  240        if(*vpt=='r') {
  241          if(who_val&4)
  242            mode_val|= S_IRUSR;
  243          if(who_val&2)
  244            mode_val|= S_IRGRP;
  245          if(who_val&1)
  246            mode_val|= S_IROTH;
  247        } else if(*vpt=='w') {
  248          if(who_val&4)
  249            mode_val|= S_IWUSR;
  250          if(who_val&2)
  251            mode_val|= S_IWGRP;
  252          if(who_val&1)
  253            mode_val|= S_IWOTH;
  254        } else if(*vpt=='x') {
  255          if(who_val&4)
  256            mode_val|= S_IXUSR;
  257          if(who_val&2)
  258            mode_val|= S_IXGRP;
  259          if(who_val&1)
  260            mode_val|= S_IXOTH;
  261        } else if(*vpt=='s') {
  262          if(who_val&4)
  263            mode_val|= S_ISUID;
  264          if(who_val&2)
  265            mode_val|= S_ISGID;
  266        } else if(*vpt=='t') {
  267          if(who_val&1)
  268            mode_val|= S_ISVTX;
  269        } else
  270          goto unrecognizable;
  271      }
  272      if(*opt=='+') {
  273        (*mode_or)|= mode_val;
  274      } else if(*opt=='=') {
  275        mask= 0;
  276        if(who_val&1)
  277          mask|= S_IRWXO|S_ISVTX;
  278        if(who_val&2)
  279          mask|= S_IRWXG|S_ISGID;
  280        if(who_val&4)
  281          mask|= S_IRWXU|S_ISUID;
  282        (*mode_and)&= ~(mask);
  283        (*mode_or)= ((*mode_or) & ~mask) | mode_val;
  284      } else if(*opt=='-') {
  285        (*mode_or)&= ~mode_val;
  286        (*mode_and)&= ~mode_val;
  287      }
  288    }
  289  } else {
  290 unrecognizable:;
  291    sprintf(xorriso->info_text,
  292            "%s: Unrecognizable or faulty permission mode ", cmd);
  293    Text_shellsafe(mode, xorriso->info_text, 1);
  294    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
  295    return(0);
  296  }
  297  return(1);
  298 }
  299 
  300 
  301 /* @param flag bit0= for Xorriso_msgs_submit: use pager
  302                bit1= do not issue warnings
  303                bit2= warn about dangling link
  304                bit3= report sorry if dangling link
  305 */
  306 int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
  307                     struct LinkiteM **link_stack, struct stat *stbuf, int flag)
  308 {
  309  int ret;
  310  char *severity;
  311  struct LinkiteM *litm;
  312 
  313  if(*link_stack != NULL) {
  314    if(Linkitem_get_link_count(*link_stack, 0) >= xorriso->follow_link_limit) {
  315      sprintf(xorriso->info_text,
  316              "Too many symbolic links in single tree branch at : ");
  317      Text_shellsafe(link_path, xorriso->info_text, 1);
  318      if(!(flag&2))
  319        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1);
  320      return(0);
  321    }
  322  }
  323  ret= stat(link_path, stbuf);
  324  if(ret == -1) {
  325    if(flag & (4 | 8)) {
  326      if(flag & 8)
  327        severity= "SORRY";
  328      else
  329        severity= "WARNING";
  330      sprintf(xorriso->info_text, "Non-existing link target with : ");
  331      Text_shellsafe(link_path, xorriso->info_text, 1);
  332      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, severity,
  333                          flag & 1);
  334    }
  335    return(0);
  336  }
  337  ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0);
  338  if(ret>0) {
  339    sprintf(xorriso->info_text, "Detected symbolic link loop around : ");
  340    Text_shellsafe(link_path, xorriso->info_text, 1);
  341    if(!(flag&2))
  342      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1);
  343    return(0);
  344  }
  345  ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino,
  346                    *link_stack, 0);
  347  if(ret<=0) {
  348    sprintf(xorriso->info_text,
  349            "Cannot add new item to link loop prevention stack");
  350    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1);
  351    return(-1);
  352  }
  353  *link_stack= litm;
  354  return(1);
  355 }
  356 
  357 
  358 /* @param flag bit0= do not only sum up sizes but also print subdirs
  359                bit1= this is a recursion
  360                bit2= do not report result by Xorriso_result()
  361    @return <=0 error , 1 ok , 2 could not open directory
  362 */
  363 int Xorriso_show_dux_subs(struct XorrisO *xorriso,
  364                       char *abs_path, char *rel_path, off_t *size,
  365                       off_t boss_mem,
  366                       struct LinkiteM *link_stack,
  367                       int flag)
  368 {
  369  int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link;
  370  char **filev= NULL, *namept;
  371  off_t sub_size, report_size, mem= 0;
  372  struct DirseQ *dirseq= NULL;
  373  struct stat stbuf;
  374  dev_t dir_dev;
  375  struct LinkiteM *own_link_stack;
  376  char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL;
  377  
  378  own_link_stack= link_stack;
  379  namept= name;
  380  *size= 0;
  381 
  382  Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
  383  Xorriso_alloc_meM(path, char, SfileadrL);
  384  Xorriso_alloc_meM(show_path, char, SfileadrL);
  385  Xorriso_alloc_meM(name, char, SfileadrL);
  386 
  387  if(lstat(abs_path, &stbuf)==-1)
  388    {ret= 2; goto ex;}
  389  dir_dev= stbuf.st_dev;
  390  if(S_ISLNK(stbuf.st_mode)) {
  391    if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2))))
  392      {ret= 2; goto ex;}
  393    if(stat(abs_path, &stbuf)==-1)
  394      {ret= 2; goto ex;}
  395    if(dir_dev != stbuf.st_dev &&
  396       !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2))))
  397      {ret= 2; goto ex;}
  398  }
  399  ret= Dirseq_new(&dirseq, abs_path, 1);
  400  if(ret<0) {
  401    sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
  402    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  403    {ret= -1; goto ex;}
  404  }
  405  if(ret==0)
  406    {ret= 2; goto ex;}
  407 
  408  while(1) {
  409    Linkitem_reset_stack(&own_link_stack, link_stack, 0);
  410    ret= Dirseq_next_adr(dirseq,name,0);
  411    if(ret<0)
  412      goto ex;
  413    if(ret==0)
  414  break;
  415 
  416    sub_size= 0;
  417    strcpy(show_path, rel_path);
  418    if(Sfile_add_to_path(show_path, name, 0)<=0)
  419        goto much_too_long;
  420 
  421    strcpy(path, abs_path);
  422    if(Sfile_add_to_path(path, name, 0)<=0) {
  423 much_too_long:;
  424      Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
  425      {ret= -1; goto ex;}
  426    }
  427    no_dive= 0;
  428 
  429    ret= lstat(path, &stbuf);
  430    if(ret==-1)
  431  continue;
  432    is_link= S_ISLNK(stbuf.st_mode);
  433    if(is_link && xorriso->do_follow_links) {
  434      ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
  435      if(ret<0)
  436        {ret= -1; goto ex;}
  437      if(ret!=1)
  438        no_dive= 1;
  439    }
  440    if(!S_ISDIR(stbuf.st_mode))
  441      no_dive= 1;
  442    if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
  443      no_dive= 1;
  444    if(!no_dive) {
  445      filec++;
  446      l= strlen(rel_path)+1;
  447      mem+= l;
  448      if(l % sizeof(char *))
  449        mem+= sizeof(char *)-(l % sizeof(char *));
  450      if(flag&1) /* diving and counting is done further below */
  451  continue;
  452      ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem,
  453                                 own_link_stack,2);
  454      if(ret<0)
  455        goto ex;
  456      if(ret==0)
  457  continue;
  458    }
  459    
  460 /*
  461    sub_size+= stbuf.st_size+strlen(name)+1;
  462 */
  463    sub_size+= stbuf.st_size+2048;
  464    if(sub_size>0)
  465      (*size)+= sub_size;
  466  }
  467 
  468  if(filec<=0 || !(flag&1))
  469    {ret= 1; goto ex;}
  470 
  471  /* Try to get a sorted list of directory names */
  472  mem+= (filec+1)*sizeof(char *);
  473  ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
  474  if(ret<0)
  475    goto ex;
  476  Dirseq_rewind(dirseq, 0);
  477  if(ret==0) {
  478 no_sort_possible:;
  479    no_sort= 1;
  480  } else {
  481    filev= (char **) calloc(filec+1, sizeof(char *));
  482    if(filev==NULL)
  483      goto no_sort_possible;
  484    else {
  485      for(i= 0; i<filec; i++)
  486        filev[i]= NULL;
  487      fc= 0;
  488      while(1) {
  489        ret= Dirseq_next_adr(dirseq,name,0);
  490        if(ret<0)
  491          goto ex;
  492        if(ret==0)
  493      break;
  494        strcpy(path, abs_path);
  495        if(Sfile_add_to_path(path, name, 0)<=0)
  496          goto much_too_long;
  497 
  498        ret= lstat(path,&stbuf);
  499        if(ret==-1)
  500      continue;
  501        is_link= S_ISLNK(stbuf.st_mode);
  502        if(is_link && xorriso->do_follow_links) {
  503          ret= stat(path,&stbuf);
  504          if(ret==-1)
  505      continue;
  506        }
  507        if(!S_ISDIR(stbuf.st_mode))
  508      continue;
  509        if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
  510      continue;
  511 
  512        if(fc>=filec) { /* Number of files changed (or programming error) */
  513 revoke_sorting:;
  514          for(j=0; j<fc; j++)
  515            free((char *) filev[j]);
  516          free((char *) filev);
  517          filev= NULL;
  518          goto no_sort_possible;
  519        }
  520 
  521        filev[fc]= strdup(name);
  522        if(filev[fc]==NULL)
  523          goto revoke_sorting;
  524        fc++;
  525      }
  526      filec= fc;
  527      if(filec>1)
  528        Sort_argv(filec, filev, 0);
  529    }
  530  }
  531 
  532  for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
  533    Linkitem_reset_stack(&own_link_stack, link_stack, 0);
  534    if(no_sort) {
  535      ret= Dirseq_next_adr(dirseq,name,0);
  536      if(ret<0)
  537        goto ex;
  538      if(ret==0)
  539  break;
  540    } else
  541      namept= filev[i];
  542 
  543    sub_size= 0;
  544    strcpy(show_path, rel_path);
  545    if(Sfile_add_to_path(show_path, namept, 0)<=0)
  546      goto much_too_long;
  547    strcpy(path, abs_path);
  548    if(Sfile_add_to_path(path, namept, 0)<=0)
  549      goto much_too_long;
  550    no_dive= 0;
  551 
  552    ret= lstat(path,&stbuf);
  553    if(ret==-1)
  554  continue;
  555    is_link= S_ISLNK(stbuf.st_mode);
  556    if(is_link && xorriso->do_follow_links) {
  557      ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
  558      if(ret<0)
  559        {ret= -1; goto ex;}
  560      if(ret!=1)
  561  continue;
  562    }
  563    if(!S_ISDIR(stbuf.st_mode))
  564  continue;
  565    if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) {
  566      ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size,
  567                                 boss_mem+mem, own_link_stack, 2|(flag&1));
  568      if(ret<0)
  569        goto ex;
  570    }
  571 
  572 /*
  573    sub_size+= stbuf.st_size+strlen(namept)+1;
  574 */
  575    sub_size+= stbuf.st_size+2048;
  576    if(sub_size>0)
  577      (*size)+= sub_size;
  578    report_size= sub_size/1024;
  579    if(report_size*1024<sub_size)
  580       report_size++;
  581    if(!(flag & 4)) {
  582      if(xorriso->sh_style_result)
  583        sprintf(xorriso->result_line, "%-7.f ",(double) (report_size));
  584      else
  585        sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
  586      sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
  587              Xorriso_esc_filepath(xorriso,show_path, sfe, 0));
  588      Xorriso_result(xorriso, 0);
  589    }
  590  }
  591 
  592  ret= 1;
  593 ex:;
  594  Xorriso_free_meM(sfe);
  595  Xorriso_free_meM(path);
  596  Xorriso_free_meM(show_path);
  597  Xorriso_free_meM(name);
  598  Linkitem_reset_stack(&own_link_stack, link_stack, 0);
  599  Dirseq_destroy(&dirseq, 0);
  600  if(filev!=NULL) {
  601    for(i=0; i<filec; i++)
  602      if(filev[i]!=NULL)
  603        free((char *) filev[i]);
  604    free((char *) filev);
  605  }
  606  return(ret);
  607 }
  608 
  609 
  610 /* @param flag   bit1= add '+' to perms
  611                  bit2-7: hidden_state :
  612                    bit2= hide in ISO/RR
  613                    bit3= hide in Joliet
  614                    bit4= hide in HFS+
  615 */
  616 int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag)
  617 {
  618  int hidden_state;
  619 
  620  strcpy(perms,"--------- ");
  621  if(st_mode&S_IRUSR) perms[0]= 'r';
  622  if(st_mode&S_IWUSR) perms[1]= 'w';
  623  if(st_mode&S_IXUSR) perms[2]= 'x';
  624  if(st_mode&S_ISUID) {
  625    if(st_mode&S_IXUSR)
  626      perms[2]= 's';
  627    else
  628      perms[2]= 'S';
  629  }
  630  if(st_mode&S_IRGRP) perms[3]= 'r';
  631  if(st_mode&S_IWGRP) perms[4]= 'w';
  632  if(st_mode&S_IXGRP) perms[5]= 'x';
  633  if(st_mode&S_ISGID) {
  634    if(st_mode&S_IXGRP)
  635      perms[5]= 's';
  636    else
  637      perms[5]= 'S';
  638  }
  639  if(st_mode&S_IROTH) perms[6]= 'r';
  640  if(st_mode&S_IWOTH) perms[7]= 'w';
  641  if(st_mode&S_IXOTH) perms[8]= 'x';
  642  if(st_mode&S_ISVTX) {
  643    if(st_mode&S_IXOTH)
  644      perms[8]= 't';
  645    else
  646      perms[8]= 'T';
  647  }
  648 
  649  hidden_state= (flag >> 2) & 63;
  650  if(hidden_state == 1)
  651    perms[9]= 'I';
  652  else if(hidden_state == 2)
  653    perms[9]= 'J';
  654  else if(hidden_state == 4)
  655    perms[9]= 'A';
  656  else if(hidden_state)
  657    perms[9]= 'H';
  658  if(flag & 2) {
  659    if(hidden_state)
  660      perms[9]= tolower(perms[9]);
  661    else
  662      perms[9]= '+';
  663  }
  664  return(1);
  665 }
  666 
  667 
  668 /* @param flag bit0= recognize Xorriso_IFBOOT as file type
  669                bit1= add '+' to perms
  670                bit2-7: hidden_state :
  671                   bit2= hide in ISO/RR
  672                   bit3= hide in Joliet
  673                   bit4= hide in HFS+
  674 */
  675 int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag)
  676 {
  677  int show_major_minor= 0, high_shift= 0, high_mask= 0;
  678  char *rpt, perms[11], mm_text[80];
  679  mode_t st_mode;
  680  dev_t dev, major, minor;
  681 
  682  rpt= xorriso->result_line;
  683  rpt[0]= 0;
  684  st_mode= stbuf->st_mode;
  685 
  686  if(S_ISDIR(st_mode))
  687    strcat(rpt, "d");
  688  else if(S_ISREG(st_mode)) {
  689    strcat(rpt, "-");
  690  } else if(S_ISLNK(st_mode))
  691    strcat(rpt, "l");
  692  else if(S_ISBLK(st_mode)) {
  693    strcat(rpt, "b");
  694    show_major_minor= 1;
  695  } else if(S_ISCHR(st_mode)) {
  696    strcat(rpt, "c");
  697    show_major_minor= 1;
  698  } else if(S_ISFIFO(st_mode))
  699    strcat(rpt, "p");
  700  else if(S_ISSOCK(st_mode))
  701    strcat(rpt, "s");
  702  else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT)
  703    strcat(rpt, "e");
  704  else
  705    strcat(rpt, "?");
  706 
  707  Xorriso__mode_to_perms(st_mode, perms, flag & (2 | 252));
  708  strcat(rpt, perms);
  709 
  710  sprintf(rpt+strlen(rpt)," %3u ",(unsigned int) stbuf->st_nlink);
  711 
  712  sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid);
  713  sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid);
  714  if(show_major_minor) {
  715    dev= stbuf->st_rdev;
  716 
  717    /* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor() 
  718       >>> but this looks as if it should go to some system dependency
  719       >>> in FreeBSD dev_t is 32 bit
  720    */
  721    if(sizeof(dev_t) > 4) {
  722      high_shift= 32;
  723      high_mask= ~0xfff;
  724    }
  725    major= (((dev >> 8) & 0xfff) |
  726            ((unsigned int) (dev >> high_shift) & high_mask))
  727           & 0xffffffff;
  728    minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff;
  729 
  730    sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor);
  731    sprintf(rpt+strlen(rpt), "%8s ", mm_text);
  732  } else
  733    sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size);
  734 
  735  Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0);
  736  strcat(rpt, " ");
  737 
  738  return(1);
  739 }
  740 
  741 
  742 struct DirentrY {
  743  char *adr;
  744  struct DirentrY *next;
  745 };
  746 
  747 
  748 int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path,
  749                          int *filec, char ***filev, off_t boss_mem, int flag)
  750 {
  751  int count= 0, ret;
  752  char *name= NULL;
  753  struct DirseQ *dirseq= NULL;
  754  off_t mem;
  755  struct DirentrY *last= NULL, *current= NULL;
  756 
  757  Xorriso_alloc_meM(name, char, SfileadrL);
  758 
  759  *filec= 0;
  760  *filev= NULL;
  761  mem= boss_mem;
  762  ret= Dirseq_new(&dirseq, dir_path, 1);
  763  if(ret<=0)
  764    goto ex;
  765  while(1) { /* loop over directory content */
  766    ret= Dirseq_next_adr(dirseq,name,0);
  767    if(ret==0)
  768  break;
  769    if(ret<0)
  770      goto ex;
  771    mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *);
  772    if(mem>xorriso->temp_mem_limit)
  773      {ret= 0; goto ex;}
  774 
  775    current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY));
  776    if(current==NULL) {
  777      Xorriso_no_malloc_memory(xorriso, NULL, 0);
  778      {ret= -1; goto ex;}
  779    }
  780    current->adr= NULL;
  781    current->next= last;
  782    last= current;
  783    last->adr= strdup(name);
  784    if(last->adr==NULL) {
  785      Xorriso_no_malloc_memory(xorriso, NULL, 0);
  786      {ret= -1; goto ex;}
  787    }
  788    count++;
  789  }
  790  *filec= count;
  791  if(count==0)
  792    {ret= 1; goto ex;}
  793  (*filev)= (char **) calloc(count, sizeof(char *));
  794  if(*filev==NULL) {
  795    Xorriso_no_malloc_memory(xorriso, NULL, 0);
  796    {ret= -1; goto ex; }
  797  }
  798  count= 0;
  799  for(current= last; current!=NULL; current= last) {
  800    last= current->next;
  801    (*filev)[count++]= current->adr;
  802    free((char *) current);
  803  }
  804  Sort_argv(*filec, *filev, 0);
  805  ret= 1; 
  806 ex:;
  807  for(current= last; current!=NULL; current= last) {
  808    last= current->next;
  809    free(current->adr);
  810    free((char *) current);
  811  }
  812  Xorriso_free_meM(name);
  813  Dirseq_destroy(&dirseq, 0);
  814  return(ret);
  815 }
  816 
  817 
  818 /* @param flag bit0= long format
  819                bit1= do not print count of nodes
  820                bit2= du format
  821                bit3= print directories as themselves (ls -d)
  822 */
  823 int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
  824                       int filec, char **filev, off_t boss_mem, int flag)
  825 {
  826  int i, ret, was_error= 0, dfilec= 0, pass, passes;
  827  char *path= NULL, *acl_text= NULL;
  828  char *rpt, *link_target= NULL, **dfilev= NULL;
  829  off_t size;
  830  struct stat stbuf;
  831 
  832  Xorriso_alloc_meM(path, char, SfileadrL);
  833  Xorriso_alloc_meM(link_target, char, SfileadrL);
  834 
  835  rpt= xorriso->result_line;
  836 
  837  Sort_argv(filec, filev, 0);
  838 
  839  /* Count valid nodes, warn of invalid ones */
  840  for(i= 0; i<filec; i++) {
  841    ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4|8);
  842    if(ret<=0) {
  843      was_error++;
  844  continue;
  845    }
  846    ret= lstat(path, &stbuf);
  847    if(ret==-1) {
  848      sprintf(xorriso->info_text, "Not found in local filesystem: ");
  849      Text_shellsafe(path, xorriso->info_text, 1);
  850      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1);
  851      was_error++;
  852  continue;
  853    }
  854  }
  855 
  856  if((flag&8) && !(flag&(2|4))) {
  857    sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error);
  858    Xorriso_info(xorriso,1);
  859    if(filec-was_error<=0)
  860      {ret= !was_error; goto ex;}
  861  }
  862 
  863  passes= 1+!(flag&(4|8));
  864  for(pass= 0; pass<passes; pass++)
  865  for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
  866    ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
  867    if(ret<=0)
  868  continue;
  869    ret= lstat(path, &stbuf);
  870    if(ret==-1)
  871  continue;
  872    if(S_ISLNK(stbuf.st_mode) &&
  873       (xorriso->do_follow_links || xorriso->do_follow_param)) {
  874      ret= stat(path, &stbuf);
  875      if(ret==-1) 
  876        ret= lstat(path, &stbuf);
  877      if(ret==-1)
  878  continue;
  879    }
  880    if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) {
  881      if(pass==0)
  882  continue;
  883      if(filec>1) {
  884        strcpy(xorriso->result_line, "\n");
  885        Xorriso_result(xorriso,0);
  886        Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 0);
  887        strcat(xorriso->result_line, ":\n");
  888        Xorriso_result(xorriso,0);
  889      }
  890      ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0);
  891      if(ret<=0) {
  892 
  893        /* >>> DirseQ loop and single item Xorriso_lsx_filev() */;
  894 
  895      } else {
  896        if(flag&1) {
  897          sprintf(xorriso->result_line, "total %d\n", dfilec);
  898          Xorriso_result(xorriso,0);
  899        }
  900        Xorriso_lsx_filev(xorriso, path,
  901                          dfilec, dfilev, boss_mem, (flag&1)|2|8);
  902      }
  903      if(dfilec>0)
  904        Sfile_destroy_argv(&dfilec, &dfilev, 0);
  905  continue;
  906    } else
  907      if(pass>0)
  908  continue;
  909    link_target[0]= 0;
  910    rpt[0]= 0;
  911    if((flag&5)==1) {
  912      Xorriso_local_getfacl(xorriso, path, &acl_text, 16);
  913      ret= Xorriso_format_ls_l(xorriso, &stbuf, (acl_text != NULL) << 1);
  914      Xorriso_local_getfacl(xorriso, path, &acl_text, 1 << 15);
  915      if(ret<=0)
  916  continue;
  917      if(S_ISLNK(stbuf.st_mode)) {
  918        ret= Xorriso_resolve_link(xorriso, path, link_target, 1);
  919        if(ret<=0)
  920          link_target[0]= 0;
  921      }
  922    } else if(flag&4) { /* -dux or -dusx */
  923      size= stbuf.st_size;
  924      if(S_ISDIR(stbuf.st_mode)) {
  925        ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem,
  926                                   NULL, flag&1);
  927        if(ret<0)
  928          {ret= -1; goto ex;}
  929        if(ret==0)
  930  continue;
  931      }
  932      if(xorriso->sh_style_result)
  933        sprintf(rpt, "%-7.f ",(double) (size/1024));
  934      else
  935        sprintf(rpt, "%7.f ",(double) (size/1024));
  936    }
  937    if(link_target[0]) {
  938      Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1);
  939      strcat(xorriso->result_line, " -> ");
  940      Xorriso_esc_filepath(xorriso,link_target, xorriso->result_line, 1 | 2);
  941    } else {
  942      Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1);
  943    }
  944    strcat(xorriso->result_line, "\n");
  945    Xorriso_result(xorriso, 0);
  946  }
  947  ret= !was_error;
  948 ex:;
  949  Xorriso_free_meM(path);
  950  Xorriso_free_meM(link_target);
  951  return(ret);
  952 }
  953 
  954 
  955 /*
  956    @param flag >>> bit0= remove whole sub tree: rm -r
  957                bit1= remove empty directory: rmdir  
  958                bit2= recursion: do not reassure in mode 2 "tree"
  959                bit3= this is for overwriting and not for plain removal
  960                bit4= count deleted files in xorriso->pacifier_count
  961                bit5= with bit0 only remove directory content, not the directory
  962                bit6= permission to call Xorriso_make_accessible()
  963    @return   <=0 = error
  964                1 = removed leaf file object
  965                2 = removed directory or tree
  966                3 = did not remove on user revocation
  967 */
  968 int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
  969 {
  970  int ret, is_dir= 0, made_accessible= 0;
  971  struct stat victim_stbuf;
  972  struct DirseQ *dirseq= NULL;
  973  char *sfe= NULL, *sub_path= NULL;
  974  struct PermiteM *perm_stack_mem;
  975 
  976  perm_stack_mem= xorriso->perm_stack;
  977 
  978  /* Avoiding large local memory objects in order to save stack space */
  979  sfe= malloc(5*SfileadrL);
  980  sub_path= malloc(2*SfileadrL);
  981  if(sfe==NULL || sub_path==NULL) {
  982    Xorriso_no_malloc_memory(xorriso, &sfe, 0);
  983    {ret= -1; goto ex;}
  984  }
  985 
  986  if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
  987    {ret= 0; goto ex;}
  988 
  989  ret= lstat(path, &victim_stbuf);
  990  if(ret==-1) {
  991    if((flag & 64) && errno == EACCES) {
  992      ret= Xorriso_make_accessible(xorriso, path, 0);
  993      if(ret < 0)
  994        goto ex;
  995      made_accessible= 1;
  996      ret= lstat(path, &victim_stbuf);
  997    }
  998    if(ret==-1) {
  999      sprintf(xorriso->info_text, "Cannot lstat(%s)",
 1000              Text_shellsafe(path, sfe, 0));
 1001      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1002      {ret= 0; goto ex;}
 1003    }
 1004  }
 1005  if(strcmp(path, "/")==0) {
 1006    sprintf(xorriso->info_text, "May not delete root directory");
 1007    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1008    {ret= 0; goto ex;}
 1009  }
 1010  if(S_ISDIR(victim_stbuf.st_mode))
 1011    is_dir= 1;
 1012  if(!is_dir) {
 1013    if(flag&2) { /* rmdir */
 1014      sprintf(xorriso->info_text, "%s in disk filesystem is not a directory",
 1015              Text_shellsafe(path, sfe, 0));
 1016      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1017      ret= 0; goto ex;
 1018    }
 1019  } else {
 1020    if(flag&1) { /* rm -r */
 1021 
 1022 #ifdef Osirrox_not_yeT
 1023      /* >>> */
 1024     
 1025      struct stat *victim_node= NULL;
 1026 
 1027      victim_node= &victim_stbuf;
 1028 
 1029      if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
 1030         (flag&32)) {
 1031        /* Iterate over subordinates and delete them */
 1032        mem= boss_mem;
 1033 
 1034        ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
 1035                          &iter, &node_array, &node_count, &node_idx,
 1036                          &node, 1|2);
 1037        if(ret<=0) {
 1038 cannot_create_iter:;
 1039          Xorriso_cannot_create_iter(xorriso, ret, 0);
 1040          ret= -1; goto ex;
 1041        }
 1042        pl= strlen(path);
 1043        strcpy(sub_path, path);
 1044        if(pl==0 || sub_path[pl-1]!='/') {
 1045          sub_path[pl++]= '/';
 1046          sub_path[pl]= 0;
 1047        }
 1048        sub_name= sub_path+pl;
 1049        while(1) { 
 1050          ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
 1051                                 &node_array, &node_count, &node_idx, &node, 0);
 1052          if(ret<0)
 1053            goto ex;
 1054          if(ret==0 || xorriso->request_to_abort)
 1055        break;
 1056          name= (char *) iso_node_get_name(node);
 1057          if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
 1058            {ret= 0; goto rm_r_problem_handler;}
 1059          strcpy(sub_name, name);
 1060          ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
 1061          if(ret==3 || ret<=0 || xorriso->request_to_abort) {
 1062 rm_r_problem_handler:;
 1063            not_removed= 1;
 1064            fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
 1065            if(fret<0)
 1066              goto dir_not_removed;
 1067          }
 1068        }
 1069        if(flag&32)
 1070          {ret= 2; goto ex;}
 1071 
 1072        if(not_removed) {
 1073 dir_not_removed:;
 1074          sprintf(xorriso->info_text, "Directory not removed: %s",
 1075                  Text_shellsafe(path, sfe, 0));
 1076          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1077          if(ret>0)
 1078            ret= 3;
 1079          goto ex;
 1080        }
 1081      }
 1082 
 1083 #else /* Osirrox_not_yeT */
 1084 
 1085        sprintf(xorriso->info_text, "-rm_rx is not implemented yet");
 1086        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1087        ret= 0; goto ex;
 1088 
 1089 #endif /* !Osirrox_not_yeT */
 1090 
 1091    } else {
 1092      if(!(flag&2)) { /* not rmdir */
 1093        sprintf(xorriso->info_text, "%s in disk filesystem is a directory",
 1094                Text_shellsafe(path, sfe, 0));
 1095        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1096        ret= 0; goto ex;
 1097      }
 1098      ret= Dirseq_new(&dirseq, path, 1);
 1099      if(ret>0) {
 1100        ret= Dirseq_next_adr(dirseq, sfe, 0);
 1101        if(ret>0) {
 1102          sprintf(xorriso->info_text,
 1103                  "Directory not empty on attempt to delete: %s",
 1104                  Text_shellsafe(path, sfe, 0));
 1105          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1106          ret= 0; goto ex;
 1107        }
 1108      }
 1109    }
 1110  }
 1111  if(xorriso->request_to_abort)
 1112    {ret= 3; goto ex;}
 1113  ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir);
 1114  if(ret<=0 || ret==3)
 1115    goto ex;
 1116  if(is_dir)
 1117    ret= rmdir(path);
 1118  else
 1119    ret= unlink(path);
 1120  if(ret == -1) {
 1121    if((flag & 64) && errno == EACCES && !made_accessible) {
 1122      ret= Xorriso_make_accessible(xorriso, path, 0);
 1123      if(ret < 0)
 1124        goto ex;
 1125      made_accessible= 1;
 1126      if(is_dir)
 1127        ret= rmdir(path);
 1128      else
 1129        ret= unlink(path);
 1130    }
 1131    if(ret == -1) {
 1132      sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
 1133              Text_shellsafe(path, sfe, 0));
 1134      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1135      ret= -1; goto ex;
 1136    }
 1137  }
 1138  if(flag&16)
 1139    xorriso->pacifier_count++;
 1140  ret= 1+!!is_dir;
 1141 ex:;
 1142  if(made_accessible)
 1143    Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 1144  if(sfe!=NULL)
 1145    free(sfe);
 1146  if(sub_path!=NULL)
 1147    free(sub_path);
 1148  Dirseq_destroy(&dirseq, 0);
 1149  return(ret);
 1150 } 
 1151 
 1152 
 1153 /* @param flag bit0= recursion
 1154 */ 
 1155 int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
 1156                          char *abs_path, char *show_path, int depth, int flag)
 1157 {
 1158  int ret= 0, type, action= 0, dpl= 0, compare_result, uret;
 1159  uid_t user= 0;
 1160  gid_t group= 0;
 1161  time_t date= 0;
 1162  mode_t mode_or= 0, mode_and= ~1;
 1163  char *target, *text_2, *wdi_mem= NULL, *disk_prefix, *iso_path= NULL;
 1164  char *basename;
 1165  struct FindjoB *subjob;
 1166  struct stat stbuf; 
 1167 
 1168  Xorriso_alloc_meM(iso_path, char, SfileadrL);
 1169 
 1170  action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
 1171                                 &mode_and, &mode_or, &type, &date, &subjob, 0);
 1172  if(action<0)
 1173    action= 0;
 1174  if(action==15 || action==16 || action==18 || action==19 || action==20) {
 1175    /* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */
 1176    Findjob_get_start_path(job, &disk_prefix, 0);
 1177    if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
 1178      {ret= -1; goto ex;}
 1179    dpl= strlen(disk_prefix);
 1180    if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL)
 1181      {ret= -1; goto ex;}
 1182    if(abs_path[dpl]=='/')
 1183      dpl++;
 1184    ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4);
 1185    if(ret<=0)
 1186      {goto ex;}
 1187 
 1188  }
 1189  if(action==15) { /* in_iso */
 1190    ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 1191    if(ret<0)
 1192      {ret= 1; goto ex;}
 1193    Text_shellsafe(show_path, xorriso->result_line, 0);
 1194    strcat(xorriso->result_line, "\n");
 1195    Xorriso_result(xorriso, 0);
 1196    ret= 1;
 1197  } else if(action==16) { /* not_in_iso */
 1198    ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
 1199                                 &compare_result, 4);
 1200    if(ret<xorriso->find_compare_result)
 1201      xorriso->find_compare_result= ret;
 1202    if(ret>=0)
 1203      ret= 1;
 1204  } else if(action==18) { /* add_missing */
 1205    ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
 1206                                 &compare_result, 4|(1u<<31));
 1207    if(ret<xorriso->find_compare_result)
 1208      xorriso->find_compare_result= ret;
 1209    if(ret==0) {
 1210      uret= Xorriso_update_interpreter(xorriso, NULL, NULL, compare_result,
 1211                                       abs_path, iso_path, ((flag&1)<<2) | 2);
 1212      if(uret<=0)
 1213        ret= 0;
 1214    }
 1215    if(ret>=0)
 1216      ret= 1;
 1217  } else if(action==19) { /* empty_iso_dir */
 1218    ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 1219    if(ret<0)
 1220      {ret= 1; goto ex;}
 1221    if(!S_ISDIR(stbuf.st_mode))
 1222      {ret= 1; goto ex;}
 1223    ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32);
 1224    if(ret>0) {
 1225      sprintf(xorriso->info_text, "Emptied directory ");
 1226      Text_shellsafe(iso_path, xorriso->info_text, 1);
 1227      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1228    }
 1229  } else if(action==20) { /* is_full_in_iso */
 1230    ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 1231    if(ret<0)
 1232      {ret= 1; goto ex;}
 1233    if(!S_ISDIR(stbuf.st_mode))
 1234      {ret= 1; goto ex;}
 1235    wdi_mem= strdup(xorriso->wdi);
 1236    if(wdi_mem == NULL) {
 1237      Xorriso_no_malloc_memory(xorriso, NULL, 0);
 1238      {ret= -1; goto ex;}
 1239    }
 1240    strcpy(xorriso->wdi, iso_path);
 1241    ret= Xorriso_ls(xorriso, 4|8);
 1242    strcpy(xorriso->wdi, wdi_mem);
 1243    if(ret>0) {
 1244      strcpy(xorriso->result_line, "d ");
 1245      Text_shellsafe(iso_path, xorriso->result_line, 1);
 1246      strcat(xorriso->result_line,
 1247             " (ISO) : non-empty directory (would not match mount point)\n");
 1248      Xorriso_result(xorriso,0);
 1249    }
 1250    {ret= 1; goto ex;}
 1251  } else if(action == 40) { /* estimate_size */
 1252    basename= strrchr(abs_path, '/');
 1253    if(basename != NULL)
 1254      basename++;
 1255    else
 1256      basename= abs_path;
 1257    ret= lstat(abs_path, &stbuf);
 1258    if(ret != -1)
 1259      ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode,
 1260                                      stbuf.st_size, 0);
 1261  } else if(action == 44) { /* list_extattr */
 1262    ret= Xorriso_list_extattr(xorriso, NULL, abs_path, show_path, target, 2);
 1263  } else {
 1264    Xorriso_esc_filepath(xorriso,show_path, xorriso->result_line, 0);
 1265    strcat(xorriso->result_line, "\n");
 1266    Xorriso_result(xorriso, 0);
 1267    ret= 1;
 1268  } 
 1269 ex:;
 1270  if(action==15 || action==16 || action==18 || action==19 || action==20)
 1271    if(xorriso->no_volset_present)
 1272      xorriso->request_to_abort= 1; /* Need an image. No use to try again. */
 1273  if(wdi_mem != NULL)
 1274    free(wdi_mem);
 1275  Xorriso_free_meM(iso_path);
 1276  return(ret);
 1277 }
 1278 
 1279 
 1280 /* @param flag bit0=recursion
 1281 */
 1282 int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job,
 1283                   char *abs_dir_parm, char *dir_path,
 1284                   struct stat *dir_stbuf, int depth,
 1285                   struct LinkiteM *link_stack, int flag)
 1286 {
 1287  int ret,is_link, no_dive;
 1288  struct DirseQ *dirseq= NULL;
 1289  struct stat stbuf;
 1290  struct LinkiteM *own_link_stack;
 1291  char *abs_dir_path, *namept;
 1292  char *name= NULL, *path= NULL, *sfe= NULL;
 1293  char *abs_dir_path_data= NULL, *abs_path= NULL;
 1294 
 1295  job->depth= depth;
 1296 
 1297  if(xorriso->request_to_abort)
 1298    {ret= 0; goto ex;}
 1299 
 1300  Xorriso_alloc_meM(sfe, char, 5*SfileadrL);
 1301  Xorriso_alloc_meM(name, char, SfileadrL);
 1302  Xorriso_alloc_meM(path, char, SfileadrL);
 1303  Xorriso_alloc_meM(abs_dir_path_data, char, SfileadrL);
 1304  Xorriso_alloc_meM(abs_path, char, SfileadrL);
 1305 
 1306  own_link_stack= link_stack;
 1307  abs_dir_path= abs_dir_parm;
 1308  if(abs_dir_path[0]==0) {
 1309    ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path,
 1310                              abs_dir_path_data, 1|2|8);
 1311    if(ret<=0)
 1312      goto ex;
 1313    abs_dir_path= abs_dir_path_data;
 1314    ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1));
 1315    if(ret<0)
 1316      goto ex;
 1317    if(ret>0)
 1318      {ret= 0; goto ex;}
 1319    ret= lstat(abs_dir_path, dir_stbuf);
 1320    if(ret==-1)
 1321      {ret= 0; goto ex;}
 1322    if(S_ISLNK(dir_stbuf->st_mode) &&
 1323       (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
 1324      if(stat(abs_dir_path, &stbuf)!=-1)
 1325        if(dir_stbuf->st_dev == stbuf.st_dev ||
 1326          (xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
 1327          memcpy(dir_stbuf, &stbuf, sizeof(struct stat));
 1328 
 1329    namept= strrchr(dir_path, '/');
 1330    if(namept==NULL)
 1331      namept= dir_path;
 1332    else
 1333      namept++;
 1334 
 1335    ret= Findjob_test_2(xorriso, job, NULL, namept, dir_path, NULL, dir_stbuf,
 1336                        0);
 1337    if(ret<0)
 1338      goto ex;
 1339    if(ret>0) {
 1340      ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth,
 1341                                flag&1);
 1342      if(xorriso->request_to_abort)
 1343        {ret= 0; goto ex;}
 1344      if(ret<=0) {
 1345        if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 1346          goto ex;
 1347      }
 1348    }
 1349  }
 1350  if(xorriso->request_to_abort)
 1351    {ret= 1; goto ex;}
 1352  if(!S_ISDIR(dir_stbuf->st_mode))
 1353    {ret= 2; goto ex;}
 1354 
 1355  ret= Dirseq_new(&dirseq, abs_dir_path, 1);
 1356  if(ret<0) {
 1357    sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
 1358    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1359    {ret= -1; goto ex;}
 1360  }
 1361  if(ret==0)
 1362    {ret= 2; goto ex;}
 1363  
 1364  job->depth++;
 1365  while(!xorriso->request_to_abort) {
 1366    Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 1367    ret= Dirseq_next_adr(dirseq,name,0);
 1368    if(ret==0)
 1369  break;
 1370    if(ret<0) {
 1371      sprintf(xorriso->info_text,"Failed to obtain next directory entry");
 1372      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1373      {ret= -1; goto ex;}
 1374    }
 1375    ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1);
 1376    if(ret<=0)
 1377      goto ex;
 1378    ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
 1379    if(ret<=0)
 1380      goto ex;
 1381    ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */
 1382    if(ret<0)
 1383      goto ex;
 1384    if(ret>0)
 1385  continue;
 1386    ret= lstat(abs_path, &stbuf);
 1387    if(ret==-1)
 1388  continue;
 1389    no_dive= 0;
 1390 
 1391    is_link= S_ISLNK(stbuf.st_mode);
 1392    if(is_link && xorriso->do_follow_links) {
 1393      ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2);
 1394      if(ret<0)
 1395        {ret= -1; goto ex;}
 1396      if(ret!=1)
 1397        no_dive= 1;
 1398    }
 1399 
 1400    ret= Findjob_test_2(xorriso, job, NULL, name, path, dir_stbuf, &stbuf, 0);
 1401    if(ret<0)
 1402      goto ex;
 1403    if(ret>0) {
 1404      ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1);
 1405      if(xorriso->request_to_abort)
 1406        {ret= 0; goto ex;}
 1407      if(ret<=0) {
 1408        if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 1409          goto ex;
 1410      }
 1411    }
 1412    if(!S_ISDIR(stbuf.st_mode))
 1413      no_dive= 1;
 1414    if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount)
 1415      no_dive= 1;
 1416    if(!no_dive) {
 1417      ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1,
 1418                         own_link_stack, flag|1);
 1419      if(ret<0)
 1420        goto ex;
 1421    }
 1422  }
 1423 
 1424  ret= 1;
 1425 ex:;
 1426  job->depth= depth;
 1427  Xorriso_free_meM(sfe);
 1428  Xorriso_free_meM(name);
 1429  Xorriso_free_meM(path);
 1430  Xorriso_free_meM(abs_dir_path_data);
 1431  Xorriso_free_meM(abs_path);
 1432  Dirseq_destroy(&dirseq, 0);
 1433  return(ret);
 1434 }
 1435 
 1436 
 1437 /* @param flag bit0= no hardlink reconstruction
 1438                bit1= do not set xorriso->node_*_prefixes
 1439                bit5= -extract_single: eventually do not insert directory tree
 1440 */
 1441 int Xorriso_restore_sorted(struct XorrisO *xorriso, int count,
 1442                            char **src_array, char **tgt_array,
 1443                            int *problem_count, int flag)
 1444 {
 1445  int i, ret, with_node_array= 0, hflag= 0, hret;
 1446 
 1447  *problem_count= 0;
 1448  if(!(((xorriso->ino_behavior & 16) && xorriso->do_restore_sort_lba) ||
 1449       (xorriso->ino_behavior & 4) || (flag & 1))) {
 1450    ret= Xorriso_make_hln_array(xorriso, 0);
 1451    if(ret<=0)
 1452      goto ex;
 1453  }
 1454  if(xorriso->do_restore_sort_lba) {
 1455    /* Count affected nodes */
 1456    Xorriso_destroy_node_array(xorriso, 0);
 1457    for(i= 0; i < count; i++) {
 1458      if(src_array[i] == NULL || tgt_array[i] == NULL)
 1459    continue;
 1460      /* sort_lba : Make directories plus node_array and then
 1461                    run array extractor (with eventual hardlink detection)
 1462      */
 1463      hflag= (1 << 7) | ((!!(flag & 2)) << 9) | (flag & 32);
 1464      ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 1465                           (off_t) 0, (off_t) 0, hflag);
 1466      if(ret <= 0) {
 1467        (*problem_count)++;
 1468        hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 1469        if(hret < 0)
 1470          goto ex;
 1471      }
 1472      with_node_array= 1;
 1473    }
 1474  }
 1475 
 1476  if(with_node_array) {
 1477    /* Allocate and fill node array */
 1478    if(xorriso->node_counter <= 0)
 1479      {ret= 2; goto ex;}
 1480    ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0,
 1481                                !xorriso->do_restore_sort_lba);
 1482    if(ret<=0)
 1483      goto ex;
 1484    for(i= 0; i < count; i++) {
 1485      if(src_array[i] == NULL || tgt_array[i] == NULL)
 1486    continue;
 1487      ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 1488                           (off_t) 0, (off_t) 0, (2 << 7) | (flag & 32));
 1489      if(ret <= 0) {
 1490        (*problem_count)++;
 1491        hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 1492        if(hret < 0)
 1493          goto ex;
 1494      }
 1495    }
 1496  }
 1497 
 1498  /* Perform restore operations */
 1499  if(xorriso->do_restore_sort_lba) {
 1500    ret= Xorriso_restore_node_array(xorriso, 0);
 1501    if(ret <= 0)
 1502      goto ex;
 1503  } else {
 1504    for(i= 0; i < count; i++) {
 1505      if(src_array[i] == NULL || tgt_array[i] == NULL)
 1506    continue;
 1507      ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 1508                           (off_t) 0, (off_t) 0, flag & 32);
 1509      if(ret <= 0) {
 1510        (*problem_count)++;
 1511        hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 1512        if(hret < 0)
 1513          goto ex;
 1514      }
 1515    }
 1516  }
 1517 
 1518  ret= 1;
 1519 ex:;
 1520  return(ret);
 1521 }
 1522 
 1523 
 1524 /* @param flag bit0= path is a directory
 1525                bit2= recursion: do not reassure in mode 2 "tree"
 1526              bit3-7= question text mode
 1527                      0= plain removal 
 1528                      1= replacing file object
 1529                      2= overwriting of content, keeping file object
 1530                      3= appending of content, keeping file object
 1531 */
 1532 int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
 1533 {
 1534  int ret, mode;
 1535 
 1536  mode= (flag >> 3) & 31;
 1537  while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
 1538        && !xorriso->request_not_to_ask) {
 1539    /* ls -ld */
 1540    Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8);
 1541    if(flag&1) /* du -s */
 1542      Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4);
 1543    if(mode == 3)
 1544      sprintf(xorriso->info_text,
 1545    "File exists. Append content ?  n= no, y= yes, x= abort, @= stop asking\n");
 1546    else if(mode == 2)
 1547      sprintf(xorriso->info_text,
 1548 "File exists. Overwrite content ?  n= no, y= yes, x= abort, @= stop asking\n");
 1549    else if(mode == 1)
 1550      sprintf(xorriso->info_text,
 1551   "File exists. Remove ?  n= keep old, y= remove, x= abort, @= stop asking\n");
 1552    else
 1553      sprintf(xorriso->info_text,
 1554   "Remove above file ?  n= keep it, y= remove it, x= abort, @= stop asking\n");
 1555    Xorriso_info(xorriso, 4);
 1556    ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
 1557    if(ret<=0)
 1558      goto ex;
 1559    if(xorriso->request_to_abort) {
 1560      sprintf(xorriso->info_text,
 1561              "File alteration operation aborted by user before file: ");
 1562      Text_shellsafe(path, xorriso->info_text, 1);
 1563      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1564      ret= 3; goto ex;
 1565    }
 1566    if(ret==3)
 1567  continue;
 1568    if(ret==6) /* yes */
 1569  break;
 1570    if(ret==4) { /* yes, do not ask again */
 1571      xorriso->request_not_to_ask= 1;
 1572  break;
 1573    }
 1574    if(ret==1) { /* no */
 1575      sprintf(xorriso->info_text, "Kept in existing state: ");
 1576      Text_shellsafe(path, xorriso->info_text, 1);
 1577      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1578      ret= 3; goto ex;
 1579    }
 1580  }
 1581  ret= 1;
 1582 ex:
 1583  return(ret);
 1584 }
 1585 
 1586 
 1587 /* @param flag bit7= return 4 if restore fails from denied permission
 1588                      do not issue error message
 1589    @return <=0 failure , 1 success ,
 1590            4 with bit7: permission to  create file was denied
 1591 */
 1592 int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
 1593                           char *tmp_path, int *fd, int flag)
 1594 {
 1595  char *cpt;
 1596 
 1597  cpt= strrchr(orig_path, '/');
 1598  if(cpt==NULL)
 1599    tmp_path[0]= 0;
 1600  else {
 1601    strncpy(tmp_path, orig_path, cpt+1-orig_path);
 1602    tmp_path[cpt+1-orig_path]= 0;
 1603  }
 1604  strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX");
 1605  *fd= mkstemp(tmp_path);
 1606  if(*fd==-1) {
 1607    if(errno == EACCES && (flag & 128))
 1608      return(4);
 1609    strcpy(xorriso->info_text, "Cannot create temporary file : ");
 1610    Text_shellsafe(tmp_path, xorriso->info_text, 1);
 1611    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1612    return(0);
 1613  }
 1614  fchmod(*fd, S_IRUSR|S_IWUSR);
 1615  return(1);
 1616 }
 1617 
 1618 
 1619 /* @param flag bit0= change regardless of xorriso->do_auto_chmod
 1620                bit1= desired is only rx
 1621    @return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded
 1622 */
 1623 int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
 1624 {
 1625  int ret, is_link= 0;
 1626  char *path_pt, *link_target= NULL;
 1627  mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR;
 1628  struct stat stbuf;
 1629 
 1630  Xorriso_alloc_meM(link_target, char, SfileadrL);
 1631 
 1632  if(!(xorriso->do_auto_chmod || (flag & 1)))
 1633    {ret= 0; goto ex;}
 1634 
 1635  if(flag & 2)
 1636    desired &= ~S_IWUSR;
 1637  path_pt= disk_path;
 1638  ret= lstat(path_pt, &stbuf);
 1639  if(ret==-1)
 1640    {ret= 0; goto ex;}
 1641  if(S_ISLNK(stbuf.st_mode)) {
 1642    is_link= 1;
 1643    ret= stat(path_pt, &stbuf);
 1644    if(ret==-1)
 1645      {ret= 0; goto ex;}
 1646  }
 1647  if(!S_ISDIR(stbuf.st_mode))
 1648    {ret= 0; goto ex;}
 1649  if(is_link) {
 1650    ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0);
 1651    if(ret<=0)
 1652      goto ex;
 1653    path_pt= link_target;
 1654  }
 1655  if((stbuf.st_mode & desired) == desired)
 1656    {ret= 0; goto ex;}
 1657  if(stbuf.st_uid!=geteuid())
 1658    {ret= -2; goto ex;}
 1659 
 1660  mode= (stbuf.st_mode | desired) & 07777;
 1661  ret= chmod(path_pt, mode);
 1662  if(ret==-1) {
 1663    sprintf(xorriso->info_text,
 1664            "Cannot change access permissions of disk directory: chmod %o ",
 1665            (unsigned int) (mode & 07777));
 1666    Text_shellsafe(path_pt, xorriso->info_text, 1);
 1667    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
 1668    {ret= -2; goto ex;}
 1669  }
 1670  ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0);
 1671  if(ret<=0)
 1672    goto ex;
 1673  ret= 1;
 1674 ex:;
 1675  Xorriso_free_meM(link_target);
 1676  return(ret);
 1677 }
 1678 
 1679 
 1680 int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag)
 1681 {
 1682  int done= 0, ret, just_rx= 2;
 1683  char *npt, *apt, *path, *wpt;
 1684 
 1685  Xorriso_alloc_meM(path, char, SfileadrL); 
 1686 
 1687  apt= disk_path;
 1688  wpt= path;
 1689  for(npt= apt; !done; apt= npt + 1) {
 1690    npt= strchr(apt, '/');
 1691    if(npt == NULL)
 1692  break;
 1693    if(strchr(npt + 1, '/') == NULL)
 1694      just_rx= 0;
 1695    strncpy(wpt, apt, npt + 1 - apt);
 1696    wpt+= npt + 1 - apt;
 1697    *wpt= 0;
 1698    ret= Xorriso_auto_chmod(xorriso, path, just_rx);
 1699    if(ret == -1)
 1700      {ret= -1; goto ex;}
 1701    if(ret == -2)
 1702      {ret= 0; goto ex;}
 1703  }
 1704  ret= 1;
 1705 ex:
 1706  Xorriso_free_meM(path);
 1707  return(ret);
 1708 }
 1709 
 1710 
 1711 /* @param flag bit0= prefer to find a match after *img_prefixes
 1712                      (but deliver img_prefixes if no other can be found)
 1713 */
 1714 int Xorriso_make_restore_path(struct XorrisO *xorriso,
 1715          struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
 1716          char img_path[SfileadrL], char disk_path[SfileadrL], int flag)
 1717 {
 1718  int li;
 1719  struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL;
 1720  char *ipfx, *dpfx;
 1721 
 1722  /* Obtain disk_path by replacing start piece of img_path */
 1723  
 1724  d= *disk_prefixes;
 1725  for(s= *img_prefixes; s != NULL;
 1726      s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) {
 1727 
 1728    ipfx= Xorriso_lst_get_text(s, 0);
 1729    li= strlen(ipfx);
 1730    dpfx= Xorriso_lst_get_text(d, 0);
 1731    if(li == 1 && ipfx[0] == '/') {
 1732      li= 0;
 1733      if(img_path[0] != '/')
 1734  continue;
 1735    } else {
 1736      if(strncmp(img_path, ipfx, li) != 0)
 1737  continue;
 1738      if(img_path[li] != 0 && img_path[li] != '/')
 1739  continue;
 1740    }
 1741    if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL)
 1742      return(-1);
 1743    if(img_path[li]=='/') {
 1744      if(dpfx[0] == '/' && dpfx[1] == 0)
 1745        sprintf(disk_path, "/%s", img_path + li + 1);
 1746      else
 1747        sprintf(disk_path, "%s/%s", dpfx, img_path + li + 1);
 1748    } else
 1749      strcpy(disk_path, dpfx);     /* img_path[li] is 0, img_path equals ipfx */
 1750    found_s= s;
 1751    found_d= d;
 1752    if(s != *img_prefixes || !(flag & 1))
 1753  break;
 1754  }
 1755  *img_prefixes= found_s;
 1756  *disk_prefixes= found_d;
 1757  return(found_s != NULL);
 1758 }
 1759 
 1760 
 1761 /* @param flag bit0=permission to run Xorriso_make_accessible
 1762 */
 1763 int Xorriso_restore_make_hl(struct XorrisO *xorriso,
 1764                             char *old_path, char *new_path, int flag)
 1765 {
 1766  int ret;
 1767  struct PermiteM *perm_stack_mem;
 1768 
 1769  ret= link(old_path, new_path);
 1770  if(ret == 0)
 1771    return(1);
 1772  if(errno == EACCES && (flag & 1)) {
 1773    perm_stack_mem= xorriso->perm_stack;
 1774    ret= Xorriso_make_accessible(xorriso, new_path, 0);
 1775    if(ret > 0) {
 1776       ret= link(old_path, new_path);
 1777       if(ret == 0) {
 1778         Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 1779         return(1);
 1780       }
 1781    }
 1782    Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 1783  }
 1784 
 1785  sprintf(xorriso->info_text, "Hardlinking failed: ");
 1786  Text_shellsafe(new_path, xorriso->info_text, 1);
 1787  strcat(xorriso->info_text, " -> ");
 1788  Text_shellsafe(old_path, xorriso->info_text, 1 | 2);
 1789  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "WARNING", 0);
 1790  return(0);
 1791 }
 1792 
 1793 
 1794 int Xorriso_afile_fopen(struct XorrisO *xorriso,
 1795                         char *filename, char *mode, FILE **ret_fp, int flag)
 1796 /*
 1797  bit0= do not print error message on failure
 1798  bit1= do not open stdin
 1799 */
 1800 {
 1801  FILE *fp= NULL;
 1802 
 1803  *ret_fp= NULL;
 1804  if(strcmp(filename,"-")==0) {
 1805    if(mode[0]=='a' || mode[0]=='w' ||
 1806       (mode[0]=='r' && mode[1]=='+') ||
 1807       (mode[0]=='r' && mode[1]=='b' && mode[2]=='+')) 
 1808      fp= stdout;
 1809    else if(flag & 2) {
 1810      Xorriso_msgs_submit(xorriso, 0, "Not allowed as input path: '-'", 0,
 1811                        "FAILURE", 0);
 1812      return(0);
 1813    } else {
 1814      Xorriso_msgs_submit(xorriso, 0, "Ready for data at standard input", 0,
 1815                          "NOTE", 0);
 1816      fp= stdin;
 1817    }
 1818  } else if(strncmp(filename,"tcp:",4)==0){
 1819    Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0,
 1820                        "FAILURE", 0);
 1821  } else if(strncmp(filename,"file:",5)==0){
 1822    fp= fopen(filename+5,mode);
 1823  } else {
 1824    fp= fopen(filename,mode);
 1825  }
 1826  if(fp==NULL){
 1827    if(!(flag&1)) {
 1828      sprintf(xorriso->info_text,
 1829              "Failed to open file '%s' in %s mode", filename, mode);
 1830      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 1831    }
 1832    return(0);
 1833  }
 1834  *ret_fp= fp;
 1835  return(1);
 1836 }
 1837 
 1838 
 1839 /*
 1840    @param flag bit0= make absolute command paths with known systems
 1841                bit1= do not allow prefixes with cmd
 1842                bit2= interpret unprefixed cmd as shell:
 1843                bit3= do not care for device filetype
 1844 */
 1845 int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd,
 1846                            int lba, int track, int session, char *volid,
 1847                            char *devadr, char result[SfileadrL], int flag)
 1848 {
 1849  int ret, reg_file= 0, is_safe= 0, sys_code= 0;
 1850  char *form= NULL, session_text[12], track_text[12], lba_text[12];
 1851  char *vars[5][2], *sfe= NULL, *volid_sfe= NULL, *cpt, *sysname;
 1852  char *cooked_dev= NULL, *eff_dev;
 1853  struct stat stbuf;
 1854 
 1855  Xorriso_alloc_meM(form, char, 6 * SfileadrL);
 1856  Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
 1857  Xorriso_alloc_meM(volid_sfe, char, 5 * 80 + 1);
 1858  Xorriso_alloc_meM(cooked_dev, char, SfileadrL);
 1859 
 1860  if(strlen(cmd) > SfileadrL) {
 1861    Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0);
 1862    {ret= 0; goto ex;}
 1863  }
 1864  eff_dev= devadr;
 1865  ret= stat(devadr, &stbuf);
 1866  if(ret != -1 && !(flag & 8))
 1867    if(S_ISREG(stbuf.st_mode))
 1868      reg_file= 1;
 1869  if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) {
 1870    cpt= cmd + 6;
 1871    sys_code= 1;
 1872  } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) {
 1873    cpt= cmd + 8;
 1874    sys_code= 2;
 1875  } else if(strncmp(cmd, "netbsd:", 7) == 0 && !(flag & 2)) {
 1876    cpt= cmd + 7;
 1877    sys_code= 3;
 1878  } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) {
 1879    cpt= cmd + 7;
 1880    strcpy(form, cpt);
 1881  } else if(flag & 4) {
 1882    cpt= cmd;
 1883    strcpy(form, cpt);
 1884  } else {
 1885    cpt= cmd;
 1886    ret= System_uname(&sysname, NULL, NULL, NULL, 0);
 1887    if(ret <= 0) {
 1888      Xorriso_msgs_submit(xorriso, 0,
 1889                          "-mount*: Cannot determine current system type",
 1890                          0, "FAILURE", 0);
 1891      {ret= 0; goto ex;}
 1892    } else if(strcmp(sysname, "FreeBSD") == 0 ||
 1893              strcmp(sysname, "GNU/kFreeBSD") == 0) {
 1894                                          /* "GNU/kFreeBSD" = Debian kfreebsd */
 1895      sys_code= 2;
 1896    } else if(strcmp(sysname, "NetBSD") == 0) {
 1897      sys_code= 3;
 1898    } else if(strcmp(sysname, "Linux") == 0) {
 1899      sys_code= 1;
 1900    } else {
 1901      sprintf(xorriso->info_text, "-mount*: Unsupported system type %s",
 1902              Text_shellsafe(sysname, sfe, 0));
 1903      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1904      {ret= 0; goto ex;}
 1905    }
 1906  }
 1907 
 1908  if(sys_code == 1) { /* GNU/Linux */
 1909    sprintf(form,
 1910            "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s",
 1911            (flag & 1 ? "/bin/" : ""),
 1912            (reg_file || (xorriso->mount_opts_flag & 1) ? "loop," : ""),
 1913            Text_shellsafe(cpt, sfe, 0));
 1914    is_safe= 1;
 1915  } else if(sys_code == 2 || sys_code == 3) { /* FreeBSD , NetBSD */
 1916    if(reg_file) {
 1917 
 1918 /*  <<< Considered to create vnode as of
 1919         J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008
 1920         but for now refraining from creating that persistent file object
 1921 
 1922      strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)");
 1923      sprintf(form + strlen(form),
 1924          " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s",
 1925          Text_shellsafe(cmd+8, sfe, 0));
 1926 */
 1927 
 1928      Xorriso_msgs_submit(xorriso, 0, 
 1929            "Detected regular file as mount device with BSD style command.",
 1930            0, "FAILURE", 0);
 1931      if(sys_code == 2) {
 1932        Xorriso_msgs_submit(xorriso, 0,
 1933 "Command mdconfig -a -t vnode -f can create a device node which uses the file",
 1934                          0, "HINT", 0);
 1935      } else {
 1936        Xorriso_msgs_submit(xorriso, 0,
 1937      "Command  vnconfig -c vndX  can create a device node which uses the file",
 1938                          0, "HINT", 0);
 1939      }
 1940      {ret= 0; goto ex;}
 1941    } else {
 1942      if(sys_code == 3 && strncmp(devadr, "/dev/rcd", 8) == 0) {
 1943        sprintf(cooked_dev, "/dev/cd%s", devadr + 8);
 1944        eff_dev= cooked_dev;
 1945      }
 1946      sprintf(form,
 1947          "%smount_cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s",
 1948          (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cpt, sfe, 0));
 1949    }
 1950    is_safe= 1;
 1951  }
 1952  sprintf(session_text, "%d", session);
 1953  sprintf(track_text, "%d", track);
 1954  sprintf(lba_text, "%d", lba);
 1955  vars[0][0]= "sbsector";
 1956  vars[0][1]= lba_text;
 1957  vars[1][0]= "track";
 1958  vars[1][1]= track_text;
 1959  vars[2][0]= "session";
 1960  vars[2][1]= session_text;
 1961  vars[3][0]= "volid";
 1962  vars[3][1]= Text_shellsafe(volid, volid_sfe, 0);
 1963  vars[4][0]= "device";
 1964  vars[4][1]= Text_shellsafe(eff_dev, sfe, 0);
 1965  ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0);
 1966  if(ret <= 0)
 1967    goto ex;
 1968  ret= 1 + is_safe;
 1969 ex:;
 1970  Xorriso_free_meM(cooked_dev);
 1971  Xorriso_free_meM(volid_sfe);
 1972  Xorriso_free_meM(sfe);
 1973  Xorriso_free_meM(form);
 1974  return(ret);
 1975 }
 1976 
 1977 
 1978 int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag)
 1979 {
 1980  FILE *fp= NULL;
 1981  char dummy[81], name[81], timestamp[81], size[81], md5[81];
 1982 
 1983  if(xorriso->scdbackup_tag_written[0] == 0)
 1984    return(1);
 1985 
 1986  name[0]= timestamp[0]= size[0]= md5[0]= 0;
 1987  sscanf(xorriso->scdbackup_tag_written, "%s %s %s %s %s %s %s",
 1988         dummy, dummy, dummy, name, timestamp, size, md5);
 1989  sprintf(xorriso->info_text, "scdbackup tag written : %s %s %s %s\n",
 1990          name, timestamp, size, md5);
 1991  Xorriso_msgs_submit(xorriso, 0,  xorriso->info_text, 0, "NOTE", 0);
 1992 
 1993  if(xorriso->scdbackup_tag_listname[0]) {
 1994    fp= fopen(xorriso->scdbackup_tag_listname, "a");
 1995    if(fp==0) {
 1996      strcpy(xorriso->info_text, "-scdbackup_tag: Cannot open file ");
 1997      Text_shellsafe(xorriso->scdbackup_tag_listname, xorriso->info_text, 1);
 1998      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1999      return(0);
 2000    }
 2001    fprintf(fp, "%s %s %s %s\n", name, timestamp, size, md5);
 2002    fclose(fp);
 2003  }
 2004  return(1);
 2005 }
 2006 
 2007 
 2008 /* @param flag bit0= for append rather than overwrite
 2009 */
 2010 int Xorriso_is_concat_target(struct XorrisO *xorriso,  char *target,
 2011                              int *ftype, int *fd, int flag)
 2012 {
 2013  int ret;
 2014  char *why= "";
 2015 
 2016  *ftype= 0;
 2017  *fd = -1;
 2018 
 2019  if(strcmp(target, "-") == 0) {
 2020    *fd= 1;
 2021    *ftype= 8; /* character device */
 2022    return(1);
 2023  }
 2024 
 2025  *ftype= Sfile_type(target, 1 | 8 | 16);
 2026  if(*ftype == -1)
 2027    return(2); /* not yet existing regular */
 2028 
 2029  if(*ftype & 1024) {
 2030    *fd= Sfile_get_dev_fd_no(target, 0);
 2031    *ftype &= ~1024;
 2032  }
 2033  if(*ftype & 2048) {
 2034    why= "fstat(2) returned -1 on file descriptor number.";
 2035    goto not_usable;
 2036  }
 2037 
 2038  if(*ftype == 3) {
 2039    if(!xorriso->do_follow_concat) {
 2040      why= "May not follow symbolic link. No -follow \"...:concat:...\".";
 2041      goto not_usable;
 2042    }
 2043    *ftype= Sfile_type(target, 1 | 4 | 8);
 2044    if(*ftype == -1)
 2045      return(2); /* not yet existing regular */
 2046  }
 2047  if(*ftype == 2) {
 2048    why= "May not write data into a directory.";
 2049    goto not_usable;
 2050  }
 2051  if(*ftype == 0) {
 2052    why= "Cannot determine file type.";
 2053    goto not_usable;
 2054  }
 2055  if(*ftype == 7) {
 2056 
 2057    /* >>> what to do with UNIX socket ? */;
 2058 
 2059    why= "Cannot yet handle socket file as target.";
 2060    goto not_usable;
 2061  }
 2062 
 2063  if(xorriso->do_overwrite != 1 && xorriso->do_overwrite != 2) {
 2064    why= "May not alter existing file.";
 2065    goto not_usable;
 2066  }
 2067  ret= Xorriso_reassure_restore(xorriso, target, (2 + (flag & 1)) << 3);
 2068  if(ret <= 0 || ret == 0) {
 2069    why= "User revoked alteration of existing file.";
 2070    goto not_usable;
 2071  }
 2072 
 2073  if(*ftype == 1)
 2074    return(2); /* existing regular */
 2075  if(*ftype == 4 || *ftype == 6 || *ftype == 8)
 2076    return(1); /* named pipe, block device, character device */
 2077 
 2078 not_usable:; 
 2079  sprintf(xorriso->info_text,
 2080                "Unsuitable -concat target: ");
 2081  Text_shellsafe(target, xorriso->info_text, 1);
 2082  sprintf(xorriso->info_text + strlen(xorriso->info_text), ". %s", why);
 2083  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2084  return(0);
 2085 }
 2086 
 2087 
 2088 int Xorriso_concat(struct XorrisO *xorriso, char *mode, char *target,
 2089                    int progc, char **progv,
 2090                    int filec, char **filev, int flag)
 2091 {
 2092  int ret, i, fd= -1, target_is_regular= 0, fd_opened= 0, ftype, prog_forked= 0;
 2093  int status;
 2094  int open_mode= O_WRONLY | O_CREAT;
 2095  struct stat stbuf;
 2096  pid_t forked_pid;
 2097 
 2098  for(i= 0; i < filec; i++) {
 2099    ret= Xorriso_iso_lstat(xorriso, filev[i], &stbuf, 4);
 2100    if(ret == -1)
 2101      goto ex;
 2102    if(!S_ISREG(stbuf.st_mode)) {
 2103      sprintf(xorriso->info_text,
 2104              "-concat: iso_rr_path is not a regular data file: ");
 2105      Text_shellsafe(filev[i], xorriso->info_text, 1);
 2106      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2107      ret= 0; goto ex;
 2108    }
 2109  }
 2110  if(strcmp(mode, "overwrite") == 0) {
 2111    ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 0);
 2112    if(ret <= 0)
 2113      goto ex;
 2114    if(ret == 2) {
 2115      target_is_regular= 1;
 2116      open_mode |= O_TRUNC;
 2117    }
 2118    if(fd == -1) {
 2119      fd= open(target, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666);
 2120      fd_opened= 1;
 2121    }
 2122  } else if(strcmp(mode, "append") == 0) {
 2123    ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 1);
 2124    if(ret <= 0)
 2125      goto ex;
 2126    target_is_regular= (ret == 2);
 2127    if(fd == -1) {
 2128      fd= open(target, O_WRONLY | O_CREAT | O_BINARY, 0666);
 2129      fd_opened= 1;
 2130      if(fd != -1 && target_is_regular) {
 2131        ret= lseek(fd, (off_t) 0, SEEK_END);
 2132        if(ret == -1) {
 2133          sprintf(xorriso->info_text,
 2134                  "-concat append: Cannot lseek(2) to file end of ");
 2135          Text_shellsafe(target, xorriso->info_text, 1);
 2136          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2137          ret= 0; goto ex;
 2138        }
 2139      }
 2140    }
 2141 
 2142  } else if(strcmp(mode, "pipe") == 0) {
 2143    ret= Xorriso_pipe_open(xorriso, "-concat pipe", progv[0], progc, progv,
 2144                           "", &fd, &forked_pid, 2 | 8);
 2145    if(ret <= 0)
 2146      goto ex;
 2147    fd_opened= 1;
 2148    prog_forked= 1;
 2149 
 2150  } else {
 2151    sprintf(xorriso->info_text, "-concat: Unknown mode ");
 2152    Text_shellsafe(mode, xorriso->info_text, 1);
 2153    strcat(xorriso->info_text, ". Known modes: overwrite, append, pipe");
 2154    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2155    ret= 0; goto ex;
 2156  }
 2157  if(fd == -1) {
 2158    sprintf(xorriso->info_text,
 2159            "-concat: Cannot open file handle to ");
 2160    Text_shellsafe(target, xorriso->info_text, 1);
 2161    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2162    ret= 0; goto ex;
 2163  }
 2164 
 2165  for(i= 0; i < filec; i++) {
 2166    ret= Xorriso_iso_file_to_fd(xorriso, filev[i], fd, 0);
 2167    if(ret <= 0) {
 2168      if(i < filec - 1) {
 2169        ret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
 2170        if(ret < 0) {
 2171          sprintf(xorriso->info_text,
 2172                  "-concat: Aborted although %d files stay unprocessed.",
 2173                  filec - i + 1);
 2174          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2175          ret= 0; goto ex;
 2176        }
 2177      }
 2178    }
 2179  }
 2180 
 2181  ret= 1; 
 2182 ex:;
 2183  if(fd_opened && fd != -1)
 2184    close(fd);
 2185  if(prog_forked)
 2186    Xorriso_wait_child_end(xorriso, forked_pid, &status, 0);
 2187  return(ret);
 2188 }
 2189 
 2190 
 2191 /* flag: bit0= *capacity is a desired value.
 2192                Try SEEK_SET with *capacity
 2193          bit1= open for writing
 2194    return:  0= no random access , -1= cannot open path
 2195             1= *capacity is valid
 2196 */
 2197 int Xorriso_lseek_capacity(struct XorrisO *xorriso, char *path,
 2198                            off_t *capacity, int flag)
 2199 {
 2200  int fd;
 2201  off_t seek_result;
 2202 
 2203  if(flag & 2)
 2204    fd= open(path, O_WRONLY);
 2205  else
 2206    fd= open(path, O_RDONLY);
 2207  if(fd < 0) {
 2208    sprintf(xorriso->info_text,
 2209            "Cannot open for determination of random-access capacity: ");
 2210            Text_shellsafe(path, xorriso->info_text, 1);
 2211    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2212    return(-1);
 2213  }
 2214  if(flag & 1) {
 2215    seek_result= lseek(fd, *capacity, SEEK_SET);
 2216  } else {
 2217    seek_result= lseek(fd, 0, SEEK_END);
 2218  }
 2219  close(fd);
 2220  if(seek_result < 0)
 2221    return(0);
 2222  *capacity= seek_result;
 2223  return(1);
 2224 }
 2225 
 2226 
 2227 /* flag: bit0= *capacity is a desired value.
 2228                If SEEK_END fails, try SEEK_SET with *capacity
 2229          bit1= open for writing
 2230    return: 0= no random access , -1= path does not exist , -2= wrong type
 2231           -3= cannot open path
 2232            1= *capacity is valid
 2233 */
 2234 int Xorriso_determine_capacity(struct XorrisO *xorriso, char *path,
 2235                                off_t *capacity, char **reason, int flag)
 2236 {
 2237  int ret;
 2238  off_t src_size, src_seek_size= -1;
 2239  struct stat stbuf;
 2240 
 2241  if(reason != NULL)
 2242    *reason= "offers no random access";
 2243  if(lstat(path, &stbuf) == -1) {
 2244    *capacity= 0;
 2245    if(reason != NULL)
 2246      *reason= "does not exist";
 2247    return(-1);
 2248  }
 2249  if(S_ISREG(stbuf.st_mode)) {
 2250    src_size= stbuf.st_size;
 2251  } else if(!(S_ISDIR(stbuf.st_mode) || S_ISLNK(stbuf.st_mode) ||
 2252              S_ISFIFO(stbuf.st_mode) || S_ISSOCK(stbuf.st_mode))) {
 2253    ret= Xorriso_lseek_capacity(xorriso, path, &src_size, flag & 2);
 2254    if(ret <= 0 || src_size <= 0) {
 2255      if(ret == -1 || !(flag & 1)) {
 2256        *capacity= 0;
 2257        if(ret == -1) {
 2258          if(reason != NULL)
 2259            *reason= "cannot be opened";
 2260          return(-3);
 2261        }
 2262        return(ret > 0);
 2263      }
 2264      if(ret > 0)
 2265        src_seek_size= 0;
 2266      src_size= *capacity;
 2267      ret= Xorriso_lseek_capacity(xorriso, path, &src_size, flag & 3);
 2268      if(ret <= 0 || src_size < src_seek_size) {
 2269        if(src_seek_size == 0) {
 2270          src_size= src_seek_size;
 2271        } else {
 2272          *capacity= 0;
 2273          if(ret == -1) {
 2274            if(reason != NULL)
 2275              *reason= "cannot be opened";
 2276            return(-3);
 2277          }
 2278          return(0);
 2279        }
 2280      }
 2281    }
 2282  } else {
 2283    *capacity= 0;
 2284    if(reason != NULL)
 2285      *reason= "is of wrong type";
 2286    return(-2);
 2287  }
 2288  *capacity= src_size;
 2289  if(reason != NULL)
 2290    *reason= "";
 2291  return(1);
 2292 }
 2293