libisoburn/xorriso/misc_funct.c

1468 lines
33 KiB
C

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2024 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) or [d] (512).
(Also accepts capital letters.)
@param text Input like "42", "2k", "3.14m" or "-1g"
@param flag Bitfield for control purposes:
bit0= return -1 rather 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;
if(c=='d' || c=='D') ret*= 512.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[LOC] */
/* 2010040711405800 */
{
int i, l, num, utc= 1;
struct tm norm_tm;
memset(erg, 0, sizeof(*erg));
erg->tm_isdst= -1;
l= strlen(text);
if(l == 19) {
if(strcmp(text + 16, "LOC") != 0)
return(0);
utc= 0;
l= 16;
}
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);
/* Let mktime(3) compute erg->tm_wday and erg->tm_yday */
memcpy(&norm_tm, erg, sizeof(struct tm));
mktime(&norm_tm);
erg->tm_wday= norm_tm.tm_wday;
erg->tm_yday= norm_tm.tm_yday;
return(1 + !utc);
}
int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag)
/* 2007.11.07.225624 or 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] != '.' && 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] == '.' || 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]=='_' || 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);
}
int Decode_timestring(char *code, time_t *date, int flag)
{
char scale_chr;
double value,seconds;
struct tm result_tm;
int seconds_valid= 0, ret;
*date= 0;
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((ret= Decode_ecma119_format(&result_tm, code, 0)) > 0) {
/* YYYYMMDDhhmmsscc[LOC] */
/* 2010040711405800LOC */
seconds= mktime(&result_tm);
if(ret == 1) {
#ifdef HAVE_TM_GMTOFF
seconds+= result_tm.tm_gmtoff;
#else
if(result_tm.tm_isdst < 0)
result_tm.tm_isdst = 0;
#ifndef Libburnia_timezonE
#define Libburnia_timezonE timezone
#endif
seconds-= Libburnia_timezonE - result_tm.tm_isdst * 3600;
#endif
}
seconds_valid= 1;
goto completed;
}
return(0);
completed:;
if(!seconds_valid)
return(0);
*date= seconds;
return(1);
}
int Decode_ecma119_17byte(time_t *seconds, char *code, int flag)
/* YYYYMMDDhhmmssccN (N = 15 minutes Offset from GMT: -48 West to +52 east) */
{
int ret;
char digits[17];
struct tm erg;
*seconds= 0;
strncpy(digits, code, 16);
digits[16]= 0;
ret= Decode_ecma119_format(&erg, digits, 0);
if(ret <= 0)
return(ret);
*seconds= mktime(&erg);
*seconds-= (int) code[16] * 60 * 15;
/* Convert from local time to GMT */
#ifdef HAVE_TM_GMTOFF
*seconds+= erg.tm_gmtoff;
#else
if(erg.tm_isdst < 0)
erg.tm_isdst = 0;
#ifndef Libburnia_timezonE
#define Libburnia_timezonE timezone
#endif
*seconds-= Libburnia_timezonE - erg.tm_isdst * 3600;
#endif
return(1);
}
int Encode_ecma119_17byte(time_t seconds, char *centi_seconds,
char *code, int flag)
{
struct tm *gmt;
gmt= gmtime(&seconds);
if(gmt == NULL)
return(0);
sprintf(code, "%4.4d", 1900 + gmt->tm_year);
sprintf(code + 4, "%2.2d", gmt->tm_mon + 1);
sprintf(code + 6, "%2.2d", gmt->tm_mday);
sprintf(code + 8, "%2.2d", gmt->tm_hour);
sprintf(code + 10, "%2.2d", gmt->tm_min);
sprintf(code + 12, "%2.2d", gmt->tm_sec);
strncpy(code + 14, centi_seconds, 2);
code[16]= code[17]= 0;
return(1);
}
/* flag: bit0= format to xorriso timestamp in local time
bit1= truncate centiseconds (with !bit0)
*/
int Untimezone_ecma119_17byte(char *code, int flag)
{
int ret;
time_t seconds;
char new_code[18];
if(code[16] == 0 && !(flag & 1))
return(1);
ret= Decode_ecma119_17byte(&seconds, code, 0);
if(ret <= 0)
return(ret);
if(flag & 1) {
/* xorriso timestamp format in local time */
if(Ftimetxt(seconds, new_code, 1 | 2) == NULL)
return(0);
} else {
/* ECMA-119 17 byte format in GMT */
ret= Encode_ecma119_17byte(seconds, flag & 2 ? "00" : code + 14, new_code,
0);
if(ret <= 0)
return(ret);
}
strcpy(code, new_code);
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, 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_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 */
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)
{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:;
strcpy(out_text, "'xorriso: TEXT MUCH TOO LONG ... '");
return(out_text);
}
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 < 2 * bin_size) || l == 0)
return(-1); /* malformed */
*bin_count= 0;
for(i= 0; i < l; i+= 2) {
if(*bin_count >= bin_size)
return(0); /* overflow */
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);
bin_data[*bin_count]= acc;
(*bin_count)++;
}
return(1);
}
#ifndef Xorriso_fileliste_externaL
/* @param flag bit0= pathspec mode "on" rather than "as_mkisofs"
*/
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) == '=' || (*(npt + 1) == '\\' && !(flag & 1)))
npt++;
continue;
}
if(*npt=='=')
break;
}
if(*npt==0)
npt= NULL;
(*limit_pt)= npt;
return(npt!=NULL);
}
int Fileliste__escape_source_path(char *line, int size, int flag)
{
int l, count= 0, i;
char *wpt;
l= strlen(line);
for(i= 0; i < l; i++)
if(line[i] == '=' || line[i] == '\\')
count++;
if(l + count >= size)
return(0);
wpt= line + l + count;
for(i= l; i >= 0; i--) {
*(wpt--)= line[i];
if(line[i] == '=' || line[i] == '\\')
*(wpt--)= '\\';
}
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));
}
#endif /* ! Xorriso_fileliste_externaL */
int Xorriso__hide_mode(char *mode, int flag)
{
char *npt, *cpt;
int l, value= 0;
npt= cpt= mode;
for(; npt!=NULL; cpt= npt+1) {
npt= strchr(cpt,':');
if(npt==NULL)
l= strlen(cpt);
else
l= npt-cpt;
if(l == 0)
continue;
if(l == 2 && strncmp(cpt, "on", l) == 0)
value= 1 | 2 | 4;
else if(l == 6 && strncmp(cpt, "iso_rr", l) == 0)
value |= 1;
else if(l == 6 && strncmp(cpt, "joliet", l) == 0)
value |= 2;
else if(l == 7 && strncmp(cpt, "hfsplus", l) == 0)
value |= 4;
else if(l == 3 && strncmp(cpt, "off", l) == 0)
value= 0;
else
return(-1);
}
return(value);
}
char *Xorriso__hide_mode_text(int hide_mode, int flag)
{
char *acc= NULL;
acc = calloc(1, 80);
if(acc == NULL)
return(NULL);
acc[0]= 0;
if(hide_mode == 0) {
strcat(acc, "off:");
} else if(hide_mode == 7) {
strcat(acc, "on:");
} else {
if(hide_mode & 1)
strcat(acc, "iso_rr:");
if(hide_mode & 2)
strcat(acc, "joliet:");
if(hide_mode & 4)
strcat(acc, "hfsplus:");
}
if(acc[0])
acc[strlen(acc) - 1]= 0; /* cut off last colon */
return acc;
}
/* @return 0=truncated, 1=ok
*/
int Xorriso__to_upper(char *in, char *out, int out_size, int flag)
{
int i;
for(i= 0; i < out_size - 1 && in[i] != 0; i++)
if(isalpha(in[i]))
out[i]= toupper(in[i]);
else
out[i]= in[i];
out[i]= 0;
return(in[i] == 0);
}
/* @param flag bit0= prepend target_prefix even if source_prefix does not get
removed
*/
int Xorriso__exchange_prefix(char *source_prefix, char *target_prefix,
char *eff_source, char *eff_target, int flag)
{
char *source_pt;
strcpy(eff_target, target_prefix);
source_pt= eff_source;
if(source_prefix[0]) {
if(strncmp(source_prefix, eff_source, strlen(source_prefix)) != 0) {
if(!(flag & 1))
return(0);
} else {
source_pt+= strlen(source_prefix);
}
}
strcat(eff_target, source_pt);
return(1);
}
/* @param text takes result, must provide at least 37 characters of storage
@param flag bit0= structured text format (else hex string)
*/
int Xorriso__format_guid(uint8_t guid[16], char *text, int flag)
{
int i;
if(flag & 1) {
/* Structured text */
text[0]= 0;
for(i= 3; i >= 0; i--)
sprintf(text + strlen(text), "%-2.2x", (unsigned int) guid[i]);
sprintf(text + strlen(text), "-");
for(i= 5; i >= 4; i--)
sprintf(text + strlen(text), "%-2.2x", (unsigned int) guid[i]);
sprintf(text + strlen(text), "-");
for(i= 7; i >= 6; i--)
sprintf(text + strlen(text), "%-2.2x", (unsigned int) guid[i]);
sprintf(text + strlen(text), "-");
for(i= 8; i <= 9; i++)
sprintf(text + strlen(text), "%-2.2x", (unsigned int) guid[i]);
sprintf(text + strlen(text), "-");
for(i= 10; i <= 15; i++)
sprintf(text + strlen(text), "%-2.2x", (unsigned int) guid[i]);
} else {
/* Plain hex string */
for(i= 0; i < 16; i++)
sprintf(text + i * 2, "%-2.2x", (unsigned int) guid[i]);
}
return(1);
}
int Xorriso__parse_size_param(char *cpt, int key_l, int l, double *num)
{
char text[16];
*num= 0.0;
if(l <= key_l || l >= key_l + 16)
return(0);
strncpy(text, cpt + key_l, l - key_l);
text[l - key_l]= 0;
*num= Scanf_io_size(text, 0);
return(1);
}