libisoburn/xorriso/misc_funct.c

1223 lines
27 KiB
C

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This file contains the miscellaneous helper functions of xorriso.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#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 <sys/time.h>
#include <time.h>
#include <sys/utsname.h>
#include "sfile.h"
#include "misc_funct.h"
/* --------------------------------- 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
*/
int Compare_text_lines(char *text1, char *text2, int *diff_count, int flag)
{
int ret, argc1= 0, argc2= 0;
char **argv1= NULL, **argv2= NULL, *copy1= NULL, *copy2= NULL;
if(!(flag & 1))
*diff_count= 0;
if(text1 == NULL && text2 == NULL)
return(1);
if(text1 != NULL) {
copy1= strdup(text1);
if(copy1 == NULL)
{ret= -1; goto ex;}
ret= Text_to_argv(copy1, &argc1, &argv1, 0);
if(ret <= 0)
{ret= -1; goto ex;}
}
if(text2 != NULL) {
copy2= strdup(text2);
if(copy2 == NULL)
{ret= -1; goto ex;}
ret= Text_to_argv(copy2, &argc2, &argv2, 0);
if(ret <= 0)
{ret= -1; goto ex;}
}
ret= Count_diffs(argc1, argv1, argc2, argv2, 1);
if(ret < 0)
goto ex;
*diff_count+= ret;
ret= (*diff_count == 0);
ex:;
if(argv1 != NULL)
free(argv1);
if(argv2 != NULL)
free(argv2);
if(copy1 != NULL)
free(copy1);
if(copy2 != NULL)
free(copy2);
return ret;
}
/** Convert a text into a number of type double and multiply it by unit code
[kmgtpe] (2^10 to 2^60) or [s] (2048). (Also accepts capital letters.)
@param text Input like "42", "2k", "3.14m" or "-1g"
@param flag Bitfield for control purposes:
bit0= return -1 rathern than 0 on failure
@return The derived double value
*/
double Scanf_io_size(char *text, int flag)
/*
bit0= default value -1 rather than 0
*/
{
int c;
double ret= 0.0;
if(flag&1)
ret= -1.0;
if(text[0]==0)
return(ret);
sscanf(text,"%lf",&ret);
c= text[strlen(text)-1];
if(c=='k' || c=='K') ret*= 1024.0;
if(c=='m' || c=='M') ret*= 1024.0*1024.0;
if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0;
if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0;
if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0;
if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0;
if(c=='s' || c=='S') ret*= 2048.0;
return(ret);
}
int Decode_date_input_format(struct tm *erg, char *text, int flag)
/* MMDDhhmm[[CC]YY][.ss]] */
{
int i,l,year;
time_t current_time;
struct tm *now;
current_time= time(0);
now= localtime(&current_time);
for(i= 0; i < (int) 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) + (int) 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) + (int) 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= NULL;
regex_t re;
regmatch_t match[1];
re_text= TSOB_FELD(char, 2 * SfileadrL);
if(re_text == NULL)
{ret= -1; goto ex;}
Xorriso__bourne_to_reg(pattern, re_text, 0);
ret= regcomp(&re, re_text, 0);
if(ret != 0)
{ret= -1; goto ex;}
if(flag & 1) {
regfree(&re);
{ret= 1; goto ex;}
}
ret= regexec(&re, text, 1, match, 0);
regfree(&re);
if(ret != 0)
goto ex;
ret= 1;
ex:;
if(re_text != NULL)
free(re_text);
return(ret);
}
#endif /* Xorriso_sregex_externaL */
/* @param flag bit0= append to out_text rather than overwrite it
bit1= length limit is 10 * SfileadrL rather than 5 *
*/
char *Text_shellsafe(char *in_text, char *out_text, int flag)
{
int l,i,w=0, limit= 5 * SfileadrL;
if(flag&1)
w= strlen(out_text);
if(flag & 2)
limit= 10 * SfileadrL;
/* 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 > limit)
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 > limit) {
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);
}
int Hex_to_bin(char *hex,
int bin_size, int *bin_count, unsigned char *bin_data, int flag)
{
int i, l, acc;
l= strlen(hex);
if(l % 2 || l == 0)
return(-1); /* malformed */
*bin_count= 0;
for(i= 0; i < l; i+= 2) {
if(hex[i] >= '0' && hex[i] <= '9')
acc= (hex[i] - '0') << 4;
else if(hex[i] >= 'A' && hex[i] <= 'F')
acc= (hex[i] - 'A' + 10) << 4;
else if(hex[i] >= 'a' && hex[i] <= 'f')
acc= (hex[i] - 'a' + 10) << 4;
else
return(-1);
if(hex[i + 1] >= '0' && hex[i + 1] <= '9')
acc|= (hex[i + 1] - '0');
else if(hex[i + 1] >= 'A' && hex[i + 1] <= 'F')
acc|= (hex[i + 1] - 'A' + 10);
else if(hex[i + 1] >= 'a' && hex[i + 1] <= 'f')
acc|= (hex[i + 1] - 'a' + 10);
else
return(-1);
if(*bin_count >= bin_size)
return(0); /* overflow */
bin_data[*bin_count]= acc;
(*bin_count)++;
}
return(1);
}
#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 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));
}
#endif /* ! Xorriso_fileliste_externaL */
int Xorriso__hide_mode(char *mode, int flag)
{
if(strcmp(mode, "on") == 0)
return(1 | 2);
else if(strcmp(mode, "iso_rr") == 0)
return(1);
else if(strcmp(mode, "joliet") == 0)
return(2);
else if(strcmp(mode, "off") == 0)
return(0);
return(-1);
}
char *Xorriso__hide_mode_text(int hide_mode, int flag)
{
switch(hide_mode & 3) {
case 0:
return "off";
case 1:
return "iso_rr";
case 2:
return "joliet";
case 3:
return "on";
}
return "invalid";
}