You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
21346 lines
620 KiB
21346 lines
620 KiB
|
|
/* |
|
|
|
( cd .. ; libisoburn-develop/xorriso/compile_xorriso.sh -g ) |
|
|
|
or |
|
|
|
cc -g -DXorriso_with_maiN -DXorriso_with_readlinE \ |
|
-DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \ |
|
-Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ |
|
-o xorriso/xorriso \ |
|
xorriso/xorriso.c xorriso/xorrisoburn.c \ |
|
-lz -lacl -lpthread -lreadline -lburn -lisofs -lisoburn |
|
|
|
or |
|
|
|
cc -g -DXorriso_with_readlinE \ |
|
-DXorriso_build_timestamP='"'"$(date -u '+%Y.%m.%d.%H%M%S')"'"' \ |
|
-Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ |
|
-c \ |
|
xorriso/xorriso.c xorriso/xorrisoburn.c |
|
|
|
*/ |
|
|
|
/* Command line oriented batch and dialog tool which creates, loads, |
|
manipulates and burns ISO 9660 filesystem images. |
|
|
|
Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net> |
|
|
|
Initial code of this program was derived from program src/askme.c out |
|
of scdbackup-0.8.8, Copyright 2007 Thomas Schmitt, BSD-License. |
|
|
|
Provided under GPL version 2 or later, with the announcement that this |
|
might get changed in future. I would prefer BSD or LGPL as soon as the |
|
license situation of the library code allows that. |
|
(This announcement affects only future releases of xorriso and it will |
|
always be possible to derive a GPLv2+ from the future license.) |
|
|
|
There is a derived package "GNU xorriso" under GPLv3+ which combines the |
|
libburnia libraries and program xorriso to a statically linked binary. |
|
|
|
|
|
Overview of xorriso architecture: |
|
|
|
libburn provides the ability to read and write data. |
|
|
|
libisofs interprets and manipulates ISO 9660 directory trees. It generates |
|
the output stream which is handed over to libburn. |
|
|
|
libisoburn encapsulates the connectivity issues between libburn and |
|
libisofs. It also enables multi-session emulation on overwritable media |
|
and random access file objects. |
|
xorriso is intended as reference application of libisoburn. |
|
|
|
xorrisoburn.[ch] encapsulate any usage of the libraries by xorriso. |
|
|
|
xorriso.h exposes the public functions of xorriso which are intended |
|
to be used by programs which link with xorriso.o. These functions are |
|
direct equivalents of the xorriso interpreter commands. |
|
There is also the API for handling event messages. |
|
|
|
xorriso_private.h is not to be included by other software. It encapsulates |
|
the inner interfaces of xorriso. |
|
|
|
xorriso.c provides the command interpreter as described in xorriso.1. |
|
It performs any activity that does not demand a reference to a symbol |
|
of the library APIs. This includes: |
|
- Interpretation of user input from arguments, dialog, and scripting. |
|
- Output of result text and event messages. |
|
- POSIX filesystem operations. |
|
- Public functions which perform the particular xorriso commands. |
|
- The main() function, if enabled by #define Xorriso_with_maiN. |
|
|
|
*/ |
|
|
|
/* This may be changed to Xorriso_GNU_xorrisO in order to create GNU xorriso */ |
|
#define Xorriso_libburnia_xorrisO yes |
|
|
|
|
|
#ifdef Xorriso_without_subS |
|
|
|
|
|
|
|
#include <ctype.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
|
|
#include <locale.h> |
|
|
|
/* The official xorriso options API. "No shortcuts" */ |
|
#include "xorriso.h" |
|
|
|
|
|
|
|
#else /* Xorriso_without_subS */ |
|
|
|
|
|
|
|
#include <ctype.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#include <fcntl.h> |
|
#include <errno.h> |
|
#include <sys/time.h> |
|
#include <sys/resource.h> |
|
#include <sys/wait.h> |
|
#include <dirent.h> |
|
#include <time.h> |
|
#include <utime.h> |
|
#include <pwd.h> |
|
#include <grp.h> |
|
#include <signal.h> |
|
#include <sys/utsname.h> |
|
#include <sys/select.h> |
|
|
|
/* for -charset */ |
|
#include <iconv.h> |
|
#include <langinfo.h> |
|
#include <locale.h> |
|
|
|
/* eventually, this is done in xorriso_private.h : #include <regex.h> */ |
|
|
|
#ifdef Xorriso_with_readlinE |
|
#ifdef Xorriso_with_old_readlinE |
|
#include <readline.h> |
|
#include <history.h> |
|
#else /* Xorriso_with_old_readlinE */ |
|
#include <readline/readline.h> |
|
#include <readline/history.h> |
|
#endif /* ! Xorriso_with_old_readlinE */ |
|
#endif /* Xorriso_with_readlinE */ |
|
|
|
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ)); |
|
|
|
|
|
/* Diet facility: exclude help texts from binaries */ |
|
/* This will eventually be redefined to eat up its content */ |
|
#define AlN(x) x |
|
|
|
|
|
/* There is only one stage of diet: Xorriso_no_helP */ |
|
#ifdef Xorriso_no_helP |
|
#undef AlN |
|
#define AlN(x) |
|
#endif |
|
|
|
|
|
/* ------------------------------------------------------------------------ */ |
|
|
|
|
|
/* The official xorriso options API. "No shortcuts" */ |
|
#include "xorriso.h" |
|
|
|
/* The inner description of XorrisO */ |
|
#define Xorriso_is_xorriso_selF 1 |
|
#include "xorriso_private.h" |
|
|
|
/* The inner isofs- and burn-library interface */ |
|
#include "xorrisoburn.h" |
|
|
|
|
|
/* See Xorriso__preset_signal_behavior() */ |
|
static int Xorriso_signal_behavioR= 1; |
|
|
|
|
|
/* ------------------------------------------------------------------------ */ |
|
|
|
|
|
#ifndef Xorriso_sfile_externaL |
|
/* @param flag bit0= do not clip of carriage return at line end |
|
*/ |
|
char *Sfile_fgets_n(char *line, int maxl, FILE *fp, int flag) |
|
{ |
|
int l; |
|
char *ret; |
|
|
|
ret= fgets(line,maxl,fp); |
|
if(ret==NULL) |
|
return(NULL); |
|
l= strlen(line); |
|
if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0; |
|
if(l > 0) if(line[l-1] == '\n') line[--l]= 0; |
|
if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0; |
|
return(ret); |
|
} |
|
|
|
|
|
int Sfile_count_components(char *path, int flag) |
|
/* |
|
bit0= do not ignore trailing slash |
|
bit1= do not ignore empty components (other than the empty root name) |
|
*/ |
|
{ |
|
int l,count= 0; |
|
char *cpt; |
|
|
|
l= strlen(path); |
|
if(l==0) |
|
return(0); |
|
count= 1; |
|
for(cpt= path+l-1;cpt>=path;cpt--) { |
|
if(*cpt=='/') { |
|
if(*(cpt+1)==0 && !(flag&1)) |
|
continue; |
|
if(*(cpt+1)=='/' && !(flag&2)) |
|
continue; |
|
count++; |
|
} |
|
} |
|
return(count); |
|
} |
|
|
|
|
|
int Sfile_component_pointer(char *path, char **sourcept, int idx, int flag) |
|
/* |
|
bit0= do not ignore trailing slash |
|
bit1= do not ignore empty components (other than the empty root name) |
|
bit2= accept 0 as '/' |
|
*/ |
|
{ |
|
int count= 0; |
|
char *spt; |
|
|
|
for(spt= path;*spt!=0 || (flag&4);spt++) { |
|
if(count>=idx) { |
|
*sourcept= spt; |
|
return(1); |
|
} |
|
if(*spt=='/' || *spt==0) { |
|
if(*(spt+1)=='/' && !(flag&2)) |
|
continue; |
|
if(*(spt+1)==0 && !(flag&1)) |
|
continue; |
|
count++; |
|
} |
|
} |
|
if((flag&1) && count>=idx) |
|
return(1); |
|
return(0); |
|
} |
|
|
|
|
|
int Sfile_leafname(char *path, char leafname[SfileadrL], int flag) |
|
{ |
|
int count, ret; |
|
char *lpt; |
|
|
|
leafname[0]= 0; |
|
count= Sfile_count_components(path, 0); |
|
if(count==0) |
|
return(0); |
|
ret= Sfile_component_pointer(path, &lpt, count-1, 0); |
|
if(ret<=0) |
|
return(ret); |
|
if(Sfile_str(leafname, lpt, 0)<=0) |
|
return(0); |
|
lpt= strchr(leafname, '/'); |
|
if(lpt!=NULL) |
|
*lpt= 0; |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag) |
|
{ |
|
int l; |
|
|
|
l= strlen(path); |
|
if(l+1>=SfileadrL) |
|
return(0); |
|
if(l==0) { |
|
strcpy(path,"/"); |
|
l= 1; |
|
} else if(path[l-1]!='/') { |
|
path[l++]= '/'; |
|
path[l]= 0; |
|
} |
|
if(l+strlen(addon)>=SfileadrL) |
|
return(0); |
|
if(addon[0]=='/') |
|
strcpy(path+l,addon+1); |
|
else |
|
strcpy(path+l,addon); |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_prepend_path(char *prefix, char path[SfileadrL], int flag) |
|
{ |
|
int l, i; |
|
|
|
l= strlen(path)+strlen(prefix)+1; |
|
if(l>=SfileadrL) { |
|
|
|
#ifdef Not_yeT |
|
/* >>> ??? how to transport messages to xorriso ? */ |
|
sprintf(xorriso->info_text, |
|
"Combination of wd and relative address too long (%d > %d)", |
|
l,SfileadrL-1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
#endif |
|
|
|
return(-1); |
|
} |
|
l-= strlen(path); |
|
for(i= strlen(path)+1; i>=0; i--) |
|
path[i+l]= path[i]; |
|
strcpy(path,prefix); |
|
path[l-1]= '/'; |
|
return(1); |
|
} |
|
|
|
int Sfile_being_group_member(struct stat *stbuf, int flag) |
|
{ |
|
int i, suppl_groups; |
|
gid_t *suppl_glist; |
|
|
|
if (getegid()==stbuf->st_gid) |
|
return(1); |
|
suppl_groups= getgroups(0, NULL); |
|
suppl_glist= (gid_t *) malloc((suppl_groups + 1) * sizeof(gid_t)); |
|
if (suppl_glist==NULL) |
|
return(-1); |
|
suppl_groups= getgroups(suppl_groups+1,suppl_glist); |
|
for (i= 0; i<suppl_groups; i++) { |
|
if (suppl_glist[i]==stbuf->st_gid) { |
|
free((char *) suppl_glist); |
|
return(1); |
|
} |
|
} |
|
free((char *) suppl_glist); |
|
return(0); |
|
} |
|
|
|
|
|
int Sfile_type(char *filename, int flag) |
|
/* |
|
bit0= return -1 if file is missing |
|
bit1= return a hardlink with siblings as type 5 |
|
bit2= evaluate eventual link target rather than the link object itself |
|
bit3= return a socket or a char device as types 7 or 8 rather than 0 |
|
*/ |
|
/* |
|
return: |
|
0=unknown |
|
1=regular |
|
2=directory |
|
3=symbolic link |
|
4=named pipe |
|
5=multiple hardlink (with bit1) |
|
6=block device |
|
7=socket (with bit3) |
|
8=character device (with bit3) |
|
*/ |
|
{ |
|
struct stat stbuf; |
|
if(flag&4) { |
|
if(stat(filename,&stbuf)==-1) { |
|
if(flag&1) return(-1); |
|
else return(0); |
|
} |
|
} else { |
|
if(lstat(filename,&stbuf)==-1) { |
|
if(flag&1) return(-1); |
|
else return(0); |
|
} |
|
} |
|
if(S_ISREG(stbuf.st_mode)) { |
|
if(flag&2) |
|
if(stbuf.st_nlink>1) |
|
return(5); |
|
return(1); |
|
} |
|
if(S_ISDIR(stbuf.st_mode)) |
|
return(2); |
|
if((stbuf.st_mode&S_IFMT)==S_IFLNK) |
|
return(3); |
|
if(S_ISFIFO(stbuf.st_mode)) |
|
return(4); |
|
if(S_ISBLK(stbuf.st_mode)) |
|
return(6); |
|
if(flag&8) |
|
if((stbuf.st_mode&S_IFMT)==S_IFSOCK) |
|
return(7); |
|
if(flag&8) |
|
if(S_ISCHR(stbuf.st_mode)) |
|
return(8); |
|
return(0); |
|
} |
|
|
|
|
|
char *Sfile_datestr(time_t tim, short int flag) |
|
/* |
|
bit0=with hours+minutes |
|
bit1=with seconds |
|
|
|
bit8= local time rather than UTC |
|
*/ |
|
{ |
|
static char zeitcode[80]={"000000"}; |
|
char puff[80]; |
|
struct tm *azt; |
|
|
|
if(flag&256) |
|
azt = localtime(&tim); |
|
else |
|
azt = gmtime(&tim); |
|
|
|
if(azt->tm_year>99) |
|
sprintf(zeitcode,"%c%1.1d%2.2d%2.2d", |
|
'A'+(azt->tm_year-100)/10,azt->tm_year%10, |
|
azt->tm_mon+1,azt->tm_mday); |
|
else |
|
sprintf(zeitcode,"%2.2d%2.2d%2.2d", |
|
azt->tm_year,azt->tm_mon+1,azt->tm_mday); |
|
if(flag&1){ |
|
sprintf(puff,".%2.2d%2.2d",azt->tm_hour,azt->tm_min); |
|
strcat(zeitcode,puff); |
|
} |
|
if(flag&2){ |
|
sprintf(puff,"%2.2d",azt->tm_sec); |
|
strcat(zeitcode,puff); |
|
} |
|
|
|
return(zeitcode); |
|
} |
|
|
|
|
|
int Sfile_scale(double value, char *result, int siz, double thresh, int flag) |
|
/* |
|
bit0= eventually ommit 'b' |
|
bit1= make text as short as possible |
|
bit2= no fraction (if it would fit at all) |
|
*/ |
|
{ |
|
char scale_c,scales[7],form[80], *negpt= NULL, *cpt; |
|
int i,dec_siz= 0,avail_siz= 1; |
|
|
|
if(value<0) { |
|
value= -value; |
|
siz--; |
|
result[0]= '-'; |
|
negpt= result; |
|
result++; |
|
} |
|
strcpy(scales,"bkmgtp"); |
|
scale_c= scales[0]; |
|
for(i=1;scales[i]!=0;i++) { |
|
if(value<thresh-0.5) |
|
break; |
|
value/= 1024.0; |
|
scale_c= scales[i]; |
|
} |
|
if(scale_c!='b' && !(flag&4)) { /* is there room for fractional part ? */ |
|
avail_siz= siz-1; |
|
sprintf(form,"%%.f"); |
|
sprintf(result,"%.f",value); |
|
if(strlen(result)<=avail_siz-2) |
|
dec_siz= 1; /* we are very modest */ |
|
} |
|
if(scale_c=='b' && (flag&1)) { |
|
if(flag&2) |
|
sprintf(form,"%%.f"); |
|
else |
|
sprintf(form,"%%%d.f",siz); |
|
sprintf(result,form,value); |
|
} else { |
|
if(flag&2) |
|
sprintf(form,"%%.f%%c"); |
|
else if(dec_siz>0) |
|
sprintf(form,"%%%d.%df%%c",avail_siz,dec_siz); |
|
else |
|
sprintf(form,"%%%d.f%%c",siz-1); |
|
sprintf(result,form,value,scale_c); |
|
} |
|
if(negpt != NULL) { |
|
for(cpt= result; *cpt==' '; cpt++); |
|
if(cpt > result) { |
|
*negpt= ' '; |
|
*(cpt - 1)= '-'; |
|
} |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_off_t_text(char text[80], off_t num, int flag) |
|
{ |
|
char *tpt; |
|
off_t hnum, scale= 1; |
|
int digits= 0, d, i; |
|
|
|
tpt= text; |
|
hnum= num; |
|
if(hnum<0) { |
|
*(tpt++)= '-'; |
|
hnum= -num; |
|
} |
|
if(hnum<0) { /* it can stay nastily persistent */ |
|
strcpy(text, "_overflow_"); |
|
return(0); |
|
} |
|
for(i= 0; i<23; i++) { /* good for up to 70 bit = 10 exp 21.07... */ |
|
if(hnum==0) |
|
break; |
|
hnum/= 10; |
|
if(hnum) |
|
scale*= 10; |
|
} |
|
if(i==0) { |
|
strcpy(text, "0"); |
|
return(1); |
|
} |
|
if(i==23) { |
|
strcpy(text, "_overflow_"); |
|
return(0); |
|
} |
|
digits= i; |
|
hnum= num; |
|
for(; i>0; i--) { |
|
d= hnum/scale; |
|
tpt[digits-i]= '0'+d; |
|
hnum= hnum%scale; |
|
scale/= 10; |
|
} |
|
tpt[digits]= 0; |
|
return(1); |
|
} |
|
|
|
|
|
/* Converts backslash codes into single characters: |
|
\a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 , |
|
\t HT 9 , \v VT 11 , \\ \ 92 |
|
\[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code , |
|
\cX control-x (ascii(X)-64) |
|
@param upto maximum number of characters to examine for backslash. |
|
The scope of a backslash (0 to 3 characters) is not affected. |
|
@param eaten returns the difference in length between input and output |
|
@param flag bit0= only determine *eaten, do not convert |
|
bit1= allow to convert \000 to binary 0 |
|
*/ |
|
int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag) |
|
{ |
|
char *rpt, *wpt, num_text[8], wdummy[8]; |
|
unsigned int num= 0; |
|
|
|
*eaten= 0; |
|
wpt= text; |
|
for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) { |
|
if(flag & 1) |
|
wpt= wdummy; |
|
if(*rpt == '\\') { |
|
rpt++; |
|
(*eaten)++; |
|
if(*rpt == 'a') { |
|
*(wpt++)= 7; |
|
} else if(*rpt == 'b') { |
|
*(wpt++)= 8; |
|
} else if(*rpt == 'e') { |
|
*(wpt++)= 27; |
|
} else if(*rpt == 'f') { |
|
*(wpt++)= 12; |
|
} else if(*rpt == 'n') { |
|
*(wpt++)= 10; |
|
} else if(*rpt == 'r') { |
|
*(wpt++)= 13; |
|
} else if(*rpt == 't') { |
|
*(wpt++)= 9; |
|
} else if(*rpt == 'v') { |
|
*(wpt++)= 11; |
|
} else if(*rpt == '\\') { |
|
*(wpt++)= '\\'; |
|
} else if(rpt[0] >= '0' && rpt[0] <= '7' && |
|
rpt[1] >= '0' && rpt[1] <= '7' && |
|
rpt[2] >= '0' && rpt[2] <= '7') { |
|
num_text[0]= '0'; |
|
num_text[1]= *(rpt + 0); |
|
num_text[2]= *(rpt + 1); |
|
num_text[3]= *(rpt + 2); |
|
num_text[4]= 0; |
|
sscanf(num_text, "%o", &num); |
|
if((num > 0 || (flag & 2)) && num <= 255) { |
|
rpt+= 2; |
|
(*eaten)+= 2; |
|
*(wpt++)= num; |
|
} else |
|
goto not_a_code; |
|
} else if(rpt[0] == 'x' && |
|
((rpt[1] >= '0' && rpt[1] <= '9') || |
|
(rpt[1] >= 'A' && rpt[1] <= 'F') || |
|
(rpt[1] >= 'a' && rpt[1] <= 'f')) |
|
&& |
|
((rpt[2] >= '0' && rpt[2] <= '9') || |
|
(rpt[2] >= 'A' && rpt[2] <= 'F') || |
|
(rpt[2] >= 'a' && rpt[2] <= 'f')) |
|
) { |
|
num_text[0]= *(rpt + 1); |
|
num_text[1]= *(rpt + 2); |
|
num_text[2]= 0; |
|
sscanf(num_text, "%x", &num); |
|
if(num > 0 && num <= 255) { |
|
rpt+= 2; |
|
(*eaten)+= 2; |
|
*(wpt++)= num; |
|
} else |
|
goto not_a_code; |
|
} else if(*rpt == 'c') { |
|
if(rpt[1] > 64 && rpt[1] < 96) { |
|
*(wpt++)= rpt[1] - 64; |
|
rpt++; |
|
(*eaten)++; |
|
} else |
|
goto not_a_code; |
|
} else { |
|
not_a_code:; |
|
*(wpt++)= '\\'; |
|
rpt--; |
|
(*eaten)--; |
|
} |
|
} else |
|
*(wpt++)= *rpt; |
|
} |
|
*wpt= *rpt; |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_argv_bsl(int argc, char ***argv, int flag) |
|
{ |
|
int i, ret, eaten; |
|
char **new_argv= NULL; |
|
|
|
if(argc <= 0) |
|
return(0); |
|
new_argv= (char **) Smem_malloC(argc * sizeof(char *)); |
|
if(new_argv == NULL) |
|
return(-1); |
|
for(i= 0; i < argc; i++) { |
|
new_argv[i]= strdup((*argv)[i]); |
|
if(new_argv[i] == NULL) |
|
{ret= -1; goto ex;} |
|
ret= Sfile_bsl_interpreter(new_argv[i], strlen(new_argv[i]), &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
ret= 1; |
|
ex:; |
|
if(ret <= 0) { |
|
if(new_argv != NULL) |
|
free((char *) new_argv); |
|
} else |
|
*argv= new_argv; |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= only encode inside quotes |
|
bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13 |
|
bit2= encode in any case above 126 |
|
bit3= encode in any case shellsafe and name-value-safe: |
|
<=42 , 59, 60, 61, 62, 63, 92, 94, 96, >=123 |
|
*/ |
|
int Sfile_bsl_encoder(char **result, char *text, size_t text_len, int flag) |
|
{ |
|
char *rpt, *wpt; |
|
int count, sq_open= 0, dq_open= 0; |
|
|
|
count= 0; |
|
for(rpt= text; rpt - text < text_len; rpt++) { |
|
count++; |
|
if(flag & 8) { |
|
if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) || |
|
*rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123)) |
|
continue; |
|
} else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') |
|
continue; |
|
if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag & 8)) |
|
count++; |
|
else |
|
count+= 3; |
|
} |
|
(*result)= wpt= calloc(count + 1, 1); |
|
if(wpt == NULL) |
|
return(-1); |
|
for(rpt= text; rpt - text < text_len; rpt++) { |
|
if(*rpt == '\'') |
|
sq_open= !(sq_open || dq_open); |
|
if(*rpt == '"') |
|
dq_open= !(sq_open || dq_open); |
|
|
|
if(flag & 8) { |
|
if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) || |
|
*rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123)) { |
|
*(wpt++)= *rpt; |
|
continue; |
|
} |
|
} else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') { |
|
*(wpt++)= *rpt; |
|
continue; |
|
} else if( ((flag & 1) && !(sq_open || dq_open)) && |
|
!((flag & 2) && (*rpt >= 1 && * rpt <= 31 && |
|
!(*rpt == 7 || *rpt == 8 || *rpt == 9 || *rpt == 10 || |
|
*rpt == 12 || *rpt == 13))) && |
|
!((flag & 4) && (*rpt > 126 || *rpt < 0)) && |
|
!((flag & 6) && *rpt == '\\')) { |
|
*(wpt++)= *rpt; |
|
continue; |
|
} |
|
*(wpt++)= '\\'; |
|
if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag&8)) { |
|
if(*rpt == 7) |
|
*(wpt++)= 'a'; |
|
else if(*rpt == 8) |
|
*(wpt++)= 'b'; |
|
else if(*rpt == 9) |
|
*(wpt++)= 't'; |
|
else if(*rpt == 10) { |
|
*(wpt++)= 'n'; |
|
} else if(*rpt == 11) |
|
*(wpt++)= 'v'; |
|
else if(*rpt == 12) |
|
*(wpt++)= 'f'; |
|
else if(*rpt == 13) |
|
*(wpt++)= 'c'; |
|
else if(*rpt == 27) |
|
*(wpt++)= 'e'; |
|
else if(*rpt == '\\') |
|
*(wpt++)= '\\'; |
|
} else { |
|
sprintf(wpt, "%-3.3o", (unsigned int) *((unsigned char *) rpt)); |
|
wpt+= 3; |
|
} |
|
} |
|
*wpt= 0; |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_destroy_argv(int *argc, char ***argv, int flag) |
|
{ |
|
int i; |
|
|
|
if(*argc>0 && *argv!=NULL){ |
|
for(i=0;i<*argc;i++){ |
|
if((*argv)[i]!=NULL) |
|
Smem_freE((*argv)[i]); |
|
} |
|
Smem_freE((char *) *argv); |
|
} |
|
*argc= 0; |
|
*argv= NULL; |
|
return(1); |
|
} |
|
|
|
|
|
int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, |
|
int flag) |
|
/* |
|
bit0= read progname as first argument from line |
|
bit1= just release argument list argv and return |
|
bit2= abort with return(0) if incomplete quotes are found |
|
bit3= eventually prepend missing '-' to first argument read from line |
|
bit4= like bit2 but only check quote completeness, do not allocate memory |
|
bit5+6= interpretation of backslashes: |
|
0= no interpretation, leave unchanged |
|
1= only inside double quotes |
|
2= outside single quotes |
|
3= everywhere |
|
bit7= append a NULL element to argv |
|
*/ |
|
{ |
|
int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten; |
|
char *cpt,*start; |
|
char *buf= NULL; |
|
|
|
Sfile_destroy_argv(argc,argv,0); |
|
if(flag&2) |
|
{ret= 1; goto ex;} |
|
|
|
if(flag & 16) |
|
flag|= 4; |
|
bsl_mode= (flag >> 5) & 3; |
|
|
|
buf= calloc(strlen(line) + SfileadrL, 1); |
|
if(buf == NULL) |
|
{ret= -1; goto ex;} |
|
for(pass=0;pass<2;pass++) { |
|
cpt= line-1; |
|
if(!(flag&1)){ |
|
argzaehl= line_start_argc= 1; |
|
if(pass==0) |
|
maxl= strlen(progname); |
|
else |
|
strcpy((*argv)[0],progname); |
|
} else { |
|
argzaehl= line_start_argc= 0; |
|
if(pass==0) maxl= 0; |
|
} |
|
while(*(++cpt)!=0){ |
|
if(isspace(*cpt)) continue; |
|
start= cpt; |
|
buf[0]= 0; |
|
cpt--; |
|
while(*(++cpt)!=0) { |
|
if(isspace(*cpt)) break; |
|
if(*cpt=='"'){ |
|
l= cpt-start; bufl= strlen(buf); |
|
if(l>0) { |
|
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
|
if(bsl_mode >= 3) { |
|
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
l= strlen(buf); |
|
start= cpt+1; |
|
while(*(++cpt)!=0) if(*cpt=='"') break; |
|
if((flag&4) && *cpt==0) |
|
{ret= 0; goto ex;} |
|
l= cpt-start; bufl= strlen(buf); |
|
if(l>0) { |
|
strncpy(buf + bufl, start, l); |
|
buf[bufl + l]= 0; |
|
if(bsl_mode >= 1) { |
|
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
start= cpt+1; |
|
}else if(*cpt=='\''){ |
|
l= cpt-start; bufl= strlen(buf); |
|
if(l>0) { |
|
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
|
if(bsl_mode >= 3) { |
|
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
l= strlen(buf); |
|
start= cpt+1; |
|
while(*(++cpt)!=0) if(*cpt=='\'') break; |
|
if((flag&4) && *cpt==0) |
|
{ret= 0; goto ex;} |
|
l= cpt-start; bufl= strlen(buf); |
|
if(l>0) { |
|
strncat(buf,start,l);buf[bufl+l]= 0; |
|
if(bsl_mode >= 2) { |
|
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
start= cpt+1; |
|
} |
|
if(*cpt==0) break; |
|
} |
|
l= cpt-start; |
|
bufl= strlen(buf); |
|
if(l>0) { |
|
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
|
if(bsl_mode >= 3) { |
|
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
l= strlen(buf); |
|
if(pass==0){ |
|
if(argzaehl==line_start_argc && (flag&8)) |
|
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') |
|
l++; |
|
if(l>maxl) maxl= l; |
|
}else{ |
|
strcpy((*argv)[argzaehl],buf); |
|
if(argzaehl==line_start_argc && (flag&8)) |
|
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') |
|
sprintf((*argv)[argzaehl],"-%s", buf); |
|
} |
|
argzaehl++; |
|
if(*cpt==0) break; |
|
} |
|
if(pass==0){ |
|
if(flag & 16) |
|
{ret= 1; goto ex;} |
|
*argc= argzaehl; |
|
if(argzaehl>0 || (flag & 128)) { |
|
*argv= (char **) Smem_malloC((argzaehl + !!(flag & 128)) |
|
* sizeof(char *)); |
|
if(*argv==NULL) |
|
{ret= -1; goto ex;} |
|
} |
|
for(i=0;i<*argc;i++) { |
|
(*argv)[i]= (char *) Smem_malloC((maxl+1)); |
|
if((*argv)[i]==NULL) |
|
{ret= -1; goto ex;} |
|
} |
|
if(flag & 128) |
|
(*argv)[*argc]= NULL; |
|
} |
|
} |
|
ret= 1; |
|
ex: |
|
if(buf != NULL) |
|
free(buf); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= append */ |
|
int Sfile_str(char target[SfileadrL], char *source, int flag) |
|
{ |
|
int l; |
|
|
|
l= strlen(source); |
|
if(flag&1) |
|
l+= strlen(target); |
|
if(l>=SfileadrL) { |
|
fprintf(stderr, "--- Path string overflow (%d > %d). Malicious input ?\n", |
|
l,SfileadrL-1); |
|
return(0); |
|
} |
|
if(flag&1) |
|
strcat(target, source); |
|
else |
|
strcpy(target, source); |
|
return(1); |
|
} |
|
|
|
|
|
/** Combine environment variable HOME with given filename |
|
@param filename Address relative to $HOME |
|
@param fileadr Resulting combined address |
|
@param fa_size Size of array fileadr |
|
@param flag Unused yet |
|
@return 1=ok , 0=no HOME variable , -1=result address too long |
|
*/ |
|
int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag) |
|
{ |
|
char *home; |
|
|
|
strcpy(fileadr,filename); |
|
home= getenv("HOME"); |
|
if(home==NULL) |
|
return(0); |
|
if(strlen(home)+strlen(filename)+1>=fa_size) |
|
return(-1); |
|
strcpy(fileadr,home); |
|
if(filename[0]!=0){ |
|
strcat(fileadr,"/"); |
|
strcat(fileadr,filename); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/** Return a double representing seconds and microseconds since 1 Jan 1970 */ |
|
double Sfile_microtime(int flag) |
|
{ |
|
struct timeval tv; |
|
struct timezone tz; |
|
gettimeofday(&tv,&tz); |
|
return((double) (tv.tv_sec+1.0e-6*tv.tv_usec)); |
|
} |
|
|
|
|
|
int Sfile_decode_datestr(struct tm *reply, char *text, int flag) |
|
/* YYMMDD[.hhmm[ss]] */ |
|
{ |
|
int i,l; |
|
time_t current_time; |
|
struct tm *now; |
|
|
|
current_time= time(0); |
|
now= localtime(¤t_time); |
|
for(i=0;i<sizeof(struct tm);i++) |
|
((char *) reply)[i]= ((char *) now)[i]; |
|
|
|
if(text[0]<'0'|| (text[0]>'9' && text[0]<'A') || text[0]>'Z') |
|
return(0); |
|
l= strlen(text); |
|
for(i=1;i<l;i++) |
|
if(text[i]<'0'||text[i]>'9') |
|
break; |
|
if(i!=6) |
|
return(0); |
|
if(text[i]==0) |
|
goto decode; |
|
if(text[i]!='.' || (l!=11 && l!=13)) |
|
return(0); |
|
for(i++;i<l;i++) |
|
if(text[i]<'0'||text[i]>'9') |
|
break; |
|
if(i!=l) |
|
return(0); |
|
|
|
decode:; |
|
reply->tm_hour= 0; |
|
reply->tm_min= 0; |
|
reply->tm_sec= 0; |
|
i= 0; |
|
if(text[0]>='A') |
|
reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0'; |
|
else |
|
reply->tm_year= 10*(text[0]-'0')+text[1]-'0'; |
|
reply->tm_mon= 10*(text[2]-'0')+text[3]-'0'-1; |
|
reply->tm_mday= 10*(text[4]-'0')+text[5]-'0'; |
|
if(l==6) |
|
return(1); |
|
reply->tm_hour= 10*(text[7]-'0')+text[8]-'0'; |
|
reply->tm_min= 10*(text[9]-'0')+text[10]-'0'; |
|
if(l==11) |
|
return(1); |
|
reply->tm_sec= 10*(text[11]-'0')+text[12]-'0'; |
|
return(1); |
|
} |
|
|
|
#endif /* Xorriso_sfile_externaL */ |
|
|
|
|
|
/* --------------------------------- misc --------------------------------- */ |
|
|
|
|
|
int Strcmp(const void *pt1, const void *pt2) |
|
{ |
|
return(strcmp(*((char **) pt1), *((char **) pt2))); |
|
} |
|
|
|
|
|
int Sort_argv(int argc, char **argv, int flag) |
|
{ |
|
if(argc<=0) |
|
return(2); |
|
qsort(argv,(size_t) argc,sizeof(char *),Strcmp); |
|
return(1); |
|
} |
|
|
|
|
|
static int Text_to_argv(char *text, int *argc, char ***argv, int flag) |
|
{ |
|
char *npt, *cpt; |
|
int pass; |
|
|
|
*argv= NULL; |
|
*argc= 0; |
|
for(pass= 0; pass < 2; pass++) { |
|
if(pass) { |
|
if(*argc == 0) |
|
return(1); |
|
(*argv)= calloc(*argc, sizeof(char *)); |
|
if(*argv == NULL) { |
|
*argc= 0; |
|
return(-1); |
|
} |
|
*argc= 0; |
|
} |
|
for(npt= cpt= text; npt != NULL; cpt= npt + 1) { |
|
npt= strchr(cpt, '\n'); |
|
if(pass) { |
|
if(npt != NULL) |
|
*npt= 0; |
|
(*argv)[*argc]= cpt; |
|
} |
|
(*argc)++; |
|
} |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
static int Count_diffs(int argc1, char **argv1, int argc2, char **argv2, |
|
int flag) |
|
{ |
|
int count= 0, i1= 0, i2= 0, cmp, end_corr= 0; |
|
|
|
Sort_argv(argc1, argv1, 0); |
|
Sort_argv(argc2, argv2, 0); |
|
|
|
while(1) { |
|
if(i1 >= argc1) { |
|
count+= argc2 - i2 - end_corr; |
|
break; |
|
} |
|
if(i2 >= argc2) { |
|
count+= argc1 - i1 - end_corr; |
|
break; |
|
} |
|
cmp= strcmp(argv1[i1], argv2[i2]); |
|
if(cmp == 0) { |
|
end_corr= 0; |
|
i1++; |
|
i2++; |
|
} else if(cmp > 0) { |
|
count++; |
|
end_corr= 1; |
|
i2++; |
|
if(i2 < argc2 && i1 < argc1 - 1) |
|
if(strcmp(argv1[i1 + 1], argv2[i2]) == 0) { |
|
i1++; |
|
end_corr= 0; |
|
} |
|
} else { |
|
count++; |
|
end_corr= 1; |
|
i1++; |
|
if(i1 < argc1 && i2 < argc2 - 1) |
|
if(strcmp(argv2[i2 + 1], argv1[i1]) == 0) { |
|
i2++; |
|
end_corr= 0; |
|
} |
|
} |
|
} |
|
return(count); |
|
} |
|
|
|
|
|
/* |
|
@flag bit0= do not initialize *diff_count |
|
@return <0 error , 0 = mismatch , 1 = match |
|
*/ |
|
static int Compare_text_lines(char *text1, char *text2, int *diff_count, |
|
int flag) |
|
{ |
|
int ret, argc1= 0, argc2= 0; |
|
char **argv1= NULL, **argv2= NULL, *copy1= NULL, *copy2= NULL; |
|
|
|
if(!(flag & 1)) |
|
*diff_count= 0; |
|
if(text1 == NULL && text2 == NULL) |
|
return(1); |
|
if(text1 != NULL) { |
|
copy1= strdup(text1); |
|
if(copy1 == NULL) |
|
{ret= -1; goto ex;} |
|
ret= Text_to_argv(copy1, &argc1, &argv1, 0); |
|
if(ret <= 0) |
|
{ret= -1; goto ex;} |
|
} |
|
if(text2 != NULL) { |
|
copy2= strdup(text2); |
|
if(copy2 == NULL) |
|
{ret= -1; goto ex;} |
|
ret= Text_to_argv(copy2, &argc2, &argv2, 0); |
|
if(ret <= 0) |
|
{ret= -1; goto ex;} |
|
} |
|
ret= Count_diffs(argc1, argv1, argc2, argv2, 1); |
|
if(ret < 0) |
|
goto ex; |
|
*diff_count+= ret; |
|
ret= (*diff_count == 0); |
|
ex:; |
|
if(argv1 != NULL) |
|
free(argv1); |
|
if(argv2 != NULL) |
|
free(argv2); |
|
if(copy1 != NULL) |
|
free(copy1); |
|
if(copy2 != NULL) |
|
free(copy2); |
|
return ret; |
|
} |
|
|
|
|
|
/** Convert a text into a number of type double and multiply it by unit code |
|
[kmgtpe] (2^10 to 2^60) or [s] (2048). (Also accepts capital letters.) |
|
@param text Input like "42", "2k", "3.14m" or "-1g" |
|
@param flag Bitfield for control purposes: |
|
bit0= return -1 rathern than 0 on failure |
|
@return The derived double value |
|
*/ |
|
double Scanf_io_size(char *text, int flag) |
|
/* |
|
bit0= default value -1 rather than 0 |
|
*/ |
|
{ |
|
int c; |
|
double ret= 0.0; |
|
|
|
if(flag&1) |
|
ret= -1.0; |
|
if(text[0]==0) |
|
return(ret); |
|
sscanf(text,"%lf",&ret); |
|
c= text[strlen(text)-1]; |
|
if(c=='k' || c=='K') ret*= 1024.0; |
|
if(c=='m' || c=='M') ret*= 1024.0*1024.0; |
|
if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0; |
|
if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0; |
|
if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0; |
|
if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0; |
|
if(c=='s' || c=='S') ret*= 2048.0; |
|
return(ret); |
|
} |
|
|
|
|
|
int Decode_date_input_format(struct tm *erg, char *text, int flag) |
|
/* MMDDhhmm[[CC]YY][.ss]] */ |
|
{ |
|
int i,l,year; |
|
time_t current_time; |
|
struct tm *now; |
|
|
|
current_time= time(0); |
|
now= localtime(¤t_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_ecma119_format(struct tm *erg, char *text, int flag) |
|
/* YYYYMMDDhhmmsscc */ |
|
/* 2010040711405800 */ |
|
{ |
|
int i, l, num; |
|
|
|
memset(erg, 0, sizeof(*erg)); |
|
erg->tm_isdst= -1; |
|
l= strlen(text); |
|
if(l != 16) |
|
return(0); |
|
for(i= 0; i < l; i++) |
|
if(text[i] < '0' || text[i] > '9') |
|
return(0); |
|
num= 0; |
|
for(i= 0; i < 4; i++) |
|
num= num * 10 + text[i] - '0'; |
|
if(num < 1970 || num > 3000) |
|
return(0); |
|
erg->tm_year = num - 1900; |
|
erg->tm_mon= 10*(text[4]-'0')+text[5]-'0'-1; |
|
if(erg->tm_mon > 12) |
|
return(0); |
|
erg->tm_mday= 10*(text[6]-'0')+text[7]-'0'; |
|
if(erg->tm_mday > 31) |
|
return(0); |
|
erg->tm_hour= 10*(text[8]-'0')+text[9]-'0'; |
|
if(erg->tm_hour > 23) |
|
return(0); |
|
erg->tm_min= 10*(text[10]-'0')+text[11]-'0'; |
|
if(erg->tm_min > 59) |
|
return(0); |
|
erg->tm_sec= 10*(text[12]-'0')+text[13]-'0'; |
|
if(erg->tm_sec > 59) |
|
return(0); |
|
return(1); |
|
} |
|
|
|
|
|
int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag) |
|
/* 2007.11.07.225624 */ |
|
{ |
|
char buf[20]; |
|
int year,month,day,hour= 0,minute= 0,second= 0, i, l, mem; |
|
|
|
memset(erg, 0, sizeof(*erg)); |
|
erg->tm_isdst= -1; |
|
|
|
l= strlen(code); |
|
if(l>17 || l<10) |
|
return(0); |
|
strcpy(buf, code); |
|
for(i= 0; buf[i]!=0 && i<4; i++) |
|
if(!isdigit(buf[i])) |
|
return(0); |
|
if(buf[4]!='.') |
|
return(0); |
|
buf[4]= 0; |
|
sscanf(buf, "%d", &year); |
|
if(year<1900 || year>3000) |
|
return(0); |
|
if(!(isdigit(buf[5]) && isdigit(buf[6]) && buf[7]=='.')) |
|
return(0); |
|
buf[7]= 0; |
|
sscanf(buf+5, "%d", &month); |
|
if(month<1 || month>12) |
|
return(0); |
|
if(!(isdigit(buf[8]) && isdigit(buf[9]) && (buf[10]=='.' || buf[10]==0))) |
|
return(0); |
|
buf[10]= 0; |
|
sscanf(buf+8, "%d", &day); |
|
if(day<1 || day>31) |
|
return(0); |
|
if(l==10) |
|
goto done; |
|
if(!(isdigit(buf[11]) && isdigit(buf[12]) && |
|
(isdigit(buf[13]) || buf[13]==0))) |
|
return(0); |
|
mem= buf[13]; |
|
buf[13]= 0; |
|
sscanf(buf+11, "%d", &hour); |
|
buf[13]= mem; |
|
if(hour<0 || hour>23) |
|
return(0); |
|
if(l==13) |
|
goto done; |
|
if(!(isdigit(buf[13]) && isdigit(buf[14]) && |
|
(isdigit(buf[15]) || buf[15]==0))) |
|
return(0); |
|
mem= buf[15]; |
|
buf[15]= 0; |
|
sscanf(buf+13, "%d", &minute); |
|
buf[15]= mem; |
|
if(minute<0 || minute>59) |
|
return(0); |
|
if(l==15) |
|
goto done; |
|
if(!(isdigit(buf[15]) && isdigit(buf[16]) && buf[17]==0)) |
|
return(0); |
|
sscanf(buf+15, "%d", &second); |
|
if(second<0 || second>59) |
|
return(0); |
|
|
|
done:; |
|
erg->tm_year= year-1900; |
|
erg->tm_mon= month-1; |
|
erg->tm_mday= day; |
|
erg->tm_hour= hour; |
|
erg->tm_min= minute; |
|
erg->tm_sec= second; |
|
return(1); |
|
} |
|
|
|
|
|
time_t Decode_timestring(char *code, time_t *date, int flag) |
|
{ |
|
char *cpt,scale_chr; |
|
double value,seconds; |
|
struct tm result_tm; |
|
int seconds_valid= 0; |
|
|
|
*date= 0; |
|
cpt= code; |
|
if(code[0]=='-' || code[0]=='+' || code[0]=='=' || code[0]=='@'){ |
|
if(code[1]==0) |
|
return(0); |
|
if(!isdigit(code[1])) |
|
return(0); |
|
value= -1; |
|
if(code[0]=='=' || code[0]=='@') { |
|
seconds= 0; |
|
sscanf(code+1,"%lf",&value); |
|
} else { |
|
seconds= time(NULL); |
|
sscanf(code,"%lf",&value); |
|
} |
|
scale_chr= code[strlen(code)-1]; |
|
if(isalpha(scale_chr)) |
|
scale_chr= tolower(scale_chr); |
|
if (scale_chr=='s') seconds+= 1.0*value; |
|
else if(scale_chr=='h') seconds+= 3600.0*value; |
|
else if(scale_chr=='d') seconds+= 86400.0*value; |
|
else if(scale_chr=='w') seconds+= 86400.0*7.0*value; |
|
else if(scale_chr=='m') seconds+= 86400.0*31.0*value; |
|
else if(scale_chr=='y') seconds+= 86400.0*(365.25*value+1.0); |
|
else seconds+= 1.0*value; |
|
seconds_valid= 1; |
|
goto completed; |
|
} else if(Sfile_decode_datestr(&result_tm,code,0)>0) { |
|
/* YYMMDD[.hhmm[ss]] */ |
|
result_tm.tm_isdst= -1; |
|
seconds= mktime(&result_tm); |
|
seconds_valid= 1; |
|
goto completed; |
|
} else if(Decode_date_input_format(&result_tm,code,0)>0) { |
|
/* MMDDhhmm[[CC]YY][.ss]] */ |
|
result_tm.tm_isdst= -1; |
|
seconds= mktime(&result_tm); |
|
seconds_valid= 1; |
|
goto completed; |
|
} else if(Decode_xorriso_timestamp(&result_tm, code, 0)>0) { |
|
/* 2007.11.07.225624 */ |
|
seconds= mktime(&result_tm); |
|
seconds_valid= 1; |
|
goto completed; |
|
} else if(Decode_date_output_format(&result_tm, code, 0)>0) { |
|
/* Thu Nov 8 09:07:50 CET 2007 */; |
|
/* Sat, 03 Nov 2007 08:58:30 +0100 */; |
|
/* Nov 7 23:24 */; |
|
seconds= mktime(&result_tm); |
|
seconds_valid= 1; |
|
goto completed; |
|
} else if(Decode_ecma119_format(&result_tm, code, 0)>0) { |
|
/* YYYYMMDDhhmmsscc */ |
|
/* 2010040711405800 */ |
|
seconds= mktime(&result_tm); |
|
seconds_valid= 1; |
|
goto completed; |
|
} |
|
return(0); |
|
completed:; |
|
if(!seconds_valid) |
|
return(0); |
|
*date= seconds; |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0=with year and seconds |
|
bit1-3= form |
|
0= ls -l format |
|
1= timestamp format YYYY.MM.DD.hhmmss |
|
2= Wdy Mon Day hh:mm:ss Year |
|
3= Mon Day hh:mm:ss Year |
|
4= YYMMDD.hhmmss |
|
*/ |
|
char *Ftimetxt(time_t t, char timetext[40], int flag) |
|
{ |
|
char *rpt; |
|
struct tm tms, *tmpt; |
|
static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
|
static char days[7][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; |
|
int form; |
|
|
|
form= (flag>>1)&7; |
|
tmpt= localtime_r(&t, &tms); |
|
rpt= timetext; |
|
rpt[0]= 0; |
|
if(tmpt==0) |
|
sprintf(rpt+strlen(rpt), "%12.f", (double) t); |
|
else if (form==1) |
|
sprintf(rpt+strlen(rpt), "%4.4d.%2.2d.%2.2d.%2.2d%2.2d%2.2d", |
|
1900+tms.tm_year, tms.tm_mon+1, tms.tm_mday, |
|
tms.tm_hour, tms.tm_min, tms.tm_sec); |
|
else if (form==2) |
|
sprintf(rpt+strlen(rpt), "%s %s %2.2d %2.2d:%2.2d:%2.2d %4.4d", |
|
days[tms.tm_wday], months[tms.tm_mon], tms.tm_mday, |
|
tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year); |
|
else if (form==3) |
|
sprintf(rpt+strlen(rpt), "%s %2.2d %2.2d:%2.2d:%2.2d %4.4d", |
|
months[tms.tm_mon], tms.tm_mday, |
|
tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year); |
|
else if (form == 4) { |
|
if(tms.tm_year>99) |
|
sprintf(rpt+strlen(rpt), "%c", 'A' + (tms.tm_year - 100) / 10); |
|
else |
|
sprintf(rpt+strlen(rpt), "%c", '0' + tms.tm_year / 10); |
|
sprintf(rpt+strlen(rpt), "%1.1d%2.2d%2.2d.%2.2d%2.2d%2.2d", |
|
tms.tm_year % 10, tms.tm_mon + 1, tms.tm_mday, |
|
tms.tm_hour, tms.tm_min, tms.tm_sec); |
|
} else if (flag&1) |
|
sprintf(rpt+strlen(rpt), "%2d %3s %4.4d %2.2d:%2.2d:%2.2d", |
|
tms.tm_mday, months[tms.tm_mon], 1900+tms.tm_year, |
|
tms.tm_hour, tms.tm_min, tms.tm_sec); |
|
else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0) |
|
sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d", |
|
months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); |
|
else |
|
sprintf(rpt+strlen(rpt), "%3s %2d %4.4d", |
|
months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year); |
|
return(timetext); |
|
} |
|
|
|
|
|
/* @param flag bit0= single letters */ |
|
char *Ftypetxt(mode_t st_mode, int flag) |
|
{ |
|
if(flag&1) |
|
goto single_letters; |
|
if(S_ISDIR(st_mode)) |
|
return("directory"); |
|
else if(S_ISREG(st_mode)) |
|
return("regular_file"); |
|
else if(S_ISLNK(st_mode)) |
|
return("symbolic_link"); |
|
else if(S_ISBLK(st_mode)) |
|
return("block_device"); |
|
else if(S_ISCHR(st_mode)) |
|
return("char_device"); |
|
else if(S_ISFIFO(st_mode)) |
|
return("name_pipe"); |
|
else if(S_ISSOCK(st_mode)) |
|
return("unix_socket"); |
|
return("unknown"); |
|
single_letters:; |
|
if(S_ISDIR(st_mode)) |
|
return("d"); |
|
else if(S_ISREG(st_mode)) |
|
return("-"); |
|
else if(S_ISLNK(st_mode)) |
|
return("l"); |
|
else if(S_ISBLK(st_mode)) |
|
return("b"); |
|
else if(S_ISCHR(st_mode)) |
|
return("c"); |
|
else if(S_ISFIFO(st_mode)) |
|
return("p"); |
|
else if(S_ISSOCK(st_mode)) |
|
return("s"); |
|
return("?"); |
|
} |
|
|
|
|
|
int Wait_for_input(int fd, int microsec, int flag) |
|
{ |
|
struct timeval wt; |
|
fd_set rds,wts,exs; |
|
int ready; |
|
|
|
FD_ZERO(&rds); |
|
FD_ZERO(&wts); |
|
FD_ZERO(&exs); |
|
FD_SET(fd,&rds); |
|
FD_SET(fd,&exs); |
|
wt.tv_sec= microsec/1000000; |
|
wt.tv_usec= microsec%1000000; |
|
ready= select(fd+1,&rds,&wts,&exs,&wt); |
|
if(ready<=0) |
|
return(0); |
|
if(FD_ISSET(fd,&exs)) |
|
return(-1); |
|
if(FD_ISSET(fd,&rds)) |
|
return(1); |
|
return(0); |
|
} |
|
|
|
|
|
int System_uname(char **sysname, char **release, char **version, |
|
char **machine, int flag) |
|
{ |
|
int ret; |
|
static struct utsname uts; |
|
static int initialized= 0; |
|
|
|
if(initialized == 0) { |
|
ret= uname(&uts); |
|
if(ret != 0) |
|
initialized = -1; |
|
} |
|
if(initialized == -1) |
|
return(0); |
|
if(sysname != NULL) |
|
*sysname= uts.sysname; |
|
if(release != NULL) |
|
*release= uts.release; |
|
if(version != NULL) |
|
*version= uts.version; |
|
if(machine != NULL) |
|
*machine= uts.machine; |
|
return(1); |
|
} |
|
|
|
/* ------------------------------------------------------------------------ */ |
|
|
|
|
|
#ifndef Xorriso_sregex_externaL |
|
|
|
#ifndef Smem_malloC |
|
#define Smem_malloC malloc |
|
#endif |
|
#ifndef Smem_freE |
|
#define Smem_freE free |
|
#endif |
|
|
|
|
|
int Sregex_string_cut(char **handle, char *text, int len, int flag) |
|
/* |
|
bit0= append (text!=NULL) |
|
*/ |
|
{ |
|
int l=0; |
|
char *old_handle; |
|
|
|
if((flag&1)&&*handle!=NULL) |
|
l+= strlen(*handle); |
|
old_handle= *handle; |
|
if(text!=NULL) { |
|
l+= len; |
|
*handle= TSOB_FELD(char,l+1); |
|
if(*handle==NULL) { |
|
*handle= old_handle; |
|
return(0); |
|
} |
|
if((flag&1) && old_handle!=NULL) |
|
strcpy(*handle,old_handle); |
|
else |
|
(*handle)[0]= 0; |
|
if(len>0) |
|
strncat(*handle,text,len); |
|
} else { |
|
*handle= NULL; |
|
} |
|
if(old_handle!=NULL) |
|
Smem_freE(old_handle); |
|
return(1); |
|
} |
|
|
|
|
|
int Sregex_string(char **handle, char *text, int flag) |
|
/* |
|
bit0= append (text!=NULL) |
|
*/ |
|
{ |
|
int ret,l=0; |
|
|
|
if(text!=NULL) |
|
l= strlen(text); |
|
|
|
/* #define Sregex_looking_for_contenT 1 */ |
|
#ifdef Sregex_looking_for_contenT |
|
/* a debugging point if a certain text content has to be caught */ |
|
if(text!=NULL) |
|
if(strcmp(text,"clear")==0) |
|
ret= 0; |
|
#endif |
|
|
|
ret= Sregex_string_cut(handle,text,l,flag&1); |
|
return(ret); |
|
} |
|
|
|
|
|
/* |
|
vars[][0] points to the variable names, vars[][1] to their contents. |
|
start marks the begin of variable names. It must be non-empty. esc before |
|
start disables this meaning. start and esc may be equal but else they must |
|
have disjoint character sets. |
|
end marks the end of a variable name. It may be empty but if non-empty it |
|
must not appear in vars[][0]. |
|
@param flag bit0= Substitute unknown variables by empty text |
|
(else copy start,name,end unaltered to result). |
|
Parameter end must be non-empty for that. |
|
*/ |
|
int Sregex_resolve_var(char *form, char *vars[][2], int num_vars, |
|
char *start, char *end, char *esc, |
|
char *result, int result_size, int flag) |
|
{ |
|
int l_e, l_v, l_s, l_esc, i, start_equals_esc; |
|
char *rpt, *wpt, *spt, *npt, *ept; |
|
|
|
if(start[0] == 0) /* It is not allowed to have no start marker */ |
|
return(-1); |
|
l_s= strlen(start); |
|
l_e= strlen(end); |
|
l_esc= strlen(esc); |
|
start_equals_esc= !strcmp(start, esc); |
|
rpt= form; |
|
wpt= result; |
|
wpt[0]= 0; |
|
while(1) { |
|
|
|
/* look for start mark */ |
|
spt= strstr(rpt, start); |
|
if(spt == NULL) { |
|
if((wpt - result) + strlen(rpt) >= result_size) |
|
return(0); |
|
strcpy(wpt, rpt); |
|
wpt+= strlen(wpt); |
|
break; |
|
} |
|
|
|
/* copy cleartext part up to next variable */ |
|
if((wpt - result) + (spt - rpt) >= result_size) |
|
return(0); |
|
strncpy(wpt, rpt, spt - rpt); |
|
wpt+= spt - rpt; |
|
*wpt= 0; |
|
rpt= spt; |
|
npt= spt + l_s; |
|
|
|
/* handle eventual escape */ |
|
if(start_equals_esc) { |
|
if(strncmp(spt + l_s, esc, l_esc) == 0) { |
|
/* copy esc and start */ |
|
if((wpt - result) + l_esc + l_s >= result_size) |
|
return(0); |
|
strncpy(wpt, spt, l_esc + l_s); |
|
wpt+= l_esc + l_s; |
|
rpt+= l_esc + l_s; |
|
*wpt= 0; |
|
continue; |
|
} |
|
} else { |
|
/* escape would be already copied */ |
|
if(l_esc > 0 && spt - form >= l_esc) { |
|
if(strncmp(spt - l_esc, esc, l_esc) == 0) { |
|
/* copy start */ |
|
if((wpt - result) + l_s >= result_size) |
|
return(0); |
|
strncpy(wpt, spt, l_s); |
|
wpt+= l_s; |
|
rpt+= l_s; |
|
*wpt= 0; |
|
continue; |
|
} |
|
} |
|
} |
|
|
|
/* Memorize eventual end mark for default handling */; |
|
ept= NULL; |
|
if(l_e > 0) |
|
ept= strstr(npt, end); |
|
|
|
/* Look for defined variable name */ |
|
for(i = 0; i < num_vars; i++) { |
|
if(strncmp(npt, vars[i][0], strlen(vars[i][0])) == 0 |
|
&& (l_e == 0 || strncmp(npt + strlen(vars[i][0]), end, l_e) == 0)) |
|
break; |
|
} |
|
if(i < num_vars) { |
|
/* substitute found variable */ |
|
l_v= strlen(vars[i][0]); |
|
if((wpt - result) + strlen(vars[i][1]) >= result_size) |
|
return(0); |
|
strcpy(wpt, vars[i][1]); |
|
rpt= npt + strlen(vars[i][0]) + l_e; |
|
} else if((flag & 1) && ept != NULL) { |
|
/* skip up to end mark */ |
|
rpt= ept + l_e; |
|
} else if(ept != NULL) { |
|
/* copy start,name,end */ |
|
if((wpt - result) + (ept - rpt) + l_e >= result_size) |
|
return(0); |
|
strncpy(wpt, rpt, (ept - rpt) + l_e); |
|
rpt= ept + l_e; |
|
} else { |
|
/* copy start marker only */ |
|
if((wpt - result) + l_s >= result_size) |
|
return(0); |
|
strncpy(wpt, rpt, l_s); |
|
rpt= rpt + l_s; |
|
} |
|
wpt+= strlen(wpt); |
|
*wpt= 0; |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= only test expression whether compilable |
|
*/ |
|
int Sregex_match(char *pattern, char *text, int flag) |
|
{ |
|
int ret; |
|
char re_text[2*SfileadrL]; |
|
regex_t re; |
|
regmatch_t match[1]; |
|
|
|
Xorriso__bourne_to_reg(pattern, re_text, 0); |
|
ret= regcomp(&re, re_text, 0); |
|
if(ret != 0) |
|
return(-1); |
|
if(flag & 1) { |
|
regfree(&re); |
|
return(1); |
|
} |
|
ret= regexec(&re, text, 1, match, 0); |
|
regfree(&re); |
|
if(ret != 0) |
|
return(0); |
|
return(1); |
|
} |
|
|
|
|
|
#endif /* Xorriso_sregex_externaL */ |
|
|
|
|
|
|
|
/* @param flag bit0= append to out_text rather than overwrite it |
|
*/ |
|
char *Text_shellsafe(char *in_text, char *out_text, int flag) |
|
{ |
|
int l,i,ol= 0,w=0; |
|
|
|
if(flag&1) |
|
ol= w= strlen(out_text); |
|
/* enclose everything by hard quotes */ |
|
l= strlen(in_text); |
|
out_text[w++]= '\''; |
|
for(i=0;i<l;i++){ |
|
if(in_text[i]=='\''){ |
|
if(w+7>5*SfileadrL+ol) |
|
goto overflow; |
|
/* escape hard quote within the text */ |
|
out_text[w++]= '\''; |
|
out_text[w++]= '"'; |
|
out_text[w++]= '\''; |
|
out_text[w++]= '"'; |
|
out_text[w++]= '\''; |
|
} else { |
|
if(w+3>5*SfileadrL) { |
|
overflow:; |
|
strncpy(out_text, "'xorriso: TEXT MUCH TOO LONG ... ",33); |
|
break; |
|
} |
|
out_text[w++]= in_text[i]; |
|
} |
|
} |
|
out_text[w++]= '\''; |
|
out_text[w++]= 0; |
|
return(out_text); |
|
} |
|
|
|
|
|
#ifndef Xorriso_fileliste_externaL |
|
|
|
/* ??? ts A71006 : Is this compatible with mkisofs pathspecs ? |
|
I dimly remember so */ |
|
|
|
int Fileliste__target_source_limit(char *line, char sep, char **limit_pt, |
|
int flag) |
|
{ |
|
char *npt; |
|
|
|
for(npt= line;*npt!=0;npt++) { |
|
if(*npt=='\\') { |
|
if(*(npt+1)!=0) |
|
npt++; |
|
continue; |
|
} |
|
if(*npt=='=') |
|
break; |
|
} |
|
if(*npt==0) |
|
npt= NULL; |
|
(*limit_pt)= npt; |
|
return(npt!=NULL); |
|
} |
|
|
|
#endif /* ! Xorriso_fileliste_externaL */ |
|
|
|
|
|
/* ------------------------------------------------------------------------ */ |
|
/* DirseQ : crawl along a directory's content list */ |
|
|
|
static int Dirseq_buffer_sizE= 100; |
|
|
|
struct DirseQ { |
|
char adr[SfileadrL]; |
|
DIR *dirpt; |
|
int count; |
|
char **buffer; |
|
int buffer_size; |
|
int buffer_fill; |
|
int buffer_rpt; |
|
|
|
struct DirseQ *next; |
|
}; |
|
|
|
int Dirseq_destroy(struct DirseQ **o, int flag); |
|
int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count, |
|
int max_replies, int flag); |
|
|
|
|
|
int Dirseq_new(struct DirseQ **o, char *adr, int flag) |
|
/* |
|
bit0= with non-fatal errors do not complain about failed opendir() |
|
*/ |
|
{ |
|
int ret,i,severe_error; |
|
struct DirseQ *m; |
|
|
|
m= *o= TSOB_FELD(struct DirseQ,1); |
|
if(m==NULL) |
|
return(-1); |
|
m->adr[0]= 0; |
|
m->dirpt= NULL; |
|
m->count= 0; |
|
m->buffer= NULL; |
|
m->buffer_size= 0; |
|
m->buffer_fill= 0; |
|
m->buffer_rpt= 0; |
|
m->next= NULL; |
|
if(Sfile_str(m->adr, adr, 0)<=0) |
|
{ret= 0; goto failed;} |
|
m->buffer= TSOB_FELD(char *,Dirseq_buffer_sizE); |
|
if(m->buffer==NULL) |
|
{ret= -1; goto failed;} |
|
m->buffer_size= Dirseq_buffer_sizE; |
|
for(i= 0;i<m->buffer_size;i++) |
|
m->buffer[i]= NULL; |
|
if(adr[0]==0) |
|
m->dirpt= opendir("."); |
|
else |
|
m->dirpt= opendir(adr); |
|
if(m->dirpt==NULL) { |
|
severe_error= (errno && errno!=ENOENT && errno!=EACCES && errno!=ENOTDIR); |
|
if(severe_error || !(flag&1)) |
|
fprintf(stderr,"opendir(%s) failed : %s\n",adr,strerror(errno)); |
|
ret= -severe_error; |
|
goto failed; |
|
} |
|
return(1); |
|
failed:; |
|
Dirseq_destroy(o,0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Dirseq_destroy(struct DirseQ **o, int flag) |
|
{ |
|
int i; |
|
|
|
if(*o==NULL) |
|
return(0); |
|
if((*o)->dirpt!=NULL) |
|
closedir((*o)->dirpt); |
|
if((*o)->buffer!=NULL) { |
|
for(i=0;i<(*o)->buffer_size;i++) |
|
if((*o)->buffer[i]!=NULL) |
|
free((*o)->buffer[i]); |
|
free((char *) (*o)->buffer); |
|
} |
|
free((char *) *o); |
|
(*o)= NULL; |
|
return(1); |
|
} |
|
|
|
|
|
int Dirseq_set_next(struct DirseQ *o, struct DirseQ *next, int flag) |
|
{ |
|
o->next= next; |
|
return(1); |
|
} |
|
|
|
|
|
int Dirseq_get_next(struct DirseQ *o, struct DirseQ **next, int flag) |
|
{ |
|
*next= o->next; |
|
return(1); |
|
} |
|
|
|
|
|
int Dirseq_get_adr(struct DirseQ *o, char **adrpt, int flag) |
|
{ |
|
*adrpt= o->adr; |
|
return(1); |
|
} |
|
|
|
|
|
int Dirseq_rewind(struct DirseQ *o, int flag) |
|
{ |
|
rewinddir(o->dirpt); |
|
return(1); |
|
} |
|
|
|
|
|
int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag) |
|
/* |
|
flag: |
|
bit0= permission to use buffer |
|
bit1= do not increment counter |
|
bit2= ignore buffer in any case |
|
bit3= do not exclude '.' and '..' |
|
bit4= sort buffer |
|
bit5= sort only incomplete last buffer |
|
return: |
|
<0 error |
|
0= no more entries available |
|
1= ok, reply is valid |
|
*/ |
|
{ |
|
int ret; |
|
struct dirent *entry; |
|
char *name; |
|
|
|
static int override_flag_0= 0,override_flag_1= 32; |
|
flag= (flag&~override_flag_0)|override_flag_1; |
|
|
|
if((flag&1) && o->buffer_rpt>=o->buffer_fill) { |
|
/* permission to buffer and buffer empty : load a buffer */ |
|
ret= Dirseq_next_adrblock(o,o->buffer,&(o->buffer_fill), |
|
o->buffer_size,2|4|(flag&16)); |
|
if(ret<=0) |
|
return(ret); |
|
o->buffer_rpt= 0; |
|
if((flag&32) && o->buffer_fill<o->buffer_size && o->buffer_fill>0) |
|
Sort_argv(o->buffer_fill,o->buffer,0); |
|
} |
|
if(o->buffer_rpt<o->buffer_fill && !(flag&4)) { |
|
ret= Sfile_str(reply,o->buffer[o->buffer_rpt],0); |
|
Sregex_string(&(o->buffer[o->buffer_rpt]),NULL,0); |
|
if(ret<=0) |
|
return(-1); |
|
(o->buffer_rpt)++; |
|
if(!(flag&2)) |
|
o->count++; |
|
return(1); |
|
} |
|
do { |
|
entry= readdir(o->dirpt); |
|
if(entry==NULL) { |
|
/* >>> how to distinguish error from EOF , do i need a (FILE *) ? */ |
|
return(0); |
|
} |
|
if(strlen(entry->d_name)>=SfileadrL) { |
|
fprintf(stderr,"--- oversized directory entry (number %d) :\n %s", |
|
o->count+1,entry->d_name); |
|
return(-1); |
|
} |
|
name= entry->d_name; |
|
if(flag&8) |
|
break; |
|
/* skip "." and ".." */ |
|
} while(name[0]=='.' && ((name[1]=='.' && name[2]==0) || name |