libisoburn/test/xorriso.c

8934 lines
235 KiB
C

/*
( cd .. ; libisoburn-develop/test/compile_xorriso.sh -g )
or
cc -g -DXorriso_with_maiN -DXorriso_with_regeX -DXorriso_with_readlinE \
-DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \
-Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
-o test/xorriso \
test/xorriso.c test/xorrisoburn.c \
-lpthread -lreadline -lburn -lisofs -lisoburn
or
cc -g -DXorriso_with_regeX -DXorriso_with_readlinE \
-DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \
-Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
-c \
test/xorriso.c test/xorrisoburn.c
*/
/* Command line oriented batch and dialog tool which creates, loads,
manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2008 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, with the announcement that this might
get changed in future. I would prefer BSD or a modified LGPL with no
option to choose any kind of future GPL version.
(This announcement affects only future releases of xorriso.
If you obtain a copy licensed as "GPL version 2" then this license is
not revocable for that particular copy, of course.)
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.
*/
#define PROG_VERSION "0.1.0"
/** The source code release timestamp */
#include "xorriso_timestamp.h"
#ifndef Xorriso_timestamP
#define Xorriso_timestamP "-none-given-"
#endif
/** The binary build timestamp is to be set externally by the compiler */
#ifndef Xorriso_build_timestamP
#define Xorriso_build_timestamP "-none-given-"
#endif
#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>
/* 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 isofs- and burn-library interface */
#include "xorrisoburn.h"
/* The inner description of XorrisO */
#define Xorriso_is_xorriso_selF 1
#include "xorriso_private.h"
/* ------------------------------------------------------------------------ */
#ifndef Xorriso_sfile_externaL
char *Sfile_fgets(char *line, int maxl, FILE *fp)
{
int l;
char *ret;
ret= fgets(line,maxl,fp);
if(ret==NULL)
return(NULL);
l= strlen(line);
if(l>0) if(line[l-1]=='\r') line[--l]= 0;
if(l>0) if(line[l-1]=='\n') line[--l]= 0;
if(l>0) if(line[l-1]=='\r') line[--l]= 0;
return(ret);
}
int Sfile_fclose(FILE *fp)
{
if(fp!=stdout && fp!=stdin && fp!=NULL)
fclose(fp);
return(1);
}
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, "SORRY", 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);
}
int Sfile_lookup_permissions(char *fname, int *perms, mode_t *st_mode,int flag)
/* @param perms bit0= r , bit1= w , bit2= x */
/* return: <0 fatal error, 0= file nonexistent, 1=owner, 2=group, 3=other */
{
struct stat stbuf;
int is_root;
*perms= 0;
if(stat(fname,&stbuf)==-1)
return(0);
*st_mode= stbuf.st_mode;
is_root= (geteuid()==0);
if(is_root) /* root can always read and write */
*perms= 3;
if(is_root || geteuid()==stbuf.st_uid) {
if(stbuf.st_mode & S_IRUSR)
(*perms)|= 1;
if(stbuf.st_mode & S_IWUSR)
(*perms)|= 2;
if(stbuf.st_mode & S_IXUSR)
(*perms)|= 4;
if(!is_root)
return(1);
}
/* group membership is a complicated thing */
if(is_root || Sfile_being_group_member(&stbuf,0)>0) {
if(stbuf.st_mode & S_IRGRP)
(*perms)|= 1;
if(stbuf.st_mode & S_IWGRP)
(*perms)|= 2;
if(stbuf.st_mode & S_IXGRP)
(*perms)|= 4;
if(!is_root)
return(2);
}
if(stbuf.st_mode & S_IROTH)
(*perms)|= 1;
if(stbuf.st_mode & S_IWOTH)
(*perms)|= 2;
if(stbuf.st_mode & S_IXOTH)
(*perms)|= 4;
if(is_root)
return(1);
return(3);
}
int Sfile_select(int *fds, int fdcount, int fdidx[3], unsigned int microsec,
int flag)
/*
bit0= check for reading (and choose one into fdidx[0])
bit1= check for writing (and choose one into fdidx[1])
bit2= check for exception (and choose one into fdidx[2])
bit3= initialize fdidx
return-bits are set according to matching flag-bits
*/
{
struct timeval wt;
fd_set rds,wts,exs,*s;
int ready,ret,i,j,max_fd= -1;
if(flag&8)
for(j=0;j<3;j++)
fdidx[j]= 0;
wt.tv_sec= microsec/1000000;
wt.tv_usec= microsec%1000000;
FD_ZERO(&rds);
FD_ZERO(&wts);
FD_ZERO(&exs);
for(i= 0;i<fdcount;i++) {
if(fds[i]<0)
continue;
if(flag&1)
FD_SET(fds[i],&rds);
if(flag&2)
FD_SET(fds[i],&wts);
if(flag&4)
FD_SET(fds[i],&exs);
if(fds[i]>max_fd)
max_fd= fds[i];
}
ready= select(max_fd+1,&rds,&wts,&exs,&wt);
if(ready<=0)
return(0);
ret= 0;
if(fdcount>0)
for(j=0;j<2;j++)
fdidx[j]= (fdidx[j]+1)%fdcount;
for(i= 0;i<fdcount;i++) {
for(j=0;j<3;j++) {
if(j==0)
s= &rds;
else if(j==1)
s= &wts;
else
s= &exs;
if((flag&(1<<j)) && !(ret&(1<<j))) {
if(fds[fdidx[j]]<0)
fdidx[j]= (fdidx[j]+1)%fdcount;
else if(FD_ISSET(fds[fdidx[j]],s))
ret|= (1<<j);
else
fdidx[j]= (fdidx[j]+1)%fdcount;
}
}
}
return(ret);
}
int Sfile_identical(char *file1, char *file2, int flag)
/*
bit0= check whether it is the same i-node
*/
{
FILE *fp1,*fp2;
struct stat stbuf;
int ret,c1,c2;
ino_t ino1,ino2;
dev_t dev1,dev2;
ret= 0;
if(flag&1){
if(stat(file1,&stbuf)==-1) return(0);
ino1= stbuf.st_ino;
dev1= stbuf.st_dev;
if(stat(file2,&stbuf)==-1) return(0);
ino2= stbuf.st_ino;
dev2= stbuf.st_dev;
return((ino1==ino2) && (dev1==dev2));
}
fp1= fopen(file1,"rb");
fp2= fopen(file2,"rb");
if(fp1==NULL||fp2==NULL) goto fertig;
while(1){
c1= fgetc(fp1);
c2= fgetc(fp2);
if(c1==EOF && c2==EOF){
ret= 1;
break;
}
if(c1!=c2)
break;
}
fertig:;
if(fp1!=NULL) fclose(fp1);
if(fp2!=NULL) fclose(fp2);
return(ret);
}
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[6],form[80];
int i,dec_siz= 0,avail_siz= 1;
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);
}
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
*/
{
int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc;
char *cpt,*start;
char buf[SfileadrL];
Sfile_destroy_argv(argc,argv,0);
if(flag&2) return(1);
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) {strncat(buf,start,l);buf[bufl+l]= 0;}
l= strlen(buf);
start= cpt+1;
while(*(++cpt)!=0) if(*cpt=='"') break;
if((flag&4) && *cpt==0)
return(0);
l= cpt-start; bufl= strlen(buf);
if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;}
start= cpt+1;
}else if(*cpt=='\''){
l= cpt-start; bufl= strlen(buf);
if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;}
l= strlen(buf);
start= cpt+1;
while(*(++cpt)!=0) if(*cpt=='\'') break;
if((flag&4) && *cpt==0)
return(0);
l= cpt-start; bufl= strlen(buf);
if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;}
start= cpt+1;
}
if(*cpt==0) break;
}
l= cpt-start;
bufl= strlen(buf);
if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;}
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){
*argc= argzaehl;
if(argzaehl>0) {
*argv= (char **) Smem_malloC(argzaehl*sizeof(char *));
if(*argv==NULL)
return(-1);
}
for(i=0;i<*argc;i++) {
(*argv)[i]= (char *) Smem_malloC((maxl+1));
if((*argv)[i]==NULL)
return(-1);
}
}
}
return(1);
}
/* @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 Write_to_channel(char *text, int channel_no, int flag)
/*
bit0= packet write disabled, write to stdin resp. stderr
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,ret= 1;
char prefix[16];
static int num_channels= 4;
static char channel_prefixes[4][4]= {".","R","I","M"};
static FILE *logfile_fp[4]= {NULL,NULL,NULL,NULL};
static FILE *pktlog_fp= NULL;
if(channel_no<0 || channel_no>=num_channels)
return(-1);
/* Logfiles */
if((flag&2) && logfile_fp[channel_no]!=NULL) {
fprintf(logfile_fp[channel_no],
"! 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[channel_no]);
logfile_fp[channel_no]= 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);
pktlog_fp= NULL;
}
if(flag&(1<<15))
return(1);
if((flag&2)) {
logfile_fp[channel_no]= fopen(text,"a");
if(logfile_fp[channel_no]==NULL)
return(0);
fprintf(logfile_fp[channel_no],
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : %s : %s\n",
channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256));
fflush(logfile_fp[channel_no]);
}
if((flag&4)) {
pktlog_fp= fopen(text,"a");
if(pktlog_fp==NULL)
return(0);
fprintf(pktlog_fp,
"I:1:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : . : %s\n",
Sfile_datestr(time(0),1|2|256));
fflush(pktlog_fp);
}
if(flag&(2|4))
return(1);
if(flag&1) {
if(channel_no==1 || channel_no==3)
printf("%s",text);
if(channel_no==2 || channel_no==3)
fprintf(stderr,"%s",text);
if(logfile_fp[channel_no]!=NULL) {
fprintf(logfile_fp[channel_no],"%s",text);
fflush(logfile_fp[channel_no]);
}
if(pktlog_fp!=NULL)
return(1);
}
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(!(flag&1)) {
ret= fwrite(prefix,5,1,stdout);
if(ret<=0)
return(0);
}
if(pktlog_fp!=NULL) {
ret= fwrite(prefix,5,1,pktlog_fp);
if(ret<=0)
return(0);
}
if(npt==NULL) {
if(!(flag&1)) {
ret= fwrite(rpt,strlen(rpt),1,stdout);
if(ret<=0)
return(0);
ret= fwrite("\n",1,1,stdout);
if(ret<=0)
return(0);
}
if(pktlog_fp!=NULL) {
ret= fwrite(rpt,strlen(rpt),1,pktlog_fp);
if(ret<=0)
return(0);
ret= fwrite("\n",1,1,pktlog_fp);
if(ret<=0)
return(0);
}
break;
} else {
if(!(flag&1)) {
ret= fwrite(rpt,npt+1-rpt,1,stdout);
if(ret<=0)
return(0);
}
if(pktlog_fp!=NULL) {
ret= fwrite(rpt,npt+1-rpt,1,pktlog_fp);
if(ret<=0)
return(0);
}
}
rpt= npt+1;
}
if(!(flag&1))
fflush(stdout);
if(pktlog_fp!=NULL)
fflush(pktlog_fp);
return(1);
}
int Exec_cmd(char *prog, char *cmd, char *simple_arg, char **argv,
char errmsg[SfileadrL], int flag)
/*
bit0= package mode (!bit0 of Write_to_channel())
*/
{
int wait_status,is_dead= 0,pipes_open= 0,ret,channel_no;
int stdout_pipe[2],stderr_pipe[2],fds[2],fdidx[3];
char **exec_argv,*simple_argv[3],buffer[256];
pid_t pid,dead_pid;
static int debug= 0;
errmsg[0]= 0;
if(debug)
fprintf(stderr,"Exec_cmd():fork\n");
/* create pipes */
if(pipe(stdout_pipe)==-1) {
cannot_make_pipe:;
sprintf(errmsg,"%s : cannot create two pipes\n reason given: %s\n",
prog,strerror(errno));
return(-1);
}
if(pipe(stderr_pipe)==-1) {
close(stdout_pipe[0]);
close(stdout_pipe[1]);
goto cannot_make_pipe;
}
pipes_open= 1;
pid= fork();
if(pid==-1) {
sprintf(errmsg,"%s : cannot fork a new process\n reason given: %s\n",
prog,strerror(errno));
{ret= -1; goto father_ex;}
} else if(pid>0) { /* original process */
if(debug)
fprintf(stderr,"Exec_cmd():father\n");
/* close unused pipe ends so we register EOF by the child process */
close(stdout_pipe[1]);
close(stderr_pipe[1]);
fds[0]= stdout_pipe[0];
fds[1]= stderr_pipe[0];
is_dead= 0;
while(1) {
if((fds[0]==-1 && fds[1]==-1)) { /* not before both pipes have closed */
dead_pid= wait3(&wait_status,WNOHANG,NULL);
if(dead_pid==pid) {
is_dead= 1;
break;
} else if(dead_pid<0) {
sprintf(errmsg,
"%s : error while waiting for end of sub process\n %s\n",
prog,strerror(errno));
{ret= -1; goto father_ex;}
}
}
/* check for input at both pipes */;
ret= Sfile_select(fds,2,fdidx,100000,1|8);
if(ret<=0 || fdidx[0]<0 || fdidx[0]>1)
continue;
ret= read(fds[fdidx[0]],buffer,sizeof(buffer)-3);
if(ret<0) {
sprintf(errmsg,"--- error %d on read from %s pipe : %s\n",
errno,(fdidx[0]?"stdout":"stderr"),
(errno>0?strerror(errno):"-unknown error-"));
{ret= -1; goto father_ex;}
}
if(ret==0) {
fds[fdidx[0]]= -1;
continue;
}
buffer[ret]= 0;
channel_no= fdidx[0]+1;
ret= Write_to_channel(buffer,channel_no,!(flag&1));
if(ret<=0) {
sprintf(errmsg,"--- error %d on write to %s : %s\n",
errno,(fdidx[0]?"stdout":"stderr"),
(errno>0?strerror(errno):"-unknown error-"));
{ret= -1; goto father_ex;}
}
}
ret= 127;
if(WIFEXITED(wait_status))
ret= WEXITSTATUS(wait_status);
father_ex:;
if(pipes_open) {
close(stdout_pipe[0]);
close(stderr_pipe[0]);
}
return(ret);
}
if(debug)
fprintf(stderr,"Exec_cmd():child\n");
/* Connect stdout and stderr to the appropriate ends of the pipes. */
close(1);
ret= dup(stdout_pipe[1]);
if(ret==-1) {
cannot_dup_pipe:;
sprintf(errmsg,
"%s : cannot redirect standard i/o to pipes\n reason given: %s\n",
prog,strerror(errno));
Write_to_channel(errmsg,2,!(flag&1));
exit(1);
}
close(2);
ret= dup(stderr_pipe[1]);
if(ret==-1)
goto cannot_dup_pipe;
/* close pipes so we register EOF by the father process */
close(stdout_pipe[0]);
close(stdout_pipe[1]);
close(stderr_pipe[0]);
close(stderr_pipe[1]);
/* switch process to desired program */
if(simple_arg!=NULL) {
simple_argv[0]= cmd;
simple_argv[1]= simple_arg;
simple_argv[2]= NULL;
exec_argv= simple_argv;
} else {
exec_argv= argv;
}
if(debug) { int i;
fprintf(stderr,"debug: cmd='%s'\n",cmd);
for(i=0;exec_argv[i]!=NULL;i++)
fprintf(stderr,"debug: argv[%d]='%s'\n",i,exec_argv[i]);
}
if(strchr(cmd,'/')!=NULL)
execv(cmd,exec_argv);
else
execvp(cmd,exec_argv);
sprintf(errmsg,"%s : cannot start program %s\n reason given: %s\n",
prog,cmd,strerror(errno));
Write_to_channel(errmsg,2,!(flag&1));
exit(127);
}
int Exec_cmd_line(char *prog, char *cmd_line,
int extra_argc, char **extra_argv, char *errmsg, int flag)
/*
bit0= packade mode (!bit0 of Write_to_channel())
*/
{
int ret,cmd_argc= 0,i,w;
char **cmd_argv= NULL,**argv= NULL;
ret= Sfile_make_argv("",cmd_line,&cmd_argc,&cmd_argv,1);
if(ret<=0)
{ret= -1; goto ex;}
argv= TSOB_FELD(char *,cmd_argc+extra_argc+1);
if(argv==NULL)
{ret= -1; goto ex;}
w= 0;
for(i=0;i<cmd_argc;i++)
argv[w++]= cmd_argv[i];
for(i=0;i<extra_argc;i++)
argv[w++]= extra_argv[i];
argv[w]= NULL;
ret= Exec_cmd(prog,argv[0],NULL,argv,errmsg,flag&1);
ex:;
if(argv!=NULL)
free((char *) argv);
Sfile_make_argv("",cmd_line,&cmd_argc,&cmd_argv,2);
return(ret);
}
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);
}
int Set_bit(int *data, int idx, int flag)
/*
bit0= clear bit
*/
{
if(idx<0 || idx>31)
return(0);
if(flag&1)
(*data)&= ~(1<<idx);
else
(*data)|= (1<<idx);
return(1);
}
FILE *Afile_fopen(char *filename, char *mode, int flag)
/*
bit0= do not print error message on failure
bit6= write packeted error messages (see Write_to_channel())
*/
{
FILE *fp= NULL;
char errmsg[2*SfileadrL];
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
fp= stdin;
} else if(strncmp(filename,"tcp:",4)==0){
sprintf(errmsg,"sorry - TCP/IP service isn't implemented yet.\n");
Write_to_channel(errmsg,2,!(flag&64));
} else if(strncmp(filename,"file:",5)==0){
fp= fopen(filename+5,mode);
} else {
fp= fopen(filename,mode);
}
if(fp==NULL){
if(!(flag&1)) {
sprintf(errmsg,"failed to open file '%s' in %s mode\n",filename,mode);
if(errno>0)
sprintf(errmsg+strlen(errmsg)," %s\n",strerror(errno));
Write_to_channel(errmsg,2,!(flag&64));
}
return(NULL);
}
return(fp);
}
/** 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]=='='){
if(code[1]==0)
return(0);
if(!isdigit(code[1]))
return(0);
value= -1;
if(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);
}
/* ------------------------------------------------------------------------ */
#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);
}
/*
from Juergen Helbing's yencode-c.txt
found at www.yenc.org , Feb 4, 2002
license : "It is public domain - as well as the yEnc specification"
some alterations made to adapt it to Sregex_crc32()
seems to be compatible with SFV/CSV files
*/
int Sregex_crc32_yenc(char *data, int len, unsigned long *crc, int flag)
/*
bit0= start of data polynom
*/
{
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
static unsigned long crc_tab[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
int k;
unsigned long crc_val,ch1,ch2,cc;
if(flag&1)
crc_val = ~0;
else
crc_val = ~*crc;
for(k=0;k<len;k++) {
cc= data[k] & 0xffL;
ch1= (crc_val ^ cc) & 0xffL;
ch1= crc_tab[ch1];
ch2= (crc_val>>8L) & 0xffffffL;
crc_val= ch1 ^ ch2;
}
*crc= ~crc_val;
return(1);
}
#endif /* Xorriso_sregex_externaL */
#ifndef Xorriso_text_shellsafe_externaL
char *Text_shellsafe(char *in_text, char *out_text, int flag)
{
int l,i,w=0;
/* 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)
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);
}
#endif /* ! Xorriso_text_shellsafe_externaL */
#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);
}
int Fileliste__unescape_target(char *line, char *endpt, char sep, int flag)
{
char *wpt,*rpt;
if(endpt==NULL)
endpt= line+strlen(line);
/* unescape sep and '\\' */
wpt= line;
for(rpt= line; rpt<endpt; rpt++) {
if(*rpt=='\\') {
if(*(rpt+1)==sep || *(rpt+1)=='\\')
rpt++;
}
*(wpt++)= *rpt;
}
*wpt= 0;
return(1);
}
int Fileliste__escape_target(char *target, int flag)
{
int i,offset= 0;
/* escape '=' and '\\' in target address */
for(i= strlen(target)-1;i>=0;i--)
if(target[i]=='=' || target[i]=='\\')
offset++;
target[strlen(target)+offset]= 0;
for(i= strlen(target)-1;i>=0;i--) {
if(target[i]=='=' || target[i]=='\\') {
target[i+offset]= target[i];
offset--;
target[i+offset]= '\\';
} else {
target[i+offset]= target[i];
}
}
return(1);
}
#endif /* ! Xorriso_fileliste_externaL */
#define Xorriso_cleanup_externaL 1
#ifndef Xorriso_cleanup_externaL
/* <<< ??? ts A71006 : will this be replaced by the libburn signal handler ? */
#include <signal.h>
typedef void (*sighandler_t)(int);
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 24;
/* Signals not to be caught */
static int non_signal_list[]= {
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
};
static int non_signal_list_count= 5;
/* run time dynamic part */
static char cleanup_msg[SfileadrL]= {""};
static int cleanup_exiting= 0;
static void *cleanup_app_handle= NULL;
static Cleanup_app_handler_T cleanup_app_handler= NULL;
static int cleanup_perform_app_handler_first= 0;
static int Cleanup_handler_exit(int exit_value, int signum, int flag)
{
int ret;
if(cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
if(ret==2)
return(2);
}
if(cleanup_exiting) {
if(cleanup_msg[0]!=0)
fprintf(stderr,"%s\n",cleanup_msg);
fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n",
getpid(),signum);
return(0);
}
cleanup_exiting= 1;
if(cleanup_msg[0]!=0)
fprintf(stderr,"%s\n",cleanup_msg);
alarm(0);
if(!cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL)
(*cleanup_app_handler)(cleanup_app_handle,signum,0);
exit(exit_value);
}
static void Cleanup_handler_generic(int signum)
{
int i;
sprintf(cleanup_msg,"UNIX-SIGNAL caught: %d errno= %d",signum,errno);
for(i= 0; i<signal_list_count; i++)
if(signum==signal_list[i]) {
sprintf(cleanup_msg,"UNIX-SIGNAL: %s errno= %d",
signal_name_list[i],errno);
break;
}
Cleanup_handler_exit(1,signum,0);
}
static int Cleanup_set_handlers(void *handle,
Cleanup_app_handler_T handler, int flag)
/*
bit0= set to default handlers
bit1= set to ignore
bit2= set cleanup_perform_app_handler_first
bit3= set SIGABRT to handler (makes sense with bits 0 or 1)
*/
{
int i,j,max_sig= -1,min_sig= 0x7fffffff;
sighandler_t sig_handler;
cleanup_msg[0]= 0;
cleanup_app_handle= handle;
cleanup_app_handler= handler;
if(flag&4)
cleanup_perform_app_handler_first= 1;
if(flag&1)
sig_handler= SIG_DFL;
else if(flag&2)
sig_handler= SIG_IGN;
else
sig_handler= Cleanup_handler_generic;
/* set all signal numbers between the lowest and highest in the list
except those in the non-signal list */
for(i= 0; i<signal_list_count; i++) {
if(signal_list[i]>max_sig)
max_sig= signal_list[i];
if(signal_list[i]<min_sig)
min_sig= signal_list[i];
}
for(i= min_sig; i<=max_sig; i++) {
for(j= 0; j<non_signal_list_count; j++)
if(i==non_signal_list[j])
break;
if(j>=non_signal_list_count) {
if(i==SIGABRT && (flag&8))
signal(i,Cleanup_handler_generic);
else
signal(i,sig_handler);
}
}
return(1);
}
#endif /* ! Xorriso_cleanup_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);
}
/* ------------------------------- TreeseQ -------------------------------- */
/* DirseQ : crawl along a filesystem subtree */
struct TreeseQ {
char adr[SfileadrL];
char path[SfileadrL];
struct DirseQ *dir_stack;
struct stat stbuf;
int follow_links;
int unused_yet;
};
int Treeseq_destroy(struct TreeseQ **o, int flag);
/* @param flag bit0= follow symbolic links */
int Treeseq_new(struct TreeseQ **o, char *adr, int flag)
{
int ret;
struct TreeseQ *m;
m= *o= TSOB_FELD(struct TreeseQ,1);
if(m==NULL)
return(-1);
m->adr[0]= 0;
m->path[0]= 0;
m->dir_stack= NULL;
m->follow_links= (flag&1);
m->unused_yet= 1;
if(Sfile_str(m->adr, adr, 0)<=0)
{ret= 0; goto failed;}
strcpy(m->path, adr);
if(m->follow_links)
ret= stat(adr, &(m->stbuf));
else
ret= lstat(adr, &(m->stbuf));
if(ret==-1)
{ret= 0; goto failed;}
if(S_ISDIR(m->stbuf.st_mode)) {
ret= Dirseq_new(&(m->dir_stack), adr, 0);
if(ret<=0)
goto failed;
}
return(1);
failed:;
Treeseq_destroy(o,0);
return(ret);
}
int Treeseq_destroy(struct TreeseQ **o, int flag)
{
struct DirseQ *dirseq, *next;
for(dirseq= (*o)->dir_stack; dirseq!=NULL; dirseq= next) {
next= dirseq->next;
Dirseq_destroy(&dirseq,0);
}
free((char *) *o);
(*o)= NULL;
return(1);
}
/* @return <0 error, 0= no more entries available, 1= ok, reply is valid
*/
int Treeseq_next(struct TreeseQ *o, char adr[SfileadrL], struct stat **stbuf,
int flag)
{
int ret;
char next_name[SfileadrL], *spt;
struct DirseQ *next_dirseq;
if(o->dir_stack==NULL) {
if(!o->unused_yet)
return(0);
strcpy(adr, o->adr);
*stbuf= &(o->stbuf);
o->unused_yet= 0;
return(1);
}
o->unused_yet= 0;
next_in_dirseq:;
ret= Dirseq_next_adr(o->dir_stack, next_name, 1);
if(ret<0)
return(ret);
if(ret>0) {
strcpy(adr, o->path);
ret= Sfile_add_to_path(adr, next_name, 0);
if(ret<=0)
return(-1);
if(o->follow_links)
ret= stat(adr, &(o->stbuf));
else
ret= lstat(adr, &(o->stbuf));
*stbuf= &(o->stbuf);
if(!S_ISDIR(o->stbuf.st_mode))
return(1);
/* Directory found: push new DirseQ on stack */
ret= Dirseq_new(&next_dirseq, adr, 0);
if(ret<=0)
return(-1);
Dirseq_set_next(next_dirseq, o->dir_stack, 0);
o->dir_stack= next_dirseq;
strcpy(o->path, adr);
return(1);
}
/* pop DirseQ from stack */
Dirseq_get_next(o->dir_stack, &next_dirseq, 0);
Dirseq_destroy(&(o->dir_stack), 0);
o->dir_stack= next_dirseq;
spt= strrchr(o->path, '/');
if(spt!=NULL)
(*spt)= 0;
else
o->path[0]= 0;
if(o->dir_stack!=NULL)
goto next_in_dirseq;
return(0); /* it is done */
}
/* ------------------------------ 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);
}
/* ------------------------------- FindjoB -------------------------------- */
struct FindjoB {
char *start_path;
char *name_expr;
#ifdef Xorriso_with_regeX
regex_t name_re;
regmatch_t name_match;
#endif
/* b = blockdev, c = chardev, d = directory, p = fifo, f = reg , - = reg,
s = socket, X = other , 0x0 = test inactive
*/
char file_type;
/* 0= echo
>>> 1= rm
>>> 2= rm_r
>>> 3= mv target
4= chown user
5= chgrp group
6= chmod mode_and mode_or
7= alter_date type date
8= lsdl
9= chown_r user
10= chgrp_r group
11= chmod_r mode_and mode_or
12= alter_date_r type date
13= find
*/
int action;
char *target;
uid_t user;
gid_t group;
mode_t mode_and, mode_or;
int type; /* see Xorriso_set_time flag */
time_t date;
struct FindjoB *subjob;
};
int Findjob_destroy(struct FindjoB **job, int flag);
int Findjob_new(struct FindjoB **o, char *start_path, int flag)
{
struct FindjoB *m;
m= *o= TSOB_FELD(struct FindjoB,1);
if(m==NULL)
return(-1);
m->start_path= NULL;
m->name_expr= NULL;
m->file_type= 0;
m->action= 0; /* print */
m->target= NULL; /* a mere pointer, not managed memory */
m->user= 0;
m->group= 0;
m->type= 0;
m->date= 0;
m->subjob= NULL;
m->start_path= strdup(start_path);
if(m->start_path==NULL)
goto failed;
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->start_path!=NULL)
free(m->start_path);
if(m->name_expr!=NULL) {
#ifdef Xorriso_with_regeX
regfree(&(m->name_re));
#endif
free(m->name_expr);
}
Findjob_destroy(&(m->subjob), 0);
free((char *) m);
*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_set_name_expr(struct FindjoB *o, char *name_expr, int flag)
{
char regexpr[2*SfileadrL+2];
if(o->name_expr!=NULL) {
#ifdef Xorriso_with_regeX
regfree(&(o->name_re));
#endif
free(o->name_expr);
o->name_expr= NULL;
}
if(strlen(name_expr)>=SfileadrL)
return(0);
o->name_expr= strdup(name_expr);
if(o->name_expr==NULL)
return(-1);
Xorriso__bourne_to_reg(name_expr, regexpr, 0);
if(regcomp(&(o->name_re), regexpr, 0)!=0)
return(0);
return(1);
}
int Findjob_set_file_type(struct FindjoB *o, char file_type, int flag)
{
static char known[]= {"bcdpf-lsX"};
if(file_type!=0)
if(strchr(known, file_type)==NULL)
return(0);
o->file_type= file_type;
return(1);
}
/* @return 0=no match , 1=match , <0 = error
*/
int Findjob_test(struct FindjoB *o, char *name,
struct stat *boss_stbuf, struct stat *stbuf,
int depth, int flag)
{
int ret;
if(o->name_expr!=NULL) {
#ifdef Xorriso_with_regeX
ret= regexec(&(o->name_re),name,1,&(o->name_match),0);
#else
ret= !(strcmp(name, o->name_expr)==0 || strcmp(o->name_expr, "*")==0);
#endif
if(ret!=0)
return(0);
}
if(o->file_type!=0) {
if(S_ISBLK(stbuf->st_mode)) {
if(o->file_type!='b')
return(0);
} else if(S_ISCHR(stbuf->st_mode)) {
if(o->file_type!='c')
return(0);
} else if(S_ISDIR(stbuf->st_mode)) {
if(o->file_type!='d')
return(0);
} else if(S_ISFIFO(stbuf->st_mode)) {
if(o->file_type!='p')
return(0);
} else if(S_ISREG(stbuf->st_mode)) {
if(o->file_type!='f' && o->file_type!='-')
return(0);
} else if(((stbuf->st_mode)&S_IFMT)==S_IFLNK) {
if(o->file_type!='l')
return(0);
} else if(((stbuf->st_mode)&S_IFMT)==S_IFSOCK) {
if(o->file_type!='s')
return(0);
} else {
if(o->file_type!='X')
return(0);
}
}
/* ??? >>> more tests to come ?*/;
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,
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;
*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_set_action_target(struct FindjoB *o, int action, char *target,
int flag)
{
o->action= action;
o->target= target;
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);
}
/* ------------------------------- 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;
struct XorrisO *m;
*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->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->do_joliet= 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->loaded_volid[0]= 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->do_overwrite= 2;
m->do_reassure= 0;
m->indev[0]= 0;
m->in_drive_handle= NULL;
m->in_volset_handle= NULL;
m->volset_change_pending= 0;
m->outdev[0]= 0;
m->out_drive_handle= NULL;
m->ban_stdio_write= 0;
m->do_dummy= 0;
m->do_close= 0;
m->speed= 0;
m->fs= 4*512; /* 4 MiB */
m->allow_graft_points= 0;
m->dialog= 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->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->status_history_max= Xorriso_status_history_maX;
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;
#ifdef Xorriso_with_regeX
m->re= NULL;
/* >>> ??? how to initialize m->match[0] ? */
#endif /* Xorriso_with_regeX */
m->re_constants= NULL;
m->re_count= 0;
m->re_fill= 0;
m->reg_expr[0]= 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->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;
return(1);
}
int Xorriso_destroy_re(struct XorrisO *m, int flag)
{
int i;
#ifdef Xorriso_with_regeX
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;
}
#endif /* Xorriso_with_regeX */
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);
Xorriso_destroy_re(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;
int ret;
#ifdef Xorriso_with_readlinE
int l;
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);
#ifdef Xorriso_with_readlinE
if(xorriso->use_stdin) {
if(flag&2)
{ret= 1; goto ex;}
if(Sfile_fgets(line,linesize-1,stdin)==NULL) {
/* need a very dramatic end */
kill(getpid(),SIGHUP);
{ret= -1; goto ex;}
}
{ret= 1; goto ex;}
}
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) {
strncpy(line,cpt,linesize-1);
line[sizeof(line)-1]= 0;
} else
strcpy(line,cpt);
}
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;
}
#else /* Xorriso_with_readlinE */
if(flag&2)
{ret= 1; goto ex;}
if(Sfile_fgets(line,linesize-1,stdin)==NULL) {
/* need a very dramatic end */
kill(getpid(),SIGHUP);
{ret= -1; goto ex;}
}
#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);
}
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)
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_result(struct XorrisO *xorriso, int flag)
/*
bit0= no considerations or computations or dialog. Just put out.
*/
{
int ret;
if(flag&1)
goto put_it_out;
if(xorriso->request_to_abort)
return(1);
if(xorriso->result_page_length>0) {
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= Write_to_channel(xorriso->result_line,1,!xorriso->packet_output);
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= Write_to_channel(xorriso->info_text,2,!xorriso->packet_output);
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= Write_to_channel(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_reset_counters(struct XorrisO *xorriso, int flag)
/*
bit0= reset xorriso->found to -1
*/
{
xorriso->error_count= 0;
xorriso->insert_count= 0;
xorriso->insert_bytes= 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;
#ifndef Xorriso_with_regeX
if(xorriso->search_mode==2 ||
(xorriso->search_mode==3 && xorriso->structured_search==0)) {
no_regex_available:;
sprintf(xorriso->info_text,"%s : regular expressions not implemented",
xorriso->progname);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
#endif /* ! Xorriso_with_regeX */
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, "SORRY", 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;
#ifdef Xorriso_with_regeX
xorriso->re= TSOB_FELD(regex_t,count);
if(xorriso->re==NULL)
return(-1);
#endif /* Xorriso_with_regeX */
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<=1) {
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
#ifdef Xorriso_with_regeX
regfree(&(xorriso->re[xorriso->re_fill-1]));
#else /* Xorriso_with_regeX */
;
#endif /* ! Xorriso_with_regeX */
(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 {
#ifdef Xorriso_with_regeX
if(regcomp(&(xorriso->re[xorriso->re_fill]),xorriso->reg_expr,0)!=0)
goto cannot_compile;
#else /* Xorriso_with_regeX */
if(!warned_of_regex) {
sprintf(xorriso->info_text,
"No wildcards get recognized besides single '*'");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING",0);
warned_of_regex= 1;
}
if(Sregex_string(&(xorriso->re_constants[xorriso->re_fill]),adr_part,0)
<=0)
return(-1);
#endif /* ! Xorriso_with_regeX */
}
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, "SORRY",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 {
#ifdef Xorriso_with_regeX
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, "SORRY",0);
return(0);
}
#else /* Xorriso_with_regeX */
sprintf(xorriso->info_text,
"No wildcards get recognized besides single '*'");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING",0);
Xorriso_info(xorriso,0);
if(Sregex_string(&(xorriso->re_constants[0]),adr,0)<=0)
return(-1);
xorriso->re_fill= 1;
#endif /* ! Xorriso_with_regeX */
}
}
}
return(1);
}
/* @return 0=match , else no match
*/
int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at,
int flag)
/*
bit0= do not shortcut last component of to_match
bit2= retry beginning at failed last component
*/
{
int ret,i,re_start= 0,reg_nomatch= -1;
char *cpt,*npt,adr_part[SfileadrL],*mpt;
#ifdef Xorriso_with_regeX
reg_nomatch= REG_NOMATCH;
#endif /* Xorriso_with_regeX */
*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);
}
#ifdef Xorriso_with_regeX
ret= regexec(&(xorriso->re[0]),to_match,1,xorriso->match,0);
#else
ret= reg_nomatch;
#endif /* ! Xorriso_with_regeX */
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 {
#ifdef Xorriso_with_regeX
ret= regexec(&(xorriso->re[i]),mpt,1,xorriso->match,0);
if(ret!=0)
return(ret);
#else
return(reg_nomatch);
#endif /* ! Xorriso_with_regeX */
}
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;
return(reg_nomatch);
}
/* @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:;
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, "SORRY",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) {
sprintf(xorriso->info_text, "Empty link target with : %s",
Text_shellsafe(link_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY",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:;
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,"SORRY",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,l;
if(filter!=NULL)
if(filter[0]=='-') {
l= strlen(filter);
if(strncmp(filter,xorriso->result_line,l)!=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_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;
char *line, sfe[5*SfileadrL], mode[80];
static char channel_prefixes[4][4]= {".","R","I","M"};
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= 0;
if(xorriso->dialog)
sprintf(line,"-dialog on\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->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->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,"-fs %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);
}
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->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= (strcmp(xorriso->volid, "ISOIMAGE")==0);
sprintf(line,"-volid %s\n",Text_shellsafe(xorriso->volid,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);
}
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->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= (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= (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 */
if(strcmp(xorriso->indev,xorriso->outdev)==0) {
sprintf(line,"-dev %s\n", Text_shellsafe(xorriso->indev,sfe,0));
Xorriso_status_result(xorriso,filter,fp,flag&2);
} else {
sprintf(line,"-indev %s\n", Text_shellsafe(xorriso->indev,sfe,0));
Xorriso_status_result(xorriso,filter,fp,flag&2);
sprintf(line,"-outdev %s\n", Text_shellsafe(xorriso->outdev,sfe,0));
Xorriso_status_result(xorriso,filter,fp,flag&2);
}
return(1);
}
int Xorriso_exec(struct XorrisO *xorriso, char *cmd, int flag)
{
char *spt,*cpt,**argv= NULL,errmsg[2*SfileadrL];
int is_done= 0,argc= 0,widx= 0,cmd_l,pass,ret;
cmd_l= strlen(cmd);
if(cmd_l>SfileadrL) {
sprintf(xorriso->info_text,
"Command for external process too long : %d (max %d)",
cmd_l, SfileadrL);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
}
for(pass=0;pass<2;pass++) {
is_done= 0;
widx= 0;
for(spt= cmd;!is_done;spt= cpt+1) {
for(cpt= spt;*cpt!=0 && *cpt!=':' && *cpt!=' ';cpt++);
if(*cpt==0)
is_done= 1;
if(pass==0) {
argc++;
} else {
*cpt= 0;
if(Sregex_string(&(argv[widx]),spt,0)<=0)
{ret= -1; goto ex;}
widx++;
}
}
if(pass==0) {
if(argc==0)
{ret= 2; goto ex;}
argv= TSOB_FELD(char *,argc+1);
if(argv==NULL)
{ret= -1; goto ex;}
for(widx= 0;widx<argc+1;widx++)
argv[widx]= NULL;
}
}
ret= Exec_cmd(xorriso->progname,cmd,NULL,argv,errmsg,
!!(xorriso->packet_output));
if(ret<0)
goto ex;
if(ret>0) {
for(widx=0; widx<cmd_l; widx++)
if(cmd[widx]==0)
cmd[widx]= ' ';
sprintf(xorriso->info_text,"External process failed : %s",cmd);
if(errmsg[0]!=0)
sprintf(xorriso->info_text+strlen(xorriso->info_text),
"message: %s\n",errmsg);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
{ret= 0; goto ex;}
}
ret= 1;
ex:
if(argv!=NULL) {
for(widx=0;widx<argc;widx++)
Sregex_string(&(argv[widx]),NULL,0);
free((char *) argv);
}
return(ret);
}
/* @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, "SORRY", 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(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 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;
#ifdef Xorriso_fat_local_meM
char adr[SfileadrL], name[SfileadrL], path_data[SfileadrL];
#else /* Xorriso_fat_local_meM */
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;}
}
#endif /* ! Xorriso_fat_local_meM */
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:;
#ifndef Xorriso_fat_local_meM
if(adr!=NULL)
free(adr);
if(name!=NULL)
free(name);
if(path_data!=NULL)
free(path_data);
#endif /* ! Xorriso_fat_local_meM */
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
*/
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, "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, "SORRY", 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 SORRY 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);
ret= Sfile_type(dir_adr, 1|4);
if(ret!=2) {
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, "SORRY", 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);
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);
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" : "-iso_rr_pattern");
}
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], "--")==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. Wiith 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 "--" 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 bit allow 0 matches if pattern is a constant
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);
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);
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= "FATAL";
int sev, ret;
ret= Xorriso__text_to_sev(severity, &sev, 0);
if(ret<=0)
return(0);
xorriso->problem_status= sev;
strcpy(xorriso->problem_status_text, sev_text);
return(1);
}
/* 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: ""
*/
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: ",
"", "", "", "", "", "", "", "", "", "", "", "" };
/* 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);
}
/* 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);
}
xorriso->info_text[li+lt]= '\n';
xorriso->info_text[li+lt+1]= 0;
Xorriso_info(xorriso,flag&3);
if(os_errno>0) {
sprintf(xorriso->info_text, "%ssys : %s\n",
pfx_list[(flag>>2)&15], strerror(os_errno));
Xorriso_info(xorriso,flag&3);
}
return(1);
}
/**
@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 : ABORT : -abort_on '%s' encountered '%s'",
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= ~1;
*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, "SORRY", 0);
return(0);
}
return(1);
}
int Xorriso_no_findjob(struct XorrisO *xorriso, char *cmd, int flag)
{
sprintf(xorriso->info_text, "%s: cannot set 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;
#ifdef Xorriso_fat_local_meM
char path[SfileadrL], show_path[SfileadrL], name[SfileadrL], sfe[5*SfileadrL];
#else /* Xorriso_fat_local_meM */
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;}
}
#endif /* ! Xorriso_fat_local_meM */
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:;
#ifndef Xorriso_fat_local_meM
if(sfe!=NULL)
free(sfe);
if(path!=NULL)
free(path);
if(show_path!=NULL)
free(show_path);
if(name!=NULL)
free(name);
#endif /* ! Xorriso_fat_local_meM */
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);
}
int Xorriso__mode_to_perms(mode_t st_mode, char perms[10], 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';
}
return(1);
}
int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag)
{
char *rpt, perms[10];
mode_t st_mode;
time_t mtime;
struct tm tms, *tmpt;
static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
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");
else if(S_ISCHR(st_mode))
strcat(rpt, "c");
else if(S_ISFIFO(st_mode))
strcat(rpt, "p");
else if(S_ISSOCK(st_mode))
strcat(rpt, "s");
else
strcat(rpt, "?");
Xorriso__mode_to_perms(st_mode, perms, 0);
strcat(rpt, perms);
sprintf(rpt+strlen(rpt),"%4u ",(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);
sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size);
mtime= stbuf->st_mtime;
tmpt= localtime_r(&mtime, &tms);
if(tmpt==0)
sprintf(rpt+strlen(rpt), "%12.f ",(double) mtime);
else if(time(NULL)-mtime < 180*86400 && time(NULL)-mtime >= 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(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];
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) {
ret= Xorriso_format_ls_l(xorriso, &stbuf, 0);
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=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;
#ifdef Xorriso_fat_local_meM
char name[SfileadrL], path[SfileadrL], sfe[5*SfileadrL];
char abs_dir_path_data[SfileadrL], abs_path[SfileadrL];
#else /* Xorriso_fat_local_meM */
char *name= NULL, *path= NULL, *sfe= NULL;
char *abs_dir_path_data= NULL, *abs_path= NULL;
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;}
}
#endif /* ! Xorriso_fat_local_meM */
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= 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(job, namept, NULL, dir_stbuf, depth, 0);
if(ret<0)
goto ex;
if(ret>0) {
sprintf(xorriso->result_line, "%s\n", Text_shellsafe(dir_path, sfe, 0));
Xorriso_result(xorriso, 0);
}
}
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= 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(job, name, dir_stbuf, &stbuf, depth, 0);
if(ret<0)
goto ex;
if(ret>0) {
sprintf(xorriso->result_line, "%s\n", Text_shellsafe(path, sfe, 0));
Xorriso_result(xorriso, 0);
}
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:;
#ifndef Xorriso_fat_local_meM
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);
#endif /* ! Xorriso_fat_local_meM */
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
@return <=0 iis 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;
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, 32|64);
if(ret<=0)
goto ex;
/* Evaluate target address */
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) {
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, "SORRY", 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);
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);
}
/* ---------------------------- 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, "SORRY", 0);
return(ret);
}
if(Sfile_str(xorriso->abort_on_text,severity,0)<=0)
return(-1);
xorriso->abort_on_severity= sev;
return(1);
}
/* Option -add */
/* @param flag bit0=do not report the added item */
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;
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(source[0]!='/') {
ret= Sfile_prepend_path(xorriso->wdx, source, 0);
if(ret<=0)
goto problem_handler;
}
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, source, target, 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, 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;
}
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 -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, "-chmod_r", 0);
{ret= -1; goto ex;}
}
Findjob_set_action_ad(job, t_type, t, 0);
ret= Xorriso_findi(xorriso, job, 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 -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 */
int Xorriso_option_blank(struct XorrisO *xorriso, char *mode, int flag)
{
char drive_name[SfileadrL], *cmd= "-blank", sfe[5*SfileadrL];
int ret, aq_flag= 2, mode_flag;
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, "SORRY", 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, "SORRY", 0);
return(0);
}
aq_flag= 3;
}
if(strcmp(mode, "all")==0 || strcmp(mode, "full")==0)
mode_flag= 0;
else if(strcmp(mode, "deformat")==0 || strcmp(mode, "deformat_sequential")==0)
mode_flag= 2;
else if(strcmp(mode, "deformat_quickest")==0 ||
strcmp(mode, "deformat_sequential_quickest")==0)
mode_flag= 3;
else if(strcmp(mode, "fast")==0 || mode[0]==0)
mode_flag= 1;
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, "SORRY", 0);
return(0);
}
if(flag&1)
ret= Xorriso_format_media(xorriso, 0);
else
ret= Xorriso_blank_media(xorriso, mode_flag);
if(ret==0)
return(ret);
strcpy(drive_name, xorriso->outdev);
if(ret!=2) {
Xorriso_give_up_drive(xorriso, aq_flag);
if(ret<=0) { /* this is the return value of the blank|format function */
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(ret);
}
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, "SORRY", 0);
return(ret);
}
}
return(1);
}
/* 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, "SORRY", 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, "SORRY", 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, "SORRY", 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) {
sprintf(xorriso->info_text,"-cdx: file not found : %s",
Text_shellsafe(eff_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
if(ret!=2) {
sprintf(xorriso->info_text,
"-cdx: not a directory : %s",
Text_shellsafe(eff_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
}
if(Sfile_str(xorriso->wdx,eff_path,0)<=0)
return(-1);
Xorriso_option_pwdx(xorriso, 0);
return(1);
}
/* 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, 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, 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, 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 -commit */
/* @param flag bit0= do not aquire outdrive as new indrive */
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(2);
}
ret= Xorriso_write_session(xorriso, 0);
if(ret<=0)
return(ret);
xorriso->volset_change_pending= 0;
if(flag&1)
return(1);
strcpy(newdev, xorriso->outdev);
ret= Xorriso_option_dev(xorriso, newdev, 3);
return(ret);
}
/* 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 */
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) {
printf(xorriso->info_text, "Effective path gets much too long (%d)",
strlen(eff_dest)+strlen(leafname)+1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
goto problem_handler;
}
}
ret= Xorriso_graft_in(xorriso, eff_origin, eff_dest, 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, 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;
}
ret= !was_failure;
ex:;
Xorriso_opt_args(xorriso, "-cpri",
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,
off_t startbyte, off_t bytecount, char *iso_rr_path, int flag)
{
fprintf(stderr,
">>> LIBISOFS : would cut out from %s , byte %.f to %.f, and graft as %s",
disk_path, (double) startbyte, (double) (startbyte+bytecount),
iso_rr_path);
return(1);
}
/* Options -dev , -indev, -outdev */
/** @param flag bit0=use as indev , bit1= use as outdev */
int Xorriso_option_dev(struct XorrisO *xorriso, char *adr, int flag)
{
int ret;
char sfe[5*SfileadrL];
if(xorriso->ban_stdio_write && strncmp(adr, "stdio:", 6)==0) {
sprintf(xorriso->info_text,
"Drive address banned by -ban_stdio_write : '%s'",
adr);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 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, "SORRY", 0);
return(0);
}
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->in_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);
} else
ret= Xorriso_aquire_drive(xorriso, adr, flag&3);
if(ret<0)
return(ret);
return(1);
}
/* Option -devices */
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, "SORRY", 0);
return(0);
}
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) {
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) {
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"|"off" */
int Xorriso_option_dialog(struct XorrisO *xorriso, char *mode, int flag)
{
xorriso->dialog= !!strcmp(mode, "off");
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, "SORRY", 0);
return(0);
}
return(1);
}
/* Option -dummy "on"|"off" */
int Xorriso_option_dummy(struct XorrisO *xorriso, char *mode, int flag)
{
xorriso->do_dummy= !!strcmp(mode, "off");
return(1);
}
/* Option -eject */
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, "SORRY", 0);
return(0);
}
ret= Xorriso_give_up_drive(xorriso, gu_flag);
return(ret);
}
/* Option -end */
int Xorriso_option_end(struct XorrisO *xorriso, int flag)
{
int ret;
if(xorriso->volset_change_pending) {
ret= Xorriso_option_commit(xorriso, 1);
if(ret<=0)
return(ret);
}
ret= Xorriso_give_up_drive(xorriso, 3);
if(ret<=0)
return(ret);
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, "SORRY", 0);
return(0);
}
return(1);
}
/* 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, "SORRY", 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 -find alias -findi, and -findx */
/* @param flag bit0= -findx rather than -findi
*/
int Xorriso_option_find(struct XorrisO *xorriso, int argc, char **argv,
int *idx, int flag)
{
int ret, i, end_idx, type= 0;
struct FindjoB *job, *first_job= NULL, *new_job;
char *start_path, sfe[5*SfileadrL], *cpt;
struct stat dir_stbuf;
uid_t user= 0;
gid_t group= 0;
time_t date= 0;
mode_t mode_or= 0, mode_and= ~1;
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;
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 -exec %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], "-exec")==0) {
if(i+1>=end_idx)
goto not_enough_arguments;
i++;
cpt= argv[i];
if(*cpt=='-')
cpt++;
if(strcmp(cpt, "echo")==0) {
Findjob_set_action_target(job, 0, NULL, 0);
#ifdef NIX
/* >>> not implemented yet */;
} else if(strcmp(cpt, "rm")==0) {
Findjob_set_action_target(job, 1, NULL, 0);
} else if(strcmp(cpt, "rm_r")==0) {
Findjob_set_action_target(job, 2, NULL, 0);
} else if(strcmp(cpt, "mv")==0) {
if(i+1>=end_idx)
goto not_enough_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_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_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_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_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 {
sprintf(xorriso->info_text, "-find -exec: unknown action %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 {
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, "SORRY", 0);
{ret= 0; goto ex;}
}
}
if(flag&1)
ret= Xorriso_findx(xorriso, first_job, "", start_path, &dir_stbuf, 0, NULL,
0);
else
ret= Xorriso_findi(xorriso, first_job, NULL, start_path, &dir_stbuf, 0, 0);
ex:;
Findjob_destroy(&first_job, 0);
(*idx)= end_idx;
return(ret);
}
/* 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);
}
/* 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 -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 with prefix \"stdio:\", e.g. stdio:/tmp/pseudo_drive .",
" -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. Switch from",
" growing to modifying.",
" -outdev address",
" Set output drive and switch from growing to modifying.",
" -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 \"full\"",
" Format DVD-RW to overwriteable state or de-ice DVD+RW.",
" -volid volume_id",
" Specifies the volume ID text.",
" -joliet \"on\"|\"off\"",
" Generate Joliet info additional to Rock Ridge info.",
"",
" -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. (MMC, not ISO 9660)",
"",
" -print-size Print the foreseeable consumption by next -commit.",
"",
" -tell_media_space",
" Print foreseeable available space on output media",
"",
"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 with variable length path list [...] need \"--\" as end mark",
"if they are followed by another option. 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.",
"Options marked by [***] have variable argument length and perform pattern",
"expansion if enabled by -iso_rr_pattern resp. -disk_pattern.",
"",
" -add pathspec [...] | disk_path [***]",
" Insert the given files or directory trees from",
" filesystem into the ISO image. Much like mkisofs.",
" -path-list disk_path",
" Like -add but read the pathspecs from file disk_path.",
" -pathspecs \"on\"|\"off\" Allow or disallow pathspecs of form ",
" iso_rr_path=disk_path . Only \"off\" allows eventual",
" -disk_pattern expansion.",
"",
" -cpr disk_path [...] iso_rr_path",
" Insert the given files or directory trees from filesystem",
" into the ISO image.",
" -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.",
" -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 [-name pattern] [-type t] [-exec action [params]]",
" performs an action on files below the current working",
" directory in the ISO image. If -name pattern is given",
" then only files with matching leaf names are processed.",
" If -type is given then only files with matching type are",
" processed. Types: block,char,dir,pipe,file,link,socket.",
" action may be one of: echo, chown, chown_r, chgrp, chgrp_r",
" chmod, chmod_r, alter_date, alter_date_r, lsdl, find.",
" params are their arguments except iso_rr_path.",
" I.e. echo and lsdl have no params at all.",
" -mkdir iso_rr_path [...]",
" Create empty directories if they do not exist yet.",
" -rmdir iso_rr_path [***]",
" Delete empty directories.",
" -- Mark end of particular action argument list.",
"",
" -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.",
" -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.",
"",
"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.",
" -close \"on\"|\"off\"",
" If \"on\" then mark the written media as not appendable.",
" -dummy \"on\"|\"off\"",
" If \"on\" simulate burning. Refuse if media cannot simulate.",
" -speed number[\"k\"|\"m\"|\"[x]CD\"|\"[x]DVD\"]",
" Set the burn speed. Default is 0 = maximum speed.",
" -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.",
"",
" -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] like -find but in local filesystem.",
" Any -exec option is ignored. Action is always echo.",
"",
"General options:",
" -help Print this text",
" -abort_on severity Set the threshhold for events to abort the program.",
" Useful severities are: NEVER, ABORT, FATAL, SORRY, WARNING",
" -report_about severity Set the threshhold for events to be reported.",
" Use -abort_on severities or: HINT, NOTE, UPDATE, DEBUG, ALL",
" -dialog after all arguments are processed, enter dialog mode.",
" In this mode you may enter searchtexts or any of the options",
" described here. One per line.",
" -dialog_reset Revoke -dialog (works only if given as argument)",
" -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 */
" -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.",
" # 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 immediately",
"",
"",
"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 -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, "SORRY", 0);
return(0);
}
return(1);
}
/* 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;
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) {
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_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 -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= Write_to_channel(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);
}
/* 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 -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);
}
/* 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) {
printf(xorriso->info_text, "Effective path gets much too long (%d)",
strlen(eff_dest)+strlen(leafname)+1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
goto problem_handler;
}
}
ret= Xorriso_rename(xorriso, 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 -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, was_failure= 0, fret;
FILE *fp= NULL;
char line[5*SfileadrL], shellsafe[5*SfileadrL];
char **argv= 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);
}
fp= Afile_fopen(adr,"rb",((!!xorriso->packet_output)<<6));
if(fp==NULL)
return(0);
while(1) {
if(Sfile_fgets(line,sizeof(line),fp)==NULL) {
ret= 1;
if(ferror(fp))
ret= 0;
break;
}
linecount++;
if(line[0]==0 || line[0]=='#')
continue;
if(flag&1) {
ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, 4|8);
if(ret<=0)
goto problem_handler;
ret= Xorriso_prescan_args(xorriso,argc,argv,1);
Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */
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;
}
ex:;
Xorriso_reset_counters(xorriso,1);
if(fp!=NULL)
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 -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, "SORRY", 0);
return(0);
}
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 -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;
FILE *fp= NULL;
char *argpt, sfe[5*SfileadrL],line[SfileadrL];
if(adr[0]==0) {
sprintf(xorriso->info_text,"Empty file name given with -path-list");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
fp= Afile_fopen(adr,"rb",((!!xorriso->packet_output)<<6));
if(fp==NULL)
return(0);
while(1) {
if(Sfile_fgets(line,sizeof(line),fp)==NULL) {
ret= 1;
if(ferror(fp))
ret= 0;
break;
}
linecount++;
if(line[0]==0)
continue;
argpt= line;
null= 0;
ret= Xorriso_option_add(xorriso, 1, &argpt, &null, 1);
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(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" : "SORRY"), 0);
}
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, "SORRY", 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 */
int Xorriso_option_print_size(struct XorrisO *xorriso, int flag)
{
int ret;
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 : 0\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);
}
sprintf(xorriso->result_line,"Image size : %d\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 -pwd alias -pwdi */
int Xorriso_option_pwdi(struct XorrisO *xorriso, int flag)
{
sprintf(xorriso->info_text,"current working directory in ISO image:\n");
Xorriso_info(xorriso,0);
sprintf(xorriso->result_line,"%s/\n",xorriso->wdi);
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 -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);
}
/* Options -rm alias -rmi , -rm_r alias -rm_ri , -rmdir alias -rmdiri */
/* @param flag bit0=recursive , bit2= 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];
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, 2);
if(ret<=0)
goto problem_handler;
strcpy(path, eff_path);
ret= Xorriso_rmi(xorriso, NULL, 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 */
int Xorriso_option_rollback(struct XorrisO *xorriso, int flag)
{
int ret;
char indev[SfileadrL];
if(Sfile_str(indev, xorriso->indev, 0)<=0)
return(-1);
ret= Xorriso_give_up_drive(xorriso, 1|8);
if(ret<=0)
return(ret);
ret= Xorriso_option_dev(xorriso, indev, 1);
/*
1|((xorriso->out_drive_handle==NULL)<<1));
*/
return(ret);
}
/* Option -speed */
int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag)
{
int is_cd= 1, unit_found= 0;
double num;
char *cpt;
if(speed[0]==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(*cpt=='c' || *cpt=='C') {
cd_speed:;
num*= 176.4;
} else if(*cpt=='d' || *cpt=='D') {
dvd_speed:;
num*= 1385;
} else if (!unit_found) {
/* >>> try to determine target media */;
if(is_cd)
goto cd_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 -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 -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 : %d\n", media_space);
Xorriso_result(xorriso, 0);
sprintf(xorriso->result_line, "Free space : %d\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);
}
/* 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)
{
sprintf(xorriso->result_line,
"xorriso %s : RockRidge filesystem manipulator\n", PROG_VERSION);
sprintf(xorriso->result_line+strlen(xorriso->result_line),
"Copyright (C) 2008, Thomas Schmitt <scdbackup@gmx.net>, libburnia project\n");
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);
return(1);
}
/* Option -volid */
int Xorriso_option_volid(struct XorrisO *xorriso, char *volid, int flag)
{
int warn= 0, i, ret;
static char good_chars[]= {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-+=:.,~@"};
for(i=0; volid[i]!=0; i++)
if(strchr(good_chars, volid[i])==NULL)
warn= 1;
if(i>32) {
sprintf(xorriso->info_text, "-volid: Text too long (%d > 32)", i);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
if(warn) {
sprintf(xorriso->info_text,
"-volid text problematic as automatic mount point name");
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);
return(1);
}
/* ---------------------------- End Options API ------------------------ */
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
*/
/*
bit0= recursion
*/
{
int ret, was_dashed;
int num1, num2;
double d1, d2;
char *cmd, *arg1, *arg2, *arg4;
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:;
xorriso->prepended_wd= 0;
xorriso->request_to_abort= xorriso->request_not_to_ask= 0;
Xorriso_set_problem_status(xorriso, "", 0);
if((*idx)<argc)
cmd= argv[*idx];
else
cmd= "";
was_dashed= 0;
if(cmd[0]=='-' && cmd[1]!='-' && cmd[1]!=0) {
was_dashed= 1;
cmd++;
}
(*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,"add")==0) {
ret= Xorriso_option_add(xorriso, argc, argv, idx, 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,"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,"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,"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,"commit")==0) {
ret= Xorriso_option_commit(xorriso, 0);
} else if(strcmp(cmd,"cpr")==0 || strcmp(cmd,"cpri")==0) {
ret= Xorriso_option_cpri(xorriso, argc, argv, idx, 0);
} else if(strcmp(cmd,"cut_out")==0) {
(*idx)+= 2;
d1= d2= -1;
sscanf(arg2,"%lf", &d1);
if((*idx)<argc)
sscanf(argv[*idx],"%lf", &d2);
if((*idx)+1<argc)
arg4= argv[(*idx)+1];
else
arg4= "";
(*idx)+= 2;
ret= Xorriso_option_cut_out(xorriso, arg1, (off_t) d1, (off_t) d2, arg4, 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,"dummy")==0) {
(*idx)++;
ret= Xorriso_option_dummy(xorriso, arg1, 0);
} else if(strcmp(cmd,"dialog")==0) {
(*idx)++;
ret= Xorriso_option_dialog(xorriso, arg1, 0);
} else if(strcmp(cmd,"disk_pattern")==0) {
(*idx)++;
ret= Xorriso_option_disk_pattern(xorriso, arg1, 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,"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) {
Xorriso_option_end(xorriso, 0);
ret= Xorriso_eval_problem_status(xorriso, ret, 0);
if(ret<0)
return(ret);
{ret= 3; goto ex;}
} else if(strcmp(cmd,"iso_rr_pattern")==0) {
(*idx)++;
ret= Xorriso_option_iso_rr_pattern(xorriso, arg1, 0);
} else if(strcmp(cmd,"follow")==0) {
(*idx)++;
ret= Xorriso_option_follow(xorriso, arg1, 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,"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,"gid")==0) {
(*idx)++;
ret= Xorriso_option_gid(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,"joliet")==0) {
(*idx)++;
ret= Xorriso_option_joliet(xorriso, arg1, 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,"logfile")==0) {
(*idx)+= 2;
ret= Xorriso_option_logfile(xorriso, arg1, arg2, 0);
} else if(strcmp(cmd,"mark")==0) {
(*idx)++;
ret= Xorriso_option_mark(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,"options_from_file")==0) {
(*idx)++;
ret= Xorriso_option_options_from_file(xorriso,arg1,0);
if(ret==3)
goto ex;
} else if(strcmp(cmd,"overwrite")==0) {
(*idx)++;
ret= Xorriso_option_overwrite(xorriso,arg1,0);
} else if(strcmp(cmd,"outdev")==0) {
(*idx)++;
ret= Xorriso_option_dev(xorriso, arg1, 2);
} 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,"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 || 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,"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,"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,"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,"speed")==0) {
(*idx)++;
ret= Xorriso_option_speed(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,"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. */
char line[4096];
struct TreeseQ *seq;
struct stat *stbufpt;
printf("XORRISO: -test : enter a file address for tree crawling\n");
ret= Xorriso_dialog_input(xorriso,line,sizeof(line),4);
if(ret<=0)
goto eval_any_problems;
ret= Treeseq_new(&seq, line, 0);
if(ret<=0) {
sprintf(xorriso->info_text,"Failed to create TreeseQ");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
goto eval_any_problems;
}
while(1) {
ret= Treeseq_next(seq, line, &stbufpt, 0);
if(ret<=0)
break;
sprintf(xorriso->result_line,"%s%s\n",line,
S_ISDIR(stbufpt->st_mode) ? "/" : "");
Xorriso_result(xorriso,0);
if(xorriso->request_to_abort)
break;
}
Treeseq_destroy(&seq, 0);
if(ret<0) {
sprintf(xorriso->info_text,"Tree crawling aborted");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
goto eval_any_problems;
}
} 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,"volid")==0) {
(*idx)++;
ret= Xorriso_option_volid(xorriso,arg1,0);
} 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,"--")==0){
/* tis ok */;
} else if(was_dashed) {
unknown_option:;
sprintf(xorriso->info_text,
"=== Not a known option:\n");
sprintf(xorriso->info_text+strlen(xorriso->info_text),
"=== '%s%s'\n",(was_dashed ? "-" : ""), cmd);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
{ret= 0; goto eval_any_problems;}
} else {
goto unknown_option;
/* >>> ??? pathspecs for option -add */;
sprintf(xorriso->info_text, "Ignored argument : '%s'", cmd);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
}
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,1);
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);
if(ret<=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,1);
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];
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)
break;
xorriso->did_something_useful= 1;
}
ret= 1;
ex:;
xorriso->is_dialog= 0;
return(ret);
}
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;
char *cmd, *arg1;
for(i=1+(flag&1);i<argc;i++) {
cmd= argv[i];
was_dashed= 0;
if(cmd[0]=='-' && cmd[1]!='-' && cmd[1]!=0) {
was_dashed= 1;
cmd++;
}
arg1= "";
if(i+1<argc)
arg1= argv[i+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;
return(0);
} else if(strcmp(cmd,"help")==0) {
Xorriso_option_help(xorriso,0);
xorriso->did_something_useful= 1;
return(0);
} else if(strcmp(cmd,"version")==0) {
Xorriso_option_version(xorriso, 0);
xorriso->did_something_useful= 1;
return(0);
}
} else if(strcmp(cmd,"no_rc")==0) {
ret= Xorriso_option_no_rc(xorriso, 0);
if(ret<=0)
return(ret);
}
}
return(1);
}
/** Load content startup files into preskin cache */
int Xorriso_read_rc(struct XorrisO *xorriso, int flag)
{
int ret,i,was_failure= 0,fret;
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);
}
#ifdef Xorriso_with_maiN
int main(int argc, char **argv)
{
#else
int Xorriso_main(int argc, char **argv)
{
#endif /* Xorriso_with_maiN */
int ret,i;
struct XorrisO *xorriso= NULL;
if(argc<2) {
fprintf(stderr,
"xorriso %s : RockRidge filesystem manipulator, libburnia project.\n\n",
PROG_VERSION);
fprintf(stderr,"usage : %s [options]\n",
argv[0]);
fprintf(stderr," More is told by option -help\n");
exit(2);
}
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. Currently:
-no_rc and single-argument runs like -help or -version.
*/
ret= Xorriso_prescan_args(xorriso,argc,argv,0);
if(ret==0)
goto end_sucessfully;
if(ret<0)
exit(5);
fprintf(stderr,
"xorriso %s : RockRidge filesystem manipulator, libburnia project.\n\n",
PROG_VERSION);
ret= Xorriso_startup_libraries(xorriso, 0);
if(ret<=0)
exit(4);
Xorriso_process_msg_queues(xorriso, 0);
/* Interpret startup file */
if(!xorriso->no_rc) {
ret= Xorriso_read_rc(xorriso, 0);
if(ret==3)
goto end_sucessfully;
if(ret<=0)
exit(5);
}
/* Interpret program arguments */
i= 1;
ret= Xorriso_interpreter(xorriso,argc,argv,&i,0);
if(ret==3)
goto end_sucessfully;
if(ret<=0)
exit(5);
if(xorriso->dialog) {
ret= Xorriso_dialog(xorriso,0);
if(ret<=0)
exit(6);
}
end_sucessfully:;
Xorriso_process_msg_queues(xorriso, 0);
if(xorriso->volset_change_pending)
Xorriso_option_end(xorriso, 0);
Xorriso_process_msg_queues(xorriso, 0);
Xorriso_destroy(&xorriso,1);
exit(0);
}