2
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
4
Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
6
Provided under GPL version 2 or later.
8
This file contains the implementation of functions around files and strings.
12
#include "../config.h"
16
#include <sys/types.h>
31
/* @param flag bit0= do not clip off carriage return at line end
33
char *Sfile_fgets_n(char *line, int maxl, FILE *fp, int flag)
38
ret= fgets(line,maxl,fp);
42
if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
43
if(l > 0) if(line[l-1] == '\n') line[--l]= 0;
44
if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
49
int Sfile_count_components(char *path, int flag)
51
bit0= do not ignore trailing slash
52
bit1= do not ignore empty components (other than the empty root name)
62
for(cpt= path+l-1;cpt>=path;cpt--) {
64
if(*(cpt+1)==0 && !(flag&1))
66
if(*(cpt+1)=='/' && !(flag&2))
75
int Sfile_component_pointer(char *path, char **sourcept, int idx, int flag)
77
bit0= do not ignore trailing slash
78
bit1= do not ignore empty components (other than the empty root name)
85
for(spt= path;*spt!=0 || (flag&4);spt++) {
90
if(*spt=='/' || *spt==0) {
91
if(*(spt+1)=='/' && !(flag&2))
93
if(*(spt+1)==0 && !(flag&1))
98
if((flag&1) && count>=idx)
104
int Sfile_leafname(char *path, char leafname[SfileadrL], int flag)
110
count= Sfile_count_components(path, 0);
113
ret= Sfile_component_pointer(path, &lpt, count-1, 0);
116
if(Sfile_str(leafname, lpt, 0)<=0)
118
lpt= strchr(leafname, '/');
125
int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag)
135
} else if(path[l-1]!='/') {
139
if(l+strlen(addon)>=SfileadrL)
142
strcpy(path+l,addon+1);
144
strcpy(path+l,addon);
149
int Sfile_prepend_path(char *prefix, char path[SfileadrL], int flag)
151
int l, i, slashes, prefix_len, path_len;
157
/* Do not copy slashes between both parts */
158
for(prefix_len= l; prefix_len > 0; prefix_len--)
159
if(prefix[prefix_len - 1] != '/')
162
prefix_len= strlen(prefix) - 1;
163
path_len= strlen(path);
164
for(slashes= 0; slashes < path_len; slashes++)
165
if(path[slashes] != '/')
168
l= (strlen(path) - slashes) + prefix_len + 1;
172
/* >>> ??? how to transport messages to xorriso ? */
173
sprintf(xorriso->info_text,
174
"Combination of wd and relative address too long (%d > %d)",
176
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
183
for(i= slashes; i <= path_len + 1; i++)
186
for(i= path_len + 1; i >= slashes; i--)
190
memcpy(path, prefix, prefix_len);
191
path[l - 1 + slashes]= '/';
195
int Sfile_being_group_member(struct stat *stbuf, int flag)
200
if (getegid()==stbuf->st_gid)
202
suppl_groups= getgroups(0, NULL);
203
suppl_glist= (gid_t *) malloc((suppl_groups + 1) * sizeof(gid_t));
204
if (suppl_glist==NULL)
206
suppl_groups= getgroups(suppl_groups+1,suppl_glist);
207
for (i= 0; i<suppl_groups; i++) {
208
if (suppl_glist[i]==stbuf->st_gid) {
209
free((char *) suppl_glist);
213
free((char *) suppl_glist);
218
int Sfile_type(char *filename, int flag)
220
bit0= return -1 if file is missing
221
bit1= return a hardlink with siblings as type 5
222
bit2= evaluate eventual link target rather than the link object itself
223
bit3= return a socket or a char device as types 7 or 8 rather than 0
232
5=multiple hardlink (with bit1)
235
8=character device (with bit3)
240
if(stat(filename,&stbuf)==-1) {
241
if(flag&1) return(-1);
245
if(lstat(filename,&stbuf)==-1) {
246
if(flag&1) return(-1);
250
if(S_ISREG(stbuf.st_mode)) {
256
if(S_ISDIR(stbuf.st_mode))
258
if((stbuf.st_mode&S_IFMT)==S_IFLNK)
260
if(S_ISFIFO(stbuf.st_mode))
262
if(S_ISBLK(stbuf.st_mode))
265
if((stbuf.st_mode&S_IFMT)==S_IFSOCK)
268
if(S_ISCHR(stbuf.st_mode))
274
char *Sfile_datestr(time_t tim, short int flag)
276
bit0=with hours+minutes
279
bit8= local time rather than UTC
282
static char zeitcode[80]={"000000"};
287
azt = localtime(&tim);
292
sprintf(zeitcode,"%c%1.1d%2.2d%2.2d",
293
'A'+(azt->tm_year-100)/10,azt->tm_year%10,
294
azt->tm_mon+1,azt->tm_mday);
296
sprintf(zeitcode,"%2.2d%2.2d%2.2d",
297
azt->tm_year,azt->tm_mon+1,azt->tm_mday);
299
sprintf(puff,".%2.2d%2.2d",azt->tm_hour,azt->tm_min);
300
strcat(zeitcode,puff);
303
sprintf(puff,"%2.2d",azt->tm_sec);
304
strcat(zeitcode,puff);
311
int Sfile_scale(double value, char *result, int siz, double thresh, int flag)
313
bit0= eventually ommit 'b'
314
bit1= make text as short as possible
315
bit2= no fraction (if it would fit at all)
318
char scale_c,scales[7],form[80], *negpt= NULL, *cpt;
319
int i,dec_siz= 0,avail_siz= 1;
328
strcpy(scales,"bkmgtp");
330
for(i=1;scales[i]!=0;i++) {
336
if(scale_c!='b' && !(flag&4)) { /* is there room for fractional part ? */
338
sprintf(form,"%%.f");
339
sprintf(result,"%.f",value);
340
if(strlen(result)<=avail_siz-2)
341
dec_siz= 1; /* we are very modest */
343
if(scale_c=='b' && (flag&1)) {
345
sprintf(form,"%%.f");
347
sprintf(form,"%%%d.f",siz);
348
sprintf(result,form,value);
351
sprintf(form,"%%.f%%c");
353
sprintf(form,"%%%d.%df%%c",avail_siz,dec_siz);
355
sprintf(form,"%%%d.f%%c",siz-1);
356
sprintf(result,form,value,scale_c);
359
for(cpt= result; *cpt==' '; cpt++);
369
int Sfile_off_t_text(char text[80], off_t num, int flag)
372
off_t hnum, scale= 1;
381
if(hnum<0) { /* it can stay nastily persistent */
382
strcpy(text, "_overflow_");
385
for(i= 0; i<23; i++) { /* good for up to 70 bit = 10 exp 21.07... */
397
strcpy(text, "_overflow_");
404
tpt[digits-i]= '0'+d;
413
/* Converts backslash codes into single characters:
414
\a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 ,
415
\t HT 9 , \v VT 11 , \\ \ 92
416
\[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code ,
417
\cX control-x (ascii(X)-64)
418
@param upto maximum number of characters to examine for backslash.
419
The scope of a backslash (0 to 3 characters) is not affected.
420
@param eaten returns the difference in length between input and output
421
@param flag bit0= only determine *eaten, do not convert
422
bit1= allow to convert \000 to binary 0
424
int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
426
char *rpt, *wpt, num_text[8], wdummy[8];
431
for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) {
439
} else if(*rpt == 'b') {
441
} else if(*rpt == 'e') {
443
} else if(*rpt == 'f') {
445
} else if(*rpt == 'n') {
447
} else if(*rpt == 'r') {
449
} else if(*rpt == 't') {
451
} else if(*rpt == 'v') {
453
} else if(*rpt == '\\') {
455
} else if(rpt[0] >= '0' && rpt[0] <= '7' &&
456
rpt[1] >= '0' && rpt[1] <= '7' &&
457
rpt[2] >= '0' && rpt[2] <= '7') {
459
num_text[1]= *(rpt + 0);
460
num_text[2]= *(rpt + 1);
461
num_text[3]= *(rpt + 2);
463
sscanf(num_text, "%o", &num);
464
if((num > 0 || (flag & 2)) && num <= 255) {
470
} else if(rpt[0] == 'x' &&
471
((rpt[1] >= '0' && rpt[1] <= '9') ||
472
(rpt[1] >= 'A' && rpt[1] <= 'F') ||
473
(rpt[1] >= 'a' && rpt[1] <= 'f'))
475
((rpt[2] >= '0' && rpt[2] <= '9') ||
476
(rpt[2] >= 'A' && rpt[2] <= 'F') ||
477
(rpt[2] >= 'a' && rpt[2] <= 'f'))
479
num_text[0]= *(rpt + 1);
480
num_text[1]= *(rpt + 2);
482
sscanf(num_text, "%x", &num);
483
if(num > 0 && num <= 255) {
489
} else if(*rpt == 'c') {
490
if(rpt[1] > 64 && rpt[1] < 96) {
491
*(wpt++)= rpt[1] - 64;
510
int Sfile_argv_bsl(int argc, char ***argv, int flag)
513
char **new_argv= NULL;
517
new_argv= (char **) Smem_malloC(argc * sizeof(char *));
520
for(i= 0; i < argc; i++) {
521
new_argv[i]= strdup((*argv)[i]);
522
if(new_argv[i] == NULL)
524
ret= Sfile_bsl_interpreter(new_argv[i], strlen(new_argv[i]), &eaten, 0);
532
free((char *) new_argv);
539
/* @param flag bit0= only encode inside quotes
540
bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13
541
bit2= encode in any case above 126
542
bit3= encode in any case shellsafe and name-value-safe:
543
<=42 , 59, 60, 61, 62, 63, 92, 94, 96, >=123
545
int Sfile_bsl_encoder(char **result, char *text, size_t text_len, int flag)
548
int count, sq_open= 0, dq_open= 0;
551
for(rpt= text; rpt - text < text_len; rpt++) {
554
if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
555
*rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123))
557
} else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\')
559
if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag & 8))
564
(*result)= wpt= calloc(count + 1, 1);
567
for(rpt= text; rpt - text < text_len; rpt++) {
569
sq_open= !(sq_open || dq_open);
571
dq_open= !(sq_open || dq_open);
574
if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
575
*rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123)) {
579
} else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') {
582
} else if( ((flag & 1) && !(sq_open || dq_open)) &&
583
!((flag & 2) && (*rpt >= 1 && * rpt <= 31 &&
584
!(*rpt == 7 || *rpt == 8 || *rpt == 9 || *rpt == 10 ||
585
*rpt == 12 || *rpt == 13))) &&
586
!((flag & 4) && (*rpt > 126 || *rpt < 0)) &&
587
!((flag & 6) && *rpt == '\\')) {
592
if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag&8)) {
599
else if(*rpt == 10) {
601
} else if(*rpt == 11)
609
else if(*rpt == '\\')
612
sprintf(wpt, "%-3.3o", (unsigned int) *((unsigned char *) rpt));
621
int Sfile_destroy_argv(int *argc, char ***argv, int flag)
625
if(*argc>0 && *argv!=NULL){
626
for(i=0;i<*argc;i++){
628
Smem_freE((*argv)[i]);
630
Smem_freE((char *) *argv);
638
int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv,
641
bit0= read progname as first argument from line
642
bit1= just release argument list argv and return
643
bit2= abort with return(0) if incomplete quotes are found
644
bit3= eventually prepend missing '-' to first argument read from line
645
bit4= like bit2 but only check quote completeness, do not allocate memory
646
bit5+6= interpretation of backslashes:
647
0= no interpretation, leave unchanged
648
1= only inside double quotes
649
2= outside single quotes
651
bit7= append a NULL element to argv
654
int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten;
658
Sfile_destroy_argv(argc,argv,0);
664
bsl_mode= (flag >> 5) & 3;
666
buf= calloc(strlen(line) + SfileadrL, 1);
669
for(pass=0;pass<2;pass++) {
672
argzaehl= line_start_argc= 1;
674
maxl= strlen(progname);
676
strcpy((*argv)[0],progname);
678
argzaehl= line_start_argc= 0;
682
if(isspace(*cpt)) continue;
687
if(isspace(*cpt)) break;
689
l= cpt-start; bufl= strlen(buf);
691
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
693
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
700
while(*(++cpt)!=0) if(*cpt=='"') break;
701
if((flag&4) && *cpt==0)
703
l= cpt-start; bufl= strlen(buf);
705
strncpy(buf + bufl, start, l);
708
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
714
}else if(*cpt=='\''){
715
l= cpt-start; bufl= strlen(buf);
717
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
719
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
726
while(*(++cpt)!=0) if(*cpt=='\'') break;
727
if((flag&4) && *cpt==0)
729
l= cpt-start; bufl= strlen(buf);
731
strncat(buf,start,l);buf[bufl+l]= 0;
733
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
745
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
747
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
754
if(argzaehl==line_start_argc && (flag&8))
755
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
759
strcpy((*argv)[argzaehl],buf);
760
if(argzaehl==line_start_argc && (flag&8))
761
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
762
sprintf((*argv)[argzaehl],"-%s", buf);
771
if(argzaehl>0 || (flag & 128)) {
772
*argv= (char **) Smem_malloC((argzaehl + !!(flag & 128))
777
for(i=0;i<*argc;i++) {
778
(*argv)[i]= (char *) Smem_malloC((maxl+1));
783
(*argv)[*argc]= NULL;
794
/* @param flag bit0= append */
795
int Sfile_str(char target[SfileadrL], char *source, int flag)
803
fprintf(stderr, "--- Path string overflow (%d > %d). Malicious input ?\n",
808
strcat(target, source);
810
strcpy(target, source);
815
/** Combine environment variable HOME with given filename
816
@param filename Address relative to $HOME
817
@param fileadr Resulting combined address
818
@param fa_size Size of array fileadr
819
@param flag Unused yet
820
@return 1=ok , 0=no HOME variable , -1=result address too long
822
int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag)
826
strcpy(fileadr,filename);
827
home= getenv("HOME");
830
if(strlen(home)+strlen(filename)+1>=fa_size)
832
strcpy(fileadr,home);
835
strcat(fileadr,filename);
841
/** Return a double representing seconds and microseconds since 1 Jan 1970 */
842
double Sfile_microtime(int flag)
846
gettimeofday(&tv,&tz);
847
return((double) (tv.tv_sec+1.0e-6*tv.tv_usec));
851
int Sfile_decode_datestr(struct tm *reply, char *text, int flag)
852
/* YYMMDD[.hhmm[ss]] */
858
current_time= time(0);
859
now= localtime(¤t_time);
860
for(i=0;i<sizeof(struct tm);i++)
861
((char *) reply)[i]= ((char *) now)[i];
863
if(text[0]<'0'|| (text[0]>'9' && text[0]<'A') || text[0]>'Z')
867
if(text[i]<'0'||text[i]>'9')
873
if(text[i]!='.' || (l!=11 && l!=13))
876
if(text[i]<'0'||text[i]>'9')
887
reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0';
889
reply->tm_year= 10*(text[0]-'0')+text[1]-'0';
890
reply->tm_mon= 10*(text[2]-'0')+text[3]-'0'-1;
891
reply->tm_mday= 10*(text[4]-'0')+text[5]-'0';
894
reply->tm_hour= 10*(text[7]-'0')+text[8]-'0';
895
reply->tm_min= 10*(text[9]-'0')+text[10]-'0';
898
reply->tm_sec= 10*(text[11]-'0')+text[12]-'0';