
/*

    ( cd .. ; libisoburn-develop/xorriso/compile_xorriso.sh -g )

or

    cc -g -DXorriso_with_maiN -DXorriso_with_readlinE \
          -DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \
          -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
          -o xorriso/xorriso \
          xorriso/xorriso.c xorriso/xorrisoburn.c \
          -lz -lacl -lpthread -lreadline -lburn -lisofs -lisoburn 

or

    cc -g -DXorriso_with_readlinE \
          -DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \
          -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
          -c \
          xorriso/xorriso.c xorriso/xorrisoburn.c

*/

/* Command line oriented batch and dialog tool which creates, loads,
   manipulates and burns ISO 9660 filesystem images.

   Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>

   Initial code of this program was derived from program src/askme.c out
   of scdbackup-0.8.8, Copyright 2007 Thomas Schmitt, BSD-License.

   Provided under GPL version 2 or later, with the announcement that this
   might get changed in future. I would prefer BSD or LGPL as soon as the
   license situation of the library code allows that.
   (This announcement affects only future releases of xorriso and it will
    always be possible to derive a GPLv2+ from the future license.)

   There is a derived package "GNU xorriso" under GPLv3+ which combines the
   libburnia libraries and program xorriso to a statically linked binary.


   Overview of xorriso architecture:

   libburn provides the ability to read and write data. 

   libisofs interprets and manipulates ISO 9660 directory trees. It generates
   the output stream which is handed over to libburn.

   libisoburn encapsulates the connectivity issues between libburn and
   libisofs. It also enables multi-session emulation on overwritable media
   and random access file objects.
   xorriso is intended as reference application of libisoburn.

   xorrisoburn.[ch] encapsulate any usage of the libraries by xorriso.

   xorriso.h exposes the public functions of xorriso which are intended
   to be used by programs which link with xorriso.o. These functions are
   direct equivalents of the xorriso interpreter commands.
   There is also the API for handling event messages.

   xorriso_private.h is not to be included by other software. It encapsulates
   the inner interfaces of xorriso.

   xorriso.c provides the command interpreter as described in xorriso.1.
   It performs any activity that does not demand a reference to a symbol
   of the library APIs. This includes:
   - Interpretation of user input from arguments, dialog, and scripting.
   - Output of result text and event messages.
   - POSIX filesystem operations.
   - Public functions which perform the particular xorriso commands.
   - The main() function, if enabled by #define Xorriso_with_maiN.

*/

/* Create GNU xorriso */
#define Xorriso_GNU_xorrisO yes


#ifdef Xorriso_without_subS



#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <locale.h>

/* The official xorriso options API. "No shortcuts" */
#include "xorriso.h"



#else /* Xorriso_without_subS */



#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <dirent.h>
#include <time.h>
#include <utime.h>
#include <pwd.h>
#include <grp.h>
#include <signal.h>
#include <sys/utsname.h>
#include <sys/select.h>

/* for -charset */
#include <iconv.h>
#include <langinfo.h>
#include <locale.h>

/* eventually, this is done in xorriso_private.h : #include <regex.h> */

#ifdef Xorriso_with_readlinE
#ifdef Xorriso_with_old_readlinE
#include <readline.h>
#include <history.h>
#else /* Xorriso_with_old_readlinE */
#include <readline/readline.h>
#include <readline/history.h>
#endif /* ! Xorriso_with_old_readlinE */
#endif /* Xorriso_with_readlinE */

#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));


/* Diet facility: exclude help texts from binaries */
/* This will eventually be redefined to eat up its content */
#define AlN(x) x


/* There is only one stage of diet: Xorriso_no_helP */
#ifdef Xorriso_no_helP
#undef AlN
#define AlN(x) 
#endif


/* ------------------------------------------------------------------------ */


/* The official xorriso options API. "No shortcuts" */
#include "xorriso.h"

/* The inner description of XorrisO */
#define Xorriso_is_xorriso_selF 1
#include "xorriso_private.h"

/* The inner isofs- and burn-library interface */
#include "xorrisoburn.h"


/* ------------------------------------------------------------------------ */


#ifndef Xorriso_sfile_externaL
/* @param flag bit0= do not clip of carriage return at line end
*/
char *Sfile_fgets_n(char *line, int maxl, FILE *fp, int flag)
{
 int l;
 char *ret;

 ret= fgets(line,maxl,fp);
 if(ret==NULL)
   return(NULL);
 l= strlen(line);
 if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
 if(l > 0) if(line[l-1] == '\n') line[--l]= 0;
 if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
 return(ret);
}


int Sfile_count_components(char *path, int flag)
/*
 bit0= do not ignore trailing slash
 bit1= do not ignore empty components (other than the empty root name)
*/
{
 int l,count= 0;
 char *cpt;

 l= strlen(path);
 if(l==0)
   return(0);
 count= 1;
 for(cpt= path+l-1;cpt>=path;cpt--) { 
   if(*cpt=='/') {
     if(*(cpt+1)==0   && !(flag&1))
 continue;
     if(*(cpt+1)=='/' && !(flag&2))
 continue;
     count++;
   }
 }
 return(count);
}


int Sfile_component_pointer(char *path, char **sourcept, int idx, int flag)
/*
 bit0= do not ignore trailing slash
 bit1= do not ignore empty components (other than the empty root name)
 bit2= accept 0 as '/'
*/
{
 int count= 0;
 char *spt;

 for(spt= path;*spt!=0 || (flag&4);spt++) {
   if(count>=idx) {
     *sourcept= spt;
     return(1);
   }
   if(*spt=='/' || *spt==0) {
     if(*(spt+1)=='/' && !(flag&2))
 continue;
     if(*(spt+1)==0 && !(flag&1))
 continue;
     count++;
   }
 }
 if((flag&1) && count>=idx)
   return(1);
 return(0);
}


int Sfile_leafname(char *path, char leafname[SfileadrL], int flag)
{
 int count, ret;
 char *lpt;

 leafname[0]= 0;
 count= Sfile_count_components(path, 0);
 if(count==0)
   return(0);
 ret= Sfile_component_pointer(path, &lpt, count-1, 0);
 if(ret<=0)
   return(ret);
 if(Sfile_str(leafname, lpt, 0)<=0)
   return(0);
 lpt= strchr(leafname, '/');
 if(lpt!=NULL)
   *lpt= 0;
 return(1);
} 


int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag)
{
 int l;

 l= strlen(path);
 if(l+1>=SfileadrL)
   return(0);
 if(l==0) {
   strcpy(path,"/");
   l= 1;
 } else if(path[l-1]!='/') {
   path[l++]= '/';
   path[l]= 0;
 }
 if(l+strlen(addon)>=SfileadrL)
   return(0);
 if(addon[0]=='/')
   strcpy(path+l,addon+1);
 else
   strcpy(path+l,addon);
 return(1);
}


int Sfile_prepend_path(char *prefix, char path[SfileadrL], int flag)
{
 int l, i;

 l= strlen(path)+strlen(prefix)+1;
 if(l>=SfileadrL) {

#ifdef Not_yeT
   /* >>> ??? how to transport messages to xorriso ? */
   sprintf(xorriso->info_text,
           "Combination of wd and relative address too long (%d > %d)",
           l,SfileadrL-1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
#endif

   return(-1);
 }
 l-= strlen(path);
 for(i= strlen(path)+1; i>=0; i--)
   path[i+l]= path[i];
 strcpy(path,prefix);
 path[l-1]= '/';
 return(1);
}

int Sfile_being_group_member(struct stat *stbuf, int flag)
{
 int i, suppl_groups;
 gid_t *suppl_glist;

 if (getegid()==stbuf->st_gid)
   return(1);
 suppl_groups= getgroups(0, NULL);
 suppl_glist= (gid_t *) malloc((suppl_groups + 1) * sizeof(gid_t));
 if (suppl_glist==NULL)
   return(-1);
 suppl_groups= getgroups(suppl_groups+1,suppl_glist);
 for (i= 0; i<suppl_groups; i++) {
   if (suppl_glist[i]==stbuf->st_gid) {
     free((char *) suppl_glist);
     return(1);
   }
 }
 free((char *) suppl_glist);
 return(0);
}


int Sfile_type(char *filename, int flag)
/*
 bit0= return -1 if file is missing 
 bit1= return a hardlink with siblings as type 5
 bit2= evaluate eventual link target rather than the link object itself
 bit3= return a socket or a char device as types 7 or 8 rather than 0
*/
/*
 return:
  0=unknown
  1=regular
  2=directory
  3=symbolic link
  4=named pipe
  5=multiple hardlink (with bit1)
  6=block device
  7=socket (with bit3)
  8=character device (with bit3)
*/
{
 struct stat stbuf;
 if(flag&4) {
   if(stat(filename,&stbuf)==-1) {
     if(flag&1) return(-1);
     else       return(0);
   }
 } else {
   if(lstat(filename,&stbuf)==-1) {
     if(flag&1) return(-1);
     else       return(0);
   }
 }
 if(S_ISREG(stbuf.st_mode)) {
   if(flag&2)
     if(stbuf.st_nlink>1)
       return(5);
   return(1);
 }
 if(S_ISDIR(stbuf.st_mode))
   return(2);
 if((stbuf.st_mode&S_IFMT)==S_IFLNK)
   return(3);
 if(S_ISFIFO(stbuf.st_mode))
   return(4);
 if(S_ISBLK(stbuf.st_mode))
   return(6);
 if(flag&8)
   if((stbuf.st_mode&S_IFMT)==S_IFSOCK)
     return(7);
 if(flag&8)
   if(S_ISCHR(stbuf.st_mode))
     return(8);
 return(0);
}


char *Sfile_datestr(time_t tim, short int flag)
/*
 bit0=with hours+minutes  
 bit1=with seconds

 bit8= local time rather than UTC
*/
{
 static char zeitcode[80]={"000000"};
 char puff[80];
 struct tm *azt;

 if(flag&256) 
   azt = localtime(&tim);
 else
   azt = gmtime(&tim);
 
 if(azt->tm_year>99)
   sprintf(zeitcode,"%c%1.1d%2.2d%2.2d",
           'A'+(azt->tm_year-100)/10,azt->tm_year%10,
           azt->tm_mon+1,azt->tm_mday);
 else
   sprintf(zeitcode,"%2.2d%2.2d%2.2d",
           azt->tm_year,azt->tm_mon+1,azt->tm_mday);
 if(flag&1){
   sprintf(puff,".%2.2d%2.2d",azt->tm_hour,azt->tm_min);
   strcat(zeitcode,puff);
 }
 if(flag&2){
   sprintf(puff,"%2.2d",azt->tm_sec);
   strcat(zeitcode,puff);
 }

 return(zeitcode);
}


int Sfile_scale(double value, char *result, int siz, double thresh, int flag)
/*
 bit0= eventually ommit 'b'
 bit1= make text as short as possible
 bit2= no fraction (if it would fit at all)
*/
{
 char scale_c,scales[7],form[80], *negpt= NULL, *cpt;
 int i,dec_siz= 0,avail_siz= 1;

 if(value<0) {
   value= -value;
   siz--;
   result[0]= '-';
   negpt= result;
   result++;
 }
 strcpy(scales,"bkmgtp");
 scale_c= scales[0];
 for(i=1;scales[i]!=0;i++) {
   if(value<thresh-0.5) 
 break;
   value/= 1024.0;
   scale_c= scales[i];
 } 
 if(scale_c!='b' && !(flag&4)) { /* is there room for fractional part ? */
   avail_siz= siz-1;
   sprintf(form,"%%.f");
   sprintf(result,"%.f",value);
   if(strlen(result)<=avail_siz-2) 
     dec_siz= 1;                                  /* we are very modest */
 }
 if(scale_c=='b' && (flag&1)) {
   if(flag&2)
     sprintf(form,"%%.f");
   else
     sprintf(form,"%%%d.f",siz);
   sprintf(result,form,value);
 } else {
   if(flag&2)
     sprintf(form,"%%.f%%c");
   else if(dec_siz>0) 
     sprintf(form,"%%%d.%df%%c",avail_siz,dec_siz);
   else
     sprintf(form,"%%%d.f%%c",siz-1);
   sprintf(result,form,value,scale_c);
 }
 if(negpt != NULL) {
   for(cpt= result; *cpt==' '; cpt++);
   if(cpt > result) {
     *negpt= ' ';
     *(cpt - 1)= '-';
   } 
 }
 return(1);
}


int Sfile_off_t_text(char text[80], off_t num, int flag)
{
 char *tpt;
 off_t hnum, scale= 1;
 int digits= 0, d, i;

 tpt= text;
 hnum= num;
 if(hnum<0) {
   *(tpt++)= '-';
   hnum= -num;
 }
 if(hnum<0) { /* it can stay nastily persistent */
   strcpy(text, "_overflow_");
   return(0);
 }
 for(i= 0; i<23; i++) { /* good for up to 70 bit = 10 exp 21.07... */
   if(hnum==0)
 break;
   hnum/= 10;
   if(hnum)
     scale*= 10;
 }
 if(i==0) {
   strcpy(text, "0");
   return(1);
 }
 if(i==23) {
   strcpy(text, "_overflow_");
   return(0);
 }
 digits= i;
 hnum= num;
 for(; i>0; i--) {
   d= hnum/scale;
   tpt[digits-i]= '0'+d;
   hnum= hnum%scale;
   scale/= 10;
 }
 tpt[digits]= 0;
 return(1);
}


/* Converts backslash codes into single characters:
    \a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 ,
    \t  HT 9 , \v VT 11 , \\ \ 92 
    \[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code ,
    \cX control-x (ascii(X)-64)
   @param upto  maximum number of characters to examine for backslash.
                The scope of a backslash (0 to 3 characters) is not affected.
   @param eaten returns the difference in length between input and output
   @param flag bit0= only determine *eaten, do not convert
               bit1= allow to convert \000 to binary 0 
*/
int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
{
 char *rpt, *wpt, num_text[8], wdummy[8];
 unsigned int num= 0;

 *eaten= 0;
 wpt= text;
 for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) {
   if(flag & 1)
     wpt= wdummy;
   if(*rpt == '\\') {
     rpt++;
     (*eaten)++;
     if(*rpt == 'a') {
       *(wpt++)= 7;
     } else if(*rpt == 'b') {
       *(wpt++)= 8;
     } else if(*rpt == 'e') {
       *(wpt++)= 27;
     } else if(*rpt == 'f') {
       *(wpt++)= 12;
     } else if(*rpt == 'n') {
       *(wpt++)= 10;
     } else if(*rpt == 'r') {
       *(wpt++)= 13;
     } else if(*rpt == 't') {
       *(wpt++)= 9;
     } else if(*rpt == 'v') {
       *(wpt++)= 11;
     } else if(*rpt == '\\') {
       *(wpt++)= '\\';
     } else if(rpt[0] >= '0' && rpt[0] <= '7' &&
               rpt[1] >= '0' && rpt[1] <= '7' &&
               rpt[2] >= '0' && rpt[2] <= '7') {
       num_text[0]= '0';
       num_text[1]= *(rpt + 0);
       num_text[2]= *(rpt + 1);
       num_text[3]= *(rpt + 2);
       num_text[4]= 0;
       sscanf(num_text, "%o", &num);
       if((num > 0 || (flag & 2)) && num <= 255) {
         rpt+= 2;
         (*eaten)+= 2;
         *(wpt++)= num;
       } else
         goto not_a_code;
     } else if(rpt[0] == 'x' &&
               ((rpt[1] >= '0' && rpt[1] <= '9') ||
                (rpt[1] >= 'A' && rpt[1] <= 'F') ||
                (rpt[1] >= 'a' && rpt[1] <= 'f'))
               &&
               ((rpt[2] >= '0' && rpt[2] <= '9') ||
                (rpt[2] >= 'A' && rpt[2] <= 'F') ||
                (rpt[2] >= 'a' && rpt[2] <= 'f'))
               ) {
       num_text[0]= *(rpt + 1);
       num_text[1]= *(rpt + 2);
       num_text[2]= 0;
       sscanf(num_text, "%x", &num);
       if(num > 0 && num <= 255) {
         rpt+= 2;
         (*eaten)+= 2;
         *(wpt++)= num;
       } else
         goto not_a_code;
     } else if(*rpt == 'c') {
       if(rpt[1] > 64 && rpt[1] < 96) {
         *(wpt++)= rpt[1] - 64;
         rpt++;
         (*eaten)++;
       } else
         goto not_a_code;
     } else {
not_a_code:;
       *(wpt++)= '\\';
       rpt--;
       (*eaten)--;
     }
   } else
     *(wpt++)= *rpt;
 }
 *wpt= *rpt;
 return(1);
}


int Sfile_argv_bsl(int argc, char ***argv, int flag)
{
 int i, ret, eaten;
 char **new_argv= NULL;

 if(argc <= 0)
   return(0);
 new_argv= (char **) Smem_malloC(argc * sizeof(char *));
 if(new_argv == NULL)
   return(-1);
 for(i= 0; i < argc; i++) {
   new_argv[i]= strdup((*argv)[i]);
   if(new_argv[i] == NULL)
     {ret= -1; goto ex;}
   ret= Sfile_bsl_interpreter(new_argv[i], strlen(new_argv[i]), &eaten, 0);
   if(ret <= 0)
     goto ex;
 }
 ret= 1;
ex:;
 if(ret <= 0) {
   if(new_argv != NULL)
     free((char *) new_argv);
 } else
   *argv= new_argv;
 return(ret);
}


/* @param flag bit0= only encode inside quotes
               bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13
               bit2= encode in any case above 126
               bit3= encode in any case shellsafe and name-value-safe:
                     <=42 , 59, 60, 61, 62, 63, 92, 94, 96, >=123
*/
int Sfile_bsl_encoder(char **result, char *text, size_t text_len, int flag)
{
 char *rpt, *wpt;
 int count, sq_open= 0, dq_open= 0;

 count= 0;
 for(rpt= text; rpt - text < text_len; rpt++) {
   count++;
   if(flag & 8) {
      if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
           *rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123))
 continue;
   } else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\')
 continue;
   if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag & 8))
     count++;
   else
     count+= 3;
 }
 (*result)= wpt= calloc(count + 1, 1);
 if(wpt == NULL)
   return(-1);
 for(rpt= text; rpt - text < text_len; rpt++) {
   if(*rpt == '\'')
     sq_open= !(sq_open || dq_open);
   if(*rpt == '"')
     dq_open= !(sq_open || dq_open);
 
   if(flag & 8) {
     if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
          *rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123)) {
       *(wpt++)= *rpt; 
 continue;
     }  
   } else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') {
     *(wpt++)= *rpt;
 continue;
   } else if( ((flag & 1) && !(sq_open || dq_open)) &&
             !((flag & 2) && (*rpt >= 1 && * rpt <= 31 &&
               !(*rpt == 7 || *rpt == 8 || *rpt == 9 || *rpt == 10 ||
                 *rpt == 12 || *rpt == 13))) &&
             !((flag & 4) && (*rpt > 126 || *rpt < 0)) &&
             !((flag & 6) && *rpt == '\\')) {
     *(wpt++)= *rpt;
 continue;
   }
   *(wpt++)= '\\';
   if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag&8)) {
     if(*rpt == 7)
       *(wpt++)= 'a';
     else if(*rpt == 8)
       *(wpt++)= 'b';
     else if(*rpt == 9)
       *(wpt++)= 't';
     else if(*rpt == 10) {
       *(wpt++)= 'n';
     } else if(*rpt == 11)
       *(wpt++)= 'v';
     else if(*rpt == 12)
       *(wpt++)= 'f';
     else if(*rpt == 13)
       *(wpt++)= 'c';
     else if(*rpt == 27)
       *(wpt++)= 'e';
     else if(*rpt == '\\')
       *(wpt++)= '\\';
   } else {
     sprintf(wpt, "%-3.3o", (unsigned int) *((unsigned char *) rpt));
     wpt+= 3;
   }
 }
 *wpt= 0;
 return(1);
}


int Sfile_destroy_argv(int *argc, char ***argv, int flag)
{
 int i;

 if(*argc>0 && *argv!=NULL){
   for(i=0;i<*argc;i++){
     if((*argv)[i]!=NULL)
       Smem_freE((*argv)[i]);
   }
   Smem_freE((char *) *argv);
 }
 *argc= 0;
 *argv= NULL;
 return(1);
}


int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv,
                    int flag)
/*
 bit0= read progname as first argument from line
 bit1= just release argument list argv and return
 bit2= abort with return(0) if incomplete quotes are found
 bit3= eventually prepend missing '-' to first argument read from line
 bit4= like bit2 but only check quote completeness, do not allocate memory
 bit5+6= interpretation of backslashes:
       0= no interpretation, leave unchanged
       1= only inside double quotes
       2= outside single quotes
       3= everywhere
 bit7= append a NULL element to argv
*/
{
 int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten;
 char *cpt,*start;
 char *buf= NULL;

 Sfile_destroy_argv(argc,argv,0);
 if(flag&2)
   {ret= 1; goto ex;}

 if(flag & 16)
   flag|= 4;
 bsl_mode= (flag >> 5) & 3;

 buf= calloc(strlen(line) + SfileadrL, 1);
 if(buf == NULL)
   {ret= -1; goto ex;}
 for(pass=0;pass<2;pass++) {
   cpt= line-1;
   if(!(flag&1)){
     argzaehl= line_start_argc= 1;
     if(pass==0)
       maxl= strlen(progname);
     else
       strcpy((*argv)[0],progname);
   } else {
     argzaehl= line_start_argc= 0;
     if(pass==0) maxl= 0;
   }
   while(*(++cpt)!=0){
   if(isspace(*cpt)) continue;
     start= cpt;
     buf[0]= 0;
     cpt--;
     while(*(++cpt)!=0) {
     if(isspace(*cpt)) break;
       if(*cpt=='"'){
         l= cpt-start; bufl= strlen(buf);
         if(l>0) {
           strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
           if(bsl_mode >= 3) {
             ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
             if(ret <= 0)
               goto ex;
           }
         }
         l= strlen(buf);
         start= cpt+1;
         while(*(++cpt)!=0) if(*cpt=='"') break;
         if((flag&4) && *cpt==0)
           {ret= 0; goto ex;}
         l= cpt-start; bufl= strlen(buf);
         if(l>0) {
           strncpy(buf + bufl, start, l);
           buf[bufl + l]= 0;
           if(bsl_mode >= 1) {
             ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
             if(ret <= 0)
               goto ex;
           }
         }
         start= cpt+1;
       }else if(*cpt=='\''){
         l= cpt-start; bufl= strlen(buf);
         if(l>0) {
           strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
           if(bsl_mode >= 3) {
             ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
             if(ret <= 0)
               goto ex;
           }
         }
         l= strlen(buf);
         start= cpt+1;
         while(*(++cpt)!=0) if(*cpt=='\'') break;
         if((flag&4) && *cpt==0)
           {ret= 0; goto ex;}
         l= cpt-start; bufl= strlen(buf);
         if(l>0) {
           strncat(buf,start,l);buf[bufl+l]= 0;
           if(bsl_mode >= 2) {
             ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
             if(ret <= 0)
               goto ex;
           }
         }
         start= cpt+1;
       }
     if(*cpt==0) break;
     }
     l= cpt-start;
     bufl= strlen(buf);
     if(l>0) {
       strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
       if(bsl_mode >= 3) {
         ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
         if(ret <= 0)
           goto ex;
       }
     }
     l= strlen(buf);
     if(pass==0){
       if(argzaehl==line_start_argc && (flag&8))
         if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
           l++;
       if(l>maxl) maxl= l;
     }else{
       strcpy((*argv)[argzaehl],buf);
       if(argzaehl==line_start_argc && (flag&8))
         if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
           sprintf((*argv)[argzaehl],"-%s", buf);
     }
     argzaehl++;
   if(*cpt==0) break;
   }
   if(pass==0){
     if(flag & 16)
       {ret= 1; goto ex;}
     *argc= argzaehl;
     if(argzaehl>0 || (flag & 128)) {
       *argv= (char **) Smem_malloC((argzaehl + !!(flag & 128))
                                    * sizeof(char *));
       if(*argv==NULL)
         {ret= -1; goto ex;}
     }
     for(i=0;i<*argc;i++) {
       (*argv)[i]= (char *) Smem_malloC((maxl+1));
       if((*argv)[i]==NULL)
         {ret= -1; goto ex;}
     }
     if(flag & 128)
       (*argv)[*argc]= NULL;
   }
 }
 ret= 1;
ex:
 if(buf != NULL)
   free(buf);
 return(ret);
}


/* @param flag bit0= append */
int Sfile_str(char target[SfileadrL], char *source, int flag)
{
 int l;

 l= strlen(source);
 if(flag&1)
   l+= strlen(target);
 if(l>=SfileadrL) {
   fprintf(stderr, "--- Path string overflow (%d > %d). Malicious input ?\n",
           l,SfileadrL-1);
   return(0);
 }
 if(flag&1)
   strcat(target, source);
 else
   strcpy(target, source);
 return(1);
}


/** Combine environment variable HOME with given filename
    @param filename Address relative to $HOME
    @param fileadr Resulting combined address
    @param fa_size Size of array fileadr
    @param flag Unused yet
    @return 1=ok , 0=no HOME variable , -1=result address too long
*/
int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag)
{
 char *home;

 strcpy(fileadr,filename);
 home= getenv("HOME");
 if(home==NULL)
   return(0);
 if(strlen(home)+strlen(filename)+1>=fa_size)
   return(-1);
 strcpy(fileadr,home);
 if(filename[0]!=0){
   strcat(fileadr,"/");
   strcat(fileadr,filename);
 }
 return(1);
}


/** Return a double representing seconds and microseconds since 1 Jan 1970 */
double Sfile_microtime(int flag)
{
 struct timeval tv;
 struct timezone tz;
 gettimeofday(&tv,&tz);
 return((double) (tv.tv_sec+1.0e-6*tv.tv_usec));
}


int Sfile_decode_datestr(struct tm *reply, char *text, int flag)
/* YYMMDD[.hhmm[ss]] */
{
 int i,l;
 time_t current_time;
 struct tm *now;

 current_time= time(0);
 now= localtime(&current_time);
 for(i=0;i<sizeof(struct tm);i++)
   ((char *) reply)[i]= ((char *) now)[i];

 if(text[0]<'0'|| (text[0]>'9' && text[0]<'A') || text[0]>'Z')
   return(0);
 l= strlen(text);
 for(i=1;i<l;i++)
   if(text[i]<'0'||text[i]>'9')
     break;
 if(i!=6)
   return(0);
 if(text[i]==0)
   goto decode;
 if(text[i]!='.' || (l!=11 && l!=13))
   return(0);
 for(i++;i<l;i++)
   if(text[i]<'0'||text[i]>'9')
     break;
 if(i!=l)
   return(0);

decode:;
 reply->tm_hour= 0;
 reply->tm_min= 0;
 reply->tm_sec= 0;
 i= 0;
 if(text[0]>='A') 
   reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0';
 else
   reply->tm_year= 10*(text[0]-'0')+text[1]-'0';
 reply->tm_mon=  10*(text[2]-'0')+text[3]-'0'-1;
 reply->tm_mday= 10*(text[4]-'0')+text[5]-'0';
 if(l==6)
   return(1);
 reply->tm_hour= 10*(text[7]-'0')+text[8]-'0';
 reply->tm_min=  10*(text[9]-'0')+text[10]-'0';
 if(l==11)
   return(1);
 reply->tm_sec=  10*(text[11]-'0')+text[12]-'0';
 return(1);
}

#endif /*  Xorriso_sfile_externaL */


/* --------------------------------- misc --------------------------------- */


int Strcmp(const void *pt1, const void *pt2)
{
 return(strcmp(*((char **) pt1), *((char **) pt2)));
}


int Sort_argv(int argc, char **argv, int flag)
{
 if(argc<=0)
   return(2);
 qsort(argv,(size_t) argc,sizeof(char *),Strcmp);
 return(1);
}


static int Text_to_argv(char *text, int *argc, char ***argv, int flag)
{
 char *npt, *cpt;
 int pass;
 
 *argv= NULL;
 *argc= 0;
 for(pass= 0; pass < 2; pass++) {
   if(pass) {
     if(*argc == 0)
       return(1);
     (*argv)= calloc(*argc, sizeof(char *));
     if(*argv == NULL) {
       *argc= 0;
       return(-1);
     }
     *argc= 0;
   }
   for(npt= cpt= text; npt != NULL; cpt= npt + 1) {
     npt= strchr(cpt, '\n');
     if(pass) {
       if(npt != NULL)
         *npt= 0;
       (*argv)[*argc]= cpt;
     }
     (*argc)++;
   }
 }
 return(1);
}


static int Count_diffs(int argc1, char **argv1, int argc2, char **argv2,
                       int flag)
{
 int count= 0, i1= 0, i2= 0, cmp, end_corr= 0;

 Sort_argv(argc1, argv1, 0);
 Sort_argv(argc2, argv2, 0);

 while(1) {
   if(i1 >= argc1) {
     count+= argc2 - i2 - end_corr;
 break;
   }
   if(i2 >= argc2) {
     count+= argc1 - i1 - end_corr;
 break;
   }
   cmp= strcmp(argv1[i1], argv2[i2]);
   if(cmp == 0) {
     end_corr= 0;
     i1++;
     i2++;
   } else if(cmp > 0) {
     count++;
     end_corr= 1;
     i2++;
     if(i2 < argc2 && i1 < argc1 - 1)
       if(strcmp(argv1[i1 + 1], argv2[i2]) == 0) {
         i1++;
         end_corr= 0;
       }
   } else {
     count++;
     end_corr= 1;
     i1++;
     if(i1 < argc1 && i2 < argc2 - 1)
       if(strcmp(argv2[i2 + 1], argv1[i1]) == 0) {
         i2++;
         end_corr= 0;
       }
   }
 }
 return(count);
}


/*
   @flag        bit0= do not initialize *diff_count
   @return  <0 error , 0 = mismatch , 1 = match
*/
static int Compare_text_lines(char *text1, char *text2, int *diff_count,
                              int flag)
{
 int ret, argc1= 0, argc2= 0;
 char **argv1= NULL, **argv2= NULL, *copy1= NULL, *copy2= NULL;

 if(!(flag & 1))
   *diff_count= 0;
 if(text1 == NULL && text2 == NULL)
   return(1);
 if(text1 != NULL) {
   copy1= strdup(text1);
   if(copy1 == NULL)
     {ret= -1; goto ex;}
   ret= Text_to_argv(copy1, &argc1, &argv1, 0);
   if(ret <= 0)
     {ret= -1; goto ex;}
 }
 if(text2 != NULL) {
   copy2= strdup(text2);
   if(copy2 == NULL)
     {ret= -1; goto ex;}
   ret= Text_to_argv(copy2, &argc2, &argv2, 0);
   if(ret <= 0)
     {ret= -1; goto ex;}
 }
 ret= Count_diffs(argc1, argv1, argc2, argv2, 1);
 if(ret < 0)
   goto ex;
 *diff_count+= ret;
 ret= (*diff_count == 0);
ex:;
 if(argv1 != NULL)
   free(argv1);
 if(argv2 != NULL)
   free(argv2);
 if(copy1 != NULL)
   free(copy1);
 if(copy2 != NULL)
   free(copy2);
 return ret;
}


/** Convert a text into a number of type double and multiply it by unit code
    [kmgtpe] (2^10 to 2^60) or [s] (2048). (Also accepts capital letters.)
    @param text Input like "42", "2k", "3.14m" or "-1g"
    @param flag Bitfield for control purposes:
                bit0= return -1 rathern than 0 on failure
    @return The derived double value
*/
double Scanf_io_size(char *text, int flag)
/*
 bit0= default value -1 rather than 0
*/
{
 int c;
 double ret= 0.0;

 if(flag&1)
   ret= -1.0;
 if(text[0]==0)
   return(ret);
 sscanf(text,"%lf",&ret);
 c= text[strlen(text)-1];
 if(c=='k' || c=='K') ret*= 1024.0;
 if(c=='m' || c=='M') ret*= 1024.0*1024.0;
 if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0;
 if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0;
 if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0;
 if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0;
 if(c=='s' || c=='S') ret*= 2048.0;
 return(ret);
}


int Decode_date_input_format(struct tm *erg, char *text, int flag)
/* MMDDhhmm[[CC]YY][.ss]] */
{
 int i,l,year;
 time_t current_time;
 struct tm *now;

 current_time= time(0);
 now= localtime(&current_time);
 for(i=0;i<sizeof(struct tm);i++)
   ((char *) erg)[i]= ((char *) now)[i];

 l= strlen(text);
 for(i=0;i<l;i++)
   if(text[i]<'0'||text[i]>'9')
     break;
 if(i!=8 && i!=10 && i!=12)
   return(0);
 if(text[i]==0)
   goto decode;
 if(text[i]!='.' || l!=15)
   return(0);
 i++;
 if(text[i]<'0'||text[i]>'9')
   return(0);  
 i++;
 if(text[i]<'0'||text[i]>'9')
   return(0);

decode:; 
 /* MMDDhhmm[[CC]YY][.ss]] */
 i= 0;
 erg->tm_mon=  10*(text[0]-'0')+text[1]-'0'-1;
 erg->tm_mday= 10*(text[2]-'0')+text[3]-'0';
 erg->tm_hour= 10*(text[4]-'0')+text[5]-'0';
 erg->tm_min=  10*(text[6]-'0')+text[7]-'0';
 erg->tm_sec= 0;
 if(l==8)
   return(1);
 if(l>10){
   year= 1000*(text[8]-'0')+100*(text[9]-'0')+10*(text[10]-'0')+(text[11]-'0');
 }else{
   year= 1900+10*(text[8]-'0')+(text[9]-'0');
   if(year<1970)
     year+= 100;
 }
 erg->tm_year= year-1900;
 if(l<=12)
   return(1);
 erg->tm_sec=  10*(text[13]-'0')+text[14]-'0';
 return(1);
}


int Decode_date_weekday(char *text, int flag)
{
 int i;
 static char days[][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", ""};

 for(i= 0; days[i][0]!=0; i++)
   if(strncmp(text,days[i],3)==0)
     return(i);
 if((strlen(text)==3 || (strlen(text)==4 && text[3]==',')) &&
    isalpha(text[0]) && isalpha(text[1]) && isalpha(text[2]))
   return(7);
 return(-1);
}


int Decode_date_month(char *text, int flag)
{
 int i;
 static char months[][4]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};

 for(i= 0; months[i][0]!=0; i++)
   if(strncmp(text,months[i],3)==0)
     return(i);
 return(-1);
}


/* @return -1=not a number, -2=not a day , 1 to 31 day of month */
int Decode_date_mday(char *text, int flag)
{
 int ret, i;

 for(i= 0; text[i]!=0; i++)
   if(!isdigit(text[i]))
     return(-1);
 if(strlen(text)>2 || text[0]==0)
   return(-2);
 sscanf(text, "%d", &ret);
 if(ret<=0 || ret>31)
   return(-2);
 return(ret); 
}

int Decode_date_hms(char *text, struct tm *erg, int flag)
{
 int i, hour= -1, minute= -1, second= 0;

 for(i= 0; i<9; i+= 3) {
   if(i==6&&text[i]==0)
 break;
   if(!isdigit(text[i]))
     return(-1);
   if(!isdigit(text[i+1]))
     return(-1);
   if(text[i+2]!=':' && !(text[i+2]==0 && i>=3))
     return(-1);
   if(i==0)
     sscanf(text+i,"%d",&hour);
   else if(i==3)
     sscanf(text+i,"%d",&minute);
   else
     sscanf(text+i,"%d",&second);
 }
 if(hour<0 || hour>23 || minute<0 || minute>59 || second>59)
   return(-1);
 erg->tm_hour= hour;
 erg->tm_min= minute;
 erg->tm_sec= second;
 return(1);
}


/* @return -1=not a number, -2=not a year , >=0 years AD */
int Decode_date_year(char *text, int flag)
{
 int ret, i;

 for(i= 0; text[i]!=0; i++)
   if(!isdigit(text[i]))
     return(-1);
 if(strlen(text)!=4)
   return(-2);
 sscanf(text, "%d", &ret);
 if(ret<0 || ret>3000)
   return(-2);
 return(ret); 
}


int Decode_date_timezone(char *text, struct tm *erg, int flag)
{
 int i;
 static char tzs[][5]= {"GMT", "CET", "CEST", "0000", ""};

 for(i= 0; tzs[i][0]!=0; i++)
   if(strcmp(text,tzs[i])==0) {

     /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */

     return(1);
   }
 if(text[0]=='+' || text[0]=='-') {
   for(i= 1; text[i]!=0; i++)
     if(!isdigit(text[i]))
       return(-1);
   if(i!=5)
     return(-1);

   /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */

   return(1);
 } else {
   for(i= 0; text[i]!=0; i++)
     if(text[i]<'A' || text[i]>'Z')
       return(-1);
   if(i!=3 && i!=4)
     return(-1);
   return(2);
 }
}


int Decode_date_output_format(struct tm *erg, char *text, int flag)
/* Thu Nov  8 09:07:50 CET 2007 */
/* Sat, 03 Nov 2007 08:58:30 +0100 */
/* Nov  7 23:24 */
{
 int ret, i, argc= 0, seen_year= 0, seen_month= 0, seen_day= 0, seen_time= 0;
 char **argv= NULL;
 struct tm *now;
 time_t timep;

 memset(erg, 0, sizeof(*erg));
 erg->tm_isdst= -1;
 ret= Sfile_make_argv("xorriso", text, &argc, &argv, 0);
 if(ret<=0)
   goto ex;
 for(i= 1; i<argc; i++) {
   if(!seen_month) {
     ret= Decode_date_month(argv[i], 0);
     if(ret>=0) {
       seen_month= 1;
       erg->tm_mon= ret;
 continue;
     }
   }
   if(!seen_day) {
     ret= Decode_date_mday(argv[i], 0);
     if(ret>0) {
       seen_day= 1;
       erg->tm_mday= ret;
 continue;
     }
     if(ret==-2) /* first pure number must be day of month */
       {ret= 0; goto ex;}
   }
   if(!seen_time) {
     ret= Decode_date_hms(argv[i], erg, 0);
     if(ret>0) {
       seen_time= 1;
 continue;
     }
   }
   if(!seen_year) {
     ret= Decode_date_year(argv[i], 0);
     if(ret>0) {
       erg->tm_year= ret-1900;
       seen_year= 1;
 continue;
     }
   }

   /* ignorants have to stay at the end of the loop */

   ret= Decode_date_timezone(argv[i], erg, 0);
   if(ret>=0)
 continue;
   ret= Decode_date_weekday(argv[i], 0);
   if(ret>=0)
 continue; /* ignore weekdays */

   {ret= 0; goto ex;} /* unrecognizable component */
 }

 if(!(seen_day && seen_month))
  {ret= 0; goto ex;}
 if(!seen_year) { /* then use this year */
   timep= time(NULL);
   now= localtime(&timep);
   erg->tm_year= now->tm_year;
 }   
 ret= 1;
ex:
 Sfile_make_argv("", "", &argc, &argv, 2); /* release storage */
 return(ret);
}


int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag)
   /* 2007.11.07.225624 */
{
 char buf[20];
 int year,month,day,hour= 0,minute= 0,second= 0, i, l, mem;

 memset(erg, 0, sizeof(*erg));
 erg->tm_isdst= -1;

 l= strlen(code);
 if(l>17 || l<10)
   return(0);
 strcpy(buf, code);
 for(i= 0; buf[i]!=0 && i<4; i++)
   if(!isdigit(buf[i]))
     return(0);
 if(buf[4]!='.')
   return(0);
 buf[4]= 0;
 sscanf(buf, "%d", &year);
 if(year<1900 || year>3000)
   return(0);
 if(!(isdigit(buf[5]) && isdigit(buf[6]) && buf[7]=='.'))
   return(0);
 buf[7]= 0;
 sscanf(buf+5, "%d", &month);
 if(month<1 || month>12)
   return(0);
 if(!(isdigit(buf[8]) && isdigit(buf[9]) && (buf[10]=='.' || buf[10]==0)))
   return(0);
 buf[10]= 0;
 sscanf(buf+8, "%d", &day);
 if(day<1 || day>31)
   return(0);
 if(l==10)
   goto done;
 if(!(isdigit(buf[11]) && isdigit(buf[12]) &&
      (isdigit(buf[13]) || buf[13]==0)))
   return(0);
 mem= buf[13];
 buf[13]= 0;
 sscanf(buf+11, "%d", &hour);
 buf[13]= mem;
 if(hour<0 || hour>23)
   return(0);
 if(l==13)
   goto done;
 if(!(isdigit(buf[13]) && isdigit(buf[14]) &&
      (isdigit(buf[15]) || buf[15]==0)))
   return(0);
 mem= buf[15];
 buf[15]= 0;
 sscanf(buf+13, "%d", &minute);
 buf[15]= mem;
 if(minute<0 || minute>59)
   return(0);
 if(l==15)
   goto done;
 if(!(isdigit(buf[15]) && isdigit(buf[16]) && buf[17]==0))
   return(0);
 sscanf(buf+15, "%d", &second);
 if(second<0 || second>59)
   return(0);

done:;
 erg->tm_year= year-1900;
 erg->tm_mon= month-1;
 erg->tm_mday= day;
 erg->tm_hour= hour;
 erg->tm_min= minute;
 erg->tm_sec= second;
 return(1);
}


time_t Decode_timestring(char *code, time_t *date, int flag)
{
 char *cpt,scale_chr;
 double value,seconds;
 struct tm result_tm;
 int seconds_valid= 0;

 *date= 0;
 cpt= code;
 if(code[0]=='-' || code[0]=='+' || code[0]=='=' || code[0]=='@'){
   if(code[1]==0)
     return(0);
   if(!isdigit(code[1]))
     return(0);
   value= -1;
   if(code[0]=='=' || code[0]=='@') {
     seconds= 0;
     sscanf(code+1,"%lf",&value);
   } else {
     seconds= time(NULL);
     sscanf(code,"%lf",&value);
   }
   scale_chr= code[strlen(code)-1];
   if(isalpha(scale_chr))
     scale_chr= tolower(scale_chr);
   if     (scale_chr=='s') seconds+= 1.0*value;
   else if(scale_chr=='h') seconds+= 3600.0*value;
   else if(scale_chr=='d') seconds+= 86400.0*value;
   else if(scale_chr=='w') seconds+= 86400.0*7.0*value;
   else if(scale_chr=='m') seconds+= 86400.0*31.0*value;
   else if(scale_chr=='y') seconds+= 86400.0*(365.25*value+1.0);
   else                    seconds+= 1.0*value;
   seconds_valid= 1;
   goto completed;
 } else if(Sfile_decode_datestr(&result_tm,code,0)>0) {
   /* YYMMDD[.hhmm[ss]] */
   result_tm.tm_isdst= -1;
   seconds= mktime(&result_tm);
   seconds_valid= 1;
   goto completed;
 } else if(Decode_date_input_format(&result_tm,code,0)>0) {
   /* MMDDhhmm[[CC]YY][.ss]] */
   result_tm.tm_isdst= -1;
   seconds= mktime(&result_tm);
   seconds_valid= 1;
   goto completed;
 } else if(Decode_xorriso_timestamp(&result_tm, code, 0)>0) {
   /* 2007.11.07.225624 */
   seconds= mktime(&result_tm);
   seconds_valid= 1;
   goto completed;
 } else if(Decode_date_output_format(&result_tm, code, 0)>0) {
   /* Thu Nov  8 09:07:50 CET 2007 */;
   /* Sat, 03 Nov 2007 08:58:30 +0100 */;
   /* Nov  7 23:24 */;
   seconds= mktime(&result_tm);
   seconds_valid= 1;
   goto completed;
 }
 return(0);
completed:;
 if(!seconds_valid)
   return(0);
 *date= seconds;
 return(1);
}


/* @param flag bit0=with year and seconds
               bit1-3= form
                       0= ls -l format
                       1= timestamp format YYYY.MM.DD.hhmmss
                       2= Wdy Mon Day hh:mm:ss Year
                       3= Mon Day hh:mm:ss Year
                       4= YYMMDD.hhmmss
*/
char *Ftimetxt(time_t t, char timetext[40], int flag)
{
 char *rpt;
 struct tm tms, *tmpt;
 static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 static char days[7][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
 int form;

 form= (flag>>1)&7;
 tmpt= localtime_r(&t, &tms);
 rpt= timetext;
 rpt[0]= 0;
 if(tmpt==0)
   sprintf(rpt+strlen(rpt), "%12.f", (double) t);
 else if (form==1)
   sprintf(rpt+strlen(rpt), "%4.4d.%2.2d.%2.2d.%2.2d%2.2d%2.2d",
           1900+tms.tm_year, tms.tm_mon+1, tms.tm_mday,
           tms.tm_hour, tms.tm_min, tms.tm_sec);
 else if (form==2)
   sprintf(rpt+strlen(rpt), "%s %s %2.2d %2.2d:%2.2d:%2.2d %4.4d",
           days[tms.tm_wday], months[tms.tm_mon], tms.tm_mday,
           tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year);
 else if (form==3)
   sprintf(rpt+strlen(rpt), "%s %2.2d %2.2d:%2.2d:%2.2d %4.4d",
           months[tms.tm_mon], tms.tm_mday,
           tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year);
 else if (form == 4) {
   if(tms.tm_year>99)
     sprintf(rpt+strlen(rpt), "%c", 'A' + (tms.tm_year - 100) / 10);
   else
     sprintf(rpt+strlen(rpt), "%c", '0' + tms.tm_year / 10);
   sprintf(rpt+strlen(rpt), "%1.1d%2.2d%2.2d.%2.2d%2.2d%2.2d",
           tms.tm_year % 10, tms.tm_mon + 1, tms.tm_mday,
           tms.tm_hour, tms.tm_min, tms.tm_sec);
 } else if (flag&1)
   sprintf(rpt+strlen(rpt), "%2d %3s %4.4d %2.2d:%2.2d:%2.2d",
           tms.tm_mday, months[tms.tm_mon], 1900+tms.tm_year,
           tms.tm_hour, tms.tm_min, tms.tm_sec);
 else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0)
   sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d",
           months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min);
 else
   sprintf(rpt+strlen(rpt), "%3s %2d  %4.4d",
           months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year);
 return(timetext);
}


/* @param flag bit0= single letters */
char *Ftypetxt(mode_t st_mode, int flag)
{
 if(flag&1)
   goto single_letters;
 if(S_ISDIR(st_mode))
   return("directory");
 else if(S_ISREG(st_mode))
   return("regular_file");
 else if(S_ISLNK(st_mode))
   return("symbolic_link");
 else if(S_ISBLK(st_mode))
   return("block_device");
 else if(S_ISCHR(st_mode))
   return("char_device");
 else if(S_ISFIFO(st_mode))
   return("name_pipe");
 else if(S_ISSOCK(st_mode))
   return("unix_socket");
 return("unknown");
single_letters:;
 if(S_ISDIR(st_mode))
   return("d");
 else if(S_ISREG(st_mode))
   return("-");
 else if(S_ISLNK(st_mode))
   return("l");
 else if(S_ISBLK(st_mode))
   return("b");
 else if(S_ISCHR(st_mode))
   return("c");
 else if(S_ISFIFO(st_mode))
   return("p");
 else if(S_ISSOCK(st_mode))
   return("s");
 return("?");
}


int Wait_for_input(int fd, int microsec, int flag)
{
 struct timeval wt;
 fd_set rds,wts,exs;
 int ready;

 FD_ZERO(&rds);
 FD_ZERO(&wts);
 FD_ZERO(&exs);
 FD_SET(fd,&rds);
 FD_SET(fd,&exs);
 wt.tv_sec=  microsec/1000000;
 wt.tv_usec= microsec%1000000;
 ready= select(fd+1,&rds,&wts,&exs,&wt);
 if(ready<=0)
   return(0);
 if(FD_ISSET(fd,&exs))
   return(-1);
 if(FD_ISSET(fd,&rds))
   return(1);
 return(0);
}


int System_uname(char **sysname, char **release, char **version,
                 char **machine, int flag)
{
 int ret;
 static struct utsname uts;
 static int initialized= 0;
 
 if(initialized == 0) {
   ret= uname(&uts);
   if(ret != 0)
     initialized = -1;
 }
 if(initialized == -1)
   return(0);
 if(sysname != NULL)
   *sysname= uts.sysname;
 if(release != NULL)
   *release= uts.release;
 if(version != NULL)
   *version= uts.version;
 if(machine != NULL)
   *machine= uts.machine;
 return(1);
}

/* ------------------------------------------------------------------------ */


#ifndef Xorriso_sregex_externaL

#ifndef Smem_malloC
#define Smem_malloC malloc
#endif
#ifndef Smem_freE
#define Smem_freE free
#endif


int Sregex_string_cut(char **handle, char *text, int len, int flag)
/*
 bit0= append (text!=NULL)
*/
{
 int l=0;
 char *old_handle;

 if((flag&1)&&*handle!=NULL)
   l+= strlen(*handle);
 old_handle= *handle;
 if(text!=NULL) {
   l+= len;
   *handle= TSOB_FELD(char,l+1);
   if(*handle==NULL) {
     *handle= old_handle;
     return(0);
   }
   if((flag&1) && old_handle!=NULL)
     strcpy(*handle,old_handle);
   else
     (*handle)[0]= 0;
   if(len>0)
     strncat(*handle,text,len);
 } else {
   *handle= NULL;
 }
 if(old_handle!=NULL)
   Smem_freE(old_handle);
 return(1);
}


int Sregex_string(char **handle, char *text, int flag)
/*
 bit0= append (text!=NULL)
*/
{
 int ret,l=0;

 if(text!=NULL)
   l= strlen(text);
 
/* #define Sregex_looking_for_contenT 1 */
#ifdef Sregex_looking_for_contenT
 /* a debugging point if a certain text content has to be caught */
 if(text!=NULL)
   if(strcmp(text,"clear")==0)
     ret= 0;
#endif

 ret= Sregex_string_cut(handle,text,l,flag&1);
 return(ret);
}


/*
  vars[][0] points to the variable names, vars[][1] to their contents. 
  start marks the begin of variable names. It must be non-empty. esc before
  start disables this meaning. start and esc may be equal but else they must
  have disjoint character sets.
  end marks the end of a variable name. It may be empty but if non-empty it
  must not appear in vars[][0].
  @param flag bit0= Substitute unknown variables by empty text
                    (else copy start,name,end unaltered to result).
                    Parameter end must be non-empty for that.
*/
int Sregex_resolve_var(char *form, char *vars[][2], int num_vars,
                       char *start, char *end, char *esc,
                       char *result, int result_size, int flag)
{
 int l_e, l_v, l_s, l_esc, i, start_equals_esc;
 char *rpt, *wpt, *spt, *npt, *ept;

 if(start[0] == 0) /* It is not allowed to have no start marker */
   return(-1);
 l_s= strlen(start);
 l_e= strlen(end);
 l_esc= strlen(esc);
 start_equals_esc= !strcmp(start, esc);
 rpt= form;
 wpt= result;
 wpt[0]= 0;
 while(1) {

   /* look for start mark */
   spt= strstr(rpt, start);
   if(spt == NULL) {
     if((wpt - result) + strlen(rpt) >= result_size)
       return(0);
     strcpy(wpt, rpt);
     wpt+= strlen(wpt);
 break;
   }

   /* copy cleartext part up to next variable */
   if((wpt - result) + (spt - rpt) >= result_size)
     return(0);
   strncpy(wpt, rpt, spt - rpt);
   wpt+= spt - rpt;
   *wpt= 0;
   rpt= spt;
   npt= spt + l_s;

   /* handle eventual escape */
   if(start_equals_esc) {
     if(strncmp(spt + l_s, esc, l_esc) == 0) {
       /* copy esc and start */
       if((wpt - result) + l_esc + l_s >= result_size)
         return(0);
       strncpy(wpt, spt, l_esc + l_s);
       wpt+= l_esc + l_s;
       rpt+= l_esc + l_s;
       *wpt= 0;
 continue;
     }
   } else {
     /* escape would be already copied */
     if(l_esc > 0 && spt - form >= l_esc) {
       if(strncmp(spt - l_esc, esc, l_esc) == 0) {
         /* copy start */
         if((wpt - result) + l_s >= result_size)
           return(0);
         strncpy(wpt, spt, l_s);
         wpt+= l_s;
         rpt+= l_s;
       *wpt= 0;
 continue;
       }
     }
   }

   /* Memorize eventual end mark for default handling */;
   ept= NULL;
   if(l_e > 0)
     ept= strstr(npt, end);

   /* Look for defined variable name */
   for(i = 0; i < num_vars; i++) {
     if(strncmp(npt, vars[i][0], strlen(vars[i][0])) == 0
        && (l_e == 0 || strncmp(npt + strlen(vars[i][0]), end, l_e) == 0))
   break;
   }
   if(i < num_vars) {
     /* substitute found variable */
     l_v= strlen(vars[i][0]);
     if((wpt - result) + strlen(vars[i][1]) >= result_size)
       return(0);
     strcpy(wpt, vars[i][1]);
     rpt= npt + strlen(vars[i][0]) + l_e;
   } else if((flag & 1) && ept != NULL) {
     /* skip up to end mark */
     rpt= ept + l_e;
   } else if(ept != NULL) {
     /* copy start,name,end */
     if((wpt - result) + (ept - rpt) + l_e >= result_size)
       return(0);
     strncpy(wpt, rpt, (ept - rpt) + l_e);
     rpt= ept + l_e;
   } else {
     /* copy start marker only */
     if((wpt - result) + l_s >= result_size)
       return(0);
     strncpy(wpt, rpt, l_s);
     rpt= rpt + l_s;
   }
   wpt+= strlen(wpt);
   *wpt= 0;
 }
 return(1);
}


/* @param flag bit0= only test expression whether compilable
*/
int Sregex_match(char *pattern, char *text, int flag)
{
 int ret;
 char re_text[2*SfileadrL];
 regex_t re;
 regmatch_t match[1];

 Xorriso__bourne_to_reg(pattern, re_text, 0);
 ret= regcomp(&re, re_text, 0);
 if(ret != 0) 
   return(-1);
 if(flag & 1) {
   regfree(&re);
   return(1);
 }
 ret= regexec(&re, text, 1, match, 0);
 regfree(&re);
 if(ret != 0)
     return(0);
 return(1);
}


#endif /*  Xorriso_sregex_externaL */



/* @param flag bit0= append to out_text rather than overwrite it
*/
char *Text_shellsafe(char *in_text, char *out_text, int flag)
{
 int l,i,ol= 0,w=0;

 if(flag&1)
   ol= w= strlen(out_text);
 /* enclose everything by hard quotes */
 l= strlen(in_text);
 out_text[w++]= '\'';
 for(i=0;i<l;i++){
   if(in_text[i]=='\''){
     if(w+7>5*SfileadrL+ol)
       goto overflow;
     /* escape hard quote within the text */
     out_text[w++]= '\'';
     out_text[w++]= '"';
     out_text[w++]= '\'';
     out_text[w++]= '"';
     out_text[w++]= '\'';
   } else {
     if(w+3>5*SfileadrL) {
overflow:;
       strncpy(out_text, "'xorriso: TEXT MUCH TOO LONG ...   ",33);
 break;
     }
     out_text[w++]= in_text[i];
   }
 }
 out_text[w++]= '\'';
 out_text[w++]= 0;
 return(out_text);
}


#ifndef Xorriso_fileliste_externaL 

/* ??? ts A71006 : Is this compatible with mkisofs pathspecs ?
                   I dimly remember so */

int Fileliste__target_source_limit(char *line, char sep, char **limit_pt,
                                    int flag)
{
 char *npt;

 for(npt= line;*npt!=0;npt++) {
   if(*npt=='\\') {
     if(*(npt+1)!=0)
       npt++;
 continue;
   }
   if(*npt=='=')
 break;
 }
 if(*npt==0)
   npt= NULL;
 (*limit_pt)= npt;
 return(npt!=NULL);
}

#endif /* ! Xorriso_fileliste_externaL */


/* ------------------------------------------------------------------------ */
/* DirseQ : crawl along a directory's content list */

static int Dirseq_buffer_sizE= 100;

struct DirseQ {
  char adr[SfileadrL];
  DIR *dirpt;
  int count;  
  char **buffer;
  int buffer_size;
  int buffer_fill;
  int buffer_rpt;

  struct DirseQ *next;
};

int Dirseq_destroy(struct DirseQ **o, int flag);
int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count,
                         int max_replies, int flag);


int Dirseq_new(struct DirseQ **o, char *adr, int flag)
/*
 bit0= with non-fatal errors do not complain about failed opendir() 
*/
{
 int ret,i,severe_error;
 struct DirseQ *m;

 m= *o= TSOB_FELD(struct DirseQ,1);
 if(m==NULL)
   return(-1);
 m->adr[0]= 0;
 m->dirpt= NULL;
 m->count= 0;
 m->buffer= NULL;
 m->buffer_size= 0;
 m->buffer_fill= 0;
 m->buffer_rpt= 0;
 m->next= NULL;
 if(Sfile_str(m->adr, adr, 0)<=0)
   {ret= 0; goto failed;}
 m->buffer= TSOB_FELD(char *,Dirseq_buffer_sizE);
 if(m->buffer==NULL)
   {ret= -1; goto failed;}
 m->buffer_size= Dirseq_buffer_sizE;
 for(i= 0;i<m->buffer_size;i++)
   m->buffer[i]= NULL;
 if(adr[0]==0)
   m->dirpt= opendir(".");
 else
   m->dirpt= opendir(adr);
 if(m->dirpt==NULL) {
   severe_error= (errno && errno!=ENOENT && errno!=EACCES && errno!=ENOTDIR);
   if(severe_error || !(flag&1))
     fprintf(stderr,"opendir(%s) failed : %s\n",adr,strerror(errno));
   ret= -severe_error;
   goto failed;
 }
 return(1);
failed:;
 Dirseq_destroy(o,0);
 return(ret);
}


int Dirseq_destroy(struct DirseQ **o, int flag)
{
 int i;

 if(*o==NULL)
   return(0);
 if((*o)->dirpt!=NULL)
   closedir((*o)->dirpt);
 if((*o)->buffer!=NULL) {
   for(i=0;i<(*o)->buffer_size;i++)
     if((*o)->buffer[i]!=NULL)
       free((*o)->buffer[i]);
   free((char *) (*o)->buffer);
 }
 free((char *) *o);
 (*o)= NULL;
 return(1);
}


int Dirseq_set_next(struct DirseQ *o, struct DirseQ *next, int flag)
{
 o->next= next;
 return(1);
}


int Dirseq_get_next(struct DirseQ *o, struct DirseQ **next, int flag)
{
 *next= o->next;
 return(1);
}


int Dirseq_get_adr(struct DirseQ *o, char **adrpt, int flag)
{
 *adrpt= o->adr;
 return(1);
}


int Dirseq_rewind(struct DirseQ *o, int flag)
{
 rewinddir(o->dirpt);
 return(1);
}


int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag)
/*
flag:
 bit0= permission to use buffer
 bit1= do not increment counter
 bit2= ignore buffer in any case
 bit3= do not exclude '.' and '..'
 bit4= sort buffer
 bit5= sort only incomplete last buffer
return:
 <0 error
 0= no more entries available
 1= ok, reply is valid
*/
{
 int ret;
 struct dirent *entry;
 char *name;

 static int override_flag_0= 0,override_flag_1= 32;
 flag= (flag&~override_flag_0)|override_flag_1;

 if((flag&1) && o->buffer_rpt>=o->buffer_fill) {
   /* permission to buffer and buffer empty : load a buffer */
   ret= Dirseq_next_adrblock(o,o->buffer,&(o->buffer_fill),
                             o->buffer_size,2|4|(flag&16));
   if(ret<=0)
     return(ret);
   o->buffer_rpt= 0;
   if((flag&32) && o->buffer_fill<o->buffer_size && o->buffer_fill>0) 
     Sort_argv(o->buffer_fill,o->buffer,0);
 }
 if(o->buffer_rpt<o->buffer_fill && !(flag&4)) {
   ret= Sfile_str(reply,o->buffer[o->buffer_rpt],0);
   Sregex_string(&(o->buffer[o->buffer_rpt]),NULL,0);
   if(ret<=0)
     return(-1);
   (o->buffer_rpt)++;
   if(!(flag&2))
     o->count++;
   return(1);
 }
 do {
   entry= readdir(o->dirpt);
   if(entry==NULL) {
     /* >>> how to distinguish error from EOF , do i need a (FILE *) ? */
     return(0);
   }
   if(strlen(entry->d_name)>=SfileadrL) {
     fprintf(stderr,"--- oversized directory entry (number %d) :\n    %s",
                    o->count+1,entry->d_name);
     return(-1);
   }
   name= entry->d_name;
   if(flag&8)
 break;
   /* skip "." and ".." */
 } while(name[0]=='.' && ((name[1]=='.' && name[2]==0) || name[1]==0));
 if(Sfile_str(reply,name,0)<=0)
   return(-1);
 if(!(flag&2))
   o->count++;
 return(1);
}


int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count,
                         int max_replies, int flag)
/* @param replies A vector of Sregex_string pointers */
/*
flag:
 bit0= permission to use buffer
 bit1= do not increment counter
 bit2= ignore buffer in any case
 bit4= sort replies
return:
 <0 error
 0= no more entries available
 1= ok, reply is valid
*/
{
 int i,ret;
 char reply[SfileadrL];

 *reply_count= 0;
 for(i=0;i<max_replies;i++) {
   ret= Dirseq_next_adr(o,reply,flag&(1|2|4));
   if(ret<0)
     return(ret);
   if(ret==0)
 break;
   if(Sregex_string(&(replies[i]),reply,0)<=0)
     return(-1);
   (*reply_count)++;
 }
 if((*reply_count)==0)
   return(0);
 if(flag&16) 
   Sort_argv(*reply_count,replies,0);
 return(1);
}


/* --------------------------------- Xorriso_lsT --------------------------- */


/*
 @param flag Bitfield for control purposes
        bit0= insert before link rather than after it
        bit1= do not copy data (e.g. because *data is invalid)
        bit2= attach data directly by pointer rather than by copying
*/
int Xorriso_lst_new_binary(struct Xorriso_lsT **lstring, char *data,
                           int data_len, struct Xorriso_lsT *link, int flag)
{
 int ret;
 struct Xorriso_lsT *s;

 s= TSOB_FELD(struct Xorriso_lsT,1);
 if(s==NULL)
   return(-1);
 s->text= NULL;
 s->next= s->prev= NULL;

 if(flag & 4) {
   s->text= data;
 } else {
   if(data_len<=0)
     {ret= -1; goto failed;}
   s->text= Smem_malloC(data_len);
   if(s->text==NULL)
     {ret= -1; goto failed;}
   if(!(flag&2))
     memcpy(s->text,data,data_len);
 }

 if(link==NULL) {
   ;
 } else if(flag&1) {
   s->next= link;
   s->prev= link->prev;
   if(link->prev!=NULL) 
     link->prev->next= s;
   link->prev= s;
 } else {
   s->prev= link;
   s->next= link->next;
   if(link->next!=NULL) 
     link->next->prev= s;
   link->next= s;
 }
 *lstring= s;
 return(1);
failed:;
 *lstring= s;
 Xorriso_lst_destroy(lstring,0);
 return(-1);
}


/*
 @param flag Bitfield for control purposes
             see Xorriso_lst_new_binary()
*/
int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text,
                    struct Xorriso_lsT *link, int flag)
{
 int ret;

 ret= Xorriso_lst_new_binary(lstring,text,strlen(text)+1,link,flag);
 return(ret);
}


/*
 @param flag Bitfield for control purposes
             bit0= do not set *lstring to NULL
*/
int Xorriso_lst_destroy(struct Xorriso_lsT **lstring, int flag)
{
 struct Xorriso_lsT *s;

 s= *lstring;
 if(s==NULL)
   return(0);
 if(s->prev!=NULL)
   s->prev->next= s->next;
 if(s->next!=NULL)
   s->next->prev= s->prev;
 if(s->text!=NULL)
   Smem_freE(s->text);
 Smem_freE((char *) s);
 if(!(flag&1))
   *lstring= NULL;
 return(1);
}


int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag)
{
 struct Xorriso_lsT *s,*next;

 if(lstring==NULL)
   return(-1);
 if((*lstring)==NULL)
   return(0);
 for(s= *lstring; s->prev!=NULL; s= s->prev);
 for(;s!=NULL;s= next){
   next= s->next;
   Xorriso_lst_destroy(&s,0);
 }
 *lstring= NULL;
 return(1);
}


int Xorriso_lst_append_binary(struct Xorriso_lsT **entry,
                              char *data, int data_len, int flag)
{
 struct Xorriso_lsT *target= NULL,*newby;

 if(*entry!=NULL)
   for(target= *entry; target->next!=NULL; target= target->next);
 if(Xorriso_lst_new_binary(&newby, data, data_len, target, flag & ~1)<=0)
   return(-1);
 if(*entry==NULL || (flag & 1))
   *entry= newby;
 return(1);
}


struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag)
{
 return(entry->next);
}


struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag)
{
 return(entry->prev);
}


char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag)
{
 return(entry->text);
}


int Xorriso_lst_detach_text(struct Xorriso_lsT *entry, int flag)
{
 entry->text= NULL;
 return(1);
}


/* ------------------------------ LinkiteM -------------------------------- */

struct LinkiteM {
 char *link_path;
 dev_t target_dev;
 ino_t target_ino;
 int link_count;
 struct LinkiteM *next;
};

int Linkitem_destroy(struct LinkiteM **o, int flag);


int Linkitem_new(struct LinkiteM **o, char *link_path, dev_t target_dev,
                 ino_t target_ino, struct LinkiteM *next, int flag)
{
 struct LinkiteM *m;

 m= *o= TSOB_FELD(struct LinkiteM,1);
 if(m==NULL)
   return(-1);
 m->target_dev= target_dev;
 m->target_ino= target_ino;
 m->next= next;
 m->link_count= 1;
 if(next!=NULL)
   m->link_count= m->next->link_count+1;
 m->link_path= strdup(link_path);
 if(m->link_path==NULL)
   goto failed;
 return(1);
failed:;
 Linkitem_destroy(o, 0);
 return(-1);
}


int Linkitem_destroy(struct LinkiteM **o, int flag)
{
 if((*o)==NULL)
   return(0);
 if((*o)->link_path!=NULL)
   free((*o)->link_path);
 free((char *) (*o));
 *o= NULL;
 return(1);
}


int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag)
{
 struct LinkiteM *m, *m_next= NULL;

 /* Prevent memory corruption */
 for(m= *o;  m!=to; m= m->next)
   if(m==NULL) { /* this may actually not happen */
     *o= to;
     return(-1);
   }

 for(m= *o; m!=to; m= m_next) {
   m_next= m->next;
   Linkitem_destroy(&m, 0);
 }
 *o= to;
 return(1);
}


int Linkitem_find(struct LinkiteM *stack, dev_t target_dev, ino_t target_ino,
                  struct LinkiteM **result, int flag)
{
 struct LinkiteM *m;

 for(m= stack; m!=NULL; m= m->next) {
   if(target_dev == m->target_dev && target_ino == m->target_ino) {
     *result= m;
     return(1);
   }
 }
 return(0);
}


/* ----------------------- Exprtest ----------------------- */


int Exprtest_new( struct ExprtesT **ftest, struct FindjoB *boss, int flag)
{
 struct ExprtesT *f;

 *ftest= f= TSOB_FELD(struct ExprtesT,1);
 if(f==NULL)
   return(-1);
 f->boss= boss;
 f->invert= 0;
 f->test_type= -1;
 f->arg1= NULL;
 f->arg2= NULL;
 return(1);
}


int Exprtest_destroy(struct ExprtesT **ftest, int flag)
{
 struct ExprtesT *f;
 
 f= *ftest;
 if(f==NULL)
   return(0);

 if(f->test_type == 1) {
   if(f->arg1 != NULL)
     free(f->arg1);
   if(f->arg2 != NULL) {
     regfree(f->arg2);
     free(f->arg2);
   }
 } else if(f->test_type == 9) {
   /* arg1 is not an allocated value */;
 } else {
   if(f->arg1 != NULL)
     free(f->arg1);
   if(f->arg2 != NULL)
     free(f->arg2);
 }
 free((char *) f);
 *ftest= NULL;
 return(1);
}


/* ----------------------- Nttpfnode ----------------------- */


int Exprnode_new(struct ExprnodE **fnode, struct FindjoB *job,
                 struct ExprnodE *up, char *origin, int flag)
/*
 bit0= set invert-property
 bit1= set use_shortcuts
*/
{
 struct ExprnodE *n;
 int ret,i;

 *fnode= n= TSOB_FELD(struct ExprnodE,1);
 if(n == NULL)
   return(-1);
 for(i= 0; i < sizeof(n->origin); i++)
   n->origin[i]= 0;
 strncpy(n->origin, origin, sizeof(n->origin) - 1);
 n->up= up;
 n->invert= (flag & 1);
 n->assoc= 0;
 n->use_shortcuts= !!(flag & 2);
 n->left= NULL;
 n->left_op= -1;
 n->right= NULL;
 n->right_op= -1;
 n->sub= NULL;
 n->is_if_then_else= 0;
 n->true_branch= NULL;
 n->false_branch= NULL;
 n->test= NULL;
 n->own_value= -1;
 n->composed_value= -1;

 ret= Exprtest_new(&(n->test), job, 0);
 if(ret<=0){
   Exprnode_destroy(fnode, 0);
   return(-1);
 }
 return(1);
}


int Exprnode_destroy(struct ExprnodE **fnode, int flag)
{
 if(*fnode == NULL)
   return(0);
 Exprnode_destroy(&((*fnode)->right),0);
 Exprnode_destroy(&((*fnode)->sub),0);
 Exprnode_destroy(&((*fnode)->true_branch),0);
 Exprnode_destroy(&((*fnode)->false_branch),0);
 Exprtest_destroy(&((*fnode)->test),0);
 free((char *) *fnode);
 *fnode= NULL;
 return(1);
}


int Exprnode_set_is_if(struct ExprnodE *fnode, int value, int flag)
{
 fnode->is_if_then_else= value;
 return(1);
}


int Exprnode_is_if(struct ExprnodE *fnode, int flag)
{
  return(fnode->is_if_then_else);
}


int Exprnode_set_branch(struct ExprnodE *fnode, struct ExprnodE *target,
                        int flag)
/*
 bit0= false_branch (else true_branch)
*/
{
 struct ExprnodE **branch;

 if(flag&1) 
   branch= &(fnode->false_branch);
 else
   branch= &(fnode->true_branch);
 Exprnode_destroy(branch,0);
 (*branch)= target;
 return(1);
}


int Exprnode_get_branch(struct ExprnodE *fnode, struct ExprnodE **branch,
                        int flag)
/*
 bit0= false_branch (else true_branch)
*/
{
 if(flag&1) 
   (*branch)= fnode->false_branch;
 else
   (*branch)= fnode->true_branch;
 return(1);
}


int Exprnode_is_defined(struct ExprnodE *fnode, int flag)
{
 struct ExprtesT *ftest;

 if(fnode==NULL)
   return(0);
 if(fnode->sub!=NULL)
   return(1);
 ftest= fnode->test;
 if(ftest==NULL)
   return(0);
 if(ftest->test_type>=0)
   return(1);
 return(0);
}


int Exprnode_own_value(struct XorrisO *xorriso, struct ExprnodE *fnode, 
                       void *node, char *name, char *path,
                       struct stat *boss_stbuf, struct stat *stbuf, int flag)
/*
flag:
return: (also from Exprtest_match() and Exprnode_tree_value() )
 <0 = error
  0 = does not match
  1 = does match
  2 = immediate decision : does not match
  3 = immediate decision : does match
*/
{
 int ret;

 if(fnode==NULL)
   return(1);
 if(fnode->sub!=NULL) {
   ret= Exprnode_tree_value(xorriso, fnode->sub, -1,
                            node, name, path, boss_stbuf, stbuf, 0);
 } else {
   ret= Exprtest_match(xorriso, fnode->test, node, name, path,
                       boss_stbuf, stbuf, 0);
 }
 if(ret<0)
   return(ret);
 if(ret>1)
   return(ret);
 if(fnode->invert)
   ret= !ret;
 return(ret);
}


int Exprnode_op(int value1, int value2, int op, int flag)
{
 int ret;

 if(op==0)
   ret= value1 || value2 ;
 else
   ret= value1 && value2 ;
 return(ret);
}


int Exprnode_tree_value(struct XorrisO *xorriso, struct ExprnodE *fnode,
                        int left_value, void *node, char *name, char *path,
                        struct stat *boss_stbuf, struct stat *stbuf, int flag)
/*
 bit0-7= testmode: 0=head , 1=filename
return: (also from Nntpftest_match() and Nntpfnode_own_value() )
 <0 = error
  0 = does not match
  1 = does match
  2 = immediate decision : does not match
  3 = immediate decision : does match
*/
{
 int value= 1,ret;

 if(fnode==NULL)
   return(1);
 if(!Exprnode_is_defined(fnode,0))
   return(1);

 if(fnode->use_shortcuts && fnode->left!=NULL){
   fnode->composed_value= left_value;
   if(fnode->left_op==0) {/* OR */
     if(left_value!=0) 
       goto ex;
   } else {                /* AND */
     if(left_value==0)
       goto ex;
   }
 }
 fnode->composed_value= fnode->own_value= 
    Exprnode_own_value(xorriso, fnode, node, name, path, boss_stbuf, stbuf, 0);
 if(fnode->own_value < 0 || fnode->own_value > 1)
   return(fnode->own_value);

 if(fnode->assoc == 0){ /* left associative */
   if(fnode->left != NULL && left_value >= 0)
     fnode->composed_value= 
       Exprnode_op(left_value, fnode->own_value, fnode->left_op, 0);
   /* compute right value */
   /* is the right value relevant ? */
   if(fnode->right!=NULL){
     if(fnode->use_shortcuts){
       if(fnode->right_op==0) {/* OR */
         if(fnode->composed_value!=0)
           goto ex;
       } else {                /* AND */
         if(fnode->composed_value==0)
           goto ex;
       }  
     }
     value= Exprnode_tree_value(xorriso, fnode->right,fnode->composed_value,
                               node, name, path, boss_stbuf, stbuf, 0);
     if(value<0 || value>1)
       return(value);
     fnode->composed_value= value;
   }
 }else{ /* right associative */
   if(fnode->right!=NULL){
     /* is the right value relevant ? */
     if(fnode->use_shortcuts){
       if(fnode->right_op==0) {/* OR */
         if(fnode->composed_value!=0)
           goto ex;
       } else {                /* AND */
         if(fnode->composed_value==0)
           goto ex;
       }
     }
     value= Exprnode_tree_value(xorriso, fnode->right,fnode->own_value,
                               node, name, path, boss_stbuf, stbuf, 0);
     if(value<0||value>1)
       return(value);
   } else
     value= fnode->own_value;
   fnode->composed_value= value;
   if(fnode->left!=NULL && left_value>=0)
     fnode->composed_value=
       Exprnode_op(left_value,fnode->composed_value,fnode->left_op,0);
 }
ex:
 ret= fnode->composed_value;
 if(fnode->is_if_then_else) {
   /* The if-condition is evaluated. Now follow the chosen branch */
   struct ExprnodE *branch;
   if(ret>0) 
     branch= fnode->true_branch;
   else 
     branch= fnode->false_branch;
   if(branch!=NULL) {
     ret= Exprnode_tree_value(xorriso, branch, -1,
                              node, name, path, boss_stbuf, stbuf, 0);
     if(ret<0)
       return(ret);
     if(ret>1)
       return(ret);
   }
   fnode->composed_value= ret;
 }
 return(fnode->composed_value);
}


/* --------------------- Findjob -------------------- */


int Findjob_new(struct FindjoB **o, char *start_path, int flag)
{
 struct FindjoB *m;
 int ret;

 m= *o= TSOB_FELD(struct FindjoB,1);
 if(m==NULL)
   return(-1);
 m->start_path= NULL;
 m->test_tree= NULL;
 m->cursor= NULL;
 m->invert= 0;
 m->use_shortcuts= 1;
 m->action= 0; /* print */
 m->prune= 0;
 m->target= NULL; /* a mere pointer, not managed memory */
 m->text_2= NULL; /* a mere pointer, not managed memory */
 m->user= 0;
 m->group= 0;
 m->type= 0;
 m->date= 0;
 m->start_path= strdup(start_path);
 if(m->start_path==NULL)
   goto failed;
 m->found_path= NULL;
 m->subjob= NULL;

 ret= Exprnode_new(&(m->test_tree), m, NULL, "-find", (m->use_shortcuts)<<1);
 if(ret<=0)
   goto failed;
 m->cursor= m->test_tree;
 return(1);

failed:;
 Findjob_destroy(o, 0);
 return(-1);
}


int Findjob_destroy(struct FindjoB **o, int flag)
{
 struct FindjoB *m;
 
 m= *o;
 if(m==NULL)
   return(0);
 if(m->test_tree != NULL)
   Exprnode_destroy(&(m->test_tree), 0); 
 free((char *) *o);
 *o= NULL;
 return(1);
}


int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag)
{
 if(o->start_path!=NULL)
   free(o->start_path);
 if(start_path!=NULL) {
   o->start_path= strdup(start_path);
   if(o->start_path==NULL)
     return(-1);
 } else
   o->start_path= NULL;
 return(1);
}


int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag)
{
 *start_path= o->start_path;
 return(1);
}


int Findjob_cursor_complete( struct FindjoB *job, int flag)
{
 int ret;

 if(job==NULL)
   return(0);
 ret= Exprnode_is_defined(job->cursor,0);
 return(ret);
}


int Findjob_is_restrictive(struct FindjoB *job, int flag)
{
 if(job == NULL)
   return(0);
 if(job->test_tree == NULL)
   return(0);
 if(!Exprnode_is_defined(job->test_tree, 0))
   return(0);
 return(1);
}


int Findjob_new_node(struct FindjoB *job, struct ExprnodE **fnode,
                     char *origin, int flag)
/*
 bit0= open new branch 
 bit1= with bit1 : do not register as sub-node of job->cursor
*/
{
 int ret;
 struct ExprnodE *f;

 ret= Exprnode_new(fnode,job,NULL,origin,
                   job->invert|((job->use_shortcuts)<<1));
 if(ret<=0)
   return(ret);
 f= *fnode;
 if(flag&1) {
   f->up= job->cursor;
   if(job->cursor!=NULL && !(flag&2)) {
     if(job->cursor->sub!=NULL) {
       /* This would become a memory leak */
       job->errn= -2;
       sprintf(job->errmsg,
               "Program error while parsing -job : sub branch overwrite");
       return(0);
     } else
       job->cursor->sub= f;
   }
 } else {
   f->up= job->cursor->up;
   f->left= job->cursor;
   if(job->cursor!=NULL)
     job->cursor->right= f;
 }
 job->invert= 0;
 return(1);
}


/* If an operator is expected : use -and
   @param flag bit0= prepare for a pseudo-test:
                     if an operator is expected, do nothing and return 2
*/
int Findjob_default_and(struct FindjoB *o, int flag)
{
 int ret;

 if(Findjob_cursor_complete(o, 0)) {
   if(flag & 1) 
     return(2);
   ret= Findjob_and(o, 0);
   if(ret <= 0)
     return(ret);
 }
 return(1);
}


int Findjob_open_bracket(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode;

 ret= Findjob_default_and(job, 0);
 if(ret <= 0)
   return(ret);
 ret= Findjob_new_node(job, &fnode, "-sub", 1);
 if(ret <= 0)
   return(ret);
 job->cursor= fnode;
 return(1);
}


int Findjob_close_bracket(struct FindjoB *job, int flag)
{
 if(!Findjob_cursor_complete(job, 0)) {
   job->errn= -3;
   sprintf(job->errmsg,
     "Unary operator or expression expected, closing-bracket found");
   return(0);
 }

 if(job->cursor->up==NULL){
   job->errn= -1;
   sprintf(job->errmsg,
           "No bracket open when encountering closing bracket.");
   return(0);
 }
 job->cursor= job->cursor->up;
 return(1);
}


int Findjob_not(struct FindjoB *job, int flag)
{
 int ret;

 ret= Findjob_default_and(job, 0);
 if(ret <= 0)
   return(ret);
 job->cursor->invert= !job->cursor->invert;
 return(1);
}


int Findjob_and(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode;

 if(!Findjob_cursor_complete(job, 0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, binary operator found");
   return(0);
 }

 ret= Findjob_new_node(job, &fnode, "-and", 0);
 if(ret<=0)
   return(ret);
 job->cursor->right_op= 1;
 job->cursor->assoc= 1;        /* compute right side first */
 fnode->left_op= 1;
 fnode->assoc= 0;              /* compute left side first */
 job->cursor= fnode;
 return(1);
}


int Findjob_or(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode;

 if(!Findjob_cursor_complete(job, 0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, binary operator found");
   return(0);
 }

 ret= Findjob_new_node(job, &fnode, "-or", 0);
 if(ret<=0)
   return(ret);
 job->cursor->right= fnode;
 job->cursor->right_op= 0;
                                    /* if existing : compute left side first */
 job->cursor->assoc= (job->cursor->left == NULL);
 fnode->left= job->cursor;
 fnode->left_op= 0;
 fnode->assoc= 0;            /* no right side yet : compute left side first */
 job->cursor= fnode;
 return(1);
}


int Findjob_if(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode;

 ret= Findjob_default_and(job, 0);
 if(ret <= 0)
   return(ret);
 ret= Findjob_new_node(job, &fnode, "-if", 1);
 if(ret<=0)
   return(ret);
 Exprnode_set_is_if(fnode,1,0);
 job->cursor= fnode;
 return(1);
}


int Findjob_then(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode,*branch= NULL;

 if(! Findjob_cursor_complete(job,0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, -then-operator found");
   return(0);
 } 
 /* Finding the -if that matches this -then
    Do not go up one node but look for the leftmost one.
    If everything is right we are at level of the -if node */
 while(job->cursor->left!=NULL)
   job->cursor= job->cursor->left;
 Exprnode_get_branch(job->cursor, &branch, 0);
 if(!Exprnode_is_if(job->cursor, 0) || branch != NULL) {
   job->errn= -5;
   sprintf(job->errmsg, "-then-operator found outside its proper range.");
   return(0);
 }
 ret= Findjob_new_node(job, &fnode, "-then", 1|2);
 if(ret <= 0)
   return(ret);
 Exprnode_set_branch(job->cursor, fnode, 0);
 job->cursor= fnode;
 return(1);
}


int Findjob_else(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *fnode, *true_branch, *false_branch;

 if(! Findjob_cursor_complete(job, 0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, -else-operator found");
   return(0);
 } 
 if(job->cursor->up == NULL)
   goto improper_range;
 job->cursor= job->cursor->up;
 Exprnode_get_branch(job->cursor, &true_branch, 0);
 Exprnode_get_branch(job->cursor, &false_branch, 1);
 if(!Exprnode_is_if(job->cursor, 0) || 
    true_branch == NULL || false_branch != NULL) {
improper_range:;
   job->errn= -5;
   sprintf(job->errmsg, "-else-operator found outside its proper range.");
   return(0);
 }
 ret= Findjob_new_node(job, &fnode, "-else", 1 | 2);
 if(ret <= 0)
   return(ret);
 Exprnode_set_branch(job->cursor, fnode, 1);
 job->cursor= fnode;
 return(1);
}


int Findjob_elseif(struct FindjoB *job, int flag)
{
 int ret;
 struct ExprnodE *true_branch, *false_branch;

 if(!Findjob_cursor_complete(job, 0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, -elseif-operator found");
   return(0);
 } 
 if(job->cursor->up == NULL)
   goto improper_range;
 job->cursor= job->cursor->up;
 Exprnode_get_branch(job->cursor, &true_branch, 0);
 Exprnode_get_branch(job->cursor, &false_branch, 1);
 if(!Exprnode_is_if(job->cursor, 0) || 
    true_branch==NULL || false_branch!=NULL) {
improper_range:;
   job->errn= -5;
   sprintf(job->errmsg,
           "-elseif-operator found outside its proper range.");
   return(0);
 }
 job->cursor= job->cursor->up;
 /* -elseif is equivalent to the three-step sequence :  -endif -or -if
    ( -endif has already been performed by following job->cursor->up ) */
 ret= Findjob_or(job, 0);
 if(ret <= 0)
   return(0);
 ret= Findjob_if(job, 0);
 if(ret <= 0)
   return(0);
 return(1);
}


int Findjob_endif(struct FindjoB *job, int flag)
{
 struct ExprnodE *true_branch;

 if(!Findjob_cursor_complete(job,0)) {
   job->errn= -3;
   sprintf(job->errmsg,
           "Unary operator or expression expected, -endif found");
   return(0);
 }
 if(job->cursor->up==NULL)
   goto improper_range;
 /* test wether parent node is -if */
 job->cursor= job->cursor->up;
 Exprnode_get_branch(job->cursor, &true_branch, 0);
 if(!Exprnode_is_if(job->cursor,0) || true_branch == NULL) {
improper_range:;
   job->errn= -5;
   sprintf(job->errmsg, "-endif-mark found outside its proper range.");
   return(0);
 }
 /* go to grand parent node */
 job->cursor= job->cursor->up;
 return(1);
}


/* @param flag bit0= -wholename rather than -name
*/
int Findjob_set_name_expr(struct FindjoB *o, char *name_expr, int flag)
{
 char regexpr[2*SfileadrL+2];
 regex_t *name_re;
 struct ExprtesT *t;
 int ret;
   
 if(strlen(name_expr)>=SfileadrL)
   return(0);

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);
 t= o->cursor->test;
 t->test_type= (flag & 1 ? 13 : 1);
 name_re= (regex_t *) calloc(1, sizeof(regex_t));
 if(name_re == NULL)
   return(-1);
 t->arg1= strdup(name_expr);
 if(t->arg1 == NULL) {
   free((char *) name_re);
   return(-1);
 }
 Xorriso__bourne_to_reg(name_expr, regexpr, 0);
 if(regcomp(name_re, regexpr, 0) != 0)
   return(0);
 t->arg2= name_re;
 return(1);
}


int Findjob_set_file_type(struct FindjoB *o, char file_type, int flag)
{
 static char known[]= {"bcdpf-lsmeX"};
 struct ExprtesT *t;
 int ret;

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);

 if(file_type != 0)
   if(strchr(known, file_type) == NULL)
     return(0);
 t= o->cursor->test;
 t->test_type= 2;
 t->arg1= calloc(1, 1);
 if(t->arg1 == NULL)
   return(-1);
 *((char *) t->arg1)= file_type;
 return(1);
}

 
/* @param value -1= only without property, 1= only with property
   @param flag bit0= pseudo-test:
                     if no operator is open, do nothing and return 2
*/
int Findjob_set_prop_filter(struct FindjoB *o, int test_type, int value,
                            int flag)
{
 struct ExprtesT *t;
 int ret;

 ret= Findjob_default_and(o, flag & 1);
 if(ret <= 0 || ret == 2)
   return(ret);

 t= o->cursor->test;
 t->test_type= test_type;
 if(value < 0)
   t->invert= !t->invert;
 return(1);
}
 
 
/* @param value -1= only undamaged files, 1= only damaged files
*/
int Findjob_set_damage_filter(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 3, value, 0);
 return(ret);
}
 

int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count,
                          int flag)
{
 struct ExprtesT *t;
 int ret;

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);

 t= o->cursor->test;
 t->test_type= 4;
 t->arg1= calloc(sizeof(int), 1);
 t->arg2= calloc(sizeof(int), 1);
 if(t->arg1 == NULL || t->arg2 == NULL)
   return(-1);
 *((int *) t->arg1)= start_lba;
 if(start_lba > 0)
   *((int *) t->arg2)= start_lba + count - 1;
 else
   *((int *) t->arg2)= start_lba - count + 1;
 return(1);
}


/* @param value -1= files without ACL, 1= only files with ACL
*/
int Findjob_set_acl_filter(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 5, value, 0);
 return(ret);
}


/* @param value -1= files without xattr, 1= only files with xattr
   @param flag bit0=-has_any_xattr rather than -has_xattr
*/
int Findjob_set_xattr_filter(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, (flag & 1 ? 14 : 6), value, 0);
 return(ret);
}


/* @param value -1= files without aaip, 1= only files with aaip
*/
int Findjob_set_aaip_filter(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 7, value, 0);
 return(ret);
}


/* @param value -1= files without filter, 1= files with filter
*/
int Findjob_set_filter_filter(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 8, value, 0);
 return(ret);
}


int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag)
{
 struct ExprtesT *t;
 int ret;

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);

 t= o->cursor->test;
 t->test_type= 9;
 t->arg1= wanted_node;
 return(1);
}


int Findjob_set_commit_filter_2(struct FindjoB *o, int flag)
{
 int ret;

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);

 o->cursor->test->test_type= 10;
 return(1);
}


int Findjob_set_decision(struct FindjoB *o, char *decision, int flag)
{
 struct ExprtesT *t;
 int ret;

 ret= Findjob_default_and(o, 0);
 if(ret <= 0)
   return(ret);

 t= o->cursor->test;
 t->test_type= 11;
 t->arg1= strdup(decision);
 if(t->arg1 == NULL)
   return(-1);
 return(1);
}


/* @param value -1= true, 1= false
   @param flag bit0= pseudo-test:
                     if no operator is open, do nothing and return 2
*/
int Findjob_set_false(struct FindjoB *o, int value, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 0, value, flag & 1);
 return(ret);
}


int Findjob_set_prune(struct FindjoB *o, int flag)
{
 int ret;

 ret= Findjob_set_prop_filter(o, 12, 0, 0);
 return(ret);
}


int Findjob_set_found_path(struct FindjoB *o, char *path, int flag)
{
 if(o->found_path != NULL)
   free(o->found_path);
 if(path != NULL) {
   o->found_path= strdup(path);
   if(o->found_path == NULL)
     return(-1);
 } else
   o->found_path= NULL;
 return(1);
}


int Findjob_get_found_path(struct FindjoB *o, char **path, int flag)
{
 *path= o->found_path;
 return(1);
}


int Findjob_get_action(struct FindjoB *o, int flag)
{
 return(o->action);
}  


/* @return <0 error, >=0 see above struct FindjoB.action
*/
int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,
                             uid_t *user, gid_t *group,
                             mode_t *mode_and, mode_t *mode_or,
                             int *type, time_t *date, struct FindjoB **subjob,
                             int flag)
{
 *target= o->target;
 *text_2= o->text_2;
 *user= o->user;
 *group= o->group;
 *mode_and= o->mode_and;
 *mode_or= o->mode_or;
 *type= o->type;
 *date= o->date;
 *subjob= o->subjob;
 return(o->action);
}


int Findjob_test_2(struct XorrisO *xorriso, struct FindjoB *o,
                   void *node, char *name, char *path,
                   struct stat *boss_stbuf, struct stat *stbuf, int flag)
{
 int ret;

 ret= Exprnode_tree_value(xorriso, o->test_tree, -1,
                          node, name, path, boss_stbuf, stbuf, 0);
 if(ret == 3)
   ret= 1;
 else if(ret == 2)
   ret= 0;
 return(ret);
}


int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
                              int flag)
{
 o->action= action;
 o->target= target;
 return(1);
}


int Findjob_set_action_text_2(struct FindjoB *o, int action, char *target,
                              char* text_2, int flag)
{
 o->action= action;
 o->target= target;
 o->text_2= text_2;
 return(1);
}


/* @param flag bit0= recursive
*/
int Findjob_set_action_chown(struct FindjoB *o, uid_t user,int flag)
{
 int ret;

 if(flag&1) {
   o->action= 0;
   Findjob_destroy(&(o->subjob), 0);
   ret= Findjob_new(&(o->subjob), "", 0);
   if(ret<=0)
     return(-1);
   Findjob_set_action_chown(o->subjob, user, 0);
   o->action= 9;
 } else {
   o->action= 4;
   o->user= user;
 }
 return(1);
}


/* @param flag bit0= recursive
*/
int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag)
{
 int ret;

 if(flag&1) {
   o->action= 0;
   Findjob_destroy(&(o->subjob), 0);
   ret= Findjob_new(&(o->subjob), "", 0);
   if(ret<=0)
     return(-1);
   Findjob_set_action_chgrp(o->subjob, group, 0);
   o->action= 10;
 } else {
   o->action= 5;
   o->group= group;
 }
 return(1);
}


/* @param flag bit0= recursive
*/
int Findjob_set_action_chmod(struct FindjoB *o,
                             mode_t mode_and, mode_t mode_or, int flag)
{
 int ret;

 if(flag&1) {
   o->action= 0;
   Findjob_destroy(&(o->subjob), 0);
   ret= Findjob_new(&(o->subjob), "", 0);
   if(ret<=0)
     return(-1);
   Findjob_set_action_chmod(o->subjob, mode_and, mode_or, 0);
   o->action= 11;
 } else {
   o->action= 6;
   o->mode_and= mode_and;
   o->mode_or= mode_or;
 }
 return(1);
}


/* @param flag bit0= recursive
*/
int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag)
{
 int ret;

 if(flag&1) {
   o->action= 0;
   Findjob_destroy(&(o->subjob), 0);
   ret= Findjob_new(&(o->subjob), "", 0);
   if(ret<=0)
     return(-1);
   Findjob_set_action_ad(o->subjob, type, date, 0);
   o->action= 12;
 } else {
   o->action= 7;
   o->type= type;
   o->date= date;
 }
 return(1);
}


int Findjob_set_action_subjob(struct FindjoB *o, int action,
                              struct FindjoB *subjob, int flag)
{
 o->action= action;
 Findjob_destroy(&(o->subjob), 0);
 o->subjob= subjob;
 return(1);
}


int Findjob_set_action_found_path(struct FindjoB *o, int flag)
{
 o->action= 23;
 Findjob_set_found_path(o, NULL, 0);
 return(1);
}


/* ---------------------------- SplitparT ------------------------- */


struct SplitparT {
 char *name;
 int partno;
 int total_parts;
 off_t offset;
 off_t bytes;
 off_t total_bytes;
};

static char Splitpart_wordS[][16]= {"part_", "_of_", "_at_", "_with_", "_of_"};


int Splitparts_new(struct SplitparT **o, int count, int flag)
{
 int i;

 (*o)= TSOB_FELD(struct SplitparT, count);
 if((*o)==NULL)
   return(-1);
 for(i= 0; i<count; i++) {
   (*o)[i].name= NULL;
   (*o)[i].partno= 0;
   (*o)[i].total_parts= 0;
   (*o)[i].offset= 0;
   (*o)[i].bytes= 0;
   (*o)[i].total_bytes= 0;
 }
 return(1);
}


int Splitparts_destroy(struct SplitparT **o, int count, int flag)
{
 int i;

 if((*o)==NULL)
   return(0);
 for(i= 0; i<count; i++) {
   if((*o)[i].name!=NULL)
     free((*o)[i].name);
 }
 free(*o);
 *o= NULL;
 return(1);
}


int Splitparts_set(struct SplitparT *o, int idx,
                   char *name, int partno, int total_parts,
                   off_t offset, off_t bytes, off_t total_bytes, int flag)
{
 if(o[idx].name!=NULL)
   free(o[idx].name);
 o[idx].name= strdup(name);
 if(o[idx].name==NULL)
   return(-1);
 o[idx].partno= partno;
 o[idx].total_parts= total_parts;
 o[idx].offset= offset;
 o[idx].bytes= bytes;
 o[idx].total_bytes= total_bytes;
 return(1);
}


int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno,
                   int *total_parts, off_t *offset, off_t *bytes,
                   off_t *total_bytes, int flag)
{
 *name= o[idx].name;
 *partno= o[idx].partno;
 *total_parts= o[idx].total_parts;
 *offset= o[idx].offset;
 *bytes= o[idx].bytes;
 *total_bytes= o[idx].total_bytes;
 return(1);
}


int Splitpart__read_next_num(char *base_pt, char **next_pt, off_t *num,
                             int flag)
{
 char *cpt, *ept, scale[4];
 double sfak;

 *num= 0;
 for(cpt= base_pt; *cpt!=0 && !isdigit(*cpt); cpt++);
 if(*cpt==0)
   return(0);
 for(ept= cpt; *ept!=0 && isdigit(*ept); ept++)
   *num= (*num)*10+(*ept)-'0';
 scale[0]= '1';
 scale[1]= *ept;
 scale[2]= 0;
 sfak= Scanf_io_size(scale, 0);
 *num *= (off_t) sfak;
 if(sfak > 1.0)
   ept++;
 *next_pt= ept;
 return(1);
}


int Splitpart__parse(char *name, int *partno, int *total_parts,
                    off_t *offset, off_t *bytes, off_t *total_bytes, int flag)

{
 int ret; 
 off_t num;
 char *cpt, *ept;

 cpt= name;
 if(strncmp(cpt, Splitpart_wordS[0], strlen(Splitpart_wordS[0])) != 0)
   return(0);
 ret= Splitpart__read_next_num(cpt, &ept, &num, 0);
 if(ret<=0)
   return(ret);
 *partno= num;
 cpt= ept;
 if(strncmp(cpt, Splitpart_wordS[1], strlen(Splitpart_wordS[1])) != 0)
   return(0);
 ret= Splitpart__read_next_num(cpt, &ept, &num, 0);
 if(ret<=0)
   return(ret);
 *total_parts= num;
 cpt= ept;
 if(strncmp(cpt, Splitpart_wordS[2], strlen(Splitpart_wordS[2])) != 0)
   return(0);
 ret= Splitpart__read_next_num(cpt, &ept, offset, 0);
 if(ret<=0)
   return(ret);
 cpt= ept;
 if(strncmp(cpt, Splitpart_wordS[3], strlen(Splitpart_wordS[3])) != 0)
   return(0);
 ret= Splitpart__read_next_num(cpt, &ept, bytes, 0);
 if(ret<=0)
   return(ret);
 cpt= ept;
 if(strncmp(cpt, Splitpart_wordS[4], strlen(Splitpart_wordS[4])) != 0)
   return(0);
 ret= Splitpart__read_next_num(cpt, &ept, total_bytes, 0);
 if(ret<=0)
   return(ret);
 if(*ept != 0)
   return(0);
 return(1);
}


int Splitpart__is_part_path(char *path, int flag)
{
 int partno, total_parts, ret;
 off_t offset, bytes, total_bytes;
 char *name;

 name= strrchr(path, '/');
 if(name == NULL)
   name= path;
 else
   name++;
 ret= Splitpart__parse(name, &partno, &total_parts, &offset, &bytes,
                       &total_bytes, 0);
 return(ret > 0);
}


/* part_#_of_#_at_#_with_#_of_#
*/
int Splitpart__compose(char *adr, int partno, int total_parts,
                       off_t offset, off_t bytes, off_t total_bytes, int flag)
{
 sprintf(adr, "%s%d%s%d%s", Splitpart_wordS[0], partno, Splitpart_wordS[1],
                            total_parts, Splitpart_wordS[2]);
 if((offset % (1024*1024))==0 && offset>0) {
   Sfile_off_t_text(adr+strlen(adr), offset / (1024*1024), 0);
   strcat(adr, "m");
 } else
   Sfile_off_t_text(adr+strlen(adr), offset, 0);
 strcat(adr, Splitpart_wordS[3]); 
 if((bytes % (1024*1024))==0) {
   Sfile_off_t_text(adr+strlen(adr), bytes / (1024*1024), 0);
   strcat(adr, "m");
 } else
   Sfile_off_t_text(adr+strlen(adr), bytes, 0);
 strcat(adr, Splitpart_wordS[4]);
 Sfile_off_t_text(adr+strlen(adr), total_bytes, 0);
 return(1);
}


int Splitparts_cmp(const void *v1, const void *v2)
{
 struct SplitparT *p1, *p2;

 p1= (struct SplitparT *) v1;
 p2= (struct SplitparT *) v2;
 
 if(p1->partno>p2->partno)
   return(1);
 if(p1->partno<p2->partno)
   return(-1);
 if(p1->offset>p2->offset)
   return(1);
 if(p1->offset<p2->offset)
   return(-1);
 return(0);
}


int Splitparts_sort(struct SplitparT *o, int count, int flag)
{
 qsort(o, (size_t) count, sizeof(struct SplitparT), Splitparts_cmp);
 return(1);
}


/* ---------------------------- End SplitparT ------------------------- */

/* ------------------------------ ExclusionS ------------------------------ */

struct ExclusionS {

 /* Absolute input patterns which lead to not_paths */
 struct Xorriso_lsT *not_paths_descr;

 /* Actually banned absolute paths */
 struct Xorriso_lsT *not_paths;

 /* Input patterns which lead to not_leafs */
 struct Xorriso_lsT *not_leafs_descr;

 /* Compiled not_leaf patterns. Caution: not char[] but  regex_t */
 struct Xorriso_lsT *not_leafs;
 
};


int Exclusions_new(struct ExclusionS **o, int flag)
{
 struct ExclusionS *m;

 m= *o= TSOB_FELD(struct ExclusionS, 1);
 if(m==NULL)
   return(-1);
 m->not_paths_descr= NULL;
 m->not_paths= NULL;
 m->not_leafs_descr= NULL;
 m->not_leafs= NULL;
 return(1);
}


int Exclusions_destroy(struct ExclusionS **o, int flag)
{
 struct Xorriso_lsT *s,*next;

 if((*o)==NULL)
   return(0);
 Xorriso_lst_destroy_all(&((*o)->not_paths_descr), 0);
 Xorriso_lst_destroy_all(&((*o)->not_paths), 0);
 Xorriso_lst_destroy_all(&((*o)->not_leafs_descr), 0);
 for(s= (*o)->not_leafs; s!=NULL; s= next){
   next= s->next;
   regfree((regex_t *) s->text);
   Xorriso_lst_destroy(&s, 0);
 }
 free((char *) *o);
 (*o)= NULL;
 return(1);
}


int Exclusions_add_not_paths(struct ExclusionS *o, int descrc, char **descrs,
                             int pathc, char **paths, int flag)
{
 struct Xorriso_lsT *s, *new_s;
 int i, ret;

 s= NULL;
 if(o->not_paths_descr!=NULL) 
   for(s= o->not_paths_descr; s->next!=NULL; s= s->next);
 for(i= 0; i<descrc; i++) {
   ret= Xorriso_lst_new(&new_s, descrs[i], s, 0);
   if(ret<=0)
     return(ret);
   if(o->not_paths_descr==NULL)
     o->not_paths_descr= new_s;
   s= new_s;
 }
 s= NULL;
 if(o->not_paths!=NULL) 
   for(s= o->not_paths; s->next!=NULL; s= s->next);
 for(i= 0; i<pathc; i++) {
   ret= Xorriso_lst_new(&new_s, paths[i], s, 0);
   if(ret<=0)
     return(ret);
   if(o->not_paths==NULL)
     o->not_paths= new_s;
   s= new_s;
 }
 return(1);
}


/* @return -1=cannot store , 0=cannot compile regex , 1=ok
*/
int Exclusions_add_not_leafs(struct ExclusionS *o, char *not_leafs_descr,
                             regex_t *re, int flag)
{
 int ret;

 ret= Xorriso_lst_append_binary(&(o->not_leafs_descr),
                            not_leafs_descr, strlen(not_leafs_descr)+1, 0);
 if(ret<=0)
   return(-1);
 ret= Xorriso_lst_append_binary(&(o->not_leafs), (char *) re, sizeof(regex_t), 0);
 if(ret<=0)
   return(-1);
 return(1);
}


/* @param flag bit0= whole subtree is banned with -not_paths 
   @return 0=no match , 1=not_paths , 2=not_leafs, <0=error
*/
int Exclusions_match(struct ExclusionS *o, char *abs_path, int flag)
{
 struct Xorriso_lsT *s;
 char leaf[SfileadrL], *leaf_pt;
 regmatch_t match[1];
 int ret, was_non_slash, l;

 /* test abs_paths */
 if(flag&1) {
   for(s= o->not_paths; s!=NULL; s= s->next) {
     l= strlen(s->text);
     if(strncmp(abs_path, s->text, l)==0)
       if(abs_path[l]=='/' || abs_path[l]==0)
         return(1);
   }
 } else {
   for(s= o->not_paths; s!=NULL; s= s->next)
     if(strcmp(abs_path, s->text)==0)
       return(1);
 }

 /* determine leafname */
 was_non_slash= 0;
 for(leaf_pt= abs_path+strlen(abs_path); leaf_pt>abs_path; leaf_pt--) {
   if(*leaf_pt=='/') {
     if(was_non_slash) {
       leaf_pt++;
 break;
     }
   } else if(*leaf_pt!=0)
     was_non_slash= 1;
 }
 if(strlen(leaf_pt)>=SfileadrL)
   return(-1);
 strcpy(leaf, leaf_pt);
 leaf_pt= strchr(leaf, '/');
 if(leaf_pt!=NULL)
   *leaf_pt= 0;

 /* test with leaf expressions */
 for(s= o->not_leafs; s!=NULL; s= s->next) {
   ret= regexec((regex_t *) s->text, leaf, 1, match, 0);
   if(ret==0)
     return(2);
 }
 return(0);
}


int Exclusions_get_descrs(struct ExclusionS *o,
                          struct Xorriso_lsT **not_paths_descr,
                          struct Xorriso_lsT **not_leafs_descr, int flag)
{
 *not_paths_descr= o->not_paths_descr;
 *not_leafs_descr= o->not_leafs_descr;
 return(1);
}


/* ---------------------------- End ExclusionS ---------------------------- */

/* ------------------------------ PermstacK ------------------------------- */


struct PermiteM {
 char *disk_path;
 struct stat stbuf;
 struct PermiteM *next;
};


int Permstack_push(struct PermiteM **o, char *disk_path, struct stat *stbuf,
                   int flag)
{
 struct PermiteM *m;

 m= TSOB_FELD(struct PermiteM,1);
 if(m==NULL)
   return(-1);
 m->disk_path= NULL;
 memcpy(&(m->stbuf), stbuf, sizeof(struct stat));
 m->next= *o;

 m->disk_path= strdup(disk_path);
 if(m->disk_path==NULL)
   goto failed;

 *o= m;
 return(1);
failed:;
 if(m->disk_path!=NULL)
   free(m->disk_path);
 free((char *) m);
 return(-1);
}


/* @param flag bit0= minimal transfer: access permissions only
               bit1= do not set timestamps
*/ 
int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper,
                  struct XorrisO *xorriso, int flag)
{
 int ret;
 char sfe[5*SfileadrL];
 struct utimbuf utime_buffer;
 struct PermiteM *m, *m_next;

 if((*o)==stopper)
   return(1);
 for(m= *o; m!=NULL; m= m->next)
   if(m->next==stopper)
 break;
 if(m==NULL) {
   sprintf(xorriso->info_text,
           "Program error: Permstack_pop() : cannot find stopper");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
   return(-1);
 }

 for(m= *o; m!=stopper; m= m_next) {
   ret= chmod(m->disk_path, m->stbuf.st_mode);
   if(ret==-1) {
     if(xorriso!=NULL) {
       sprintf(xorriso->info_text,
             "Cannot change access permissions of disk directory: chmod %o %s",
             (unsigned int) (m->stbuf.st_mode & 07777),
             Text_shellsafe(m->disk_path, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
                           0);
     }
   }
   if(!(flag&1)) {
     chown(m->disk_path, m->stbuf.st_uid, m->stbuf.st_gid);
                                               /* don't complain if it fails */
     if(!(flag&2)) {
       utime_buffer.actime= m->stbuf.st_atime;
       utime_buffer.modtime= m->stbuf.st_mtime;
       ret= utime(m->disk_path,&utime_buffer);
       if(ret==-1 && xorriso!=NULL) {
         sprintf(xorriso->info_text,
                 "Cannot change timestamps of disk directory: %s",
                 Text_shellsafe(m->disk_path, sfe, 0));
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
                             0);
       }
     }
   }
   m_next= m->next;
   free(m->disk_path);
   free((char *) m);
   *o= m_next;
 }
 return(1);
}


/* ---------------------------- End PermstacK ----------------------------- */

/* ------------------------------ SpotlisT -------------------------------- */

struct SpotlistiteM {
 int start_lba;
 int blocks;
 int quality;
 struct SpotlistiteM *next;
};


int Spotlistitem_new(struct SpotlistiteM **o, int start_lba, int blocks,
                     int quality, int flag)
{
 struct SpotlistiteM *m;

 m= TSOB_FELD(struct SpotlistiteM,1);
 if(m==NULL)
   return(-1);
 *o= m;
 m->start_lba= start_lba;
 m->blocks= blocks;
 m->quality= quality;
 m->next= NULL;
 return(1);
}


int Spotlistitem_destroy(struct SpotlistiteM **o, int flag)
{  
 if((*o) == NULL)
   return(0);
 free((char *) *o);
 *o= NULL;
 return(1);
}


struct SpotlisT {
 struct SpotlistiteM *list_start;
 struct SpotlistiteM *list_end;
 int list_count;
 struct SpotlistiteM *current_item;
 int current_idx;
};


int Spotlist_new(struct SpotlisT **o, int flag)
{
 struct SpotlisT *m;

 m= TSOB_FELD(struct SpotlisT,1);
 if(m==NULL)
   return(-1);
 *o= m;
 m->list_start= NULL;
 m->list_end= NULL;
 m->list_count= 0;
 m->current_item= NULL;
 m->current_idx= -1;
 return(1);
}


int Spotlist_destroy(struct SpotlisT **o, int flag)
{
 struct SpotlisT *m;
 struct SpotlistiteM *li, *next_li;

 if((*o) == NULL)
   return(0);
 m= *o;
 for(li= m->list_start; li != NULL; li= next_li) {
   next_li= li->next;
   Spotlistitem_destroy(&li, 0);
 }
 free((char *) *o);
 *o= NULL;
 return(1);
}


int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks, 
                      int quality, int flag)
{
 int ret;
 struct SpotlistiteM *li;
 static int debug_verbous= 0;

 ret= Spotlistitem_new(&li, start_lba, blocks, quality, 0);
 if(ret <= 0)
   return(ret);
 if(o->list_end != NULL)
   o->list_end->next= li;
 o->list_end= li;
 if(o->list_start == NULL)
   o->list_start= li;
 (o->list_count)++;

 if(debug_verbous) {char quality_name[80];
   fprintf(stderr, "debug: lba %10d , size %10d , quality '%s'\n",
          start_lba, blocks, Spotlist__quality_name(quality, quality_name,
                                         Xorriso_read_quality_invaliD, 0) + 2);
 }

 return(1);
}


int Spotlist_count(struct SpotlisT *o, int flag)
{
 return o->list_count;
}


int Spotlist_block_count(struct SpotlisT *o, int flag)
{
 int list_blocks= 0;
 struct SpotlistiteM *li;

 for(li= o->list_start; li != NULL; li= li->next) {
   if(li->start_lba + li->blocks > list_blocks)
     list_blocks= li->start_lba + li->blocks;
 }
 return(list_blocks);
}


int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag)
{
 int sector_size;
 struct SpotlistiteM *li;

 sector_size= read_chunk * 2048;
 for(li= o->list_start; li != NULL; li= li->next) {
   if((li->start_lba % read_chunk) || (li->blocks % read_chunk)) {
     sector_size= 2048;
 break;
   }
 }
 return(sector_size);
}


int Spotlist_get_item(struct SpotlisT *o, int idx, 
                      int *start_lba, int *blocks, int *quality, int flag)
{
 int i;
 struct SpotlistiteM *li;
 
 if(idx < 0 || idx > o->list_count)
   return(0);
 if(idx == o->current_idx && o->current_item != NULL)
   li= o->current_item;
 else if(idx == o->current_idx + 1 && o->current_item != NULL) {
   li= o->current_item->next;
 } else {
   li= o->list_start;
   for(i= 0; i < idx; i++)
     li= li->next;
 }
 o->current_item= li;
 o->current_idx= idx;
 *start_lba= li->start_lba;
 *blocks= li->blocks;
 *quality= li->quality;
 return(1);
}


char *Spotlist__quality_name(int quality, char name[80], int bad_limit,
                             int flag)
{
 if(quality == Xorriso_read_quality_untesteD ||
   quality == Xorriso_read_quality_tao_enD ||
   quality == Xorriso_read_quality_off_tracK)
   strcpy(name, "0 ");
 else if(quality <= bad_limit)
   strcpy(name, "- ");
 else
   strcpy(name, "+ ");
 if(quality == Xorriso_read_quality_gooD)
   strcat(name, "good");
 else if(quality == Xorriso_read_quality_md5_matcH)
   strcat(name, "md5_match");
 else if(quality == Xorriso_read_quality_sloW)
   strcat(name, "slow");
 else if(quality == Xorriso_read_quality_partiaL)
   strcat(name, "partial");
 else if(quality == Xorriso_read_quality_valiD)
   strcat(name, "valid");
 else if(quality == Xorriso_read_quality_untesteD)
   strcat(name, "untested");
 else if(quality == Xorriso_read_quality_invaliD)
   strcat(name, "invalid");
 else if(quality == Xorriso_read_quality_tao_enD)
   strcat(name, "tao_end");
 else if(quality == Xorriso_read_quality_off_tracK)
   strcat(name, "off_track");
 else if(quality == Xorriso_read_quality_md5_mismatcH)
   strcat(name, "md5_mismatch");
 else if(quality == Xorriso_read_quality_unreadablE)
   strcat(name, "unreadable");
 else
   sprintf(name, "0 0x%8.8X", (unsigned int) quality);
 return(name);
}


/* ---------------------------- End SpotlisT ------------------------------ */

/* ---------------------------- SectorbitmaP ------------------------------ */

struct SectorbitmaP {
 int sectors;
 int sector_size;
 unsigned char *map;
 int map_size;
};


int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size,
                     int flag)
{
 struct SectorbitmaP *m;

 m= TSOB_FELD(struct SectorbitmaP,1);
 if(m==NULL)
   return(-1);
 *o= m;
 m->sectors= sectors;
 m->sector_size= sector_size;
 m->map= NULL;
 m->map_size= sectors / 8 + 1;

 m->map= calloc(m->map_size, 1);
 if(m->map == NULL)
   goto failure;
 return(1);
failure:;
 Sectorbitmap_destroy(o, 0);
 return(-1);
}


int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag)
{  
 if((*o) == NULL)
   return(0);
 if((*o)->map != NULL)
   free((char *) (*o)->map);
 free((char *) *o);
 *o= NULL;
 return(1);
}


int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg,
                           int *os_errno, int flag)
{
 int ret, fd= -1, sectors, sector_size, i, todo, map_size, skip;
 unsigned char *map;
 unsigned char buf[1024];

 *os_errno= 0;
 if(msg != NULL)
   msg[0]= 0;
 fd= open(path, O_RDONLY);
 if(fd == -1) {
   *os_errno= errno;
   if(msg != NULL) {
     strcpy(msg, "Cannot open path ");
     Text_shellsafe(path, msg+strlen(msg), 0);
   }
   return(0);
 }
 ret= read(fd, buf, 32);
 if(ret < 32) {
wrong_filetype:;
   if(ret == -1)
     *os_errno= errno;
   if(msg != NULL) {
     strcpy(msg, "Not a sector bitmap file: ");
     Text_shellsafe(path, msg+strlen(msg), 0);
   }
   ret= 0; goto ex;
 }
 if(strncmp((char *) buf, "xorriso sector bitmap v1        ", 32) == 0)
   /* ok */;
 else if(strncmp((char *) buf, "xorriso sector bitmap v2 ", 25) == 0) {
   skip= -1;
   sscanf(((char *) buf) + 25, "%d", &skip);
   if(skip < 0)
     {ret= 0; goto wrong_filetype;}
   for(i= 0; i < skip; i+= sizeof(buf)) {
     todo= sizeof(buf);
     if(i + todo > skip)
       todo= skip - i;
     ret= read(fd, buf, todo);
     if(ret < todo)
       goto wrong_filetype;
   }
 } else
   {ret= 0; goto wrong_filetype;}
 ret= read(fd, buf, 8);
 if(ret < 4)
   goto wrong_filetype;
 sectors= (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
 sector_size= (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
 if(sectors <= 0 || sector_size <= 0)
   goto wrong_filetype;
 ret= Sectorbitmap_new(o, sectors, sector_size, 0);
 if(ret <= 0) {
   if(msg != NULL)
     sprintf(msg, "Cannot allocate bitmap memory for %d sectors", sectors);
   ret= -1; goto ex;
 }
 map= (*o)->map;
 map_size= (*o)->map_size;
 for(i= 0; i < map_size; i+= sizeof(buf)) {
   todo=  sizeof(buf);
   if(i + todo > map_size)
     todo= map_size - i;
   ret= read(fd, buf, todo);
   if(ret != todo)
     goto wrong_filetype;
   memcpy(map + i, buf, todo);
 }
 ret= 1;
ex:;
 if(fd != -1)
   close(fd);
 if(ret <= 0)
   Sectorbitmap_destroy(o, 0);
 return(ret);
}


int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info,
                         char *msg, int *os_errno, int flag)
{
 int ret, fd= -1, j, l;
 unsigned char buf[40];

 *os_errno= 0;
 fd= open(path, O_WRONLY | O_CREAT,  S_IRUSR | S_IWUSR);
 if(fd == -1) {
   *os_errno= errno;
   if(msg != NULL) {
     strcpy(msg, "Cannot open path ");
     Text_shellsafe(path, msg+strlen(msg), 0);
   }
   return(0);
 }

 l= 0;
 if(info != NULL)
   l= strlen(info);
 if(l > 999999) {
   strcpy(msg, "Info string is longer than 999999 bytes");
   return(0);
 }
 sprintf((char *) buf, "xorriso sector bitmap v2 %-6d\n", l);

 ret= write(fd, buf, 32);
 if(ret != 32) {
cannot_write:;
   *os_errno= errno;
   if(msg != NULL) {
     strcpy(msg, "Cannot write to ");
     Text_shellsafe(path, msg+strlen(msg), 0);
   }
   ret= 0; goto ex;
 }
 if(l > 0) {
   ret= write(fd, info, l);
   if(ret != l)
     goto cannot_write;
 }

 for(j= 0; j < 4; j++) {
   buf[j]= o->sectors >> (24 - j * 8);
   buf[j+4]= o->sector_size >> (24 - j * 8);
 }
 ret= write(fd, buf, 8);
 if(ret != 8)
   goto cannot_write;
 ret= write(fd, o->map, o->map_size);
 if(ret != o->map_size)
   goto cannot_write;

 ret= 1;
ex:;
 if(fd != -1)
   close(fd);
 return(ret);
}


/* @param flag bit0= sector bit value
*/
int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag)
{
 if(sector < 0 || sector >= o->sectors)
   return(0);
 if(flag & 1)
   o->map[sector / 8]|= 1 << (sector % 8);
 else
   o->map[sector / 8]&= ~(1 << (sector % 8));
 return(1);
}


/* @param flag bit0= sector bit value
*/
int Sectorbitmap_set_range(struct SectorbitmaP *o,
                           int start_sector, int sectors, int flag)
{
 int start_i, end_i, i;
 unsigned char value;

 if(start_sector < 0 || start_sector + sectors > o->sectors || sectors < 1)
   return(0);
 if(flag & 1)
   value= ~0;
 else
   value= 0;
 start_i= start_sector / 8;
 end_i= (start_sector + sectors - 1) / 8;
 for(i= start_sector; i / 8 == start_i && i < start_sector + sectors; i++)
   Sectorbitmap_set(o, i, flag & 1);
 for(i= start_i + 1; i < end_i; i++)
   o->map[i]= value;
 if(end_i > start_i)
   for(i= end_i * 8; i < start_sector + sectors; i++)
     Sectorbitmap_set(o, i, flag & 1);
 return(1);
}


int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag)
{
 if(sector < 0 || sector >= o->sectors)
   return(0);
 return(!! (o->map[sector / 8] & (1 << (sector % 8))));
}


int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o,
                               off_t start_byte, off_t end_byte, int flag)
{
 int end_sector, i;

 end_sector= end_byte / o->sector_size;
 for(i= start_byte / o->sector_size; i <= end_sector; i++)
   if(!Sectorbitmap_is_set(o, i, 0))
     return(0);
 return(1);
}
                               

int Sectorbitmap_get_layout(struct SectorbitmaP *o,
                           int *sectors, int *sector_size, int flag)
{
 *sectors= o->sectors;
 *sector_size= o->sector_size;
 return(1);
}


int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to,
                      int flag)
{
 int i, run_start, run_value, start_sec, limit_sec, start_aligned;
 int end_complete;

 if(((off_t) from->sectors) * ((off_t) from->sector_size) >
    ((off_t) to->sectors) * ((off_t) to->sector_size))
   return(-1);
 if(from->sector_size == to->sector_size) {
   for(i= 0; i < from->map_size; i++)
     to->map[i]= from->map[i];
   return(1);
 }
 run_start= 0;
 run_value= Sectorbitmap_is_set(from, 0, 0);
 for(i= 1; i <= from->sectors; i++) {
   if(i < from->sectors)
     if(Sectorbitmap_is_set(from, i, 0) == run_value)
 continue;
   start_sec= run_start * from->sector_size / to->sector_size;
   start_aligned=
                (start_sec * to->sector_size == run_start * from->sector_size);
   limit_sec= i * from->sector_size / to->sector_size;
   end_complete= (limit_sec * to->sector_size == i * from->sector_size);
   if(run_value) {
     if(!start_aligned)
       start_sec++;
   } else {
     if(!end_complete)
       limit_sec++;
   }
   if(start_sec < limit_sec)
     Sectorbitmap_set_range(to, start_sec, limit_sec - 1 - start_sec,
                            !!run_value);
   run_value= !run_value;
   run_start= i;
 }
 return(1);
}


int Sectorbitmap_clone(struct SectorbitmaP *from, struct SectorbitmaP **clone,
                      int flag)
{
 int ret;

 ret= Sectorbitmap_new(clone, from->sectors, from->sector_size, 0);
 if(ret <= 0)
   return(ret);
 ret= Sectorbitmap_copy(from, *clone, 0);
 if(ret <= 0)
   Sectorbitmap_destroy(clone, 0);
 return(ret);
}


/* -------------------------- End SectorbitmaP ---------------------------- */

/* ---------------------------- CheckmediajoB ----------------------------- */

int Checkmediajob_new(struct CheckmediajoB **o, int flag)
{
 struct CheckmediajoB *m;

 m= TSOB_FELD(struct CheckmediajoB,1);
 if(m==NULL)
   return(-1);
 *o= m;
 m->use_dev= 0;
 m->min_lba= -1;
 m->max_lba= -1;
 m->min_block_size= 0;
 m->mode= 0;
 m->start_time= time(NULL);
 m->time_limit= 28800;
 m->item_limit= 100000;
 strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media");
 m->data_to_path[0]= 0;
 m->data_to_fd= -1;
 m->data_to_offset= 0;
 m->data_to_limit= -1;
 m->patch_lba0= 0;
 m->patch_lba0_msc1= -1;
 m->sector_map_path[0]= 0;
 m->sector_map= NULL;
 m->map_with_volid= 0;
 m->retry= 0;
 m->report_mode= 0;
 strcpy(m->event_severity, "ALL");
 m->slow_threshold_seq= 1.0;
 m->untested_valid= 0;
 return(1);
}


int Checkmediajob_destroy(struct CheckmediajoB **o, int flag)
{  
 if((*o) == NULL)
   return(0);
 if((*o)->data_to_fd != -1)
   close((*o)->data_to_fd);
 Sectorbitmap_destroy(&((*o)->sector_map), 0);
 free((char *) *o);
 *o= NULL;
 return(1);
}


int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to,
                       int flag)
{  
 to->use_dev= from->use_dev;
 to->min_lba= from->min_lba;
 to->max_lba= from->max_lba;
 to->min_block_size= from->min_block_size;
 to->mode= from->mode;
 to->time_limit= from->time_limit;
 to->item_limit= from->item_limit;
 strcpy(to->abort_file_path, from->abort_file_path);
 strcpy(to->data_to_path, from->data_to_path);
 /* not copied: data_to_fd */
 to->data_to_offset= from->data_to_offset;
 to->data_to_limit= from->data_to_limit;
 to->patch_lba0= from->patch_lba0;
 to->patch_lba0_msc1= from->patch_lba0_msc1;
 strcpy(to->sector_map_path, from->sector_map_path);
 /* not copied: sector_map */
 to->map_with_volid= from->map_with_volid;
 to->retry= from->retry;
 to->report_mode= from->report_mode;
 strcpy(to->event_severity, from->event_severity);
 to->slow_threshold_seq= from->slow_threshold_seq;
 to->untested_valid= from->untested_valid;
 return(1);
}


/* -------------------------- End CheckmediajoB --------------------------- */

/* ------------------------------- Xorriso -------------------------------- */


/** The list of startup file names */
#define Xorriso_rc_nuM 4

static char Xorriso_sys_rc_nameS[Xorriso_rc_nuM][80]= {
 "/etc/default/xorriso",
 "/etc/opt/xorriso/rc",
 "/etc/xorriso/xorriso.conf",
 "placeholder for $HOME/.xorrisorc"
};


int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
{
 int i, ret;
 struct XorrisO *m;
 char leafname[SfileadrL];
 
 *xorriso= m= TSOB_FELD(struct XorrisO,1);
 if(m==NULL)
   return(-1);
 m->libs_are_started= 0;
 strncpy(m->progname,progname,sizeof(m->progname)-1);
 m->progname[sizeof(m->progname)-1]= 0;
 if(getcwd(m->initial_wdx,sizeof(m->initial_wdx)-1)==NULL)
   m->initial_wdx[0]= 0;
 m->no_rc= 0;
 m->argument_emulation= 0;

 m->rc_filename_count= Xorriso_rc_nuM;
 for(i=0;i<m->rc_filename_count-1;i++)
   strcpy(m->rc_filenames[i],Xorriso_sys_rc_nameS[i]);
 m->rc_filenames[m->rc_filename_count-1][0]= 0;

 m->wdi[0]= 0;
 strcpy(m->wdx, m->initial_wdx);
 m->did_something_useful= 0;
 m->add_plainly= 0;
 m->split_size= 0;
 strcpy(m->list_delimiter, "--");
 m->ino_behavior= 7;
 m->do_joliet= 0;
 m->do_aaip= 0;
 m->do_md5= 0;
 m->scdbackup_tag_name[0]= 0;
 m->scdbackup_tag_time[0]= 0;
 m->scdbackup_tag_written[0]= 0;
 m->scdbackup_tag_listname[0]= 0;
 m->relax_compliance= 0;
 m->do_follow_pattern= 1;
 m->do_follow_param= 0;
 m->do_follow_links= 0;
 m->follow_link_limit= 100;
 m->do_follow_mount= 1;
 m->do_global_uid= 0;
 m->global_uid= 0;
 strcpy(m->volid, "ISOIMAGE");
 m->volid_default= 1;
 m->loaded_volid[0]= 0;
 m->assert_volid[0]= 0;
 m->assert_volid_sev[0]= 0;
 m->publisher[0]= 0;
 m->application_id[0]= 0;
 m->system_id[0]= 0;
 m->volset_id[0]= 0;
 m->session_logfile[0]= 0;
 m->session_lba= -1;
 m->session_blocks= 0;
 m->do_global_gid= 0;
 m->global_gid= 0;
 m->do_global_mode= 0;
 m->global_dir_mode= 0555;
 m->global_file_mode= 0444;
 m->filters= NULL;
 m->filter_list_closed= 0;
 m->zlib_level_default= m->zlib_level= 6;
 m->zisofs_block_size= m->zisofs_block_size_default= (1 << 15);
 m->zisofs_by_magic= 0;
 m->do_overwrite= 2;
 m->do_reassure= 0;
 m->drive_blacklist= NULL;
 m->drive_greylist= NULL;
 m->drive_whitelist= NULL;
 m->toc_emulation_flag= 0;
 m->image_start_mode= 0;
 m->image_start_value[0]= 0;
 m->drives_exclusive= 1;
 m->do_calm_drive= 1;
 m->indev[0]= 0;
 m->in_drive_handle= NULL;
 m->in_volset_handle= NULL;
 m->in_charset= NULL;
 m->isofs_st_out= time(0) - 1;
 m->indev_is_exclusive= 1;
 m->isofs_st_in= 0;
 m->volset_change_pending= 0;
 m->no_volset_present= 0;
 m->in_sector_map= NULL;
 m->check_media_default= NULL;
 m->check_media_bad_limit= Xorriso_read_quality_invaliD;
 m->outdev[0]= 0;
 m->out_drive_handle= NULL;
 m->out_charset= NULL;
 m->dev_fd_1= -1;
 m->outdev_is_exclusive= 1;
 m->grow_blindly_msc2= -1;
 m->ban_stdio_write= 0;
 m->do_dummy= 0;
 m->do_close= 0;
 m->speed= 0;
 m->fs= 4*512; /* 4 MiB */
 m->padding= 300*1024;
 m->alignment= 0;
 m->do_stream_recording= 0;
 m->dvd_obs= 0;
 m->stdio_sync= 0;
 m->keep_boot_image= 0;
 m->patch_isolinux_image= 0;
 m->boot_image_bin_path[0]= 0;
 m->boot_image_emul= 0;
 m->boot_image_cat_path[0]= 0;
 m->boot_image_load_size= 4 * 512;     /* hearsay out of libisofs/demo/iso.c */
 m->boot_image_isohybrid= 1;
 m->loaded_boot_bin_lba= 0;
 m->loaded_boot_cat_path[0]= 0;
 m->allow_graft_points= 0;
 m->allow_restore= 0;
 m->do_concat_split= 1;
 m->do_auto_chmod= 0;
 m->do_restore_sort_lba= 0;
 m->dialog= 0;
 m->bsl_interpretation= 0;
 m->search_mode= 0;
 m->structured_search= 1;
 m->do_iso_rr_pattern= 1;
 m->do_disk_pattern= 2;
 m->temp_mem_limit= 16*1024*1024;
 m->file_size_limit= Xorriso_default_file_size_limiT;
 m->disk_exclusions= NULL;
 m->disk_excl_mode= 1;
 m->use_stdin= 0;
 m->result_page_length= 0;
 m->result_page_width= 80;
 m->mark_text[0]= 0;
 m->packet_output= 0;
 for(i=0; i<4; i++) {
   m->logfile[i][0]= 0;
   m->logfile_fp[i]= NULL;
 }
 m->pktlog_fp= NULL;
 for(i= 0; i < Xorriso_max_outlist_stacK; i++) {
   m->result_msglists[i]= NULL;
   m->info_msglists[i]= NULL;
   m->msglist_flags[i]= 0;
 }
 m->msglist_stackfill= 0;
 m->status_history_max= Xorriso_status_history_maX;
 m->scsi_log= 0;
 strcpy(m->report_about_text, "UPDATE");
 Xorriso__text_to_sev(m->report_about_text, &m->report_about_severity, 0);
 m->library_msg_direct_print= 0;
 strcpy(m->abort_on_text,"FATAL");
 Xorriso__text_to_sev(m->abort_on_text, &m->abort_on_severity, 0);
 m->problem_status= 0;
 m->problem_status_text[0]= 0;
 m->errfile_log[0]= 0;
 m->errfile_mode= 0;
 m->errfile_fp= NULL;
 
 m->img_read_error_mode= 2;         /* abort faulty image reading with FATAL */
 m->extract_error_mode= 1;          /* keep extracted files after read error */
 strcpy(m->return_with_text, "SORRY");
 Xorriso__text_to_sev(m->return_with_text, &m->return_with_severity, 0);
 m->return_with_value= 32;
 m->eternal_problem_status= 0;
 m->eternal_problem_status_text[0]= 0;
 m->re= NULL;
 /* >>> ??? how to initialize m->match[0] ? */
 m->re_constants= NULL;
 m->re_count= 0;
 m->re_fill= 0;
 m->reg_expr[0]= 0;
 m->run_state= 0;
 m->is_dialog= 0;
 m->bar_is_fresh= 0;
 m->pending_option[0]= 0;
 m->request_to_abort= 0;
 m->request_not_to_ask= 0;
 m->idle_time= 0.0;
 m->re_failed_at= -1;
 m->prepended_wd= 0;
 m->insert_count= 0;
 m->insert_bytes= 0;
 m->error_count= 0;
 m->pacifier_style= 0;
 m->pacifier_interval= 1.0;
 m->pacifier_count= 0;
 m->pacifier_total= 0;
 m->pacifier_byte_count= 0;
 m->pacifier_fifo= NULL;
 m->start_time= 0.0;
 m->last_update_time= 0.0;
 m->find_compare_result= 1;
 m->find_check_md5_result= 0;

 m->node_counter= 0;
 m->node_array_size= 0;
 m->node_array= NULL;
 m->node_disk_prefixes= NULL;
 m->node_img_prefixes= NULL;

 m->hln_count= 0;
 m->hln_array= NULL; 
 m->hln_targets= NULL;
 m->hln_change_pending= 0;
 m->di_do_widen= NULL;
 m->di_disk_paths= NULL;
 m->di_iso_paths= NULL;

 m->node_targets_availmem= 0;

 m->di_count= 0;
 m->di_array= NULL;

 m->perm_stack= NULL;

 m->result_line[0]= 0;
 m->result_line_counter= 0;
 m->result_page_counter= 0;
 m->result_open_line_len= 0;

 m->info_text[0]= 0;

 ret= Sfile_leafname(progname, leafname, 0);
 if(ret<=0)
   goto failure;
 if(strcmp(leafname, "osirrox")==0) {
   m->allow_restore= 1;
   m->drives_exclusive= 0;
 } else if(strcmp(leafname, "xorrisofs")==0 || strcmp(leafname, "genisofs")==0 ||
        strcmp(leafname, "mkisofs")==0 || strcmp(leafname, "genisoimage")==0) {
   m->argument_emulation= 1;
   m->pacifier_style= 1;
   Xorriso_protect_stdout(*xorriso, 0);
 } else if(strcmp(leafname, "xorrecord")==0 || strcmp(leafname, "wodim")==0 ||
           strcmp(leafname, "cdrecord")==0 || strcmp(leafname, "cdrskin")==0) {
   m->argument_emulation= 2;
   m->pacifier_style= 2;
 }
 ret= Exclusions_new(&(m->disk_exclusions), 0);
 if(ret<=0)
   goto failure;
 Xorriso_relax_compliance(m, "default", 0);
 ret= Xorriso_lst_new(&(m->drive_greylist), "/dev", m->drive_greylist, 1);
 if(ret <= 0)
   goto failure;

 return(1);
failure:;
 Xorriso_destroy(xorriso, 0);
 return(-1);
}


int Xorriso_destroy_re(struct XorrisO *m, int flag)
{
 int i;

 if(m->re!=NULL) {
   for(i=0;i<m->re_fill;i++) {
     if(m->re_constants!=NULL)
       if(m->re_constants[i]!=NULL)
   continue; /* ,->re[i] was never subject to regcomp() */
     regfree(&(m->re[i]));
   }
   free((char *) m->re);
   m->re= NULL;
 }

 if(m->re_constants!=NULL) {
   for(i=0;i<m->re_fill;i++)
     if(m->re_constants[i]!=NULL)
       free(m->re_constants[i]);
   free((char *) m->re_constants);
   m->re_constants= NULL;
 }
 m->re_count= 0;
 m->re_fill= 0;
 return(1);
}


/* @param flag bit0= global shutdown of libraries */
int Xorriso_destroy(struct XorrisO **xorriso, int flag)
{
 struct XorrisO *m;

 m= *xorriso;
 if(m==NULL)
   return(0);
 if(m->in_charset!=NULL)
   free(m->in_charset);
 if(m->out_charset!=NULL)
   free(m->out_charset);
 Xorriso_destroy_re(m,0);
 Exclusions_destroy(&(m->disk_exclusions), 0);
 Xorriso_destroy_all_extf(m, 0);
 Xorriso_lst_destroy_all(&(m->drive_blacklist), 0);
 Xorriso_lst_destroy_all(&(m->drive_greylist), 0);
 Xorriso_lst_destroy_all(&(m->drive_whitelist), 0);
 Xorriso_destroy_node_array(m, 0);
 Xorriso_destroy_hln_array(m, 0);
 Xorriso_destroy_di_array(m, 0);

 Xorriso_detach_libraries(m, flag&1);

 free((char *) m);
 *xorriso= NULL;
 return(1);
}


int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize,
                         int flag)
/*
 bit0= do not write to history
 bit1= do not read input (but eventually write to history)
 bit2= do not write to history line which begin with "-history:" or "-history "
*/
{
 char *cpt= NULL, **argv= NULL, *linept, *why_append= "";
 int ret, argc= 0, base_length= 0, l, append_line;
#ifdef Xorriso_with_readlinE
 static char last_input[SfileadrL]= {""};
#endif /* ! Xorriso_with_readlinE */
 double tdiff;
 struct timeval tv;
 struct timezone tz;

 gettimeofday(&tv,&tz);
 tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec);

 fflush(stdout);
 linept= line;

get_single:;
#ifdef Xorriso_with_readlinE

 if(xorriso->use_stdin || xorriso->dev_fd_1>=0) {
   if(flag&2)
     {ret= 1; goto ex;}
   if(Sfile_fgets_n(linept,linesize - base_length - 1, stdin,
                      (xorriso->dialog == 2)) == NULL) {
     /* need a very dramatic end */
     kill(getpid(),SIGHUP);
     {ret= -1; goto ex;}
   }
   goto process_single;
 }
 if(flag&2) {
   cpt= NULL;
 } else {
   cpt= readline("");
   if(cpt==NULL) {
     /* need a very dramatic end */
     kill(getpid(),SIGHUP);
     {ret= -1; goto ex;}
   }
   l= strlen(cpt);
   if(l >= linesize - base_length - 1) {
     strncpy(linept, cpt, linesize - 1);
     line[sizeof(line)-1]= 0;
     sprintf(xorriso->info_text,"Input line too long !");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     goto new_empty;
   } else 
     strcpy(linept, cpt);
 }

process_single:;

#else /*  Xorriso_with_readlinE */

 if(flag&2)
   {ret= 1; goto ex;}
 if(Sfile_fgets_n(linept, linesize - base_length - 1, stdin,
                  (xorriso->dialog == 2)) == NULL) {
   /* need a very dramatic end */
   kill(getpid(),SIGHUP);
   {ret= -1; goto ex;}
 }

#endif /* ! Xorriso_with_readlinE */

 if(xorriso->dialog == 2) {
   append_line= 0;
   if(linept != line && strcmp(linept, "@@@") == 0) {
     sprintf(xorriso->info_text, "Incomplete input line cleared by %s",
             linept);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
new_empty:;
     line[0]= 0;
     linept= line;
     sprintf(xorriso->info_text, "-------------------------------------\n");
     Xorriso_info(xorriso,0);
     sprintf(xorriso->info_text, "Enter new text for empty input line :\n");
     Xorriso_info(xorriso,0);
     goto get_single;
   }
   l= strlen(line);
   ret= Sfile_make_argv("", line, &argc, &argv, 16);
   if(ret < 0)
     goto ex;
   if(ret == 0 && !append_line) {
     /* append a newline character */
     if(l >= linesize - 1) {
       sprintf(xorriso->info_text,"Input line too long !");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
       goto new_empty;
     }
     line[l]= '\n';
     line[l + 1]= 0;
     append_line= 1;
     why_append= "Quoted newline char";
   }
   if(l > 0 && !append_line)
     if(line[l - 1] == '\\') {
       line[l - 1]= 0;
       append_line= 1;
       why_append= "Trailing backslash ";
     }
   if(append_line) {
     base_length= strlen(line);
     linept= line + base_length;
     sprintf(xorriso->info_text,
          "---------------------------------------------------------------\n");
     Xorriso_info(xorriso,0);
     sprintf(xorriso->info_text,
             "%s : Enter rest of line (or @@@ to clear it) :\n", why_append);
     Xorriso_info(xorriso,0);
     goto get_single;
   }
 }

#ifdef Xorriso_with_readlinE

 if(line[0]!=0 && strcmp(last_input,line)!=0 && !(flag&1))
   if(!((flag&4) && 
      (strncmp(line,"-history:",9)==0 || strncmp(line,"-history ",9)==0))) {
     add_history(line);
     strncpy(last_input,line,sizeof(last_input)-1);
     last_input[sizeof(last_input)-1]= 0;
   }

#endif /* ! Xorriso_with_readlinE */

 ret= 1;
ex:;
 if(cpt!=NULL)
   free(cpt);
 gettimeofday(&tv,&tz);
 xorriso->idle_time+= tv.tv_sec+(1.e-6*(double) tv.tv_usec)-tdiff;
 return(ret);
}


int Xorriso_request_confirmation(struct XorrisO *xorriso, int flag)
/*
 bit0= important operation going on: 
       demand confirmation of abort, only abort on @@@
 bit1= mark '@' and '@@' by return 4
 bit2= accept: i|n= ignore | do not remove , r|y= retry | remove , q|x= abort
 bit3= @@@ = 'done reading' rather than 'abort'
 bit4= in non-dialog mode return 6 rather than 1
*/
/* return: <=0 error
           1= go on | do not remove existing file
           2= abort
           3= redo request for confirmation
           4= see flag bit1
          (5= skip volume)
           6= retry failed operation | remove existing file
 */
{
 int ret;
 char line[SfileadrL],*cpt,previous_line[SfileadrL];
 char *abort_req_text,*abort_really_text;

 if(!xorriso->dialog) {
   if(flag&16)
     return(6);
   return(1);
 }
 if(flag&8) {
   abort_req_text= "request to end";
   abort_really_text= "done reading";
 } else {
   abort_req_text= "request to abort";
   abort_really_text= "abort this command";
 }
 ret= Xorriso_dialog_input(xorriso,line,sizeof(line),1);
 xorriso->result_line_counter= 0;
 xorriso->result_page_counter++;
 if(ret<=0)
   if(xorriso->result_page_length>0)
     xorriso->result_page_length= -xorriso->result_page_length;

 cpt= line;
 if(strcmp(cpt,"@@@")==0 ||
    strcmp(cpt,"x")==0 || strcmp(cpt,"X")==0 ||
    strcmp(cpt,"q")==0 || strcmp(cpt,"Q")==0) {
   if(flag&1) {
     strcpy(previous_line,cpt);
     sprintf(xorriso->info_text,
             "... [%s = %s registered. Really %s ? (y/n) ] ...\n",
             cpt,abort_req_text,abort_really_text);
     Xorriso_info(xorriso,0);
     ret= Xorriso_dialog_input(xorriso,line,sizeof(line),1);
     if(ret<=0)
       return(ret);
     cpt= line;
     if(strcmp(cpt,previous_line)==0 || 
        ((*cpt=='Y' || *cpt=='y' || *cpt=='j' || *cpt=='J' || *cpt=='1') &&
           *(cpt+1)==0)) {
       xorriso->request_to_abort= 1;
       sprintf(xorriso->info_text,
               "------- ( %s confirmed )\n",abort_req_text);
       Xorriso_info(xorriso,0);
       return(2);
     }
     sprintf(xorriso->info_text, "....... ( %s revoked )\n",abort_req_text);
     Xorriso_info(xorriso,0);
     return(3);
   }
   xorriso->request_to_abort= 1;
   sprintf(xorriso->info_text,
"----------- [%s = request to abort registered. Operation ends ] ------------\n",
           cpt);
   Xorriso_info(xorriso,0);
   return(2);
 } else if(*cpt=='@') {
   if(strcmp(cpt,"@@")==0) {
     goto klammer_affe;
     
   } else if(strcmp(cpt,"@")==0) {
klammer_affe:;
     if(xorriso->result_page_length>0)
       xorriso->result_page_length= -xorriso->result_page_length;
     if(flag&1) {
       sprintf(xorriso->info_text,
"... [@ = prompt suppression registered. Prompting disabled temporarily ] ...\n");
       Xorriso_info(xorriso,0);
     }

   } else {
     Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */
     sprintf(xorriso->info_text,
 "--- Unrecognized input beginning with @. Please enter someting else.\n");
     Xorriso_info(xorriso,0);
     return(3);
   }
   if(flag&2)
     return(4);
   if(flag&1)
     return(3);
   return(1);
 } else if(flag&4) {

   if(strcmp(cpt,"i")==0 || strcmp(cpt,"I")==0 ||
      strcmp(cpt,"n")==0 || strcmp(cpt,"N")==0 ||
      *cpt==0) { 
     return(1);
   } else if(strcmp(cpt,"r")==0 || strcmp(cpt,"R")==0 ||
             strcmp(cpt,"y")==0 || strcmp(cpt,"Y")==0) {
     return(6);
   } else {
     /* >>> unknown input */
     sprintf(xorriso->info_text,
          "--- Please enter one of : empty line, i,n, r,y, q,x, @, @@@\n");
     Xorriso_info(xorriso,0);
     return(3);
   }

 } else if(*cpt!=0 && !(flag&1)) {
   Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */
   strcpy(xorriso->pending_option,cpt);
   xorriso->request_to_abort= 1;
   sprintf(xorriso->info_text,
"-------------- [ Input of option registered. Operation ends ] ---------------\n");
   Xorriso_info(xorriso,0);
   return(2);

 } else if(*cpt!=0) {
   Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */
   sprintf(xorriso->info_text,
           "--- Please enter one of : empty line, @, @@@\n");
   Xorriso_info(xorriso,0);
   return(3);
 }
 return(1);
}


/* @param flag bit0= quoted multiline mode
               bit1= release allocated memory and return 1
               bit2= with bit0: warn of empty text arguments
               bit3= deliver as single quoted text including all whitespace
                     and without any backslash interpretation
   @return -1=out of memory , 0=line format error , 1=ok, go on , 2=done
*/
int Xorriso_read_lines(struct XorrisO *xorriso, FILE *fp, int *linecount,
                       int *argc, char ***argv, int flag)
{
 char line[5 * SfileadrL + 2], *linept, *fgot;
 int l, base_length, append_line, ret, mem_linecount, i;

 Sfile_make_argv("", line, argc, argv, 2);
 if(flag & 2)
   return(1);

 mem_linecount= *linecount;
 linept= line;
 base_length= 0;
 while(1) {
   fgot= Sfile_fgets_n(linept, SfileadrL - base_length + 1, fp,
                       !!(flag & (1 | 8)));
   if(fgot == NULL) {
     if(ferror(fp))
       return(0);
     if(linept != line) {
       sprintf(xorriso->info_text,"Open quotation mark at end of input");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       return(0);
     }
     return(2);
   }
   l= strlen(line);
   (*linecount)++;
   append_line= 0;
   if(flag & 1) { /* check whether the line is incomplete yet */
     ret= Sfile_make_argv("", line, argc, argv, 16);
     if(ret < 0)
       return(ret);
     if(ret == 0 && !append_line) {
       line[l]= '\n';
       line[l + 1]= 0;
       append_line= 1;
     }
     if(l > 0 && !append_line)
       if(line[l - 1] == '\\') {
         line[l - 1]= 0;
         append_line= 1;
       }
   }
   if(l >= SfileadrL) {
     sprintf(xorriso->info_text,"Input line too long !");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   if(!append_line)
 break;
   base_length= strlen(line);
   linept= line + base_length;
 }
 if((flag & 1) && !(flag & 8)) {
   ret= Sfile_make_argv("", line, argc, argv,
                        1 | ((xorriso->bsl_interpretation & 3) << 5));
   if(ret < 0)
     return(ret);
   if(flag & 4)
     for(i= 0; i < *argc; i++) {
       if((*argv)[i][0] == 0) {
         sprintf(xorriso->info_text, "Empty text as quoted argument in ");
       } else if(strlen((*argv)[i]) >= SfileadrL) {
         (*argv)[i][SfileadrL - 1]= 0;
         sprintf(xorriso->info_text,
                 "Input text too long and now truncated in");
       } else
     continue;
       if(mem_linecount + 1 < *linecount)
         sprintf(xorriso->info_text + strlen(xorriso->info_text),
                 "lines %d to %d", mem_linecount + 1, *linecount);
       else
         sprintf(xorriso->info_text + strlen(xorriso->info_text),
                 "line %d", mem_linecount + 1);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
     }
 } else {
   (*argv)= Smem_malloC(sizeof(char *));
   if(argv == NULL)
     return(-1);
   (*argv)[0]= strdup(line);
   if((*argv)[0] == NULL)
     return(-1);
   *argc= 1;
 }
 return(1);
}


int Xorriso_predict_linecount(struct XorrisO *xorriso, char *line,
                              int *linecount, int flag)
{
 int width,l;
 char *spt,*ept;

 *linecount= 0;
 spt= line;
 width= xorriso->result_page_width;
 while(1) {
   ept= strchr(spt,'\n');
   if(ept==NULL)
     l= strlen(spt);
   else
     l= ept-spt;
   l+= xorriso->result_open_line_len;
   if(ept!=NULL && l==0)
     (*linecount)++;
   else {
     (*linecount)+= l/width;
     if(ept==NULL) {
       xorriso->result_open_line_len= l%width;
 break;
     }
     (*linecount)+= !!(l%width);
   }
   xorriso->result_open_line_len= 0;
   spt= ept+1;
 }
 return(1);
}


int Xorriso_pager(struct XorrisO *xorriso, char *line, int flag)
/*
 bit1= mark '@' by return 4
*/
/* return: <=0 error , 1=go on , 2=abort , 4=see flag bit1*/
{
 int ret,linecount;
 char info_text[10*SfileadrL];

 if(xorriso->result_page_length<=0 || xorriso->request_not_to_ask ||
    xorriso->dialog == 0)
   return(1);
 Xorriso_predict_linecount(xorriso,line,&linecount,0);
 if(xorriso->result_line_counter+linecount>xorriso->result_page_length) {
ask_for_page:;
   strcpy(info_text,xorriso->info_text);
   sprintf(xorriso->info_text,"\n");
   Xorriso_info(xorriso,0);
   sprintf(xorriso->info_text,
".... [Press Enter to continue. @,Enter avoids further stops. @@@ aborts] ....\n");
   Xorriso_info(xorriso,0);
   ret= Xorriso_request_confirmation(xorriso,flag&2);
   strcpy(xorriso->info_text,info_text);
   if(ret<=0)
     return(ret);
   if(ret==2)
     return(2);
   if(ret==3)
     goto ask_for_page;
 }
 xorriso->result_line_counter+= linecount;
 return(1);
}


int Xorriso_write_to_channel(struct XorrisO *xorriso,
                             char *in_text, int channel_no, int flag)
/*
 bit0= eventually backslash encode linefeeds
 bit1= text is the name of the log file for the given channel 
 bit2= text is the name of the consolidated packet log file for all channels 
bit15= with bit1 or bit2: close depicted log file
*/
{
 char *rpt, *npt, *text;
 int ret= 1, info_redirected= 0, result_redirected= 0;
 char prefix[16];
 FILE *logfile_fp, *pktlog_fp;
 struct Xorriso_lsT *msglist;
 static int num_channels= 4;
 static char channel_prefixes[4][4]= {".","R","I","M"};

 if(channel_no<0 || channel_no>=num_channels)
   {ret= -1; goto ex;}

 text= in_text; /* might change due to backslash encoding */

 /* Logfiles */
 logfile_fp= xorriso->logfile_fp[channel_no];
 pktlog_fp= xorriso->pktlog_fp;
 if((flag&2) && logfile_fp!=NULL) {
   fprintf(logfile_fp,
     "! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n",
           channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256));
   fclose(logfile_fp);
   xorriso->logfile_fp[channel_no]= logfile_fp= NULL;
 }
 if((flag&4) && pktlog_fp!=NULL) {
   fprintf(pktlog_fp,
 "I:1:! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n",
           channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256));
   fclose(pktlog_fp);
   xorriso->pktlog_fp= pktlog_fp= NULL;
 }
 if(flag&(1<<15))
   {ret= 1; goto ex;}
 if((flag&2)) {
   xorriso->logfile_fp[channel_no]= logfile_fp= fopen(text,"a");
   if(logfile_fp==NULL)
     {ret= 0; goto ex;}
   fprintf(logfile_fp,
  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : %s : %s\n",
           channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256));
   fflush(logfile_fp);
 }
 if((flag&4)) {
   xorriso->pktlog_fp= pktlog_fp= fopen(text,"a");
   if(pktlog_fp==NULL)
     {ret= 0; goto ex;}
   fprintf(pktlog_fp,
  "I:1:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : . : %s\n",
           Sfile_datestr(time(0),1|2|256));
   fflush(pktlog_fp);
 }
 if(flag&(2|4))
   {ret= 1; goto ex;}

 /* Eventually perform backslash encoding of non-printable characters */
 if(((xorriso->bsl_interpretation & 32) && channel_no == 1) ||
    ((xorriso->bsl_interpretation & 64) && channel_no == 2)) {
   ret= Sfile_bsl_encoder(&text, text, strlen(text), 1 | 2 | 4);
   if(ret <= 0)
     {ret= -1; goto ex;}
 }

 /* Eventually perform messag redirection */
 if(xorriso->msglist_stackfill > 0) {
   if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1)
     result_redirected= 1;
   if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 2)
     info_redirected= 1;
 }
 if(result_redirected) {
   if(channel_no==1 || channel_no==3) {
     msglist= xorriso->result_msglists[xorriso->msglist_stackfill - 1];
     ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0);
     if(ret <= 0)
       {ret= -1; goto ex;}
     if(xorriso->result_msglists[xorriso->msglist_stackfill - 1] == NULL)
       xorriso->result_msglists[xorriso->msglist_stackfill - 1]= msglist;
   }
 }
 if(info_redirected) {
   if(channel_no==2 || channel_no==3) {
     msglist= xorriso->info_msglists[xorriso->msglist_stackfill - 1];
     ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0);
     if(ret <= 0)
       {ret= -1; goto ex;}
     if(xorriso->info_msglists[xorriso->msglist_stackfill - 1] == NULL)
       xorriso->info_msglists[xorriso->msglist_stackfill - 1]= msglist;
   }
 }
 if((channel_no == 1 && result_redirected) ||
    (channel_no == 2 && info_redirected) ||
    (result_redirected && info_redirected))
   {ret= 1; goto ex;}

 /* Non-redirected output */
 if(!xorriso->packet_output) {
   if(channel_no==1 || channel_no==3) {
     printf("%s",text);
     fflush(stdout);
   }
   if(channel_no==2 || channel_no==3)
     fprintf(stderr,"%s",text);
   if(logfile_fp!=NULL) {
     fprintf(logfile_fp,"%s",text);
     fflush(logfile_fp);
   }
   if(pktlog_fp==NULL)
     {ret= 1; goto ex;}
 }
 rpt= text;
 sprintf(prefix,"%s:x: ",channel_prefixes[channel_no]);
 while(*rpt!=0) {
   npt= strchr(rpt,'\n');
   if(npt==NULL)
     prefix[2]= '0';
   else
     prefix[2]= '1';
   if(xorriso->packet_output) {
     ret= fwrite(prefix,5,1,stdout);
     if(ret<=0)
       {ret= 0; goto ex;}
   }
   if(pktlog_fp!=NULL) {
     ret= fwrite(prefix,5,1,pktlog_fp);
     if(ret<=0)
       {ret= 0; goto ex;}
   }
   if(npt==NULL) {
     if(xorriso->packet_output) {
       ret= fwrite(rpt,strlen(rpt),1,stdout);
       if(ret<=0)
         {ret= 0; goto ex;}
       ret= fwrite("\n",1,1,stdout);
       if(ret<=0)
         {ret= 0; goto ex;}
     }
     if(pktlog_fp!=NULL) {
       ret= fwrite(rpt,strlen(rpt),1,pktlog_fp);
       if(ret<=0)
         {ret= 0; goto ex;}
       ret= fwrite("\n",1,1,pktlog_fp);
       if(ret<=0)
         {ret= 0; goto ex;}
     }
 break;
   } else {
     if(xorriso->packet_output) {
       ret= fwrite(rpt,npt+1-rpt,1,stdout);
       if(ret<=0)
         {ret= 0; goto ex;}
     }
     if(pktlog_fp!=NULL) {
       ret= fwrite(rpt,npt+1-rpt,1,pktlog_fp);
       if(ret<=0)
         {ret= 0; goto ex;}
     }
   }
   rpt= npt+1;
 }
 if(xorriso->packet_output)
   fflush(stdout);
 if(pktlog_fp!=NULL)
   fflush(pktlog_fp);
 ret= 1;
ex:
 if(text != in_text && text != NULL)
   free(text);
 return(ret);
}


int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle,
                          int flag)
{
 if(xorriso->msglist_stackfill + 1 >= Xorriso_max_outlist_stacK) {
   Xorriso_msgs_submit(xorriso, 0,
                "Overflow of message output redirection stack", 0, "FATAL", 0);
   return(-1);
 }
 if((flag & 3) == 0)
   flag|= 3;
 xorriso->msglist_stackfill++;
 xorriso->result_msglists[xorriso->msglist_stackfill - 1]= NULL;
 xorriso->info_msglists[xorriso->msglist_stackfill - 1]= NULL;
 xorriso->msglist_flags[xorriso->msglist_stackfill - 1]= flag & 3;
 *stack_handle= xorriso->msglist_stackfill - 1;
 return(1);
}


int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle,
                          struct Xorriso_lsT **result_list,
                          struct Xorriso_lsT **info_list, int flag)
{
 int i;

 if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) {
   Xorriso_msgs_submit(xorriso, 0,
                "Program error: Wrong message output redirection stack handle",
                0, "FATAL", 0);
   return(-1);
 }
 *result_list= xorriso->result_msglists[stack_handle];
 *info_list= xorriso->info_msglists[stack_handle];
 for(i = stack_handle + 1; i < xorriso->msglist_stackfill - 1; i++) {
   xorriso->result_msglists[i - 1]= xorriso->result_msglists[i];
   xorriso->info_msglists[i - 1]= xorriso->info_msglists[i];
 }
 xorriso->msglist_stackfill--;
 return(1);
}


int Xorriso_result(struct XorrisO *xorriso, int flag)
/*
 bit0= no considerations or computations or dialog. Just put out.
*/
{
 int ret, redirected= 0;

 if(flag&1)
   goto put_it_out;
 if(xorriso->request_to_abort)
   return(1);
 if(xorriso->msglist_stackfill > 0)
   if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1)
     redirected= 1;
 if(xorriso->result_page_length>0 && !redirected) {
   ret= Xorriso_pager(xorriso,xorriso->result_line,2);
   if(ret<=0)
     return(ret);
   if(ret==2)
     return(1);
   if(xorriso->request_to_abort)
     return(1);
 }
put_it_out:;
 xorriso->bar_is_fresh= 0;
 ret= Xorriso_write_to_channel(xorriso, xorriso->result_line, 1,0);
 return(ret);
}


int Xorriso_info(struct XorrisO *xorriso, int flag)
/*
 bit0= use pager (as with result)
 bit1= permission to suppress output
 bit2= insist in showing output
*/
{
 int ret;
 static int note_sev= 0;

 if(flag&2)
   if(xorriso->request_to_abort)
     return(1);

 if(note_sev==0)
   Xorriso__text_to_sev("NOTE", &note_sev, 0);
 if(note_sev<xorriso->report_about_severity &&
    note_sev<xorriso->abort_on_severity && !(flag&4))
   return(1);

 if(flag&1) {
   ret= Xorriso_pager(xorriso,xorriso->info_text,2);
   if(ret<=0)
     return(ret);
   if(ret==2)
     return(1);
   if(flag&2)
     if(xorriso->request_to_abort)
       return(1);
 }
 xorriso->bar_is_fresh= 0;
 ret=Xorriso_write_to_channel(xorriso, xorriso->info_text, 2, 0);
 return(ret);
}


int Xorriso_mark(struct XorrisO *xorriso, int flag)
{
 int ret= 1,r_ret,i_ret;

 if(xorriso->mark_text[0]==0)
   return(1);
 if(xorriso->packet_output) 
   ret=Xorriso_write_to_channel(xorriso, xorriso->mark_text, 3, 0);
 else {
   sprintf(xorriso->result_line,"%s\n",xorriso->mark_text);
   r_ret= Xorriso_result(xorriso,1);
   strcpy(xorriso->info_text,xorriso->result_line);
   i_ret= Xorriso_info(xorriso,0);
   if(r_ret==0 || i_ret==0)
     ret= 0;
 }
 return(ret);
}


int Xorriso_restxt(struct XorrisO *xorriso, char *text)
{
 int ret;

 strncpy(xorriso->result_line,text,sizeof(xorriso->result_line)-1);
 xorriso->result_line[sizeof(xorriso->result_line)-1]= 0;
 ret= Xorriso_result(xorriso,0);
 return(ret);
}


int Xorriso_pacifier_reset(struct XorrisO *xorriso, int flag)
{
 xorriso->start_time= Sfile_microtime(0);
 xorriso->last_update_time= xorriso->start_time;
 xorriso->pacifier_count= 0;
 xorriso->pacifier_total= 0;
 xorriso->pacifier_byte_count= 0;
 return(1);
}


/* This call is to be issued by long running workers in short intervals.
   It will check whether enough time has elapsed since the last pacifier
   message and eventually issue an update message.
   @param what_done  A sparse description of the action, preferrably in past
                     tense. E.g. "done" , "files added".
   @param count The number of objects processed so far.
                Is ignored if <=0.
   @param todo  The number of objects to be done in total.
                Is ignored if <=0.
   @param current_object A string telling the object currently processed.
                         Ignored if "".
   @param flag  bit0= report unconditionally, no time check
                bit1= report count <=0 (no thank you for being patient then)
                bit2= report xorriso->pacifier_byte_count
                bit6= report with carriage return rather than line feed
*/
int Xorriso_pacifier_callback(struct XorrisO *xorriso, char *what_done,
                              off_t count, off_t todo, char *current_object,
                              int flag)
{
 double current_time, since;
 char count_text[80], byte_text[80];
 
 current_time= Sfile_microtime(0);
 if(current_time - xorriso->last_update_time < xorriso->pacifier_interval
    && !(flag&1))
   return(1);
 xorriso->last_update_time= Sfile_microtime(0);
 since= current_time - xorriso->start_time;
 if((flag&1)&&since<1.0)
   since= 1.0;
 byte_text[0]= 0;
 if(flag&4) {
   strcat(byte_text, " (");
   Sfile_scale((double) xorriso->pacifier_byte_count,
               byte_text+strlen(byte_text), 7, 1e5, 0);
   strcat(byte_text, ")");
 }
 if(count<=0.0 && !(flag&2)) {
   sprintf(xorriso->info_text,
           "Thank you for being patient for %.f seconds", since);
 } else if(todo<=0.0) {
   if(count<10000000)
     sprintf(count_text, "%.f", (double) count);
   else
     Sfile_scale((double) count, count_text, 7, 1e5, 1);
   sprintf(xorriso->info_text, "%s %s%s in %.f %s",
         count_text, what_done, byte_text, since, (flag&64) ? "s" : "seconds");
 } else {
   sprintf(xorriso->info_text, "%.f of %.f %s%s in %.f seconds",
           (double) count, (double) todo, what_done, byte_text, since);
 }
 if(current_object[0]!=0)
   sprintf(xorriso->info_text+strlen(xorriso->info_text),
           ", now at %s", current_object);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", (flag&64));
 return(1);
}


int Xorriso_reset_counters(struct XorrisO *xorriso, int flag)
{
 xorriso->error_count= 0;
 xorriso->insert_count= 0;
 xorriso->insert_bytes= 0;
 Xorriso_pacifier_reset(xorriso, 0);
 return(1);
}


int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag)
/* reg_expr should be twice as large as bourne_expr ( + 2 to be exact) */
/* return: 2= bourne_expr is surely a constant */
{
 char *wpt,*lpt;
 int backslash= 0,is_constant= 1,in_square_brackets= 0;
 int first_in_square_brackets=0;

 wpt= reg_expr;
 lpt= bourne_expr;

 *(wpt++)= '^';

 while(*lpt!=0){
  if(first_in_square_brackets>0)
    first_in_square_brackets--;
  if(!backslash){
    switch(*lpt){
    case '?':
      *(wpt++)= '.';
      is_constant= 0;
    break;case '*':
      *(wpt++)= '.';
      *(wpt++)= '*';
      is_constant= 0;
    break;case '.':
      *(wpt++)= '\\';
      *(wpt++)= '.';
    break;case '+':
      *(wpt++)= '\\';
      *(wpt++)= '+';
    break;case '[':
      *(wpt++)= *lpt;
      first_in_square_brackets= 2;
      in_square_brackets= 1;
      is_constant= 0;
    break;case ']':
      *(wpt++)= *lpt;
      in_square_brackets= 0;
    break;case '!':
      if(first_in_square_brackets)
        *(wpt++)= '^';
      else if(in_square_brackets)
        *(wpt++)= '!';
      else {
        *(wpt++)= '\\';
        *(wpt++)= '!';
      }
    break;case '^':
      if(in_square_brackets)
        *(wpt++)= '^';
      else
        *(wpt++)= '\\';
        *(wpt++)= '^';
    break;case '$':
      *(wpt++)= '\\';
      *(wpt++)= '$';
    break;case '\\':
      backslash= 1;
      *(wpt++)= '\\';
      is_constant= 0;
    break;default:
      *(wpt++)= *lpt;
    }
  } else {
    backslash= 0;
    *(wpt++)= *lpt;
  }
  lpt++;
 }
 *(wpt++)= '$';
 *wpt= 0;
 return(1+(is_constant>0));
}


/* @param flag bit0= do not augment relative structured search by xorriso->wdi
               bit1= return 2 if bonked at start point by .. 
                     (caller then aborts or retries without bit0)
               bit2= eventually prepend wdx rather than wdi
   @return <=0 error, 1= ok, 2= with bit1: relative pattern exceeds start point
*/
int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag)
{
 int l,ret,i,count,bonked= 0,is_constant,is_still_relative= 0;
 char *cpt,*npt,adr_part[2*SfileadrL],absolute_adr[2*SfileadrL],*adr_start,*wd;

 if(flag&4)
   wd= xorriso->wdx;
 else
   wd= xorriso->wdi;

 if(xorriso->search_mode>=2 && xorriso->search_mode<=4) {
   if(xorriso->search_mode==3 || xorriso->search_mode==4) {
     l= strlen(adr)+strlen(wd)+1;
     if(l*2+2>sizeof(xorriso->reg_expr) || l*2+2>sizeof(adr_part)) {
       sprintf(xorriso->info_text,"Search pattern too long");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       return(0);
     }
   }
   Xorriso_destroy_re(xorriso,0);
   if(xorriso->structured_search && xorriso->search_mode==3) {
     if(adr[0]!='/')
       is_still_relative= 1;
     if(is_still_relative && !(flag&1)) {
       /* relative expression : prepend working directory */
       sprintf(absolute_adr,"%s/%s",wd,adr);
       adr_start= absolute_adr;
       xorriso->prepended_wd= 1;
       is_still_relative= 0;
     } else
       adr_start= adr;
     /* count slashes */;
     cpt= adr_start;
     while(*cpt=='/')
       cpt++;
     for(i= 0;1;i++) {
       cpt= strchr(cpt,'/');
       if(cpt==NULL)
     break;
       while(*cpt=='/')
         cpt++;
     }
     count= i+1;
     xorriso->re= TSOB_FELD(regex_t,count);
     if(xorriso->re==NULL)
       return(-1);
     xorriso->re_constants= TSOB_FELD(char *,count);
     if(xorriso->re_constants==NULL)
       return(-1);
     for(i= 0;i<count;i++)
       xorriso->re_constants[i]= NULL;
     xorriso->re_count= count;
     xorriso->re_fill= 0;
       
     /* loop over slash chunks*/;
     cpt= adr_start;
     xorriso->re_fill= 0;
     while(*cpt=='/')
       cpt++;
     for(i= 0;i<count;i++) {
       npt= strchr(cpt,'/');
       if(npt==NULL) {
         if(strlen(cpt)>=sizeof(adr_part))
           return(-1);
         strcpy(adr_part,cpt);
       } else {
         if(npt-cpt>=sizeof(adr_part))
           return(-1);
         strncpy(adr_part,cpt,npt-cpt);
         adr_part[npt-cpt]= 0;
       }

       if(adr_part[0]==0)
         goto next_adr_part;
       if(adr_part[0]=='.' && adr_part[1]==0 &&
          (xorriso->re_fill>0 || i<count-1))
         goto next_adr_part;
       if(adr_part[0]=='.' && adr_part[1]=='.' && adr_part[2]==0) {
         /* delete previous part */
         if(xorriso->re_fill <= 0) {
           bonked= 1;
           goto next_adr_part;
         } 
         if(xorriso->re_constants[xorriso->re_fill-1]!=NULL) {
           free(xorriso->re_constants[xorriso->re_fill-1]);
           xorriso->re_constants[xorriso->re_fill-1]= NULL;
         } else
           regfree(&(xorriso->re[xorriso->re_fill-1]));
         (xorriso->re_fill)--;
         goto next_adr_part;
       }
       if(strcmp(adr_part,"*")==0) {
         adr_part[0]= 0;
         ret= 2;
       } else
         ret= Xorriso__bourne_to_reg(adr_part,xorriso->reg_expr,0);
       if(ret==2) {
         if(Sregex_string(&(xorriso->re_constants[xorriso->re_fill]),adr_part,0)
            <=0)
           return(-1);
       } else {
         if(regcomp(&(xorriso->re[xorriso->re_fill]),xorriso->reg_expr,0)!=0)
           goto cannot_compile;
       }
       xorriso->re_fill++;
next_adr_part:;
       if(i==count-1)
     break;
       cpt= npt+1;
       while(*cpt=='/')
         cpt++;
     }
     if(bonked) {
       if(flag&2)
         return(2);
       sprintf(xorriso->info_text, "Your '..' bonked at the %s directory.",
               is_still_relative ? "working" : "root");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
       return(0);
     }

     Xorriso__bourne_to_reg(adr_start,xorriso->reg_expr,0); /* just for show */

   } else { 
     is_constant= 0;
     if(strcmp(adr,"*")==0 || adr[0]==0) {
       is_constant= 1;
     } else if(xorriso->search_mode==3 || xorriso->search_mode==4) {
       ret= Xorriso__bourne_to_reg(adr,xorriso->reg_expr,0);
       is_constant= (ret==2);
     } else {
       if(strlen(adr)>=sizeof(xorriso->reg_expr))
         return(-1);
       strcpy(xorriso->reg_expr,adr);
     }
     xorriso->re_count= 0; /* tells matcher that this is not structured */
     xorriso->re_constants= TSOB_FELD(char *,1);
     if(xorriso->re_constants==NULL)
       return(-1);
     xorriso->re_constants[0]= NULL;
     if(is_constant) {
       if(strcmp(adr,"*")==0) {
         if(Sregex_string(&(xorriso->re_constants[0]),"",0)<=0)
           return(-1);
       } else {
         if(Sregex_string(&(xorriso->re_constants[0]),adr,0)<=0)
           return(-1);
       }
       xorriso->re_fill= 1;
     } else { 
       xorriso->re= TSOB_FELD(regex_t,1);
       if(xorriso->re==NULL)
         return(-1);
       if(regcomp(&(xorriso->re[0]),xorriso->reg_expr,0)!=0) {
cannot_compile:;
         sprintf(xorriso->info_text, "Cannot compile regular expression : %s",
                 xorriso->reg_expr);
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
         return(0);
       }
     }

   }
 }
 return(1);
}


/* @param flag bit0= do not shortcut last component of to_match
               bit1= consider match if regex matches parent of path
               bit2= retry beginning at failed last component 

 @return 0=match , else no match 
*/
int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at,
                    int flag)
{
 int ret,i,re_start= 0,reg_nomatch= -1;
 char *cpt,*npt,adr_part[SfileadrL],*mpt;

 reg_nomatch= REG_NOMATCH;

 *failed_at= 0;
 if(!(xorriso->structured_search && xorriso->re_count>0)) {
   if(xorriso->re_constants!=NULL)
     if(xorriso->re_constants[0]!=NULL) {
       if(xorriso->re_constants[0][0]==0)
         return(0);
       if(strcmp(xorriso->re_constants[0],to_match)!=0)
         return(reg_nomatch);
       return(0);
     }  
   ret= regexec(&(xorriso->re[0]),to_match,1,xorriso->match,0);
   return(ret);
 }

 cpt= to_match;
 while(*cpt=='/')
  cpt++;
 if(flag&4)
   re_start= xorriso->re_failed_at;
 if(re_start<0)
   re_start= 0;
 for(i= re_start;i<xorriso->re_fill;i++) {
   *failed_at= i;
   npt= strchr(cpt,'/');
   if(npt==NULL) {
     if(i<xorriso->re_fill-1 && !(flag&1)) 
       return(reg_nomatch); /* this must be the last expression part */
     mpt= cpt;
   } else {
     strncpy(adr_part,cpt,npt-cpt);
     adr_part[npt-cpt]= 0;
     mpt= adr_part;
   }
   if(xorriso->re_constants[i]!=NULL) {
     if(xorriso->re_constants[i][0]!=0) /* empty constant matches anything */
       if(strcmp(xorriso->re_constants[i],mpt)!=0)
         return(reg_nomatch);
   } else {
     ret= regexec(&(xorriso->re[i]),mpt,1,xorriso->match,0);
     if(ret!=0)
       return(ret);
   }
   if(npt==NULL) {
     if(i>=xorriso->re_fill-1)
       return(0); /* MATCH */
     *failed_at= i+1;
     return(reg_nomatch);
   }
   cpt= npt+1;
   while(*cpt=='/')
     cpt++; 
 }
 *failed_at= xorriso->re_fill;
 if(flag & 2)
   return(0); /* MATCH */
 return(reg_nomatch);
}


int Xorriso_is_in_patternlist(struct XorrisO *xorriso,
                              struct Xorriso_lsT *patternlist, char *path,
                              int flag)
{
 int ret, failed_at, i= 0;
 struct Xorriso_lsT *s;

 xorriso->search_mode= 3;
 xorriso->structured_search= 1;

 for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
   ret= Xorriso_prepare_regex(xorriso, Xorriso_lst_get_text(s, 0), 0);
   if(ret <= 0)
     return(-1);
   /* Match path or parent of path */
   ret= Xorriso_regexec(xorriso, path, &failed_at, 2);
   if(ret == 0)
     return(i + 1);
   i++;
 }
 return(0);
}


char *Xorriso_get_pattern(struct XorrisO *xorriso,
                          struct Xorriso_lsT *patternlist, int index, int flag)
{
 int i= 0;
 struct Xorriso_lsT *s;

 for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
   if(i == index)
     return(Xorriso_lst_get_text(s, 0));
   i++;
 }
 return(NULL);
}


/* @param flag bit0= simple readlink(): no normalization, no multi-hop
*/
int Xorriso_resolve_link(struct XorrisO *xorriso,
                     char *link_path, char result_path[SfileadrL], int flag)
{
 ssize_t l;
 struct stat stbuf;
 int link_count= 0, ret, show_errno= 0;
 char buf[SfileadrL], dirbuf[SfileadrL], *lpt, *spt, sfe[5*SfileadrL];
 static int link_limit= 100;

 if(!(flag&1))
   if(stat(link_path, &stbuf)==-1)
     if(errno==ELOOP) {
       show_errno= errno;
       goto too_many_hops;
     }
 lpt= link_path;
 while(1) {
   l= readlink(lpt, buf, SfileadrL-1);
   if(l==-1) {
handle_error:;
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
     sprintf(xorriso->info_text, "Cannot obtain link target of : %s",
             Text_shellsafe(link_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
handle_abort:;
     if(strcmp(lpt, link_path)!=0) {
       sprintf(xorriso->info_text,
               "Problem occured with intermediate path : %s",
               Text_shellsafe(lpt, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
     }
     return(0);
   }
   buf[l]= 0;
   if(l==0) {
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
     sprintf(xorriso->info_text, "Empty link target with : %s",
             Text_shellsafe(link_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
     goto handle_abort;
   }

   if(flag&1) {
     strcpy(result_path, buf);
     return(1);
   }

   /* normalize relative to disk_path */
   if(Sfile_str(dirbuf, lpt, 0)<=0)
     return(-1);
   while(1) {
     spt= strrchr(dirbuf,'/');
     if(spt!=NULL) {
       *spt= 0;
       if(*(spt+1)!=0)
   break;
     } else
   break;
   }
   ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4);
   if(ret<=0)
     return(ret);

   if(lstat(result_path, &stbuf)==-1) {
     lpt= result_path;
     goto handle_error;
   }
   if(!S_ISLNK(stbuf.st_mode))
 break;
   
   lpt= result_path;
   link_count++;
   if(link_count>link_limit) {
too_many_hops:;
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
     sprintf(xorriso->info_text, "Too many link hops with : %s",
             Text_shellsafe(link_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
                         "FAILURE",0);
     return(0);
   }
 }
 return(1);
}


int Xorriso_status_filter(struct XorrisO *xorriso, char *filter, char *line,
                          int flag)
{
 if(filter!=NULL)
   if(filter[0]=='-')
     if(strncmp(filter, line, strlen(filter))!=0)
       return(0);
 return(1);
}


int Xorriso_status_result(struct XorrisO *xorriso, char *filter, FILE *fp,
                          int flag)
/* 
bit1= do only report to fp
*/
{
 int ret;

 ret= Xorriso_status_filter(xorriso, filter, xorriso->result_line, 0);
 if(ret <= 0)
   return(2);
 if(!(flag&2))
   Xorriso_result(xorriso,0);
 if(fp!=NULL) {
   ret= fwrite(xorriso->result_line,strlen(xorriso->result_line),1,fp);
   if(ret<=0)
     return(ret);
 }   
 return(1);
}


int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
                               struct CheckmediajoB *job,
                               char **argv, int old_idx, int end_idx, int flag)
{
 int ret, i, sev;
 double num;
 struct CheckmediajoB *default_job;
 char sev_text[20];

 if(xorriso->check_media_default != NULL)
   Checkmediajob_copy(xorriso->check_media_default, job, 0);
 for(i= old_idx; i < end_idx; i++) {
   if(strncmp(argv[i], "abort_file=", 11) == 0) {
     ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0);
     if(ret <= 0)
       goto ex;
   } else if(strncmp(argv[i], "bad_limit=", 10) == 0) {
     if(strcmp(argv[i] + 10, "good") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_gooD;
     else if(strcmp(argv[i] + 10, "md5_match") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_md5_matcH;
     else if(strcmp(argv[i] + 10, "slow") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_sloW;
     else if(strcmp(argv[i] + 10, "partial") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_partiaL;
     else if(strcmp(argv[i] + 10, "valid") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_valiD;
     else if(strcmp(argv[i] + 10, "untested") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_untesteD;
     else if(strcmp(argv[i] + 10, "invalid") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
     else if(strcmp(argv[i] + 10, "tao_end") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_tao_enD;
     else if(strcmp(argv[i] + 10, "off_track") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_off_tracK;
     else if(strcmp(argv[i] + 10, "md5_mismatch") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_md5_mismatcH;
     else if(strcmp(argv[i] + 10, "unreadable") == 0)
       xorriso->check_media_bad_limit= Xorriso_read_quality_unreadablE;
     else
       goto unknown_value;
   } else if(strncmp(argv[i], "data_to=", 8) == 0) {
     ret= Sfile_str(job->data_to_path, argv[i] + 8, 0);
     if(ret <= 0)
       goto ex;
   } else if(strncmp(argv[i], "chunk_size=", 11) == 0) {
     num= Scanf_io_size(argv[i] + 11, 1);
     if(num >= 2048 || num == 0)
       job->min_block_size= num / 2048;
     else
       goto unknown_value;
   } else if(strncmp(argv[i], "event=", 6) == 0) {
     strncpy(sev_text, argv[i] + 6, 19);
     sev_text[19]= 0;
     ret= Xorriso__text_to_sev(sev_text, &sev, 0);
     if(ret <= 0) {
       strcpy(xorriso->info_text, "-check_media event=");
       Text_shellsafe(sev_text, xorriso->info_text, 1);
       strcat(xorriso->info_text, " : Not a known severity name");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       goto ex;
     }
     strcpy(job->event_severity, sev_text);
   } else if(strncmp(argv[i], "map_with_volid=", 15) == 0) {
     if(strcmp(argv[i] + 15, "on") == 0)
       job->map_with_volid= 1;
     else if(strcmp(argv[i] + 15, "off") == 0)
       job->map_with_volid= 0;
     else
       goto unknown_value;
   } else if(strncmp(argv[i], "max_lba=", 8) == 0 ||
      strncmp(argv[i], "min_lba=", 8) == 0) {
     num= -1;
     sscanf(argv[i] + 8, "%lf", &num);
     if(num > 0x7fffffff || num < 0)
       num= -1;
     if(strncmp(argv[i], "max_lba=", 8) == 0)
       job->max_lba= num;
     else
       job->min_lba= num;
   } else if(strncmp(argv[i], "patch_lba0=", 11) == 0) {
     job->patch_lba0_msc1= -1;
     if(strcmp(argv[i] + 11, "on") == 0)
       job->patch_lba0= 1;
     else if(strcmp(argv[i] + 11, "off") == 0)
       job->patch_lba0= 0;
     else if(strcmp(argv[i] + 11, "force") == 0)
       job->patch_lba0= 2;
     else if(argv[i][11] >= '1' && argv[i][11] <= '9') {
       num= -1;
       sscanf(argv[i] + 11, "%lf", &num);
       if(num > 0x7fffffff || num < 0)
         goto unknown_value;
       job->patch_lba0_msc1= num;
       job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL);
     } else 
       goto unknown_value;
   } else if(strncmp(argv[i], "report=", 7) == 0) {
     if(strcmp(argv[i] + 7, "blocks") == 0)
       job->report_mode= 0;
     else if(strcmp(argv[i] + 7, "files") == 0)
       job->report_mode= 1;
     else if(strcmp(argv[i] + 7, "blocks_files") == 0)
       job->report_mode= 2;
     else
       goto unknown_value;
   } else if(strcmp(argv[i], "reset=now") == 0) {
     ret= Checkmediajob_new(&default_job, 0);
     if(ret <= 0) {
       sprintf(xorriso->info_text,
               "-check_media: Cannot reset options due to lack of resources");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
       ret= -1; goto ex;
     }
     Checkmediajob_copy(default_job, job, 0);
     Checkmediajob_destroy(&default_job, 0);
     xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
   } else if(strncmp(argv[i], "retry=", 6) == 0) {
     if(strcmp(argv[i] + 6, "on") == 0)
       job->retry= 1;
     else if(strcmp(argv[i] + 6, "off") == 0)
       job->retry= -1;
     else if(strcmp(argv[i] + 6, "default") == 0)
       job->retry= 0;
     else
       goto unknown_value;
   } else if(strncmp(argv[i], "sector_map=", 11) == 0) {
     ret= Sfile_str(job->sector_map_path, argv[i] + 11, 0);
     if(ret <= 0)
       goto ex;
   } else if(strncmp(argv[i], "slow_limit=", 11) == 0) {
     sscanf(argv[i] + 11, "%lf", &(job->slow_threshold_seq));
   } else if(strncmp(argv[i], "time_limit=", 11) == 0 ||
             strncmp(argv[i], "item_limit=", 11) == 0 ) {
     num= -1;
     sscanf(argv[i] + 11, "%lf", &num);
     if(num > 0x7fffffff || num < 0)
       num= -1;
     if(strncmp(argv[i], "time_limit=", 11) == 0)
       job->time_limit= num;
     else
       job->item_limit= num;

#ifdef NIX
   } else if(strncmp(argv[i], "untested=", 9) == 0) {
     if(strcmp(argv[i] + 9, "damaged") == 0)
       job->untested_valid= 0;
     if(strcmp(argv[i] + 9, "undamaged") == 0 ||
        strcmp(argv[i] + 9, "ok") == 0)
       job->untested_valid= 1;
     else
       goto unknown_value;
#endif

   } else if(strncmp(argv[i], "use=", 4) == 0) {
     if(strcmp(argv[i] + 4, "outdev") == 0)
       job->use_dev= 1;
     else if(strcmp(argv[i] + 4, "indev") == 0)
       job->use_dev= 0;
     else if(strcmp(argv[i] + 4, "sector_map") == 0)
       job->use_dev= 2;
     else
       goto unknown_value;
   } else if(strncmp(argv[i], "what=", 5) == 0) {
     if(strcmp(argv[i]+5, "tracks") == 0)
       job->mode= 0;
     else if(strcmp(argv[i]+5, "disc")== 0)
       job->mode= 1;
     else {
unknown_value:;
       sprintf(xorriso->info_text,
               "-check_media: Unknown value with option %s", argv[i]);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   } else {
     sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   }
 }
 ret= 1;
ex:;
 return(ret);
}


/* @param report Buffer of at least 10*SfileadrL
   @param flag bit0= only report non-default settings
   @return <=0 error , 1 ok , 2 with bit0: every option is on default setting
*/
int Xorriso_check_media_list_job(struct XorrisO *xorriso,
                                 struct CheckmediajoB *job,
                                 char *report, int flag)
{
 int all, ret;
 char default_report[161], quality_name[80];
 struct CheckmediajoB *dflt= NULL;

 all= !(flag&1);
 report[0]= 0;
 ret= Checkmediajob_new(&dflt, 0);
 if(ret <= 0)
   return(-1);
 sprintf(report, "-check_media_defaults");
 if(!all)
   strcat(report, " reset=now");
 if(all || job->use_dev != dflt->use_dev) 
   sprintf(report + strlen(report), " use=%s",
           job->use_dev == 1 ? "outdev" :
           job->use_dev == 2 ? "sector_map" : "indev");
 if(all || job->mode != dflt->mode)
   sprintf(report + strlen(report), " what=%s",
           job->mode == 1 ? "disc" : "tracks");
 if(all || job->min_lba != dflt->min_lba)
   sprintf(report + strlen(report), " min_lba=%d", job->min_lba);
 if(all || job->max_lba != dflt->max_lba)
   sprintf(report + strlen(report), " max_lba=%d", job->max_lba);
 if(all || job->retry != dflt->retry)
   sprintf(report + strlen(report), " retry=%s",
           job->retry == 1 ? "on" : job->retry == -1 ? "off" : "default");
 if(all || job->time_limit != dflt->time_limit)
   sprintf(report + strlen(report), " time_limit=%d", job->time_limit);
 if(all || job->item_limit != dflt->item_limit)
   sprintf(report + strlen(report), " item_limit=%d", job->item_limit);
 if(all || strcmp(job->abort_file_path, dflt->abort_file_path)) {
   strcat(report, " abort_file=");
   Text_shellsafe(job->abort_file_path, report + strlen(report), 0);
 }
 if(strlen(report) > 4 * SfileadrL)
   {ret= 0; goto ex;}
 if(all || strcmp(job->data_to_path, dflt->data_to_path)) {
   strcat(report, " data_to=");
   Text_shellsafe(job->data_to_path, report + strlen(report), 0);
 }
 if(strlen(report) > 4 * SfileadrL)
   {ret= 0; goto ex;}
 if(all || strcmp(job->sector_map_path, dflt->sector_map_path)) {
   strcat(report, " sector_map=");
   Text_shellsafe(job->sector_map_path, report + strlen(report), 0);
 }
 if(all || job->map_with_volid != dflt->map_with_volid)
   sprintf(report + strlen(report), " map_with_volid=%s",
           job->map_with_volid == 1 ? "on" : "off");
 if(all || job->patch_lba0 != dflt->patch_lba0) {
   sprintf(report + strlen(report), " patch_lba0=");
   if(job->patch_lba0 == 0)
     sprintf(report + strlen(report), "off");
   else if(job->patch_lba0_msc1 >= 0)
     sprintf(report + strlen(report), "%d%s",
             job->patch_lba0_msc1, job->patch_lba0 == 2 ? ":force" : "");
   else
     sprintf(report + strlen(report), "%s",
             job->patch_lba0 == 2 ? "force" : "on");
 }
 if(all || job->report_mode != dflt->report_mode)
   sprintf(report + strlen(report), " report=%s",
           job->report_mode == 0 ? "blocks" :
           job->report_mode == 1 ? "files" : "blocks_files");
 if(all || job->slow_threshold_seq != dflt->slow_threshold_seq)
   sprintf(report + strlen(report), " slow_limit=%f", job->slow_threshold_seq);
 if(all || xorriso->check_media_bad_limit != Xorriso_read_quality_invaliD)
   sprintf(report + strlen(report), " bad_limit=%s",
           Spotlist__quality_name(xorriso->check_media_bad_limit, quality_name,
                                  Xorriso_read_quality_invaliD, 0) + 2);
 if(all || job->min_block_size != dflt->min_block_size)
   sprintf(report + strlen(report), " chunk_size=%ds", job->min_block_size);
 if(all || strcmp(job->event_severity, "ALL") != 0)
   sprintf(report + strlen(report), " event=%s", job->event_severity);
 if(strlen(report) > 4 * SfileadrL)
   {ret= 0; goto ex;}
 ret= 1;
ex:;
 strcat(report, " ");
 strcat(report, xorriso->list_delimiter);
 Checkmediajob_destroy(&dflt, 0);
 sprintf(default_report, "-check_media_defaults reset=now %s",
         xorriso->list_delimiter);
 if(ret > 0 && strcmp(report, default_report) == 0)
   return(2);
 return(ret);
}


int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag)
/*
 bit0= do only report non-default settings
 bit1= do only report to fp
 bit2= report current -resume status even if bit0 is set, but only if valid
 bit3= report readline history
 bit4= report -resume options indirectly as 
              -options_from_file:${resume_state_file}_pos
*/
{
 int is_default, no_defaults, i, ret, adr_mode, bin_path_in_use= 0, do_single;
 int show_indev= 1, show_outdev= 1, show_dev= 0;
 char *line, sfe[5 * SfileadrL + 80], mode[80], *form, *treatment;
 char *in_pt, *out_pt, *nl_charset, *local_charset, *mode_pt;
 char *dev_filter= NULL;
 static char channel_prefixes[4][4]= {".","R","I","M"};
 static char load_names[][20]= {"auto", "session", "track", "lba", "volid"};
 static int max_load_mode= 4;
 struct Xorriso_lsT *paths, *leafs, *s;

 no_defaults= flag&1;
 line= xorriso->result_line;

 if(xorriso->no_rc) {
   sprintf(line,"-no_rc\n");
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 is_default= strcmp(xorriso->list_delimiter, "--") == 0;
 sprintf(line,"-list_delimiter %s\n", xorriso->list_delimiter);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= 0;
 if(xorriso->dialog == 2)
   sprintf(line,"-dialog on\n");
 else if(xorriso->dialog == 1)
   sprintf(line,"-dialog single_line\n");
 else {
   sprintf(line,"-dialog off\n");
   is_default= 1;
 }
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->result_page_length==0 && xorriso->result_page_width==80);
 sprintf(line,"-page %d %d\n",
              (xorriso->result_page_length>=0?xorriso->result_page_length
                                           :-xorriso->result_page_length),
              xorriso->result_page_width);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->use_stdin==0);
 sprintf(line,"-use_readline %s\n", (xorriso->use_stdin?"off":"on"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->bsl_interpretation == 0);
 strcpy(line, "-backslash_codes ");
 if(xorriso->bsl_interpretation == 0)
   strcat(line, "off");
 else if(xorriso->bsl_interpretation == (3 | 16 | 32 | 64))
   strcat(line, "on");
 else {
   if((xorriso->bsl_interpretation & 3) == 1)
     strcat(line, "in_double_quotes");
   else if((xorriso->bsl_interpretation & 3) == 2)
     strcat(line, "in_quotes");
   else if((xorriso->bsl_interpretation & 3) == 3)
     strcat(line, "with_quoted_input");
   if(xorriso->bsl_interpretation & 16) {
     if(strlen(line) > 17)
       strcat(line, ":"); 
     strcat(line, "with_program_arguments");
   }
   if((xorriso->bsl_interpretation & (32 | 64)) == (32 | 64)) {
     if(strlen(line) > 17)
       strcat(line, ":"); 
     strcat(line, "encode_output");
   } else {
     if(xorriso->bsl_interpretation & 32) {
       if(strlen(line) > 17)
         strcat(line, ":"); 
       strcat(line, "encode_results");
     }
     if(xorriso->bsl_interpretation & 64) {
       if(strlen(line) > 17)
         strcat(line, ":"); 
       strcat(line, "encode_infos");
     }
   }
 }
 strcat(line, "\n");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= !xorriso->packet_output;
 sprintf(line,"-pkt_output %s\n",(xorriso->packet_output?"on":"off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 for(i=0;i<4;i++) {
   is_default= (xorriso->logfile[i]!=0);
   sprintf(line,"-logfile %s %s\n",
           channel_prefixes[i],Text_shellsafe(xorriso->logfile[i],sfe,0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 is_default= (xorriso->errfile_log[0]==0);
 sprintf(line,"-errfile_log %s\n",Text_shellsafe(xorriso->errfile_log,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 if(xorriso->check_media_default == NULL) {
   is_default= 1;
   sprintf(line, "-check_media_defaults reset=now %s\n",
           xorriso->list_delimiter);
 } else {
   ret= Xorriso_check_media_list_job(xorriso, xorriso->check_media_default,
                                     line, no_defaults);
   is_default= (ret == 2);
   strcat(line, "\n");
 }
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->img_read_error_mode==2);
 treatment= "best_effort";
 if(xorriso->img_read_error_mode==1)
   treatment= "failure";
 else if(xorriso->img_read_error_mode==2)
   treatment= "fatal";
 sprintf(line,"-error_behavior image_loading %s\n", treatment);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 is_default= (xorriso->extract_error_mode == 1);
 treatment= "keep";
 if(xorriso->extract_error_mode == 0)
   treatment= "best_effort";
 else if(xorriso->extract_error_mode == 2)
   treatment= "delete";
 sprintf(line,"-error_behavior file_extraction %s\n", treatment);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->mark_text[0]==0);
 sprintf(line,"-mark %s\n",Text_shellsafe(xorriso->mark_text,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->temp_mem_limit==16*1024*1024);
 if((xorriso->temp_mem_limit/1024/1024)*1024*1024==xorriso->temp_mem_limit)
   sprintf(line,"-temp_mem_limit %dm\n", xorriso->temp_mem_limit/1024/1024);
 else
   sprintf(line,"-temp_mem_limit %dk\n", xorriso->temp_mem_limit/1024);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);


 sprintf(line,"-prog %s\n",Text_shellsafe(xorriso->progname,sfe,0));
 Xorriso_status_result(xorriso,filter,fp,flag&2);

 if(xorriso->ban_stdio_write) {
   sprintf(line,"-ban_stdio_write\n");
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 is_default= (xorriso->allow_restore==0 && xorriso->do_concat_split==1 &&
              xorriso->do_auto_chmod==0 && xorriso->drives_exclusive == 1);
 mode_pt= "off"; 
 if(xorriso->allow_restore == -1)
   mode_pt= "banned";
 else if(xorriso->allow_restore == 1)
   mode_pt= "on";
 else if(xorriso->allow_restore == 2)
   mode_pt= "device_files";
 if(xorriso->allow_restore == -1)
   sprintf(line,"-osirrox %s\n", mode_pt);
 else
   sprintf(line,"-osirrox %s:%s:%s:%s:%s\n", mode_pt,
         xorriso->do_concat_split ? "concat_split_on" : "concat_split_off",
         xorriso->do_auto_chmod ? "auto_chmod_on" : "auto_chmod_off",
         xorriso->do_restore_sort_lba ? "sort_lba_on" : "sort_lba_off",
         xorriso->drives_exclusive ? "o_excl_on" : "o_excl_off"
        );
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->mount_opts_flag == 0);
  sprintf(line,"-mount_opts %s\n",
          xorriso->mount_opts_flag & 1 ? "shared" : "exclusive");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->keep_boot_image == 0
              && xorriso->patch_isolinux_image == 0
              && xorriso->boot_image_bin_path[0] == 0);
 form= "any";
 treatment= "discard";
 if(xorriso->boot_image_bin_path[0]) {
   form= "isolinux";
   if(strcmp(xorriso->boot_image_bin_path, "/isolinux.bin") == 0 &&
      strcmp(xorriso->boot_image_cat_path, "/boot.cat") == 0)
     strcpy(sfe, "dir=/");
   else if(strcmp(xorriso->boot_image_bin_path, "/isolinux/isolinux.bin") == 0
        && strcmp(xorriso->boot_image_cat_path, "/isolinux/boot.cat") == 0)
     strcpy(sfe, "dir=/isolinux");
   else if(strcmp(xorriso->boot_image_bin_path,
                  "/boot/isolinux/isolinux.bin") == 0
        && strcmp(xorriso->boot_image_cat_path,
                  "/boot/isolinux/boot.cat") == 0)
     strcpy(sfe, "dir=/boot/isolinux");
   else {
     strcpy(sfe, "bin_path=");
     Text_shellsafe(xorriso->boot_image_bin_path, sfe + strlen(sfe), 0);
     bin_path_in_use= 1;
   }
   treatment= sfe;
 } else if(xorriso->patch_isolinux_image) {
   form= "isolinux";
   treatment= "patch";
 } else if(xorriso->keep_boot_image) {
   treatment= "keep";
 }
 sprintf(line,"-boot_image %s %s\n", form, treatment);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 if(xorriso->boot_image_bin_path[0] && bin_path_in_use) {
   is_default= 0;
   sprintf(line,"-boot_image isolinux cat_path=%s\n",
           Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   is_default= xorriso->boot_image_load_size == 4 * 512;
   sprintf(line,"-boot_image isolinux load_size=%.f\n",
           (double) xorriso->boot_image_load_size);
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso,filter,fp,flag&2);
 }
 if(strcmp(form, "isolinux") == 0) {
   static char modes[4][6]= {"off", "auto", "on", "force"};
   is_default= (xorriso->boot_image_isohybrid == 1);
   sprintf(line,"-boot_image isolinux isohybrid=%s\n",
           modes[xorriso->boot_image_isohybrid & 3]);
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 sprintf(line,"-cd %s\n",
         (xorriso->wdi[0] ? Text_shellsafe(xorriso->wdi,sfe,0) : "'/'"));
 Xorriso_status_result(xorriso,filter,fp,flag&2);
 sprintf(line,"-cdx %s\n",
         (xorriso->wdx[0] ? Text_shellsafe(xorriso->wdx,sfe,0) : "'/'"));
 Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->split_size==0);
 strcpy(line,"-split_size ");
 if(xorriso->split_size % (1024*1024) || xorriso->split_size==0) {
   Sfile_off_t_text(line+strlen(line), xorriso->split_size, 0);
 } else {
   Sfile_off_t_text(line+strlen(line), xorriso->split_size / (1024*1024), 0);
   strcat(line, "m");
 }
 strcat(line, "\n");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->add_plainly==0);
 sprintf(line,"-add_plainly %s\n",
         (xorriso->add_plainly == 1 ? "unknown" : 
          xorriso->add_plainly == 2 ? "dashed" :
          xorriso->add_plainly == 3 ? "any" : "none"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 ret= Exclusions_get_descrs(xorriso->disk_exclusions, &paths, &leafs, 0);
 if(ret>0) {
   for(; paths!=NULL; paths= paths->next) {
     sprintf(line, "-not_paths %s %s\n",
             Text_shellsafe(paths->text, sfe, 0), xorriso->list_delimiter);
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   } 
   for(; leafs!=NULL; leafs= leafs->next) {
     sprintf(line,"-not_leaf %s\n", Text_shellsafe(leafs->text, sfe, 0));
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   } 
 }

 is_default= (xorriso->file_size_limit ==
              Xorriso_default_file_size_limiT);
 if(xorriso->file_size_limit <= 0)
   sprintf(line, "-file_size_limit off %s\n", xorriso->list_delimiter);
 else
   sprintf(line, "-file_size_limit %.f %s\n",
           (double) xorriso->file_size_limit, xorriso->list_delimiter);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->disk_excl_mode==1);
 sprintf(line, "-not_mgt %s:%s:%s:%s\n",
         (xorriso->disk_excl_mode&1 ? "on" : "off"),
         (xorriso->disk_excl_mode&2 ? "param_on" : "param_off"),
         (xorriso->disk_excl_mode&4 ? "subtree_on" : "subtree_off"),
         (xorriso->disk_excl_mode&8 ? "ignore_on" : "ignore_off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_iso_rr_pattern==1);
 sprintf(line,"-iso_rr_pattern %s\n",
         (xorriso->do_iso_rr_pattern == 1 ? "on" :
         (xorriso->do_iso_rr_pattern == 2 ? "ls" : "off")));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_disk_pattern==2);
 sprintf(line,"-disk_pattern %s\n",
         (xorriso->do_disk_pattern == 1 ? "on" :
         (xorriso->do_disk_pattern == 2 ? "ls" : "off")));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= xorriso->volid_default;
 sprintf(line,"-volid %s\n",Text_shellsafe(xorriso->volid,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 if(is_default && xorriso->loaded_volid[0] &&
    strcmp(xorriso->loaded_volid, xorriso->volid)!=0 && !no_defaults) {
   sprintf(line,"# loaded image effective -volid %s\n",
           Text_shellsafe(xorriso->loaded_volid,sfe,0));
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 is_default= (xorriso->publisher[0]==0);
 sprintf(line,"-publisher %s\n",Text_shellsafe(xorriso->publisher,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->application_id[0]==0);
 sprintf(line,"-application_id %s\n",
         Text_shellsafe(xorriso->application_id,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->system_id[0]==0);
 sprintf(line,"-system_id %s\n", Text_shellsafe(xorriso->system_id,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->volset_id[0]==0);
 sprintf(line,"-volset_id %s\n", Text_shellsafe(xorriso->volset_id,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_joliet==0);
 sprintf(line,"-joliet %s\n", (xorriso->do_joliet == 1 ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 if(xorriso->do_global_uid) {
   sprintf(line,"-uid %lu\n", (unsigned long) xorriso->global_uid);
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 if(xorriso->do_global_gid) {
   sprintf(line,"-gid %lu\n", (unsigned long) xorriso->global_gid);
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 Xorriso_status_extf(xorriso, filter, fp, flag & 2);
 Xorriso_status_zisofs(xorriso, filter, fp, flag & 3);

 is_default= !xorriso->allow_graft_points;
 sprintf(line,"-pathspecs %s\n", xorriso->allow_graft_points ? "on" : "off");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_follow_pattern && (!xorriso->do_follow_param)
              && xorriso->do_follow_mount && (!xorriso->do_follow_links)
              && xorriso->follow_link_limit==100);
 mode[0]= 0;
 if(xorriso->do_follow_pattern &&
    !(xorriso->do_follow_links && xorriso->do_follow_mount))
   strcat(mode,":pattern");
 if(xorriso->do_follow_param && !(xorriso->do_follow_links))
   strcat(mode,":param");
 if(xorriso->do_follow_links)
   strcat(mode,":link");
 if(xorriso->do_follow_mount)
   strcat(mode,":mount");
 if(mode[0]==0)
   strcpy(mode, ":off");
 sprintf(mode+strlen(mode), ":limit=%d", xorriso->follow_link_limit);
 sprintf(line,"-follow %s\n", mode+1);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_overwrite==2);
 sprintf(line,"-overwrite %s\n",(xorriso->do_overwrite == 1 ? "on" :
                             (xorriso->do_overwrite == 2 ? "nondir" : "off")));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= !xorriso->do_reassure;
 sprintf(line,"-reassure %s\n",(xorriso->do_reassure == 1 ? "on" :
                             (xorriso->do_reassure == 2 ? "tree" : "off")));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= !xorriso->do_close;
 sprintf(line,"-close %s\n",(xorriso->do_close ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= !xorriso->do_dummy;
 sprintf(line,"-dummy %s\n",(xorriso->do_dummy ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->speed==0);
 sprintf(line,"-speed %dkB/s\n", xorriso->speed);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->do_stream_recording==0);
 strcpy(mode, "off");
 if(xorriso->do_stream_recording == 1)
   strcpy(mode, "full");
 if(xorriso->do_stream_recording == 2)
   strcpy(mode, "data");
 else if(xorriso->do_stream_recording == 32)
   strcpy(mode, "on");
 else if(xorriso->do_stream_recording >= 16)
   sprintf(mode, "%ds", xorriso->do_stream_recording);
 sprintf(line,"-stream_recording %s\n", mode);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->dvd_obs == 0);
 strcpy(mode, "default");
 if(xorriso->dvd_obs == 32768 || xorriso->dvd_obs == 65536)
   sprintf(mode, "%dk", xorriso->dvd_obs / 1024);
 sprintf(line,"-dvd_obs %s\n", mode);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->stdio_sync == 0);
 strcpy(line, "-stdio_sync ");
 if(xorriso->stdio_sync == -1)
   strcat(line, "off");
 else if(xorriso->stdio_sync == 0)
   strcat(line, "on");
 else if(xorriso->stdio_sync % 512) {
   Sfile_off_t_text(line+strlen(line), (off_t) (xorriso->stdio_sync * 2048),
                    0);
 } else {
   Sfile_off_t_text(line+strlen(line), (off_t) (xorriso->stdio_sync / 512), 0);
   strcat(line, "m"); 
 }
 strcat(line, "\n"); 
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->fs==4*512);
 if((xorriso->fs/512)*512==xorriso->fs)
   sprintf(line,"-fs %dm\n", xorriso->fs/512);
 else
   sprintf(line,"-fs %dk\n", xorriso->fs*2);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->padding==300*1024);
 sprintf(line,"-padding %dk\n", xorriso->padding/1024);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (strcmp(xorriso->report_about_text,"UPDATE")==0);
 sprintf(line,"-report_about %s\n",xorriso->report_about_text);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->scsi_log == 0);
 sprintf(line,"-scsi_log %s\n", xorriso->scsi_log ? "on" : "off");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->session_logfile[0]==0);
 sprintf(line,"-session_log %s\n",
         Text_shellsafe(xorriso->session_logfile,sfe,0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->pacifier_style==0);
 sprintf(line,"-pacifier '%s'\n",
         xorriso->pacifier_style==1 ? "mkisofs" : 
         xorriso->pacifier_style==2 ? "cdrecord" : "xorriso");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (strcmp(xorriso->return_with_text,"SORRY")==0 &&
              xorriso->return_with_value==32);
 sprintf(line,"-return_with %s %d\n",
         xorriso->return_with_text, xorriso->return_with_value);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 
 is_default= (strcmp(xorriso->abort_on_text,"FATAL")==0);
 sprintf(line,"-abort_on %s\n",xorriso->abort_on_text);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 
 if(xorriso->status_history_max!=Xorriso_status_history_maX || !no_defaults) {
   sprintf(line,"-status_history_max %d\n",xorriso->status_history_max);
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

#ifdef Xorriso_with_readlinE

 if((flag&8) && xorriso->status_history_max>0) {
   HIST_ENTRY **hl;
   int hc,i;

   hl= history_list();
   if(hl!=NULL) {
     for(hc= 0;hl[hc]!=NULL;hc++);
     if(hc>0)
       if(strcmp(hl[hc-1]->line,"-end")==0)
         hc--;
     if(hc>=xorriso->status_history_max)
       i= hc-xorriso->status_history_max;
     else
       i= 0;
     for(;i<hc;i++) {
       sprintf(line,"-history %s\n",Text_shellsafe(hl[i]->line,sfe,0));
       Xorriso_status_result(xorriso,filter,fp,flag&2);
     }   
   }
 }

#endif /* Xorriso_with_readlinE */

 is_default= (xorriso->toc_emulation_flag == 0);
 sprintf(line,"-rom_toc_scan %s%s\n",
         xorriso->toc_emulation_flag & 4 ? "force" :
                                xorriso->toc_emulation_flag & 1 ? "on" : "off",
         xorriso->toc_emulation_flag & 2 ? ":emul_off" : "");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso, filter, fp, flag & 2);

 adr_mode= xorriso->image_start_mode & 0xffff;
 if(adr_mode>=0 && adr_mode<=max_load_mode) {
   is_default= (adr_mode==0);
   sprintf(line,"-load %s ", load_names[adr_mode]);
   if(adr_mode==0)
     sprintf(line+strlen(line),"''\n");
   else if(adr_mode>=1 && adr_mode<=3)
     sprintf(line+strlen(line),"%s\n", xorriso->image_start_value);
   else
     sprintf(line+strlen(line),"%s\n",
              Text_shellsafe(xorriso->image_start_value, sfe, 0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso,filter,fp,flag&2);
 }

 is_default= (xorriso->do_calm_drive & 1);
 sprintf(line,"-calm_drive %s\n", xorriso->do_calm_drive & 1 ? "on" : "off");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->grow_blindly_msc2<0);
 sprintf(sfe, "%d", xorriso->grow_blindly_msc2);
 sprintf(line,"-grow_blindly %s\n",
         xorriso->grow_blindly_msc2 < 0 ? "off" : sfe);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 Xorriso_get_local_charset(xorriso, &local_charset, 0);
 nl_charset= nl_langinfo(CODESET);
 is_default= (strcmp(local_charset, nl_charset) == 0);
 sprintf(line, "-local_charset %s\n", Text_shellsafe(local_charset, sfe, 0));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso, filter, fp, flag & 2);

 is_default= (xorriso->out_charset == NULL && xorriso->in_charset == NULL);
 in_pt= "";
 if(xorriso->in_charset != NULL)
   in_pt= xorriso->in_charset;
 out_pt= "";
 if(xorriso->out_charset != NULL)
   out_pt= xorriso->out_charset;
 do_single= 0;
 ret= Xorriso_status_filter(xorriso, filter, "-in_charset", 0);
 if(ret <= 0)
   ret= Xorriso_status_filter(xorriso, filter, "-out_charset", 0);
 if(ret > 0)
   do_single= 1;
 if(strcmp(in_pt, out_pt) == 0 && !do_single) {
   sprintf(line, "-charset %s\n", Text_shellsafe(in_pt, sfe, 0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso, filter, fp, flag & 2);
 } else {
   sprintf(line, "-in_charset %s\n", Text_shellsafe(in_pt, sfe, 0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso, filter, fp, flag & 2);
   sprintf(line, "-out_charset %s\n", Text_shellsafe(out_pt, sfe, 0));
   if(!(is_default && no_defaults))
     Xorriso_status_result(xorriso, filter, fp, flag & 2);
 }
 is_default= ((xorriso->do_aaip & (256 | 512)) == 0);
 sprintf(line,"-auto_charset %s\n", (xorriso->do_aaip & 256 ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= ((xorriso->ino_behavior & 31) == 7);
 switch (xorriso->ino_behavior & 15) {
 case 0: form= "on";
 break; case 8: form= "without_update";
 break; default: form= "off";
 }
 sprintf(line,"-hardlinks %s:%s\n", form,
         xorriso->ino_behavior & 16 ?
         "cheap_sorted_extract" : "normal_extract"); 
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= ((xorriso->do_aaip & (1 | 4)) == 0);
 sprintf(line,"-acl %s\n", (xorriso->do_aaip & 1 ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 is_default= ((xorriso->do_aaip & (2 | 8)) == 0);
 sprintf(line,"-xattr %s\n", (xorriso->do_aaip & 4 ? "on" : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 is_default= ((xorriso->do_aaip & (16 | 32 | 64)) == 0);
 sprintf(line,"-disk_dev_ino %s\n",
         (xorriso->do_aaip & 16 ? (xorriso->do_aaip & 128 ? "ino_only" : "on" )
                                : "off"));
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= ((xorriso->do_md5 & 31) == 0);
 sprintf(line, "-md5 ");
 if(xorriso->do_md5 & 1) {
   if((xorriso->do_md5 & (8)) == (8)) {
     strcat(line, "all\n");
   } else {
     strcat(line, "on");
     if(xorriso->do_md5 & 8)
       strcat(line, ":stability_check_on");
     strcat(line, "\n");
   }
 } else
   strcat(line, "off\n");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->scdbackup_tag_name[0] == 0 &&
              xorriso->scdbackup_tag_listname[0] == 0);
 sprintf(line, "-scdbackup_tag ");
 Text_shellsafe(xorriso->scdbackup_tag_listname, line, 1);
 strcat(line, " ");
 Text_shellsafe(xorriso->scdbackup_tag_name, line, 1);
 strcat(line, "\n");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (Xorriso_get_relax_text(xorriso, sfe, 0) == 2);
 sprintf(line,"-compliance %s\n", sfe);
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);

 is_default= (xorriso->assert_volid[0] == 0);
 sprintf(line, "-assert_volid ");
 Text_shellsafe(xorriso->assert_volid, line, 1);
 strcat(line, " ");
 Text_shellsafe(xorriso->assert_volid_sev, line, 1);
 strcat(line, "\n");
 if(!(is_default && no_defaults))
   Xorriso_status_result(xorriso,filter,fp,flag&2);
 
 is_default= 1;
 if(xorriso->drive_blacklist != NULL || xorriso->drive_whitelist != NULL ||
    xorriso->drive_greylist == NULL)
   is_default= 0;
 if(xorriso->drive_greylist != NULL) {
   if(strcmp(Xorriso_get_pattern(xorriso, xorriso->drive_greylist, 0, 0),
              "/dev") != 0)
     is_default= 0;
   if(Xorriso_get_pattern(xorriso, xorriso->drive_greylist, 1, 0) != NULL)
     is_default= 0;
 }
 if(!(is_default && no_defaults)) {
   for(s= xorriso->drive_blacklist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
     sprintf(line, "-drive_class 'banned'   %s\n",
             Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0));
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   }
   for(s= xorriso->drive_greylist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
     sprintf(line, "-drive_class 'caution'  %s\n",
             Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0));
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   }
   for(s= xorriso->drive_whitelist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
     sprintf(line, "-drive_class 'harmless' %s\n",
             Text_shellsafe(Xorriso_lst_get_text(s, 0), sfe, 0));
     Xorriso_status_result(xorriso,filter,fp,flag&2);
   }
 }

 do_single= 0;
 dev_filter= filter;
 if(dev_filter != NULL) {
   show_dev= Xorriso_status_filter(xorriso, filter, "-dev", 0);
   if(show_dev > 0)
     dev_filter= NULL; 
 }
 if(dev_filter != NULL) {
   show_indev= Xorriso_status_filter(xorriso, filter, "-indev", 0);
   show_outdev= Xorriso_status_filter(xorriso, filter, "-outdev", 0);
   if(show_outdev > 0 || show_indev > 0)
     do_single= 1;
 }
 if(xorriso->drives_exclusive != xorriso->indev_is_exclusive &&
    xorriso->indev[0]) 
   do_single= 1;
 else if(xorriso->drives_exclusive != xorriso->outdev_is_exclusive &&
         xorriso->outdev[0]) 
   do_single= 1;
 if(strcmp(xorriso->indev, xorriso->outdev) == 0 && !do_single) {
   sprintf(line,"-dev %s\n", Text_shellsafe(xorriso->indev,sfe,0));
   Xorriso_status_result(xorriso, dev_filter, fp, flag & 2);
 } else {
   if(xorriso->drives_exclusive != xorriso->indev_is_exclusive &&
      xorriso->indev[0] && show_indev) {
     sprintf(line,"-osirrox o_excl_%s\n",
             xorriso->indev_is_exclusive ? "on" : "off");
     Xorriso_status_result(xorriso, NULL, fp, flag & 2);
   }
   sprintf(line,"-indev %s\n", Text_shellsafe(xorriso->indev,sfe,0));
   Xorriso_status_result(xorriso, dev_filter, fp, flag & 2);
   if(xorriso->drives_exclusive != xorriso->indev_is_exclusive &&
      xorriso->indev[0] && show_indev) {
     sprintf(line,"-osirrox o_excl_%s\n",
             xorriso->drives_exclusive ? "on" : "off");
     Xorriso_status_result(xorriso, NULL, fp, flag & 2);
   }

   if(xorriso->drives_exclusive != xorriso->outdev_is_exclusive &&
      xorriso->outdev[0] && show_outdev) {
     sprintf(line,"-osirrox o_excl_%s\n",
             xorriso->outdev_is_exclusive ? "on" : "off");
     Xorriso_status_result(xorriso, NULL, fp, flag & 2);
   }
   sprintf(line,"-outdev %s\n", Text_shellsafe(xorriso->outdev,sfe,0));
   Xorriso_status_result(xorriso, dev_filter, fp, flag & 2);
   if(xorriso->drives_exclusive != xorriso->outdev_is_exclusive &&
      xorriso->outdev[0] && show_outdev) {
     sprintf(line,"-osirrox o_excl_%s\n",
             xorriso->drives_exclusive ? "on" : "off");
     Xorriso_status_result(xorriso, NULL, fp, flag & 2);
   }
 }

 return(1);
}


/* @param flag bit2= this is a disk_pattern
   @return <=0 failure , 1 pattern ok , 2 pattern needed prepended wd */
int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern,
                                      int flag)
{
 int ret, prepwd= 0;

 ret= Xorriso_prepare_regex(xorriso, pattern, 1|2|(flag&4));
 if(ret==2) {
   ret= Xorriso_prepare_regex(xorriso, pattern, flag&4);
   prepwd= 1;
 }
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "Cannot compile pattern to regular expression:  %s", pattern);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1+prepwd);
}


/* @param flag bit0= count results rather than storing them
               bit1= unexpected change of number is a FATAL event
   @return <=0 error , 1 is root (end processing) ,
                       2 is not root (go on processing)
*/
int Xorriso_check_for_root_pattern(struct XorrisO *xorriso, 
               int *filec, char **filev, int count_limit, off_t *mem, int flag)
{
 if(xorriso->re_fill!=0)
   return(2);
 /* This is the empty pattern representing root */
 if(flag&1) {
   (*filec)++;
   (*mem)+= 8;
 } else {
   if(*filec >= count_limit) {
     sprintf(xorriso->info_text,
            "Number of matching files changed unexpectedly (> %d)",
             count_limit);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
                         (flag&2 ? "FATAL" : "WARNING"), 0);
     return(flag&2 ? -1 : 0);
   }
   filev[*filec]= strdup("/");
   if(filev[*filec]==NULL) {
     Xorriso_no_pattern_memory(xorriso, (off_t) 2, 0);
     return(-1);
   }
   (*filec)++;
 }
 return(1);
}


/* @param flag bit0= prepend wd only if name does not begin by '/'
               bit1= normalize image path
               bit2= prepend wd (automatically done if wd[0]!=0)
               bit3= (with bit1) this is an address in the disk world
*/
int Xorriso_make_abs_adr(struct XorrisO *xorriso, char *wd, char *name,
                             char adr[], int flag)
{
 char norm_adr[SfileadrL];
 int ret;

 if((wd[0]!=0 || (flag&4)) && !((flag&1) && name[0]=='/')) {
   if(strlen(wd)+1>=SfileadrL)
     goto much_too_long;
   strcpy(adr, wd);
   if(name[0])
     if(Sfile_add_to_path(adr, name, 0)<=0) {
much_too_long:;
       Xorriso_much_too_long(xorriso, (int) (strlen(adr)+strlen(name)+1), 2);
       return(0);
     }
 } else {
   if(strlen(name)+1>=SfileadrL)
     goto much_too_long;
   strcpy(adr, name);
 }
 if(flag&2) {
   ret= Xorriso_normalize_img_path(xorriso, "", adr, norm_adr,
                                   1|2|((flag&8)>>1));
   if(ret<=0)
     return(ret);
   if(norm_adr[0]==0)
     strcpy(norm_adr, "/");
   strcpy(adr, norm_adr);
 }
 return(1);
}


/*
   @param result  Bitfield indicationg type of mismatch
              bit11= cannot open regular disk file
              bit12= cannot open iso file
              bit13= early eof of disk file
              bit14= early eof of iso file
              bit15= content bytes differ
   @param flag bit0= mtimes of both file objects are equal
              bit29= do not issue pacifier messages
              bit31= do not issue result messages
   @return    >0 ok , <=0 error
*/
int Xorriso_compare_2_contents(struct XorrisO *xorriso, char *common_adr,
                               char *disk_adr, off_t disk_size,
                               off_t offset, off_t bytes,
                               char *iso_adr, off_t iso_size,
                               int *result, int flag)
{
 int fd1= -1, ret, r1, r2, done, wanted, i, was_error= 0, use_md5= 0;
 void *stream2= NULL;
 off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1;
 char *respt, buf1[32*1024], buf2[32*1024], offset_text[80];
 char disk_md5[16], iso_md5[16];
 void *ctx= NULL;

 respt= xorriso->result_line;

 fd1= open(disk_adr, O_RDONLY);
 if(fd1==-1) {
   sprintf(respt, "- %s (DISK) : cannot open() : %s\n",
           disk_adr, strerror(errno));
cannot_address:;
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= 2048;
   {ret= 0; goto ex;}
 }
 if(offset>0)
   if(lseek(fd1, offset, SEEK_SET)==-1) {
     sprintf(respt, "- %s (DISK) : cannot lseek(%.f) : %s\n",
             disk_adr, (double) offset, strerror(errno));
     close(fd1);
     goto cannot_address;
   }

 if(xorriso->do_md5 & 16) {
   use_md5= 1;
   ret= Xorriso_is_plain_image_file(xorriso, NULL, iso_adr, 0);
   if(ret <= 0) 
     ret= 0; /* (reverse) filtered files are likely not to match their MD5 */
   else
     ret= Xorriso_get_md5(xorriso, NULL, iso_adr, iso_md5, 1);
   if(ret <= 0)
     use_md5= 0;
   else {
     ret= Xorriso_md5_start(xorriso, &ctx, 0);
     if(ret <= 0)
       use_md5= 0;
   }
 }
 if (! use_md5) {
   ret= Xorriso_iso_file_open(xorriso, iso_adr, NULL, &stream2, 0);
   if(ret<=0) {
     sprintf(respt, "- %s  (ISO) : cannot open() file in ISO image\n",iso_adr);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     close(fd1);
     (*result)|= 4096;
     {ret= 0; goto ex;}
   }
 }

 done= 0;
 while(!done) {

   wanted= sizeof(buf1);
   if(r1count+offset+wanted>disk_size)
     wanted= disk_size-r1count-offset;
   if(r1count+wanted>bytes)
     wanted= bytes-r1count;
   r1= 0;
   while(wanted>0) {
     ret= read(fd1, buf1, wanted);
     if(ret<=0)
   break;
     wanted-= ret;
     r1+= ret;
   }

   wanted= sizeof(buf2);
   if(r2count+wanted>iso_size)
     wanted= iso_size-r2count;
/*
   if(r2count+wanted>bytes)
     wanted= bytes-r2count;
*/
   if(use_md5)
     r2= r1;
   else if(wanted>0)
     r2= Xorriso_iso_file_read(xorriso, stream2, buf2, wanted, 0);
   else
     r2= 0;

   if(r1<0 || r2<0)
     was_error= 1;

   if(r1<=0 && r2<=0)
 break;
   if(r1<=0) {
     if(r1<0)
       r1= 0;
     if(disk_size > r1count + r1 + offset) {
       sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n",
               disk_adr, (double) r1count);
       if(!(flag&(1<<31)))
         Xorriso_result(xorriso,0);
       (*result)|= 8196;
     }
     (*result)|= (1<<15);
   }
   r1count+= r1;
   if(r2<=0 || r2<r1) {
     if(r2<0)
       r2= 0;
     if(iso_size > r2count + r2) {
       sprintf(respt, "- %s  (ISO) : early EOF after %.f bytes\n",
               iso_adr, (double) r2count);
       if(!(flag&(1<<31)))
         Xorriso_result(xorriso,0);
       (*result)|= (1<<14);
     }
     (*result)|= (1<<15);
     done= 1;
   }
   if(r2>r1) {
     if(disk_size > r1count + r1 + offset) {
       sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n",
               disk_adr, (double) r1count);
       if(!(flag&(1<<31)))
         Xorriso_result(xorriso,0);
       (*result)|= 8196;
     }
     (*result)|= (1<<15);
     done= 1;
   }
   r2count+= r2;
   if(r1>r2)
     r1= r2;

   if(use_md5) {
     Xorriso_md5_compute(xorriso, ctx, buf1, r1, 0);
   } else {
     for(i= 0; i<r1; i++) {
       if(buf1[i]!=buf2[i]) {
         if(first_diff<0)
           first_diff= r1count - r1 + i;
         diffcount++;
       }
     }
   }
   if(!(flag&(1<<29))) {
     xorriso->pacifier_count+= r1;
     xorriso->pacifier_byte_count+= r1;
     if(flag&(1<<31))
       Xorriso_pacifier_callback(xorriso, "content bytes read",
                                 xorriso->pacifier_count, 0, "", 0);
     else
       Xorriso_pacifier_callback(xorriso, "bytes", xorriso->pacifier_count, 0,
                                 "", 1<<6);
   }
 }

 if(use_md5) {
   ret= Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
   if(ret <= 0) {
     *result |= (1 << 15);
     ret= -1; goto ex;
   }
   for(i= 0; i < 16; i++)
     if(iso_md5[i] != disk_md5[i])
   break;
   if(i < 16 ) {
     offset_text[0]= 0;
     if(offset>0)
       sprintf(offset_text, "%.f+", (double) offset);
     sprintf(respt, "%s %s  :  differs by MD5 sums.\n",
             common_adr, (flag&1 ?  "CONTENT": "content"));
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= (1<<15);
   }
 } else if(diffcount>0 || r1count!=r2count) {
   if(first_diff<0)
     first_diff= (r1count>r2count ? r2count : r1count);
   offset_text[0]= 0;
   if(offset>0)
     sprintf(offset_text, "%.f+", (double) offset);
   sprintf(respt, "%s %s  :  differs by at least %.f bytes. First at %s%.f\n",
           common_adr, (flag&1 ?  "CONTENT": "content"),
           (double) (diffcount + abs(r1count-r2count)),
           offset_text, (double) first_diff);
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= (1<<15);
 }
 if(fd1!=-1)
   close(fd1);
 if(! use_md5)
   Xorriso_iso_file_close(xorriso, &stream2, 0);
 if(was_error)
   {ret= -1; goto ex;}
 ret= 1;
ex:;
 if(ctx != NULL)
   Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
 return(ret);
}


/*
   @param result  Bitfield indicationg type of mismatch
               bit0= disk_adr not existing
               bit1= iso_adr not existing
               bit2= access permissions
               bit3= file type 
               bit4= user id
               bit5= group id
               bit6= minor, major with device file
               bit7= size
               bit8= mtime
               bit9= atime
              bit10= ctime
              bit11= cannot open regular disk file
              bit12= cannot open iso file
              bit13= early eof of disk file
              bit14= early eof of iso file
              bit15= content bytes differ
              bit16= symbolic link on disk pointing to dir, dir in iso
              bit17= file chunks detected and compared
              bit18= incomplete chunk collection encountered
              bit19= ACL differs (this condition sets also bit2)
              bit20= xattr differ
              bit21= mismatch of recorded dev,inode
              bit22= no recorded dev,inode found in node
              bit23= timestamps younger than xorriso->isofs_st_in
              bit24= hardlink split
              bit25= hardlink fusion
   @param flag bit0= compare atime
               bit1= compare ctime
               bit2= check only existence of both file objects
                     count one or both missing as "difference"
              bit27= for Xorriso_path_is_excluded(): bit0
              bit28= examine eventual disk_path link target rather than link
              bit29= do not issue pacifier messages
              bit30= omit adr_common_tail in report messages
              bit31= do not issue result messages
   @return     1=files match properly , 0=difference detected , -1=error
*/
int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
                            char *iso_adr, char *adr_common_tail,
                            int *result, int flag)
{
 struct stat s1, s2, stbuf;
 int ret, missing= 0, is_split= 0, i, was_error= 0, diff_count= 0;
 int content_shortcut= 0;
 char *respt;
 char a[5*SfileadrL], sfe[5*SfileadrL];
 char ttx1[40], ttx2[40];
 char *a1_acl= NULL, *a2_acl= NULL, *d1_acl= NULL, *d2_acl= NULL;
 char *attrlist1= NULL, *attrlist2= NULL;
 struct SplitparT *split_parts= NULL;
 int split_count= 0;
 time_t stamp;

 char part_path[SfileadrL], *part_name;
 int partno, total_parts= 0;
 off_t offset, bytes, total_bytes;

 *result= 0;
 respt= xorriso->result_line;

 if(!(xorriso->disk_excl_mode&8)) {
   ret= Xorriso_path_is_excluded(xorriso, disk_adr, 2 | !!(flag&(1<<27)));
   if(ret>0) {
     sprintf(respt , "? %s (DISK) : exluded by %s\n",
             Text_shellsafe(disk_adr, sfe, 0),
             (ret==1 ? "-not_paths" : "-not_leaf"));
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     missing= 1;
     (*result)|= 1;
   }
 }
 if(!missing) {
   if(flag&(1<<28))
     ret= stat(disk_adr, &s1);
   else
     ret= lstat(disk_adr, &s1);
   if(ret==-1) {
     sprintf(respt , "? %s (DISK) : cannot lstat() : %s\n",
             Text_shellsafe(disk_adr, sfe, 0), strerror(errno));
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     missing= 1;
     (*result)|= 1;
   }
 }
 if(missing)
   strcpy(a, "?");
 else
   strcpy(a, Ftypetxt(s1.st_mode, 1));  
 strcat(a, " ");
 if(adr_common_tail[0])
   strcat(a, Text_shellsafe(adr_common_tail, sfe, 0));
 else {
   Text_shellsafe(disk_adr, a+strlen(a), 0);
   strcat(a, " (DISK)");
/*
   strcat(a, "'.'");
*/
 }
 strcat(a, " :");
 if(flag&(1<<30))
   a[0]= 0;

 ret= Xorriso_iso_lstat(xorriso, iso_adr, &s2, 0);
 if(ret<0) {
   sprintf(respt, "? %s  (ISO) : cannot find this file in ISO image\n",
           Text_shellsafe(iso_adr, sfe, 0));
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   missing= 1;
   (*result)|= 2;
 }

 if((flag&4)||missing)
   {ret= !missing; goto ex;}


 /* Splitfile parts */
 if((S_ISREG(s1.st_mode) || S_ISBLK(s1.st_mode)) && S_ISDIR(s2.st_mode)) {
   is_split= Xorriso_identify_split(xorriso, iso_adr, NULL, &split_parts,
                                    &split_count, &s2, 0);
   if(is_split>0)
     (*result)|= (1<<17);
   else
     is_split= 0;
 }

 /* Attributes */
 if(s1.st_mode != s2.st_mode) {
   if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) {
     sprintf(respt, "%s st_mode  :  %7.7o  <>  %7.7o\n",
             a, (unsigned int) (s1.st_mode & ~S_IFMT),
                (unsigned int) (s2.st_mode & ~S_IFMT));
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= 4;
   }

   if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) {
     sprintf(respt, "%s type     :  %s  <>  %s\n",
             a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0));
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= 8;
     if((s1.st_mode&S_IFMT) == S_IFLNK) {
       /* check whether link target type matches */
       ret= stat(disk_adr, &stbuf);
       if(ret!=-1)
         if(S_ISDIR(stbuf.st_mode) && S_ISDIR(s2.st_mode))
           (*result)|= (1<<16);
     }
   }
 }

 /* ACL */
 if(xorriso->do_aaip & 3) {
   Xorriso_local_getfacl(xorriso, disk_adr, &a1_acl,
                         16 | ((flag & (1 << 28)) >> 23));
   if(S_ISDIR(s1.st_mode))
     Xorriso_local_getfacl(xorriso, disk_adr, &d1_acl, 1);
   ret= Xorriso_getfacl(xorriso, NULL, iso_adr, &a2_acl, 1 | 4 | 16);
   if(ret < 0)
     goto ex;
   if(S_ISDIR(s1.st_mode)) {
     ret= Xorriso_getfacl(xorriso, NULL, iso_adr, &d2_acl, 1 | 8);
     if(ret < 0)
       goto ex;
   }
   ret= Compare_text_lines(a1_acl, a2_acl, &diff_count, 0);
   if(ret < 0)
     goto ex;
   if(ret == 0)
     (*result)|= 4 | (1 << 19);
   ret= Compare_text_lines(d1_acl, d2_acl, &diff_count, 1);
   if(ret < 0)
     goto ex;
   if(ret == 0)
     (*result)|= 4 | (1 << 19);
   if((*result) & (1 << 19)) {
     sprintf(respt, "%s ACL      :  %d difference%s\n",
             a, diff_count, diff_count == 1 ? "" : "s");
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
   }
 }

 /* xattr */
 if(xorriso->do_aaip & 12) {
   ret= Xorriso_getfattr(xorriso, NULL, disk_adr, &attrlist1,
                         1 | 2 | ((flag & (1 << 28)) >> 23));
   if(ret < 0)
     goto ex;
   ret= Xorriso_getfattr(xorriso, NULL, iso_adr, &attrlist2, 1);
   if(ret < 0)
     goto ex;
   ret= Compare_text_lines(attrlist1, attrlist2, &diff_count, 0);
   if(ret < 0)
     goto ex;
   if(ret == 0) {
     (*result)|= (1 << 20);
     sprintf(respt, "%s xattr    :  %d difference%s\n",
             a, diff_count, diff_count == 1 ? "" : "s");
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
   }
 }

 if(s1.st_uid != s2.st_uid) {
   sprintf(respt, "%s st_uid   :   %d  <>  %d\n", a, s1.st_uid, s2.st_uid);
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= 16;
 }
 if(s1.st_gid != s2.st_gid) {
   sprintf(respt, "%s st_gid   :   %d  <>  %d\n", a, s1.st_gid, s2.st_gid);
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= 32;
 }
 if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) ||
    (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) {
   if(s1.st_rdev != s2.st_rdev) {
     sprintf(respt, "%s %s st_rdev  :  %lu  <>  %lu\n", a,
            (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"),
            (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= 64;
   }
 }
 if((!(xorriso->do_aaip & 32)) &&
    S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) {
   sprintf(respt, "%s st_size  :  %.f  <>  %.f      diff= %.f\n",
          a, (double) s1.st_size, (double) s2.st_size,
          ((double) s1.st_size) - (double) s2.st_size);
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= 128;
 }
 if(s1.st_mtime != s2.st_mtime) {
   sprintf(respt, "%s st_mtime :  %s  <>  %s      diff= %.f s\n",
           a, Ftimetxt(s1.st_mtime, ttx1, 0),
              Ftimetxt(s2.st_mtime, ttx2, 0),
              ((double) s1.st_mtime) - (double) s2.st_mtime);
   if(!(flag&(1<<31)))
     Xorriso_result(xorriso,0);
   (*result)|= 256;
 }
 if(flag&1) {
   if(s1.st_atime != s2.st_atime) {
     sprintf(respt, "%s st_atime :  %s  <>  %s      diff= %.f s\n",
             a, Ftimetxt(s1.st_atime, ttx1, 0), 
                Ftimetxt(s2.st_atime, ttx2, 0),
                ((double) s1.st_atime) - (double) s2.st_atime);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= 512;
   }
 }
 if(flag&2) {
   if(s1.st_ctime != s2.st_ctime) {
     sprintf(respt, "%s st_ctime :  %s  <>  %s      diff= %.f s\n",
             a, Ftimetxt(s1.st_ctime, ttx1, 0),
                Ftimetxt(s2.st_ctime, ttx2, 0),
                ((double) s1.st_ctime) - (double) s2.st_ctime);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= 1024;
   }
 }
 if(xorriso->isofs_st_in > 0 &&
    (xorriso->isofs_st_in <= s2.st_mtime ||
     ((flag & 1) && xorriso->isofs_st_in <= s2.st_atime) ||
     ((flag & 2) && xorriso->isofs_st_in <= s2.st_ctime)))
   (*result)|= 1 << 23;

 if((xorriso->do_aaip & 32) || !(xorriso->ino_behavior & 2)) {
   /* dev,inode comparison.
      For skipping content comparison or for hardlink detection.
   */
   ret= Xorriso_record_dev_inode(xorriso, "", s1.st_dev, s1.st_ino, NULL,
       iso_adr, 1 | 2 | ((flag & (1 << 28)) >> 23) | (xorriso->do_aaip & 128));
   if(ret < 0) {
     ret= -1; goto ex;
   } else if(ret == 0) { /* match */
     if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
       if(xorriso->do_aaip & 32)
         content_shortcut= 1;
       if((*result) & (8 | 128 | 256 | 512 | 1024 | (1 << 23))) {
         (*result)|= (1 << 15); /* content bytes differ */
         if(((*result) & (1 << 23)) &&
            !((*result) & (8 | 128 | 256 | 512 | 1024))) {
           sprintf(respt,
            "%s content  :  node timestamp younger than image timestamp\n", a);
           if(!(flag&(1<<31)))
             Xorriso_result(xorriso,0);
           stamp= s2.st_mtime;
           if((flag & 1) && s2.st_atime >= stamp)
             stamp= s2.st_atime;
           if((flag & 2) && s2.st_ctime >= stamp)
             stamp= s2.st_ctime;
           sprintf(respt, "%s content  :  %s  >  %s    diff= %.f s\n",
                   a, Ftimetxt(stamp, ttx1, 3 << 1),
                   Ftimetxt(xorriso->isofs_st_in, ttx2, 3 << 1),
                   ((double) stamp) - (double) xorriso->isofs_st_in);
           if(!(flag&(1<<31)))
             Xorriso_result(xorriso,0);
         }
         sprintf(respt,
          "%s content  :  assuming inequality due to size or timestamps\n", a);
         if(!(flag&(1<<31)))
           Xorriso_result(xorriso,0);
       }
     }
   } else if(ret == 1) { /* mismatch */
     (*result)|= (1 << 21);
     sprintf(respt, "%s dev_ino  :  differing\n", a);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);

     if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
       if(xorriso->do_aaip & 32)
         content_shortcut= 1;
       (*result)|= (1 << 15); /* content bytes differ */
       sprintf(respt,
             "%s content  :  assuming inequality after dev_ino mismatch\n", a);
       if(!(flag&(1<<31)))
         Xorriso_result(xorriso,0);
     }
   } else {
     sprintf(respt, "%s dev_ino  :  no dev_ino stored with image node\n", a);
     if(!(flag&(1<<31)))
       Xorriso_result(xorriso,0);
     (*result)|= (1 << 22);
   }
 }

 if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode) && !content_shortcut) {
   /* Content */
   if(is_split) { 
     for(i= 0; i<split_count; i++) {
       Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
                      &offset, &bytes, &total_bytes, 0);
       strcpy(part_path, iso_adr);
       if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
         Xorriso_much_too_long(xorriso, strlen(iso_adr)+strlen(part_name)+1,
                               2);
         {ret= -1; goto ex;}
       }
       ret= Xorriso_iso_lstat(xorriso, part_path, &stbuf, 0);
       if(ret<0)
     continue;
       ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size,
                                       offset, bytes,
                                       part_path, stbuf.st_size, result,
                        (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1<<31))));
       if(ret<0)
         was_error= 1;
     }
     if(total_parts>0 && split_count!=total_parts) {
       sprintf(xorriso->info_text,
               "- %s/* (ISO) : Not all split parts present (%d of %d)\n",
               iso_adr, split_count, total_parts);
       if(!(flag&(1<<31)))
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 1);
       (*result)|= 1<<18;
     }
   } else {
     ret= Xorriso_compare_2_contents(xorriso, a, disk_adr, s1.st_size,
                                     (off_t) 0, s1.st_size,
                                     iso_adr, s2.st_size, result,
                        (s1.st_mtime==s2.st_mtime) | (flag&((1<<29)|(1<<31))));
     if(ret<0)
       was_error= 1;
   }

 }
 if(was_error)
   ret= -1;
 else
   ret= (((*result) & ~((1 << 17) | (1 << 18) | (1 << 23)))==0);
ex:;
 if(split_parts!=NULL)
   Splitparts_destroy(&split_parts, split_count, 0);
 Xorriso_local_getfacl(xorriso, disk_adr, &a1_acl, 1 << 15);
 Xorriso_local_getfacl(xorriso, disk_adr, &d1_acl, 1 << 15);
 if(a2_acl != NULL)
   free(a2_acl);
 if(d2_acl != NULL)
   free(d2_acl);
 return(ret);
}


int Xorriso_pfx_disk_path(struct XorrisO *xorriso, char *iso_path,
                          char *iso_prefix, char *disk_prefix,
                          char disk_path[SfileadrL], int flag)
{
 int ret;
 char adrc[SfileadrL];

 if(strncmp(iso_path, iso_prefix, strlen(iso_prefix))!=0)
   return(-1);
 if(strlen(disk_prefix) + strlen(iso_path) - strlen(iso_prefix)+1 >= SfileadrL)
   return(-1);
 if(iso_path[strlen(iso_prefix)] == '/')
   strcpy(adrc, iso_path + strlen(iso_prefix) + 1);
 else
   strcpy(adrc, iso_path + strlen(iso_prefix));
 ret= Xorriso_make_abs_adr(xorriso, disk_prefix, adrc, disk_path, 4 | 8);
 if(ret <= 0)
   return(ret);
 return(1);
}


/* @param boss_iter Opaque handle to be forwarded to actions in ISO image
                    Set to NULL if calling this function from outside ISO world
   @param flag bit0= update rather than compare
               bit1= find[ix] is in recursion
   @return <=0 error, 1= ok , 2= iso_path was deleted
             3=ok, do not dive into directory (e.g. because it is a split file)
*/
int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter,
                         char *iso_path, char *iso_prefix, char *disk_prefix,
                         int flag)
{
 int ret, result, uret, follow_links, deleted= 0;
 char disk_path[SfileadrL];

 ret= Xorriso_pfx_disk_path(xorriso, iso_path, iso_prefix, disk_prefix,
                            disk_path, 0);
 if(ret <= 0)
   return(ret);

 /* compare exclusions against disk_path resp. leaf name */
 if(xorriso->disk_excl_mode&8)
   ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&2));
 else
   ret= 0;
 if(ret<0)
   return(ret);
 if(ret>0)
   return(3);

 follow_links= (xorriso->do_follow_links ||
               (xorriso->do_follow_param && !(flag&2))) <<28;
 ret= Xorriso_compare_2_files(xorriso, disk_path, iso_path, "", &result,
                        2 | follow_links | ((!(flag&2))<<27) | ((flag&1)<<31));
                                            /* was once: | ((!(flag&1))<<29) */
 if(ret<xorriso->find_compare_result)
   xorriso->find_compare_result= ret;
 if(flag&1) {
   if(ret<=0) {
     if(ret<0)
       if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
         return(ret);
     uret= Xorriso_update_interpreter(xorriso, boss_iter, result,
                                      disk_path, iso_path, (flag&2)<<1);
     if(uret<=0)
       ret= 0;
     if(uret==2)
       deleted= 1;
   }
 }
 if(ret<0)
   return(ret);
 if(deleted)
   return(2);
 if(result&(1<<17))
   return(3);
 return(ret);
}


/* @param flag bit0= count result rather than storing it
               bit1= unexpected change of number is a FATAL event
*/
int Xorriso_register_matched_adr(struct XorrisO *xorriso,
                                char *adr, int count_limit,
                                int *filec, char **filev, off_t *mem, int flag)
{
 int l;

 if(flag&1) {
   (*filec)++;
   l= strlen(adr)+1;
   (*mem)+= sizeof(char *)+l;
   if(l % sizeof(char *))
     (*mem)+= sizeof(char *)-(l % sizeof(char *));
 } else {
   if(*filec >= count_limit) {
     sprintf(xorriso->info_text,
         "Number of matching files changed unexpectedly (> %d)",
         count_limit);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
                         (flag&2 ? "FATAL" : "WARNING"), 0);
     return(flag&2 ? -1 : 0);
   }
   filev[*filec]= strdup(adr);
   if(filev[*filec]==NULL) {
     Xorriso_no_pattern_memory(xorriso, (off_t) (strlen(adr)+1), 0);
     return(-1);
   }
   (*filec)++;
 }
 return(1);
}


/* @param flag bit0= count results rather than storing them
               bit1= this is a recursion
               bit2= prepend wd (automatically done if wd[0]!=0)
   @return <=0 error , 1 ok , 2 could not open directory
*/
int Xorriso_obtain_pattern_files_x(
       struct XorrisO *xorriso, char *wd, char *dir_adr,
       int *filec, char **filev, int count_limit, off_t *mem,
       int *dive_count, int flag)
{
 int ret, failed_at, follow_mount, follow_links;
 struct DirseQ *dirseq= NULL;
 struct stat stbuf;
 dev_t dir_dev;
 char *path;
 char *adr= NULL, *name= NULL, *path_data= NULL;

 adr= malloc(SfileadrL);
 name= malloc(SfileadrL);
 path_data= malloc(SfileadrL);
 if(adr==NULL || name==NULL || path_data==NULL) {
   Xorriso_no_malloc_memory(xorriso, &adr, 0);
   {ret= -1; goto ex;}
 }
 follow_mount= (xorriso->do_follow_mount || xorriso->do_follow_pattern);
 follow_links= (xorriso->do_follow_links || xorriso->do_follow_pattern);
 if(!(flag&2))
   *dive_count= 0;
 else
   (*dive_count)++;

 ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit,
                                     mem, flag&1);
 if(ret!=2)
   goto ex;

 if(lstat(dir_adr, &stbuf)==-1)
   {ret= 2; goto ex;}
 dir_dev= stbuf.st_dev;
 if(S_ISLNK(stbuf.st_mode)) {
   if(stat(dir_adr, &stbuf)==-1)
     {ret= 2; goto ex;}
   if(dir_dev != stbuf.st_dev && !follow_mount)
     {ret= 2; goto ex;}
 }
 ret= Dirseq_new(&dirseq, dir_adr, 1);
 if(ret<0) {
   sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
   {ret= -1; goto ex;}
 }
 if(ret==0)
   {ret= 2; goto ex;}

 while(1) {
   ret= Dirseq_next_adr(dirseq,name,0);
   if(ret==0)
 break;
   if(ret<0) {
     sprintf(xorriso->info_text,"Failed to obtain next directory entry");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
     {ret= -1; goto ex;}
   }

   ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4);
   if(ret<=0)
     goto ex;

   ret= Xorriso_regexec(xorriso, adr, &failed_at, 1);
   if(ret>0) { /* no match */
     if(failed_at <= *dive_count) /* no hope for a match */
 continue;
     path= adr;
     if(adr[0]!='/') {
       path= path_data;
       ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, adr, path, 1|4);
       if(ret<=0)
         goto ex;
     }

     if(follow_links)
       ret= stat(path,&stbuf);
     else
       ret= lstat(path,&stbuf);
     if(ret==-1)
 continue;
     if(!S_ISDIR(stbuf.st_mode))
 continue;
     if(dir_dev != stbuf.st_dev && !follow_mount)
 continue;

     /* dive deeper */
     ret= Xorriso_obtain_pattern_files_x(xorriso, adr, path,
                           filec, filev, count_limit, mem, dive_count, flag|2);
     if(ret<=0)
       goto ex;
   } else {
     ret= Xorriso_register_matched_adr(xorriso, adr, count_limit,
                                       filec, filev, mem, flag&1);
     if(ret<0)
       goto ex;
     if(ret==0)
 break;
   }
 } 
 ret= 1;
ex:;
 if(adr!=NULL)
   free(adr);
 if(name!=NULL)
   free(name);
 if(path_data!=NULL)
   free(path_data);
 Dirseq_destroy(&dirseq,0);
 if(flag&2)
   (*dive_count)--;
 return(ret);
}


int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern,
                          int *nonconst_mismatches, off_t *mem, int flag)
{
 int k,l;

 /* Is this a constant pattern ? */
 for(k= 0; k<xorriso->re_fill; k++) {
   if(xorriso->re_constants[k]==NULL)
 break;
   if(xorriso->re_constants[k][0]==0)
 break;
 }
 if(k<xorriso->re_fill)
   (*nonconst_mismatches)++; /* it is not */

 l= strlen(pattern)+1;
 (*mem)+= sizeof(char *)+l;
 if(l % sizeof(char *))
   (*mem)+= sizeof(char *)-(l % sizeof(char *));
 return(1);
}


/* @param flag bit0= a match count !=1 is a SORRY event
               bit1= a match count !=1 is a FAILURE event
*/
int Xorriso_check_matchcount(struct XorrisO *xorriso,
                int count, int nonconst_mismatches, int num_patterns,
                char **patterns, int flag)
{
 char sfe[5*SfileadrL];

 if((flag&1) && (count!=1 || nonconst_mismatches)){
   if(count-nonconst_mismatches>0)
     sprintf(xorriso->info_text,
             "Pattern match with more than one file object");
   else
     sprintf(xorriso->info_text, "No pattern match with any file object");
   if(num_patterns==1)
     sprintf(xorriso->info_text+strlen(xorriso->info_text), ": %s",
             Text_shellsafe(patterns[0], sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, 
                       (flag&2 ? "FAILURE" : "SORRY"), 0);
   return(0);
 }
 return(1);
}


int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag)
{
 char mem_text[80];

 Sfile_scale((double) mem, mem_text,5,1e4,1);
 sprintf(xorriso->info_text,
         "Cannot allocate enough memory (%s) for pattern expansion",
         mem_text);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 return(1);
}


int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free, int flag)
{
 if(to_free!=NULL)
   if(*to_free!=NULL) {
     /* Eventual memory sacrifice to get on going */
     free(*to_free);
     *to_free= NULL;
   }
 sprintf(xorriso->info_text, "Out of virtual memory");
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "ABORT", 0);
 return(1);
}


int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem, 
                              int count, char ***filev, int flag)
{
 char mem_text[80], limit_text[80];

 Sfile_scale((double) mem, mem_text,5,1e4,0);
 sprintf(xorriso->info_text,
         "Temporary memory needed for pattern expansion : %s", mem_text);
 if(!(flag&1))
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 if(mem > xorriso->temp_mem_limit) {
   Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1);
   sprintf(xorriso->info_text,
           "List of matching file addresses exceeds -temp_mem_limit (%s > %s)",
           mem_text, limit_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }

 (*filev)= (char **) calloc(count, sizeof(char *));
 if(*filev==NULL) {
   Xorriso_no_pattern_memory(xorriso, mem, 0);
   return(-1);
 }
 return(1);
}


/* @param flag bit0= a match count !=1 is a FAILURE event
               bit1= with bit0 tolerate 0 matches if pattern is a constant
*/
int Xorriso_expand_disk_pattern(struct XorrisO *xorriso,
                           int num_patterns, char **patterns, int extra_filec,
                           int *filec, char ***filev, off_t *mem, int flag)
{
 int ret, count= 0, abs_adr= 0, i, was_count, was_filec;
 int nonconst_mismatches= 0, dive_count= 0;
 char sfe[5*SfileadrL], dir_adr[SfileadrL];

 *filec= 0;
 *filev= NULL;

 xorriso->search_mode= 3;
 xorriso->structured_search= 1;

 for(i= 0; i<num_patterns; i++) {

   ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
   if(ret<=0)
     return(ret);
   if(ret==2)
     abs_adr= 4;

   if(patterns[i][0]=='/' || abs_adr) {
     strcpy(dir_adr, "/");
     abs_adr= 4;
   } else {
     strcpy(dir_adr, xorriso->wdx);
     if(dir_adr[0]==0)
       strcpy(dir_adr, "/");
     ret= Sfile_type(dir_adr, 1|4);
     if(ret!=2) {
       Xorriso_msgs_submit(xorriso, 0, dir_adr, 0, "ERRFILE", 0);
       sprintf(xorriso->info_text,
               "Address set by -cdx is not a directory: %s",
               Text_shellsafe(dir_adr, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   }

   /* count the matches */
   was_count= count;
   ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, &count, NULL, 0,
                                       mem, &dive_count, 1 | abs_adr);
   if(ret<=0)
     goto ex;
   if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1) {
     count++;
     ret= Xorriso_eval_nonmatch(xorriso, patterns[i],
                                &nonconst_mismatches, mem, 0);
     if(ret<=0)
       goto ex;
   }
 }

 ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches,
                               num_patterns, patterns, (flag&1)|2);
 if(ret<=0)
   goto ex;

 count+= extra_filec;
 mem+= extra_filec*sizeof(char *);

 if(count<=0)
   {ret= 0; goto ex;}

 ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, 0);
 if(ret<=0)
   goto ex;

 /* now store addresses */
 for(i= 0; i<num_patterns; i++) {

   ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
   if(ret<=0)
     return(ret);

   if(patterns[i][0]=='/' || abs_adr) {
     strcpy(dir_adr, "/");
     abs_adr= 4;
   } else {
     strcpy(dir_adr, xorriso->wdx);
     if(dir_adr[0]==0)
       strcpy(dir_adr, "/");
   }

   was_filec= *filec;
   ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, filec, *filev,
                                       count, mem, &dive_count, abs_adr);
   if(ret<=0)
     goto ex;

   if(was_filec == *filec && strcmp(patterns[i],"*")!=0) {
     (*filev)[*filec]= strdup(patterns[i]);
     if((*filev)[*filec]==NULL) {
       (*mem)= strlen(patterns[i])+1;
       Xorriso_no_pattern_memory(xorriso, *mem, 0);
       ret= -1; goto ex;
     }
     (*filec)++;
   } 
 }

 ret= 1;
ex:;
 if(ret<=0) {
   if(filev!=NULL)
     Sfile_destroy_argv(&count, filev, 0);
   *filec= 0;
 }
 return(ret);
}


/* @param flag bit0= command without pattern capability
               bit1= disk_pattern rather than iso_rr_pattern
*/
int Xorriso_warn_of_wildcards(struct XorrisO *xorriso, char *path, int flag)
{
 if(strchr(path,'*')!=NULL || strchr(path,'?')!=NULL ||
    strchr(path,'[')!=NULL) {
   if(flag&1) {
     sprintf(xorriso->info_text,
      "Pattern expansion of wildcards \"*?[\" does not apply to this command");
   } else {
     sprintf(xorriso->info_text,
            "Pattern expansion of wildcards \"*?[\" is disabled by command %s",
            (flag&2) ? "-disk_pattern or -pathspecs" : "-iso_rr_pattern");
   }
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   sprintf(xorriso->info_text,"Pattern seen: %s\n", path);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   return(1);
 }
 return(0);
}


/* @param flag bit0= do not warn of wildcards
               bit1= these are disk_paths
*/
int Xorriso_end_idx(struct XorrisO *xorriso,
                    int argc, char **argv, int idx, int flag)
{
 int i, warned= 0;

 for(i= idx; i<argc; i++) {
   if(strcmp(argv[i], xorriso->list_delimiter)==0)
 break;
   if(!((flag&1) || warned))
     warned= Xorriso_warn_of_wildcards(xorriso, argv[i], flag&2);
 }
 return(i);
}


/* Returns a vector of strings which belong to an open ended arg list.
   If expansion is enabled, the vector might be allocated, else it is
   a pointer into the argv input vector.
   Thus the release of that memory is an expert task to be done by this
   function only. Use bit8 for that. With bit8 parameter argc MUST be the
   same value as with the call which might have allocated memory.
   @param xorriso The environment object
   @param argc Length of argv
   @param argv The vector with arguments, eventual list_delimiter ("--")
               and then eventual unrelated words
   @param idx  Start index in argv of the argument list
   @param optc Length of the effective possibly expanded option vector
   @param optv The option vector. Maybe a pointer into argv or maybe
               an own allocated vector.
   @param flag bit0= do not warn of wildcards
               bit1= these are disk_paths
               bit2= never expand wildcards
               bit3= do not expand last argument
               bit4= ignore last argument
               bit5= demand exactly one match
               bit6= with bit5 allow 0 matches if pattern is a constant
               bit7= silently tolerate empty argument list
               bit8= free the eventually allocated sub_vector
*/
int Xorriso_opt_args(struct XorrisO *xorriso, char *cmd,
                     int argc, char **argv, int idx,
                     int *end_idx, int *optc, char ***optv, int flag)
{
 int i, do_expand, nump, was_empty= 0, filec= 0, ret;
 char **filev= NULL, **patterns= NULL;
 off_t mem= 0;

 if(flag&2)
   do_expand= xorriso->do_disk_pattern==1 && !(flag&4);
 else
   do_expand= xorriso->do_iso_rr_pattern==1 && !(flag&4);
 if(flag&256) {
   if(*optv<argv || *optv>=argv+argc)
     Sfile_destroy_argv(optc, optv, 0);
   return(1);
 }
 if(idx>=argc) {
   *end_idx= argc;
   *optc= 0;
   *optv= NULL;
   sprintf(xorriso->info_text, "%s : Not enough arguments given", cmd);
   if((flag & 128))
     return(1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 *end_idx= Xorriso_end_idx(xorriso, argc, argv, idx,
                           ((flag&1) || do_expand) | (flag&2));
 if(*end_idx<0)
   return(*end_idx);
 if((flag&16) && (*end_idx)>idx)
   (*end_idx)--;
 *optc= *end_idx - idx;
 *optv= argv+idx;
 if(*optc<=0 || !do_expand)
   return(1);
 patterns= calloc(*optc, sizeof(char *));
 if(patterns==NULL) {
no_memory:;
   sprintf(xorriso->info_text,
           "%s : Cannot allocate enough memory for pattern expansion", cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
   {ret= -1; goto ex;}
 }
 nump= 0;
 if(flag&8) {
   was_empty= 1;
   mem+= strlen(argv[idx + *optc - 1])+1+sizeof(char *);
 }
 for(i= 0; i<*optc-!!(flag&8); i++) {
   if(argv[i + idx][0]==0) {
     was_empty++;
     mem+= sizeof(char *); /* as upper limit for size of an empty string */
 continue;
   }
   patterns[nump++]= argv[i + idx];
 }
 if(nump<=0) { /* Only empty texts. May the caller get happy with them. */
   free(patterns);
   return(1);
 }
 if(flag&2)
   ret= Xorriso_expand_disk_pattern(xorriso, nump, patterns, was_empty,
                                    &filec, &filev, &mem, (flag>>5)&3);
 else
   ret= Xorriso_expand_pattern(xorriso, nump, patterns, was_empty, 
                               &filec, &filev, &mem, (flag>>5)&3);
 if(ret<=0)
   {ret= 0; goto ex;}
 for(i= 0; i<was_empty; i++) {
   if(i==was_empty-1 && (flag&8))
     filev[filec++]= strdup(argv[idx + *optc - 1]);
   else
     filev[filec++]= strdup("");
   if(filev[filec-1]==NULL)
     goto no_memory;
 }

#ifdef Xorriso_verbous_pattern_expansioN
{ int l;
 sprintf(xorriso->info_text, "Pattern expansion yields %d items:", filec);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 l= 0;
 xorriso->info_text[0]= 0;
 for(i= 0; i<filec; i++) {
   l= strlen(xorriso->info_text);
   if(l>0 && l+1+strlen(filev[i])>60) {
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
     xorriso->info_text[0]= 0;
     l= 0;
   }
   sprintf(xorriso->info_text+l, " %s", filev[i]);
 }
 l= strlen(xorriso->info_text);
 if(l>0)
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
}
#endif /* Xorriso_verbous_pattern_expansioN */

 ret= 1;
ex:;
 if(ret<=0) {
   if(patterns!=NULL)
     free((char *) patterns);
   Sfile_destroy_argv(&filec, &filev, 0);
 } else {
   *optc= filec;
   *optv= filev;
 }
 return(ret);
}


int Xorriso_get_problem_status(struct XorrisO *xorriso, char severity[80],
                               int flag)
{
 strcpy(severity, xorriso->problem_status_text);
 return(xorriso->problem_status);
}


int Xorriso_set_problem_status(struct XorrisO *xorriso, char *severity, 
                               int flag)
{
 char *sev_text= "ALL";
 int sev, ret;

 if(severity[0])
   sev_text= severity;
 ret= Xorriso__text_to_sev(sev_text, &sev, 0);
 if(ret<=0)
   return(0);
 xorriso->problem_status= sev;
 strcpy(xorriso->problem_status_text, sev_text);
 if(sev > xorriso->eternal_problem_status) {
   xorriso->eternal_problem_status= sev;
   strcpy(xorriso->eternal_problem_status_text, sev_text);
 }
 return(1);
}


/* @param flag bit0-7= purpose
                       0= ERRFILE
                       1= mark line (only to be put out if enabled)
*/
int Xorriso_process_errfile(struct XorrisO *xorriso,
                            int error_code, char msg_text[], int os_errno,
                            int flag)
{
 char ttx[41];
 int purpose;

 if(strlen(msg_text)>SfileadrL)
   return(-1);

 purpose= flag&255;
 if(purpose==1 && !(xorriso->errfile_mode&1))
   return(2);
 if(xorriso->errfile_fp!=NULL) {
   if(purpose==1)
     fprintf(xorriso->errfile_fp, "----------------- %s  %s\n",
             msg_text, Ftimetxt(time(0), ttx, 1));
   else
     fprintf(xorriso->errfile_fp, "%s\n", msg_text);
   fflush(xorriso->errfile_fp);
   return(1);
 }
 if(xorriso->errfile_log[0]==0)
   return(1);
 if(strcmp(xorriso->errfile_log, "-")==0 ||
    strcmp(xorriso->errfile_log, "-R")==0) {
   if(purpose==1)
     sprintf(xorriso->result_line, "----------------- %s  %s\n",
             msg_text, Ftimetxt(time(0), ttx, 1));
   else
     sprintf(xorriso->result_line, "%s\n", msg_text);
   Xorriso_result(xorriso, 1);
   return(1);
 }
 if(strcmp(xorriso->errfile_log, "-I")==0) {
   if(purpose==1)
     sprintf(xorriso->info_text, "ERRFILE_MARK=%s  %s\n",
             msg_text, Ftimetxt(time(0), ttx, 1));
   else
     sprintf(xorriso->info_text, "ERRFILE=%s", msg_text);
   Xorriso_info(xorriso, 0);
   return(1);
 }
 return(2);
}


/* Note: It is ok to submit xorriso->info_text as msg_text here. */
/* flag: 
     bit0= for Xorriso_info() : use pager (as with result)
     bit1= for Xorriso_info() : permission to suppress output
     bit2..5= name prefix
       0="xorriso"
       1="libisofs"
       2="libburn"
       3="libisoburn"
       else: ""
     bit6= append carriage return rather than line feed (if not os_errno)
     bit7= perform Xorriso_process_msg_queues() first
*/
int Xorriso_msgs_submit(struct XorrisO *xorriso, 
                        int error_code, char msg_text[], int os_errno,
                        char severity[], int flag)
{
 int ret, lt, li, sev, i;
 char *sev_text= "FATAL", prefix[80];
 static char pfx_list[20][16]= {
                   "xorriso : ", "libisofs: ", "libburn : ", "libisoburn: ",
                    "", "", "", "", "", "", "", "", "", "", "", "" };

 if(flag&128)
   Xorriso_process_msg_queues(xorriso, 0);

 if(strcmp(severity, "ERRFILE")==0)
   Xorriso_process_errfile(xorriso, error_code, msg_text, os_errno, 0);

 /* Set problem status */
 ret= Xorriso__text_to_sev(severity, &sev, 0);
 if(ret<=0)
   Xorriso__text_to_sev(sev_text, &sev, 0);
 else
   sev_text= severity;
 if(xorriso->problem_status<sev) {
   xorriso->problem_status= sev;
   strcpy(xorriso->problem_status_text, sev_text);
 }
 if(xorriso->eternal_problem_status<sev) {
   xorriso->eternal_problem_status= sev;
   strcpy(xorriso->eternal_problem_status_text, sev_text);
 }

 /* Report problem event */
 if(sev<xorriso->report_about_severity && sev<xorriso->abort_on_severity)
   return(2);
 sprintf(prefix,"%s%s : ", pfx_list[(flag>>2)&15], sev_text);
 li= strlen(prefix);
 lt= strlen(msg_text);
 if(lt>sizeof(xorriso->info_text)-li-2)
   lt= sizeof(xorriso->info_text)-li-2;
 if(msg_text==xorriso->info_text) {
   for(i= lt; i>=0; i--)
     msg_text[i+li]= msg_text[i];
   for(i=0; i<li; i++)
     msg_text[i]= prefix[i];
 } else {
   strcpy(xorriso->info_text, prefix);
   strncpy(xorriso->info_text+li, msg_text, lt);
 }
 if((flag&64) && os_errno<=0)
   xorriso->info_text[li+lt]= '\r';
 else
   xorriso->info_text[li+lt]= '\n';
 xorriso->info_text[li+lt+1]= 0;
 Xorriso_info(xorriso,4|(flag&3));
 if(os_errno>0) {
   sprintf(xorriso->info_text, "%ssys   : %s\n",
           pfx_list[(flag>>2)&15], strerror(os_errno));
   Xorriso_info(xorriso,4|(flag&3));
 }
 return(1);   
}


/* To be used with isoburn_set_msgs_submit()
*/
int Xorriso_msgs_submit_void(void *xorriso,
                        int error_code, char msg_text[], int os_errno,
                        char severity[], int flag)
{
 int ret;

 ret= Xorriso_msgs_submit((struct XorrisO *) xorriso, error_code, msg_text,
                          os_errno, severity, flag);
 return(ret);
}


/**
    @param flag       bit0= do not issue own event messages
                      bit1= take xorriso->request_to_abort as reason for abort
    @return           Gives the advice:
                        2= pardon was given, go on
                        1= no problem, go on
                        0= function failed but xorriso would not abort, go on
                       <0= do abort
                           -1 = due to problem_status
                           -2 = due to xorriso->request_to_abort
*/
int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag)
{
 static int sev= 0;
 if(sev==0)
   Xorriso__text_to_sev("SORRY", &sev, 0);

 if((flag&2) && xorriso->request_to_abort)
   return(-2);

 Xorriso_process_msg_queues(xorriso, 0);
 if(ret>0 && xorriso->problem_status <= 0)
   return(1);

 if(xorriso->problem_status < xorriso->abort_on_severity &&
    xorriso->problem_status > 0) {
   if(xorriso->problem_status >= sev && !(flag&1)) {
     sprintf(xorriso->info_text,
             "xorriso : NOTE : Tolerated problem event of severity '%s'\n",
             xorriso->problem_status_text);
     Xorriso_info(xorriso, 0);/* submit not as problem event */
   }
   ret= 2;
 } else if(xorriso->problem_status > 0) {
   sprintf(xorriso->info_text,
           "xorriso : aborting : -abort_on '%s' encountered '%s'\n",
           xorriso->abort_on_text, xorriso->problem_status_text);
   if(!(flag&1))
     Xorriso_info(xorriso, 0);/* submit not as problem event */
   ret= -1;
 } else if(ret>0)
   ret= 1;
 else
   ret= 2;
 return(ret);
}


int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string,
                              uid_t *uid, int flag)
{
 double num;
 char text[80];
 struct passwd *pwd;

 sscanf(uid_string, "%lf", &num);
 sprintf(text,"%.f",num);
 if(strcmp(text,uid_string)==0) {
   *uid= num;
   return(1);
 }
 pwd= getpwnam(uid_string);
 if(pwd==NULL) {
   sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 *uid= pwd->pw_uid;
 return(1);
}


int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string,
                              gid_t *gid, int flag)
{
 double num;
 char text[80];
 struct group *grp;

 sscanf(gid_string, "%lf", &num);
 sprintf(text,"%.f",num);
 if(strcmp(text,gid_string)==0) {
   *gid= num;
   return(1);
 }
 grp= getgrnam(gid_string);
 if(grp==NULL) {
   sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 *gid= grp->gr_gid;
 return(1);
}
 

int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode,
                              mode_t *mode_and, mode_t *mode_or, int flag)
{
 int who_val= 0;
 char sfe[5*SfileadrL], *mpt, *vpt, *opt;
 unsigned int num= 0;
 mode_t mode_val,mask;

 *mode_and= ~0;
 *mode_or= 0;
 if(mode[0]=='0') {
   *mode_and= 0;
   sscanf(mode,"%o",&num);
   *mode_or= num;
 } else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL
           || strchr(mode,'=')!=NULL) {
   /* [ugoa][+-][rwxst] */;
   for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) {
     if(*mpt==',')
       mpt++;
     if(strlen(mpt)<2)
       goto unrecognizable;
     who_val= 0;
     for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) {
       if(*vpt=='u')
         who_val|= 4;
       else if(*vpt=='g')
         who_val|= 2;
       else if(*vpt=='o')
         who_val|= 1;
       else if(*vpt=='a')
         who_val|= 7;
       else
         goto unrecognizable;
     }
     opt= vpt;
     mode_val= 0;
     for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) {
       if(*vpt=='r') {
         if(who_val&4)
           mode_val|= S_IRUSR;
         if(who_val&2)
           mode_val|= S_IRGRP;
         if(who_val&1)
           mode_val|= S_IROTH;
       } else if(*vpt=='w') {
         if(who_val&4)
           mode_val|= S_IWUSR;
         if(who_val&2)
           mode_val|= S_IWGRP;
         if(who_val&1)
           mode_val|= S_IWOTH;
       } else if(*vpt=='x') {
         if(who_val&4)
           mode_val|= S_IXUSR;
         if(who_val&2)
           mode_val|= S_IXGRP;
         if(who_val&1)
           mode_val|= S_IXOTH;
       } else if(*vpt=='s') {
         if(who_val&4)
           mode_val|= S_ISUID;
         if(who_val&2)
           mode_val|= S_ISGID;
       } else if(*vpt=='t') {
         if(who_val&1)
           mode_val|= S_ISVTX;
       } else
         goto unrecognizable;
     }
     if(*opt=='+') {
       (*mode_or)|= mode_val;
     } else if(*opt=='=') {
       mask= 0;
       if(who_val&1)
         mask|= S_IRWXO|S_ISVTX;
       if(who_val&2)
         mask|= S_IRWXG|S_ISGID;
       if(who_val&4)
         mask|= S_IRWXU|S_ISUID;
       (*mode_and)&= ~(mask);
       (*mode_or)= ((*mode_or) & ~mask) | mode_val;
     } else if(*opt=='-') {
       (*mode_or)&= ~mode_val;
       (*mode_and)&= ~mode_val;
     }
   }
 } else {
unrecognizable:;
   sprintf(xorriso->info_text,
           "%s: Unrecognizable or faulty permission mode %s\n", cmd,
           Text_shellsafe(mode, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


int Xorriso_convert_datestring(struct XorrisO *xorriso, char *cmd,
                               char *time_type, char *timestring,
                               int *t_type, time_t *t, int flag)
{
 int ret;

 if(strcmp(time_type, "a")==0)
   (*t_type)|= 1;
 else if(strcmp(time_type, "m")==0)
   (*t_type)|= 4;
 else if(strcmp(time_type, "b")==0)
   (*t_type)|= 5;
 else {
   sprintf(xorriso->info_text, "%s: Unrecognized type '%s'", cmd, time_type);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 ret= Decode_timestring(timestring, t, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text, "%s: Cannot decode timestring '%s'", cmd,
           timestring);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 sprintf(xorriso->info_text, "Understanding timestring '%s' as:  %s",
         timestring, ctime(t));
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 return(1);
}


/* @param flag bit0=path is in source filesystem , bit1= unconditionally */
int Xorriso_much_too_long(struct XorrisO *xorriso, int len, int flag)
{
 if(len>=SfileadrL || (flag&2)) {
   sprintf(xorriso->info_text,
           "Path given for %s is much too long (%d)",
           ((flag&1) ? "local filesystem" : "ISO image"), len);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


int Xorriso_no_findjob(struct XorrisO *xorriso, char *cmd, int flag)
{
 sprintf(xorriso->info_text, "%s: cannot create find job object", cmd);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 return(1);
}


/* @param flag bit1= do not report memory usage as DEBUG
*/
int Xorriso_check_temp_mem_limit(struct XorrisO *xorriso, off_t mem, int flag)
{
 char mem_text[80], limit_text[80];

 Sfile_scale((double) mem, mem_text,5,1e4,0);
 if(!(flag&2)) {
   sprintf(xorriso->info_text,
           "Temporary memory needed for result sorting : %s", mem_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 } 
 if(mem > xorriso->temp_mem_limit) {
   Sfile_scale((double) xorriso->temp_mem_limit,limit_text,5,1e4,1);
   sprintf(xorriso->info_text,
       "Cannot sort. List of matching files exceeds -temp_mem_limit (%s > %s)",
           mem_text, limit_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   return(0);
 }
 return(1);
}


/* @param flag bit0= for Xorriso_msgs_submit: use pager
               bit1= do not issue warnings
*/
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
                    struct LinkiteM **link_stack, struct stat *stbuf, int flag)
{
 int ret;
 struct LinkiteM *litm;
 char sfe[5*SfileadrL];

 if(*link_stack != NULL) {
   if((*link_stack)->link_count>=xorriso->follow_link_limit) {
     sprintf(xorriso->info_text,
             "Too many symbolic links in single tree branch at : %s",
             Text_shellsafe(link_path, sfe, 0));
     if(!(flag&2))
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1);
     return(0);
   }
 }
 ret= stat(link_path, stbuf);
 if(ret==-1)
   return(0);
 ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0);
 if(ret>0) {
   sprintf(xorriso->info_text,
           "Detected symbolic link loop around : %s",
           Text_shellsafe(link_path, sfe, 0));
   if(!(flag&2))
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1);
   return(0);
 }
 ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino,
                   *link_stack, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "Cannot add new item to link loop prevention stack");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1);
   return(-1);
 }
 *link_stack= litm;
 return(1);
}


/* @param flag bit0= do not only sum up sizes but also print subdirs
               bit1= this is a recursion
   @return <=0 error , 1 ok , 2 could not open directory
*/
int Xorriso_show_dux_subs(struct XorrisO *xorriso,
                      char *abs_path, char *rel_path, off_t *size,
                      off_t boss_mem,
                      struct LinkiteM *link_stack,
                      int flag)
{
 int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link;
 char **filev= NULL, *namept;
 off_t sub_size, report_size, mem= 0;
 struct DirseQ *dirseq= NULL;
 struct stat stbuf;
 dev_t dir_dev;
 struct LinkiteM *own_link_stack;
 char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL;
 
 sfe= malloc(5*SfileadrL);
 path= malloc(SfileadrL);
 show_path= malloc(SfileadrL);
 name= malloc(SfileadrL);
 if(path==NULL || show_path==NULL || name==NULL || sfe==NULL) {
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
   {ret= -1; goto ex;}
 }
 own_link_stack= link_stack;
 namept= name;
 *size= 0;

 if(lstat(abs_path, &stbuf)==-1)
   {ret= 2; goto ex;}
 dir_dev= stbuf.st_dev;
 if(S_ISLNK(stbuf.st_mode)) {
   if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2))))
     {ret= 2; goto ex;}
   if(stat(abs_path, &stbuf)==-1)
     {ret= 2; goto ex;}
   if(dir_dev != stbuf.st_dev &&
      !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2))))
     {ret= 2; goto ex;}
 }
 ret= Dirseq_new(&dirseq, abs_path, 1);
 if(ret<0) {
   sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
   {ret= -1; goto ex;}
 }
 if(ret==0)
   {ret= 2; goto ex;}

 while(1) {
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
   ret= Dirseq_next_adr(dirseq,name,0);
   if(ret<0)
     goto ex;
   if(ret==0)
 break;

   sub_size= 0;
   strcpy(show_path, rel_path);
   if(Sfile_add_to_path(show_path, name, 0)<=0)
       goto much_too_long;

   strcpy(path, abs_path);
   if(Sfile_add_to_path(path, name, 0)<=0) {
much_too_long:;
     Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
     {ret= -1; goto ex;}
   }
   no_dive= 0;

   ret= lstat(path, &stbuf);
   if(ret==-1)
 continue;
   is_link= S_ISLNK(stbuf.st_mode);
   if(is_link && xorriso->do_follow_links) {
     ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
     if(ret<0)
       {ret= -1; goto ex;}
     if(ret!=1)
       no_dive= 1;
   }
   if(!S_ISDIR(stbuf.st_mode))
     no_dive= 1;
   if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
     no_dive= 1;
   if(!no_dive) {
     filec++;
     l= strlen(rel_path)+1;
     mem+= l;
     if(l % sizeof(char *))
       mem+= sizeof(char *)-(l % sizeof(char *));
     if(flag&1) /* diving and counting is done further below */
 continue;
     ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem,
                                own_link_stack,2);
     if(ret<0)
       goto ex;
     if(ret==0)
 continue;
   }
   
/*
   sub_size+= stbuf.st_size+strlen(name)+1;
*/
   sub_size+= stbuf.st_size+2048;
   if(sub_size>0)
     (*size)+= sub_size;
 }

 if(filec<=0 || !(flag&1))
   {ret= 1; goto ex;}

 /* Try to get a sorted list of directory names */
 mem+= (filec+1)*sizeof(char *);
 ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
 if(ret<0)
   goto ex;
 Dirseq_rewind(dirseq, 0);
 if(ret==0) {
no_sort_possible:;
   no_sort= 1;
 } else {
   filev= (char **) calloc(filec+1, sizeof(char *));
   if(filev==NULL)
     goto no_sort_possible;
   else {
     for(i= 0; i<filec; i++)
       filev[i]= NULL;
     fc= 0;
     while(1) {
       ret= Dirseq_next_adr(dirseq,name,0);
       if(ret<0)
         goto ex;
       if(ret==0)
     break;
       strcpy(path, abs_path);
       if(Sfile_add_to_path(path, name, 0)<=0)
         goto much_too_long;

       ret= lstat(path,&stbuf);
       if(ret==-1)
     continue;
       is_link= S_ISLNK(stbuf.st_mode);
       if(is_link && xorriso->do_follow_links) {
         ret= stat(path,&stbuf);
         if(ret==-1)
     continue;
       }
       if(!S_ISDIR(stbuf.st_mode))
     continue;
       if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
     continue;

       if(fc>=filec) { /* Number of files changed (or programming error) */
revoke_sorting:;
         for(j=0; j<fc; j++)
           free((char *) filev[j]);
         free((char *) filev);
         filev= NULL;
         goto no_sort_possible;
       }

       filev[fc]= strdup(name);
       if(filev[fc]==NULL)
         goto revoke_sorting;
       fc++;
     }
     filec= fc;
     if(filec>1)
       Sort_argv(filec, filev, 0);
   }
 }

 for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
   if(no_sort) {
     ret= Dirseq_next_adr(dirseq,name,0);
     if(ret<0)
       goto ex;
     if(ret==0)
 break;
   } else
     namept= filev[i];

   sub_size= 0;
   strcpy(show_path, rel_path);
   if(Sfile_add_to_path(show_path, namept, 0)<=0)
     goto much_too_long;
   strcpy(path, abs_path);
   if(Sfile_add_to_path(path, namept, 0)<=0)
     goto much_too_long;
   no_dive= 0;

   ret= lstat(path,&stbuf);
   if(ret==-1)
 continue;
   is_link= S_ISLNK(stbuf.st_mode);
   if(is_link && xorriso->do_follow_links) {
     ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
     if(ret<0)
       {ret= -1; goto ex;}
     if(ret!=1)
 continue;
   }
   if(!S_ISDIR(stbuf.st_mode))
 continue;
   if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) {
     ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size,
                                boss_mem+mem, own_link_stack, 2|(flag&1));
     if(ret<0)
       goto ex;
   }

/*
   sub_size+= stbuf.st_size+strlen(namept)+1;
*/
   sub_size+= stbuf.st_size+2048;
   if(sub_size>0)
     (*size)+= sub_size;
   report_size= sub_size/1024;
   if(report_size*1024<sub_size)
      report_size++;
   sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
   sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
           Text_shellsafe(show_path, sfe, 0));
   Xorriso_result(xorriso, 0);
 }

 ret= 1;
ex:;
 if(sfe!=NULL)
   free(sfe);
 if(path!=NULL)
   free(path);
 if(show_path!=NULL)
   free(show_path);
 if(name!=NULL)
   free(name);
 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 Dirseq_destroy(&dirseq, 0);
 if(filev!=NULL) {
   for(i=0; i<filec; i++)
     if(filev[i]!=NULL)
       free((char *) filev[i]);
   free((char *) filev);
 }
 return(ret);
}


/* @param flag   bit1= add '+' to perms
*/
int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag)
{
 strcpy(perms,"--------- ");
 if(st_mode&S_IRUSR) perms[0]= 'r';
 if(st_mode&S_IWUSR) perms[1]= 'w';
 if(st_mode&S_IXUSR) perms[2]= 'x';
 if(st_mode&S_ISUID) {
   if(st_mode&S_IXUSR)
     perms[2]= 's';
   else
     perms[2]= 'S';
 }
 if(st_mode&S_IRGRP) perms[3]= 'r';
 if(st_mode&S_IWGRP) perms[4]= 'w';
 if(st_mode&S_IXGRP) perms[5]= 'x';
 if(st_mode&S_ISGID) {
   if(st_mode&S_IXGRP)
     perms[5]= 's';
   else
     perms[5]= 'S';
 }
 if(st_mode&S_IROTH) perms[6]= 'r';
 if(st_mode&S_IWOTH) perms[7]= 'w';
 if(st_mode&S_IXOTH) perms[8]= 'x';
 if(st_mode&S_ISVTX) {
   if(st_mode&S_IXOTH)
     perms[8]= 't';
   else
     perms[8]= 'T';
 }
 if(flag & 2)
   perms[9]= '+';
 return(1);
}


/* @param flag bit0= recognize Xorriso_IFBOOT as file type
               bit1= add '+' to perms
*/
int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag)
{
 int show_major_minor= 0, high_shift= 0, high_mask= 0;
 char *rpt, perms[11], mm_text[80];
 mode_t st_mode;
 dev_t dev, major, minor;

 rpt= xorriso->result_line;
 rpt[0]= 0;
 st_mode= stbuf->st_mode;

 if(S_ISDIR(st_mode))
   strcat(rpt, "d");
 else if(S_ISREG(st_mode))
   strcat(rpt, "-");
 else if(S_ISLNK(st_mode))
   strcat(rpt, "l");
 else if(S_ISBLK(st_mode)) {
   strcat(rpt, "b");
   show_major_minor= 1;
 } else if(S_ISCHR(st_mode)) {
   strcat(rpt, "c");
   show_major_minor= 1;
 } else if(S_ISFIFO(st_mode))
   strcat(rpt, "p");
 else if(S_ISSOCK(st_mode))
   strcat(rpt, "s");
 else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT)
   strcat(rpt, "e");
 else
   strcat(rpt, "?");

 Xorriso__mode_to_perms(st_mode, perms, flag & 2);
 strcat(rpt, perms);

 sprintf(rpt+strlen(rpt)," %3u ",(unsigned int) stbuf->st_nlink);

 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid);
 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid);
 if(show_major_minor) {
   dev= stbuf->st_rdev;

   /* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor() 
      >>> but this looks as if it should go to some system dependency
      >>> in FreeBSD dev_t is 32 bit
   */
   if(sizeof(dev_t) > 4) {
     high_shift= 32;
     high_mask= ~0xfff;
   }
   major= (((dev >> 8) & 0xfff) |
           ((unsigned int) (dev >> high_shift) & high_mask))
          & 0xffffffff;
   minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff;

   sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor);
   sprintf(rpt+strlen(rpt), "%8s ", mm_text);
 } else
   sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size);

 Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0);
 strcat(rpt, " ");

 return(1);
}


struct DirentrY {
 char *adr;
 struct DirentrY *next;
};


int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path,
                         int *filec, char ***filev, off_t boss_mem, int flag)
{
 int count= 0, ret;
 char name[SfileadrL];
 struct DirseQ *dirseq= NULL;
 off_t mem;
 struct DirentrY *last= NULL, *current= NULL;

 *filec= 0;
 *filev= NULL;
 mem= boss_mem;
 ret= Dirseq_new(&dirseq, dir_path, 1);
 if(ret<=0)
   goto ex;
 while(1) { /* loop over directory content */
   ret= Dirseq_next_adr(dirseq,name,0);
   if(ret==0)
 break;
   if(ret<0)
     goto ex;
   mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *);
   if(mem>xorriso->temp_mem_limit)
     {ret= 0; goto ex;}

   current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY));
   if(current==NULL)
     {ret= -1; goto ex;}
   current->adr= NULL;
   current->next= last;
   last= current;
   last->adr= strdup(name);
   if(last->adr==NULL)
     {ret= -1; goto ex;}
   count++;
 }
 *filec= count;
 if(count==0)
   {ret= 1; goto ex;}
 (*filev)= (char **) calloc(count, sizeof(char *));
 if(*filev==NULL)
   {ret= -1; goto ex; }
 count= 0;
 for(current= last; current!=NULL; current= last) {
   last= current->next;
   (*filev)[count++]= current->adr;
   free((char *) current);
 }
 Sort_argv(*filec, *filev, 0);
 ret= 1; 
ex:;
 for(current= last; current!=NULL; current= last) {
   last= current->next;
   free(current->adr);
   free((char *) current);
 }
 return(ret);
}


/* @param flag bit0= long format
               bit1= do not print count of nodes
               bit2= du format
               bit3= print directories as themselves (ls -d)
*/
int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
                      int filec, char **filev, off_t boss_mem, int flag)
{
 int i, ret, was_error= 0, dfilec= 0, pass, passes;
 char sfe[5*SfileadrL], sfe2[5*SfileadrL], path[SfileadrL], *acl_text= NULL;
 char *rpt, link_target[SfileadrL], **dfilev= NULL;
 off_t size;
 struct stat stbuf;

 rpt= xorriso->result_line;

 Sort_argv(filec, filev, 0);

 /* Count valid nodes, warn of invalid ones */
 for(i= 0; i<filec; i++) {
   ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
   if(ret<=0) {
     was_error++;
 continue;
   }
   ret= lstat(path, &stbuf);
   if(ret==-1) {
     sprintf(xorriso->info_text, "Not found in local filesystem: %s",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1);
     was_error++;
 continue;
   }
 }

 if((flag&8) && !(flag&(2|4))) {
   sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error);
   Xorriso_info(xorriso,1);
   if(filec-was_error<=0)
     return(!was_error);
 }

 passes= 1+!(flag&(4|8));
 for(pass= 0; pass<passes; pass++)
 for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
   ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
   if(ret<=0)
 continue;
   ret= lstat(path, &stbuf);
   if(ret==-1)
 continue;
   if(S_ISLNK(stbuf.st_mode) &&
      (xorriso->do_follow_links || xorriso->do_follow_param)) {
     ret= stat(path, &stbuf);
     if(ret==-1) 
       ret= lstat(path, &stbuf);
     if(ret==-1)
 continue;
   }
   if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) {
     if(pass==0)
 continue;
     if(filec>1) {
       strcpy(xorriso->result_line, "\n");
       Xorriso_result(xorriso,0);
       sprintf(xorriso->result_line, "%s:\n", Text_shellsafe(filev[i], sfe,0));
       Xorriso_result(xorriso,0);
     }
     ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0);
     if(ret<=0) {

       /* >>> DirseQ loop and single item Xorriso_lsx_filev() */;

     } else {
       if(flag&1) {
         sprintf(xorriso->result_line, "total %d\n", dfilec);
         Xorriso_result(xorriso,0);
       }
       Xorriso_lsx_filev(xorriso, path,
                         dfilec, dfilev, boss_mem, (flag&1)|2|8);
     }
     if(dfilec>0)
       Sfile_destroy_argv(&dfilec, &dfilev, 0);
 continue;
   } else
     if(pass>0)
 continue;
   link_target[0]= 0;
   rpt[0]= 0;
   if((flag&5)==1) {
     Xorriso_local_getfacl(xorriso, path, &acl_text, 16);
     ret= Xorriso_format_ls_l(xorriso, &stbuf, (acl_text != NULL) << 1);
     Xorriso_local_getfacl(xorriso, path, &acl_text, 1 << 15);
     if(ret<=0)
 continue;
     if(S_ISLNK(stbuf.st_mode)) {
       ret= Xorriso_resolve_link(xorriso, path, link_target, 1);
       if(ret<=0)
         link_target[0]= 0;
     }
   } else if(flag&4) { /* -du or -dus */
     size= stbuf.st_size;
     if(S_ISDIR(stbuf.st_mode)) {
       ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem,
                                  NULL, flag&1);
       if(ret<0)
         return(-1);
       if(ret==0)
 continue;
     }
     sprintf(rpt, "%7.f ",(double) (size/1024));
   }
   if(link_target[0])
     sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n",
             Text_shellsafe(filev[i], sfe, 0),
             Text_shellsafe(link_target, sfe2, 0));
   else
     sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
               Text_shellsafe(filev[i], sfe, 0));
   Xorriso_result(xorriso, 0);
 }
 return(!was_error);
}


/* @param flag bit0= path is a directory
               bit2= recursion: do not reassure in mode 2 "tree"
               bit3= this is for overwriting and not for plain removal
*/
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
{
 int ret;
 char sfe[5*SfileadrL];

 while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
       && !xorriso->request_not_to_ask) {
   /* ls -ld */
   Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8);
   if(flag&1) /* du -s */
     Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4);
   if(flag&8)
     sprintf(xorriso->info_text,
  "File exists. Remove ?  n= keep old, y= remove, x= abort, @= stop asking\n");
   else
     sprintf(xorriso->info_text,
  "Remove above file ?  n= keep it, y= remove it, x= abort, @= stop asking\n");
   Xorriso_info(xorriso, 4);
   ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
   if(ret<=0)
     goto ex;
   if(xorriso->request_to_abort) {
     sprintf(xorriso->info_text,
             "Removal operation aborted by user before file: %s",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     ret= 3; goto ex;
   }
   if(ret==3)
 continue;
   if(ret==6) /* yes */
 break;
   if(ret==4) { /* yes, do not ask again */
     xorriso->request_not_to_ask= 1;
 break;
   }
   if(ret==1) { /* no */
     sprintf(xorriso->info_text, "Kept in existing state: %s",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     ret= 3; goto ex;
   }
 }
 ret= 1;
ex:
 return(ret);
}


/*
   @param flag >>> bit0= remove whole sub tree: rm -r
               bit1= remove empty directory: rmdir  
               bit2= recursion: do not reassure in mode 2 "tree"
               bit3= this is for overwriting and not for plain removal
               bit4= count deleted files in xorriso->pacifier_count
               bit5= with bit0 only remove directory content, not the directory
               bit6= permission to call Xorriso_make_accessible()
   @return   <=0 = error
               1 = removed leaf file object
               2 = removed directory or tree
               3 = did not remove on user revocation
*/
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
{
 int ret, is_dir= 0, made_accessible= 0;
 struct stat victim_stbuf, *victim_node= NULL;
 struct DirseQ *dirseq= NULL;
 char *sfe= NULL, *sub_path= NULL;
 struct PermiteM *perm_stack_mem;

 perm_stack_mem= xorriso->perm_stack;

 /* Avoiding large local memory objects in order to save stack space */
 sfe= malloc(5*SfileadrL);
 sub_path= malloc(2*SfileadrL);
 if(sfe==NULL || sub_path==NULL) {
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
   {ret= -1; goto ex;}
 }

 if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
   {ret= 0; goto ex;}

 ret= lstat(path, &victim_stbuf);
 if(ret==-1) {
   if((flag & 64) && errno == EACCES) {
     ret= Xorriso_make_accessible(xorriso, path, 0);
     if(ret < 0)
       goto ex;
     made_accessible= 1;
     ret= lstat(path, &victim_stbuf);
   }
   if(ret==-1) {
     sprintf(xorriso->info_text, "Cannot lstat(%s)",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
     {ret= 0; goto ex;}
   }
 }
 if(strcmp(path, "/")==0) {
   sprintf(xorriso->info_text, "May not delete root directory");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   {ret= 0; goto ex;}
 }
 victim_node= &victim_stbuf;
 if(S_ISDIR(victim_stbuf.st_mode))
   is_dir= 1;
 if(!is_dir) {
   if(flag&2) { /* rmdir */
     sprintf(xorriso->info_text, "%s in disk filesystem is not a directory",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   }
 } else {
   if(flag&1) { /* rm -r */

#ifdef Osirrox_not_yeT
     /* >>> */

     if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
        (flag&32)) {
       /* Iterate over subordinates and delete them */
       mem= boss_mem;

       ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
                         &iter, &node_array, &node_count, &node_idx,
                         &node, 1|2);
       if(ret<=0) {
cannot_create_iter:;
         Xorriso_cannot_create_iter(xorriso, ret, 0);
         ret= -1; goto ex;
       }
       pl= strlen(path);
       strcpy(sub_path, path);
       if(pl==0 || sub_path[pl-1]!='/') {
         sub_path[pl++]= '/';
         sub_path[pl]= 0;
       }
       sub_name= sub_path+pl;
       while(1) { 
         ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
                                &node_array, &node_count, &node_idx, &node, 0);
         if(ret<0)
           goto ex;
         if(ret==0 || xorriso->request_to_abort)
       break;
         name= (char *) iso_node_get_name(node);
         if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
           {ret= 0; goto rm_r_problem_handler;}
         strcpy(sub_name, name);
         ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
         if(ret==3 || ret<=0 || xorriso->request_to_abort) {
rm_r_problem_handler:;
           not_removed= 1;
           fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
           if(fret<0)
             goto dir_not_removed;
         }
       }
       if(flag&32)
         {ret= 2; goto ex;}

       if(not_removed) {
dir_not_removed:;
         sprintf(xorriso->info_text, "Directory not removed: %s",
                 Text_shellsafe(path, sfe, 0));
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
         if(ret>0)
           ret= 3;
         goto ex;
       }
     }

#else /* Osirrox_not_yeT */

       sprintf(xorriso->info_text, "-rm_rx is not implemented yet");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;

#endif /* !Osirrox_not_yeT */

   } else {
     if(!(flag&2)) { /* not rmdir */
       sprintf(xorriso->info_text, "%s in disk filesystem is a directory",
               Text_shellsafe(path, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
     ret= Dirseq_new(&dirseq, path, 1);
     if(ret>0) {
       ret= Dirseq_next_adr(dirseq, sfe, 0);
       if(ret>0) {
         sprintf(xorriso->info_text,
                 "Directory not empty on attempt to delete: %s",
                 Text_shellsafe(path, sfe, 0));
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
         ret= 0; goto ex;
       }
     }
   }
 }
 if(xorriso->request_to_abort)
   {ret= 3; goto ex;}
 ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir);
 if(ret<=0 || ret==3)
   goto ex;
 if(is_dir)
   ret= rmdir(path);
 else
   ret= unlink(path);
 if(ret == -1) {
   if((flag & 64) && errno == EACCES && !made_accessible) {
     ret= Xorriso_make_accessible(xorriso, path, 0);
     if(ret < 0)
       goto ex;
     made_accessible= 1;
     if(is_dir)
       ret= rmdir(path);
     else
       ret= unlink(path);
   }
   if(ret == -1) {
     sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
     ret= -1; goto ex;
   }
 }
 if(flag&16)
   xorriso->pacifier_count++;
 ret= 1+!!is_dir;
ex:;
 if(made_accessible)
   Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 if(sfe!=NULL)
   free(sfe);
 if(sub_path!=NULL)
   free(sub_path);
 Dirseq_destroy(&dirseq, 0);
 return(ret);
} 


/* @param flag bit0= recursion
*/ 
int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
                         char *abs_path, char *show_path, int depth, int flag)
{
 int ret= 0, type, action= 0, dpl= 0, compare_result, uret;
 uid_t user= 0;
 gid_t group= 0;
 time_t date= 0;
 mode_t mode_or= 0, mode_and= ~1;
 char *target, *text_2, sfe[5*SfileadrL], *disk_prefix, iso_path[SfileadrL];
 struct FindjoB *subjob;
 struct stat stbuf; 

 action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
                                &mode_and, &mode_or, &type, &date, &subjob, 0);
 if(action<0)
   action= 0;
 if(action<0)
   action= 0;
 if(action==15 || action==16 || action==18 || action==19 || action==20) {
   /* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */
   Findjob_get_start_path(job, &disk_prefix, 0);
   if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
     {ret= -1; goto ex;}
   dpl= strlen(disk_prefix);
   if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL)
     {ret= -1; goto ex;}
   if(abs_path[dpl]=='/')
     dpl++;
   ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4);
   if(ret<=0)
     {goto ex;}

 }
 if(action==15) { /* in_iso */
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
   if(ret<0)
     {ret= 1; goto ex;}
   sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
   Xorriso_result(xorriso, 0);
   ret= 1;
 } else if(action==16) { /* not_in_iso */
   ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
                                &compare_result, 4);
   if(ret<xorriso->find_compare_result)
     xorriso->find_compare_result= ret;
   if(ret>=0)
     ret= 1;
 } else if(action==18) { /* add_missing */
   ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
                                &compare_result, 4|(1<<31));
   if(ret<xorriso->find_compare_result)
     xorriso->find_compare_result= ret;
   if(ret==0) {
     uret= Xorriso_update_interpreter(xorriso, NULL, compare_result,
                                      abs_path, iso_path, (flag&1)<<2);
     if(uret<=0)
       ret= 0;
   }
   if(ret>=0)
     ret= 1;
 } else if(action==19) { /* empty_iso_dir */
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
   if(ret<0)
     {ret= 1; goto ex;}
   if(!S_ISDIR(stbuf.st_mode))
     {ret= 1; goto ex;}
   ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32);
   if(ret>0) {
     sprintf(xorriso->info_text, "Emptied directory %s",
             Text_shellsafe(iso_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
   }
 } else if(action==20) { /* is_full_in_iso */
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
   if(ret<0)
     {ret= 1; goto ex;}
   if(!S_ISDIR(stbuf.st_mode))
     {ret= 1; goto ex;}
   strcpy(sfe, xorriso->wdi);
   strcpy(xorriso->wdi, iso_path);
   ret= Xorriso_ls(xorriso, 4|8);
   strcpy(xorriso->wdi, sfe);
   if(ret>0) {
     sprintf(xorriso->result_line,
            "d %s (ISO) : non-empty directory (would not match mount point)\n",
            Text_shellsafe(iso_path, sfe, 0));
     Xorriso_result(xorriso,0);
   }
   {ret= 1; goto ex;}
 } else {
   sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
   Xorriso_result(xorriso, 0);
   ret= 1;
 } 
ex:;
 if(action==15 || action==16 || action==18 || action==19 || action==20)
   if(xorriso->no_volset_present)
     xorriso->request_to_abort= 1; /* Need an image. No use to try again. */
 return(ret);
}


/* @param flag bit0=recursion
*/
int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job,
                  char *abs_dir_parm, char *dir_path,
                  struct stat *dir_stbuf, int depth,
                  struct LinkiteM *link_stack, int flag)
{
 int ret,is_link, no_dive;
 struct DirseQ *dirseq= NULL;
 struct stat stbuf;
 struct LinkiteM *own_link_stack;
 char *abs_dir_path, *namept;
 char *name= NULL, *path= NULL, *sfe= NULL;
 char *abs_dir_path_data= NULL, *abs_path= NULL;

 if(xorriso->request_to_abort)
   {ret= 0; goto ex;}

 sfe= malloc(5*SfileadrL);
 name= malloc(SfileadrL);
 path= malloc(SfileadrL);
 abs_dir_path_data= malloc(SfileadrL);
 abs_path= malloc(SfileadrL);
 if(name==NULL || sfe==NULL || path==NULL ||
    abs_dir_path_data==NULL || abs_path==NULL) {
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
   {ret= -1; goto ex;}
 }
 own_link_stack= link_stack;
 abs_dir_path= abs_dir_parm;
 if(abs_dir_path[0]==0) {
   ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path,
                             abs_dir_path_data, 1|2|8);
   if(ret<=0)
     goto ex;
   abs_dir_path= abs_dir_path_data;
   ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1));
   if(ret<0)
     goto ex;
   if(ret>0)
     {ret= 0; goto ex;}
   ret= lstat(abs_dir_path, dir_stbuf);
   if(ret==-1)
     {ret= 0; goto ex;}
   if(S_ISLNK(dir_stbuf->st_mode) &&
      (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
     if(stat(abs_dir_path, &stbuf)!=-1)
       if(dir_stbuf->st_dev == stbuf.st_dev ||
         (xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
         memcpy(dir_stbuf, &stbuf, sizeof(struct stat));

   namept= strrchr(dir_path, '/');
   if(namept==NULL)
     namept= dir_path;
   else
     namept++;

   ret= Findjob_test_2(xorriso, job, NULL, namept, dir_path, NULL, dir_stbuf,
                       0);
   if(ret<0)
     goto ex;
   if(ret>0) {
     ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth,
                               flag&1);
     if(xorriso->request_to_abort)
       {ret= 0; goto ex;}
     if(ret<=0) {
       if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
         goto ex;
     }
   }
 }
 if(xorriso->request_to_abort)
   {ret= 1; goto ex;}
 if(!S_ISDIR(dir_stbuf->st_mode))
   {ret= 2; goto ex;}

 ret= Dirseq_new(&dirseq, abs_dir_path, 1);
 if(ret<0) {
   sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
   {ret= -1; goto ex;}
 }
 if(ret==0)
   {ret= 2; goto ex;}
 
 while(!xorriso->request_to_abort) {
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
   ret= Dirseq_next_adr(dirseq,name,0);
   if(ret==0)
 break;
   if(ret<0) {
     sprintf(xorriso->info_text,"Failed to obtain next directory entry");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
     {ret= -1; goto ex;}
   }
   ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1);
   if(ret<=0)
     goto ex;
   ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
   if(ret<=0)
     goto ex;
   ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */
   if(ret<0)
     goto ex;
   if(ret>0)
 continue;
   ret= lstat(abs_path, &stbuf);
   if(ret==-1)
 continue;
   no_dive= 0;

   is_link= S_ISLNK(stbuf.st_mode);
   if(is_link && xorriso->do_follow_links) {
     ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2);
     if(ret<0)
       {ret= -1; goto ex;}
     if(ret!=1)
       no_dive= 1;
   }

   ret= Findjob_test_2(xorriso, job, NULL, name, path, dir_stbuf, &stbuf, 0);
   if(ret<0)
     goto ex;
   if(ret>0) {
     ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1);
     if(xorriso->request_to_abort)
       {ret= 0; goto ex;}
     if(ret<=0) {
       if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
         goto ex;
     }
   }
   if(!S_ISDIR(stbuf.st_mode))
     no_dive= 1;
   if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount)
     no_dive= 1;
   if(!no_dive) {
     ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1,
                        own_link_stack, flag|1);
     if(ret<0)
       goto ex;
   }
 }

 ret= 1;
ex:;
 if(sfe!=NULL)
   free(sfe);
 if(name!=NULL)
   free(name);
 if(path!=NULL)
   free(path);
 if(abs_dir_path_data!=NULL)
   free(abs_dir_path_data);
 if(abs_path!=NULL)
   free(abs_path);
 Dirseq_destroy(&dirseq, 0);
 return(ret);
}


/* @param flag bit0= a non-existing target of multiple sources is a directory
               bit1= all paths except the last one are disk_paths
               bit2= the last path is a disk_path
   @return <=0 is error, 1= leaf file object, 2= directory
*/
int Xorriso_cpmv_args(struct XorrisO *xorriso, char *cmd,
                      int argc, char **argv, int *idx,
                      int *optc, char ***optv, char eff_dest[SfileadrL],
                      int flag)
{
 int destc= 0, is_dir=0, end_idx, ret, i;
 char **destv= NULL;
 char sfe[5*SfileadrL];

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx,
                          (xorriso->do_iso_rr_pattern==1)|(flag&2));
 if(end_idx - *idx < 2) {
   sprintf(xorriso->info_text, "%s: not enough arguments", cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   {ret= 0; goto ex;}
 }

 ret= Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, optc, optv,
                       (flag&2)|16); /* ignore last argument */
 if(ret<=0)
   goto ex;
 /* demand one match, or 0 with a constant */
 ret= Xorriso_opt_args(xorriso, cmd, argc, argv, end_idx, &end_idx, &destc,
                       &destv, ((flag&4)>>1) | 32 | 64);
 if(ret<=0)
   goto ex;

 /* Evaluate target address */
 if(flag&4)
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, destv[0], eff_dest,
                                   2|4|16);
 else
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest,
                                   1);
 if(ret<0)
   {ret= 0; goto ex;}
 if(ret==2 || ((flag&1) && *optc > 1 && ret==0)) {
   is_dir= 1;
 } else if(*optc > 1) {
   for(i= 0; i<*optc; i++)
     Xorriso_msgs_submit(xorriso, 0, (*optv)[i], 0, "ERRFILE", 0);
   sprintf(xorriso->info_text,
        "%s: more than one origin given, destination is a non-directory: %s",
        cmd, Text_shellsafe(destv[0], sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   {ret= 0; goto ex;}
 }
 if(ret==0) { /* compute complete eff_dest */
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest,
                                   2 | (flag&4));
   if(ret<0)
     {ret= 0; goto ex;}
 }

 ret= 1+is_dir;
ex:;
 Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &destc, &destv,
                  256);
 (*idx)= end_idx;
 return(ret);
}


/** @return -1= abort , 0= no , 1= yes
*/
int Xorriso_reassure(struct XorrisO *xorriso, char *cmd, char *which_will,
                     int flag)
{
 int ret;

 if(!xorriso->do_reassure)
   return(1);
 sprintf(xorriso->info_text, "Really perform %s which will %s ? (y/n)\n",
         cmd, which_will);
 Xorriso_info(xorriso, 4);
 do {
   ret= Xorriso_request_confirmation(xorriso, 2|4|16);
 } while(ret==3);
 if(ret==6 || ret==4) {
   sprintf(xorriso->info_text, "%s confirmed", cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   return(1);
 }
 if(ret==2) {
   sprintf(xorriso->info_text, "%s aborted", cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   return(-1);
 }
 sprintf(xorriso->info_text, "%s revoked", cmd);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 return(0);
}


/* @param flag bit0+1= what to aquire after giving up outdev
                       0=none, 1=indev, 2=outdev, 3=both
*/
int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag)
{
 int ret, aq_flag;
 char drive_name[SfileadrL], sfe[5*SfileadrL];

 aq_flag= flag&3;
 strcpy(drive_name, xorriso->outdev);
 Xorriso_give_up_drive(xorriso, aq_flag);
 if(aq_flag==0) { 
   sprintf(xorriso->info_text,"Gave up -outdev %s",
           Text_shellsafe(xorriso->outdev, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   return(1);
 }
 sprintf(xorriso->info_text,"Re-aquiring -outdev %s",
         Text_shellsafe(drive_name, sfe, 0));
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 ret= Xorriso_aquire_drive(xorriso, drive_name, aq_flag); 
 if(ret<=0) {
   sprintf(xorriso->info_text,"Could not re-aquire -outdev %s",
           Text_shellsafe(xorriso->outdev, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(ret);
 }
 return(1);
}


int Xorriso_cdrskin_help(struct XorrisO *xorriso, int flag)
{
 static char helptext[][80]= {
"Usage: xorriso -as cdrecord [options|source_addresses]",
"Note: This is not cdrecord. See xorriso -help, xorriso -version, man xorriso",
"Options:",
"\t-version\tprint version information and exit emulation",
"\t--devices\tprint list of available MMC drives and exit emulation",
"\tdev=target\tpseudo-SCSI target to use as CD-Recorder",
"\t-v\t\tincrement verbose level by one",
"\t-checkdrive\tcheck if a driver for the drive is present",
"\t-inq\t\tdo an inquiry for the drive and exit emulation",
"\tspeed=#\t\tset speed of drive",
"\tblank=type\tblank a CD-RW disc (see blank=help)",
"\tfs=#\t\tSet fifo size to # (0 to disable, default is 4 MB)",
"\t-eject\t\teject the disk after doing the work",
"\t-dummy\t\tdo everything with laser turned off",
"\t-msinfo\t\tretrieve multi-session info for mkisofs >= 1.10",
"\t-toc\t\tretrieve and print TOC/PMA data",
"\t-atip\t\tretrieve media state, print \"Is *erasable\"",
"\t-multi\t\tgenerate a TOC that allows multi session",
"\t-waiti\t\twait until input is available before opening SCSI",
"\ttsize=#\t\tannounces exact size of source data",
"\tpadsize=#\tAmount of padding",
"\t-data\t\tSubsequent tracks are CD-ROM data mode 1 (default)",
"\t-isosize\tUse iso9660 file system size for next data track",
"\t-pad\t\tpadsize=30k",
"\t-nopad\t\tDo not pad",
"\t--grow_overwriteable_iso\temulate multi-session on DVD+RW, BD-RE",
"\twrite_start_address=#\t\twrite to byte address on DVD+RW, BD-RE",
"\tstream_recording=on|number\ttry to get full speed on DVD-RAM, BD",
"\tdvd_obs=default|32k|64k\t\tbytes per DVD/BD write operation",
"\tstdio_sync=on|off|number\twhether to fsync output to \"stdio:\"",
"\t-help\t\tprint this text to stderr and exit emulation",
"Actually this is the integrated ISO RockRidge filesystem manipulator xorriso",
"lending its libburn capabilities to a very limited cdrecord emulation. Only",
"a single data track can be burnt to blank, appendable or overwriteable media.",
"A much more elaborate cdrecord emulator is cdrskin from the same project.",
"@End_of_helptexT@"
};
 int i;

 for(i= 0; strcmp(helptext[i], "@End_of_helptexT@")!=0; i++) {
   sprintf(xorriso->info_text, "%s\n", helptext[i]);
   Xorriso_info(xorriso,0);
 }
 return(1);
}


/* micro version of cdrskin */
int Xorriso_cdrskin(struct XorrisO *xorriso, char *whom, int argc, char **argv,
                    int flag)
{
 int ret, i, k, mem_do_close, aq_ret, eject_ret, msc1, msc2, hflag;
 int do_atip= 0, do_checkdrive= 0, do_eject= 0, do_scanbus= 0;
 int do_toc= 0, do_verbous= 0, do_version= 0, do_help= 0, do_waiti= 0;
 int do_multi= 0, do_msinfo= 0, do_grow= 0, do_isosize= 0, do_xa1= 0;
 double write_start_address= -1.0, tsize= -1.0;
 char track_source[SfileadrL], sfe[5*SfileadrL], dev_adr[SfileadrL], *cpt;
 char mem_report_about_text[80], *report_about= "SORRY", blank_mode[80];
 char speed[80];

 /* cdrecord 2.01 options which are not scheduled for implementation, yet */
 static char ignored_partial_options[][41]= {
   "timeout=", "debug=", "kdebug=", "kd=", "driver=", "ts=",
   "pregap=", "defpregap=", "mcn=", "isrc=", "index=", "textfile=",
   "pktsize=", "cuefile=",
   "gracetime=", "minbuf=",

   "assert_write_lba=", "fifo_start_at=", "dev_translation=",
   "drive_scsi_dev_family=", "fallback_program=", "modesty_on_drive=",
   "tao_to_sao_tsize=", 
   
   "direct_write_amount=", "msifile=",

   ""
 };
 static char ignored_full_options[][41]= {
   "-d", "-Verbose", "-V", "-silent", "-s", "-setdropts", "-prcap",
   "-reset", "-abort", "-overburn", "-ignsize", "-useinfo",
   "-fix", "-nofix",
   "-raw", "-raw96p", "-raw16",
   "-clone", "-text",
   "-cdi", "-preemp", "-nopreemp", "-copy", "-nocopy",
   "-scms", "-shorttrack", "-noshorttrack", "-packet", "-noclose",
   "-media-info", "-minfo",
   "-load", "-lock", "-raw96r", "-sao", "-dao", "-swab",
   "-tao", "-force", "-format",

   "--adjust_speed_to_drive", "--allow_emulated_drives", "--allow_setuid",
   "--allow_untested_media", "--any_track", "--demand_a_drive", 
   "--fifo_disable", "--fifo_start_empty", "--fill_up_media",
   "--list_ignored_options", "--no_rc", "--no_convert_fs_adr",
   "--prodvd_cli_compatible", "--single_track", 
   "--tell_media_space",

   ""
 };

static char blank_help[][80]= {
"Blanking options:",
"\tall\t\tblank the entire disk",
"\tdisc\t\tblank the entire disk",
"\tdisk\t\tblank the entire disk",
"\tfast\t\tminimally blank the entire disk",
"\tminimal\t\tminimally blank the entire disk",
"\tas_needed\tblank or format media to make it ready for (re-)use",
"\tdeformat\t\tblank a formatted DVD-RW",
"\tdeformat_quickest\tminimally blank a formatted DVD-RW to DAO only",
"\tformat_overwrite\tformat a DVD-RW to \"Restricted Overwrite\"",
"@End_of_helptexT@"
};

 strcpy(mem_report_about_text, xorriso->report_about_text);
 mem_do_close= xorriso->do_close;

 track_source[0]= 0;
 dev_adr[0]= 0;
 blank_mode[0]= 0;
 speed[0]= 0;

 if(xorriso->in_drive_handle != NULL) {
   ret= Xorriso_option_dev(xorriso, "", 1|32); /* give up indev */
   if(ret!=1)
     return(ret);
 }


 /* Assess plan, make settings */
 for(i= 0; i<argc; i++) {
   sprintf(xorriso->info_text, "-as %s: %s",
           whom, Text_shellsafe(argv[i], sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);

   for(k=0;ignored_partial_options[k][0]!=0;k++) {
     if(argv[i][0]=='-')
       if(strncmp(argv[i]+1,ignored_partial_options[k],
                            strlen(ignored_partial_options[k]))==0)
         goto no_volunteer;
     if(strncmp(argv[i],ignored_partial_options[k],
                        strlen(ignored_partial_options[k]))==0)
       goto no_volunteer;
   }
   for(k=0;ignored_full_options[k][0]!=0;k++)
     if(strcmp(argv[i],ignored_full_options[k])==0)
       goto no_volunteer;
   if(0) {
no_volunteer:;
     sprintf(xorriso->info_text, "-as %s: Ignored option %s",
             whom, Text_shellsafe(argv[i], sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 continue;
   }

   if(strcmp(argv[i], "-atip")==0) {
     do_atip= 1;
   } else if(strcmp(argv[i], "-audio")==0) {
     sprintf(xorriso->info_text, "-as %s: Option -audio not supported.", whom);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   } else if(strncmp(argv[i], "-blank=", 7)==0 ||
             strncmp(argv[i], "blank=", 6)==0) {
     cpt= strchr(argv[i], '=')+1;
     if(strcmp(cpt,"all")==0 || strcmp(cpt,"disc")==0
        || strcmp(cpt,"disk")==0) {
       strcpy(blank_mode, "all");
     } else if(strcmp(cpt,"fast")==0 || strcmp(cpt,"minimal")==0) {
       strcpy(blank_mode, "fast");
     } else if(strcmp(cpt,"help")==0) {
       strcpy(blank_mode, "help");
     } else if(strcmp(cpt,"deformat")==0 ||
               strcmp(cpt,"deformat_sequential")==0 ||
               strcmp(cpt,"deformat_quickest")==0 ||
               strcmp(cpt,"deformat_sequential_quickest")==0) {
       strcpy(blank_mode, cpt);
     } else if(strcmp(cpt,"format_overwrite")==0) {
       strcpy(blank_mode, "format_overwrite");
     } else if(strcmp(cpt,"as_needed")==0) {
       strcpy(blank_mode, "as_needed");
     } else {
       sprintf(xorriso->info_text,
               "-as %s: blank=%s not supported. See blank=help .",
               whom, Text_shellsafe(argv[i], sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   } else if(strcmp(argv[i], "-checkdrive")==0) {
     do_checkdrive= 1;
   } else if(strcmp(argv[i], "-data")==0) {
     /* ok */;
   } else if(strncmp(argv[i], "-dev=", 5)==0 ||
             strncmp(argv[i], "dev=", 4)==0) {
     cpt= strchr(argv[i], '=')+1;
     strcpy(dev_adr, cpt);
   } else if(strcmp(argv[i], "--devices")==0) {
     do_scanbus= 2;
   } else if(strncmp(argv[i],"driveropts=", 11)==0 ||
             strncmp(argv[i],"-driveropts=", 12)==0) {
     if(strcmp(argv[i]+11, "help")==0) {
       fprintf(stderr,"Driver options:\n");
       fprintf(stderr,
               "burnfree\tPrepare writer to use BURN-Free technology\n");
     } 
   } else if(strcmp(argv[i], "-dummy")==0) {
     xorriso->do_dummy= 1;
   } else if(strcmp(argv[i], "-eject")==0) {
     do_eject= 1;
   } else if(strncmp(argv[i], "-fs=", 4)==0 || strncmp(argv[i], "fs=", 3)==0) {
     cpt= strchr(argv[i], '=')+1;
     ret= Xorriso_option_fs(xorriso, cpt, 0);
     if(ret<=0)
       goto ex;
   } else if(strcmp(argv[i], "--grow_overwriteable_iso")==0) {
     do_grow= 1;
   } else if(strcmp(argv[i], "-help")==0) {
     do_help= 1;
   } else if(strcmp(argv[i], "-isosize")==0) {
     do_isosize= 1;
   } else if(strcmp(argv[i], "-inq")==0) {
     do_checkdrive= 2;
   } else if(strcmp(argv[i], "-mode2")==0) {
     Xorriso_msgs_submit(xorriso, 0,
                     "Defaulting option -mode2 to option -data", 0, "NOTE", 0);
   } else if(strcmp(argv[i], "-msinfo")==0) {
     do_msinfo= 1;
   } else if(strcmp(argv[i], "-multi")==0) {
     do_multi= 1;
   } else if(strcmp(argv[i], "-nopad")==0) {
     xorriso->padding= 0;
   } else if(strcmp(argv[i], "-pad")==0) {
     xorriso->padding= 15*2048;
   } else if(strncmp(argv[i], "-padsize=", 9)==0 ||
             strncmp(argv[i], "padsize=", 8)==0) {
     cpt= strchr(argv[i], '=')+1;
     ret= Xorriso_option_padding(xorriso, cpt, 0);
     if(ret<=0)
       goto ex;
   } else if(strcmp(argv[i], "-scanbus")==0) {
     sprintf(xorriso->info_text, "-as %s: Option -scanbus not supported.",
             whom);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;

/*     do_scanbus= 1; */
   } else if(strncmp(argv[i], "-speed=", 7)==0 ||
             strncmp(argv[i], "speed=", 6)==0) {
     cpt= strchr(argv[i], '=')+1;
     strncpy(speed, cpt, 79);
     speed[79]= 0;

   } else if(strncmp(argv[i], "-stream_recording=", 18)==0 ||
             strncmp(argv[i], "stream_recording=", 17)==0) {
     cpt= strchr(argv[i], '=')+1;
     Xorriso_option_stream_recording(xorriso, cpt, 0);

   } else if(strncmp(argv[i], "-dvd_obs=", 9)==0 ||
             strncmp(argv[i], "dvd_obs=", 8)==0) {
     cpt= strchr(argv[i], '=') + 1;
     Xorriso_option_dvd_obs(xorriso, cpt, 0);

   } else if(strncmp(argv[i], "-stdio_sync=", 12)==0 ||
             strncmp(argv[i], "stdio_sync=", 11)==0) {
     cpt= strchr(argv[i], '=') + 1;
     Xorriso_option_stdio_sync(xorriso, cpt, 0);

   } else if(strcmp(argv[i], "-toc")==0 || strcmp(argv[i], "--long_toc")==0) {
     do_toc= 1;
   } else if(strncmp(argv[i], "-tsize=", 7)==0 ||
             strncmp(argv[i], "tsize=", 6)==0) {
     cpt= strchr(argv[i], '=')+1;
     tsize= Scanf_io_size(cpt, 1);
     if(tsize > 1024.0*1024.0*1024.0*1024.0*1024.0) {
       sprintf(xorriso->info_text, "-as %s: much too large: %s",whom, argv[i]);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i],"-verbose")==0) {
     do_verbous++;
   } else if(strcmp(argv[i], "-vv")==0) {
     do_verbous+= 2;
   } else if(strcmp(argv[i], "-vvv")==0) {
     do_verbous+= 3;
   } else if(strcmp(argv[i], "-version")==0) {
     do_version= 1;
   } else if(strcmp(argv[i], "-waiti")==0) {
     do_waiti= 1;
   } else if(strncmp(argv[i], "write_start_address=", 20)==0) {
     write_start_address= Scanf_io_size(argv[i]+20,0);
   } else if(strcmp(argv[i], "-xa")==0) {
     Xorriso_msgs_submit(xorriso, 0,
                        "Defaulting option -xa to option -data", 0, "NOTE", 0);
   } else if(strcmp(argv[i], "-xa1")==0) {
     if(do_xa1 == 0)
       do_xa1= 1;
   } else if(strcmp(argv[i], "--xa1-ignore")==0) {
     do_xa1= -1;
   } else if(strcmp(argv[i], "-xa2")==0) {
     Xorriso_msgs_submit(xorriso, 0,
                       "Defaulting option -xa2 to option -data", 0, "NOTE", 0);
   } else if(strcmp(argv[i], "-xamix")==0) {
     Xorriso_msgs_submit(xorriso, 0,
   "Option -xamix not implemented and data not yet convertible to other modes",
                         0, "FATAL", 0);
     ret= 0; goto ex;
   } else if(argv[i][0]=='-' && argv[i][1]!=0) {
     sprintf(xorriso->info_text, "-as %s: Unknown option %s",
             whom, Text_shellsafe(argv[i], sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   } else {
     if(track_source[0]) {
       sprintf(xorriso->info_text, "-as %s: Surplus track source %s",
               whom, Text_shellsafe(argv[i], sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       sprintf(xorriso->info_text, "First and only track source is %s",
               Text_shellsafe(track_source, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
       ret= 0; goto ex;
     }
     if(Sfile_str(track_source, argv[i], 0)<=0)
       {ret= -1; goto ex;}
   }
 }

 /* Perform actions */
 Xorriso_option_report_about(xorriso, "NOTE", 0);
 if(do_version) {
   sprintf(xorriso->result_line, "Cdrecord 2.01-Emulation Copyright (C) 2010 see libburnia-project.org xorriso\n");
   Xorriso_result(xorriso, 1);
   Xorriso_option_version(xorriso, 0);
   ret= 1; goto ex;
 }
 if(do_waiti) {
   sprintf(xorriso->info_text,
       "xorriso: Option -waiti pauses program until input appears at stdin\n");
   Xorriso_info(xorriso,0);
   sprintf(xorriso->result_line, "Waiting for data on stdin...\n");
   Xorriso_result(xorriso, 1);
   for(ret= 0; ret==0; )
     ret= Wait_for_input(0,1000000,0);
   if(ret<0 || feof(stdin)) {
     Xorriso_msgs_submit(xorriso, 0,
                    "stdin produces exception rather than data", 0, "NOTE", 0);
   }
   sprintf(xorriso->info_text, "xorriso: Option -waiti pausing is done.\n");
 }
 if(dev_adr[0]) {
   hflag= 2 | 32 | 64;
   if(!do_grow)
     hflag|= 8; /* consider overwriteables as blank */
   ret= Xorriso_option_dev(xorriso, dev_adr, hflag);
   if(ret<=0)
     goto ex;
 }

 if(do_help) {
   Xorriso_cdrskin_help(xorriso, 0);
   ret= 1; goto ex;
 }
 if(do_scanbus) {
   if(do_scanbus==1)
     /* >>> would need -scanbus compatible output and input format */;
   else
     Xorriso_option_devices(xorriso, 0);
   ret= 1; goto ex;
 }
 if(strcmp(blank_mode, "help")==0) {
   for(i= 0; strcmp(blank_help[i], "@End_of_helptexT@")!=0; i++) {
     sprintf(xorriso->info_text, "%s\n", blank_help[i]);
     Xorriso_info(xorriso,0);
   }
   ret= 1; goto ex;
 }

 if(!(do_checkdrive || do_atip || do_toc || blank_mode[0] || track_source[0] ||
      do_eject || do_msinfo))
   {ret= 1; goto ex;}

 if(xorriso->out_drive_handle==NULL) {
   sprintf(xorriso->info_text, "-as %s: No output drive selected", whom);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }

 if(do_msinfo) {
   ret= Xorriso_msinfo(xorriso, &msc1, &msc2, 2 | !!do_grow);
   if(ret<=0)
     goto ex;
   sprintf(xorriso->result_line, "%d,%d\n", msc1, msc2);
   Xorriso_result(xorriso, 1);
 }

 if(speed[0]) {
   ret= Xorriso_option_speed(xorriso, speed, 0);
   if(ret<=0)
     goto ex;
 }

 if(do_verbous<=0)
   report_about= "SORRY";
 else if(do_verbous<=2)
   report_about= "UPDATE";
 else if(do_verbous==3)
   report_about= "DEBUG";
 else
   report_about= "ALL";
 Xorriso_option_report_about(xorriso, report_about, 0);

 if(do_checkdrive) {
   ret= Xorriso_atip(xorriso, 2-(do_checkdrive==2));
   if(ret<=0)
     goto ex;
 }
 if(do_atip) {
   ret= Xorriso_atip(xorriso, 0);
   if(ret<=0)
     goto ex;
 }
 if(do_toc) {
   ret= Xorriso_option_toc(xorriso, 0);
   if(ret<=0)
     goto ex;
 }
 if(strcmp(blank_mode, "format_overwrite")==0) {
   ret= Xorriso_option_blank(xorriso, "fast", 1);
   if(ret<=0)
     goto ex;
 } else if(blank_mode[0]) {
   ret= Xorriso_option_blank(xorriso, blank_mode, 0);
   if(ret<=0)
     goto ex;
 }
 if(track_source[0]) {
   xorriso->do_close= !do_multi;
   ret= Xorriso_burn_track(xorriso, (off_t) write_start_address,
                           track_source, (off_t) tsize,
                   (!!do_grow) | ((!!do_isosize) << 1) | ((do_xa1 == 1) << 2));
   aq_ret= Xorriso_reaquire_outdev(xorriso, 2*(ret>0));
   if(ret<=0 && ret<aq_ret)
     goto ex;
   if(aq_ret<=0)
     {ret= aq_ret; goto ex;}
 }

 ret= 1;
ex:;
 if(do_eject && ret>=0) {
   eject_ret= Xorriso_option_eject(xorriso, "out", 0);
   if(eject_ret<ret)
     ret= eject_ret;
 }
 if(ret<=0) {
   sprintf(xorriso->info_text, "-as %s: Job could not be performed properly.",
           whom);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 }
 Xorriso_option_report_about(xorriso, mem_report_about_text, 0);
 xorriso->do_close= mem_do_close;
 return(ret);
}


/* @param flag bit0= do not report eventual ignore decision
*/
int Xorriso_genisofs_ignore(struct XorrisO *xorriso, char *whom,
                            char **argv, int *i, int flag)
{
 /* mkisofs 2.01 options which are not scheduled for implementation, yet */
 static char ignored_arg0_options[][41]= {
   "-allow-leading-dots", "-ldots", "-allow-lowercase", "-allow-multidot",
   "-cache-inodes", "-no-cache-inodes", "-check-oldnames", "-d", "-D",
   "-joliet-long", "-l", "-L", "-max-iso9660-filenames", "-N", "-nobak",
   "-no-bak", "-force-rr", "-r", "-relaxed-filenames", "-T", "-U",
   "-no-iso-translate",
   ""
 };
 static char ignored_arg1_options[][41]= {
   "-biblio", "-check-session", "-p", "-root",
   "-old-root", "-table-name", "-volset-seqno", "-volset-size",
   ""
 };
 int k, idx_offset= 0;
 char sfe[5*SfileadrL];

 for(k=0;ignored_arg0_options[k][0]!=0;k++)
   if(strcmp(argv[*i],ignored_arg0_options[k])==0)
     goto no_volunteer;
 for(k=0;ignored_arg1_options[k][0]!=0;k++)
   if(strcmp(argv[*i],ignored_arg1_options[k])==0) {
     (*i)++;
     idx_offset= -1;
     goto no_volunteer;
 }
 return(0);
no_volunteer:;
 sprintf(xorriso->info_text, "-as %s: Ignored option %s",
         whom, Text_shellsafe(argv[(*i)+idx_offset], sfe, 0));
 if(!(flag & 1))
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 return(1);
}


int Xorriso_genisofs_help(struct XorrisO *xorriso, int flag)
{
 static char helptext[][80]= {
"Usage: xorriso -as mkisofs [options] file...",
"Note: This is not mkisofs. See xorriso -help, xorriso -version, man xorriso",
"Options:",
"  -f, -follow-links           Follow symbolic links",
"  -graft-points               Allow to use graft points for filenames",
"  -help                       Print option help",
"  -input-charset CHARSET      Local input charset for file name conversion",
"  -output-charset CHARSET     Output charset for file name conversion",
"  -iso-level LEVEL            Set ISO9660 conformance level (1..3)",
"  -J, -joliet                 Generate Joliet directory information",
"  -o FILE, -output FILE       Set output file name",
"  -m GLOBFILE, -exclude GLOBFILE",
"                              Exclude file name",
"  -exclude-list FILE          File with list of file names to exclude",
"  -pad                        Pad output by 300k (default)",
"  -no-pad                     Do not pad output",
"  -M FILE, -prev-session FILE Set path to previous session to merge",
"  -C PARAMS, -cdrecord-params PARAMS",
"                              Magic paramters from cdrecord",
"  -path-list FILE             File with list of pathnames to process",
"  --quoted_path_list FILE     File with list of quoted pathnames to process",
"  -print-size                 Print estimated filesystem size and exit",
"  -quiet                      Run quietly",
"  -R, -rock                   Generate Rock Ridge directory information",
"  --hardlinks                 Record eventual hard link relations of files",
"  --acl                       Record eventual ACLs of files",
"  --xattr                     Record eventual user space xattr of files",
"  --md5                       Compute and record MD5 checksums of data files",
"  --scdbackup_tag PATH NAME   With --md5 record a scdbackup checksum tag",
"  --for_backup                Use all options which improve backup fidelity",
"  -V ID, -volid ID            Set Volume ID",
"  -volset ID                  Set Volume set ID",
"  -publisher PUB              Set Volume publisher",
"  -A ID, -appid ID            Set Application ID",
"  -sysid ID                   Set System ID",
"  -b FILE, -eltorito-boot FILE",
"                              Set El Torito boot image name",
"  -c FILE, -eltorito-catalog FILE",
"                              Set El Torito boot catalog name",
"  -boot-load-size #           Set numbers of load sectors",
"  -no-emul-boot               Boot image is 'no emulation' image",
"  -boot-info-table            Patch boot image with info table",
"  isolinux_mbr=on|auto|off    Control eventual isohybrid MBR generation",
"  --stdio_sync on|off|number  Control forced output to disk files",
"  -z, -transparent-compression",
"                              Enable transparent compression of files",
"  -v, -verbose                Verbose",
"  -version                    Print the current version",
"@End_of_helptexT@"
};
 char ra_text[80];
 int i;

 strcpy(ra_text, xorriso->report_about_text);

 Xorriso_option_report_about(xorriso, "NOTE", 0);
 for(i= 0; strcmp(helptext[i], "@End_of_helptexT@")!=0; i++) {
   sprintf(xorriso->info_text, "%s\n", helptext[i]);
   Xorriso_info(xorriso, 1);
 }
 Xorriso_option_report_about(xorriso, ra_text, 0);
 return(1);
}


/* micro emulation of mkisofs */
int Xorriso_genisofs(struct XorrisO *xorriso, char *whom,
                     int argc, char **argv, int flag)
{
 int ret, i, was_path= 0, was_other_option= 0, mem_graft_points, mem;
 int do_print_size= 0, fd, idx, iso_level= 0, no_emul_boot= 0;
 int option_b= 0, was_failure= 0, fret;
 char sfe[5*SfileadrL], adr[SfileadrL+8], ra_text[80], pathspec[2*SfileadrL];
 char *ept, *add_pt, eff_path[SfileadrL], indev[SfileadrL+8], msc[80], *cpt;

 strcpy(ra_text, xorriso->report_about_text);

 adr[0]= indev[0]= msc[0]= 0;
 for(i= 0; i<argc; i++) {
   ret= Xorriso_genisofs_ignore(xorriso, whom, argv, &i, 1);
   if(ret == 1)
 continue;
   if(strcmp(argv[i], "-version")==0) {
     sprintf(xorriso->result_line,
"mkisofs 2.01-Emulation Copyright (C) 2010 see libburnia-project.org xorriso\n"
            );
     fd= xorriso->dev_fd_1;
     if(fd<0)
       fd= 1;
     write(fd, xorriso->result_line, strlen(xorriso->result_line));
     fsync(fd);
     Xorriso_option_version(xorriso, 0);

   } else if(strcmp(argv[i], "-o")==0 || strcmp(argv[i], "-output")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     adr[0]= 0;
     if(strcmp(argv[i],"-")!=0 && strncmp(argv[i], "stdio:", 6)!=0)
       strcpy(adr, "stdio:");
     if(Sfile_str(adr+strlen(adr), argv[i], 0)<=0)
       {ret= -1; goto ex;}
   } else if(strcmp(argv[i], "-M")==0  || strcmp(argv[i], "-dev")==0 ||
             strcmp(argv[i], "-prev-session")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     if(strncmp(argv[i], "stdio:", 6)!=0)
       strcpy(indev, "stdio:");
     if(Sfile_str(indev+strlen(indev), argv[i], 0)<=0)
       {ret= -1; goto ex;}
   } else if(strcmp(argv[i], "-C")==0 ||
             strcmp(argv[i], "-cdrecord-params")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     strncpy(msc, argv[i], sizeof(msc)-1);
     msc[sizeof(msc)-1]= 0;
   } else if(strcmp(argv[i], "-help")==0) {
     Xorriso_genisofs_help(xorriso, 0);
   } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "-verbose")==0) {
     strcpy(ra_text, "UPDATE");
   } else if(strcmp(argv[i], "-quiet")==0) {
     strcpy(ra_text, "SORRY");
   } else if(strcmp(argv[i], "-f")==0 || strcmp(argv[i], "-follow-links")==0) {
     ret= Xorriso_option_follow(xorriso, "on", 0);
     if(ret<=0)
       goto problem_handler_1;
   } else if(strcmp(argv[i], "-iso-level")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     sscanf(argv[i], "%d", &iso_level);
     if(iso_level < 1 || iso_level > 3) {
       sprintf(xorriso->info_text,
               "-as %s: unsupported -iso-level '%s' (use one of: 1,2,3)",
               whom, argv[i]);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto problem_handler_1;
     }
     if(iso_level < 3)
       xorriso->file_size_limit=
                          ((off_t) 4) * ((off_t) 1024*1024*1024) - ((off_t) 1);
     else
       xorriso->file_size_limit= 0;
   } else if(strcmp(argv[i], "-no-emul-boot")==0) {
     no_emul_boot= 1;
   } else if(strcmp(argv[i], "-boot-info-table")==0) {
     ;
   } else if(strcmp(argv[i], "-b") == 0 ||
             strcmp(argv[i], "-eltorito-boot") == 0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     xorriso->boot_image_bin_path[0]= 0;
     if(argv[i][0] != '/')
       strcat(xorriso->boot_image_bin_path, "/");
     ret= Sfile_str(xorriso->boot_image_bin_path
                    + strlen(xorriso->boot_image_bin_path), argv[i], 0);
     if(ret <= 0)
       goto ex;
     option_b= 1;
     xorriso->keep_boot_image= 0;
     xorriso->patch_isolinux_image= 0;
   } else if(strcmp(argv[i], "-c") == 0 ||
             strcmp(argv[i], "-eltorito-catalog") == 0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     xorriso->boot_image_cat_path[0]= 0;
     if(argv[i][0] != '/')
       strcat(xorriso->boot_image_cat_path, "/");
     ret= Sfile_str(xorriso->boot_image_cat_path
                    + strlen(xorriso->boot_image_cat_path), argv[i], 0);
     if(ret <= 0)
       goto ex;
   } else if(strcmp(argv[i], "-boot-load-size") == 0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     sscanf(argv[i], "%d", &ret);
     xorriso->boot_image_load_size= ret * 512;
   } else if(strncmp(argv[i], "isolinux_mbr=", 13)==0) {
     sprintf(sfe, "isohybrid=%s", argv[i] + 13);
     ret= Xorriso_option_boot_image(xorriso, "isolinux", sfe, 0);
     if(ret <= 0)
       goto problem_handler_1;
   } else if(strcmp(argv[i], "-input-charset")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     /* -local_charset */
     if(strcmp(argv[i], "default") == 0)
       ret= Xorriso_option_charset(xorriso, "ISO-8859-1", 4);
     else
       ret= Xorriso_option_charset(xorriso, argv[i], 4);
     if(ret <= 0)
       goto problem_handler_1;
   } else if(strcmp(argv[i], "-output-charset")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     /* -charset */
     if(strcmp(argv[i], "default") == 0)
       ret= Xorriso_option_charset(xorriso, "ISO-8859-1", 3);
     else
       ret= Xorriso_option_charset(xorriso, argv[i], 3);
     if(ret <= 0)
       goto problem_handler_1;
   } else if(strcmp(argv[i], "--hardlinks")==0) {
     Xorriso_option_hardlinks(xorriso, "on", 0);
   } else if(strcmp(argv[i], "--acl")==0) {
     Xorriso_option_acl(xorriso, "on", 0);
   } else if(strcmp(argv[i], "--xattr")==0) {
     Xorriso_option_xattr(xorriso, "on", 0);
   } else if(strcmp(argv[i], "--md5")==0) {
     Xorriso_option_md5(xorriso, "on", 0);
   } else if(strcmp(argv[i], "--scdbackup_tag")==0) {
     if(i + 2 >= argc)
       goto not_enough_args;
     i+= 2;
     ret= Xorriso_option_scdbackup_tag(xorriso, argv[i-1], argv[i], 0);
     if(ret <= 0)
       goto problem_handler_1;
   } else if(strcmp(argv[i], "--for_backup")==0) {
     Xorriso_option_hardlinks(xorriso, "on", 0);
     Xorriso_option_acl(xorriso, "on", 0);
     Xorriso_option_xattr(xorriso, "on", 0);
     Xorriso_option_md5(xorriso, "on", 0);
   } else if(strcmp(argv[i], "-z")==0 ||
             strcmp(argv[i], "-transparent-compression")==0) {
     Xorriso_option_zisofs(xorriso, "by_magic=on", 0);
   } else if(strcmp(argv[i], "--stdio_sync")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     Xorriso_option_stdio_sync(xorriso, argv[i], 0);
   } else
     was_other_option= 1;

 continue; /* regular bottom of loop */
problem_handler_1:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 Xorriso_option_report_about(xorriso, ra_text, 0);
 if(adr[0]) {
   if(strncmp(adr, "stdio:", 6)==0 && strncmp(adr, "stdio:/dev/fd/", 14)!=0) {
     ret= Sfile_type(adr+6, 1);
     if(ret==-1) {
       /* ok */;
     } else if(ret==2 || ret==3) {
       sprintf(xorriso->info_text,
               "-as %s: Cannot accept %s as target: -o %s",
               whom, (ret==3 ? "symbolic link" : "directory"),
               Text_shellsafe(adr+6, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   }
   /* Regard overwriteable as blank, truncate regular files on write start */
   ret= Xorriso_option_dev(xorriso, adr, 2|8|16);
   if(ret<=0)
     goto ex;
 }
 if(option_b && !no_emul_boot) {
   xorriso->boot_image_bin_path[0]= 0;
   sprintf(xorriso->info_text,
        "-as %s: Option -b is supported only if option -no-emul-boot is given",
        whom);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }
 if(was_other_option && xorriso->out_drive_handle==NULL) {
   ret= Xorriso_option_dev(xorriso, "-", 2|4); /* set outdev to stdout */
   if(ret<=0)
     return(ret);
 }

 if(msc[0]) {
   cpt= strchr(msc, ',');
   if(cpt==NULL) {
illegal_c:;
     sprintf(xorriso->info_text,
             "-as %s: unusable parameter with option -C: %s",
             whom, Text_shellsafe(msc, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     {ret= 0; goto ex;}
   } else if(cpt==msc || msc[1]==0)
     goto illegal_c;
   strncpy(sfe, msc, cpt-msc);
   sfe[cpt-msc]= 0;
   if(xorriso->in_drive_handle!=NULL && indev[0]) {
     /* give up indev before setting the load address */
     ret= Xorriso_option_dev(xorriso, "", 1);
     if(ret<=0)
       return(ret);
   }
   /* growisofs submits msc1+16 to avoid a theoretical bug in mkisofs.
      Therefore this bug has to be emulated here. Sigh.
   */
   ret= Xorriso_option_load(xorriso, "sbsector", sfe, 1);
   if(ret<=0)
     return(ret);
   ret= Xorriso_option_grow_blindly(xorriso, cpt+1, 0);
   if(ret<=0)
     return(ret);
 }
 if(indev[0]) {
   ret= Xorriso_option_dev(xorriso, indev, 1);
   if(ret<=0)
     goto ex;
 }

 if(!was_other_option)
   {ret= 1; goto ex;}

 xorriso->padding= 300*1024;

 for(i= 0; i<argc; i++) {
   sprintf(xorriso->info_text, "-as %s: %s",
           whom, Text_shellsafe(argv[i], sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
   ret= Xorriso_genisofs_ignore(xorriso, whom, argv, &i, 0);
   if(ret == 1)
 continue;
   if(strcmp(argv[i], "-version")==0) {
     /* was already handled in first argument scan */;

   } else if(strcmp(argv[i], "-R")==0 || strcmp(argv[i], "-rock")==0) {
     /* ok */;
   } else if(strcmp(argv[i], "-J")==0 || strcmp(argv[i], "-joliet")==0) {
     xorriso->do_joliet= 1;
   } else if(strcmp(argv[i], "-graft-points")==0) {
     xorriso->allow_graft_points= 1;
   } else if(strcmp(argv[i], "-path-list")==0 ||
             strcmp(argv[i], "--quoted_path_list")==0) {
     if(i+1>=argc) {
not_enough_args:;
       sprintf(xorriso->info_text, "-as %s: Not enough arguments to option %s",
               whom, argv[i]);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
     i++;
     was_path= 1;
     xorriso->pacifier_style= 1;
     ret= Xorriso_option_path_list(xorriso, argv[i],
                                 (strcmp(argv[i-1], "--quoted_path_list")==0));
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-f")==0 || strcmp(argv[i], "-follow-links")==0) {
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-pad")==0) {
     xorriso->padding= 300*1024;
   } else if(strcmp(argv[i], "-no-pad")==0) {
     xorriso->padding= 0;
   } else if(strcmp(argv[i], "-print-size")==0) {
     do_print_size= 1;
   } else if(strcmp(argv[i], "-o")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-M")==0  || strcmp(argv[i], "-dev")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-C")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-help")==0) {
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-V")==0 || strcmp(argv[i], "-volid")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     ret= Xorriso_option_volid(xorriso, argv[i], 0);
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-volset")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     ret= Xorriso_option_volid(xorriso, argv[i], 0);
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-P")==0 || strcmp(argv[i], "-publisher")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     ret= Xorriso_option_publisher(xorriso, argv[i], 0);
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-A")==0 || strcmp(argv[i], "-appid")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     ret= Xorriso_option_application_id(xorriso, argv[i], 0);
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-sysid")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     ret= Xorriso_option_system_id(xorriso, argv[i], 0);
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-m")==0 || strcmp(argv[i], "-exclude")==0 ||
             strcmp(argv[i], "-x")==0 || strcmp(argv[i], "-old-exclude")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     mem= xorriso->do_disk_pattern;
     xorriso->do_disk_pattern= 1;
     if(strchr(argv[i], '/')!=NULL) {
       idx= i;
       ret= Xorriso_option_not_paths(xorriso, i+1, argv, &idx, 0);
     } else
       ret= Xorriso_option_not_leaf(xorriso, argv[i], 0);
     xorriso->do_disk_pattern= mem;
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-exclude-list")==0) {
     if(i+1>=argc)
       goto not_enough_args;
     i++;
     mem= xorriso->do_disk_pattern;
     xorriso->do_disk_pattern= 1;
     ret= Xorriso_option_not_list(xorriso, argv[i], 0);
     xorriso->do_disk_pattern= mem;
     if(ret<=0)
       goto problem_handler_2;
   } else if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "-quiet")==0) {
     /* was already handled in first argument scan */;

   } else if(strcmp(argv[i], "-iso-level")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-no-emul-boot")==0) {
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-b") == 0 ||
             strcmp(argv[i], "-eltorito-boot") == 0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-c") == 0 ||
             strcmp(argv[i], "-eltorito-catalog") == 0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strncmp(argv[i], "isolinux_mbr=", 13)==0) {
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-boot-load-size") == 0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-boot-info-table")==0) {
     ;
   } else if(strcmp(argv[i], "-input-charset")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "-output-charset")==0) {
     i++;
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "--hardlinks")==0 ||
             strcmp(argv[i], "--acl")==0 ||
             strcmp(argv[i], "--xattr")==0 ||
             strcmp(argv[i], "--md5")==0 ||
             strcmp(argv[i], "--for_backup")==0) {
     /* was already handled in first argument scan */;
   } else if(strcmp(argv[i], "--scdbackup_tag")==0) {
     /* was already handled in first argument scan */;
     i+= 2;
   } else if(strcmp(argv[i], "-z")==0 ||
             strcmp(argv[i], "-transparent-compression")==0) {
     /* was already handled in first argument scan */;
   } else if(argv[i][0]=='-' && argv[i][1]!=0) {
     sprintf(xorriso->info_text, "-as %s: Unknown option %s",
             whom, Text_shellsafe(argv[i], sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   } else {
     int zero= 0;

     /* implementing mkisofs tendency to map single-path pathspecs to / */
     if((!xorriso->allow_graft_points) || 
        Fileliste__target_source_limit(argv[i], '=', &ept, 0)<=0) {
       ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, argv[i],
                                       eff_path, 2|4);
       if(ret<=0)
         goto problem_handler_2;
       ret= Sfile_type(eff_path,
                  1|((xorriso->do_follow_param||xorriso->do_follow_links)<<2));
       if(ret==2) {
         strcpy(pathspec, "/=");
       } else {
         pathspec[0]= '/';
         pathspec[1]= 0;
         ret= Sfile_leafname(eff_path, pathspec+1, 0);
         if(ret>0)
           strcat(pathspec, "=");
         else
           pathspec[0]= 0;
       }
       strcat(pathspec, eff_path);
       add_pt= pathspec;
     } else
       add_pt= argv[i];
     mem_graft_points= xorriso->allow_graft_points;
     xorriso->allow_graft_points= 1;
     ret= Xorriso_option_add(xorriso, 1, &add_pt, &zero, was_path<<1);
     xorriso->allow_graft_points= mem_graft_points;
     if(ret<=0)
       goto problem_handler_2;
     was_path= 1;
     xorriso->pacifier_style= 1;
   }
 continue; /* regular bottom of loop */
problem_handler_2:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 if(do_print_size) {
   ret= Xorriso_option_print_size(xorriso, 1);
   if(ret<=0)
     goto ex;
 }

 ret= !was_failure;
ex:;
 if(was_path && !do_print_size)
   Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1);
 if(do_print_size && xorriso->volset_change_pending)
   Xorriso_option_rollback(xorriso, 0);
 return(ret);
}


int Xorriso_as_genisofs(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int end_idx, ret, idx_count, old_idx;

 old_idx= *idx;
 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 (*idx)= end_idx;
 idx_count= end_idx-old_idx;
 if(end_idx<=0 || old_idx>=argc)
   return(1);
 ret= Xorriso_genisofs(xorriso, "genisofs", end_idx-old_idx, argv+old_idx, 0);
 return(ret);
}


int Xorriso_as_cdrskin(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int end_idx, ret, idx_count, old_idx;

 old_idx= *idx;
 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 (*idx)= end_idx;
 idx_count= end_idx-old_idx;
 if(end_idx<=0 || old_idx>=argc)
   return(1);
 ret= Xorriso_cdrskin(xorriso, "cdrskin", end_idx-old_idx, argv+old_idx, 0);
 return(ret);
}


/* @param boss_iter Opaque handle to be forwarded to actions in ISO image
                    Set to NULL if calling this function from outside ISO world
   @param flag      bit0= widen hardlink sibling:
                          Do not call Xorriso_hardlink_update()
                          Overwrite exactly if normal mode would not,
                          else do nothing
                    bit2= -follow: this is not a command parameter 
   @return <=0 error, 1= ok , 2= iso_rr_path node object has been deleted ,
                      3= no action taken
*/
int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
                               int compare_result, char *disk_path,
                               char *iso_rr_path, int flag)
{
 int ret, deleted= 0, is_split= 0, i, loop_count, late_hardlink_update= 0;
 char sfe[5*SfileadrL];
 struct stat stbuf;
 struct SplitparT *split_parts= NULL;
 int split_count= 0;
 char part_path[SfileadrL], *part_name;
 int partno, total_parts, new_total_parts;
 off_t offset, bytes, total_bytes, disk_size, first_bytes;

 if((compare_result&3)==3) {
   sprintf(xorriso->info_text, "Missing on disk and in ISO: disk_path %s",
           Text_shellsafe(disk_path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
   xorriso->find_compare_result= -1;
   ret= 3; goto ex;
 }

 if(compare_result&((1<<11)|(1<<13))) {
   if(flag & 1)
     {ret= 3; goto ex;}
   /* cannot open regular disk file, early eof of disk file */
   sprintf(xorriso->info_text, "Problems with reading disk file %s",
           Text_shellsafe(disk_path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
   xorriso->find_compare_result= -1;
   ret= 1; goto ex;
 }
 xorriso->info_text[0]= 0;
 is_split= !!(compare_result & (1<<17));

 if((!(xorriso->ino_behavior & 2)) && (compare_result & (2 | (3 << 21))) &&
    !(flag & 1)) {
   if(compare_result & 2) {
     /* File is not yet in image */
     late_hardlink_update= 1;
   } else {
     /* Hard link relation has changed resp. was not recorded. */
     ret= Xorriso_hardlink_update(xorriso, &compare_result,
                                  disk_path, iso_rr_path, flag & 4);
     if(ret < 0)
       goto ex;
     if(ret == 2)
       {ret= 1; goto ex;}
   }
 }

 if(compare_result&(8|64)) {
   /* file type, minor+major with device file */
   if(flag & 1)
     {ret= 3; goto ex;}
   ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */
   if(ret>0) {
     deleted= 1; 
     ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
                           (off_t) 0, (off_t) 0, 2|(flag&4));
   }
   sprintf(xorriso->info_text, "Deleted and re-added ");

 } else if(compare_result&(1)) {
delete:;
   /* disk_adr not existing */
   ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1);
   deleted= 1;
   sprintf(xorriso->info_text, "Deleted ");

 } else if(compare_result&(2|128|(1<<12)|(1<<14)|(1<<15))) {
   /* iso_adr not existing, size, cannot open iso file, early eof of iso file
      content bytes differ */

   if(flag & 1)
     {ret= 3; goto ex;}
overwrite:;
   if(is_split) {
     ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
                                 &split_parts, &split_count, &stbuf, 0);
     if(ret<=0)
       {ret= -1; goto ex;}  /* (should not happen) */
     ret= lstat(disk_path, &stbuf);
     if(ret==-1)
       goto delete;
     disk_size= stbuf.st_size;
     Splitparts_get(split_parts, 0, &part_name, &partno, &total_parts,
                    &offset, &first_bytes, &total_bytes, 0);
     new_total_parts= disk_size/first_bytes;
     if(disk_size % first_bytes)
       new_total_parts++;

     loop_count= split_count;
     /* If disk file grew over part limit and all parts are present:
        add new parts */
     if(new_total_parts > total_parts && split_count == total_parts)
       loop_count= new_total_parts;

     for(i= 0; i<loop_count; i++) {
       if(i<split_count) {
         /* Delete old part */
         Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
                       &offset, &bytes, &total_bytes, 0);
         strcpy(part_path, iso_rr_path);
         if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
           Xorriso_much_too_long(xorriso,
                                 strlen(iso_rr_path)+strlen(part_path)+1, 2);
           {ret= -1; goto ex;}
         }
         ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, part_path, 1);
         if(ret<=0)
           goto ex;
         deleted= 1;
       } else {
         partno= i+1;
         offset= i*first_bytes;
         bytes= first_bytes;
       }
       if(disk_size<=offset)
     continue;
       /* Insert new part */
       if(strlen(part_path)+160>SfileadrL) {
         Xorriso_much_too_long(xorriso, strlen(part_path)+160, 2);
         ret= 0; goto ex;
       }
       Splitpart__compose(part_path+strlen(iso_rr_path)+1, partno,
                          new_total_parts, offset, first_bytes, disk_size, 0);
       ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, part_path,
                             offset, bytes, 2|(flag&4)|8|128);
       if(ret<=0)
         goto ex;
     }
     /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */
     ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2 | 4);
     if(ret<=0)
       goto ex;
   } else {
     ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
                           (off_t) 0, (off_t) 0, 2|(flag&4));
     if(ret>0 && !(compare_result&2))
       deleted= 1;
   }
   if(late_hardlink_update) {
     /* Handle eventual hardlink siblings of newly created file */
     ret= Xorriso_hardlink_update(xorriso, &compare_result,
                                  disk_path, iso_rr_path, 1 | (flag & 4));
     if(ret < 0)
       goto ex;
   }
   if(flag & 1)
     sprintf(xorriso->info_text, "Widened hard link ");
   else
     sprintf(xorriso->info_text, "Added/overwrote ");

 } else if(compare_result&(4|16|32|256|512|1024|(1<<19)|(1<<20)|(1<<22))) {
   /* access permissions, user id, group id, mtime, atime, ctime, ACL, xattr,
      dev_ino missing */

   if(flag & 1)
     goto overwrite;

   if(is_split) {
     ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
                                 &split_parts, &split_count, &stbuf, 0);
     if(ret<=0)
       {ret= -1; goto ex;}  /* (should not happen) */
     for(i= 0; i<split_count; i++) {
       Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
                     &offset, &bytes, &total_bytes, 0);
       strcpy(part_path, iso_rr_path);
       if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
         Xorriso_much_too_long(xorriso,
                               strlen(iso_rr_path)+strlen(part_path)+1, 2);
         {ret= -1; goto ex;}
       }
       ret= Xorriso_copy_properties(xorriso, disk_path, part_path,
                                    4 * !(compare_result & (1<<21))); 
                             /* do not update eventually mismatching dev_ino */
       if(ret<=0)
         goto ex;
     }
     /* Copy file attributes to iso_rr_path, augment r-perms by x-perms */
     ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 2 | 4); 
     if(ret<=0)
       goto ex;
   } else
     ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 4); 
   sprintf(xorriso->info_text, "Adjusted attributes of ");

 } else if(flag & 1) {
     goto overwrite;
 } else
   ret= 1;
 if(ret>0 && xorriso->info_text[0]) {
   strcat(xorriso->info_text, Text_shellsafe(iso_rr_path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 }
 ret= 1;
ex:;
 if(split_parts!=NULL)
   Splitparts_destroy(&split_parts, split_count, 0);
 if(ret<=0)
   return(ret);
 if(deleted)
   return(2);
 return(ret);
}


int Xorriso_write_session_log(struct XorrisO *xorriso, int flag)
{
 FILE *fp= NULL;
 char sfe[5*SfileadrL], timetext[40], *rpt, *wpt;

 if(xorriso->session_logfile[0]==0)
   return(2);
 fp= fopen(xorriso->session_logfile, "a");
 if(fp==0) {
   sprintf(xorriso->info_text, "-session_log: Cannot open file %s",
           Text_shellsafe(xorriso->session_logfile, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 wpt= sfe;
 for(rpt= xorriso->volid; *rpt!=0; rpt++) {
   if(*rpt=='\n') {
     *(wpt++)= '\\';
     *(wpt++)= 'n';
   } else
     *(wpt++)= *rpt;
 }
 *wpt= 0;
 fprintf(fp, "%s %d %d %s\n",
         Ftimetxt(time(0), timetext, 2), xorriso->session_lba,
         xorriso->session_blocks, sfe);
 fclose(fp);
 return(1);
}


/* @param flag bit0= path is a command parameter
*/
int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag)
{
 int ret;
 char sfe[5*SfileadrL];

 if(!(xorriso->disk_excl_mode&1)) /* exclusion is off */
   return(0);
 if((flag&1) && !(xorriso->disk_excl_mode&2)) /* params are exempted */
   return(0);
 ret= Exclusions_match(xorriso->disk_exclusions, path,
                       !!(xorriso->disk_excl_mode&4));
 if(ret<0) {
   sprintf(xorriso->info_text,
           "Error during disk file exclusion decision");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 }
 if(ret>0 && (flag&1)) {
   sprintf(xorriso->info_text, "Disk path parameter excluded by %s : %s",
          (ret==1 ? "-not_paths" : "-not_leaf"), Text_shellsafe(path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 }
 return(ret);
}


/* @param flag bit7= return 4 if restore fails from denied permission
                     do not issue error message
   @return <=0 failure , 1 success ,
           4 with bit7: permission to  create file was denied
*/
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
                          char *tmp_path, int *fd, int flag)
{
 char *cpt;

 cpt= strrchr(orig_path, '/');
 if(cpt==NULL)
   tmp_path[0]= 0;
 else {
   strncpy(tmp_path, orig_path, cpt+1-orig_path);
   tmp_path[cpt+1-orig_path]= 0;
 }
 strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX");
 *fd= mkstemp(tmp_path);
 if(*fd==-1) {
   if(errno == EACCES && (flag & 128))
     return(4);
   strcpy(xorriso->info_text, "Cannot create temporary file : ");
   Text_shellsafe(tmp_path, xorriso->info_text, 1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
   return(0);
 }
 fchmod(*fd, S_IRUSR|S_IWUSR);
 return(1);
}


/* @param flag bit0= change regardless of xorriso->do_auto_chmod
               bit1= desired is only rx
   @return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded
*/
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
{
 int ret, is_link= 0;
 char *path_pt, sfe[5*SfileadrL], link_target[SfileadrL];
 mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR;
 struct stat stbuf;

 if(!(xorriso->do_auto_chmod || (flag & 1)))
   return(0);

 if(flag & 2)
   desired &= ~S_IWUSR;
 path_pt= disk_path;
 ret= lstat(path_pt, &stbuf);
 if(ret==-1)
   return(0);
 if(S_ISLNK(stbuf.st_mode)) {
   is_link= 1;
   ret= stat(path_pt, &stbuf);
   if(ret==-1)
     return(0);
 }
 if(!S_ISDIR(stbuf.st_mode))
   return(0);
 if(is_link) {
   ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0);
   if(ret<=0)
     return(ret);
   path_pt= link_target;
 }
 if((stbuf.st_mode & desired) == desired)
   return(0);
 if(stbuf.st_uid!=geteuid())
   return(-2);

 mode= (stbuf.st_mode | desired) & 07777;
 ret= chmod(path_pt, mode);
 if(ret==-1) {
   sprintf(xorriso->info_text,
           "Cannot change access permissions of disk directory: chmod %o %s",
           (unsigned int) (mode & 07777), Text_shellsafe(path_pt, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
   return(-2);
 }
 ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0);
 if(ret<=0)
   return(ret);
 return(1);
}


int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag)
{
 int done= 0, ret, just_rx= 2;
 char *npt, *apt, path[SfileadrL], *wpt;
 
 apt= disk_path;
 wpt= path;
 for(npt= apt; !done; apt= npt + 1) {
   npt= strchr(apt, '/');
   if(npt == NULL)
 break;
   if(strchr(npt + 1, '/') == NULL)
     just_rx= 0;
   strncpy(wpt, apt, npt + 1 - apt);
   wpt+= npt + 1 - apt;
   *wpt= 0;
   ret= Xorriso_auto_chmod(xorriso, path, just_rx);
   if(ret == -1)
     return(-1);
   if(ret == -2)
     return(0);
 }
 return(1);
}


/* @param flag bit0= prefer to find a match after *img_prefixes
                     (but deliver img_prefixes if no other can be found)
*/
int Xorriso_make_restore_path(struct XorrisO *xorriso,
         struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
         char img_path[SfileadrL], char disk_path[SfileadrL], int flag)
{
 int li;
 struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL;
 char *ipfx, *dpfx;

 /* Obtain disk_path by replacing start piece of img_path */
 
 d= *disk_prefixes;
 for(s= *img_prefixes; s != NULL;
     s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) {

   ipfx= Xorriso_lst_get_text(s, 0);
   li= strlen(ipfx);
   dpfx= Xorriso_lst_get_text(d, 0);
   if(strncmp(img_path, ipfx, li) != 0)
 continue;
   if(img_path[li] != 0 && img_path[li] != '/')
 continue;
   if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL)
     return(-1);
   if(img_path[li]=='/')
     sprintf(disk_path, "%s/%s", dpfx, img_path + strlen(ipfx) + 1);
   else
     strcpy(disk_path, dpfx);
   found_s= s;
   found_d= d;
   if(s != *img_prefixes || !(flag & 1))
 break;
 }
 *img_prefixes= found_s;
 *disk_prefixes= found_d;
 return(found_s != NULL);
}


/* @param flag bit0=permission to run Xorriso_make_accessible
*/
int Xorriso_restore_make_hl(struct XorrisO *xorriso,
                            char *old_path, char *new_path, int flag)
{
 int ret;
 struct PermiteM *perm_stack_mem;

 ret= link(old_path, new_path);
 if(ret == 0)
   return(1);
 if(errno == EACCES && (flag & 1)) {
   perm_stack_mem= xorriso->perm_stack;
   ret= Xorriso_make_accessible(xorriso, new_path, 0);
   if(ret > 0) {
      ret= link(old_path, new_path);
      if(ret == 0) {
        Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
        return(1);
      }
   }
   Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 }

 sprintf(xorriso->info_text, "Hardlinking failed: ");
 Text_shellsafe(new_path, xorriso->info_text, 1);
 strcat(xorriso->info_text, " -> ");
 Text_shellsafe(old_path, xorriso->info_text, 1);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "WARNING", 0);
 return(0);
}


/* @param flag bit0= mark untested areas as valid
*/
int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
                                  struct SpotlisT *spotlist,
                                  int read_chunk,
                                  struct SectorbitmaP **map,
                                  int flag)
{
 struct SectorbitmaP *m;
 int map_sectors= -1, map_sector_size= -1, valid;
 int list_sectors, list_blocks, sector_size, sector_blocks;
 int replace_map= 0, count, i, lba, blocks, quality, ret, pass;

 sector_size= Spotlist_sector_size(spotlist, read_chunk, 0);
 sector_blocks= sector_size / 2048;
 if(*map != NULL)
   Sectorbitmap_get_layout(*map, &map_sectors, &map_sector_size, 0);

 count= Spotlist_count(spotlist, 0);
 list_blocks= Spotlist_block_count(spotlist, 0);
 
 /* >>> ??? insist in list_blocks % sector_blocks == 0 */

 list_sectors= list_blocks / sector_blocks;
 if(list_sectors * sector_blocks < list_blocks)
   list_sectors++;
 if(*map != NULL && map_sectors * (map_sector_size / 2048) >= list_blocks &&
    map_sector_size == sector_size)
   m= *map;
 else {
   if(*map != NULL) {
     if(((off_t) (*map)->sectors) * ((off_t) (*map)->sector_size) >
        ((off_t) list_sectors)    * ((off_t) sector_size))
       list_sectors= (((off_t) (*map)->sectors) *
                      ((off_t) (*map)->sector_size)) / ((off_t) sector_size)
                     + 1;
   }
   ret= Sectorbitmap_new(&m, list_sectors, sector_size, 0);
   if(ret <= 0)
     return(-1);
   replace_map= 1;
   if(*map != NULL) {
     ret= Sectorbitmap_copy(*map, m, 0);
     if(ret <= 0) {
       Sectorbitmap_destroy(&m, 0);
       return(0);
     }
   }
 }

 count= Spotlist_count(spotlist, 0);
 /* first set good bits, then eventually override by bad bits */
 for(pass= 0; pass < 2; pass++) {
   for(i= 0; i < count; i++) {
     ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0);
     if(ret <= 0)
   continue;
     valid= quality > xorriso->check_media_bad_limit;
     if(quality == Xorriso_read_quality_untesteD && (flag & 1))
       valid= 1;
     else if(pass == 0 && !valid)
   continue;
     else if(pass == 1 && valid)
   continue;
     Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks,
                            valid);
   }
 }
 if(replace_map) {
   Sectorbitmap_destroy(map, 0);
   *map= m;
 }
 return(1);
}
 

int Xorriso_sectormap_to_spotlist(struct XorrisO *xorriso,
                                  struct CheckmediajoB *job,
                                  struct SpotlisT **spotlist,
                                  int flag)
{
 struct SectorbitmaP *map;
 int ret, i, sectors, sector_size, value, old_value= -1, old_start= -1;

 map= job->sector_map;
 if(map == NULL)
   return(-1);
 ret= Spotlist_new(spotlist, 0); 
 if(ret <= 0)
   {ret= -1; goto ex;}
 Sectorbitmap_get_layout(map, &sectors, &sector_size, 0);
 sector_size/= 2048;
 if(job->max_lba >= 0)
   sectors= (job->max_lba + 1) / sector_size;
 i= 0;
 if(job->min_lba >= 0)
   i= job->min_lba / sector_size;
 for(; i < sectors; i++) {
   value= Sectorbitmap_is_set(map, i, 0);
   if(value == old_value)
 continue;
   if(old_value >= 0) {
     ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
                            (old_value ? Xorriso_read_quality_valiD :
                                         Xorriso_read_quality_invaliD), 0);
     if(ret <= 0)
       goto ex;
     if(job->item_limit > 0 &&
        Spotlist_count(*spotlist, 0) + 1 >= job->item_limit) {
       sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
               job->item_limit);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
       if(sectors - i > 1) {
         ret= Spotlist_add_item(*spotlist, i * sector_size,
                                (sectors - i - 1) * sector_size,
                                Xorriso_read_quality_untesteD, 0);
         if(ret <= 0)
           goto ex;
       }
       ret= 2; goto ex;
     }
   }
   old_value= value;
   old_start= i * sector_size;
 }
 if(old_value >= 0) {
   ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
                          (old_value ? Xorriso_read_quality_valiD :
                                       Xorriso_read_quality_invaliD), 0);
   if(ret <= 0)
     goto ex;
 }
 ret= 1;
ex:;
 if(ret <= 0)
   Spotlist_destroy(spotlist, 0);
 return(ret);
}


int Xorriso_afile_fopen(struct XorrisO *xorriso,
                        char *filename, char *mode, FILE **ret_fp, int flag)
/*
 bit0= do not print error message on failure
*/
{
 FILE *fp= NULL;

 *ret_fp= NULL;
 if(strcmp(filename,"-")==0) {
   if(mode[0]=='a' || mode[0]=='w' ||
      (mode[0]=='r' && mode[1]=='+') ||
      (mode[0]=='r' && mode[1]=='b' && mode[2]=='+')) 
     fp= stdout;
   else {
     Xorriso_msgs_submit(xorriso, 0, "Ready for data at standard input", 0,
                         "NOTE", 0);
     fp= stdin;
   }
 } else if(strncmp(filename,"tcp:",4)==0){
   Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0,
                       "FAILURE", 0);
 } else if(strncmp(filename,"file:",5)==0){
   fp= fopen(filename+5,mode);
 } else {
   fp= fopen(filename,mode);
 }
 if(fp==NULL){
   if(!(flag&1)) {
     sprintf(xorriso->info_text,
             "Failed to open file '%s' in %s mode\n", filename, mode);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
   }
   return(0);
 }
 *ret_fp= fp;
 return(1);
}


/* @param flag bit2=do not try to read ISO heads
*/
int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag)
{
 int ret, stack_handle, toc_ret, l;
 struct Xorriso_lsT *results= NULL, *infos= NULL, *lpt;

 *toc_text= NULL;
 ret= Xorriso_push_outlists(xorriso, &stack_handle, 1);
 if(ret <= 0)
   goto ex;
 toc_ret= Xorriso_toc(xorriso, flag & 4);
 ret= Xorriso_pull_outlists(xorriso, stack_handle, &results, &infos, 0);
 if(ret <= 0)
   goto ex;
 if(toc_ret <= 0)
   {ret= toc_ret; goto ex;}
 l= 0;
 for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0))
   l+= strlen(Xorriso_lst_get_text(lpt, 0));
 *toc_text= calloc(l + 1, 1);
 l= 0;
 for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0)) {
   strcpy((*toc_text) + l, Xorriso_lst_get_text(lpt, 0));
   l+= strlen(Xorriso_lst_get_text(lpt, 0));
 }
ex:;
 Xorriso_lst_destroy_all(&results, 0);
 Xorriso_lst_destroy_all(&infos, 0);
 return(ret);
}


int Xorriso_open_job_data_to(struct XorrisO *xorriso,
                             struct CheckmediajoB *job, int flag)
{
 char sfe[5*SfileadrL];

 if(job->data_to_path[0] == 0)
   return(2);
 job->data_to_fd= open(job->data_to_path, O_RDWR | O_CREAT,
                       S_IRUSR | S_IWUSR);
 if(job->data_to_fd == -1) {
   sprintf(xorriso->info_text, "Cannot open path %s",
           Text_shellsafe(job->data_to_path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
   return(0);
 }
 return(1);
}

/*
   @param flag bit0= make absolute command paths with known systems
               bit1= do not allow prefixes with cmd
               bit2= interpret unprefixed cmd as shell:
*/
int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd,
                           int lba, int track, int session, char *volid,
                           char *devadr, char result[SfileadrL], int flag)
{
 int ret, reg_file= 0, is_safe= 0, sys_code= 0;
 char form[6*SfileadrL], session_text[12], track_text[12], lba_text[12];
 char *vars[5][2], sfe[5*SfileadrL], volid_sfe[5*80+1], *cpt, *sysname;
 struct stat stbuf;

 if(strlen(cmd) > SfileadrL) {
/*
too_long:;
*/
   Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0);
   return(0);
 }
 ret= stat(devadr, &stbuf);
 if(ret != -1)
   if(S_ISREG(stbuf.st_mode))
     reg_file= 1;
 if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) {
   cpt= cmd + 6;
   sys_code= 1;
 } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) {
   cpt= cmd + 8;
   sys_code= 2;
 } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) {
   cpt= cmd + 7;
   strcpy(form, cpt);
 } else if(flag & 4) {
   cpt= cmd;
   strcpy(form, cpt);
 } else {
   cpt= cmd;
   ret= System_uname(&sysname, NULL, NULL, NULL, 0);
   if(ret <= 0) {
     Xorriso_msgs_submit(xorriso, 0,
                         "-mount*: Cannot determine current system type",
                         0, "FAILURE", 0);
     return(0);
   } else if(strcmp(sysname, "FreeBSD") == 0 ||
             strcmp(sysname, "GNU/kFreeBSD") == 0) {
                                         /* "GNU/kFreeBSD" = Debian kfreebsd */
     sys_code= 2;
   } else if(strcmp(sysname, "Linux") == 0) {
     sys_code= 1;
   } else {
     sprintf(xorriso->info_text, "-mount*: Unsupported system type %s",
             Text_shellsafe(sysname, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }

 if(sys_code == 1) { /* GNU/Linux */
   sprintf(form,
           "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s",
           (flag & 1 ? "/bin/" : ""),
           (reg_file || (xorriso->mount_opts_flag & 1) ? "loop," : ""),
           Text_shellsafe(cpt, sfe, 0));
   is_safe= 1;
 } else if(sys_code == 2) { /* FreeBSD */
   if(reg_file) {

/*  <<< Considered to create vnode as of
        J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008
        but for now refraining from creating that persistent file object

     strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)");
     sprintf(form + strlen(form),
         " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s",
         Text_shellsafe(cmd+8, sfe, 0));
*/

     Xorriso_msgs_submit(xorriso, 0, 
           "Detected regular file as mount device with FreeBSD style command.",
           0, "FAILURE", 0);
     Xorriso_msgs_submit(xorriso, 0,
"Command mdconfig -a -t vnode -f can create a device node which uses the file",
                         0, "HINT", 0);
     return(0);
   } else {
     sprintf(form,
         "%smount_cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s",
         (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cmd+8, sfe, 0));
     /*
       Not working on FreeBSD 7.2 according to Zsolt Kuti, 11 Oct 2009:
         "%smount -t cd9660 -o noexec,nosuid -o -s %%sbsector%% %%device%% %s",
     */
   }
   is_safe= 1;
 }
 sprintf(session_text, "%d", session);
 sprintf(track_text, "%d", track);
 sprintf(lba_text, "%d", lba);
 vars[0][0]= "sbsector";
 vars[0][1]= lba_text;
 vars[1][0]= "track";
 vars[1][1]= track_text;
 vars[2][0]= "session";
 vars[2][1]= session_text;
 vars[3][0]= "volid";
 vars[3][1]= Text_shellsafe(volid, volid_sfe, 0);
 vars[4][0]= "device";
 vars[4][1]= Text_shellsafe(devadr, sfe, 0);
 ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0);
 if(ret <= 0)
   return(ret);
 return(1 + is_safe);
}


/* @param flag bit0= with adr_mode sbsector: adr_value is possibly 16 too high
*/
int Xorriso_decode_load_adr(struct XorrisO *xorriso, char *cmd,
                            char *adr_mode, char *adr_value,
                            int *entity_code, char entity_id[81],
                            int flag)
{
 double num;
 int l;

 if(strcmp(adr_mode, "auto")==0)
   *entity_code= 0;
 else if(strcmp(adr_mode, "session")==0)
   *entity_code= 1;
 else if(strcmp(adr_mode, "track")==0)
   *entity_code= 2;
 else if(strcmp(adr_mode, "lba")==0 || strcmp(adr_mode, "sbsector")==0)
   *entity_code= 3 | ((flag&1) << 16);
 else if(strcmp(adr_mode, "volid")==0)
   *entity_code= 4;
 else {
   sprintf(xorriso->info_text, "%s: unknown address mode '%s'", cmd, adr_mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 l= strlen(adr_value);
 if(l==0)
   *entity_code= 0;

 if(*entity_code>=1 && *entity_code<= 3) {
   num= Scanf_io_size(adr_value, 0);
   if(*entity_code==3 &&
      (adr_value[l-1]<'0' || adr_value[l-1]>'9'))
     num/= 2048.0;
   sprintf(entity_id, "%.f", num);
 } else {
   if(strlen(adr_value)>80) {
     sprintf(xorriso->info_text, "%s: address value too long (80 < %d)",
             cmd, (int) strlen(adr_value));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   strcpy(entity_id, adr_value);
 }
 return(1);
}


/*
  @param flag bit0= use env_path to find the desired program
return:
 <=0 : error
 1   : done
*/
int Xorriso_execv(struct XorrisO *xorriso, char *cmd, char *env_path,
                  int *status, int flag)
{
 int ret, argc= 0;
 char **argv= NULL, *pathlist= NULL, *cpt, *npt, prog[SfileadrL];
 char sfe[5*SfileadrL];
 pid_t child_pid;
 struct stat stbuf;

 wait3(NULL,WNOHANG,NULL); /* just to remove any old dead child */

 ret= Sfile_make_argv("", cmd, &argc, &argv, 1|4|128);
 if(ret <= 0)
   goto ex;
 if(argc < 1)
   {ret= 0; goto ex;}

 strcpy(prog, argv[0]);
 if((flag & 1) && strchr(argv[0], '/') == NULL) {
     if(env_path == NULL)
       env_path= "/bin:/sbin";
     else if(env_path[0] == 0)
       env_path= "/bin:/sbin";
     if(Sregex_string(&pathlist, env_path, 0) <= 0)
       {ret= -1; goto ex;}
     for(cpt= npt= pathlist; npt != NULL; cpt= npt + 1) {
       npt= strchr(cpt, ':');
       if(npt != NULL)
         *npt= 0;
       if(strlen(cpt) + strlen(argv[0]) + 1 >= SfileadrL)
         {ret= -1; goto ex;}
       sprintf(prog, "%s/%s", cpt, argv[0]);
       ret= stat(prog, &stbuf);
       if(ret != -1)
     break;
       prog[0]= 0;
     }
     if(prog[0] == 0) {
       sprintf(xorriso->info_text, "Cannot find external program %s",
               Text_shellsafe(argv[0], sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
   }

 child_pid= fork();
 if(child_pid==-1) 
   return(-1);

 if(child_pid==0) {
                     /* this is the child process */

   sprintf(xorriso->info_text, "Executing external program %s",
                               Text_shellsafe(prog, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);

   execv(prog, argv); /* should never come back */
   fprintf(stderr,"--- execution of shell command failed:\n");
   fprintf(stderr,"    %s\n",cmd);
   exit(127);
 }


         /* this is the original process waiting for child to exit */
 do {
   /* try to read and print the reply */;
   ret= waitpid(child_pid,status,WNOHANG);
   if(ret==-1) {
     if(errno!=EINTR)
       ret= 0; goto ex;
   } else if(ret==0) {

#ifdef NIX

     /* >>> An interrupt key would be nice. */

     if((flag&4)) {
       ret= Asqueue_event_is_pending(agent->queue,0,0);
       if(ret>0) {
         Asagent_stderr(agent,"--- shell command interrupted",1);
         kill(child_pid,SIGTERM);
         ret= 2; goto ex;
       }
     }
#endif /* NIX */

 continue;
   } else {
 break;
   }
 } while(1);
 ret= 1;
ex:
 Sfile_make_argv("", "", &argc, &argv, 2);
 Sregex_string(&pathlist, NULL, 0);
 return(ret);
}


/* Normalize ACL and sort apart "access" ACL from "default" ACL.
 */
int Xorriso_normalize_acl_text(struct XorrisO *xorriso, char *in_text,
                     char **access_acl_text, char **default_acl_text, int flag)
{
 int ret, access_count= 0, default_count= 0, pass, is_default, line_len;
 int was_error= 0, line_count= 0, perms;
 char *acl_text= NULL, *cpt, *npt, *access_wpt= NULL, *default_wpt= NULL; 
 char *dpt= NULL, *ddpt= NULL, **wpt, *ppt;

 if(in_text[0] == 0 || strcmp(in_text, "clear") == 0 ||
    strcmp(in_text, "--remove-all") == 0) {
   *access_acl_text= *default_acl_text= NULL;
   return(1);
 } else if (strcmp(in_text, "--remove-default") == 0) {

   /* >>> protect Access-ACL and delete Default-ACL */;

   /* <<< */
   return(0);
   
 }

 acl_text= strdup(in_text);
 if(acl_text == NULL) {
   Xorriso_no_malloc_memory(xorriso, NULL, 0);
   {ret= -1; goto ex;}
 }

 /* From comma to newline */
 for(cpt= strchr(acl_text, ','); cpt != NULL; cpt= strchr(cpt + 1, ','))
   *cpt= '\n';

 /* Normalize to long text form
    and sort apart "access" ACL from "default" ACL */;
 for(pass= 0; pass < 2; pass++) {
   line_count= 0;
   for(cpt= acl_text; cpt != NULL; cpt= npt) {
     line_count++;
     npt= strchr(cpt, '\n');
     if(npt != NULL)
       npt++;
     if(*cpt == '#' || *cpt == '\n' || *cpt == 0)
   continue;

     is_default= 0;
     wpt= &access_wpt;
     if(*cpt == 'd') {
       is_default= 1;
       if(pass == 1)
         wpt= &default_wpt;
       cpt= strchr(cpt, ':');
       if(cpt == NULL) {
         was_error= line_count;
   continue;
       }
       cpt++;
     } 

     line_len= 0;
     dpt= strchr(cpt, ':');
     if(dpt != NULL)
       ddpt= strchr(dpt + 1, ':');
     if(dpt == NULL || ddpt == NULL) {
       was_error= line_count;
   continue;
     }
     if(*cpt == 'u') {
       if(pass == 0) {
         line_len+= 5;
         line_len+= ddpt - dpt;
       } else {
         strcpy(*wpt, "user:");
         strncpy(*wpt + 5, dpt + 1, ddpt - dpt);
         (*wpt)+= 5 + (ddpt - dpt);
       }
     } else if(*cpt == 'g') {
       if(pass == 0) {
         line_len+= 6 + (ddpt - dpt);
       } else {
         strcpy(*wpt, "group:");
         strncpy(*wpt + 6, dpt + 1, ddpt - dpt);
         (*wpt)+= 6 + (ddpt - dpt);
       }
     } else if(*cpt == 'o') {
       if(pass == 0) {
         if(ddpt - dpt > 1) {
           was_error= line_count;
   continue;
         }
         line_len+= 6 + (ddpt - dpt);
       } else {
         strcpy(*wpt, "other:");
         strncpy(*wpt + 6, dpt + 1, ddpt - dpt);
         (*wpt)+= 6 + (ddpt - dpt);
       }
     } else if(*cpt == 'm') {
       if(pass == 0) {
         if(ddpt - dpt > 1) {
           was_error= line_count;
   continue;
         }
         line_len+= 5 + (ddpt - dpt);
       } else {
         strcpy(*wpt, "mask:");
         strncpy(*wpt + 5, dpt + 1, ddpt - dpt);
         (*wpt)+= 5 + (ddpt - dpt);
       }

     } else {
       /* Unknown tag type */
       was_error= line_count;
   continue;
     }

     /* Examine permissions at ddpt + 1 */;
     perms= 0;
     for(ppt= ddpt + 1; *ppt != 0 && *ppt != '\n'; ppt++) {
       if(*ppt == 'r')
         perms|= 4;
       else if(*ppt == 'w')
         perms|= 2;
       else if(*ppt == 'x')
         perms|= 1;
       else if(*ppt == '-' || *ppt == ' ' || *ppt == '\t')
         ;
       else if(*ppt == '#')
     break;
       else {
         was_error= line_count;
     break;
       }
     }
     if(pass == 0) {
       line_len+= 4;
     } else {
       sprintf(*wpt, "%c%c%c\n",
          perms & 4 ? 'r' : '-', perms & 2 ? 'w' : '-', perms & 1 ? 'x' : '-');
       (*wpt)+= 4;
     }

     if(pass == 0) {
       if(is_default)
         default_count+= line_len;
       else
         access_count+= line_len;
     }
   }

   if(pass == 0) {
     *access_acl_text= calloc(access_count + 1, 1);
     *default_acl_text= calloc(default_count + 1, 1);
     if(access_acl_text == NULL || *default_acl_text == NULL) {
       Xorriso_no_malloc_memory(xorriso, access_acl_text, 0);
       {ret= -1; goto ex;}
     }
     access_wpt= *access_acl_text;
     default_wpt= *default_acl_text;
   } else {
     *access_wpt= 0;
     *default_wpt= 0;
   }
 }

 ret= 1;
ex:;
 if(acl_text != NULL)
   free(acl_text);
 if(was_error) {
   sprintf(xorriso->info_text,
           "Malformed ACL entries encountered. Last one in line number %d.",
           was_error);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(ret);
}


int Xorriso_perform_acl_from_list(struct XorrisO *xorriso, char *file_path,
                                  char *uid, char *gid, char *acl, int flag)
{
 int ret, zero= 0;
 uid_t uid_number;
 gid_t gid_number;

 /* Set group and owner */
 if(gid[0]) {
   ret= Xorriso_convert_gidstring(xorriso, gid, &gid_number, 0);
   if(ret<=0)
     return(ret);
   ret= Xorriso_set_gid(xorriso, file_path, gid_number, 0);
   if(ret<=0)
     return(ret);
 }
 if(uid[0]) {
   ret= Xorriso_convert_uidstring(xorriso, uid, &uid_number, 0);
   if(ret<=0)
     return(ret);
   ret= Xorriso_set_uid(xorriso, file_path, uid_number, 0);
   if(ret<=0)
     return(ret);
 }
 ret= Xorriso_option_setfacli(xorriso, acl, 1, &file_path, &zero, 0);
 if(ret <= 0)
   return(ret);
 return(1);
}


/*
  @param flag   bit0= do not perform setfattr but only check input
*/
int Xorriso_path_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
                        char *name, size_t value_length, char *value, int flag)
{
 int ret, hflag;
 size_t num_attrs= 1;
 char *name_pt;

 hflag= 2;
 name_pt= name;
 if(name[0] == 0) {
   sprintf(xorriso->info_text,
           "-setfattr: Empty attribute name is not allowed");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 } else if(strcmp(name, "--remove-all") == 0) {
   if(value[0]) {
     sprintf(xorriso->info_text,
             "-setfattr: Value is not empty with pseudo name --remove-all");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     return(0);
   }
   num_attrs= 0;
   hflag= 0;
 } else if(name[0] == '-') {
   name_pt++;
   hflag|= 4;
 } else if(name[0] == '=' || name[0] == '+') {
   name_pt++;
 }
 if(flag & 1)
   return(1);
 ret= Xorriso_setfattr(xorriso, in_node, path,
                       num_attrs, &name_pt, &value_length, &value, hflag);
 return(ret);
}


/* Warning: The text content of lst gets mangled by 0s and unescaping.
*/
int Xorriso_perform_attr_from_list(struct XorrisO *xorriso, char *path,
                      struct Xorriso_lsT *lst_start, int flag)
{
 int ret, eaten;
 char *valuept, *ept, *line, **names= NULL, **values= NULL;
 size_t num_attr= 0, *value_lengths= NULL, v_len;
 struct Xorriso_lsT *lst;

 for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0))
   num_attr++;
 if(num_attr == 0) {
   ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, NULL, NULL, NULL, 0);
   goto ex;
 }

 names= calloc(num_attr, sizeof(char *));
 if(names == NULL) {
   Xorriso_no_malloc_memory(xorriso, NULL, 0);
   ret= -1; goto ex;
 }
 value_lengths= calloc(num_attr, sizeof(size_t));
 if(value_lengths== NULL) {
   free(names);
   Xorriso_no_malloc_memory(xorriso, NULL, 0);
   ret= -1; goto ex;
 }
 values= calloc(num_attr, sizeof(char *));
 if(values== NULL) {
   free(names);
   free(value_lengths);
   Xorriso_no_malloc_memory(xorriso, NULL, 0);
   ret= -1; goto ex;
 }

 num_attr= 0;
 for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0)) {
   line= Xorriso_lst_get_text(lst, 0);
   ept= strchr(line, '=');
   if(ept == NULL)
 continue;
   /* Split into name and content */;
   *ept= 0;
   valuept= ept + 1;

   /* Strip quotes from value */
   v_len= strlen(valuept);
   if(v_len < 2 || *valuept != '"' || *(valuept + v_len - 1) != '"')
 continue;
   *valuept= 0;
   *(valuept + v_len - 1)= 0;
   valuept++;
   v_len-= 2;

   /* Unescape backslashes , values eventually with 0-bytes */
   ret= Sfile_bsl_interpreter(line, strlen(line), &eaten, 0);
   if(ret <= 0)
 continue;
   ret= Sfile_bsl_interpreter(valuept, (int) v_len, &eaten, 2);
   if(ret <= 0)
 continue;

   names[num_attr]= line;
   values[num_attr]= valuept;
   value_lengths[num_attr]= v_len - eaten;
   num_attr++;
 }
 ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, names,
                       value_lengths, values, 0);
ex:;
 if(names != NULL)
   free(names);
 if(value_lengths != NULL)
   free(value_lengths);
 if(values != NULL)
   free(values);
 return(ret);
}


/* @param flag bit0= no hardlink reconstruction
               bit1= do not set xorriso->node_*_prefixes
               bit5= -extract_single: eventually do not insert directory tree
*/
int Xorriso_restore_sorted(struct XorrisO *xorriso, int count,
                           char **src_array, char **tgt_array, int flag)
{
 int i, ret, with_node_array= 0, hflag= 0, hret;

 if(!(((xorriso->ino_behavior & 16) && xorriso->do_restore_sort_lba) ||
      (xorriso->ino_behavior & 4) || (flag & 1))) {
   ret= Xorriso_make_hln_array(xorriso, 0);
   if(ret<=0)
     goto ex;
 }
 if(xorriso->do_restore_sort_lba) {
   /* Count affected nodes */
   Xorriso_destroy_node_array(xorriso, 0);
   for(i= 0; i < count; i++) {
     if(src_array[i] == NULL || tgt_array[i] == NULL)
   continue;
     /* sort_lba : Make directories plus node_array and then
                   run array extractor (with eventual hardlink detection)
     */
     hflag= (1 << 7) | ((!!(flag & 2)) << 9);
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
                          (off_t) 0, (off_t) 0, hflag);
     if(ret <= 0) {
       hret= Xorriso_eval_problem_status(xorriso, ret, 0);
       if(ret < 0)
         goto ex;
     }
     with_node_array= 1;
   }
 }

 if(with_node_array) {
   /* Allocate and fill node array */
   if(xorriso->node_counter <= 0)
     {ret= 2; goto ex;}
   ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0,
                               !xorriso->do_restore_sort_lba);
   if(ret<=0)
     goto ex;
   for(i= 0; i < count; i++) {
     if(src_array[i] == NULL || tgt_array[i] == NULL)
   continue;
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
                          (off_t) 0, (off_t) 0, 2 << 7);
     if(ret <= 0) {
       hret= Xorriso_eval_problem_status(xorriso, ret, 0);
       if(ret < 0)
         goto ex;
     }
   }
 }

 /* Perform restore operations */
 if(xorriso->do_restore_sort_lba) {
   ret= Xorriso_restore_node_array(xorriso, 0);
   if(ret <= 0)
     goto ex;
 } else {
   for(i= 0; i < count; i++) {
     if(src_array[i] == NULL || tgt_array[i] == NULL)
   continue;
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
                          (off_t) 0, (off_t) 0, 0);
     if(ret <= 0) {
       hret= Xorriso_eval_problem_status(xorriso, ret, flag & 32);
       if(ret < 0)
         goto ex;
     }
   }
 }

 ret= 1;
ex:;
 return(ret);
}


int Xorriso_report_md5_outcome(struct XorrisO *xorriso, char *severity,
                               int flag)
{
 int has_md5;

 has_md5= Xorriso_image_has_md5(xorriso, 0);
 if(xorriso->find_check_md5_result & 1) {
   sprintf(xorriso->result_line,
           "Mismatch detected between file contents and MD5 checksums.\n");
 } else if(xorriso->find_check_md5_result & 8) {
   sprintf(xorriso->result_line,
           "File contents and their MD5 checksums match.\n");
 } else {
   sprintf(xorriso->result_line,
           "Not a single file with MD5 checksum was found.");
   if(has_md5 <= 0)
     strcat(xorriso->result_line,
            " (There is no MD5 checksum array loaded.)\n");
   else
     strcat(xorriso->result_line, "\n");
 }
 Xorriso_result(xorriso,0);
 if(xorriso->find_check_md5_result & 2) {
   sprintf(xorriso->result_line,
           "Encountered errors other than non-match during MD5 checking.\n");
   Xorriso_result(xorriso,0);
 }
 if((xorriso->find_check_md5_result & 4) && has_md5) {
   sprintf(xorriso->result_line,
   "There were data files which have no MD5 and thus could not be checked.\n");
   Xorriso_result(xorriso,0);
 }
 if((xorriso->find_check_md5_result & 3) && strcmp(severity, "ALL") != 0) {
   sprintf(xorriso->info_text, "Event triggered by MD5 comparison mismatch");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, severity, 0);
 }
 return(1);
}


int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag)
{
 FILE *fp= NULL;
 char dummy[81], name[81], timestamp[81], size[81], md5[81];

 if(xorriso->scdbackup_tag_written[0] == 0)
   return(1);

 name[0]= timestamp[0]= size[0]= md5[0]= 0;
 sscanf(xorriso->scdbackup_tag_written, "%s %s %s %s %s %s %s",
        dummy, dummy, dummy, name, timestamp, size, md5);
 sprintf(xorriso->info_text, "scdbackup tag written : %s %s %s %s\n",
         name, timestamp, size, md5);
 Xorriso_msgs_submit(xorriso, 0,  xorriso->info_text, 0, "NOTE", 0);

 if(xorriso->scdbackup_tag_listname[0]) {
   fp= fopen(xorriso->scdbackup_tag_listname, "a");
   if(fp==0) {
     strcpy(xorriso->info_text, "-scdbackup_tag: Cannot open file ");
     Text_shellsafe(xorriso->scdbackup_tag_listname, xorriso->info_text, 1);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   fprintf(fp, "%s %s %s %s\n", name, timestamp, size, md5);
   fclose(fp);
 }
 return(1);
}


int Xorriso_may_burn(struct XorrisO *xorriso, int flag)
{

 if(xorriso->outdev_is_exclusive)
   return(1);
 sprintf(xorriso->info_text, "The output drive was not aquired exclusively.");
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 sprintf(xorriso->info_text, "A possible remedy is: -osirrox 'o_excl_on'");
 if(xorriso->outdev[0]) {
   strcat(xorriso->info_text," -outdev ");
   Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
 }
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
 return(0);
}


int Xorriso_check_name_len(struct XorrisO *xorriso, char *name, int size,
                           char *cmd, int flag)
{
 if(strlen(name) >= size) {
   sprintf(xorriso->info_text,
           "Name too long with option %s (%d > %d)", cmd,
           (int) strlen(name), size - 1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


/* ---------------------------- Options API ------------------------ */


/* Option -abort_on */
int Xorriso_option_abort_on(struct XorrisO *xorriso, char *severity, int flag)
{
 int ret, sev;
 char sfe[5*SfileadrL];

 ret= Xorriso__text_to_sev(severity, &sev, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "-abort_on: Not a known severity name : %s",
           Text_shellsafe(severity, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(ret);
 }
 if(Sfile_str(xorriso->abort_on_text,severity,0)<=0)
   return(-1);
 xorriso->abort_on_severity= sev;
 Xorriso_set_abort_severity(xorriso, 0);
 return(1);
}


/* Option -acl "on"|"off" */
int Xorriso_option_acl(struct XorrisO *xorriso, char *mode, int flag)
{
 int ret;

 if(strcmp(mode, "off")==0)
   xorriso->do_aaip&= ~3;
 else if(strcmp(mode, "on")==0)
   xorriso->do_aaip|= (1 | 2);
 else {
   sprintf(xorriso->info_text, "-acl: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_set_ignore_aclea(xorriso, 0);
 if(ret <= 0)
   return(ret);
 return(1);
}


/* Option -add */
/* @param flag bit0=do not report the added item
               bit1=do not reset pacifier, no final pacifier message
*/
int Xorriso_option_add(struct XorrisO *xorriso, int argc, char **argv,
                       int *idx, int flag)
{
 int i, end_idx, ret, was_failure= 0, fret, optc= 0, split;
 char target[SfileadrL], source[SfileadrL], *ept, eff_path[SfileadrL];
 char **optv= NULL, *rpt, *wpt;

 ret= Xorriso_opt_args(xorriso, "-add", argc, argv, *idx, &end_idx,
                       &optc, &optv, ((!!xorriso->allow_graft_points)<<2)|2);
 if(ret<=0)
   goto ex;

 if(!(flag&2))
   Xorriso_pacifier_reset(xorriso, 0);
 for(i= 0; i<optc; i++) {
   if(Sfile_str(target,optv[i],0)<=0)
     {ret= -1; goto ex;}
   strcpy(source, optv[i]);
   split= 0;
   if(xorriso->allow_graft_points) {
     ret= Fileliste__target_source_limit(target, '=', &ept, 0);
     if(ret>0) {
       *ept= 0;
       strcpy(source, ept+1);
       split= 1;
     }
     /* unescape \= */;
     if(split)
       rpt= wpt= target;
     else
       rpt= wpt= source;
     for(; *rpt!=0; rpt++) {
       if(*rpt=='\\')
         if(*(rpt+1)=='=')
     continue;
       *(wpt++)= *rpt;
     }
     *wpt= 0;
   }
   if(split==0) {
     strcpy(target, source);
   } else if(target[0]!='/') {
     ret= Sfile_prepend_path(xorriso->wdi, target, 0);
     if(ret<=0)
       goto problem_handler;
   }

   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, target, eff_path, 2);
   if(ret<=0)
     goto problem_handler;
   strcpy(target, eff_path);
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, source,eff_path,2|4);
   if(ret<=0)
     goto problem_handler;
   strcpy(source, eff_path);

   ret= Xorriso_graft_in(xorriso, NULL, source, target, (off_t)0, (off_t)0, 0);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n",
           (ret>1 ? "directory" : "file"), (target[0] ? target : "/"), source);
   if(!(flag&1))
     Xorriso_info(xorriso, 0);

 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 } 
 if(!(flag&2))
   Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1);
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-add", argc, argv, *idx, &end_idx, &optc, &optv,
                  256);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -add_plainly "none"|"unknown" */
int Xorriso_option_add_plainly(struct XorrisO *xorriso, char *mode,int flag)
{
 if(strcmp(mode, "none")==0)
   xorriso->add_plainly= 0;
 if(strcmp(mode, "unknown")==0)
   xorriso->add_plainly= 1;
 else if(strcmp(mode, "dashed")==0)
   xorriso->add_plainly= 2;
 else if(strcmp(mode, "any")==0)
   xorriso->add_plainly= 3;
 else {
   sprintf(xorriso->info_text, "-add_plainly: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -alter_date , -alter_date_r */
/* @param flag bit0=recursive (-alter_date_r)
*/
int Xorriso_option_alter_date(struct XorrisO *xorriso,
                               char *time_type, char *timestring,
                               int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, t_type= 0, end_idx, fret;
 time_t t;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-alter_date", argc, argv, *idx, &end_idx,
                       &optc, &optv, 0);
 if(ret<=0)
   goto ex; 
 ret= Xorriso_convert_datestring(xorriso, "-alter_date", time_type, timestring,
                                 &t_type, &t, 0);
 if(ret<=0)
   goto ex;
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-alter_date", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_ad(job, t_type, t, 0);
     ret= Xorriso_findi(xorriso, job, NULL,  (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else
     ret= Xorriso_set_time(xorriso, optv[i], t, t_type);
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-alter_date", argc, argv, *idx, &end_idx, &optc,
                  &optv, 256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -application_id */
int Xorriso_option_application_id(struct XorrisO *xorriso, char *name,
                                  int flag)
{
  if(Xorriso_check_name_len(xorriso, name,
                            (int) sizeof(xorriso->application_id),
                            "-application_id", 0) <= 0)
    return(0);
 strcpy(xorriso->application_id,name);
 Xorriso_set_change_pending(xorriso, 1);
 return(1);
}


/* Option -as */
/* @param flag bit0=do not report the added item
               bit1=do not reset pacifier, no final pacifier message
*/
int Xorriso_option_as(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int end_idx, ret, idx_count;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 idx_count= end_idx-(*idx);
 if(end_idx<=0 || (*idx)>=argc) {
   if(idx_count<1)
     sprintf(xorriso->info_text,
             "-as : Not enough arguments given. Needed: whom do_what %s",
             xorriso->list_delimiter);
   else
     sprintf(xorriso->info_text,
             "-as %s : Not enough arguments given. Needed: do_what %s",
             argv[*idx], xorriso->list_delimiter);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }
 if(strcmp(argv[*idx], "cdrecord")==0 || strcmp(argv[*idx], "wodim")==0 ||
    strcmp(argv[*idx], "cdrskin")==0 || strcmp(argv[*idx], "xorrecord")==0) {
   ret= Xorriso_cdrskin(xorriso, argv[*idx], end_idx-(*idx)-1, argv+(*idx)+1,
                        0);
   if(ret<=0)
     goto ex;
 } else if(strcmp(argv[*idx], "mkisofs")==0 ||
           strcmp(argv[*idx], "genisoimage")==0 ||
           strcmp(argv[*idx], "genisofs")==0 ||
           strcmp(argv[*idx], "xorrisofs")==0) {
   ret= Xorriso_genisofs(xorriso, argv[*idx], end_idx-(*idx)-1, argv+(*idx)+1,
                         0);
   if(ret<=0)
     goto ex;
 } else {
   sprintf(xorriso->info_text,
           "-as : Not a known emulation personality: '%s'", argv[*idx]);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }

 ret= 1;
ex:;
 (*idx)= end_idx;
 return(ret);
}


/* Option -assert_volid */
int Xorriso_option_assert_volid(struct XorrisO *xorriso, char *pattern,
                                char *severity, int flag)
{
 int ret, sev;
 char *sev_text= "";

 if(strlen(pattern)>=sizeof(xorriso->assert_volid)) {
   sprintf(xorriso->info_text,
           "Name too long with option -application_id (%d > %d)",
           (int) strlen(pattern), (int) sizeof(xorriso->assert_volid)-1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 if(pattern[0]) {
   ret= Sregex_match(pattern, "", 1);
   if(ret <= 0) {
     sprintf(xorriso->info_text, "-assert_volid: Cannot use given pattern.");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 if(severity[0] != 0 || pattern[0] != 0) {
   if(severity[0] == 0)
     sev_text= xorriso->abort_on_text;
   else
     sev_text= severity;
   if(strcmp(sev_text, "NEVER") == 0)
     sev_text= "ABORT";
   ret= Xorriso__text_to_sev(sev_text, &sev, 0);
   if(ret<=0) {
     sprintf(xorriso->info_text, "-assert_volid: Not a known severity name : ");
     Text_shellsafe(severity, xorriso->info_text, 1);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(ret);
   }
 }
 if(Sfile_str(xorriso->assert_volid, pattern,0) <= 0)
   return(-1);
 strcpy(xorriso->assert_volid_sev, sev_text);
 return(1);
}


/* Option -auto_charset "on"|"off" */
int Xorriso_option_auto_charset(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_aaip&= ~(256 | 512);
 else if(strcmp(mode, "on")==0)
   xorriso->do_aaip|= (256 | 512);
 else {
   sprintf(xorriso->info_text, "-auto_charset: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -backslash_codes */
int Xorriso_option_backslash_codes(struct XorrisO *xorriso, char *mode,
                                   int flag)
{
 char *npt, *cpt;
 int l, was;

 was= xorriso->bsl_interpretation;
 xorriso->bsl_interpretation= 0;
 npt= cpt= mode;
 for(; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l == 0)
 continue;
   if(l == 3 && strncmp(cpt, "off", l)==0) {
     xorriso->bsl_interpretation= 0;
   } else if(l == 16 && strncmp(cpt, "in_double_quotes", l)==0) {
     xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 1;
   } else if(l == 9 && strncmp(cpt, "in_quotes", l)==0) {
     xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 2;
   } else if(l == 17 && strncmp(cpt, "with_quoted_input", l)==0) {
     xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 3;
   } else if(l == 22 && strncmp(cpt, "with_program_arguments", l)==0) {
     xorriso->bsl_interpretation= xorriso->bsl_interpretation | 16;
   } else if(l == 13 && strncmp(cpt, "encode_output", l)==0) {
     xorriso->bsl_interpretation= xorriso->bsl_interpretation | 32 | 64;
   } else if(l == 14 && strncmp(cpt, "encode_results", l)==0) {
     xorriso->bsl_interpretation= xorriso->bsl_interpretation | 32;
   } else if(l == 12 && strncmp(cpt, "encode_infos", l)==0) {
     xorriso->bsl_interpretation= xorriso->bsl_interpretation | 64;
   } else if(l == 2 && strncmp(cpt, "on", l)==0) {
     xorriso->bsl_interpretation= 3 | 16 | 32 | 64;
   } else {
     if(l<SfileadrL)
       sprintf(xorriso->info_text, "-backslash_codes: unknown mode '%s'", cpt);
     else
       sprintf(xorriso->info_text,
               "-backslash_codes: oversized mode parameter (%d)", l);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     xorriso->bsl_interpretation= was;
     return(0);
   }
 }
 return(1);
}


/* Option -ban_stdio_write */
int Xorriso_option_ban_stdio_write(struct XorrisO *xorriso, int flag)
{
 xorriso->ban_stdio_write= 1;
 return(1);
}


/* Option -blank and -format */
/* @param flag bit0= format rather than blank
   @return <=0 error , 1 success, 2 revoked by -reassure 
*/
int Xorriso_option_blank(struct XorrisO *xorriso, char *mode, int flag)
{
 char drive_name[SfileadrL], *cmd= "-blank";
 int aq_ret, ret, aq_flag= 2, mode_flag= 0, as_needed= 0, idx;
 off_t size= 0;

 if(flag&1)
   cmd= "-format";
 if(xorriso->out_drive_handle == NULL) {
   sprintf(xorriso->info_text,
           "%s: No output drive set by -dev -or -outdev", cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(xorriso->in_drive_handle == xorriso->out_drive_handle) {
   if(xorriso->volset_change_pending) {
     sprintf(xorriso->info_text,
             "%s: Image changes pending. -commit or -rollback first.", cmd);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   aq_flag= 3;
 }
 ret= Xorriso_reassure(xorriso, cmd,
                       "possibly make unreadable data on outdev", 0);
 if(ret<=0)
   return(2);

 if(strcmp(mode, "as_needed")==0 || mode[0]==0)
   as_needed= 1;
 else if(strcmp(mode, "all")==0 || strcmp(mode, "full")==0)
   mode_flag= 0;
 else if((strcmp(mode, "deformat")==0 ||
          strcmp(mode, "deformat_sequential")==0) && !(flag&1))
   mode_flag= 2;
 else if((strcmp(mode, "deformat_quickest")==0 ||
          strcmp(mode, "deformat_sequential_quickest")==0) && !(flag&1))
   mode_flag= 3;
 else if(strcmp(mode, "fast")==0)
   mode_flag= 1;
 else if(strncmp(mode, "by_index_", 9)==0 && (flag&1)) {
   mode_flag= 128;
   idx= -1;
   if(strlen(mode)>9)
     sscanf(mode+9, "%d", &idx);
   if(idx<0 || idx>255) {
unusable_index:;
     sprintf(xorriso->info_text,
             "-format: mode '%s' provides unusable index number", mode);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   mode_flag|= (idx<<8);
 } else if(strncmp(mode, "fast_by_index_", 14)==0 && (flag&1)) {
   mode_flag= 1 | 128;
   idx= -1;
   if(strlen(mode)>14)
     sscanf(mode+14, "%d", &idx);
   if(idx<0 || idx>255)
     goto unusable_index;
   mode_flag|= (idx<<8);
 } else if(strncmp(mode, "by_size_", 8) == 0 && (flag & 1)) {
   size= (off_t) Scanf_io_size(mode + 8, 0);
   if(size <= 0) {
unusable_size:;
     sprintf(xorriso->info_text,
             "-format: mode '%s' provides unusable size value", mode);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   mode_flag= 2;
 } else if(strncmp(mode, "fast_by_size_", 13) == 0 && (flag & 1)) {
   size= (off_t) Scanf_io_size(mode + 13, 0);
   if(size <= 0)
     goto unusable_size;
   mode_flag= 3;
 } else {
   sprintf(xorriso->info_text,
           "%s: Unknown %s mode '%s'",
           cmd, ((flag&1) ? "-format" : "-blank"), mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(as_needed)
   ret= Xorriso_blank_as_needed(xorriso, (flag&1)<<2);
 else if(flag&1)
   ret= Xorriso_format_media(xorriso, size, mode_flag & 0xff83);
 else
   ret= Xorriso_blank_media(xorriso, mode_flag&3);
 if(ret==0)
   return(ret);
 strcpy(drive_name, xorriso->outdev);
 if(ret <= 0) { /* in case of success, above functions will have re-aquired */
   aq_ret= Xorriso_reaquire_outdev(xorriso, 0); /* actually give up drive */
   if(ret<aq_ret)
     return(ret);
   if(aq_ret<=0)
     return(aq_ret);
 }
 return(1);
}


/* Option -boot_image */
int Xorriso_option_boot_image(struct XorrisO *xorriso, char *form,
                              char *treatment, int flag)
{
 int was_ok= 1, ret;
 char *formpt, *treatpt;
 double num;

 formpt= form;
 if(formpt[0]=='-')
   formpt++;
 treatpt= treatment;
 if(treatpt[0]=='-')
   treatpt++;
 if(strcmp(formpt, "any")==0) {
   if(strcmp(treatpt, "keep")==0) {
     xorriso->keep_boot_image= 1;
     xorriso->patch_isolinux_image= 0;
     xorriso->boot_image_bin_path[0]= 0;
   } else if(strcmp(treatpt, "discard")==0) {
     xorriso->keep_boot_image= 0;
     xorriso->patch_isolinux_image= 0;
     xorriso->boot_image_bin_path[0]= 0;
   } else if(strcmp(treatpt, "show_status")==0) {
show_status:;
     sprintf(xorriso->result_line, "------------------------------------\n");
     Xorriso_result(xorriso, 0);
     sprintf(xorriso->result_line, "Status of loaded boot image        :\n");
     Xorriso_result(xorriso, 0);
     sprintf(xorriso->result_line, "------------------------------------\n");
     Xorriso_result(xorriso, 0);
     Xorriso_show_boot_info(xorriso, 0);
     sprintf(xorriso->result_line, "------------------------------------\n");
     Xorriso_result(xorriso, 0);
     sprintf(xorriso->result_line, "Boot image settings for next commit:\n");
     Xorriso_result(xorriso, 0);
     sprintf(xorriso->result_line, "------------------------------------\n");
     Xorriso_result(xorriso, 0);
     Xorriso_status(xorriso, "-boot_image", NULL, 0);
     sprintf(xorriso->result_line, "------------------------------------\n");
     Xorriso_result(xorriso, 0);
   } else
     was_ok= 0;
 } else if(strcmp(formpt, "isolinux")==0) {
   if(strcmp(treatpt, "patch")==0 ||
      strcmp(treatpt, "keep")==0) { /* no real "keep" with ISOLINUX */
     xorriso->keep_boot_image= 1;
     xorriso->patch_isolinux_image= 1;
     xorriso->boot_image_bin_path[0]= 0;
   } else if(strcmp(treatpt, "discard")==0) {
     xorriso->keep_boot_image= 0;
     xorriso->patch_isolinux_image= 0;
     xorriso->boot_image_bin_path[0]= 0;
   } else if(strcmp(treatpt, "show_status")==0) {
     goto show_status;
   } else if(strncmp(treatpt, "dir=", 4) == 0) {
     /* The three locations mentioned in http://syslinux.zytor.com/iso.php */
     if(strcmp(treatpt + 4, "/") == 0)
       strcpy(xorriso->boot_image_bin_path, "/");
     else if(strcmp(treatpt + 4, "isolinux") == 0
        || strcmp(treatpt + 4, "/isolinux") == 0)
       strcpy(xorriso->boot_image_bin_path, "/isolinux/");
     else if(strcmp(treatpt + 4, "boot/isolinux") == 0
        || strcmp(treatpt + 4, "/boot/isolinux") == 0
        || strcmp(treatpt + 4, "boot") == 0
        || strcmp(treatpt + 4, "/boot") == 0)
       strcpy(xorriso->boot_image_bin_path, "/boot/isolinux/");
     else {
       sprintf(xorriso->info_text,
               "Unrecognized keyword with -boot_image %s %s",
               form, treatment);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       sprintf(xorriso->info_text,
               "Allowed with dir= are / , /isolinux . /boot/isolinux");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
       return(0);
     }
     strcpy(xorriso->boot_image_cat_path, xorriso->boot_image_bin_path);
     strcat(xorriso->boot_image_bin_path, "isolinux.bin");
     strcat(xorriso->boot_image_cat_path, "boot.cat");
     xorriso->boot_image_load_size= 4 * 512;
     xorriso->keep_boot_image= 0;
     xorriso->patch_isolinux_image= 0;
   } else if(strncmp(treatpt, "bin_path=", 9) == 0) {
     ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, treatpt + 9,
                                     xorriso->boot_image_bin_path, 2);
     if(ret <= 0)
       return(ret);
     xorriso->keep_boot_image= 0;
     xorriso->patch_isolinux_image= 0;
     if(xorriso->boot_image_bin_path[0])
       xorriso->boot_image_load_size= 4 * 512;
   } else if(strncmp(treatpt, "cat_path=", 9) == 0) {
     ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, treatpt + 9,
                                     xorriso->boot_image_cat_path, 2);
     if(ret <= 0)
       return(ret);
   } else if(strncmp(treatpt, "load_size=", 10) == 0) {
     num= Scanf_io_size(treatpt + 10, 0);
     if(num < 512) {
       sprintf(xorriso->info_text,
               "-boot_image isolinux : load_size too small (%s < 512)",
               treatpt + 10);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       return(0);
     }
     xorriso->boot_image_load_size= num;
   } else if(strncmp(treatpt, "isohybrid=", 10) == 0) {
     if(strcmp(treatpt + 10, "off") == 0)
       xorriso->boot_image_isohybrid= 0;
     else if(strcmp(treatpt + 10, "auto") == 0)
       xorriso->boot_image_isohybrid= 1;
     else if(strcmp(treatpt + 10, "on") == 0)
       xorriso->boot_image_isohybrid= 2;
     else if(strcmp(treatpt + 10, "force") == 0)
       xorriso->boot_image_isohybrid= 3;
     else {
       sprintf(xorriso->info_text,
               "Unrecognized keyword with -boot_image %s %s",
               form, treatment);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       sprintf(xorriso->info_text,
               "Allowed with isohybrid= are: off , auto , on , force");
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
       return(0);

     }
   } else
     was_ok= 0;
 } else
   was_ok= 0;

 /* >>> BOOT : check whether directories and/or files exist:
               bin_path , dirname(cat_path),
               isolinux.cfg in / , /isolinux , or /boot/isolinux
 */

 if(!was_ok) {
   sprintf(xorriso->info_text, "Unrecognized options with -boot_image: %s %s",
           form, treatment);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -calm_drive */
int Xorriso_option_calm_drive(struct XorrisO *xorriso, char *which, int flag)
{
 int gu_flag= 0, ret;

 if(strcmp(which,"in")==0)
   gu_flag= 1;
 else if(strcmp(which,"out")==0)
   gu_flag= 2;
 else if(strcmp(which,"on")==0) {
   xorriso->do_calm_drive|= 1;
 } else if(strcmp(which,"off")==0) {
   xorriso->do_calm_drive&= ~1;
 } else if(strcmp(which,"revoke")==0) {
   gu_flag= 7;
 } else
   gu_flag= 3;
 ret= Xorriso_drive_snooze(xorriso, gu_flag);
 return(ret);
}


/* Option -cd alias -cdi */
int Xorriso_option_cdi(struct XorrisO *xorriso, char *iso_rr_path, int flag)
{
 char sfe[5*SfileadrL], path[SfileadrL], eff_path[SfileadrL];
 int ret;

 if (strlen(iso_rr_path)>sizeof(xorriso->wdi)) {
   sprintf(xorriso->info_text,"-cdi: iso_rr_path too long (%d > %d)",
           (int) strlen(iso_rr_path), (int) sizeof(xorriso->wdi)-1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 Xorriso_warn_of_wildcards(xorriso, iso_rr_path, 1);
 sprintf(xorriso->info_text,"previous working directory:\n");
 Xorriso_info(xorriso,0);
 sprintf(xorriso->result_line,"%s/\n",Text_shellsafe(xorriso->wdi, sfe, 0));
 Xorriso_result(xorriso,0);
 if(strcmp(iso_rr_path,"/")==0 || iso_rr_path[0]==0) {
   strcpy(xorriso->wdi,"");
   Xorriso_option_pwdi(xorriso, 0);
   return(1);
 } else if(iso_rr_path[0]!='/') {
   strcpy(path, xorriso->wdi);
   if(Sfile_add_to_path(path,iso_rr_path,0)<=0)
     return(-1);
 } else {
   if(Sfile_str(path,iso_rr_path,0)<=0)
     return(-1);
 }

 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1);
 if(ret<0)
   return(ret);
 if(ret==0) {
   sprintf(xorriso->info_text, "-cdi: not existing yet in ISO image : %s",
           Text_shellsafe(path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2);
   if(ret<=0)
     return(ret);
 } else if(ret!=2) {
   sprintf(xorriso->info_text, "-cdi: not a directory : %s",
           Text_shellsafe(eff_path, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 strcpy(xorriso->wdi, eff_path);

 Xorriso_option_pwdi(xorriso, 0);
 return(1);
}


/* Option -cdx */
int Xorriso_option_cdx(struct XorrisO *xorriso, char *disk_path, int flag)
{
 char sfe[5*SfileadrL], path[SfileadrL], eff_path[SfileadrL];
 int ret;

 if (strlen(disk_path)>sizeof(xorriso->wdx)) {
   sprintf(xorriso->info_text,"-cdx: disk_path too long (%d > %d)",
           (int) strlen(disk_path), (int) sizeof(xorriso->wdx)-1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 Xorriso_warn_of_wildcards(xorriso, disk_path, 1|2);
 sprintf(xorriso->info_text,"previous working directory on hard disk:\n");
 Xorriso_info(xorriso,0);
 sprintf(xorriso->result_line,"%s/\n",Text_shellsafe(xorriso->wdx, sfe, 0));
 Xorriso_result(xorriso,0);
 if(strcmp(disk_path,"/")==0) {
   strcpy(xorriso->wdx,"");
   Xorriso_option_pwdx(xorriso, 0);
   return(1);
 } else if(disk_path[0]!='/') {
   strcpy(path, xorriso->wdx);
   if(Sfile_add_to_path(path,disk_path,0)<=0)
     return(-1);
 } else {
   if(Sfile_str(path,disk_path,0)<=0)
     return(-1);
 }

 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, path, eff_path, 2|4);
 if(ret<=0)
   return(ret);
 if(eff_path[0]) {
   ret= Sfile_type(eff_path,1|4|8);
   if(ret<0) {
     Xorriso_msgs_submit(xorriso, 0, eff_path, 0, "ERRFILE", 0);
     sprintf(xorriso->info_text,"-cdx: file not found : %s",
             Text_shellsafe(eff_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   if(ret!=2) {
     Xorriso_msgs_submit(xorriso, 0, eff_path, 0, "ERRFILE", 0);
     sprintf(xorriso->info_text,
             "-cdx: not a directory : %s",
             Text_shellsafe(eff_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 if(Sfile_str(xorriso->wdx,eff_path,0)<=0)
   return(-1);
 Xorriso_option_pwdx(xorriso, 0);
 return(1);
}


/* Option -charset */
/* @param flag bit0= set in_charset
               bit1= set out_charset
               bit2= set local_charset
*/
int Xorriso_option_charset(struct XorrisO *xorriso, char *name, int flag)
{
 int ret;
 char *name_pt= NULL, sfe[5 * SfileadrL], *local_charset;
 iconv_t iconv_ret= (iconv_t) -1;

 if(name != NULL)
   if(name[0] != 0)
     name_pt= name;
 if(flag & 4) {
   ret= Xorriso_set_local_charset(xorriso, name_pt, 0);
   if(ret <= 0)
     return(ret);
 }
 if(flag & 1) {
   if(name_pt != NULL) {
     Xorriso_get_local_charset(xorriso, &local_charset, 0);
     iconv_ret= iconv_open(local_charset, name_pt);
     if(iconv_ret == (iconv_t) -1) {
       sprintf(xorriso->info_text,
               "-%scharset: Cannot convert from character set %s",
               flag & 2 ? "" : "in_", Text_shellsafe(name_pt, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
                           0);
       return(0);
     } else
       iconv_close(iconv_ret);
   }
   if(Sregex_string(&(xorriso->in_charset), name_pt, 0) <= 0) {
     Xorriso_no_malloc_memory(xorriso, NULL, 0);
     return(-1);
   }
 }
 if(flag & 2) {
   if(name_pt != NULL) {
     Xorriso_get_local_charset(xorriso, &local_charset, 0);
     iconv_ret= iconv_open(local_charset, name_pt);
     if(iconv_ret == (iconv_t) -1) {
       sprintf(xorriso->info_text, "-%scharset: Cannot convert to charset %s",
               flag & 1 ? "" : "out_", Text_shellsafe(name_pt, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
                           0);
       return(0);
     } else
       iconv_close(iconv_ret);
   }
   if(Sregex_string(&(xorriso->out_charset), name_pt, 0) <= 0) {
     Xorriso_no_malloc_memory(xorriso, NULL, 0);
     return(-1);
   }
 }
 if(flag & 3) {
   if(name_pt == NULL)
     Xorriso_get_local_charset(xorriso, &name_pt, 0);
   sprintf(xorriso->info_text, "Character set for %sconversion is now: %s",
           (flag & 3) == 1 ? "input " : (flag & 3) == 2 ? "output " : "",
           Text_shellsafe(name_pt, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 }
 return(1);
}


/* Options -check_md5 and -check_md5_r
   @param flag bit0= issue summary message
               bit1= do not reset pacifier, no final pacifier message
         >>>   bit2= do not issue pacifier messages at all
               bit3= recursive: -check_md5_r
*/
int Xorriso_option_check_md5(struct XorrisO *xorriso,
                             int argc, char **argv, int *idx, int flag)
{
 int ret, i, mem_pci, end_idx, fret, sev, do_report= 0;
 int optc= 0;
 char **optv= NULL, *cpt, *severity= "ALL";
 struct FindjoB *job= NULL;
 double mem_lut= 0.0;

 mem_pci= xorriso->pacifier_interval;

 ret= Xorriso_opt_args(xorriso, "-check_md5", argc, argv, *idx + 1, 
                       &end_idx, &optc, &optv, 128);
 if(ret<=0)
   goto ex;

 /* Interpret argv[*idx] as severity */
 if(argc <= *idx) {
   sprintf(xorriso->info_text,
           "-check_md5: No event severity given for case of mismatch");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }
 severity= argv[*idx];
 ret= Xorriso__text_to_sev(severity, &sev, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text, "-check_md5: Not a known severity name : ");
   Text_shellsafe(severity, xorriso->info_text, 1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   goto ex;
 }

 if(!(flag & (2 | 4))) {
   Xorriso_pacifier_reset(xorriso, 0);
   mem_lut= xorriso->last_update_time;
 }
 xorriso->pacifier_interval= 5.0;

 xorriso->find_check_md5_result= 0;

 if(optc == 0) {
   ret= Xorriso_check_session_md5(xorriso, severity, 0);
   do_report= 1;
   goto ex;
 } 

 for(i= 0; i < optc; i++) {
   if(flag & 8) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-check_md5_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_target(job, 35, severity, 0);
     cpt= optv[i];
     ret= Xorriso_findi_sorted(xorriso, job, (off_t) 0, 1, &cpt, 0);
     Findjob_destroy(&job, 0);
     if(ret > 0)
       ret= xorriso->find_compare_result;
     else {
       ret= -1;
       xorriso->find_check_md5_result|= 2;
     }
   } else {
     ret= Xorriso_check_md5(xorriso, NULL, optv[i], 4);
     if(ret < 0) 
       xorriso->find_check_md5_result|= 2;
     else if(ret == 0)
       xorriso->find_check_md5_result|= 1;
     else if(ret == 1)
       xorriso->find_check_md5_result|= 8;
     else if(ret == 2)
       xorriso->find_check_md5_result|= 4;
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto report_outcome;
 }
 ret= 1;

report_outcome:;
 do_report= 1;

ex:;
 if(!(flag & (2 | 4))) {
   xorriso->pacifier_interval= mem_pci;
   if(mem_lut!=xorriso->last_update_time && !(flag&2))
     Xorriso_pacifier_callback(xorriso, "content bytes read",
                               xorriso->pacifier_count, 0, "", 1);
 }
 if(do_report) {
   if(optc == 0) {
     if(ret <= 0) {
       sprintf(xorriso->result_line,
               "MD5 MISMATCH WITH DATA OF LOADED SESSION !\n");
       Xorriso_result(xorriso,0);
       if(strcmp(severity, "ALL") != 0) {
         sprintf(xorriso->info_text,
                 "Event triggered by MD5 comparison mismatch");
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, severity, 0);
       }
     } else {
       sprintf(xorriso->result_line, "Ok, session data match recorded md5.\n");
       Xorriso_result(xorriso,0);
     }
   } else {
     Xorriso_report_md5_outcome(xorriso, severity, 0);
   }
 }
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-getfacl", argc, argv, *idx, &end_idx,
                  &optc, &optv, 256); 
 Findjob_destroy(&job, 0);
 if(ret <= 0)
   return(ret);
 return((xorriso->find_check_md5_result & 3) == 0);
}


/* Option -check_media */
int Xorriso_option_check_media(struct XorrisO *xorriso,
                               int argc, char **argv, int *idx, int flag)
{
 int ret, i, count, lba, blocks, quality, pass, was_md5= 0, was_event= 0;
 int end_idx, old_idx, os_errno;
 char quality_name[80], head_buffer[64*1024];
 struct SpotlisT *spotlist= NULL;
 struct CheckmediajoB *job= NULL;
 struct FindjoB *findjob= NULL;
 struct stat dir_stbuf;

 old_idx= *idx;
 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 (*idx)= end_idx;

 ret= Checkmediajob_new(&job, 0);
 if(ret <= 0)
   goto ex;
 ret= Xorriso_check_media_setup_job(xorriso, job, argv, old_idx, end_idx, 0);
 if(ret <= 0)
   goto ex;

 if((job->report_mode == 1 || job->report_mode == 2) && job->use_dev == 1) {
   sprintf(xorriso->info_text,
           "-check_media: cannot report=*files while use=outdef");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }
 if(job->patch_lba0 && job->data_to_path[0] == 0) {
   sprintf(xorriso->info_text,
      "-check_media: cannot apply patch_lba0= while data_to= has empty value");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }

 if(job->use_dev == 2) {
   if(job->sector_map_path[0] == 0) {
     sprintf(xorriso->info_text,
             "-check_media: option use=sector_map but sector_map=''");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   }
   ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path,
                               xorriso->info_text, &os_errno, 0);
   if(ret <= 0) {
     if(xorriso->info_text[0])
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno,
                           "FAILURE", 0);
     goto ex;
   }
   ret= Xorriso_sectormap_to_spotlist(xorriso, job, &spotlist, 0);
   if(ret <= 0)
     goto ex;
   Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
   ret= Sectorbitmap_clone(job->sector_map, &(xorriso->in_sector_map), 0);
   if(ret <= 0) 
     goto ex;
 } else {
   ret= Xorriso_check_media(xorriso, &spotlist, job, 0);
   if(ret <= 0)
     goto ex;
 }

 if(job->patch_lba0) {
   ret= Xorriso_open_job_data_to(xorriso, job, 0);
   if(ret <= 0)
     goto ex;
   if(ret == 1) {
     ret= Xorriso_update_iso_lba0(xorriso, job->patch_lba0_msc1, 0,
                                  head_buffer, job,
                                  (8 * (job->patch_lba0 == 1)) |
                                  4 | (job->patch_lba0_msc1 < 0));
     if(ret <= 0)
       goto ex;
   }
 }

 if(job->report_mode == 0 || job->report_mode == 2) { /* report blocks */
   for(pass= 0; pass < 2; pass++) {
     if(pass == 0) {
       sprintf(xorriso->result_line,
               "Media checks :        lba ,       size , quality\n");
     } else {
       if(!was_md5)
   break;
       sprintf(xorriso->result_line,
               "MD5 checks   :        lba ,       size , result\n");
     }
     Xorriso_result(xorriso,0);
     count= Spotlist_count(spotlist, 0);
     for(i= 0; i < count; i++) {
       ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0);
       if(ret <= 0)
     continue;
       if(pass == 0) {
         if(quality == Xorriso_read_quality_md5_mismatcH ||
            quality == Xorriso_read_quality_unreadablE) {
           was_event= 1;
         }
         if(quality == Xorriso_read_quality_md5_matcH ||
            quality == Xorriso_read_quality_md5_mismatcH) {
           was_md5= 1;
     continue;
         }
       }
       else if(pass == 1 && !(quality == Xorriso_read_quality_md5_matcH ||
                              quality == Xorriso_read_quality_md5_mismatcH))
     continue;
       sprintf(xorriso->result_line, "%s: %10d , %10d , %s\n",
               pass == 0 ? "Media region " : "MD5 tag range",
               lba, blocks, Spotlist__quality_name(quality, quality_name,
                                           xorriso->check_media_bad_limit, 0));
       Xorriso_result(xorriso,0);
     }
   }
 }
 if(job->report_mode == 1 || job->report_mode == 2) { /* report files */
   ret= Findjob_new(&findjob, "/", 0);
   if(ret<=0) {
     Xorriso_no_findjob(xorriso, "-check_media report=files", 0);
     {ret= -1; goto ex;}
   }
   Findjob_set_damage_filter(findjob, 1, 0);
   Findjob_set_action_target(findjob, 21, NULL, 0);
   ret= Xorriso_findi(xorriso, findjob, NULL, (off_t) 0,
                      NULL, "/", &dir_stbuf, 0, 0);
   Findjob_destroy(&findjob, 0);
   if(ret <= 0)
     goto ex;
 }
 ret= 1;
ex:;
 if(was_event && strcmp(job->event_severity, "ALL") != 0) {
   sprintf(xorriso->info_text,
           "Event triggered by media read error or MD5 comparison mismatch");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, job->event_severity,
                       0);
 }
 Spotlist_destroy(&spotlist, 0);
 Checkmediajob_destroy(&job, 0);
 return(ret);
}


/* Option -check_media_defaults */
int Xorriso_option_check_media_defaults(struct XorrisO *xorriso,
                                     int argc, char **argv, int *idx, int flag)
{
 int ret, old_idx, end_idx;
 struct CheckmediajoB *job= NULL;

 old_idx= *idx;
 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 (*idx)= end_idx;

 ret= Checkmediajob_new(&job, 0);
 if(ret <= 0)
   goto ex;
 ret= Xorriso_check_media_setup_job(xorriso, job, argv, old_idx, end_idx, 0);
 if(ret <= 0)
   goto ex;
 Checkmediajob_destroy(&(xorriso->check_media_default), 0);
 xorriso->check_media_default= job;
 job= NULL;
 ret= 1;
ex:;
 Checkmediajob_destroy(&job, 0);
 return(ret);
}


/* Option -chgrp alias -chgrpi , chgrp_r alias chgrpi */
/* @param flag bit0=recursive (-chgrp_r)
*/
int Xorriso_option_chgrpi(struct XorrisO *xorriso, char *gid,
                          int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 gid_t gid_number;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-chgrpi", argc, argv, *idx, &end_idx, &optc,
                       &optv, 0);
 if(ret<=0)
   goto ex; 
 ret= Xorriso_convert_gidstring(xorriso, gid, &gid_number, 0);
 if(ret<=0)
   goto ex; 
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-chgrp_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_chgrp(job, gid_number, 0);
     ret= Xorriso_findi(xorriso, job, NULL,  (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else 
     ret= Xorriso_set_gid(xorriso, optv[i], gid_number, 0);
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-chgrpi", argc, argv, *idx, &end_idx, &optc, &optv,
                  256); /* clean up */
 if(ret<=0)
   return(ret);
 Findjob_destroy(&job, 0);
 return(!was_failure);
}


/* Option -chmod alias -chmodi , -chmod_r alias chmod_ri */
/* @param flag bit0=recursive (-chmod_r)
*/
int Xorriso_option_chmodi(struct XorrisO *xorriso, char *mode,
                          int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 mode_t mode_and= ~0, mode_or= 0;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-chmodi", argc, argv, *idx, &end_idx, &optc,
                       &optv, 0);
 if(ret<=0)
   goto ex; 
 ret= Xorriso_convert_modstring(xorriso, "-chmodi",
                                mode, &mode_and, &mode_or, 0);
 if(ret<=0)
   goto ex;
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-chmod_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_chmod(job, mode_and, mode_or, 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else {
     ret= Xorriso_set_st_mode(xorriso, optv[i], mode_and, mode_or, 0);
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-chmodi", argc, argv, *idx, &end_idx, &optc, &optv,
                  256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -chown alias -chowni , chown_r alias chown_ri */
/* @param flag bit0=recursive (-chown_r)
*/
int Xorriso_option_chowni(struct XorrisO *xorriso, char *uid,
                          int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 uid_t uid_number;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-chowni", argc, argv, *idx, &end_idx,
                       &optc, &optv, 0);
 if(ret<=0)
   goto ex;
 ret= Xorriso_convert_uidstring(xorriso, uid, &uid_number, 0);
 if(ret<=0)
   goto ex; 
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-chown_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_chown(job, uid_number, 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else 
     ret= Xorriso_set_uid(xorriso, optv[i], uid_number, 0);
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-chowni", argc, argv, *idx, &end_idx,
                  &optc, &optv, 256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -close "on"|"off" */
int Xorriso_option_close(struct XorrisO *xorriso, char *mode, int flag)
{
 xorriso->do_close= !!strcmp(mode, "off");
 return(1);
}


/* Option -close_filter_list */
int Xorriso_option_close_filter_list(struct XorrisO *xorriso, int flag)
{
 xorriso->filter_list_closed= 1;
 return(1);
}


/* Option -commit */
/* @param flag bit0= leave indrive and outdrive aquired as they were,
                     i.e. do not aquire outdrive as new in-out-drive
               bit1= do not perform eventual -reassure
   @return <=0 error , 1 success, 2 revoked by -reassure , 3 no change pending
*/
int Xorriso_option_commit(struct XorrisO *xorriso, int flag)
{
 int ret;
 char newdev[SfileadrL];

 if(!xorriso->volset_change_pending) {
   sprintf(xorriso->info_text, "-commit: No image modifications pending");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   return(3);
 }
 if(!(flag&2)) {
   ret= Xorriso_reassure(xorriso, "-commit",
                         "write the pending image changes to media", 0);
   if(ret<=0)
     return(2);
 }
 Xorriso_process_errfile(xorriso, 0, "burn session start", 0, 1);
 ret= Xorriso_write_session(xorriso, 0);
 Xorriso_process_errfile(xorriso, 0, "burn session end", 0, 1);
 if(ret<=0)
   return(ret);
 Xorriso_write_session_log(xorriso, 0);
 xorriso->volset_change_pending= 0;
 xorriso->no_volset_present= 0;
 if(flag&1)
   return(1);
 if(Sregex_string(&(xorriso->in_charset), xorriso->out_charset, 0) <= 0)
   return(-1);
 strcpy(newdev, xorriso->outdev);
 if(xorriso->grow_blindly_msc2>=0)
   ret= Xorriso_option_dev(xorriso, "", 3|4);
 else
   ret= Xorriso_option_dev(xorriso, newdev, 3|4);
 return(ret);
}


/* Option -commit_eject */
/* @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_commit_eject(struct XorrisO *xorriso, char *which, int flag)
{
 int ret, eret;

 ret= Xorriso_option_commit(xorriso, 1);
 if(ret<=0 || ret==2 || ret==3)
   return(ret);
 if(strcmp(which, "none")==0)
   eret= 1;
 else
   eret= Xorriso_option_eject(xorriso, which, 1);
 ret= Xorriso_option_dev(xorriso, "", 3|4);
 if(eret<ret)
   return(eret);
 return(ret);
}


/* Options -compare and -compare_r
   @param flag bit0= issue summary message
               bit1= do not reset pacifier, no final pacifier message
               bit2= do not issue pacifier messages at all
               bit3= recursive: -compare_r
*/
int Xorriso_option_compare(struct XorrisO *xorriso, char *disk_path,
                           char *iso_path, int flag)
{
 int ret, mem_pci, zero= 0, result, follow_links;
 double mem_lut= 0.0;
 char *ipth, *argv[6], eff_origin[SfileadrL], eff_dest[SfileadrL];

 ipth= iso_path;
 if(ipth[0]==0)
   ipth= disk_path;
 if(disk_path[0]==0) {
   sprintf(xorriso->info_text, "-compare: Empty disk_path given");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
   return(0);
 }
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin,
                                 2|4|8);
 if(ret<=0)
   return(ret);
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2|8);
 if(ret<=0)
   return(ret);

 if(xorriso->disk_excl_mode&8)
   ret= Xorriso_path_is_excluded(xorriso, eff_origin, 1);
 else
   ret= 0;
 if(ret!=0)
   goto report_outcome;
 if(!(flag&2)) {
   Xorriso_pacifier_reset(xorriso, 0);
   mem_lut= xorriso->last_update_time;
 }
 mem_pci= xorriso->pacifier_interval;
 xorriso->pacifier_interval= 5.0;

 if(flag&8) {
   xorriso->find_compare_result= 1;
   argv[0]= eff_dest;
   argv[1]= "-exec";
   argv[2]= "compare";
   argv[3]= eff_origin;
   zero= 0;
   ret= Xorriso_option_find(xorriso, 4, argv, &zero, 2); /* -findi */
   if(ret>0) {
     argv[0]= eff_origin;
     argv[1]= "-exec";
     argv[2]= "not_in_iso";
     argv[3]= eff_dest;
     zero= 0;
     ret= Xorriso_option_find(xorriso, 4, argv, &zero, 1|2); /* -findx */
     if(ret>0 && !xorriso->do_follow_mount) {
       argv[0]= eff_origin;
       argv[1]= "-type";
       argv[2]= "m";
       argv[3]= "-exec";
       argv[4]= "is_full_in_iso";
       argv[5]= eff_dest;
       zero= 0;
       ret= Xorriso_option_find(xorriso, 6, argv, &zero, 1|2); /* -findx */
     }
     if(ret>0)
       ret= xorriso->find_compare_result;
     else
       ret= -1;
   } else
     ret= -1;
 } else {
   follow_links= (xorriso->do_follow_links || xorriso->do_follow_param) << 28;
   ret= Xorriso_compare_2_files(xorriso, eff_origin, eff_dest, "", &result,
                                  2 | follow_links | ((flag&4)<<27) | (1<<30));
 }

 xorriso->pacifier_interval= mem_pci;
 if(mem_lut!=xorriso->last_update_time && !(flag&2))
   Xorriso_pacifier_callback(xorriso, "content bytes read",
                             xorriso->pacifier_count, 0, "", 1);
report_outcome:;
 if(ret>0) {
   sprintf(xorriso->result_line,
           "Both file objects match as far as expectable.\n");
 } else if(ret==0) {
   sprintf(xorriso->result_line, "Differences detected.\n");
 } else {
   sprintf(xorriso->result_line, "Comparison failed due to error.\n");
 }
 if(flag&1)
   Xorriso_result(xorriso,0);
 if(ret<0)
   return(ret);
 return(1);
}


/* Option -compliance */
int Xorriso_option_compliance(struct XorrisO *xorriso, char *mode,
                                    int flag)
{
 return(Xorriso_relax_compliance(xorriso, mode, 0));
}


/* Option -cpr alias -cpri */
int Xorriso_option_cpri(struct XorrisO *xorriso, int argc, char **argv,
                         int *idx, int flag)
{
 int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy;
 char eff_origin[SfileadrL], eff_dest[SfileadrL];
 char dest_dir[SfileadrL], leafname[SfileadrL];
 int optc= 0;
 char **optv= NULL;

 ret= Xorriso_cpmv_args(xorriso, "-cpri", argc, argv, idx,
                        &optc, &optv, eff_dest, 1|2);
 if(ret<=0)
   goto ex;
 if(ret==2) {
   is_dir= 1;
   strcpy(dest_dir, eff_dest);
 }

 /* Perform graft-ins */
 Xorriso_pacifier_reset(xorriso, 0);
 for(i= 0; i<optc && !xorriso->request_to_abort; i++) {
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, optv[i], eff_origin,
                                   2|4);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   if(is_dir) {
     ret= Sfile_leafname(eff_origin, leafname, 0);
     if(ret<=0)
       goto problem_handler;
     strcpy(eff_dest, dest_dir);
     ret= Sfile_add_to_path(eff_dest, leafname, 0);
     if(ret<=0) {
       sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
             (int) (strlen(eff_dest)+ strlen(leafname)+1));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       goto problem_handler;
     }
   }
   ret= Xorriso_graft_in(xorriso, NULL, eff_origin, eff_dest,
                         (off_t) 0, (off_t) 0, 0);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n",
           (ret>1 ? "directory" : "file"), (eff_dest[0] ? eff_dest : "/"),
           eff_origin);
   if(!(flag&1))
     Xorriso_info(xorriso, 0);
 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                               xorriso->pacifier_total, "", 1);
 ret= !was_failure;
ex:;
 Xorriso_opt_args(xorriso, "-cpri",
                  argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256);
 return(ret);
}


/* Options -cpx , -cpax, -cp_rx , -cp_rax */
/* @param flag bit0= recursive (-cp_rx, -cp_rax)
               bit1= full property restore (-cpax, -cp_rax)
*/
int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv,
                         int *idx, int flag)
{
 int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy;
 char eff_origin[SfileadrL], eff_dest[SfileadrL];
 char dest_dir[SfileadrL], leafname[SfileadrL], sfe[5*SfileadrL];
 char **eff_src_array= NULL, **eff_tgt_array= NULL;

 int optc= 0;
 char **optv= NULL;
 struct stat stbuf;

 ret= Xorriso_cpmv_args(xorriso, "-cp*x", argc, argv, idx,
                        &optc, &optv, eff_dest, 1|4);
 if(ret<=0)
   goto ex;
 if(ret==2) {
   is_dir= 1;
   strcpy(dest_dir, eff_dest);
 }
 if(xorriso->allow_restore <= 0) {
   sprintf(xorriso->info_text,
          "-cpx: image-to-disk copies are not enabled by option -osirrox");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }

 if(xorriso->do_restore_sort_lba || !(xorriso->ino_behavior & 4)) {
   eff_src_array= calloc(optc, sizeof(char *));
   eff_tgt_array= calloc(optc, sizeof(char *));
   if(eff_src_array == NULL || eff_tgt_array == NULL) {
     Xorriso_no_malloc_memory(xorriso, NULL, 0);
     ret= -1; goto ex;
   }
   for(i= 0; i < optc; i++)
     eff_src_array[i]= eff_tgt_array[i]= NULL;
 }

 /* Perform copying */
 Xorriso_pacifier_reset(xorriso, 0);
 for(i= 0; i<optc && !xorriso->request_to_abort; i++) {
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, optv[i], eff_origin,
                                   2|8);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;

   ret= Xorriso_iso_lstat(xorriso, eff_origin, &stbuf, 2|4);
   if(ret==-1)
     goto problem_handler;
   if(S_ISDIR(stbuf.st_mode) && !(flag&1)) {
     /* only allow directories if they actually represent split data files */
     ret= 0;
     if(xorriso->do_concat_split)
       ret= Xorriso_is_split(xorriso, eff_origin, NULL, 0);
     if(ret<0)
       goto problem_handler;
     if(ret==0) {
       sprintf(xorriso->info_text, "-cpx: May not copy directory %s",
               Text_shellsafe(eff_origin, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto problem_handler;
     }
   }

   if(is_dir && strcmp(eff_origin, "/")!=0) {
     ret= Sfile_leafname(eff_origin, leafname, 0);
     if(ret<=0)
       goto problem_handler;
     strcpy(eff_dest, dest_dir);
     ret= Sfile_add_to_path(eff_dest, leafname, 0);
     if(ret<=0) {
       sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
             (int) (strlen(eff_dest)+strlen(leafname)+1));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       goto problem_handler;
     }
   }
   if(eff_src_array != NULL) {
     eff_src_array[i]= strdup(eff_origin);
     eff_tgt_array[i]= strdup(eff_dest);
     if(eff_src_array[i] == NULL || eff_tgt_array[i] == NULL) {
       Xorriso_no_malloc_memory(xorriso, &(eff_src_array[i]), 0);
       ret= -1; goto ex;
     }
   } else {
     ret= Xorriso_restore(xorriso, eff_origin, eff_dest, (off_t) 0, (off_t) 0,
                          16 | ((!(flag&2))<<6));
     if(ret<=0 || xorriso->request_to_abort)
       goto problem_handler;
     if(ret==3 || (flag&1))
 continue;
     sprintf(xorriso->info_text,
             "Copied from ISO image to disk: %s '%s' = '%s'\n",
             (ret>1 ? "directory" : "file"), eff_origin, eff_dest);
     Xorriso_info(xorriso, 0);
   }
 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }

 if(eff_src_array != NULL) {
   ret= Xorriso_restore_sorted(xorriso, optc, eff_src_array, eff_tgt_array, 0);
   if(ret <= 0)
     was_failure= 1;
 }
 if(xorriso->pacifier_count>0)
   Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1|4);
 ret= !was_failure;
ex:;
 i= optc;
 Sfile_destroy_argv(&i, &eff_src_array, 0);
 i= optc; 
 Sfile_destroy_argv(&i, &eff_tgt_array, 0);
 Xorriso_opt_args(xorriso, "-cp*x",
                  argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256);
 return(ret);
}


/* Option -cut_out */
int Xorriso_option_cut_out(struct XorrisO *xorriso, char *disk_path,
               char *start, char *count, char *iso_rr_path, int flag)
{
 int ret;
 double num;
 off_t startbyte, bytecount;
 
 num= Scanf_io_size(start, 0);
 if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */
   sprintf(xorriso->info_text,
         "-cut_out: startbyte address negative or much too large (%s)", start);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 startbyte= num;
 num= Scanf_io_size(count, 0);
 if(num<=0 || num > 1.0e18) {
   sprintf(xorriso->info_text,
           "-cut_out: bytecount zero, negative or much too large (%s)", count);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 bytecount= num;
 sprintf(xorriso->info_text, 
         "-cut_out from %s , byte %.f to %.f, and graft as %s",
         disk_path, (double) startbyte, (double) (startbyte+bytecount),
         iso_rr_path);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);

 ret= Xorriso_cut_out(xorriso, disk_path, startbyte, bytecount,
                      iso_rr_path, 0); 
 return(ret);
}


/* Options -dev , -indev, -outdev */
/** @param flag bit0= use as indev
                bit1= use as outdev
                bit2= do not -reassure
                bit3= regard overwriteable media as blank
                bit4= if the drive is a regular disk file: truncate it to
                      the write start address
                bit5= do not print toc of aquired drive
                bit6= do not calm down drive after aquiring it
    @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_dev(struct XorrisO *xorriso, char *in_adr, int flag)
{
 int ret;
 char sfe[5*SfileadrL], *adr;

 adr= in_adr;
 if(strcmp(in_adr, "-")==0)
   adr= "stdio:/dev/fd/1";
 if(strncmp(adr, "stdio:", 6)==0) {
   if(strlen(adr)==6 || strcmp(adr, "stdio:/")==0 ||
      strcmp(adr, "stdio:.")==0 || strcmp(adr, "stdio:..")==0 ||
      strcmp(adr, "stdio:-")==0) {
     sprintf(xorriso->info_text,
             "No suitable path given by device address '%s'", adr);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }

 if(xorriso->volset_change_pending && (flag&1)) {
   sprintf(xorriso->info_text,
           "%s: Image changes pending. -commit or -rollback first",
           (flag&2) ? "-dev" : "-indev");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if((flag&1) && (xorriso->in_drive_handle != NULL || adr[0]) && !(flag&4)) {
   ret= Xorriso_reassure(xorriso, (flag&2) ? "-dev" : "-indev",
                         "eventually discard the current image", 0);
   if(ret<=0)
     return(2);
 }

 if(adr[0]==0) {
   if((flag&1) && xorriso->in_drive_handle != NULL) {
     if(xorriso->in_drive_handle == xorriso->out_drive_handle)
       sprintf(xorriso->info_text,"Giving up -dev %s", 
               Text_shellsafe(xorriso->indev, sfe, 0));
     else
       sprintf(xorriso->info_text,"Giving up -indev %s",
               Text_shellsafe(xorriso->indev, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   }
   if((flag&2) && xorriso->out_drive_handle != NULL &&
      xorriso->in_drive_handle != xorriso->out_drive_handle) {
     sprintf(xorriso->info_text,"Giving up -outdev %s",
             Text_shellsafe(xorriso->outdev, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   }
   ret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2));
 } else
   ret= Xorriso_aquire_drive(xorriso, adr,
                          (flag & (3 | 32 | 64)) | (((flag & (8 | 16)) >> 1))); 
 if(ret<=0)
   return(ret);
 if(xorriso->in_drive_handle == NULL)
   xorriso->image_start_mode= 0; /* session setting is invalid by now */
 return(1);
}


/* Option -devices */
/* @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_devices(struct XorrisO *xorriso, int flag)
{
 int ret;
 char sfe[5*SfileadrL];

 if(xorriso->volset_change_pending) {
   sprintf(xorriso->info_text,
           "-devices: Image changes pending. -commit or -rollback first");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_reassure(xorriso, "-devices",
                       "eventually discard the current image", 0);
 if(ret<=0)
   return(2);
 xorriso->info_text[0]= 0;
 if(xorriso->in_drive_handle!=NULL || xorriso->out_drive_handle!=NULL) {
   if(xorriso->in_drive_handle == xorriso->out_drive_handle) {
     sprintf(xorriso->info_text, "Gave up -dev %s", 
             Text_shellsafe(xorriso->indev, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   }else {
     if(xorriso->in_drive_handle!=NULL) {
       sprintf(xorriso->info_text, "Gave up -indev %s", 
               Text_shellsafe(xorriso->indev, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     }
     if(xorriso->out_drive_handle!=NULL) {
       sprintf(xorriso->info_text, "Gave up -outdev %s", 
               Text_shellsafe(xorriso->outdev, sfe, 0));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     }
   }
   Xorriso_give_up_drive(xorriso, 3);
 }
 ret= Xorriso_show_devices(xorriso, 0);
 return(ret);
}


/* Option -dialog "on"|"single_line"|"off" */
int Xorriso_option_dialog(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "on") == 0 || strcmp(mode, "multi_line") == 0)
   xorriso->dialog= 2;
 else if(strcmp(mode, "single_line") == 0)
   xorriso->dialog= 2;
 else if(strcmp(mode, "off") == 0)
   xorriso->dialog= 0;
 else {
   sprintf(xorriso->info_text, "-dialog: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


/* Option -disk_dev_ino "on"|"ino_only"|"off" */
int Xorriso_option_disk_dev_ino(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "on") == 0)
   xorriso->do_aaip= (xorriso->do_aaip & ~128) | 16 | 32 | 64;
 else if(strcmp(mode, "ino_only") == 0)
   xorriso->do_aaip|= 16 | 32 | 64 | 128;
 else if(strcmp(mode, "off") == 0)
   xorriso->do_aaip &= ~(16 | 32 | 64 | 128);
 else {
   sprintf(xorriso->info_text, "-disk_dev_ino: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


/* Option -disk_pattern "on"|"ls"|"off" */
int Xorriso_option_disk_pattern(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_disk_pattern= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->do_disk_pattern= 1;
 else if(strcmp(mode, "ls")==0)
   xorriso->do_disk_pattern= 2;
 else {
   sprintf(xorriso->info_text, "-disk_pattern: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -drive_class */
int Xorriso_option_drive_class(struct XorrisO *xorriso,
                               char *d_class, char *pattern, int flag)
{
 int ret= 1;

 if(strcmp(d_class, "banned") == 0) {
   ret= Xorriso_lst_new(&(xorriso->drive_blacklist), pattern,
                          xorriso->drive_blacklist, 1);
 } else if(strcmp(d_class, "caution") == 0) {
   ret= Xorriso_lst_new(&(xorriso->drive_greylist), pattern,
                          xorriso->drive_greylist, 1);
 } else if (strcmp(d_class, "harmless") == 0) {
   ret= Xorriso_lst_new(&(xorriso->drive_whitelist), pattern,
                        xorriso->drive_whitelist, 1);
 } else if (strcmp(d_class, "clear_list") == 0) {
   if(strcmp(pattern, "banned") == 0)
     Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0);
   else if(strcmp(pattern, "caution") == 0)
     Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0);
   else if(strcmp(pattern, "harmless") == 0)
     Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0);
   else if(strcmp(pattern, "all") == 0) {
     Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0);
     Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0);
     Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0);
   } else {
     sprintf(xorriso->info_text, "-drive_class clear : unknown class '%s'",
             pattern);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   ret= 1;
 } else {
   sprintf(xorriso->info_text, "-drive_class: unknown class '%s'", d_class);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(ret);
}


/* Option -dummy "on"|"off" */
int Xorriso_option_dummy(struct XorrisO *xorriso, char *mode, int flag)
{
 xorriso->do_dummy= !!strcmp(mode, "off");
 return(1);
}


/* Option -dvd_obs "default"|"32k"|"64k" */
int Xorriso_option_dvd_obs(struct XorrisO *xorriso, char *obs, int flag)
{
 double num;

 if(strcmp(obs, "default") == 0)
   num= 0;
 else
   num = Scanf_io_size(obs,0);
 if(num != 0 && num != 32768 && num != 65536) {
   sprintf(xorriso->info_text,
           "-dvd_obs : Bad size. Acceptable are 0, 32k, 64k");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 } else
   xorriso->dvd_obs= num;
 return(1);
}


/* Option -eject */
/* @param flag bit0=do not report toc of eventually remaining drives
*/
int Xorriso_option_eject(struct XorrisO *xorriso, char *which, int flag)
{
 int gu_flag= 4, ret;

 if(strncmp(which,"in",2)==0)
   gu_flag|= 1;
 else if(strncmp(which,"out",3)==0)
   gu_flag|= 2;
 else
   gu_flag|= 3;
 if((gu_flag&1) && xorriso->volset_change_pending) {
   sprintf(xorriso->info_text,
           "-eject: Image changes pending. -commit or -rollback first");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(flag&1)
   gu_flag|= 8;
 ret= Xorriso_give_up_drive(xorriso, gu_flag);
 return(ret);
}


/* Options -end , and -rollback_end */
/* @param flag bit0= discard pending changes
               bit1= do not -reassure
   @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_end(struct XorrisO *xorriso, int flag)
{
 int ret;
 char *cmd, *which_will;
 
 if(flag&1)
   cmd= "-rollback_end";
 else
   cmd= "-end";
 if(xorriso->volset_change_pending) {
   if(flag&1)
     which_will= "end the program discarding image changes";
   else
     which_will= "commit image changes and then end the program";
 } else {
   which_will= "end the program";
 }
 if(!(flag&2)) {
   ret= Xorriso_reassure(xorriso, cmd, which_will, 0);
   if(ret<=0)
     return(2);
 }

 if(xorriso->volset_change_pending) {
   if(flag&1) {
     xorriso->volset_change_pending= 0;
   } else {
     ret= Xorriso_option_commit(xorriso, 1);
     xorriso->volset_change_pending= 0; /* no further tries to commit */
     if(ret<=0)
       return(ret);
   }
 }
 ret= Xorriso_give_up_drive(xorriso, 3);
 if(ret<=0)
   return(ret);
 return(1);
}


/* Option -errfile_log marked|plain  path|-|"" */
int Xorriso_option_errfile_log(struct XorrisO *xorriso,
                               char *mode, char *path, int flag)
{
 int ret, mode_word;
 FILE *fp= NULL;
 char sfe[5*SfileadrL];

 if(path[0]==0 || path[0]=='-') {
   /* ok */;
 } else {
   fp= fopen(path, "a");
   if(fp==0) {
     sprintf(xorriso->info_text, "-errfile_log: Cannot open file %s",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 mode_word= xorriso->errfile_mode;
 if(strcmp(mode, "marked")==0)
   mode_word|= 1;
 else if(strcmp(mode, "plain")==0)
   mode_word&= ~1;
 else {
   sprintf(xorriso->info_text, "-errfile_log: Unknown mode %s",
           Text_shellsafe(mode, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 
 Xorriso_process_errfile(xorriso, 0, "log end", 0, 1);
 if(xorriso->errfile_fp!=NULL)
   fclose(xorriso->errfile_fp);
 xorriso->errfile_fp= fp;
 xorriso->errfile_mode= mode_word;
 ret= Sfile_str(xorriso->errfile_log, path, 0);
 if(ret>0)
   ret= Xorriso_process_errfile(xorriso, 0, "log start", 0, 1);
 if(ret<=0)
   return(ret);
 return(1);
}


/* Option -error_behavior */
int Xorriso_option_error_behavior(struct XorrisO *xorriso,
                                  char *occasion, char *behavior, int flag)
{
 if(strcmp(occasion, "image_loading")==0) {
   if(strcmp(behavior, "best_effort")==0)
     xorriso->img_read_error_mode= 0;
   else if(strcmp(behavior, "failure")==0 || strcmp(behavior, "FAILURE")==0)
     xorriso->img_read_error_mode= 1;
   else if(strcmp(behavior, "fatal")==0 || strcmp(behavior, "FATAL")==0)
     xorriso->img_read_error_mode= 2;
   else {
unknown_behavior:;
     sprintf(xorriso->info_text,
             "-error_behavior: with '%s': unknown behavior '%s'",
             occasion, behavior);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 } else if(strcmp(occasion, "file_extraction")==0) {
   if(strcmp(behavior, "best_effort")==0)
     xorriso->extract_error_mode= 0;
   else if(strcmp(behavior, "keep")==0)
     xorriso->extract_error_mode= 1;
   else if(strcmp(behavior, "delete")==0)
     xorriso->extract_error_mode= 2;
   else
     goto unknown_behavior;
 } else {
   sprintf(xorriso->info_text, "-error_behavior: unknown occasion '%s'",
           occasion);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -external_filter */
int Xorriso_option_external_filter(struct XorrisO *xorriso,
                                   int argc, char **argv, int *idx, int flag)
{
 int ret, start_idx, end_idx;

 start_idx= *idx;
 end_idx= Xorriso_end_idx(xorriso, argc, argv, start_idx, 1);
 (*idx)= end_idx;
 if(end_idx - start_idx < 3) {
   sprintf(xorriso->info_text,
 "-external_filter : Not enough arguments given. Needed: name options path %s",
           xorriso->list_delimiter);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_external_filter(xorriso, argv[start_idx],
                             argv[start_idx + 1], argv[start_idx + 2],
                             end_idx - start_idx - 3, argv + start_idx + 3, 0);
 return(ret);
}


/* Options -extract , -extract_single */
/* @param flag bit0=do not report the restored item
               bit1=do not reset pacifier, no final pacifier message
               bit2= do not make lba-sorted node array for hardlink detection
               bit5= -extract_single: eventually do not insert directory tree
*/
int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path,
                           char *disk_path, int flag)
{
 int ret;
 char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth, *eopt[1], *edpt[1];

 if(xorriso->allow_restore <= 0) {
   sprintf(xorriso->info_text,
          "-extract: image-to-disk copies are not enabled by option -osirrox");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   ret= 0; goto ex;
 }
 if(!(flag&2))
   Xorriso_pacifier_reset(xorriso, 0);

 ipth= iso_path;
 if(ipth[0]==0)
   ipth= disk_path;
 if(disk_path[0]==0) {
   sprintf(xorriso->info_text, "-extract: Empty disk_path given");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
   ret= 0; goto ex;
 }
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest,
                                 2|4);
 if(ret<=0)
   goto ex;
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_origin, 2|8);
 if(ret<=0)
   goto ex;

 eopt[0]= eff_origin;
 edpt[0]= eff_dest;
 ret= Xorriso_restore_sorted(xorriso, 1, eopt, edpt, (flag & 32 ? 33 : 0));

 if(!(flag&2))
   Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1|4);
 if(ret<=0)
   goto ex;

 if(!(flag&1)) {
   sprintf(xorriso->info_text, "Extracted from ISO image: %s '%s'='%s'\n",
           (ret>1 ? "directory" : "file"), eff_origin, eff_dest);
   Xorriso_info(xorriso,0);
 }
 ret= 1;
ex:;
 if(!(flag & (4 | 32)))
   Xorriso_destroy_node_array(xorriso, 0);
 return(ret);
}


/* Option -extract_cut */
int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *iso_rr_path,
                           char *start, char *count, char *disk_path, int flag)
{
 int ret;
 double num;
 off_t startbyte, bytecount;
 
 num= Scanf_io_size(start, 0);
 if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */
   sprintf(xorriso->info_text,
           "-extract_cut: startbyte address negative or much too large (%s)",
           start);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 startbyte= num;
 num= Scanf_io_size(count, 0);
 if(num<=0 || num > 1.0e18) {
   sprintf(xorriso->info_text,
           "-extract_cut: bytecount zero, negative or much too large (%s)",
           count);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 bytecount= num;
 sprintf(xorriso->info_text, 
         "-extract_cut from %s , byte %.f to %.f, and store as %s",
         iso_rr_path, (double) startbyte, (double) (startbyte+bytecount),
         disk_path);
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);

 ret= Xorriso_extract_cut(xorriso, iso_rr_path, disk_path,
                          startbyte, bytecount, 0); 
 return(ret);
}


/* Option -file_size_limit */
int Xorriso_option_file_size_limit(struct XorrisO *xorriso,
                                   int argc, char **argv, int *idx, int flag)
{
 int ret, i, end_idx;
 off_t new_limit= 0;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 if(*idx >= end_idx)
   {ret= 2; goto ex;}
 if(*idx + 1 == end_idx && strcmp(argv[*idx], "off") == 0) {
   xorriso->file_size_limit= 0;
   ret= 1; goto ex;
 }
 for(i= *idx; i < end_idx; i++)
   new_limit+= Scanf_io_size(argv[i], 0);
 if(new_limit <= 0) {
   sprintf(xorriso->info_text, "-file_size_limit: values sum up to %.f",
           (double) new_limit);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
   ret= 0; goto ex;
 }
 xorriso->file_size_limit= new_limit;
 ret= 1;
ex:;
 (*idx)= end_idx;
 if(ret > 0) {
   if(xorriso->file_size_limit > 0)
     sprintf(xorriso->info_text, "-file_size_limit now at %.f\n",
             (double) xorriso->file_size_limit);
   else
     sprintf(xorriso->info_text, "-file_size_limit now off\n");
   Xorriso_info(xorriso,0);
 }
 return(ret);
}


/* Option -find alias -findi, and -findx */
/* @param flag bit0= -findx rather than -findi
               bit1= do not reset pacifier, no final pacifier message
                     do not reset find_compare_result
               bit2= do not count deleted files with rm and rm_r
               bit3= use Xorriso_findi_sorted() rather than Xorriso_findi()
                     (this can also be ordered by test -sort_lba)
*/
int Xorriso_option_find(struct XorrisO *xorriso, int argc, char **argv,
                       int *idx, int flag)
{
 int ret, i, end_idx, type= 0, action, deleter= 0, start_lba, count;
 struct FindjoB *job, *first_job= NULL, *new_job;
 char *start_path, sfe[5*SfileadrL], *cpt, other_path_start[SfileadrL];
 char *access_acl_text= NULL, *default_acl_text= NULL;

 struct stat dir_stbuf;
 uid_t user= 0;
 gid_t group= 0;
 time_t date= 0;
 mode_t mode_or= 0, mode_and= ~1;
 double mem_lut= 0.0;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 start_path= ".";
 if(end_idx > *idx && start_path[0]!=0)
   start_path= argv[*idx];
 ret= Findjob_new(&first_job, start_path, 0);
 if(ret<=0) {
   Xorriso_no_findjob(xorriso, "-find[ix]", 0);
   {ret= -1; goto ex;}
 }
 job= first_job;
 if(!(flag&2))
   xorriso->find_compare_result= 1;
 for(i= *idx+1; i<end_idx; i++) {
   if(strcmp(argv[i], "-name")==0) {
     if(i+1>=end_idx) {
not_enough_arguments:;
       sprintf(xorriso->info_text,
               "-find[ix]: not enough arguments with test %s",
               Text_shellsafe(argv[i], sfe, 0));
       goto sorry_ex;
     }
     i++;
     ret= Findjob_set_name_expr(job, argv[i], 0);
     if(ret<=0) {
       sprintf(xorriso->info_text, "-find[ix]: cannot set -name expression %s",
               Text_shellsafe(argv[i], sfe, 0));
       goto sorry_ex;
     }
   } else if(strcmp(argv[i], "-wholename")==0) {
     if(i+1>=end_idx)
       goto not_enough_arguments;
     i++;
     ret= Findjob_set_name_expr(job, argv[i], 1);
     if(ret<=0) {
       sprintf(xorriso->info_text,
               "-find[ix]: cannot set -wholename expression %s",
               Text_shellsafe(argv[i], sfe, 0));
       goto sorry_ex;
     }
   } else if(strcmp(argv[i], "-type")==0) {
     if(i+1>=end_idx)
       goto not_enough_arguments;
     i++;
     ret= Findjob_set_file_type(job, argv[i][0], 0);
     if(ret<=0) {
       sprintf(xorriso->info_text, "-find[ix]: unknown -type '%c'",argv[i][0]);
       goto sorry_ex;
     }
   } else if(strcmp(argv[i], "-damaged")==0) {
     Findjob_set_damage_filter(job, 1, 0);
   } else if(strcmp(argv[i], "-undamaged")==0) {
     Findjob_set_damage_filter(job, -1, 0);
   } else if(strcmp(argv[i], "-lba_range")==0) {
     if(i+2>=end_idx)
       goto not_enough_arguments;
     i+= 2;
     sscanf(argv[i-1], "%d", &start_lba);
     sscanf(argv[i], "%d", &count);
     Findjob_set_lba_range(job, start_lba, count, 0);
   } else if(strcmp(argv[i], "-pending_data")==0) {
     Findjob_set_commit_filter_2(job, 0);
   } else if(strcmp(argv[i], "-has_acl")==0) {
     Findjob_set_acl_filter(job, 1, 0);
   } else if(strcmp(argv[i], "-has_no_acl")==0) {
     Findjob_set_acl_filter(job, -1, 0);
   } else if(strcmp(argv[i], "-has_xattr")==0) {
     Findjob_set_xattr_filter(job, 1, 0);
   } else if(strcmp(argv[i], "-has_any_xattr")==0) {
     Findjob_set_xattr_filter(job, 1, 1);
   } else if(strcmp(argv[i], "-has_no_xattr")==0) {
     Findjob_set_xattr_filter(job, -1, 0);
   } else if(strcmp(argv[i], "-has_aaip")==0) {
     Findjob_set_aaip_filter(job, 1, 0);
   } else if(strcmp(argv[i], "-has_no_aaip")==0) {
     Findjob_set_aaip_filter(job, -1, 0);
   } else if(strcmp(argv[i], "-has_filter")==0) {
     Findjob_set_filter_filter(job, 1, 0);
   } else if(strcmp(argv[i], "-has_no_filter")==0) {
     Findjob_set_filter_filter(job, -1, 0);
   } else if(strcmp(argv[i], "-has_md5")==0) {
     Findjob_set_prop_filter(job, 15, 1, 0);
   } else if(strcmp(argv[i], "-true") == 0) {
     ret= Findjob_set_false(job, -1, 0);
   } else if(strcmp(argv[i], "-false") == 0) {
     ret= Findjob_set_false(job, 1, 0);
   } else if(strcmp(argv[i], "-decision") == 0) {
     if(i+1>=end_idx)
       goto not_enough_arguments;
     i++;
     ret= Findjob_set_decision(job, argv[i], 0);
   } else if(strcmp(argv[i], "-prune") == 0) {
     ret= Findjob_set_prune(job, 0);
   } else if(strcmp(argv[i], "-sub") == 0 || strcmp(argv[i], "(") == 0) {
     ret= Findjob_open_bracket(job, 0);
   } else if(strcmp(argv[i], "-subend") == 0 || strcmp(argv[i], ")") == 0) {
     ret= Findjob_close_bracket(job, 0);
   } else if(strcmp(argv[i], "-not") == 0 || strcmp(argv[i], "!") == 0) {
     ret= Findjob_not(job, 0);
   } else if(strcmp(argv[i], "-and") == 0 || strcmp(argv[i], "-a") == 0) {
     ret= Findjob_and(job, 0);
   } else if(strcmp(argv[i], "-or") == 0 || strcmp(argv[i], "-o") == 0) {
     ret= Findjob_or(job, 0);
   } else if(strcmp(argv[i], "-if") == 0) {
     ret= Findjob_if(job, 0);
   } else if(strcmp(argv[i], "-then") == 0) {
     ret= Findjob_then(job, 0);
   } else if(strcmp(argv[i], "-else") == 0) {
     ret= Findjob_else(job, 0);
   } else if(strcmp(argv[i], "-elseif") == 0) {
     ret= Findjob_elseif(job, 0);
   } else if(strcmp(argv[i], "-endif") == 0) {
     ret= Findjob_endif(job, 0);
   } else if(strcmp(argv[i], "-sort_lba") == 0) {
     flag|= 8;
     /* If an operator is open: insert a -true test, else do nothing */
     ret= Findjob_set_false(job, -1, 1);
     if(ret == 2)
       ret= 1;
   } else if(strcmp(argv[i], "-exec")==0) {
     if(i+1>=end_idx) {
not_enough_exec_arguments:;
       sprintf(xorriso->info_text,
               "-find[ix]: not enough arguments with -exec %s",
               Text_shellsafe(argv[i], sfe, 0));
       goto sorry_ex;
     }
     i++;
     cpt= argv[i];
     if(*cpt=='-')
       cpt++;
     if(strcmp(cpt, "echo")==0) {
       Findjob_set_action_target(job, 0, NULL, 0);
     } else if(strcmp(cpt, "rm")==0) {
       Findjob_set_action_target(job, 1, NULL, 0);
       deleter= 1;
     } else if(strcmp(cpt, "rm_r")==0) {
       Findjob_set_action_target(job, 2, NULL, 0);
       deleter= 1;

#ifdef NIX
/* >>> not implemented yet */;
     } else if(strcmp(cpt, "mv")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       Findjob_set_action_target(job, 3, argv[i], 0);
#endif

     } else if(strcmp(cpt, "chown")==0 || strcmp(cpt, "chown_r")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       ret= Xorriso_convert_uidstring(xorriso, argv[i], &user, 0);
       if(ret<=0)
         goto ex;
       ret= Findjob_set_action_chown(job, user, strlen(cpt)>5);
       if(ret<=0) {
         Xorriso_no_findjob(xorriso, "-find -exec chown_r", 0);
         goto ex;
       }
     } else if(strcmp(cpt, "chgrp")==0 || strcmp(cpt, "chgrp_r")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       ret= Xorriso_convert_gidstring(xorriso, argv[i], &group, 0);
       if(ret<=0)
         goto ex;
       ret= Findjob_set_action_chgrp(job, group, strlen(cpt)>5);
       if(ret<=0) {
         Xorriso_no_findjob(xorriso, "-find -exec chgrp_r", 0);
         goto ex;
       }
     } else if(strcmp(cpt, "chmod")==0 || strcmp(cpt, "chmod_r")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       ret= Xorriso_convert_modstring(xorriso, "-find -exec chmod",
                                      argv[i], &mode_and, &mode_or, 0);
       if(ret<=0)
         goto ex;
       ret= Findjob_set_action_chmod(job, mode_and, mode_or, strlen(cpt)>5);
       if(ret<=0) {
         Xorriso_no_findjob(xorriso, "-find -exec chmod_r", 0);
         goto ex;
       }
     } else if(strcmp(cpt, "alter_date")==0 || strcmp(cpt, "alter_date_r")==0){
       if(i+2>=end_idx)
         goto not_enough_exec_arguments;
       i+= 2;
       ret= Xorriso_convert_datestring(xorriso, "-find -exec alter_date",
                                       argv[i-1], argv[i], &type, &date, 0);
       if(ret<=0)
         goto ex;
       ret= Findjob_set_action_ad(job, type, date, strlen(cpt)>10);
       if(ret<=0) {
         Xorriso_no_findjob(xorriso, "-find -exec alter_date_r", 0);
         goto ex;
       }
     } else if(strcmp(cpt, "lsdl")==0) {
       Findjob_set_action_target(job, 8, NULL, 0);

     } else if(strcmp(cpt, "find")==0) {
       ret= Findjob_new(&new_job, "", 0);
       if(ret<=0) {
         Xorriso_no_findjob(xorriso, "-find[ix]", 0);
         {ret= -1; goto ex;}
       }
       Findjob_set_action_subjob(job, 13, new_job, 0);
       job= new_job;

     } else if(strcmp(cpt, "compare")==0 || strcmp(cpt, "update")==0 ||
               strcmp(cpt, "widen_hardlinks")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       action= 14;
       if(strcmp(cpt, "update")==0)
         action= 17;
       if(strcmp(cpt, "widen_hardlinks")==0)
         action= 32;
       ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, argv[i],
                                 other_path_start, 1|2|4|8);
       if(ret<=0)
         goto ex;
       Findjob_set_action_target(job, action, other_path_start, 0);
       ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, start_path,sfe, 1|2|4);
       if(ret<=0)
         goto ex;
       Findjob_set_start_path(job, sfe, 0);
       if(!(flag&2)) {
         Xorriso_pacifier_reset(xorriso, 0);
         mem_lut= xorriso->last_update_time;
       }
     } else if(strcmp(cpt, "in_iso")==0 ||
               strcmp(cpt, "not_in_iso")==0 ||
               strcmp(cpt, "add_missing")==0 ||
               strcmp(cpt, "empty_iso_dir")==0 ||
               strcmp(cpt, "is_full_in_iso")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, argv[i],
                                 other_path_start, 1|2|4);
       if(ret<=0)
         goto ex;
       if(strcmp(cpt, "in_iso")==0)
         action= 15;
       else if(strcmp(cpt, "add_missing")==0)
         action= 18;
       else if(strcmp(cpt, "empty_iso_dir")==0)
         action= 19;
       else if(strcmp(cpt, "is_full_in_iso")==0)
         action= 20;
       else
         action= 16;
       Findjob_set_action_target(job, action, other_path_start, 0);
       ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, start_path, sfe,
                                 1|2|4|8);
       if(ret<=0)
         goto ex;
       Findjob_set_start_path(job, sfe, 0);

     } else if(strcmp(cpt, "report_damage")==0) {
       Findjob_set_action_target(job, 21, NULL, 0);
     } else if(strcmp(cpt, "report_lba")==0) {
       Findjob_set_action_target(job, 22, NULL, 0);
     } else if(strcmp(cpt, "getfacl")==0) {
       Findjob_set_action_target(job, 24, NULL, 0);
     } else if(strcmp(cpt, "setfacl")==0) {
       if(i+1>=end_idx)
         goto not_enough_exec_arguments;
       i++;
       ret= Xorriso_normalize_acl_text(xorriso, argv[i],
                                       &access_acl_text, &default_acl_text, 0);
       if(ret <= 0)
         goto ex;
       Findjob_set_action_text_2(job, 25, access_acl_text, default_acl_text,
                                 0);
     } else if(strcmp(cpt, "getfattr")==0) {
       Findjob_set_action_target(job, 26, NULL, 0);
     } else if(strcmp(cpt, "setfattr")==0) {
       if(i + 2 >= end_idx)
         goto not_enough_exec_arguments;
       i+= 2;
       /* check input */
       ret= Xorriso_path_setfattr(xorriso, NULL, "", argv[i - 1],
                                  strlen(argv[i]), argv[i], 1);
       if(ret <= 0)
         goto ex;
       Findjob_set_action_text_2(job, 27, argv[i - 1], argv[i], 0);
     } else if(strcmp(cpt, "set_filter")==0) {
       if(i + 1 >= end_idx)
         goto not_enough_exec_arguments;
       i+= 1;
       Findjob_set_action_target(job, 28, argv[i], 0);
       if(!(flag&2)) {
         Xorriso_pacifier_reset(xorriso, 0);
         mem_lut= xorriso->last_update_time;
       }
     } else if(strcmp(cpt, "show_stream")==0) {
       Findjob_set_action_target(job, 29, NULL, 0);
     } else if(strcmp(cpt, "get_any_xattr")==0) {
       Findjob_set_action_target(job, 33, NULL, 0);
     } else if(strcmp(cpt, "get_md5")==0) {
       Findjob_set_action_target(job, 34, NULL, 0);
     } else if(strcmp(cpt, "check_md5")==0) {
       if(i + 1 >= end_idx)
         goto not_enough_exec_arguments;
       i+= 1;
       Findjob_set_action_target(job, 35, argv[i], 0);
       flag|= 8;
       if(!(flag&2)) {
         Xorriso_pacifier_reset(xorriso, 0);
         mem_lut= xorriso->last_update_time;
       }
       if(!(flag & 1))
         xorriso->find_check_md5_result= 0;
     } else if(strcmp(cpt, "make_md5")==0) {
       Findjob_set_action_target(job, 36, NULL, 0);
       flag|= 8;
       if(!(flag&2)) {
         Xorriso_pacifier_reset(xorriso, 0);
         mem_lut= xorriso->last_update_time;
       }
     } else {
       sprintf(xorriso->info_text, "-find -exec: unknown action %s",
               Text_shellsafe(argv[i], sfe, 0));
       goto sorry_ex;
     }
   } else {
     sprintf(xorriso->info_text, "-find[ix]: unknown option %s",
             Text_shellsafe(argv[i], sfe, 0));
sorry_ex:;
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     {ret= 0; goto ex;}
   }
 }
 if(flag&1)
   ret= Xorriso_findx(xorriso, first_job, "", start_path, &dir_stbuf, 0, NULL,
                      0);
 else if(flag & 8) {
   cpt= start_path;
   ret= Xorriso_findi_sorted(xorriso, first_job, (off_t) 0, 1, &cpt, 0);
 } else
   ret= Xorriso_findi(xorriso, first_job, NULL, (off_t) 0, NULL,
                      start_path, &dir_stbuf, 0, (flag&4)>>1);
ex:;
 if(deleter && !(flag&2))
   Xorriso_pacifier_callback(xorriso, "iso_rr_paths deleted",
                             xorriso->pacifier_count, 0, "", 1|2);
 else if(first_job->action == 28  && !(flag&2))
   Xorriso_pacifier_callback(xorriso, "file filters processed",
                             xorriso->pacifier_count, 0, "", 1 | 2);
 else if(mem_lut!=xorriso->last_update_time && mem_lut!=0.0 && !(flag&2))
   Xorriso_pacifier_callback(xorriso, "content bytes read",
                             xorriso->pacifier_count, 0, "", 1);
 if(first_job->action == 35 && !(flag & 1))
   Xorriso_report_md5_outcome(xorriso, first_job->target, 0);
 if(access_acl_text != NULL)
   free(access_acl_text);
 if(default_acl_text != NULL)
   free(default_acl_text);
 Findjob_destroy(&first_job, 0);
 (*idx)= end_idx;
 return(ret);
}


/* Option -follow */
int Xorriso_option_follow(struct XorrisO *xorriso, char *mode, int flag)
{
 int was_fl, was_fm, was_fpr, was_fpt, l;
 double num;
 char *cpt, *npt;

 was_fpt= xorriso->do_follow_pattern;
 was_fpr= xorriso->do_follow_param;
 was_fl= xorriso->do_follow_links;
 was_fm= xorriso->do_follow_mount;
 xorriso->do_follow_pattern= 0;
 xorriso->do_follow_param= 0;
 xorriso->do_follow_links= 0;
 xorriso->do_follow_mount= 0;
 npt= cpt= mode;
 for(cpt= mode; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l==0)
     goto unknown_mode;
   if(strncmp(cpt, "off", l)==0) {
     xorriso->do_follow_pattern= 0;
     xorriso->do_follow_param= 0;
     xorriso->do_follow_links= 0;
     xorriso->do_follow_mount= 0;
   } else if(strncmp(cpt, "on", l)==0) {
     xorriso->do_follow_pattern= 1;
     xorriso->do_follow_param= 1;
     xorriso->do_follow_links= 1;
     xorriso->do_follow_mount= 1;
   } else if(strncmp(cpt, "default", l)==0) {
     xorriso->do_follow_pattern= 1;
     xorriso->do_follow_param= 0;
     xorriso->do_follow_links= 0;
     xorriso->do_follow_mount= 1;
     xorriso->follow_link_limit= 100;
   } else if(strncmp(cpt, "link", l)==0 || strncmp(cpt,"links", l)==0) {
     xorriso->do_follow_links= 1;
   } else if(strncmp(cpt, "mount", l)==0) {
     xorriso->do_follow_mount= 1;
   } else if(strncmp(cpt,"param", l)==0) {
     xorriso->do_follow_param= 1;
   } else if(strncmp(cpt, "pattern", l)==0) {
     xorriso->do_follow_pattern= 1;
   } else if(strncmp(cpt, "limit=", 6)==0) {
     sscanf(cpt+6, "%lf", &num);
     if(num<=0 || num>1.0e6) {
       sprintf(xorriso->info_text, "-follow: Value too %s with '%s'",
               num<=0 ? "small" : "large", cpt+6);
       goto sorry_ex;
     }
     xorriso->follow_link_limit= num;
   } else {
unknown_mode:;
     if(l<SfileadrL)
       sprintf(xorriso->info_text, "-follow: unknown mode '%s'", cpt);
     else
       sprintf(xorriso->info_text, "-follow: oversized mode parameter (%d)",l);
sorry_ex:
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     xorriso->do_follow_pattern= was_fpt;
     xorriso->do_follow_param= was_fpr;
     xorriso->do_follow_links= was_fl;
     xorriso->do_follow_mount= was_fm;
     return(0);
   }
 }
 return(1);
}


/* Option -fs */
int Xorriso_option_fs(struct XorrisO *xorriso, char *size, int flag)
{
 double num;

 num= Scanf_io_size(size, 0);
 if(num < 64*1024 || num > 1024.0 * 1024.0 * 1024.0) {
   sprintf(xorriso->info_text, "-fs: wrong size %.f (allowed: %.f - %.f)",
           num, 64.0 * 1024.0, 1024.0 * 1024.0 * 1024.0);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 xorriso->fs= num / 2048.0;
 if(xorriso->fs * 2048 < num)
   xorriso->fs++;
 return(1);
}


/* Optionis -getfacl alias -getfacli, -getfacl_r alias -getfacl_ri
            -getfattr alias getfattri
*/
/* @param flag bit0= recursive -getfacl_r
               bit1= getfattr rather than getfacl
               bit3= with bit1: do not ignore eventual non-user attributes
*/
int Xorriso_option_getfacli(struct XorrisO *xorriso,
                            int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-getfacl", argc, argv, *idx, &end_idx, &optc,
                       &optv, 0);
 if(ret<=0)
   goto ex;
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-getfacl_r", 0);
       {ret= -1; goto ex;}
     }
     if(flag & 2) {
       Findjob_set_action_target(job, 26, NULL, 0);
     } else
       Findjob_set_action_target(job, 24, NULL, 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else {
     if(flag & 2)
       ret= Xorriso_getfattr(xorriso, NULL, optv[i], NULL, flag & 8);
     else
       ret= Xorriso_getfacl(xorriso, NULL, optv[i], NULL, 0);
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-getfacl", argc, argv, *idx, &end_idx,
                  &optc, &optv, 256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -gid */
int Xorriso_option_gid(struct XorrisO *xorriso, char *gid, int flag)
{
 int ret;

 xorriso->do_global_gid= 0;
 if(gid[0]==0 || strcmp(gid,"-")==0)
   return(1);
 ret= Xorriso_convert_gidstring(xorriso, gid, &(xorriso->global_gid), 0);   
 if(ret>0)
   xorriso->do_global_gid= 1;
 return(ret);
}


/* Option -grow_blindly */
int Xorriso_option_grow_blindly(struct XorrisO *xorriso, char *msc2, int flag)
{
 double num;
 int l;

 if(msc2[0]==0 || msc2[0]=='-' || strcmp(msc2, "off")==0) {
   xorriso->grow_blindly_msc2= -1;
   return(1);
 }
 num= Scanf_io_size(msc2, 0);
 l= strlen(msc2);
 if(msc2[l-1]<'0' || msc2[l-1]>'9')
   num/= 2048.0;
 xorriso->grow_blindly_msc2= num;
 return(1);
}


/* Option -hardlinks "on"|"off" */
int Xorriso_option_hardlinks(struct XorrisO *xorriso, char *mode, int flag)
{
 int ret;
 char what_data[SfileadrL], *what, *what_next;

 if(Sfile_str(what_data, mode, 0)<=0) {
   sprintf(xorriso->info_text,
           "-hardlinks: mode string is much too long (%d)",
           (int) strlen(mode));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 } 
 for(what= what_data; what != NULL; what= what_next) {
   what_next= strchr(what, ':');
   if(what_next != NULL) {
     *what_next= 0;
     what_next++;
   }
   if(strcmp(what, "off") == 0) {
     Xorriso_finish_hl_update(xorriso, 0);
     xorriso->ino_behavior|= 1 | 2 | 4;
     xorriso->ino_behavior&= ~8;
   } else if(strcmp(what, "on") == 0) {
     xorriso->ino_behavior&= ~(1 | 2 | 4 | 8);
   } else if(strcmp(what, "without_update") == 0) {
     Xorriso_finish_hl_update(xorriso, 0);
     xorriso->ino_behavior&= ~(1 | 2 | 4);
     xorriso->ino_behavior|= 8;
   } else if(strcmp(what, "start_update") == 0) {
     xorriso->ino_behavior&= ~(1 | 2 | 4 | 8);
     ret= Xorriso_make_di_array(xorriso, 1);
     if(ret <= 0)
       return(ret);
   } else if(strcmp(what, "end_update") == 0) {
     Xorriso_finish_hl_update(xorriso, 0);
   } else if(strcmp(what, "perform_update") == 0) {
     Xorriso_finish_hl_update(xorriso, 0);
   } else if(strcmp(what, "start_extract") == 0) {
     xorriso->ino_behavior&= ~(1 | 2 | 4);
     ret= Xorriso_make_hln_array(xorriso, 1);
     if(ret <= 0)
       return(ret);
   } else if(strcmp(what, "end_extract") == 0) {
     Xorriso_destroy_hln_array(xorriso, 0);
   } else if(strcmp(what, "discard_extract") == 0) {
     Xorriso_destroy_hln_array(xorriso, 0);
   } else if(strcmp(what, "normal_extract") == 0) {
     xorriso->ino_behavior&= ~16;
   } else if(strcmp(what, "cheap_sorted_extract") == 0) {
     xorriso->ino_behavior|= 16;
   } else {
     sprintf(xorriso->info_text, "-hardlinks: unknown mode '%s' in '%s'",
             what, mode);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 if(xorriso->ino_behavior & 2)
   Xorriso_option_compliance(xorriso, "new_rr", 0);

 return(1);
}


/* Option -help and part of -prog_help */
int Xorriso_option_help(struct XorrisO *xorriso, int flag)
{
 static char text[][80]={

#ifdef Xorriso_no_helP

"This binary program does not contain a help text.",
"If available, read: man 1 xorriso",

#else

"This program creates, loads, manipulates and writes ISO 9660 filesystem",
"images with Rock Ridge extensions. Write targets can be drives with optical",
"media or local filesystem objects.",
"",
"Preparation options:",
"Drive addresses are either /dev/... as listed with option -devices or",
"disk files, eventually with prefix \"stdio:\" if non-CD-drive in /dev tree.",
"E.g. /dev/sr0 , /tmp/pseudo_drive , stdio:/dev/sdc",
"  -dev address   Set input and output drive and load eventual ISO image.",
"                 Set the image expansion method to growing.",
"  -indev address  Set input drive and load eventual ISO image. Use expansion",
"                 methods modifying or blind growing.",
"  -outdev address",
"                 Set output drive and use modifying or blind growing.",
"  -drive_class \"harmless\"|\"banned\"|\"risky\"|\"clear_list\" disk_pattern",
"                 Add a drive path pattern to one of the safety lists or make",
"                 those lists empty. Defaulty entry in \"risky\" is \"/dev\".",
"  -grow_blindly \"off\"|predicted_nwa",
"                 Switch between modifying and blind growing.",
"  -load \"session\"|\"track\"|\"lba\"|\"sbsector\"|\"volid\"|\"auto\" id",
"                 Load a particular (outdated) ISO image from a -dev or",
"                 -indev which hosts more than one session.",
"  -rom_toc_scan \"on\"|\"force\"|\"off\"[:\"emul_on\"|\"emul_off\"]",
"                 Enable scanning for ISO sessions on read-only drives/media",
"                 resp. on overwriteable media with emulated TOC.",
"  -calm_drive \"in\"|\"out\"|\"all\"|\"on\"|\"off\"",
"                 Reduce drive noise until it gets actually used again.",
"  -assert_volid pattern severity",
"                 Accept input image only if its volume id matches pattern.",
"  -charset name  Set the character set name to be used for file name",
"                 conversion from and to media.",
"  -in_charset name",
"                 Like -charset but only for conversion from media.",
"  -auto_charset \"on\"|\"off\"",
"                 Enable writing and reading of character set name in image.",
"  -out_charset name",
"                 Like -charset but only for conversion to media.",
"  -local_charset name",
"                 Override system assumption of the local character set name.",
"  -hardlinks mode[:mode ...]",
"                 Enable resp. disable recording and restoring of hard links.",
"                 Modes are \"on\", \"off\", \"perform_update\",",
"                 \"without_update\", \"discard_extract\",",
"                 \"cheap_sorted_extract\", \"normal_extract\"",
"  -acl \"on\"|\"off\"",
"                 Enable resp. disable reading and writing of ACLs.",
"  -xattr \"on\"|\"off\"",
"                 Enable resp. disable reading and writing of xattr.",
"  -for_backup",
"                 Shortcut for: -hardlinks on -acl on -xattr on -md5 on",
"  -disk_dev_ino \"on\"|\"ino_only\"|\"off\"",
"                 Enable resp. disable recording of disk file dev_t and ino_t",
"                 and their use in file comparison.",
"  -md5 \"on\"|\"all\"|\"off\"",
"                 Enable resp. disable processing of MD5 checksums.",
"  -scdbackup_tag list_path record_name",
"                 Enable production of scdbackup tag with -md5 on",
"  -ban_stdio_write",
"                 Allow for writing only the usage of optical drives.",
"  -blank \"fast\"|\"all\"|\"deformat\"|\"deformat_quickest\"",
"                 Blank media resp. invalidate ISO image on media.",
"  -format \"as_needed\"|\"full\"|\"fast\"|\"by_index_#\"|\"by_size_#\"",
"                 Format BD-RE, BD-R, DVD-RAM, DVD-RW, DVD+RW.",
"  -volid volume_id",
"                 Specifies the volume ID text. (32 chars out of [A-Z0-9_])",
"  -volset_id name",
"                 Specifies the volume set id. (128 chars)",
"  -publisher name",
"                 Specifies the publisher name. (128 chars)",
"  -application_id name",
"                 Specifies the application id. (128 chars)",
"  -system_id name",
"                 Specifies the system id for the System Area. (32 chars)",
"  -joliet \"on\"|\"off\"",
"                 Generate Joliet info additional to Rock Ridge info.",
"  -compliance rule[:rule...]",
"                 Allow more or less harmless deviations from strict standards",
"                 compliance.",
"  -boot_image \"any\"|\"isolinux\" \"discard\"|\"keep\"|\"patch\"|\"dir=\"",
"                               \"bin_path=\"|\"cat_path=\"|\"load_size=\"",
"                 Whether to discard or keep an exiting El Torito boot image.",
"                 ISOLINUX can be made bootable by dir=/ or dir=/isolinux",
"                 or dir=/boot/isolinux or by bin_path=... and cat_path=...",
"                 The ISOLINUX files need to be added to the ISO image by",
"                 help of the usual commands like -map or -add.",
"",
"  -uid uid       User id to be used for the whole multi-session ISO image.",
"  -gid gid       Group id for the same purpose.",
"",
"  -devices       Show list of available optical drives and their addresses.",
"",
"  -toc           Show media specific table of content (sessions).",
"",
"  -mount_cmd drive entity id path",
"                 Print to result channel a command suitable to mount the",
"                 depicted entity (see -load) at the given directory path.",
"  -mount_opts \"exclusive\"|\"shared\"",
"                 Set options for -mount and -mount_cmd.",
"  -session_string drive entity id \"linux:\"path|\"freebsd:\"path|form",
"                 Print foreign OS command or custom line.",
"",
"  -list_formats  Show media specific list of format descriptors.",
"",
"  -list_profiles \"in\"|\"out\"|\"all\"",
"                 Show list of media types supported by indev resp. outdev.",
"  -print_size    Print the foreseeable consumption by next -commit.",
"",
"  -tell_media_space",
"                 Print foreseeable available space on output media",
"  -pvd_info      Print various id strings of the loaded ISO image."
"",
"Options with variable length path list [...] need the list delimiter text",
"as end mark if they are followed by another option. By default this delimiter",
"is \"--\". In dialog and with options read from files, the line end serves",
"as such a mark. With program arguments this mark can be omitted only with",
"the last option in the list of arguments.",
"For brevity the list delimiter is referred as \"--\" throughout this text.",
"",
"  -list_delimiter text   Set the list delimiter to be used instead of \"--\"",
"                 It has to be a single word, must not be empty, not longer",
"                 than 80 characters, may mot contain quotation marks.",
"",
"Manipulation options:",
"disk_path is a path to an object in the local filesystem tree.",
"iso_rr_path is the Rock Ridge name of a file object in the ISO image.",
"pathspec is either a disk_path or (if allowed) a pair: iso_rr_path=disk_path",
"Options marked by [***] have variable argument length and perform pattern",
"expansion if enabled by -iso_rr_pattern resp. -disk_pattern.",
"",
"  -pathspecs \"on\"|\"off\"  Allow or disallow pathspecs of form ",
"                 iso_rr_path=disk_path . Only \"off\" allows eventual",
"                 -disk_pattern expansion.",
"  -add pathspec [...] | disk_path [***]",
"                 Insert the given files or directory trees from",
"                 filesystem into the ISO image. Much like mkisofs.",
"  -add_plainly \"none\"|\"unknown\"|\"dashed\"|\"any\"",
"                 Whether to add lonely arguments as pathspec resp. disk_path.",
"  -path_list disk_path",
"                 Like -add but read the pathspecs from file disk_path.",
"  -quoted_path_list disk_path",
"                 Like -path_list but with line rules as -dialog \"on\".",
"",
"  -map disk_path iso_rr_path",
"                 Insert disk file object at the given iso_rr_path.",
"  -map_single disk_path iso_rr_path",
"                 Like -map but with directory do not insert its sub tree.",
"  -map_l disk_prefix iso_rr_prefix disk_path [***]",
"                 Performs -map with each disk_path.",
"  -update disk_path iso_rr_path",
"                 Compare both file objects and do what is necessary to make",
"                 iso_rr_path a matching copy of disk_path.", 
"  -update_r disk_path iso_rr_path",
"                 Like -update but affecting all files below directories.",
"  -update_l disk_prefix iso_rr_prefix disk_path [***]",
"                 Performs -update_r with each disk_path.",
"  -cut_out disk_path byte_offset byte_count iso_rr_path",
"                 Map a byte interval of a regular disk file into a regular",
"                 file in the ISO image.",
"",
"  -cpr disk_path [***] iso_rr_path",
"                 Insert the given files or directory trees from filesystem",
"                 into the ISO image, according to the rules of cp -r.",
"",
"  -rm iso_rr_path [***]",
"                 Delete the given files from the ISO image.",
"  -rm_r iso_rr_path [***]",
"                 Delete the given directory trees from ISO image.",
"  -mv iso_rr_path [***] iso_rr_path",
"                 Rename the given file objects in the ISO tree to the last",
"                 argument in the list.",
"  -chown uid iso_rr_path [***]",
"                 Equivalent to chown in the ISO image.",
"  -chown_r uid iso_rr_path [***]",
"                 Like -chown but affecting all files below directories.",
"  -chgrp gid iso_rr_path [***]",
"                 Equivalent to chgrp in the ISO image.",
"  -chgrp_r gid iso_rr_path [***]",
"                 Like -chgrp but affecting all files below directories.",
"  -chmod mode iso_rr_path [***]",
"                 Equivalent to chmod in the ISO image.",
"  -chmod_r mode iso_rr_path [***]",
"                 Like -chmod but affecting all files below directories.",
"  -setfacl acl_text iso_rr_path [***]",
"                 Replace the permissions and eventual ACL of the given files",
"                 in the ISO image by the ACL which is defined by acl_text.",
"  -setfacl_r acl_text iso_rr_path [***]",
"                 Like -setfacl but affecting all files below directories.",
"  -setfacl_list disk_path",
"                 Read output of getfacl from file disk_path. Set owner,",
"                 group and ACL of the iso_rr_path given by line \"# file:\".",
"  -setfattr [-]name value iso_rr_path [***]",
"                 Set xattr pair with the given name to the given value, or",
"                 delete pair if name is prefixed with \"-\" and value is",
"                 an empty text.",
"  -setfattr_r [-]name value iso_rr_path [***]",
"                 Like -setfattr but affecting all files below directories.",
"  -setfattr_list disk_path",
"                 Read output of getfattr from file disk_path. Replace the",
"                 xattr of the iso_rr_path given by line \"# file:\".",
"  -alter_date type timestring iso_rr_path [***]",
"                 Alter the date entries of a file in the ISO image. type is",
"                 one of \"a\", \"m\", \"b\" for:",
"                 access time, modification time, both times.",
"  -alter_date_r type timestring iso_rr_path [***]",
"                 Like -alter_date but affecting all files below directories.",
"  -find iso_rr_path [test [op] [test ...]] [-exec action [params]]",
"                 performs an action on files below the given directory in",
"                 the ISO image. Tests:",
"                   -name pattern, -wholename pattern, -type b|c|d|p|f|l|s|e,",
"                   -pending_data, -lba_range start count, -damaged,",
"                   -has_acl, -has_xattr, -has_aaip, -has_filter, -has_md5",
"                   -has_any_xattr, -prune, -decision yes|no, -true, -false",
"                 Operators: -not, -or, -and, -sub, (, -subend, ),",
"                   -if, -then, -elseif, -else, -endif",
"                 Action may be one of: echo, chown, chown_r, chgrp, chgrp_r",
"                   chmod, chmod_r, alter_date, alter_date_r, lsdl, compare,",
"                   rm, rm_r, compare, update, report_damage, report_lba,",
"                   getfacl, setfacl, getfattr, setfattr, get_any_xattr,",
"                   get_md5, check_md5, make_md5, set_filter, show_stream,",
"                   find.",
"                 params are their arguments except iso_rr_path.",
"  -mkdir iso_rr_path [...]",
"                 Create empty directories if they do not exist yet.",
"  -rmdir iso_rr_path [***]",
"                 Delete empty directories.",
"  --             Default list delimiter marking the end of action argument",
"                 list. It may be changed by option -list_delimiter.",
"",
"  -not_paths disk_path [***]",
"                 Add the given paths to the list of excluded absolute paths.",
"  -not_leaf pattern",
"                 Add the given pattern to the list of leafname exclusions.",
"  -not_list disk_path",
"                 Read lines from disk_path and use as -not_paths (with \"/\")",
"                 or as -not_leaf (without \"/\").",
"  -quoted_not_list disk_path",
"                 Like -not_list but with line rules as -dialog \"on\".",
"  -not_mgt \"reset\"|\"on\"|\"off\"|\"param_on\"|\"subtree_on\"|\"ignore_on\"",
"                 Control effect of exclusion lists.",
"  -follow \"on\"|\"pattern:param:link:mount:limit=#\"|\"default\"|\"off\"",
"                 Follow symbolic links and mount points within disk_path.",
"  -overwrite \"on\"|\"nondir\"|\"off\"",
"                 Allow or disallow to overwrite existing files in ISO image.",
"  -split_size number[\"k\"|\"m\"]",
"                 Set the threshold for automatic splitting of regular files.",
"  -reassure \"on\"|\"tree\"|\"off\"",
"                 If \"on\" then ask the user for \"y\" or \"n\" with any",
"                 file before deleting or overwriting it in the ISO image.",
"",
"Filter options:",
"External filter processes may produce synthetic file content by reading the",
"original content from stdin and writing to stdout whatever they want.",

#ifdef Xorriso_allow_external_filterS

"  -external_filter name option[:option] program_path [arguments] --",
"                 Define an external filter. Options are: suffix=...: ",
"                 remove_suffix:if_nonempty:if_reduction:if_block_reduction.",
"  -unregister_filter name",
"                 Undefine an external filter.",
"  -close_filter_list",
"                 Irrevocably ban -external_filter and -unregister_filter.",

#else

"Sorry: The use of external filters was not enabled at compile time.",
"       E.g. by ./configure option --enable-external-filters",

#endif /* ! Xorriso_allow_external_filterS */

"  -set_filter name iso_rr_path [***]",
"                 Apply a defined filter to the given data files.",
"                 Special name \"--remove-all-filters\" revokes filtering.",
"                 Builtin filters are --gzip , --gunzip, --zisofs .",
"  -set_filter_r name iso_rr_path [***]",
"                 Like -set_filter but affecting all files below directories.",
"",
"zisofs is a compression format which is recognized by some Linux kernels.",
"xorriso supports it by builtin filter \"--zisofs\" which is to be applied by",
"the user, and by \"--zisofs-decode\" which is applied automatically when",
"compressed content is detected with a file in the ISO image.",
"  -zisofs option[:options]",
"                 Set global zisofs parameters:",
"                   level=0|...|9 , block_size=32k|64k|128k , by_magic=on|off",
"",
"Write-to-media options:",
"  -rollback      Discard the manipulated ISO image and reload it.",
"",
"  -commit        Perform the write operation and then perform -dev outdrive.",
"                 Hint: To perform a final write operation with no new -dev",
"                       and no new loading of image, execute option -end.",
"  -commit_eject  \"in\"|\"out\"|\"all\"|\"none\"",
"                 Like -commit but rather eject than load image from outdrive.",
"                 Give up any unejected drive afterwards.",
"  -close \"on\"|\"off\"",
"                 If \"on\" then mark the written media as not appendable.",
"  -padding number[\"k\"|\"m\"]",
"                 Append extra bytes to image stream. (Default is 300k)",
"  -dummy \"on\"|\"off\"",
"                 If \"on\" simulate burning. Refuse if media cannot simulate.",
"  -speed number[\"k/s\"|\"m/s\"|\"[x]CD\"|\"[x]DVD\"|\"[x]BD\"]",
"                 Set the burn speed. Default is 0 = maximum speed.",
"  -stream_recording \"on\"|\"off\"",
"                 Try to circumvent slow checkread on DVD-RAM, BD-RE, BD-R.",
"  -dvd_obs \"default\"|\"32k\"|\"64k\"",
"                 Set number of bytes per DVD/BD write operation.",
"  -stdio_sync \"on\"|\"off\"|number",
"                 Set number of bytes after which to force output to stdio",
"                 pseudo drives. \"on\" is the same as 16m.",
"  -fs number[\"k\"|\"m\"]",
"                 Set the size of the fifo buffer. (Default is 4m)",
"  -eject \"in\"|\"out\"|\"all\"",
"                 Immediately eject the media in -indev, resp. -outdev,",
"                 resp. both.",
"",
"Navigation options:",
"",
"  -cd iso_rr_path  Change working directory in the ISO image. iso_rr_paths",
"                 which do not begin with '/' will be inserted beginning at",
"                 the path given with -cd. -ls patterns will eventually",
"                 looked up at this path.",
"  -cdi disk_path   Same as -cd disk_path",
"  -cdx disk_path  Change the current working directory in the local",
"                 filesystem. disk_paths which do not begin with '/'",
"                 will be looked up beginning at the path given with -cdx.",
"                 -lsx patterns will eventually be looked up at this path.",
"  -pwd           tells the current working directory in the ISO image.",
"  -pwdi          same as -pwd.",
"  -pwdx          tells the current working directory in the local filesystem.",
"",
"  -iso_rr_pattern \"on\"|\"ls\"|\"off\"",
"                 Enable or disable pattern expansions for ISO image commands",
"                 marked by [***]. \"ls\" restricts it to -ls and -du.",
"  -disk_pattern \"on\"|\"ls\"|\"off\"",
"                 Enable or disable pattern expansions for local filesystem",
"                 commands marked by [***]. \"ls\" restricts to -ls*x and -du*x.",
"",
"  -ls pattern [***]  lists files of the ISO image which match one of the",
"                 given shell parser patterns. (I.e. wildcards '*' '?').",
"                 Directories are listed by their content.",
"  -lsd pattern [***]   like -ls but listing directories as single items.",
"  -lsl pattern [***]   like -ls but also telling some file attributes.",
"  -lsdl pattern [***]  like -lsd but also telling some file attributes.",
"",
"  -lsx pattern [***]   lists files of the local filesystem which match one",
"                 of the patterns. Directories are listed by their content.",
"  -lsdx pattern [***]  like -lsx but listing directories as single items.",
"  -lslx pattern [***]  like -lsx but also telling some file attributes.",
"  -lsdlx pattern [***] like -lsdx but also telling some file attributes.",
"  -getfacl pattern [***]     list eventual ACLs of the given files.",
"  -getfacl_r pattern [***]   like -getfacl but listing whole file trees.",
"  -getfattr pattern [***]    list eventual xattr of the given files.",
"  -getfxattr_r pattern [***] like -getfxattr but listing whole file trees.",
"",
"  -du pattern [***]  recursively lists sizes of files or directories in the",
"                 ISO image which match one of the shell parser patterns.",
"  -dux pattern [***]  recursively lists sizes of files or directories in the",
"                 local filesystem which match one of the shell parser",
"                 patterns.",
"  -dus pattern [***]  like -du but summing up subdirectories without",
"                 listing them explicitely.",
"  -dusx pattern [***]  like -dux but summing up subdirectories without",
"                 listing them explicitely.",
"",
"  -findx disk_path [-name pattern] [-type t] [-exec action [params]]",
"                 Like -find but operating on local filesystem. Most -exec",
"                 actions are defaulted to action echo. Supported actions are:",
"                  in_iso, not_in_iso, is_full_in_iso, add_missing,",
"                  empty_iso_dir",
"",
"  -compare disk_path iso_rr_path",
"                 compare attributes and in case of regular data files the",
"                 content of filesystem object and ISO object.",
"  -compare_r disk_path iso_rr_path",
"                 Like -compare but affecting all files below directories.",
"  -compare_l disk_prefix iso_rr_prefix disk_path [***]",
"                 Performs -compare_r with each disk_path.",
"",
"  -show_stream iso_rr_path [***]",
"                 Show content stream chain of data files in the ISO image.",
"  -show_stream_r iso_rr_path [***]",
"                 Like -show_stream but affecting all files below directories.",
"",
"Restore options which copy file objects from ISO image to disk filesystem:",
"  -osirrox \"on\"|\"device_files\"|\"off\"|\"banned\"",
"           [:\"concat_split_on\"|\"concat_split_off\"]",
"           [:\"auto_chmod_on\"|\"auto_chmod_off\"]",
"           [:\"sort_lba_on\"|\"sort_lba_off\"]",
"                 By default \"off\" the inverse operation of xorriso from ISO",
"                 image to disk filesystem is disabled. \"on\" allows xorriso",
"                 to create, overwrite, delete files in the disk filesystem.", 
"                 \"banned\" is irrevocably \"off\".",
"  -extract iso_rr_path disk_path",
"                 Copy tree under iso_rr_path onto disk address disk_path.",
"                 This avoids the pitfalls of cp -r addressing rules.",
"  -extract_l iso_rr_prefix disk_prefix iso_rr_path [***]",
"                 Perform -extract with each iso_rr_path.",
"  -extract_single iso_rr_path disk_path",
"                 Like -extract but with directory do not restore sub tree.",
"  -extract_cut iso_rr_path byte_offset byte_count disk_path",
"                 Copy a byte interval from iso_rr_path to disk_path.",
"                 This is governed in part by -check_media_defaults.",
"  -cpx iso_rr_path [***] disk_path",
"                 Copy leaf file objects from ISO image to disk filesystem.",
"  -cpax iso_rr_path [***] disk_path",
"                 Like -cpx but trying to restore timestamps and ownership.",
"  -cp_rx iso_rr_path [***] disk_path",
"                 Copy directory trees from ISO image to disk filesystem.",
"  -cp_rax iso_rr_path [***] disk_path",
"                 Like -cp_rx but trying to restore timestamps and ownership.",
"  -paste_in iso_rr_path disk_path byte_offset byte_count",
"                 Copy ISO file content into a byte interval of a disk file.",
"  -mount drive entity id path",
"                 Like -mount_cmd but actually performing that command if",
"                 not setuid or setgid is active.",
"",
"Evaluation of readability:",
"  -check_media [options] --",
"                 Try to read data blocks from media and report about the",
"                 outcome. Several options modify the behavior:",
"                  use=indev|outdev , what=track|session ,",
"                  min_lba=blockadr , max_lba=blockadr ,",
"                  abort_file=path , time_limit=seconds , item_limit=number ,",
"                  retry=on|off|default , data_to=filepath ,",
"                  sector_map=filepath , map_with_volid=on|off ,",
"                  patch_lba0=on|off|force|blockadr[:force] ,",
"                  report=blocks|files|blocks_files event=severity ,",
"                  bad_limit=quality , slow_limit=seconds , chunk_size=bytes",
"  -check_media_defaults [options] --",
"                 Preset options for runs of -check_media and -extract_cut.",
"",
"Compatibility emulation (argument list may be ended by list delimiter --):",
"  -as mkisofs  [-help|-version|-o|-R|-J|-V|-P|-f|-m|-exclude-list|-no-pad|",
"                -M|-C|-graft-points|-path-list|pathspecs|-z|",
"                -no-emul-boot|-b|-c|-boot-info-table|-boot-load-size]",
"              Perform some mkisofs gestures, understand pathspecs as mkisofs",
"              does. Commit happens outside emulation at usual occasions.",
"  -as cdrecord [-help|-v|dev=|speed=|blank=|fs=|-eject|-atip|padsize=|-multi]",
"               path|-",
"              Perform some cdrecord gestures, eventually write at most one",
"              data track to blank, appendable or overwriteable media.",
"  -pacifier \"xorriso\"|\"cdrecord\"|\"mkisofs\"",
"              Choose format of UPDATE pacifier during write operations.",
"",
"General options:",
"  -help       Print this text",
"  -abort_on severity   Set the threshhold for events to abort the program.",
"              Useful severities: NEVER, ABORT, FATAL, FAILURE, SORRY, WARNING",
"  -return_with severity exit_value   Set the threshhold for events to return",
"              at program end the given exit_value even if not aborted.",
"              exit_value may be 0 or 32 to 63.",
"  -report_about severity   Set the threshhold for events to be reported.",
"              Use -abort_on severities or: HINT, NOTE, UPDATE, DEBUG, ALL",
"  -error_behavior \"image_loading\"|\"file_extraction\" behavior",
"              Behavior \"best_effort\" is most endurant but may produce",
"              results which are correct only on the first glimpse.",
"  -dialog \"on\"|\"off\"|\"single_line\"",
"              After all arguments are processed, enter dialog mode.",
"              \"single_line\" does not support newline characters within",
"              open quotation marks and no line continuation by trailing \\.",
"  -page len width  Prompt user after len output lines (0=no prompt).",
"              width (default 80) can adjust line number computation",
"              to the output terminal's line width.",
#ifdef Xorriso_with_readlinE
"  -use_stdin  Use raw standard input even if libreadline is available",
"  -use_readline  Use libreadline for dialog if available",
"  -history text  Copy text into libreadline history. This command",
"              itself is not copied to the history list.",
#endif /* Xorriso_with_readlinE */
"  -backslash_codes \"on\"|\"off\"|",
"                   \"in_double_quotes\"|\"in_quotes\"|\"with_quoted_input\"",
"                   [:\"with_program_arguments\"][:\"encode_output\"]",
"              Disable or enable interpretation of \\a \\b \\e \\f \\n \\r \\t \\v",
"              \\\\ \\NNN \\xNN \\cC in input or program arguments.",
"  -pkt_output \"on\"|\"off\"  Direct output to stdout and prefix each line",
"              by a short header which tells channel id and a mode number.",
"              Each such output packet is finalized by a newline.",
"              Channel ids are 'R:' for result lines, 'I:' for notes",
"              and error messages, 'M:' for -mark texts. Bit 0 of the",
"              mode number tells whether the newline is also part of the",
"              packet payload. Example of a info message with newline:",
"                I:1: enter option text :",
"              -pkt_output:on is intended for use by frontend programs.",
"  -logfile channel fileaddress  Copy output of a channel to the given file.",
"              channel may be 'R','I','M' as with -pkt_output or '.'",
"              for the consolidated -pkt_output stream.",
"  -mark text  If text is not empty it will get put out each time an",
"              option is completed.",
"  -temp_mem_limit number[\"k\"|\"m\"]",
"              Set the maximum size for pattern expansion. (Default is 16m)",
"  -prog text  Use text as this program's name in subsequent messages",
"  -prog_help text  Use text as this program's name and perform -help",
"  -status mode|filter  Report the current settings of persistent options.",
"              Modes:",
"                 short... print only important or altered options",
"                 long ... print options even if they have default settings",
"                 long_history  like long plus -history: lines",
"              Filters begin with '-' and are compared literally against the",
"              output lines of -status long_history. A line is put out only",
"              if its start matches the filter.",
"  -status_history_max number  Maximum number of history lines to be reported",
"              with -status:long_history",
"  -options_from_file fileaddress",
"              Reads lines from the given file and executes them as program",
"              options.",
"  -no_rc      Only if used as first command line argument this option",
"              prevents reading and interpretation of startup files.",
"  -print text",
"              Print a text to result channel.",
"  -prompt text",
"              Wait for Enter key resp. for a line of input at stdin.",
"  -errfile_log mode path|channel",
"              Log disk paths of files involved in problem events.",
"  -session_log path",
"              Set path of a file where a log record gets appended after",
"              each session. Form: timestamp start_lba size volume-id", 
"  -scsi_log \"on\"|\"off\"",
"              Enable or disable logging of SCSI commands to stderr.",
"  # any text  Is ignored. In dialog mode the input line will be stored in",
"              the eventual readline history, nevertheless.", 
"  -version    Tell program and version number",
"  -end        End program. Commit eventual pending changes.",
"  -rollback_end",
"              End program. Discard pending changes.",
"",
"",
"Option -page causes a user prompt after the given number of result lines.",
"Empty input resumes output until the next prompt. Other input may be:",
"  @     suppresses paging until the current action is done",
"  @@    suppresses further result output but continues the action",
"  @@@   aborts the current action",
"  other aborts the current action and executes input as new",
"        option",
"",

#endif /* ! Xorriso_no_helP */

"@ENDE_OF_HELPTEXT_(HOPEFULLY_UNIQUELY_SILLY_TEXT)@"
 };

 char *tpt= NULL;
 int i,pass;

 Xorriso_restxt(xorriso,"\n"); 
 sprintf(xorriso->result_line,"usage: %s [settings|actions]\n",
         xorriso->progname); 
 Xorriso_result(xorriso,0);
 Xorriso_restxt(xorriso,"\n"); 
 for(pass=0;pass<1;pass++) {
   for(i=0;1;i++) {
     if(pass==0)
       tpt= text[i];
     
     if(strcmp(tpt,"@ENDE_OF_HELPTEXT_(HOPEFULLY_UNIQUELY_SILLY_TEXT)@")==0)
   break;
     sprintf(xorriso->result_line,"%s\n",tpt);
     Xorriso_result(xorriso,0);
     if(xorriso->request_to_abort)
       return(1);
   }
 }
 Xorriso_restxt(xorriso,"\n"); 
 return(1);
}


/* Option -history */
int Xorriso_option_history(struct XorrisO *xorriso, char *line, int flag)
{
 Xorriso_dialog_input(xorriso,line,strlen(line)+1,2);
 return(1);
}


/* Option -iso_rr_pattern "on"|"ls"|"off" */
int Xorriso_option_iso_rr_pattern(struct XorrisO *xorriso, char *mode,int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_iso_rr_pattern= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->do_iso_rr_pattern= 1;
 else if(strcmp(mode, "ls")==0)
   xorriso->do_iso_rr_pattern= 2;
 else {
   sprintf(xorriso->info_text, "-iso_rr_pattern: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -joliet "on"|"off" */
int Xorriso_option_joliet(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_joliet= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->do_joliet= 1;
 else {
   sprintf(xorriso->info_text, "-joliet: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -list_delimiter */
int Xorriso_option_list_delimiter(struct XorrisO *xorriso, char *text,
                                  int flag)
{
 int ret, argc;
 char **argv= NULL;

 if(text[0] == 0) {
   sprintf(xorriso->info_text,
           "-list_delimiter: New delimiter text is empty");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(strlen(text) > 80) {
   sprintf(xorriso->info_text,
           "-list_delimiter: New delimiter text is too long");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Sfile_make_argv(xorriso->progname, text, &argc, &argv, 4);
 if(ret > 0) {
   if(argc > 2) {
     sprintf(xorriso->info_text,
            "-list_delimiter: New delimiter text contains more than one word");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   }
   Sfile_make_argv(xorriso->progname, text, &argc, &argv, 2);
   if(argc > 2)
     return(0);
 }
 if(strchr(text, '"') != NULL || strchr(text, '\'') != NULL) {
   sprintf(xorriso->info_text,
           "-list_delimiter: New delimiter text contains quotation marks");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 strcpy(xorriso->list_delimiter, text);
 return(1);
}


/* Option -list_formats */
int Xorriso_option_list_formats(struct XorrisO *xorriso, int flag)
{
 int ret;

 ret= Xorriso_list_formats(xorriso, 0);
 return(ret);
}


/* Option -list_profiles */
int Xorriso_option_list_profiles(struct XorrisO *xorriso, char *which,
                                 int flag)
{
 int ret;
 int mode= 0;

 if(strncmp(which,"in",2)==0)
   mode|= 1;
 else if(strncmp(which,"out",3)==0)
   mode|= 2;
 else
   mode|= 3;
 if(mode & 1) {
   ret= Xorriso_toc(xorriso, 1 | 16 | 32);
   if(ret > 0)
     Xorriso_list_profiles(xorriso, 0);
 }
 if((mode & 2) && xorriso->in_drive_handle != xorriso->out_drive_handle) {
   ret= Xorriso_toc(xorriso, 1 | 2 | 16 | 32);
   if(ret > 0)
     Xorriso_list_profiles(xorriso, 2);
 }
 return(1);
}


/* Option -load session|track|sbsector value */
/* @param flag bit0= with adr_mode sbsector: adr_value is possibly 16 too high
   @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_load(struct XorrisO *xorriso, char *adr_mode,
                          char *adr_value, int flag)
{
 int ret;

 if(xorriso->volset_change_pending) {
   sprintf(xorriso->info_text,
           "-load: Image changes pending. -commit or -rollback first");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_reassure(xorriso, "-load", "loads an alternative image", 0);
 if(ret<=0)
   return(2);
 ret= Xorriso_decode_load_adr(xorriso, "-load", adr_mode, adr_value,
                              &(xorriso->image_start_mode),
                              xorriso->image_start_value, flag & 1);
 if(ret <= 0)
   return(ret);
 xorriso->image_start_mode|= (1<<30); /* enable non-default msc1 processing */
 if(strlen(xorriso->indev)>0) {
   ret= Xorriso_option_rollback(xorriso, 1); /* Load image, no -reassure */
   if(ret<=0)
     return(ret);
 }
 return(1);
}


/* Option -logfile */
int Xorriso_option_logfile(struct XorrisO *xorriso, char *channel,
                                                      char *fileadr, int flag)
{
 int hflag,channel_no= 0, ret;
   
 if(channel[0]==0) {
logfile_wrong_form:;
   sprintf(xorriso->info_text,"Wrong form. Correct would be: -logfile \".\"|\"R\"|\"I\"|\"M\" file_address");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 hflag= 2;
 if(channel[0]=='R')
   channel_no= 1;
 else if(channel[0]=='I')
   channel_no= 2;
 else if(channel[0]=='M')
   channel_no= 3;
 else if(channel[0]=='.')
   hflag= 4;
 else
   goto logfile_wrong_form;
 if(strcmp(fileadr,"-")==0 || fileadr[0]==0)
     hflag|= (1<<15);
 xorriso->logfile[channel_no][0]= 0;
 ret= Xorriso_write_to_channel(xorriso, fileadr, channel_no, hflag);
 if(ret<=0) {
   sprintf(xorriso->info_text, "Cannot open logfile:  %s", fileadr);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 } else if(!(hflag&(1<<15)))
   if(Sfile_str(xorriso->logfile[channel_no], fileadr, 0)<=0)
     return(-1);
 return(ret>0);
}


/* Options -ls  alias -lsi   and -lsl  alias -lsli
       and -lsd alias -lsdi  and -lsdl alias -lsdli
       and -du  alias -dui   and -dus  alias -dusi
   @param flag bit0= long format (-lsl , -du)
               bit1= do not expand patterns but use literally
               bit2= du rather than ls
               bit3= list directories as themselves (ls -d) 
*/
int Xorriso_option_lsi(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int ret, end_idx, filec= 0, nump, i;
 char **filev= NULL, **patterns= NULL;
 off_t mem= 0;
 struct stat stbuf;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
 if(xorriso->do_iso_rr_pattern==0)
   flag|= 2;

 nump= end_idx - *idx;
 if((flag&2) && nump>0 ) {
   ;
 } else if(nump <= 0) {
   if(Xorriso_iso_lstat(xorriso, xorriso->wdi, &stbuf, 0)<0) {
     sprintf(xorriso->info_text,
             "Current -cd path does not yet exist in the ISO image");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     {ret= 0; goto ex;}
   }
   if(!S_ISDIR(stbuf.st_mode)) {
     sprintf(xorriso->info_text,
             "Current -cd meanwhile points to a non-directory in ISO image");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     {ret= 0; goto ex;}
   }
   patterns= calloc(1, sizeof(char *));
   if(patterns == NULL) {
no_memory:;
     sprintf(xorriso->info_text,
             "Cannot allocate enough memory for pattern expansion");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
     {ret= -1; goto ex;}
   }
   nump= 1;
   if(flag&8)
     patterns[0]= ".";
   else 
     patterns[0]= "*";
   flag&= ~2;
 } else {
   patterns= calloc(nump, sizeof(char *));
   if(patterns==NULL)
     goto no_memory;
   for(i= 0; i<nump; i++) {
     if(argv[i + *idx][0]==0)
       patterns[i]= "*";
     else
       patterns[i]= argv[i + *idx];
   }
 }

 if((flag & 1) && !(xorriso->ino_behavior & 1)) {
   ret= Xorriso_make_hln_array(xorriso, 0); /* for stbuf.st_nlink */
   if(ret < 0)
     return(ret);
 }
 if(flag&2) {
   ret= Xorriso_ls_filev(xorriso, xorriso->wdi, nump, argv + (*idx), mem,
                         flag&(1|4|8)); 
 } else if(nump==1 && strcmp(patterns[0],"*")==0 && !(flag&4)){
   /* save temporary memory by calling simpler function */
   ret= Xorriso_ls(xorriso, (flag&1)|4);
 } else {
   ret= Xorriso_expand_pattern(xorriso, nump, patterns, 0, &filec, &filev,
                               &mem, 0);
   if(ret<=0)
     {ret= 0; goto ex;}
   ret= Xorriso_ls_filev(xorriso, xorriso->wdi, filec, filev, mem,
                         flag&(1|4|8)); 
 }
 if(ret<=0)
   {ret= 0; goto ex;}

 ret= 1;
ex:;
 if(patterns!=NULL)
   free((char *) patterns);
 Sfile_destroy_argv(&filec, &filev, 0);
 (*idx)= end_idx;
 return(ret);
}


/* Options -lsx, -lslx, -lsdx , -lsdlx , -dux , -dusx
   @param flag bit0= long format (-lslx , -dux)
               bit1= do not expand patterns but use literally
               bit2= du rather than ls
               bit3= list directories as themselves (ls -d) 
*/
int Xorriso_option_lsx(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int ret, end_idx, filec= 0, nump, i;
 char **filev= NULL, **patterns= NULL;
 off_t mem= 0;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1|2);
 if(xorriso->do_disk_pattern==0)
   flag|= 2;

 nump= end_idx - *idx;
 if((flag&2) && nump>0) {
   ;
 } else if(nump <= 0) {
   patterns= calloc(1, sizeof(char *));
   if(patterns == NULL) {
no_memory:;
     sprintf(xorriso->info_text,
             "Cannot allocate enough memory for pattern expansion");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
     {ret= -1; goto ex;}
   }
   nump= 1;
   if(flag&8)
     patterns[0]= ".";
   else
     patterns[0]= "*";
   flag&= ~2;
 } else {
   patterns= calloc(nump, sizeof(char *));
   if(patterns==NULL)
     goto no_memory;
   for(i= 0; i<nump; i++) {
     if(argv[i + *idx][0]==0)
       patterns[i]= "*";
     else
       patterns[i]= argv[i + *idx];
   }
 }
 if(flag&2) {
   ret= Xorriso_lsx_filev(xorriso, xorriso->wdx,
                          nump, argv + (*idx), mem, flag&(1|4|8)); 

#ifdef Not_yeT
 } else if(nump==1 && strcmp(patterns[0],"*")==0 && !(flag&4)){
   /* save temporary memory by calling simpler function */
   ret= Xorriso_ls(xorriso, (flag&1)|4);
#endif

 } else {
   ret= Xorriso_expand_disk_pattern(xorriso, nump, patterns, 0, &filec, &filev,
                                    &mem, 0);
   if(ret<=0)
     {ret= 0; goto ex;}
   ret= Xorriso_lsx_filev(xorriso, xorriso->wdx, filec, filev, mem,
                          flag&(1|4|8)); 
 }
 if(ret<=0)
   {ret= 0; goto ex;}

 ret= 1;
ex:;
 if(patterns!=NULL)
   free((char *) patterns);
 Sfile_destroy_argv(&filec, &filev, 0);
 (*idx)= end_idx;
 return(ret);
}


/* Option -map , -map_single */
/* @param flag bit0=do not report the added item
               bit1=do not reset pacifier, no final pacifier message
               bit5=eventually do not insert directory tree
*/
int Xorriso_option_map(struct XorrisO *xorriso, char *disk_path,
                       char *iso_path, int flag)
{
 int ret;
 char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth;

 if(!(flag&2))
   Xorriso_pacifier_reset(xorriso, 0);

 ipth= iso_path;
 if(ipth[0]==0)
   ipth= disk_path;
 if(disk_path[0]==0) {
   sprintf(xorriso->info_text, "-map: Empty disk_path given");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
   return(0);
 }
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin,
                                 2|4);
 if(ret<=0)
   return(ret);
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2);
 if(ret<=0)
   return(ret);
 ret= Xorriso_graft_in(xorriso, NULL, eff_origin, eff_dest,
                       (off_t) 0, (off_t) 0, 2|(flag&32));
 if(!(flag&2))
   Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1);
 if(ret<=0)
   return(ret);

 if(!(flag&1)) {
   sprintf(xorriso->info_text, "Added to ISO image: %s '%s'='%s'\n",
           (ret>1 ? "directory" : "file"), (eff_dest[0] ? eff_dest : "/"),
           eff_origin);
   Xorriso_info(xorriso,0);
 }
 return(1);
}


/* Options -map_l , -compare_l , -update_l , -extract_l */
/* @param flag bit4= do not establish and dispose xorriso->di_array
                     for update_l
               bit8-11= mode 0= -map_l
                             1= -compare_l
                             2= -update_l
                             3= -extract_l
*/
int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
                         int *idx, int flag)
{
 int ret, end_idx, optc= 0, was_failure= 1, i, fret, mode;
 int ns_flag= 2|4, nt_flag= 2, opt_args_flag= 2, made_di_array= 0;
 char source_prefix[SfileadrL], target_prefix[SfileadrL], *cmd, **optv= NULL;
 char eff_source[SfileadrL], eff_target[SfileadrL], *source_pt, *s_wd, *t_wd;
 char sfe[5*SfileadrL], **eff_src_array= NULL, **eff_tgt_array= NULL;

 cmd= "-map_l";
 s_wd= xorriso->wdx;
 t_wd= xorriso->wdi;
 Xorriso_pacifier_reset(xorriso, 0);
 mode= (flag>>8) & 15;

 if(mode==1)
   cmd= "-compare_l";
 else if(mode==2)
   cmd= "-update_l";
 else if(mode==3) {
   cmd= "-extract_l";
   ns_flag= 2;
   s_wd= xorriso->wdi;
   nt_flag= 2|4;
   t_wd= xorriso->wdx;
   opt_args_flag= 0;
 }

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1|2);
 if(end_idx - (*idx) < 3) {
   sprintf(xorriso->info_text, "%s: Not enough arguments given (%d < 3)", cmd,
           end_idx - (*idx));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
   ret= 0; goto ex;
 }
 ret= Xorriso_normalize_img_path(xorriso, s_wd, argv[*idx],
                                 source_prefix, ns_flag | 64);
 if(ret<=0)
   goto ex;
 ret= Xorriso_normalize_img_path(xorriso, t_wd, argv[(*idx)+1],
                                 target_prefix, nt_flag);
 if(ret<=0)
   goto ex;
 ret= Xorriso_opt_args(xorriso, cmd, argc, argv, (*idx)+2, &end_idx,
                       &optc, &optv, opt_args_flag);
 if(ret<=0)
   goto ex;


 if(mode == 3 &&
    (xorriso->do_restore_sort_lba || !(xorriso->ino_behavior & 4))) {
   eff_src_array= calloc(optc, sizeof(char *));
   eff_tgt_array= calloc(optc, sizeof(char *));
   if(eff_src_array == NULL || eff_tgt_array == NULL) {
     Xorriso_no_malloc_memory(xorriso, NULL, 0);
     ret= -1; goto ex;
   }
   for(i= 0; i < optc; i++)
     eff_src_array[i]= eff_tgt_array[i]= NULL;
 }
 if(mode == 2 && !((xorriso->ino_behavior & 2) || (flag & 16) ||
                   xorriso->di_array != NULL)) {
   /* Create all-image node array sorted by isofs.di */
   ret= Xorriso_make_di_array(xorriso, 0);
   if(ret <= 0)
     goto ex;
   made_di_array= 1;
 }

 for(i= 0; i<optc; i++) {
   ret= Xorriso_normalize_img_path(xorriso, s_wd, optv[i],
                                   eff_source, ns_flag);
   if(ret<=0)
     goto ex;
   strcpy(eff_target, target_prefix);
   source_pt= eff_source;
   if(source_prefix[0]) {
     if(strncmp(source_prefix, eff_source, strlen(source_prefix))!=0) {
       sprintf(xorriso->info_text,
               "%s: disk_path %s does not begin with disk_prefix ", cmd,
               Text_shellsafe(eff_source, sfe, 0));
       Text_shellsafe(source_prefix,
                      xorriso->info_text+strlen(xorriso->info_text), 0);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
       ret= 0; goto ex;
     }
     source_pt+= strlen(source_prefix);
   }
   strcat(eff_target, source_pt);

   if(mode==0)
     ret= Xorriso_option_map(xorriso, eff_source, eff_target, 2);
   else if(mode==1)
     ret= Xorriso_option_compare(xorriso, eff_source, eff_target, 2|8);
   else if(mode==2)
     ret= Xorriso_option_update(xorriso, eff_source, eff_target, 2 | 8 | 16);
   else if(mode==3) {
     if(eff_src_array != NULL) {
       eff_src_array[i]= strdup(eff_source);
       eff_tgt_array[i]= strdup(eff_target);
       if(eff_src_array[i] == NULL || eff_tgt_array[i] == NULL) {
         Xorriso_no_malloc_memory(xorriso, &(eff_src_array[i]), 0);
         ret= -1; goto ex;
       }
     } else {
       ret= Xorriso_option_extract(xorriso, eff_source, eff_target, 2 | 4);
     }
   }

   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 2);
   if(fret>=0)
 continue;
   goto ex;
 }

 ret= 1;
 if(mode == 3 && eff_src_array != NULL) {
   ret= Xorriso_lst_append_binary(&(xorriso->node_disk_prefixes),
                                  target_prefix, strlen(target_prefix) + 1, 0);
   if(ret <= 0)
     goto ex;
   ret= Xorriso_lst_append_binary(&(xorriso->node_img_prefixes),
                                  source_prefix, strlen(source_prefix) + 1, 0);
   if(ret <= 0)
     goto ex;
   ret= Xorriso_restore_sorted(xorriso, optc, eff_src_array, eff_tgt_array, 0);
 }
 if(mode==0)
   Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1);
 else if(mode==1 || mode==2)
   Xorriso_pacifier_callback(xorriso, "content bytes read",
                             xorriso->pacifier_count, 0, "", 1);
 else if(mode==3)
   Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
                             xorriso->pacifier_total, "", 1|4);
ex:;
 Xorriso_destroy_node_array(xorriso, 0);
 i= optc;
 Sfile_destroy_argv(&i, &eff_src_array, 0);
 i= optc;
 Sfile_destroy_argv(&i, &eff_tgt_array, 0);
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &optc, &optv, 256);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -mark */
int Xorriso_option_mark(struct XorrisO *xorriso, char *mark, int flag)
{
 if(mark[0]==0)
   xorriso->mark_text[0]= 0;
 else
   strncpy(xorriso->mark_text,mark,sizeof(xorriso->mark_text)-1);
 xorriso->mark_text[sizeof(xorriso->mark_text)-1]= 0;
 return(1);
}


/* Option -md5 "on"|"all"|"off" */
int Xorriso_option_md5(struct XorrisO *xorriso, char *mode, int flag)
{
 char *npt, *cpt;
 int l;

 npt= cpt= mode;
 for(; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l == 0)
 continue;
   if(l == 3 && strncmp(cpt, "off", l) == 0)
     xorriso->do_md5&= ~31;
   else if(l == 2 && strncmp(cpt, "on", l) == 0)
     xorriso->do_md5= (xorriso->do_md5 & ~31) | 7 | 16;
   else if(l == 3 && strncmp(cpt, "all", l) == 0)
     xorriso->do_md5|= 31;
   else if(l == 18 && strncmp(cpt, "stability_check_on", l) == 0)
     xorriso->do_md5|= 8;
   else if(l == 19 && strncmp(cpt, "stability_check_off", l) == 0)
     xorriso->do_md5&= ~8;
   else {
     sprintf(xorriso->info_text, "-md5: unknown mode ");
     Text_shellsafe(cpt, xorriso->info_text, 1);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 return(1);
}


/* Option -mkdir alias -mkdiri */
int Xorriso_option_mkdiri(struct XorrisO *xorriso, int argc, char **argv,
                          int *idx, int flag)
{
 int i, end_idx, ret, was_failure= 0, fret;

 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 0);

 for(i= *idx; i<end_idx; i++) {
   ret= Xorriso_mkdir(xorriso, argv[i], 0);
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1; 
ex:;
 (*idx)= end_idx;
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Options -mount , -mount_cmd , -session_string */
/* @param bit0= -mount_cmd: print mount command to result channel rather
                            than performing it
          bit1= perform -session_string rather than -mount_cmd
*/
int Xorriso_option_mount(struct XorrisO *xorriso, char *dev, char *adr_mode,
                         char *adr, char *cmd, int flag)
{
 int ret, entity_code= 0, m_flag;
 char entity_id[81], *mnt;

 if(flag & 1)
   mnt= "-mount_cmd";
 else if(flag & 2)
   mnt= "-session_string";
 else {
   mnt= "-mount";
   if(xorriso->allow_restore <= 0) {
     sprintf(xorriso->info_text,
          "-mount: image-to-disk features are not enabled by option -osirrox");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
   if(xorriso->volset_change_pending) {
     sprintf(xorriso->info_text,
             "%s: Image changes pending. -commit or -rollback first", mnt);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 ret= Xorriso_decode_load_adr(xorriso, mnt, adr_mode, adr,
                              &entity_code, entity_id, 0);
 if(ret <= 0)
   return(ret);
 if(flag & 2)
   m_flag= 1 | 4;
 else
   m_flag= (flag & 1) | 2;
 ret= Xorriso_mount(xorriso, dev, entity_code, entity_id, cmd, m_flag);
 return(ret);
}


/* Option -mount_opts option[:...] */
int Xorriso_option_mount_opts(struct XorrisO *xorriso, char *mode, int flag)
{
 int was, l;
 char *cpt, *npt;

 was= xorriso->mount_opts_flag;
 npt= cpt= mode;
 for(cpt= mode; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l==0)
     goto unknown_mode;
   if(strncmp(cpt, "shared", l)==0) {
     xorriso->mount_opts_flag|= 1;
   } else if(strncmp(cpt, "exclusive", l)==0) {
     xorriso->mount_opts_flag&= ~1;
   } else {
unknown_mode:;
     if(l<SfileadrL)
       sprintf(xorriso->info_text, "-mount_opts: unknown option '%s'", cpt);
     else
       sprintf(xorriso->info_text, "-mount_opts: oversized parameter (%d)",l);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     xorriso->mount_opts_flag= was;
     return(0);
   }
 }
 return(1);
}


/* Option -mv alias -mvi */
int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv,
                      int *idx, int flag)
{
 int i, end_idx_dummy, ret, is_dir= 0, was_failure= 0, fret;
 char sfe[5*SfileadrL], sfe2[5*SfileadrL];
 char eff_origin[SfileadrL], eff_dest[SfileadrL], dest_dir[SfileadrL];
 char leafname[SfileadrL];
 int optc= 0;
 char **optv= NULL;

 ret= Xorriso_cpmv_args(xorriso, "-mvi", argc, argv, idx,
                        &optc, &optv, eff_dest, 0);
 if(ret<=0)
   goto ex;
 if(ret==2) {
   is_dir= 1;
   strcpy(dest_dir, eff_dest);
 }
 /* Perform movements */
 for(i= 0; i<optc; i++) {
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi,optv[i],eff_origin,0);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   if(is_dir) {
     ret= Sfile_leafname(eff_origin, leafname, 0);
     if(ret<=0)
       goto problem_handler;
     strcpy(eff_dest, dest_dir);
     ret= Sfile_add_to_path(eff_dest, leafname, 0);
     if(ret<=0) {
       sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
             (int) (strlen(eff_dest)+strlen(leafname)+1));
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       goto problem_handler;
     }
   }
   ret= Xorriso_rename(xorriso, NULL, eff_origin, eff_dest, 0);
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   sprintf(xorriso->info_text, "Renamed in ISO image: %s to %s\n",
           Text_shellsafe(eff_origin,sfe,0),Text_shellsafe(eff_dest,sfe2,0));
   Xorriso_info(xorriso, 0);

 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= !was_failure;
ex:;
 Xorriso_opt_args(xorriso, "-mvi",
                  argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256);
 return(ret);
}


/* Option -no_rc */
int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag)
{
 xorriso->no_rc= 1;
 return(1);
}


/* Option -not_leaf */
int Xorriso_option_not_leaf(struct XorrisO *xorriso, char *pattern, int flag)
{
 regex_t re;
 char regexpr[2*SfileadrL+2], sfe[5*SfileadrL];
 int ret= 0;

 if(pattern[0]==0)
   {ret= 0; goto cannot_add;}
 Xorriso__bourne_to_reg(pattern, regexpr, 0);
 if(regcomp(&re, regexpr, 0)!=0)
   {ret= 0; goto cannot_add;}
 ret= Exclusions_add_not_leafs(xorriso->disk_exclusions, pattern, &re, 0);
 if(ret<=0) {
cannot_add:;
   sprintf(xorriso->info_text,"Cannot add pattern: -not_leaf %s",
           Text_shellsafe(pattern, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(ret);
 }
 return(1);
}


/* Option -not_list , -quoted_not_list */
/* @param flag bit0= -quoted_not_list */
int Xorriso_option_not_list(struct XorrisO *xorriso, char *adr, int flag)
{
 int ret, linecount= 0, insertcount= 0, null= 0, argc= 0, i;
 FILE *fp= NULL;
 char sfe[5*SfileadrL], **argv= NULL;
 
 Xorriso_pacifier_reset(xorriso, 0);
 if(adr[0]==0) {
   sprintf(xorriso->info_text, "Empty file name given with %s",
           (flag & 1) ? "-quoted_not_list" : "-not_list");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0);
 if(ret <= 0)
   return(0);
 while(1) {
   ret= Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv,
                           4 | (flag & 1) );
   if(ret <= 0)
     goto ex;
   if(ret == 2)
 break;
   for(i= 0; i < argc; i++) {
     if(argv[i][0] == 0)
   continue;
     if(strchr(argv[i], '/')!=NULL) {
       null= 0;
       ret= Xorriso_option_not_paths(xorriso, 1, argv + i, &null, 0);
     } else
       ret= Xorriso_option_not_leaf(xorriso, argv[i], 0);
     if(ret<=0)
       goto ex;
     insertcount++;
   }
 }
 ret= 1;
ex:;
 if(fp != NULL && fp != stdin)
   fclose(fp);
 Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, 2);
 if(ret<=0) {
   sprintf(xorriso->info_text, "Aborted reading of file %s in line number %d",
           Text_shellsafe(adr, sfe, 0), linecount);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 }
 sprintf(xorriso->info_text, "Added %d exclusion list items from file %s\n",
         insertcount, Text_shellsafe(adr, sfe, 0));
 Xorriso_info(xorriso,0);
 return(ret);
}


/* Option -not_mgt */
int Xorriso_option_not_mgt(struct XorrisO *xorriso, char *setting, int flag)
{
 int ret;
 char what_data[SfileadrL], *what, *what_next;

 if(Sfile_str(what_data, setting, 0)<=0) {
   sprintf(xorriso->info_text,
           "-not_mgt: setting string is much too long (%d)",
           (int) strlen(setting));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 } 
 for(what= what_data; what!=NULL; what= what_next) {
   what_next= strchr(what, ':');
   if(what_next!=NULL) {
     *what_next= 0;
     what_next++;
   }

   if(strcmp(what, "reset")==0 || strcmp(what, "erase")==0) {
     if(strcmp(what, "reset")==0)
       xorriso->disk_excl_mode= 1;
     Exclusions_destroy(&(xorriso->disk_exclusions), 0);
     ret= Exclusions_new(&(xorriso->disk_exclusions), 0);
     if(ret<=0) {
       Xorriso_no_malloc_memory(xorriso, NULL, 0);
       return(ret);
     }
   } else if(strcmp(what, "on")==0) {
     xorriso->disk_excl_mode|= 1;
   } else if(strcmp(what, "off")==0) {
     xorriso->disk_excl_mode&= ~1;
   } else if(strcmp(what, "param_on")==0) {
     xorriso->disk_excl_mode|= 2;
   } else if(strcmp(what, "param_off")==0) {
     xorriso->disk_excl_mode&= ~2;
   } else if(strcmp(what, "subtree_on")==0) {
     xorriso->disk_excl_mode|= 4;
   } else if(strcmp(what, "subtree_off")==0) {
     xorriso->disk_excl_mode&= ~4;
   } else if(strcmp(what, "ignore_on")==0) {
     xorriso->disk_excl_mode|= 8;
   } else if(strcmp(what, "ignore_off")==0) {
     xorriso->disk_excl_mode&= ~8;
   } else {
     sprintf(xorriso->info_text, "-not_mgt: unknown setting '%s'", what);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 return(1);
}


/* Option -not_paths */
int Xorriso_option_not_paths(struct XorrisO *xorriso, int argc, char **argv,
                             int *idx, int flag)
{
 int ret, end_idx, num_descr, dummy, optc= 0, i;
 char **descr= NULL, **optv= NULL, sfe[5*SfileadrL], eff_path[SfileadrL];


 end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx,
                          (xorriso->do_disk_pattern==1) | 2);
 if(end_idx<=0)
   return(end_idx);
 num_descr= end_idx - *idx;
 if(num_descr<=0)
   {ret= 1; goto ex;}
 
 /* produce absolute patterns */
 descr= TSOB_FELD(char *, num_descr);
 if(descr==NULL) {
no_memory:;
   Xorriso_no_pattern_memory(xorriso, sizeof(char *) * (off_t) num_descr, 0);
   ret= -1; goto ex;
 }
 for(i= 0; i<num_descr; i++)
   descr[i]= NULL;
 for(i= 0; i<num_descr; i++) {
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, argv[i+*idx],
                                   eff_path, 2|4);
   if(ret<=0)
     goto ex;
   descr[i]= strdup(eff_path); 
   if(descr[i]==NULL)
     goto no_memory;
 }

 ret= Xorriso_opt_args(xorriso, "-not_paths",
                       num_descr, descr, 0, &dummy, &optc, &optv, 2);
 if(ret<=0)
   goto ex; 
 ret= Exclusions_add_not_paths(xorriso->disk_exclusions,
                               num_descr, descr, optc, optv, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text,"Cannot add path list: -not_paths %s%s %s",
           Text_shellsafe(argv[*idx], sfe, 0), (num_descr>1 ? " ..." : ""),
           xorriso->list_delimiter);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 }
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-not_paths",
                  num_descr, descr, 0, &dummy, &optc, &optv, 256);
 if(descr!=NULL) {
   for(i= 0; i<num_descr; i++)
     if(descr[i]!=NULL)
       free(descr[i]);
   free((char *) descr);
   descr= NULL;
 }
 return(ret);
}


/* Option -options_from_file */
int Xorriso_option_options_from_file(struct XorrisO *xorriso, char *adr,
                                     int flag)
/*
 bit0= called from Xorriso_prescan_args,
       therefore execute via that same function
*/
/*
return:
 <=0 error , 1 = success , 3 = end program run
*/
{
 int ret,linecount= 0, argc= 0, was_failure= 0, fret;
 FILE *fp= NULL;
 char shellsafe[5*SfileadrL];
 char **argv= NULL;
 int linec= 0;
 char *line= NULL, **linev= NULL;

 if(adr[0]==0) {
   sprintf(xorriso->info_text,"Empty file name given with -options_from_file");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 Text_shellsafe(adr,shellsafe,0);
 if(xorriso->is_dialog) {
   sprintf(xorriso->info_text,"+ performing command lines from file %s :\n",
           shellsafe);
   Xorriso_info(xorriso,1);
 }
 ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0);
 if(ret <= 0)
   return(0);
 while(1) {
   ret= Xorriso_read_lines(xorriso, fp, &linecount, &linec, &linev, 1 | 8);
   if(ret <= 0)
     goto ex; /* no problem_handler because there is no sense in going on */
   if(ret == 2)
 break;
   line= linev[0];
   if(line[0]==0 || line[0]=='#')
 continue;

   if(flag&1) {
     ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv,
                          4 | 8 | ((xorriso->bsl_interpretation & 3) << 5));
     if(ret<=0)
       goto problem_handler;
     ret= Xorriso_prescan_args(xorriso,argc,argv,1);
     if(ret==0)
       {ret= 3; goto ex;}
     if(ret<0)
       goto problem_handler;
   } else {
     if(xorriso->is_dialog) {
       sprintf(xorriso->info_text,"+ %d:  %s\n",linecount,line);
       Xorriso_info(xorriso,1);
     }
     ret= Xorriso_execute_option(xorriso,line,1|(1<<16));
     if(ret==3)
       goto ex;
     if(ret<=0)
       goto problem_handler;
   }

 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1;
ex:;
 Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */
 Xorriso_read_lines(xorriso, fp, &linecount, &linec, &linev, 2);
 Xorriso_reset_counters(xorriso,0);
 if(fp != NULL && fp != stdin)
   fclose(fp);
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "error triggered by line %d of file:\n    %s\n",
           linecount,shellsafe);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 1);
 }
 if(ret!=1)
   return(ret);
 return(!was_failure);
}


/* Option -osirrox "on"|"off" */
int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag)
{
 int l, allow_restore;
 char *npt, *cpt;

 allow_restore= xorriso->allow_restore;

 npt= cpt= mode;
 for(cpt= mode; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l==0 && mode[0]!=0)
     goto unknown_mode;
   if(strncmp(cpt, "off", l)==0)
     allow_restore= 0;
   else if(strncmp(cpt, "banned", l)==0)
     allow_restore= -1;
   else if(strncmp(cpt, "device_files", l)==0)
     allow_restore= 2;
   else if(strncmp(cpt, "on", l)==0 || mode[0]==0)
     allow_restore= 1;
   else if(strncmp(cpt, "concat_split_on", l)==0)
     xorriso->do_concat_split= 1;
   else if(strncmp(cpt, "concat_split_off", l)==0)
     xorriso->do_concat_split= 0;
   else if(strncmp(cpt, "auto_chmod_on", l)==0)
     xorriso->do_auto_chmod= 1;
   else if(strncmp(cpt, "auto_chmod_off", l)==0)
     xorriso->do_auto_chmod= 0;
   else if(strncmp(cpt, "sort_lba_on", l)==0)
     xorriso->do_restore_sort_lba= 1;
   else if(strncmp(cpt, "sort_lba_off", l)==0)
     xorriso->do_restore_sort_lba= 0;
   else if(strncmp(cpt, "o_excl_off", l)==0)
     xorriso->drives_exclusive= 0;
   else if(strncmp(cpt, "o_excl_on", l)==0)
     xorriso->drives_exclusive= 1;
   else {
unknown_mode:;
     sprintf(xorriso->info_text, "-osirrox: unknown mode '%s'", cpt);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 if(allow_restore > 0 && xorriso->allow_restore == -1) {
   sprintf(xorriso->info_text,
     "-osirrox: was already permanently disabled by setting 'banned'");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(xorriso->allow_restore != -1)
   xorriso->allow_restore= allow_restore;
 sprintf(xorriso->info_text,
         "Copying of file objects from ISO image to disk filesystem is: %s\n",
         xorriso->allow_restore > 0 ? "Enabled" : "Disabled");
 Xorriso_info(xorriso, 0);
 return(1);
}


/* Option -overwrite "on"|"nondir"|"off" */
int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_overwrite= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->do_overwrite= 1;
 else if(strcmp(mode, "nondir")==0)
   xorriso->do_overwrite= 2;
 else {
   sprintf(xorriso->info_text, "-overwrite: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -pacifier */
int Xorriso_option_pacifier(struct XorrisO *xorriso, char *style, int flag)
{
 if(strcmp(style, "xorriso")==0 || strcmp(style, "default")==0)
   xorriso->pacifier_style= 0;
 else if(strcmp(style, "mkisofs")==0 || strcmp(style, "genisofs")==0 ||
         strcmp(style, "genisoimage")==0 || strcmp(style, "xorrisofs")==0)
   xorriso->pacifier_style= 1;
 else if(strcmp(style, "cdrecord")==0 || strcmp(style, "cdrskin")==0 ||
         strcmp(style, "wodim")==0 || strcmp(style, "xorrecord")==0)
   xorriso->pacifier_style= 2;
 else {
   sprintf(xorriso->info_text, "-pacifier: unknown behavior code '%s'", style);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


/* Option -padding */
int Xorriso_option_padding(struct XorrisO *xorriso, char *size, int flag)
{
 double num;
 
 num= Scanf_io_size(size, 0);
 if(num < 0 || num > 1024.0 * 1024.0 * 1024.0) {
   sprintf(xorriso->info_text, "-padding: wrong size %.f (allowed: %.f - %.f)",
           num, 0.0, 1024.0 * 1024.0 * 1024.0);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 xorriso->padding= num;
 if(xorriso->padding/2048 != num/2048.0)
   xorriso->padding++;
 return(1);
}


/* Option -page */
int Xorriso_option_page(struct XorrisO *xorriso, int len, int width, int flag)
{
 if(len<0 || width<=0) {
   sprintf(xorriso->info_text,
             "Improper numeric value of arguments of -page:  %d  %d",
             len, width);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 xorriso->result_page_length= len;
 xorriso->result_page_width= width;
 return(1);
}


/* Option -paste_in */
int Xorriso_option_paste_in(struct XorrisO *xorriso, char *iso_rr_path,
                           char *disk_path, char *start, char *count, int flag)
{
 int ret;
 double num;
 off_t startbyte, bytecount;
 
 num= Scanf_io_size(start, 0);
 if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */
   sprintf(xorriso->info_text,
        "-paste_in: startbyte address negative or much too large (%s)", start);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 startbyte= num;
 num= Scanf_io_size(count, 0);
 if(num<=0 || num > 1.0e18) {
   sprintf(xorriso->info_text,
         "-paste_in : bytecount zero, negative or much too large (%s)", count);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 bytecount= num;
 sprintf(xorriso->info_text, "-paste_in from %s to %s, byte %.f to %.f",
         disk_path, iso_rr_path,
         (double) startbyte, (double) (startbyte+bytecount));
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);

 ret= Xorriso_paste_in(xorriso, disk_path, startbyte, bytecount,
                       iso_rr_path, 0); 
 return(ret);
}


/* Option -path_list , -quoted_path_list */
/* @param flag bit0= -quoted_path_list */
int Xorriso_option_path_list(struct XorrisO *xorriso, char *adr, int flag)
{
 int ret,linecount= 0, insertcount= 0, null= 0, was_failure= 0, fret= 0;
 int was_ferror= 0, argc= 0, i;
 FILE *fp= NULL;
 char sfe[5*SfileadrL], **argv= NULL;

 Xorriso_pacifier_reset(xorriso, 0);
 if(adr[0]==0) {
   sprintf(xorriso->info_text,"Empty file name given with %s",
           flag & 1 ? "-quoted_path_list" : "-path_list");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   return(0);
 }
 ret= Xorriso_afile_fopen(xorriso, adr, "rb", &fp, 0);
 if(ret <= 0)
   return(0);
 while(1) {
   ret= Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv,
                           4 | (flag & 1) );
   if(ret <= 0)
     goto ex;
   if(ret == 2)
 break;
   for(i= 0; i < argc; i++) {
     if(argv[i][0] == 0)
   continue;
     null= 0;
     ret= Xorriso_option_add(xorriso, 1, argv + i, &null, 1|2);
     if(ret<=0 || xorriso->request_to_abort)
       goto problem_handler;
     insertcount++;
   }

 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1;
ex:;
 if(flag & 1)
   Xorriso_read_lines(xorriso, fp, &linecount, &argc, &argv, 2);

 if(fp != NULL && fp != stdin)
   fclose(fp);
 Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
                           xorriso->pacifier_total, "", 1);
 if(ret<=0) {
   sprintf(xorriso->info_text, "Aborted reading of file %s in line number %d",
           Text_shellsafe(adr, sfe, 0), linecount);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
                       (fret==-2 ? "NOTE" : "FAILURE"), 0);
 } else
   ret= !was_ferror;
 sprintf(xorriso->info_text, "Added %d items from file %s\n",
         insertcount, Text_shellsafe(adr, sfe, 0));
 Xorriso_info(xorriso,0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -pathspecs */
int Xorriso_option_pathspecs(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->allow_graft_points= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->allow_graft_points= 1;
 else {
   sprintf(xorriso->info_text, "-pathspecs: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 return(1);
}


/* Option -pkt_output */
int Xorriso_option_pkt_output(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode,"off")==0)
   xorriso->packet_output= 0;
 else
   xorriso->packet_output= 1;
 return(1);
}


/* Option -print */
int Xorriso_option_print(struct XorrisO *xorriso, char *text, int flag)
{
 sprintf(xorriso->result_line,"%s\n",text);
 Xorriso_result(xorriso,1);
 return(1);
}


/* Option -print_size
   @param flag bit0= report in mkisofs compatible form on real stdout
*/
int Xorriso_option_print_size(struct XorrisO *xorriso, int flag)
{
 int ret, fd;

 if(!xorriso->volset_change_pending) {
   sprintf(xorriso->info_text,"-print_size: No image modifications pending");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   sprintf(xorriso->result_line,"Image size   : 0s\n");
   Xorriso_result(xorriso,0);
   return(2);
 }
 ret= Xorriso_write_session(xorriso, 1);
 if(ret<=0) {
   sprintf(xorriso->info_text,"-print_size: Failed to set up virtual -commit");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 if(flag&1) {
   sprintf(xorriso->result_line,"%d\n", ret);
   fd= xorriso->dev_fd_1;
   if(fd<0)
     fd= 1;
   write(fd, xorriso->result_line, strlen(xorriso->result_line));
   fsync(fd);
 } else {
   sprintf(xorriso->result_line,"Image size   : %ds\n", ret);
   Xorriso_result(xorriso,0);
 }
 return(1);
}


/* Option -prog */
int Xorriso_option_prog(struct XorrisO *xorriso, char *name, int flag)
{
 if(strlen(name)>=sizeof(xorriso->progname)) {
   sprintf(xorriso->info_text,
           "Name too long with option -prog (%d > %d)",
           (int) strlen(name), (int) sizeof(xorriso->progname)-1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 if(Sfile_str(xorriso->progname,name,0)<=0)
   return(-1);
 return(1);
}


/* Option -prog_help */
int Xorriso_option_prog_help(struct XorrisO *xorriso, char *name, int flag)
{
 int ret;

 ret= Xorriso_option_prog(xorriso, name, 0);
 if(ret<=0)
   return(ret);
 ret= Xorriso_option_help(xorriso, 0);
 return(ret);
}


/* Option -prompt */
int Xorriso_option_prompt(struct XorrisO *xorriso, char *text, int flag)
{
 int ret;
 char line[80];

 strncpy(xorriso->result_line,text,sizeof(xorriso->result_line)-1);
 xorriso->result_line[sizeof(xorriso->result_line)-1]= 0;
 Xorriso_result(xorriso,0);
 ret= Xorriso_dialog_input(xorriso, line, sizeof(line),1);
 return(ret);
}


/* Option -publisher */
int Xorriso_option_publisher(struct XorrisO *xorriso, char *name, int flag)
{
  if(Xorriso_check_name_len(xorriso, name, (int) sizeof(xorriso->publisher),
                            "-publisher", 0) <= 0)
    return(0);
 strcpy(xorriso->publisher,name);
 Xorriso_set_change_pending(xorriso, 1);
 return(1);
}


/* Option -pvd_info */
int Xorriso_option_pvd_info(struct XorrisO *xorriso, int flag)
{
  return(Xorriso_pvd_info(xorriso, 0));
}


/* Option -pwd alias -pwdi */
int Xorriso_option_pwdi(struct XorrisO *xorriso, int flag)
{
 char sfe[5 * SfileadrL];

 sprintf(xorriso->info_text,"current working directory in ISO image:\n");
 Xorriso_info(xorriso,0);
 sprintf(xorriso->result_line,"%s/\n", Text_shellsafe(xorriso->wdi, sfe, 0));
 Xorriso_result(xorriso,0);
 return(1);
}


/* Option -pwdx */
int Xorriso_option_pwdx(struct XorrisO *xorriso, int flag)
{
 sprintf(xorriso->info_text,"current working directory on hard disk:\n");
 Xorriso_info(xorriso,0);
 sprintf(xorriso->result_line,"%s/\n",xorriso->wdx);
 Xorriso_result(xorriso,0);
 return(1);
}


/* Option -reassure "on"|"tree"|"off" */
int Xorriso_option_reassure(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "off")==0)
   xorriso->do_reassure= 0;
 else if(strcmp(mode, "on")==0)
   xorriso->do_reassure= 1;
 else if(strcmp(mode, "tree")==0)
   xorriso->do_reassure= 2;
 else {
   sprintf(xorriso->info_text, "-reassure: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 return(1);
}


/* Option -unregister_filter */
int Xorriso_option_unregister_filter(struct XorrisO *xorriso, char *name,
                                     int flag)
{
 int ret;

 ret= Xorriso_external_filter(xorriso, name, "", "", 0, NULL, 1);
 return(ret);
}


/* Option -report_about */
int Xorriso_option_report_about(struct XorrisO *xorriso, char *severity,
                                int flag)
{
 int ret, sev;
 char sfe[5*SfileadrL];

 ret= Xorriso__text_to_sev(severity, &sev, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "-report_about: Not a known severity name : %s",
           Text_shellsafe(severity, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
   return(ret);
 }
 if(Sfile_str(xorriso->report_about_text,severity,0)<=0)
   return(-1);
 xorriso->report_about_severity= sev;
 return(1);
}


/* Option -return_with */
int Xorriso_option_return_with(struct XorrisO *xorriso, char *severity,
                               int exit_value, int flag)
{
 int ret, sev;
 char sfe[5*SfileadrL];

 ret= Xorriso__text_to_sev(severity, &sev, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text,
           "-return_with: Not a known severity name : %s",
           Text_shellsafe(severity, sfe, 0));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(ret);
 }
 if(exit_value && (exit_value < 32 || exit_value > 63)) {
   sprintf(xorriso->info_text,
           "-return_with: Not an allowed exit_value. Use 0, or 32 to 63.");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(Sfile_str(xorriso->return_with_text,severity,0)<=0)
   return(-1);
 xorriso->return_with_severity= sev;
 xorriso->return_with_value= exit_value;
 return(1);
}


/* Options -rm alias -rmi , -rm_r alias -rm_ri , -rmdir alias -rmdiri */
/* @param flag bit0=recursive , bit1= remove empty directory: rmdir */
int Xorriso_option_rmi(struct XorrisO *xorriso, int argc, char **argv,
                       int *idx, int flag)
{
 int i, ret, end_idx, was_failure= 0, fret;
 char path[SfileadrL], eff_path[SfileadrL], sfe[5*SfileadrL];
 int optc= 0;
 char **optv= NULL;

 ret= Xorriso_opt_args(xorriso, "-rm*i",
                       argc, argv, *idx, &end_idx, &optc, &optv, 0);
 if(ret<=0)
   goto ex; 
 for(i= 0; i<optc; i++) {
   if(Sfile_str(path,optv[i],0)<=0)
     {ret= -1; goto problem_handler;}
   if(path[0]!='/') {
     ret= Sfile_prepend_path(xorriso->wdi, path, 0);
     if(ret<=0)
       goto problem_handler;
   }
   ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1);
   if(ret<0)
     goto problem_handler;
   if(ret==0) {
     sprintf(xorriso->info_text,
             "Cannot find path %s in loaded ISO image for removal",
             Text_shellsafe(path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     goto problem_handler;
   }
   strcpy(path, eff_path);

   ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, path, flag&(1|2));
   if(ret<=0 || xorriso->request_to_abort)
     goto problem_handler;
   if(ret<3) {
     sprintf(xorriso->info_text, "Removed from ISO image: %s '%s'\n",
             ((flag&2) ? "directory" : (ret>1 ? "subtree" : "file")), path);
     Xorriso_info(xorriso, 0);
   }

 continue; /* regular bottom of loop */
problem_handler:;
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   goto ex;
 }
 ret= 1;
ex:; 
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-rm*i",
                  argc, argv, *idx, &end_idx, &optc, &optv, 256);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -rollback */
/* @param flag bit0= do not -reassure
   @return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_rollback(struct XorrisO *xorriso, int flag)
{
 int ret;
 char indev[SfileadrL], *which_will;

 if(xorriso->volset_change_pending)
   which_will= "revoke the pending image changes";
 else
   which_will= "reload the image";
 if(!(flag&1)) {
   ret= Xorriso_reassure(xorriso, "-rollback", which_will, 0);
   if(ret<=0)
     return(2);
 }

 if(Sfile_str(indev, xorriso->indev, 0)<=0)
   return(-1);
 ret= Xorriso_give_up_drive(xorriso, 1|8);
 if(ret<=0)
   return(ret);
 xorriso->image_start_mode&= ~(1<<31); /* reactivate eventual -load address */
 ret= Xorriso_option_dev(xorriso, indev, 1|4);
 return(ret);
}


/* Option -rom_toc_scan */
int Xorriso_option_rom_toc_scan(struct XorrisO *xorriso, char *mode, int flag)
{
 int l;
 char *cpt, *npt;

 xorriso->toc_emulation_flag= 0;
 npt= cpt= mode;
 for(cpt= mode; npt != NULL; cpt= npt + 1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l==0)
     goto unknown_mode;
   xorriso->toc_emulation_flag&= ~4;
   if(strncmp(cpt, "off", l) == 0)
     xorriso->toc_emulation_flag&= ~1;
   else if(strncmp(cpt, "on", l) == 0)
     xorriso->toc_emulation_flag|= 1;
   else if(strncmp(cpt, "force", l) == 0)
     xorriso->toc_emulation_flag|= 4;
   else if(strncmp(cpt, "emul_off", l) == 0)
     xorriso->toc_emulation_flag|= 2;
   else if(strncmp(cpt, "emul_on", l) == 0)
     xorriso->toc_emulation_flag&= ~2;
   else {
unknown_mode:;
     sprintf(xorriso->info_text, "-rom_toc_scan: unknown mode in '%s'", mode);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     return(0);
   }
 }
 return(1);
}


/* Option -scdbackup_tag list_path record_name */
int Xorriso_option_scdbackup_tag(struct XorrisO *xorriso, char *listname,
                                 char *recname, int flag)
{
 if(strlen(recname) > 80) {
   sprintf(xorriso->info_text,
           "Unsuitable record name given with -scdbackup_tag");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 strcpy(xorriso->scdbackup_tag_name, recname);
 xorriso->scdbackup_tag_time[0]= 0;
 if(Sfile_str(xorriso->scdbackup_tag_listname, listname, 0) <= 0)
   return(-1);
 return(1);
}


/* Option -scsi_log */
int Xorriso_option_scsi_log(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode, "on") == 0)
   xorriso->scsi_log= 1;
 else if(strcmp(mode, "off") == 0)
   xorriso->scsi_log= 0;
 else {
   sprintf(xorriso->info_text, "-scsi_log: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 Xorriso_scsi_log(xorriso, !!xorriso->scsi_log);
 return(1);
}


/* Option -session_log */
int Xorriso_option_session_log(struct XorrisO *xorriso, char *path, int flag)
{
 if(Sfile_str(xorriso->session_logfile, path, 0)<=0)
   return(-1);
 return(1);
}



/* Option -setfacl_list alias -setfacl_listi */
int Xorriso_option_setfacl_listi(struct XorrisO *xorriso, char *path, int flag)
{
 int ret, eaten;
 size_t buf_size= 0, buf_add= 64 * 1024, l, linecount= 0;
 char line[SfileadrL * 4], *buf= NULL, *wpt, *new_buf, limit_text[80];
 char file_path[SfileadrL], uid[161], gid[161];
 FILE *fp= NULL;

 Xorriso_pacifier_reset(xorriso, 0);
 if(path[0]==0) {
   sprintf(xorriso->info_text, "Empty file name given with -setfacl_list");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 0);
 if(ret <= 0)
   return(0);

 buf_size= buf_add;
 buf= calloc(buf_size, 1);
 if(buf == NULL)
   goto out_of_mem;
 wpt= buf;
 *wpt= 0;
 uid[0]= gid[0]= 0;

 while(1) {
   if(Sfile_fgets_n(line, sizeof(line), fp, 0) == NULL)
 break;
   linecount++;
   if(strncmp(line, "# file: ", 8) ==0) {
      if(wpt != buf && file_path[0]) {
        /* Commit previous list */
        ret= Xorriso_perform_acl_from_list(xorriso, file_path,
                                           uid, gid, buf, 0);
        if(ret<=0)
          goto ex;
        wpt= buf;
        *wpt= 0;
        file_path[0]= uid[0]= gid[0]= 0;
      }
      /* Unescape line and register as file path */
      Sfile_bsl_interpreter(line + 8, strlen(line + 8), &eaten, 0);
      if(strlen(line + 8) >= SfileadrL) {
        sprintf(xorriso->info_text, "-setfacl_list: Oversized file path");
        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
        ret= 0; goto ex;
      }
      strcpy(file_path, line + 8);
 continue;
   } else if(strncmp(line, "# owner: ", 9) == 0) {
      if(strlen(line + 9) > 160) {
        sprintf(xorriso->info_text, "-setfacl_list: Oversized owner id");
        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
        ret= 0; goto ex;
      }
      strcpy(uid, line + 9);
 continue;
   } else if(strncmp(line, "# group: ", 9) == 0) {
      if(strlen(line + 9) > 160) {
        sprintf(xorriso->info_text, "-setfacl_list: Oversized group id");
        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
        ret= 0; goto ex;
      }
      strcpy(gid, line + 9);
 continue;
   } else if(line[0] == '#' || line[0] == 0) {
 continue;
   } else if(strcmp(line, "@") == 0) {
     Xorriso_msgs_submit(xorriso, 0,
                "-setfacl_list input ended by '@'", 0, "NOTE", 0);
 break;
   } else if(strcmp(line, "@@@") == 0) {
     Xorriso_msgs_submit(xorriso, 0,
                "-setfacl_list aborted by input line '@@@'", 0, "WARNING", 0);
     ret= 0; goto ex;
   }

   /* Register ACL entry */
   l= strlen(line);
   if(wpt + l + 2 - buf > buf_size) {
     if(buf_size + buf_add > xorriso->temp_mem_limit) {
       Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1);
       sprintf(xorriso->info_text,
      "-setfacl_list: List entry for a single file exceeds -temp_mem_limit %s",
              limit_text);
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
       ret= 0; goto ex;
     }
     buf_size+= buf_add;
     new_buf= realloc(buf, buf_size);
     if(new_buf == NULL)
       goto out_of_mem;
     buf= new_buf;
   }
   memcpy(wpt, line, l);
   *(wpt + l)= '\n';
   wpt+= l + 1;
   *wpt= 0;
 }
 if(wpt != buf && file_path[0]) {
   /* Commit last list */
   ret= Xorriso_perform_acl_from_list(xorriso, file_path, uid, gid, buf, 0);
   if(ret<=0)
     goto ex;
 } else {
   sprintf(xorriso->info_text, "-setfacl_list: Unexpected end of file ");
   Text_shellsafe(path, xorriso->info_text, 1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 ret= 1;
ex:;
 if(buf != NULL)
   free(buf);
 if(fp != NULL && fp != stdin)
   fclose(fp);
 if(ret <= 0) {
   sprintf(xorriso->info_text, "-setfacl_list ");
   Text_shellsafe(path, xorriso->info_text, 1);
   sprintf(xorriso->info_text + strlen(xorriso->info_text),
           " aborted in line %.f\n", (double) linecount);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 }
 return(ret);
out_of_mem:;
 Xorriso_no_malloc_memory(xorriso, &buf, 0);
 ret= -1;
 goto ex;
}


/* Options -setfacl alias -setfacli, -setfacl_r alias -setfacl_ri */
/* @param flag   bit0=recursive -setfacl_r
*/
int Xorriso_option_setfacli(struct XorrisO *xorriso, char *acl_text,
                            int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 int optc= 0;
 char **optv= NULL, *access_acl_text= NULL, *default_acl_text= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-setfacl", argc, argv, *idx, &end_idx, &optc,
                       &optv, 0);
 if(ret <= 0)
   goto ex;

 ret= Xorriso_normalize_acl_text(xorriso, acl_text,
                                 &access_acl_text, &default_acl_text, 0);
 if(access_acl_text != NULL && default_acl_text != NULL) {
   sprintf(xorriso->info_text, "Access-ACL :\n%s", access_acl_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
   sprintf(xorriso->info_text, "Default-ACL :\n%s", default_acl_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 } else if(access_acl_text == NULL && default_acl_text == NULL) {
   sprintf(xorriso->info_text, "Will delete Access-ACL and Default-ACL");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 }
 if(ret <= 0)
   goto ex;

 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-setfacl_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_text_2(job, 25, access_acl_text, default_acl_text, 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else {
     ret= 1;
     if(access_acl_text == NULL || access_acl_text[0] ||
        default_acl_text == NULL || default_acl_text[0])
       ret= Xorriso_setfacl(xorriso, NULL, optv[i],
                            access_acl_text, default_acl_text, 0);
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-setfacl", argc, argv, *idx, &end_idx,
                  &optc, &optv, 256);
 Findjob_destroy(&job, 0);
 if(access_acl_text != NULL)
   free(access_acl_text);
 if(default_acl_text != NULL)
   free(default_acl_text);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Options -setfattr alias -setfattri, -setfattr_r alias -setfattr_ri */
/* @param flag   bit0=recursive -setfattr_r
*/
int Xorriso_option_setfattri(struct XorrisO *xorriso, char *name, char *value,
                            int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;

 ret= Xorriso_opt_args(xorriso, "-setfattr", argc, argv, *idx, &end_idx, &optc,
                       &optv, 0);
 if(ret <= 0)
   goto ex;

 /* check input */
 ret= Xorriso_path_setfattr(xorriso, NULL, "", name, strlen(value), value, 1);
 if(ret <= 0)
    goto ex;
 
 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, "-setfattr_r", 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_text_2(job, 27, name, value, 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else {
     ret= 1;
     ret= Xorriso_path_setfattr(xorriso, NULL, optv[i],
                                name, strlen(value), value, 0);
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, "-setfattr", argc, argv, *idx, &end_idx,
                  &optc, &optv, 256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -setfattr_list alias -setfattr_listi */
int Xorriso_option_setfattr_listi(struct XorrisO *xorriso, char *path,
                                  int flag)
{
 int ret, eaten;
 size_t linecount= 0, mem_used= 0, num_attr= 0, v_len;
 char line[SfileadrL * 4], limit_text[80], *ept, *valuept;
 char file_path[SfileadrL];
 FILE *fp= NULL;
 struct Xorriso_lsT *lst_curr= NULL, *lst_start= NULL;

 Xorriso_pacifier_reset(xorriso, 0);
 if(path[0]==0) {
   sprintf(xorriso->info_text, "Empty file name given with -setfattr_list");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 0);
 if(ret <= 0)
   return(0);

 while(1) {
   if(Sfile_fgets_n(line, sizeof(line), fp, 0) == NULL)
 break;
   linecount++;
   if(strncmp(line, "# file: ", 8) ==0) {
      if(num_attr > 0 && file_path[0]) {
        /* Commit previous list */
        ret= Xorriso_perform_attr_from_list(xorriso, file_path, lst_start, 0);
        if(ret<=0)
          goto ex;
        num_attr= 0;
        file_path[0]= 0;
        Xorriso_lst_destroy_all(&lst_start, 0);
        lst_curr= NULL;
      }
      /* Unescape line and register as file path */
      Sfile_bsl_interpreter(line + 8, strlen(line + 8), &eaten, 0);
      if(strlen(line + 8) >= SfileadrL) {
        sprintf(xorriso->info_text, "-setfattr_list: Oversized file path");
        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
        ret= 0; goto ex;
      }
      strcpy(file_path, line + 8);
 continue;
   } else if(line[0] == '#' || line[0] == 0) {
 continue;
   } else if(strcmp(line, "@") == 0) {
     Xorriso_msgs_submit(xorriso, 0,
                "-setfattr_list input ended by '@'", 0, "NOTE", 0);
 break;
   } else if(strcmp(line, "@@@") == 0) {
     Xorriso_msgs_submit(xorriso, 0,
                "-setfattr_list aborted by input line '@@@'", 0, "WARNING", 0);
     ret= 1; goto ex;
   }
   mem_used+= strlen(line) + 1;
   if(mem_used > xorriso->temp_mem_limit) {
     Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1);
     sprintf(xorriso->info_text,
     "-setfattr_list: List entry for a single file exceeds -temp_mem_limit %s",
              limit_text);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0; goto ex;
   }

   /* Register attr pair */

   ept= strchr(line, '=');
   if(ept == NULL) {
     sprintf(xorriso->info_text, "-setfattr_list: ");
     Text_shellsafe(path, xorriso->info_text, 1);
     sprintf(xorriso->info_text + strlen(xorriso->info_text),
             " : Line %.f : No separator '=' found",
             (double) linecount);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 continue;
   }
   valuept= ept + 1;
   v_len= strlen(valuept);
   for(ept= valuept + v_len - 1; ept > valuept; ept--)
     if(isspace(*ept))
       *ept= 0;
     else
   break;
   v_len= strlen(valuept);
   if(v_len < 2 || *valuept != '"' || *(valuept + v_len -1) != '"') {
     sprintf(xorriso->info_text, "-setfattr_list: ");
     Text_shellsafe(path, xorriso->info_text, 1);
     sprintf(xorriso->info_text + strlen(xorriso->info_text),
             " : Line %.f : Value not enclosed in quotes",
             (double) linecount);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);

 continue;
   }

   ret= Xorriso_lst_new(&lst_curr, line, lst_curr, 0);
   if(ret <= 0)
     goto out_of_mem;
   if(lst_start == NULL)
     lst_start= lst_curr;
   num_attr++;
 }

 if(file_path[0]) {
   /* Commit last list */
   ret= Xorriso_perform_attr_from_list(xorriso, file_path, lst_start, 0);
   if(ret<=0)
     goto ex;
 } else {
   sprintf(xorriso->info_text, "-setfattr_list: Unexpected end of file ");
   Text_shellsafe(path, xorriso->info_text, 1);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 ret= 1;
ex:;
 if(fp != NULL && fp != stdin)
   fclose(fp);
 Xorriso_lst_destroy_all(&lst_start, 0);
 if(ret <= 0) {
   sprintf(xorriso->info_text, "-setfattr_list ");
   Text_shellsafe(path, xorriso->info_text, 1);
   sprintf(xorriso->info_text + strlen(xorriso->info_text),
           " aborted in line %.f\n", (double) linecount);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 }
 return(ret);
out_of_mem:;
 Xorriso_no_malloc_memory(xorriso, NULL, 0);
 ret= -1;
 goto ex;
}


/* Options -set_filter , -set_filter_r , -show_stream , -show_stream_r */
/* @param flag   bit0=recursive -set_filter_r
                 bit1= do not reset pacifier, no final pacifier message
                 bit2= -show_stream rather than -set_filter
*/
int Xorriso_option_set_filter(struct XorrisO *xorriso, char *name,
                              int argc, char **argv, int *idx, int flag)
{
 int i, ret, was_failure= 0, end_idx, fret;
 int optc= 0;
 char **optv= NULL;
 struct FindjoB *job= NULL;
 struct stat dir_stbuf;
 char *cmd= "-set_filter";

 switch(flag & 5) {
 case 0: cmd= "-set_filter";
 break; case 1: cmd= "-set_filter_r";
 break; case 4: cmd= "-show_stream";
 break; case 5: cmd= "-show_stream_r";
 }

 ret= Xorriso_opt_args(xorriso, cmd,
                       argc, argv, *idx, &end_idx, &optc, &optv, 0);
 if(ret <= 0)
   goto ex;
 if(!(flag&2))
   Xorriso_pacifier_reset(xorriso, 0);

 for(i= 0; i<optc; i++) {
   if(flag&1) {
     ret= Findjob_new(&job, optv[i], 0);
     if(ret<=0) {
       Xorriso_no_findjob(xorriso, cmd, 0);
       {ret= -1; goto ex;}
     }
     Findjob_set_action_target(job, ((flag & 4) ? 29 : 28), name, 0);
     Findjob_set_file_type(job, 'f', 0);
     ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
                        NULL, optv[i], &dir_stbuf, 0, 0);
     Findjob_destroy(&job, 0);
   } else {
     ret= 1;
     if(flag & 4)
       ret= Xorriso_show_stream(xorriso, NULL, optv[i], 0);
     else
       ret= Xorriso_set_filter(xorriso, NULL, optv[i], name, 0);
   }
   if(ret>0 && !xorriso->request_to_abort)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
   if(fret>=0)
 continue;
   ret= 0; goto ex;
 }
 if(!(flag&2))
   Xorriso_pacifier_callback(xorriso, "file filters processed",
                             xorriso->pacifier_count, 0, "", 1);
 ret= 1;
ex:;
 (*idx)= end_idx;
 Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx,
                  &optc, &optv, 256);
 Findjob_destroy(&job, 0);
 if(ret<=0)
   return(ret);
 return(!was_failure);
}


/* Option -speed */
int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag)
{
 int is_cd= 1, unit_found= 0, ret, profile_number;
 double num;
 char *cpt, profile_name[80];

 if(speed[0]==0 || strcmp(speed, "any")==0) {
   xorriso->speed= 0; /* full speed */
   return(1);
 }

 sscanf(speed,"%lf",&num);
 for(cpt= speed+strlen(speed)-1; cpt>=speed; cpt--)
   if(isdigit(*cpt) || *cpt=='.')
 break;
 cpt++;

 if(*cpt=='k' || *cpt=='K') {
   /* is merchand kilobyte, stays merchand kilobyte */
   unit_found= 1;
 } else if(*cpt=='m' || *cpt=='M') {
   num*= 1000;
   unit_found= 1;
 } else if(*cpt=='x' || *cpt=='X')
   cpt++;

 if (unit_found) {
   ;
 } else if(*cpt=='c' || *cpt=='C') {
cd_speed:;
   num*= 176.4;
 } else if(*cpt=='d' || *cpt=='D') {
dvd_speed:;
   num*= 1385;
 } else if(*cpt=='b' || *cpt=='B') {
bd_speed:;
   num*= 4495.625;
 } else {
   ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2);
   is_cd= (ret==2);
   if(is_cd)
     goto cd_speed;
   else if (ret == 3)
     goto bd_speed;
   else
     goto dvd_speed;
 }

 if(num> 2.0e9) {
   sprintf(xorriso->info_text,
           "-speed: Value too large or not recognizable: '%s'", speed);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 xorriso->speed= num;
 if(xorriso->speed<num)
   xorriso->speed++;
 return(1);
}


/* Option -split_size */
int Xorriso_option_split_size(struct XorrisO *xorriso, char *size, int flag)
{
 double num;

 num= Scanf_io_size(size, 0);
 if(num > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
   sprintf(xorriso->info_text, "-split_size: too large %.f (allowed: %.f)",
           num, (double) xorriso->file_size_limit);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 } else if(num < 0)
   num= 0.0;
 xorriso->split_size= num;
 return(1);
}


/* Option -status */
int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode,"short")==0)
   Xorriso_status(xorriso,NULL,NULL,1);
 else if(strcmp(mode,"long")==0)
   Xorriso_status(xorriso,NULL,NULL,0);
 else if(strcmp(mode,"long_history")==0)
   Xorriso_status(xorriso,NULL,NULL,8);
 else if(mode[0]=='-')
   Xorriso_status(xorriso,mode,NULL,8);
 else
   Xorriso_status(xorriso,NULL,NULL,1);
 return(1);
}


/* Option -status_history_max */
int Xorriso_option_status_history_max(struct XorrisO *xorriso, int num,
                                      int flag)
{
 if(num>=0 && num<1000000)
   xorriso->status_history_max= num;
 return(1);
}


/* Option -stdio_sync "on"|"off"|size */
int Xorriso_option_stdio_sync(struct XorrisO *xorriso, char *rythm, int flag)
{
 double num;

 if(strcmp(rythm, "default") == 0 || strcmp(rythm, "on") == 0)
   num= 0;
 if(strcmp(rythm, "off") == 0)
   num= -1;
 else
   num = Scanf_io_size(rythm, 0);
 if(num > 0)
   num /= 2048;
 if(num != -1 && num != 0 && (num < 32 || num > 512 * 1024)) {
     sprintf(xorriso->info_text,
             "-stdio_sync : Bad size. Acceptable are -1, 0, 32k ... 1g");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
     return(0);
 } else
   xorriso->stdio_sync= num;
 return(1);
}


/* Option -stream_recording */
int Xorriso_option_stream_recording(struct XorrisO *xorriso, char *mode,
                                    int flag)
{
 double num;

 if(strcmp(mode,"on")==0 || mode[0]==0)
   xorriso->do_stream_recording= 32;
 else if(strcmp(mode,"full")==0)
   xorriso->do_stream_recording= 1;
 else if(strcmp(mode,"data")==0)
   xorriso->do_stream_recording= 2;
 else if(mode[0] >= '0' && mode[0] <= '9') {
   num= Scanf_io_size(mode, 0);
   num/= 2048.0;
   if(num >= 16 && num <= 0x7FFFFFFF)
     xorriso->do_stream_recording= num;
   else
     xorriso->do_stream_recording= 0;
 } else
   xorriso->do_stream_recording= 0;
 return(1);
}


/* Option -system_id */
int Xorriso_option_system_id(struct XorrisO *xorriso, char *name, int flag)
{
  if(Xorriso_check_name_len(xorriso, name, (int) sizeof(xorriso->system_id),
                            "-system_id", 0) <= 0)
    return(0);
 strcpy(xorriso->system_id, name);
 Xorriso_set_change_pending(xorriso, 1);
 return(1);
}


/* Option -tell_media_space */
int Xorriso_option_tell_media_space(struct XorrisO *xorriso, int flag)
{
 int ret, free_space= 0, media_space= 0;

 ret= Xorriso_tell_media_space(xorriso, &media_space, &free_space, 0);
 if(ret<=0) {
   sprintf(xorriso->info_text, "Cannot -tell_media_space");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 if(free_space<0) {
   sprintf(xorriso->info_text,
           "Pending image size larger than free space on media");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 sprintf(xorriso->result_line, "Media space  : %ds\n", media_space);
 Xorriso_result(xorriso, 0);
 sprintf(xorriso->result_line, "After commit : %ds\n", free_space);
 Xorriso_result(xorriso, 0);
 return(1);
}


/* Option -temp_mem_limit */
int Xorriso_option_temp_mem_limit(struct XorrisO *xorriso, char *size,
                                  int flag)
{
 double num;

 num= Scanf_io_size(size, 0);
 if(num < 64.0 * 1024.0 || num > 1024.0 * 1024.0 * 1024.0) {
   sprintf(xorriso->info_text,
           "-temp_mem_limit: wrong size %.f (allowed: %.f - %.f)",
           num, 64.0 * 1024.0, 1024.0 * 1024.0 * 1024.0);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
   return(0);
 }
 xorriso->temp_mem_limit= num;
 return(1);
}


/* Option -toc */
int Xorriso_option_toc(struct XorrisO *xorriso, int flag)
{
 int ret, in_ret= 1000;

 if(strcmp(xorriso->indev,xorriso->outdev)==0)
   ret= Xorriso_toc(xorriso, 0);
 else {
   if(xorriso->indev[0]!=0)
     in_ret= Xorriso_toc(xorriso, 0);
   if(xorriso->indev[0]!=0 && xorriso->outdev[0]!=0) {
     strcpy(xorriso->result_line, "-------------: ---------------------------------------------------------------\n");
     Xorriso_result(xorriso,0);
   }
   ret= 1;
   if(xorriso->outdev[0]!=0)
     ret= Xorriso_toc(xorriso, 2);
   if(in_ret<ret)
     ret= in_ret;
 }
 return(ret);
}


/* Option -uid */
int Xorriso_option_uid(struct XorrisO *xorriso, char *uid, int flag)
{
 int ret;

 xorriso->do_global_uid= 0;
 if(uid[0]==0 || strcmp(uid,"-")==0)
   return(1);
 ret= Xorriso_convert_uidstring(xorriso, uid, &(xorriso->global_uid), 0);
 if(ret>0) 
   xorriso->do_global_uid= 1;
 return(ret);
}


/* Options -update and -update_r
   @param flag bit0= issue start and summary message
               bit1= do not reset pacifier, no final pacifier message
               bit2= do not issue pacifier messages at all
               bit3= recursive: -update_r
               bit4= do not establish and dispose xorriso->di_array
*/
int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path,
                          char *iso_path, int flag)
{
 int ret, mem_pci, zero= 0, result, uret, follow_links, do_register= 1;
 int not_in_iso= 0, not_on_disk= 0, made_di_array= 0;
 double mem_lut= 0.0, start_time;
 char *ipth, *argv[6], sfe[5*SfileadrL];
 char eff_origin[SfileadrL], eff_dest[SfileadrL];
 struct stat stbuf;

 start_time= Sfile_microtime(0);

 ipth= iso_path;
 if(ipth[0]==0)
   ipth= disk_path;
 if(disk_path[0]==0) {
   sprintf(xorriso->info_text, "-update: Empty disk_path given");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
   return(0);
 }

 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_origin,
                                 2|4|8);
 if(ret<=0)
   return(ret);
 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_dest, 2|8);
 if(ret<=0)
   return(ret);

 if(!(flag&2)) {
   Xorriso_pacifier_reset(xorriso, 0);
   mem_lut= xorriso->last_update_time;
 }
 mem_pci= xorriso->pacifier_interval;
 xorriso->pacifier_interval= 5.0;

 if(flag&1) {
   sprintf(xorriso->info_text, "Updating %s to",
           Text_shellsafe(eff_origin, sfe, 0));
   sprintf(xorriso->info_text+strlen(xorriso->info_text), " %s\n",
           Text_shellsafe(eff_dest, sfe, 0));
   Xorriso_info(xorriso,0);
 }
 if(xorriso->disk_excl_mode&8)
   ret= Xorriso_path_is_excluded(xorriso, eff_origin, 1);
 else
   ret= 0;
 if(ret!=0)
   goto report_outcome;

 if(!(xorriso->ino_behavior & 2)) {
   if(!(xorriso->di_array != NULL || (flag & 16))) {
     /* Create all-image node array sorted by isofs.di */
     made_di_array= 1;
     ret= Xorriso_make_di_array(xorriso, 0);
     if(ret <= 0)
       goto ex;
   }
   if(xorriso->di_array != NULL) {
     if(!(flag & 8)) {
       /* If directory with -update : do not register di_*_paths */
       ret= lstat(eff_origin, &stbuf);
       if(ret != -1)
         if(S_ISDIR(stbuf.st_mode))
           do_register= 0;
     }
     if(do_register) {
       ret= Xorriso_lst_new(&(xorriso->di_disk_paths), eff_origin,
                            xorriso->di_disk_paths, 1);
       if(ret <= 0)
         goto ex;
       ret= Xorriso_lst_new(&(xorriso->di_iso_paths), eff_dest,
                            xorriso->di_iso_paths, 1);
       if(ret <= 0)
         goto ex;
     }
   }
 }

 if(flag&8) {
   xorriso->find_compare_result= 1;
   ret= Xorriso_iso_lstat(xorriso, eff_dest, &stbuf, 0);
   if(ret >= 0) {
     argv[0]= eff_dest;
     argv[1]= "-exec";
     argv[2]= "update";
     argv[3]= eff_origin;
     zero= 0;
     ret= Xorriso_option_find(xorriso, 4, argv, &zero,
                      2 | (8 * !((xorriso->do_aaip & 96) == 96))); /* -findi */
   } else if(ret==-2) { /* severe error (e.g. lack of image) */
     ret= -1;
     goto report_outcome;
   } else {
     not_in_iso= 1;
     ret= 1;
   }
   if(ret>0) {
     ret= lstat(eff_origin, &stbuf);
     if(ret != -1) {
       argv[0]= eff_origin;
       argv[1]= "-exec";
       argv[2]= "add_missing";
       argv[3]= eff_dest;
       zero= 0;
       ret= Xorriso_option_find(xorriso, 4, argv, &zero, 1|2); /* -findx */
       if(ret>0 && !xorriso->do_follow_mount) {
         argv[0]= eff_origin;
         argv[1]= "-type";
         argv[2]= "m";
         argv[3]= "-exec";
         argv[4]= "empty_iso_dir";
         argv[5]= eff_dest;
         zero= 0;
         ret= Xorriso_option_find(xorriso, 6, argv, &zero, 1|2); /* -findx */
       }
       if(ret>0)
         ret= xorriso->find_compare_result;
       else
         ret= -1;
     } else {
       ret= xorriso->find_compare_result;
       not_on_disk= 1;
     }
   } else
     ret= -1;
   if(not_on_disk && not_in_iso) {
     sprintf(xorriso->info_text, "Missing on disk and in ISO: disk_path %s",
             Text_shellsafe(disk_path, sfe, 0));
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
     ret= -1;
   }
 } else {
   /* compare ctime too, no filename reporting, eventually silent */
   follow_links= (xorriso->do_follow_links || xorriso->do_follow_param) <<28;
   ret= Xorriso_compare_2_files(xorriso, eff_origin, eff_dest, "", &result,
                                2 | follow_links | ((flag&4)<<27) | (3<<30));
   if(ret==0) {
     uret= Xorriso_update_interpreter(xorriso, NULL, result, eff_origin,
                                      eff_dest, 0);
     if(uret<=0)
       ret= -1;
     if(uret==3)
       ret= -1;
   }
 }
 xorriso->pacifier_interval= mem_pci;
 if(mem_lut!=xorriso->last_update_time && !(flag&2))
   Xorriso_pacifier_callback(xorriso, "content bytes read",
                             xorriso->pacifier_count, 0, "", 1);
report_outcome:;
 if(ret>0) {
   sprintf(xorriso->info_text,
           "No file object needed update.");
 } else if(ret==0) {
   sprintf(xorriso->info_text, "Differences detected and updated.");
 } else {
   sprintf(xorriso->info_text,
           "Not ok. Comparison or update failed due to error.");
 }
 sprintf(xorriso->info_text+strlen(xorriso->info_text),
         " (runtime %.1f s)\n", Sfile_microtime(0)-start_time);
 if(flag&1)
   Xorriso_info(xorriso,0);

ex:;
 if(ret < 0)
   return(ret);
 return(1);
}


/* Option -use_readline */
int Xorriso_option_use_readline(struct XorrisO *xorriso, char *mode, int flag)
{
 if(strcmp(mode,"off")==0)
   xorriso->use_stdin= 1;
 else
   xorriso->use_stdin= 0;
 return(1);
}


/* Option -version */
int Xorriso_option_version(struct XorrisO *xorriso, int flag)
{
#ifdef Xorriso_GNU_xorrisO
 sprintf(xorriso->result_line, "GNU xorriso %s%s\n",
         Xorriso_program_versioN, Xorriso_program_patch_leveL);
#else
 sprintf(xorriso->result_line, "xorriso %s%s\n",
         Xorriso_program_versioN, Xorriso_program_patch_leveL);
#endif /* ! Xorriso_GNU_xorrisO */
 Xorriso_result(xorriso, 0);
 sprintf(xorriso->result_line,
"ISO 9660 Rock Ridge filesystem manipulator and CD/DVD/BD burn program\n");
 sprintf(xorriso->result_line+strlen(xorriso->result_line),
"Copyright (C) 2010, Thomas Schmitt <scdbackup@gmx.net>, libburnia project.\n");
 Xorriso_result(xorriso, 0);
 sprintf(xorriso->result_line,
         "xorriso version   :  %s%s\n",
         Xorriso_program_versioN, Xorriso_program_patch_leveL);
 sprintf(xorriso->result_line+strlen(xorriso->result_line),
         "Version timestamp :  %s\n",Xorriso_timestamP);
 sprintf(xorriso->result_line+strlen(xorriso->result_line),
         "Build timestamp   :  %s\n",Xorriso_build_timestamP);
 Xorriso_result(xorriso, 0);
 Xorriso_report_lib_versions(xorriso, 0);

#ifdef Xorriso_GNU_xorrisO
 sprintf(xorriso->result_line,
"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n");
 Xorriso_result(xorriso, 0);
 sprintf(xorriso->result_line,
"This is free software: you are free to change and redistribute it.\n");
 Xorriso_result(xorriso, 0);
#else
 sprintf(xorriso->result_line, "Provided under GNU GPL version 2 or later.\n");
 Xorriso_result(xorriso, 0);
#endif /* ! Xorriso_GNU_xorrisO */

 sprintf(xorriso->result_line,
"There is NO WARRANTY, to the extent permitted by law.\n");
 Xorriso_result(xorriso, 0);
 return(1);
}


/* Option -volid */
int Xorriso_option_volid(struct XorrisO *xorriso, char *volid, int flag)
{
 int warn_shell= 0, warn_ecma= 0, i, ret;
 static char shell_chars[]= {
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-+=:.,~@"};
 static char ecma_chars[]= {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};

 for(i=0; volid[i]!=0; i++) {
   if(strchr(shell_chars, volid[i])==NULL)
     warn_shell= 1;
   if(strchr(ecma_chars, volid[i])==NULL)
     warn_ecma= 1;
 }
 if(i>32) {
   sprintf(xorriso->info_text, "-volid: Text too long (%d > 32)", i);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 if(warn_shell) {
   sprintf(xorriso->info_text,
           "-volid text problematic as automatic mount point name");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 if(xorriso->do_joliet && strlen(volid)>16) {
   sprintf(xorriso->info_text,
           "-volid text is too long for Joliet (%d > 16)",(int) strlen(volid));
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 if(warn_ecma) {
   sprintf(xorriso->info_text,
          "-volid text does not comply to ISO 9660 / ECMA 119 rules");
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }
 strcpy(xorriso->volid, volid);
 ret= Xorriso_set_volid(xorriso, volid, 0);
 if(ret<=0)
   return(ret);
 xorriso->volid_default= (strcmp(xorriso->volid, "ISOIMAGE")==0 ||
                          xorriso->volid[0]==0);
 return(1);
}


/* Option -volset_id */
int Xorriso_option_volset_id(struct XorrisO *xorriso, char *name, int flag)
{
  if(Xorriso_check_name_len(xorriso, name, (int) sizeof(xorriso->volset_id),
                            "-volset_id", 0) <= 0)
    return(0);
 strcpy(xorriso->volset_id, name);
 Xorriso_set_change_pending(xorriso, 1);
 return(1);
}


/* Option -xattr "on"|"off" */
int Xorriso_option_xattr(struct XorrisO *xorriso, char *mode, int flag)
{
 int ret;

 if(strcmp(mode, "off")==0)
   xorriso->do_aaip&= ~12;
 else if(strcmp(mode, "on")==0)
   xorriso->do_aaip|= (4 | 8);
 else {
   sprintf(xorriso->info_text, "-xattr: unknown mode '%s'", mode);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   return(0);
 }
 ret= Xorriso_set_ignore_aclea(xorriso, 0);
 if(ret <= 0)
   return(ret);
 return(1);
}


/* Option -zisofs */
int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag)
{
 int was_level, was_blocksize, ret, l;
 double num;
 char *cpt, *npt, text[16];

 was_level= xorriso->zlib_level;
 was_blocksize= xorriso->zisofs_block_size;
 npt= cpt= mode;
 for(cpt= mode; npt!=NULL; cpt= npt+1) {
   npt= strchr(cpt,':');
   if(npt==NULL)
     l= strlen(cpt);
   else
     l= npt-cpt;
   if(l==0)
     goto unknown_mode;

   if(strncmp(cpt, "level=", 6) == 0) {
     sscanf(cpt + 6, "%lf", &num);
     if(num < 0 || num > 9) {
       sprintf(xorriso->info_text,
               "-zisofs: Wrong zlib compression level '%s' (allowed 0...9)",
               cpt + 6);
       goto sorry_ex;
     }
     xorriso->zlib_level= num;

   } else if(strncmp(cpt, "ziso_used=", 10) == 0 ||
             strncmp(cpt, "osiz_used=", 10) == 0) {
     /* (ignored info from -status) */;

   } else if(strncmp(cpt, "block_size=", 11)==0) {
     num= 0.0;
     if(l > 11 && l < 27) {
       strncpy(text, cpt + 11, l - 11);
       text[l - 11]= 0;
       num= Scanf_io_size(text, 0);
     }
     if (num != (1 << 15) && num != (1 << 16) && num != (1 << 17)) {
       sprintf(xorriso->info_text,
               "-zisofs: Unsupported block size (allowed 32k, 64k, 128k)");
       goto sorry_ex;
     }
     xorriso->zisofs_block_size= num;

   } else if(strncmp(cpt, "by_magic=", 8)==0) {
     if(strncmp(cpt + 9, "on", l - 9) == 0)
       xorriso->zisofs_by_magic= 1;
     else
       xorriso->zisofs_by_magic= 0;

   } else if(strncmp(cpt, "default", l)==0) {
     xorriso->zlib_level= xorriso->zlib_level_default;
     xorriso->zisofs_block_size= xorriso->zisofs_block_size_default;
     xorriso->zisofs_by_magic= 0;

   } else {
unknown_mode:;
     if(l<SfileadrL)
       sprintf(xorriso->info_text, "-zisofs: unknown mode '%s'", cpt);
     else
       sprintf(xorriso->info_text, "-zisofs: oversized mode parameter (%d)",l);
sorry_ex:
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     xorriso->zlib_level= was_level;
     xorriso->zisofs_block_size= was_blocksize;
     return(0);
   }
 }
 ret= Xorriso_set_zisofs_params(xorriso, 0);
 return(ret);
}


/* ---------------------------- End Options API ------------------------ */


/* @return <0 error , >=0 number of skipped dashes
*/
int Xorriso_normalize_command(struct XorrisO *xorriso, char *original_cmd,
                              int argno, char *cmd_data, int sizeof_cmd_data,
                              char **cmd, int flag)
{
 int was_dashed= 0;
 char *dash_pt;

 if(strlen(original_cmd)>= sizeof_cmd_data) {
   if(argno>=0)
     sprintf(xorriso->info_text, "Oversized argument #%d (length %d)\n",
             argno, (int) strlen(original_cmd));
   else
     sprintf(xorriso->info_text, "Oversized option (length %d)\n",
             (int) strlen(original_cmd));
   return(-1);
 }
 strcpy(cmd_data, original_cmd);
 *cmd= cmd_data;
 if(strcmp(*cmd, xorriso->list_delimiter)==0)
   return(1);
 while((*cmd)[0]=='-') {
   if((*cmd)[1]==0)
 break;
   was_dashed++;
   (*cmd)++;
 }
 for(dash_pt= *cmd; *dash_pt!=0; dash_pt++)
   if(*dash_pt=='-')
     *dash_pt= '_';
 return(was_dashed);
}


/* @param flag bit0= do not warn of unknown option
   @return <=0 error,
           1=count is valid, 2=dashed unknown, 3=undashed unknown
*/
int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv,
                       int *count, int flag)
{
 int ret, was_dashed= 0, i;
 char *cmd, cmd_data[2*SfileadrL];
 static char arg0_commands[][40]= {
    "ban_stdio_write","close_filter_list","commit","devices","end",
    "for_backup", "help",
    "list_formats","no_rc","print_size","pvd_info","pwd","pwdi","pwdx",
    "rollback","rollback_end","tell_media_space","toc","version",
    ""
 };
 static char arg1_commands[][40]= {
    "abort_on","acl","add_plainly","application_id","auto_charset",
    "backslash_codes","blank",
    "calm_drive","cd","cdi","cdx","charset","close",
    "commit_eject","compliance",
    "dev","dialog","disk_dev_ino","disk_pattern","dummy","dvd_obs","eject",
    "iso_rr_pattern","follow","format","fs","gid","grow_blindly","hardlinks",
    "history","indev","in_charset","joliet",
    "list_delimiter","list_profiles","local_charset",
    "mark","md5","mount_opts","not_leaf","not_list","not_mgt",
    "options_from_file","osirrox","outdev","out_charset","overwrite",
    "pacifier","padding","path_list","pathspecs","pkt_output","print","prompt",
    "prog","prog_help","publisher","quoted_not_list","quoted_path_list",
    "reassure","report_about","rom_toc_scan","scsi_log",
    "session_log","speed","split_size","status","status_history_max",
    "stdio_sync","stream_recording","system_id","temp_mem_limit",
    "uid","unregister_filter","use_readline","volid","volset_id",
    "xattr","zisofs",
    ""
 };
 static char arg2_commands[][40]= {
    "assert_volid","boot_image","compare","compare_r","drive_class",
    "errfile_log","error_behavior","extract","extract_single",
    "load","logfile",
    "map","map_single","page","return_with",
    "scdbackup_tag","update","update_r",
    ""
 };
 static char arg4_commands[][40]= {
    "cut_out","extract_cut","mount","mount_cmd","paste_in","session_string",
    ""
 };
 static char argn_commands[][40]= {
    "add","alter_date","alter_date_r","as",
    "check_md5","check_md5_r","check_media","check_media_defaults",
    "chgrp","chgrpi","chgrp_r","chgrp_ri","chmod","chmodi",
    "chmod_r","chmod_ri","chown","chowni","chown_r","chown_ri",
    "compare_l","cpr","cpri","cp_rax","cp_rx","cpax","cpx",
    "du","dui","dus","dusi","dux","dusx","external_filter","extract_l",
    "file_size_limit","find","findi","finds","findx",
    "getfacl","getfacli","getfacl_r","getfacl_ri",
    "getfattr","getfattri","getfattr_r","getfattr_ri",
    "ls","lsi","lsl","lsli","lsd","lsdi","lsdl","lsdli",
    "lsx","lslx","lsdx","lsdlx","map_l","mv","mvi","mkdir","mkdiri",
    "not_paths","rm","rmi","rm_r","rm_ri","rmdir","rmdiri","update_l",
    "setfacl","setfacli","setfacl_list","setfacl_listi",
    "setfacl_r","setfacl_ri","setfattr","setfattri",
    "setfattr_list","setfattr_listi","setfattr_r","setfattr_ri",
    "set_filter","set_filter_r","show_stream","show_stream_r",
    ""
 };

 *count= 0;
 if(argc<=0)
   return(-1);
 ret= Xorriso_normalize_command(xorriso, argv[0], -1,
                                cmd_data, sizeof(cmd_data), &cmd, 0);
 if(ret<0)
   return(ret);
 was_dashed= (ret>0);
 if(cmd[0]=='#' || cmd[0]==0 || strcmp(cmd, xorriso->list_delimiter) == 0) {
   /* ignore: comment line , empty option , orphaned list delimiter */
   return(1);
 }
 for(i=0; arg0_commands[i][0]!=0; i++)
   if(strcmp(arg0_commands[i], cmd)==0)
     return(1);
 *count= 1;
 for(i=0; arg1_commands[i][0]!=0; i++)
   if(strcmp(arg1_commands[i], cmd)==0)
     return(1);
 *count= 2;
 for(i=0; arg2_commands[i][0]!=0; i++)
   if(strcmp(arg2_commands[i], cmd)==0)
     return(1);
 *count= 4;
 for(i=0; arg4_commands[i][0]!=0; i++)
   if(strcmp(arg4_commands[i], cmd)==0)
     return(1);
 *count= 0;
 for(i=0; argn_commands[i][0]!=0; i++)
   if(strcmp(argn_commands[i], cmd)==0) {
     ret= Xorriso_end_idx(xorriso, argc, argv, 1, 1);
     if(ret<1)
       return(ret);
     *count= ret-1;
     return(1);
   }

 if(!(flag&1)) {
   sprintf(xorriso->info_text, "Unknown option : '%s'", argv[0]);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 }

 return(2+!was_dashed);
}


/* @param flag bit0= recursion
               bit1= these are command line arguments
                     (for xorriso->argument_emulation)
*/
int Xorriso_interpreter(struct XorrisO *xorriso,
                        int argc, char **argv, int *idx, int flag)
/*
return:
 <=0 error , 1 = success , 2 = problem event ignored , 3 = end program run
*/
{
 int ret, was_dashed, end_ret, num1, num2;
 char *cmd, *original_cmd, cmd_data[2*SfileadrL], *arg1, *arg2;
 
 if(xorriso==NULL)
   return(0);
 if(xorriso->is_dialog) {
   xorriso->result_line_counter= xorriso->result_page_counter= 0;
   if(xorriso->result_page_length<0)
     xorriso->result_page_length= -xorriso->result_page_length;
 }

next_command:;
 if(flag&2) {
   ret= 1;
   if(xorriso->argument_emulation==1)
     ret= Xorriso_as_genisofs(xorriso, argc, argv, idx, 0);
   else if(xorriso->argument_emulation==2)
     ret= Xorriso_as_cdrskin(xorriso, argc, argv, idx, 0);
   if(xorriso->argument_emulation>0) {
     xorriso->argument_emulation= 0;
     if(ret<=0)
       goto eval_any_problems;
     if((*idx)>=argc)
       {ret= 1; goto ex;}
   }
 }

 xorriso->prepended_wd= 0;
 xorriso->request_to_abort= xorriso->request_not_to_ask= 0;
 Xorriso_set_problem_status(xorriso, "", 0);
 if((*idx)<argc)
   original_cmd= cmd= argv[*idx];
 else
   original_cmd= cmd= "";
 if(xorriso->add_plainly==3 && cmd[0] && !xorriso->is_dialog) {
   (*idx)++;
   goto add_plain_argument;
 }
 was_dashed= 0;

 ret= Xorriso_normalize_command(xorriso, original_cmd, -1,
                                cmd_data, sizeof(cmd_data), &cmd, 0);
 if(ret<0)
   goto eval_any_problems;
 was_dashed= ret;

 (*idx)++;
 if((*idx)<argc)
   arg1= argv[(*idx)];
 else
   arg1= "";
 if((*idx)+1<argc)
   arg2= argv[(*idx)+1];
 else
   arg2= "";

 ret= 1;
 if(cmd[0]=='#' || cmd[0]==0) {
   /* ignore comment line and empty option */; 

 } else if(strcmp(cmd,"abort_on")==0) {
   (*idx)++;
   ret= Xorriso_option_abort_on(xorriso, arg1, 0);

 } else if(strcmp(cmd,"acl")==0) {
   (*idx)++;
   ret= Xorriso_option_acl(xorriso, arg1, 0);

 } else if(strcmp(cmd,"add")==0) {
   ret= Xorriso_option_add(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"add_plainly")==0) {
   (*idx)++;
   ret= Xorriso_option_add_plainly(xorriso, arg1, 0);

 } else if(strcmp(cmd,"alter_date")==0 || strcmp(cmd,"alter_date_r")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_alter_date(xorriso, arg1, arg2, argc, argv, idx,
                                  strlen(cmd)>10);

 } else if(strcmp(cmd,"application_id")==0) {
   (*idx)++;
   ret= Xorriso_option_application_id(xorriso, arg1, 0);

 } else if(strcmp(cmd,"as")==0) {
   ret= Xorriso_option_as(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"assert_volid")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_assert_volid(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"auto_charset")==0) {
   (*idx)++;
   ret= Xorriso_option_auto_charset(xorriso, arg1, 0);

 } else if(strcmp(cmd,"backslash_codes")==0) {
   (*idx)++;
   ret= Xorriso_option_backslash_codes(xorriso, arg1, 0);

 } else if(strcmp(cmd,"ban_stdio_write")==0) {
   ret= Xorriso_option_ban_stdio_write(xorriso, 0);

 } else if(strcmp(cmd,"blank")==0) {
   (*idx)++;
   ret= Xorriso_option_blank(xorriso, arg1, 0);

 } else if(strcmp(cmd,"boot_image")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_boot_image(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"calm_drive")==0) {
   (*idx)++;
   ret= Xorriso_option_calm_drive(xorriso, arg1, 0);

 } else if(strcmp(cmd,"cd")==0 || strcmp(cmd,"cdi")==0) {
   (*idx)++;
   ret= Xorriso_option_cdi(xorriso, arg1, 0);

 } else if(strcmp(cmd,"cdx")==0) {
   (*idx)++;
   ret= Xorriso_option_cdx(xorriso, arg1, 0);

 } else if(strcmp(cmd,"charset")==0) {
   (*idx)++;
   ret= Xorriso_option_charset(xorriso, arg1, 3);

 } else if(strcmp(cmd,"check_md5")==0) {
   ret= Xorriso_option_check_md5(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"check_md5_r")==0) {
   ret= Xorriso_option_check_md5(xorriso, argc, argv, idx, 8);

 } else if(strcmp(cmd,"check_media")==0) {
   ret= Xorriso_option_check_media(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"check_media_defaults")==0) {
   ret= Xorriso_option_check_media_defaults(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"chgrp")==0 || strcmp(cmd,"chgrpi")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chgrpi(xorriso, arg1, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"chgrp_r")==0 || strcmp(cmd,"chgrp_ri")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chgrpi(xorriso, arg1, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"chmod")==0 || strcmp(cmd,"chmodi")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chmodi(xorriso, arg1, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"chmod_r")==0 || strcmp(cmd,"chmod_ri")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chmodi(xorriso, arg1, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"chown_r")==0 || strcmp(cmd,"chown_ri")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chowni(xorriso, arg1, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"chown")==0 || strcmp(cmd,"chowni")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_chowni(xorriso, arg1, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"close")==0) {
   (*idx)++;
   ret= Xorriso_option_close(xorriso, arg1, 0);

 } else if(strcmp(cmd,"close_filter_list")==0) {
   ret= Xorriso_option_close_filter_list(xorriso, 0);

 } else if(strcmp(cmd,"commit")==0) {
   ret= Xorriso_option_commit(xorriso, 0);

 } else if(strcmp(cmd,"commit_eject")==0) {
   (*idx)++;
   ret= Xorriso_option_commit_eject(xorriso, arg1, 0);

 } else if(strcmp(cmd,"compare")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_compare(xorriso, arg1, arg2, 1);

 } else if(strcmp(cmd,"compare_l")==0) {
   ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 1<<8);

 } else if(strcmp(cmd,"compare_r")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_compare(xorriso, arg1, arg2, 1|8);

 } else if(strcmp(cmd,"compliance")==0) {
   (*idx)++;
   Xorriso_option_compliance(xorriso, arg1, 0);

 } else if(strcmp(cmd,"cpr")==0 || strcmp(cmd,"cpri")==0) {
   ret= Xorriso_option_cpri(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"cp_rx")==0 || strcmp(cmd,"cp_rax")==0) {
   ret= Xorriso_option_cpx(xorriso, argc, argv, idx,
                           1|((strcmp(cmd,"cp_rax")==0)<<1));

 } else if(strcmp(cmd,"cpx")==0 || strcmp(cmd,"cpax")==0) {
   ret= Xorriso_option_cpx(xorriso, argc, argv, idx,
                           (strcmp(cmd,"cpax")==0)<<1);

 } else if(strcmp(cmd,"cut_out")==0) {
   (*idx)+= 4;
   if((*idx)>argc) {
     sprintf(xorriso->info_text,
            "-cut_out: Not enough arguments. Needed are: disk_path start count so_rr_path");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0;
   } else
     ret= Xorriso_option_cut_out(xorriso, arg1, arg2,
                                 argv[(*idx)-2], argv[(*idx)-1], 0);

 } else if(strcmp(cmd,"dev")==0) {
   (*idx)++;
   ret= Xorriso_option_dev(xorriso, arg1, 3);

 } else if(strcmp(cmd,"devices")==0) {
   ret= Xorriso_option_devices(xorriso, 0);

 } else if(strcmp(cmd,"dialog")==0) {
   (*idx)++;
   ret= Xorriso_option_dialog(xorriso, arg1, 0);

 } else if(strcmp(cmd,"disk_dev_ino")==0) {
   (*idx)++;
   ret= Xorriso_option_disk_dev_ino(xorriso, arg1, 0);

 } else if(strcmp(cmd,"disk_pattern")==0) {
   (*idx)++;
   ret= Xorriso_option_disk_pattern(xorriso, arg1, 0);

 } else if(strcmp(cmd,"drive_class")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_drive_class(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"du")==0   || strcmp(cmd,"dui")==0 ||
           strcmp(cmd,"dus")==0 || strcmp(cmd,"dusi")==0) {
   ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[2]!='s')|4);

 } else if(strcmp(cmd,"dummy")==0) {
   (*idx)++;
   ret= Xorriso_option_dummy(xorriso, arg1, 0);

 } else if(strcmp(cmd,"dvd_obs")==0) {
   (*idx)++;
   ret= Xorriso_option_dvd_obs(xorriso, arg1, 0);

 } else if(strcmp(cmd,"dux")==0 || strcmp(cmd,"dusx")==0) {
   ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[2]!='s')|4);

 } else if(strcmp(cmd,"eject")==0) {
   (*idx)++;
   ret= Xorriso_option_eject(xorriso, arg1, 0);

 } else if(strcmp(cmd,"end")==0) {
   end_ret= Xorriso_option_end(xorriso, 0);
   ret= Xorriso_eval_problem_status(xorriso, ret, 0);
   if(ret<0)
     return(ret);
   if(end_ret!=2)
     {ret= 3; goto ex;}

 } else if(strcmp(cmd,"errfile_log")==0) {
   (*idx)+= 2;
    ret= Xorriso_option_errfile_log(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"error_behavior")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_error_behavior(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"external_filter")==0) {
   ret= Xorriso_option_external_filter(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"extract")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_extract(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"extract_cut")==0) {
   (*idx)+= 4;
   if((*idx)>argc) {
     sprintf(xorriso->info_text,
            "-extract_cut: Not enough arguments. Needed are: disk_path start count so_rr_path");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0;
   } else
     ret= Xorriso_option_extract_cut(xorriso, arg1, arg2,
                                     argv[(*idx)-2], argv[(*idx)-1], 0);

 } else if(strcmp(cmd,"extract_l")==0) {
   ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 3<<8);

 } else if(strcmp(cmd,"extract_single")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_extract(xorriso, arg1, arg2, 32);

 } else if(strcmp(cmd,"file_size_limit")==0) {
   ret= Xorriso_option_file_size_limit(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"find")==0 || strcmp(cmd,"findi")==0) {
   ret= Xorriso_option_find(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"findx")==0) {
   ret= Xorriso_option_find(xorriso, argc, argv, idx, 1);

 } else if(strcmp(cmd,"follow")==0) {
   (*idx)++;
   ret= Xorriso_option_follow(xorriso, arg1, 0);

 } else if(strcmp(cmd,"for_backup")==0) {
   Xorriso_option_hardlinks(xorriso, "on", 0);
   Xorriso_option_acl(xorriso, "on", 0);
   Xorriso_option_xattr(xorriso, "on", 0);
   Xorriso_option_md5(xorriso, "on", 0);
   ret= 1;

 } else if(strcmp(cmd,"format")==0) {
   (*idx)++;
   ret= Xorriso_option_blank(xorriso, arg1, 1);

 } else if(strcmp(cmd,"fs")==0) {
   (*idx)++;
   ret= Xorriso_option_fs(xorriso, arg1, 0);

 } else if(strcmp(cmd,"getfacl")==0 || strcmp(cmd,"getfacli")==0) {
   ret= Xorriso_option_getfacli(xorriso, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"getfacl_r")==0 || strcmp(cmd,"getfacl_ri")==0) {
   ret= Xorriso_option_getfacli(xorriso, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"getfattr")==0 || strcmp(cmd,"getfattri")==0) {
   ret= Xorriso_option_getfacli(xorriso, argc, argv, idx, 2);   

 } else if(strcmp(cmd,"getfattr_r")==0 || strcmp(cmd,"getfattr_ri")==0) {
   ret= Xorriso_option_getfacli(xorriso, argc, argv, idx, 1 | 2);   

 } else if(strcmp(cmd,"gid")==0) {
   (*idx)++;
   ret= Xorriso_option_gid(xorriso,arg1,0);

 } else if(strcmp(cmd,"grow_blindly")==0) {
   (*idx)++;
   ret= Xorriso_option_grow_blindly(xorriso,arg1,0);

 } else if(strcmp(cmd,"hardlinks")==0) {
   (*idx)++;
   ret= Xorriso_option_hardlinks(xorriso, arg1, 0);

 } else if(strcmp(cmd,"help")==0) {
   Xorriso_option_help(xorriso,0);

 } else if(strcmp(cmd,"history")==0) {
   /* add to readline history */
   (*idx)++;
   ret= Xorriso_option_history(xorriso, arg1, 0);

 } else if(strcmp(cmd,"indev")==0) {
   (*idx)++;
   ret= Xorriso_option_dev(xorriso, arg1, 1);

 } else if(strcmp(cmd,"in_charset")==0) {
   (*idx)++;
   ret= Xorriso_option_charset(xorriso, arg1, 1);

 } else if(strcmp(cmd,"iso_rr_pattern")==0) {
   (*idx)++;
   ret= Xorriso_option_iso_rr_pattern(xorriso, arg1, 0);

 } else if(strcmp(cmd,"joliet")==0) {
   (*idx)++;
   ret= Xorriso_option_joliet(xorriso, arg1, 0);

 } else if(strcmp(cmd, "list_delimiter") == 0) {
   (*idx)++;
   ret= Xorriso_option_list_delimiter(xorriso, arg1, 0);

 } else if(strcmp(cmd,"list_formats")==0) {
   ret= Xorriso_option_list_formats(xorriso, 0);

 } else if(strcmp(cmd,"list_profiles")==0) {
   (*idx)++;
   ret= Xorriso_option_list_profiles(xorriso, arg1, 0);

 } else if(strcmp(cmd,"load")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_load(xorriso, arg1, arg2, 0);
   
 } else if(strcmp(cmd,"local_charset")==0) {
   (*idx)++;
   ret= Xorriso_option_charset(xorriso, arg1, 4);

 } else if(strcmp(cmd,"logfile")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_logfile(xorriso, arg1, arg2, 0);
   
 } else if(strcmp(cmd,"ls")==0 || strcmp(cmd,"lsi")==0 ||
           strcmp(cmd,"lsl")==0 || strcmp(cmd,"lsli")==0) {
   ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[2]=='l'));

 } else if(strcmp(cmd,"lsd")==0 || strcmp(cmd,"lsdi")==0 ||
           strcmp(cmd,"lsdl")==0 || strcmp(cmd,"lsdli")==0) {
   ret= Xorriso_option_lsi(xorriso, argc, argv, idx, (cmd[3]=='l')|8);

 } else if(strcmp(cmd,"lsdx")==0 || strcmp(cmd,"lsdlx")==0) {
   ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[3]=='l')|8);

 } else if(strcmp(cmd,"lsx")==0 || strcmp(cmd,"lslx")==0) {
   ret= Xorriso_option_lsx(xorriso, argc, argv, idx, (cmd[2]=='l'));

 } else if(strcmp(cmd,"map")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_map(xorriso, arg1, arg2, 0);

 } else if(strcmp(cmd,"map_l")==0) {
   ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"map_single")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_map(xorriso, arg1, arg2, 32);

 } else if(strcmp(cmd,"mark")==0) {
   (*idx)++;
   ret= Xorriso_option_mark(xorriso, arg1, 0);

 } else if(strcmp(cmd, "md5")==0) {
   (*idx)++;
   ret= Xorriso_option_md5(xorriso, arg1, 0);

 } else if(strcmp(cmd, "mount") == 0 || strcmp(cmd, "mount_cmd") == 0) {
   (*idx)+= 4;
   if((*idx)>argc) {
     sprintf(xorriso->info_text,
         "-%s: Not enough arguments. Needed are: device entity id command",
         cmd);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0;
   } else
     ret= Xorriso_option_mount(xorriso, arg1, arg2,
                               argv[(*idx)-2], argv[(*idx)-1],
                               (strcmp(cmd, "mount_cmd") == 0));

 } else if(strcmp(cmd, "mount_opts")==0) {
   (*idx)++;
   ret= Xorriso_option_mount_opts(xorriso, arg1, 0);

 } else if(strcmp(cmd,"mv")==0 || strcmp(cmd,"mvi")==0) {
   ret= Xorriso_option_mvi(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"mkdir")==0 || strcmp(cmd,"mkdiri")==0) {
   ret= Xorriso_option_mkdiri(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"no_rc")==0) {
   ret= Xorriso_option_no_rc(xorriso, 0);

 } else if(strcmp(cmd,"not_leaf")==0) {
   (*idx)++;
   ret= Xorriso_option_not_leaf(xorriso, arg1, 0);

 } else if(strcmp(cmd,"not_list")==0) {
   (*idx)++;
   ret= Xorriso_option_not_list(xorriso, arg1, 0);

 } else if(strcmp(cmd,"not_mgt")==0) {
   (*idx)++;
   ret= Xorriso_option_not_mgt(xorriso, arg1, 0);

 } else if(strcmp(cmd,"not_paths")==0) {
   ret= Xorriso_option_not_paths(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"options_from_file")==0) {
   (*idx)++;
   ret= Xorriso_option_options_from_file(xorriso,arg1,0);
   if(ret==3)
     goto ex;

 } else if(strcmp(cmd,"osirrox")==0) {
   (*idx)++;
   ret= Xorriso_option_osirrox(xorriso,arg1,0);

 } else if(strcmp(cmd,"outdev")==0) {
   (*idx)++;
   ret= Xorriso_option_dev(xorriso, arg1, 2);

 } else if(strcmp(cmd,"out_charset")==0) {
   (*idx)++;
   ret= Xorriso_option_charset(xorriso, arg1, 2);

 } else if(strcmp(cmd,"overwrite")==0) {
   (*idx)++;
   ret= Xorriso_option_overwrite(xorriso,arg1,0);

 } else if(strcmp(cmd,"pacifier")==0) {
   (*idx)++;
   ret= Xorriso_option_pacifier(xorriso, arg1, 0);

 } else if(strcmp(cmd,"padding")==0) {
   (*idx)++;
   ret= Xorriso_option_padding(xorriso, arg1, 0);

 } else if(strcmp(cmd,"page")==0) {
   (*idx)+= 2;
   num1= num2= 0;
   sscanf(arg1,"%d",&num1);
   sscanf(arg2,"%d",&num2);
   if(num1<0)
     num1= 0;
   if(arg1[0]==0)
     num1= 16;
   if(num2<=0)
     num2= 80;
   ret= Xorriso_option_page(xorriso, num1, num2, 0);

 } else if(strcmp(cmd,"paste_in")==0) {
   (*idx)+= 4;
   if((*idx)>argc) {
     sprintf(xorriso->info_text,
            "-paste_in: Not enough arguments. Needed are: disk_path start count so_rr_path");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0;
   } else
     ret= Xorriso_option_paste_in(xorriso, arg1, arg2,
                                 argv[(*idx)-2], argv[(*idx)-1], 0);

 } else if(strcmp(cmd,"path-list")==0 || strcmp(cmd,"path_list")==0) {
   (*idx)++;
   ret= Xorriso_option_path_list(xorriso, arg1, 0);

 } else if(strcmp(cmd,"pathspecs")==0) {
   (*idx)++;
   ret= Xorriso_option_pathspecs(xorriso, arg1, 0);

 } else if(strcmp(cmd,"pkt_output")==0) {
   (*idx)++;
   ret=  Xorriso_option_pkt_output(xorriso, arg1, 0);

 } else if(strcmp(cmd,"print")==0) {
   (*idx)++;
   ret= Xorriso_option_print(xorriso, arg1, 0);

 } else if(strcmp(cmd,"print_size")==0) {
   Xorriso_option_print_size(xorriso, 0);

 } else if(strcmp(cmd,"prompt")==0) {
   (*idx)++;
   ret= Xorriso_option_prompt(xorriso, arg1, 0);

 } else if(strcmp(cmd,"prog")==0) {
   (*idx)++;
   ret= Xorriso_option_prog(xorriso, arg1, 0);

 } else if(strcmp(cmd,"publisher")==0) { 
   (*idx)++;
   Xorriso_option_publisher(xorriso, arg1, 0);

 } else if(strcmp(cmd,"pvd_info")==0) { 
   Xorriso_option_pvd_info(xorriso, 0);

 } else if(strcmp(cmd,"pwd")==0 || strcmp(cmd,"pwdi")==0) {
   Xorriso_option_pwdi(xorriso, 0);

 } else if(strcmp(cmd,"pwdx")==0) { 
   Xorriso_option_pwdx(xorriso, 0);

 } else if(strcmp(cmd,"quoted_not_list")==0) {
   (*idx)++;
   ret= Xorriso_option_not_list(xorriso, arg1, 1);

 } else if(strcmp(cmd,"quoted_path_list")==0) {
   (*idx)++;
   ret= Xorriso_option_path_list(xorriso, arg1, 1);

 } else if(strcmp(cmd,"reassure")==0) {
   (*idx)++;
   ret= Xorriso_option_reassure(xorriso, arg1, 0);

 } else if(strcmp(cmd,"report_about")==0) {
   (*idx)++;
   ret= Xorriso_option_report_about(xorriso, arg1, 0);

 } else if(strcmp(cmd,"return_with")==0) {
   (*idx)+= 2;
   num2= 0;
   sscanf(arg2,"%d",&num2);
   ret= Xorriso_option_return_with(xorriso, arg1, num2, 0);

 } else if(strcmp(cmd,"rm")==0 || strcmp(cmd,"rmi")==0) {
   ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 0);

 } else if(strcmp(cmd,"rm_r")==0 || strcmp(cmd,"rm_ri")==0) {
   ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 1);

 } else if(strcmp(cmd,"rmdir")==0 || strcmp(cmd,"rmdiri")==0) {
   ret= Xorriso_option_rmi(xorriso, argc, argv, idx, 2);

 } else if(strcmp(cmd,"rollback")==0) {
   ret= Xorriso_option_rollback(xorriso, 0);

 } else if(strcmp(cmd,"rollback_end")==0) {
   end_ret= Xorriso_option_end(xorriso, 1);
   ret= Xorriso_eval_problem_status(xorriso, ret, 0);
   if(ret<0)
     return(ret);
   if(end_ret!=2)
     {ret= 3; goto ex;}

 } else if(strcmp(cmd,"rom_toc_scan")==0) {
   (*idx)++;
   Xorriso_option_rom_toc_scan(xorriso, arg1, 0);

 } else if(strcmp(cmd,"scdbackup_tag")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_scdbackup_tag(xorriso, arg1, arg2, 0);
 
 } else if(strcmp(cmd, "scsi_log") == 0) {
   (*idx)++;
   ret= Xorriso_option_scsi_log(xorriso, arg1, 0);

 } else if(strcmp(cmd,"session_log")==0) {
   (*idx)++;
   ret= Xorriso_option_session_log(xorriso, arg1, 0);
 
 } else if(strcmp(cmd, "session_string") == 0) {
   (*idx)+= 4;
   if((*idx)>argc) {
     sprintf(xorriso->info_text,
         "-%s: Not enough arguments. Needed are: device entity id command",
         cmd);
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
     ret= 0;
   } else
     ret= Xorriso_option_mount(xorriso, arg1, arg2,
                               argv[(*idx)-2], argv[(*idx)-1], 2);

 } else if(strcmp(cmd,"setfacl")==0 || strcmp(cmd,"setfacli")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_setfacli(xorriso, arg1, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"setfacl_list")==0 || strcmp(cmd,"setfacl_listi")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_setfacl_listi(xorriso, arg1, 0);   

 } else if(strcmp(cmd,"setfacl_r")==0 || strcmp(cmd,"setfacl_ri")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_setfacli(xorriso, arg1, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"setfattr")==0 || strcmp(cmd,"setfattri")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_setfattri(xorriso, arg1, arg2, argc, argv, idx, 0);   

 } else if(strcmp(cmd,"setfattr_list")==0 || strcmp(cmd,"setfattr_listi")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_setfattr_listi(xorriso, arg1, 0);   

 } else if(strcmp(cmd,"setfattr_r")==0 || strcmp(cmd,"setfattr_ri")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_setfattri(xorriso, arg1, arg2, argc, argv, idx, 1);   

 } else if(strcmp(cmd,"set_filter")==0 || strcmp(cmd,"set_filter_r")==0) {
   (*idx)+= 1;
   ret= Xorriso_option_set_filter(xorriso, arg1, argc, argv, idx,
                                  strcmp(cmd,"set_filter_r")==0);

 } else if(strcmp(cmd,"show_stream")==0 || strcmp(cmd,"show_stream_r")==0) {
   ret= Xorriso_option_set_filter(xorriso, "", argc, argv, idx,
                                  (strcmp(cmd,"show_stream_r")==0) | 2 | 4);

 } else if(strcmp(cmd,"speed")==0) {
   (*idx)++;
   ret= Xorriso_option_speed(xorriso, arg1, 0);

 } else if(strcmp(cmd,"split_size")==0) {
   (*idx)++;
   ret= Xorriso_option_split_size(xorriso, arg1, 0);

 } else if(strcmp(cmd,"status")==0) {
   (*idx)++;
   ret= Xorriso_option_status(xorriso, arg1, 0);

 } else if(strcmp(cmd,"status_history_max")==0) {
   (*idx)++;
   sscanf(arg1,"%d",&num1);
   ret= Xorriso_option_status_history_max(xorriso, num1, 0);

 } else if(strcmp(cmd,"stdio_sync")==0) {
   (*idx)++;
   ret= Xorriso_option_stdio_sync(xorriso, arg1, 0);

 } else if(strcmp(cmd,"stream_recording")==0) {
   (*idx)++;
   ret= Xorriso_option_stream_recording(xorriso, arg1, 0);

 } else if(strcmp(cmd,"system_id")==0) {
   (*idx)++;
   ret= Xorriso_option_system_id(xorriso, arg1, 0);

 } else if(strcmp(cmd,"tell_media_space")==0) {
   Xorriso_option_tell_media_space(xorriso, 0);

 } else if(strcmp(cmd,"temp_mem_limit")==0) {
   (*idx)++;
   ret= Xorriso_option_temp_mem_limit(xorriso, arg1, 0);

 } else if(strcmp(cmd,"test")==0) { /* This option does not exist. */

   /* install temporary test code here */;

 } else if(strcmp(cmd,"toc")==0) {
   Xorriso_option_toc(xorriso, 0);

 } else if(strcmp(cmd,"uid")==0) {
   (*idx)++;
   ret= Xorriso_option_uid(xorriso,arg1,0);

 } else if(strcmp(cmd,"unregister_filter")==0) {
   (*idx)++;
   ret= Xorriso_option_unregister_filter(xorriso, arg1, 0);

 } else if(strcmp(cmd,"update")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_update(xorriso, arg1, arg2, 1);

 } else if(strcmp(cmd,"update_l")==0) {
   ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 2<<8);

 } else if(strcmp(cmd,"update_r")==0) {
   (*idx)+= 2;
   ret= Xorriso_option_update(xorriso, arg1, arg2, 1|8);

 } else if(strcmp(cmd,"use_readline")==0) {
   (*idx)++;
   ret= Xorriso_option_use_readline(xorriso, arg1, 0);

 } else if(strcmp(cmd,"version")==0){
   ret= Xorriso_option_version(xorriso, 0);

 } else if(strcmp(cmd,"volset_id")==0) {
   (*idx)++;
   ret= Xorriso_option_volset_id(xorriso, arg1, 0);

 } else if(strcmp(cmd,"volid")==0) {
   (*idx)++;
   ret= Xorriso_option_volid(xorriso,arg1,0);

 } else if(strcmp(cmd,"xattr")==0) {
   (*idx)++;
   ret= Xorriso_option_xattr(xorriso, arg1, 0);

 } else if(strcmp(cmd,"zisofs")==0) {
   (*idx)++;
   ret= Xorriso_option_zisofs(xorriso, arg1, 0);

 } else if(strcmp(cmd, xorriso->list_delimiter)==0){
   /* tis ok */;

 } else if(was_dashed) {
   if(xorriso->add_plainly>1)
     goto add_plain_argument;
unknown_option:;
   sprintf(xorriso->info_text, "Not a known option:  '%s'\n",
           original_cmd);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   {ret= 0; goto eval_any_problems;}

 } else {
   if(xorriso->add_plainly<=0)
     goto unknown_option;
add_plain_argument:;
   (*idx)--;
   ret= Xorriso_option_add(xorriso, (*idx)+1, argv, idx, 0);
   (*idx)++;

 }

eval_any_problems:
 ret= Xorriso_eval_problem_status(xorriso, ret, 0);
 if(ret<0)
   return(ret);

 if(*idx<argc)
   goto next_command;

ex:;
 if((!xorriso->is_dialog) && !(flag&1))
   Xorriso_mark(xorriso,0);
 fflush(stdout);
 return(ret);
}


int Xorriso_execute_option(struct XorrisO *xorriso, char *line, int flag)
/*
 bit0-bit15 are forwarded to Xorriso_interpreter
 
 bit16= no pageing of info lines
 bit17= print === bar even if xorriso->found<0
*/
{
 int ret,argc= 0, idx= 1;
 char **argv= NULL;
 double tdiff;
 struct timeval tv;
 struct timezone tz;

 gettimeofday(&tv,&tz);
 Xorriso_reset_counters(xorriso,0);
 xorriso->idle_time= 0.0;
 tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec);

 /* parse line into args */
 ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv,
                      4 | ((xorriso->bsl_interpretation & 3) << 5));
 if(ret < 0) {
   Xorriso_msgs_submit(xorriso, 0,
      "Severe lack of resources during command line parsing", 0, "FATAL", 0);
   goto ex;
 }
 if(ret == 0) {
   sprintf(xorriso->info_text, "Incomplete quotation in command line: %s",
           line);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   goto ex;
 }
 if(argc<2)
   {ret= 1; goto ex;}
 if(argv[1][0]=='#')
   {ret= 1; goto ex;}

 ret= Xorriso_interpreter(xorriso, argc, argv, &idx, flag&0xffff);
 if(ret<0)
   goto ex;
 gettimeofday(&tv,&tz);
 tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec)-tdiff-xorriso->idle_time;
 if(tdiff<0.001)
   tdiff= 0.001;
 if(xorriso->error_count>0) {
   sprintf(xorriso->info_text,
           "----------------------------- %7.f errors encountered\n",
           xorriso->error_count);
   Xorriso_info(xorriso,!(flag&(1<<16)));
 }

 /* ??? >>> print elapsed time  tdiff ? */;

 if((flag&(1<<17)) && !xorriso->bar_is_fresh) {
   sprintf(xorriso->info_text,"============================\n");
   Xorriso_info(xorriso,0);
   xorriso->bar_is_fresh= 1;
 }
 Xorriso_reset_counters(xorriso,0);
ex:;
 Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */
 return(ret);
}


int Xorriso_dialog(struct XorrisO *xorriso, int flag)
{
 int ret,first_round;
 char line[2*SfileadrL];

 if(!xorriso->dialog)
   return(1);
 xorriso->is_dialog= 1;
 for(first_round= 1;1;first_round= 0) {
   if(xorriso->pending_option[0]!=0) {
     Xorriso_mark(xorriso,0);
     strcpy(line,xorriso->pending_option);
     xorriso->pending_option[0]= 0;
   } else {
     if(!xorriso->bar_is_fresh) {
       sprintf(xorriso->info_text,"============================\n");
       Xorriso_info(xorriso,0);
       xorriso->bar_is_fresh= 1;
     }
     sprintf(xorriso->info_text,"enter option and arguments :\n");
     Xorriso_info(xorriso,0);
     Xorriso_mark(xorriso,0);
     ret= Xorriso_dialog_input(xorriso,line,sizeof(line),4);
     if(ret<=0)
 break;
   }
   sprintf(xorriso->info_text,
           "==============================================================\n");
   Xorriso_info(xorriso,0);

   ret= Xorriso_execute_option(xorriso,line,1<<17);
   if(ret<0)
     goto ex;
   if(ret==3)
     goto ex;
   xorriso->did_something_useful= 1;
   xorriso->no_volset_present= 0; /* Re-enable "No ISO image present." */
 }
 ret= 1;
ex:;
 xorriso->is_dialog= 0;
 return(ret);
}


int Xorriso_change_is_pending(struct XorrisO *xorriso, int flag)
{
 return(!!xorriso->volset_change_pending);
}


int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag)
{
 if(xorriso->dev_fd_1>=0)
   return(2);
 xorriso->dev_fd_1= dup(1);
 close(1);
 dup2(2,1);
 return(1);
}


int Xorriso_prescan_args(struct XorrisO *xorriso, int argc, char **argv,
                         int flag)
/*
 bit0= do not interpret argv[1]
*/
/*
 return:
  <0  error
   0  end program
   1  ok, go on
*/
{
 int i, ret, was_dashed, num2, arg_count;
 int was_report_about= 0, was_abort_on= 0, was_return_with= 0;
 char *cmd, *original_cmd, cmd_data[5*SfileadrL], *arg1, *arg2;
 char mem_list_delimiter[81];

 strcpy(mem_list_delimiter, xorriso->list_delimiter);
 for(i=1+(flag&1);i<argc;i++) {
   original_cmd= cmd= argv[i];
   was_dashed= 0;

   was_dashed= Xorriso_normalize_command(xorriso, original_cmd, i,
                                         cmd_data, sizeof(cmd_data), &cmd, 0);
   if(was_dashed<0)
     {ret= -1; goto ex;}

   arg1= "";
   if(i+1<argc)
     arg1= argv[i+1];
   arg2= "";
   if(i+2<argc)
     arg2= argv[2+1];
   if(i>1)
     xorriso->did_something_useful= 1;
   if(i==1 && argc==2) {
     if(strcmp(cmd,"prog_help")==0) {
       i++;
       Xorriso_option_prog_help(xorriso,arg1,0);
       xorriso->did_something_useful= 1;
       {ret= 0; goto ex;}
     } else if(strcmp(cmd,"help")==0) {
       if(xorriso->argument_emulation == 1) {
         Xorriso_genisofs_help(xorriso, 0);
       } else if(xorriso->argument_emulation == 2) {
         Xorriso_cdrskin_help(xorriso, 0);
       } else {
         Xorriso_option_help(xorriso,0);
       }
       xorriso->did_something_useful= 1;
       {ret= 0; goto ex;}
     }
   } else if(i==1 && strcmp(cmd,"no_rc")==0) {
     ret= Xorriso_option_no_rc(xorriso, 0);
     if(ret<=0)
       goto ex;

   } else if((strcmp(cmd,"dev")==0 || strcmp(cmd,"outdev")==0 ||
                                      strcmp(cmd,"indev")==0) &&
             (strcmp(arg1,"stdio:/dev/fd/1")==0 || strcmp(arg1,"-")==0) &&
             xorriso->dev_fd_1<0) {
     /* Detach fd 1 from externally perceived stdout and attach it to stderr.
        Keep dev_fd_1 connected to external stdout. dev_fd_1 is to be used when
        "stdio:/dev/fd/1" is interpreted as drive address.
     */
protect_stdout:;
     Xorriso_protect_stdout(xorriso, 0);
     sprintf(xorriso->info_text,
             "Encountered  -  or  stdio:/dev/fd/1  as possible write target.");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     sprintf(xorriso->info_text,
             "Redirecting nearly all text message output to stderr.");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
     sprintf(xorriso->info_text, "Disabling use of libreadline.");
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);

   } else if(strcmp(cmd,"abort_on")==0 && was_dashed == 1) {
     i++;
     if(!was_abort_on)
       Xorriso_option_abort_on(xorriso, arg1, 0);
     was_abort_on= 1;

   } else if(strcmp(cmd,"report_about")==0 && was_dashed == 1) {
     i++;
     if(!was_report_about)
       Xorriso_option_report_about(xorriso, arg1, 0);
     was_report_about= 1;

   } else if(strcmp(cmd,"return_with")==0 && was_dashed == 1) {
     i+= 2;
     num2= 0;
     sscanf(arg2,"%d",&num2);
     if(!was_return_with)
       Xorriso_option_return_with(xorriso, arg1, num2, 0);
     was_return_with= 1;

   } else if(strcmp(cmd,"as")==0 && was_dashed == 1) {
     if(strcmp(arg1, "mkisofs")==0 || strcmp(arg1, "genisoimage")==0 ||
        strcmp(arg1, "genisofs")==0 || strcmp(arg1, "xorrisofs")==0)
       goto protect_stdout;

   } else if(strcmp(cmd, "list_delimiter") == 0) {
     /* Needed for interpreting other args. Gets reset after prescan. */
     i++;
     ret= Xorriso_option_list_delimiter(xorriso, arg1, 0);
     if(ret <= 0)
       goto ex;

   } else if(strcmp(cmd, "scsi_log") == 0 && was_dashed == 1) {
     i++;
     Xorriso_option_scsi_log(xorriso, arg1, 0);

   } else {
     ret= Xorriso_count_args(xorriso, argc-i, argv+i, &arg_count, 1);
     if(ret==1)
       i+= arg_count;
   }
 }
 ret= 1;
ex:;
 strcpy(xorriso->list_delimiter, mem_list_delimiter);
 return(ret);
}


int Xorriso_read_rc(struct XorrisO *xorriso, int flag)
{
 int ret,i,was_failure= 0,fret;

 if(xorriso->no_rc)
   return(1);
 i= xorriso->rc_filename_count-1;
 Sfile_home_adr_s(".xorrisorc", xorriso->rc_filenames[i],
                  sizeof(xorriso->rc_filenames[i]),0);
 for(i=0;i<xorriso->rc_filename_count;i++) {
   ret= Sfile_type(xorriso->rc_filenames[i],1|8);
   if(ret!=1)
 continue;
   ret= Xorriso_option_options_from_file(xorriso,xorriso->rc_filenames[i],0);
   if(ret>1)
     return(ret);
   if(ret==1)
 continue; /* regular bottom of loop */
   was_failure= 1;
   fret= Xorriso_eval_problem_status(xorriso, ret, 1);
   if(fret>=0)
 continue;
   return(ret);
 }
 return(!was_failure);
}


int Xorriso_make_return_value(struct XorrisO *xorriso, int flag)
{
 int exit_value= 0;

 if(xorriso->eternal_problem_status >= xorriso->return_with_severity)
   exit_value= xorriso->return_with_value;
 if(exit_value) {
   sprintf(xorriso->info_text,
          "-return_with %s %d triggered by problem severity %s",
          xorriso->return_with_text, exit_value,
          xorriso->eternal_problem_status_text);
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 }
 return(exit_value);
}


int Xorriso_program_arg_bsl(struct XorrisO *xorriso, int argc, char ***argv,
                            int flag)
{
 int ret;

 if(!(xorriso->bsl_interpretation & 16))
   return(1);
 ret= Sfile_argv_bsl(argc, argv, 0);
 return(ret);
}


char *Xorriso__get_version_text(int flag)
{
 return(Xorriso_program_versioN);
}


char *Xorriso__get_patch_level_text(int flag)
{
 return(Xorriso_program_patch_leveL);
}



#endif /* ! Xorriso_without_subS */



#ifdef Xorriso_with_maiN


#ifdef Xorriso_without_subS

/* xorriso consists only of a main() stub which has an own version to match
   the version of libxorriso header and runtime code.
*/
#define Xorriso_main_program_versioN "0.5.0"

#else /* Xorriso_without_subS */

/* Make sure that both version tests always match. */
#define Xorriso_main_program_versioN Xorriso_program_versioN

#endif /* ! Xorriso_without_subS */


static void yell_xorriso()
{
 fprintf(stderr,
   "%sxorriso %s%s : RockRidge filesystem manipulator, libburnia project.\n\n",
#ifdef Xorriso_GNU_xorrisO
        "GNU ",
#else
        "",
#endif
        Xorriso_main_program_versioN, Xorriso_program_patch_leveL);
}


int main(int argc, char **argv)
{
 int ret, i;
 struct XorrisO *xorriso= NULL;
 char **orig_argv= NULL;

 if(strcmp(Xorriso_main_program_versioN, Xorriso_program_versioN)) {
   yell_xorriso();
   fprintf(stderr,
    "xorriso : FATAL : libxorriso compile time version mismatch. Found %s\n\n",
           Xorriso_program_versioN);
   exit(4);
 }
 if(strcmp(Xorriso_program_versioN, Xorriso__get_version_text(0))) {
   yell_xorriso();
   fprintf(stderr,
         "xorriso : FATAL : libxorriso runtime version mismatch. Found %s\n\n",
         Xorriso__get_version_text(0));
   exit(4);
 }

 if(argc < 2) {
   yell_xorriso();
   fprintf(stderr,"usage : %s [options]\n", argv[0]);
   fprintf(stderr, "        More is told by option -help\n");
   exit(2);
 }
 setlocale(LC_CTYPE, "");
 ret= Xorriso_new(&xorriso, argv[0], 0);
 if(ret <= 0) {
   fprintf(stderr,"Creation of XorrisO object failed. (not enough memory ?)\n");
   exit(3);
 }

 /* The prescan of arguments performs actions which have to happen before
    the normal processing of startup files and arguments.
 */
 ret= Xorriso_prescan_args(xorriso,argc,argv,0);
 if(ret == 0)
   goto end_sucessfully;
 if(ret < 0)
   exit(5);

 yell_xorriso();

 /* The following functions are allowed only after this initialization */
 ret= Xorriso_startup_libraries(xorriso, 0);
 if(ret <= 0)
   {ret= 4; goto emergency_exit;}
 Xorriso_process_msg_queues(xorriso, 0);

 /* Interpret startup files */
 ret= Xorriso_read_rc(xorriso, 0);
 if(ret == 3)
   goto end_sucessfully;
 if(ret <= 0)
   {ret= 5; goto emergency_exit;}

 /* Interpret program arguments */
 orig_argv= argv;
 ret= Xorriso_program_arg_bsl(xorriso, argc, &argv, 0); 
 if(ret <= 0)
   {ret= 5; goto emergency_exit;}
 i= 1;
 ret= Xorriso_interpreter(xorriso, argc, argv, &i, 2);
 if(ret == 3)
   goto end_sucessfully;
 if(ret <= 0)
   {ret= 5; goto emergency_exit;}

 /* Enter dialog mode if it has been activated meanwhile */
 ret= Xorriso_dialog(xorriso, 0);
 if(ret <= 0)
   {ret= 6; goto emergency_exit;}

end_sucessfully:; /* normal shutdown, including eventual -commit */
 Xorriso_process_msg_queues(xorriso, 0);
 if(Xorriso_change_is_pending(xorriso, 0))
   Xorriso_option_end(xorriso, 2);
 Xorriso_process_msg_queues(xorriso, 0);
 ret= Xorriso_make_return_value(xorriso, 0);
 Xorriso_process_errfile(xorriso, 0, "xorriso end", 0, 1);
 Xorriso_destroy(&xorriso, 1);
 if(orig_argv != argv && orig_argv != NULL) {
   for(i= 0; i < argc; i++)
     if(argv[i] != NULL)
       free(argv[i]);
   free(argv);
 }
 exit(ret);

emergency_exit:;
 if(xorriso != NULL) { /* minimal shutdown */
   Xorriso_process_msg_queues(xorriso, 0);
   Xorriso_destroy(&xorriso, 1);
 }
 exit(ret);
}

#endif /* Xorriso_with_maiN */


