"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/disk_ops.c" (8 Jul 2020, 62223 Bytes) of package /linux/misc/libisoburn-1.5.4.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 last Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.5.2.

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