1
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2012 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains the miscellaneous helper functions of xorriso.
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <time.h>
24 #include <sys/utsname.h>
25
26
27 #include "sfile.h"
28 #include "misc_funct.h"
29
30
31 /* --------------------------------- misc --------------------------------- */
32
33
Strcmp(const void * pt1,const void * pt2)34 int Strcmp(const void *pt1, const void *pt2)
35 {
36 return(strcmp(*((char **) pt1), *((char **) pt2)));
37 }
38
39
Sort_argv(int argc,char ** argv,int flag)40 int Sort_argv(int argc, char **argv, int flag)
41 {
42 if(argc<=0)
43 return(2);
44 qsort(argv,(size_t) argc,sizeof(char *),Strcmp);
45 return(1);
46 }
47
48
Text_to_argv(char * text,int * argc,char *** argv,int flag)49 static int Text_to_argv(char *text, int *argc, char ***argv, int flag)
50 {
51 char *npt, *cpt;
52 int pass;
53
54 *argv= NULL;
55 *argc= 0;
56 for(pass= 0; pass < 2; pass++) {
57 if(pass) {
58 if(*argc == 0)
59 return(1);
60 (*argv)= calloc(*argc, sizeof(char *));
61 if(*argv == NULL) {
62 *argc= 0;
63 return(-1);
64 }
65 *argc= 0;
66 }
67 for(npt= cpt= text; npt != NULL; cpt= npt + 1) {
68 npt= strchr(cpt, '\n');
69 if(pass) {
70 if(npt != NULL)
71 *npt= 0;
72 (*argv)[*argc]= cpt;
73 }
74 (*argc)++;
75 }
76 }
77 return(1);
78 }
79
80
Count_diffs(int argc1,char ** argv1,int argc2,char ** argv2,int flag)81 static int Count_diffs(int argc1, char **argv1, int argc2, char **argv2,
82 int flag)
83 {
84 int count= 0, i1= 0, i2= 0, cmp, end_corr= 0;
85
86 Sort_argv(argc1, argv1, 0);
87 Sort_argv(argc2, argv2, 0);
88
89 while(1) {
90 if(i1 >= argc1) {
91 count+= argc2 - i2 - end_corr;
92 break;
93 }
94 if(i2 >= argc2) {
95 count+= argc1 - i1 - end_corr;
96 break;
97 }
98 cmp= strcmp(argv1[i1], argv2[i2]);
99 if(cmp == 0) {
100 end_corr= 0;
101 i1++;
102 i2++;
103 } else if(cmp > 0) {
104 count++;
105 end_corr= 1;
106 i2++;
107 if(i2 < argc2 && i1 < argc1 - 1)
108 if(strcmp(argv1[i1 + 1], argv2[i2]) == 0) {
109 i1++;
110 end_corr= 0;
111 }
112 } else {
113 count++;
114 end_corr= 1;
115 i1++;
116 if(i1 < argc1 && i2 < argc2 - 1)
117 if(strcmp(argv2[i2 + 1], argv1[i1]) == 0) {
118 i2++;
119 end_corr= 0;
120 }
121 }
122 }
123 return(count);
124 }
125
126
127 /*
128 @flag bit0= do not initialize *diff_count
129 @return <0 error , 0 = mismatch , 1 = match
130 */
Compare_text_lines(char * text1,char * text2,int * diff_count,int flag)131 int Compare_text_lines(char *text1, char *text2, int *diff_count, int flag)
132 {
133 int ret, argc1= 0, argc2= 0;
134 char **argv1= NULL, **argv2= NULL, *copy1= NULL, *copy2= NULL;
135
136 if(!(flag & 1))
137 *diff_count= 0;
138 if(text1 == NULL && text2 == NULL)
139 return(1);
140 if(text1 != NULL) {
141 copy1= strdup(text1);
142 if(copy1 == NULL)
143 {ret= -1; goto ex;}
144 ret= Text_to_argv(copy1, &argc1, &argv1, 0);
145 if(ret <= 0)
146 {ret= -1; goto ex;}
147 }
148 if(text2 != NULL) {
149 copy2= strdup(text2);
150 if(copy2 == NULL)
151 {ret= -1; goto ex;}
152 ret= Text_to_argv(copy2, &argc2, &argv2, 0);
153 if(ret <= 0)
154 {ret= -1; goto ex;}
155 }
156 ret= Count_diffs(argc1, argv1, argc2, argv2, 1);
157 if(ret < 0)
158 goto ex;
159 *diff_count+= ret;
160 ret= (*diff_count == 0);
161 ex:;
162 if(argv1 != NULL)
163 free(argv1);
164 if(argv2 != NULL)
165 free(argv2);
166 if(copy1 != NULL)
167 free(copy1);
168 if(copy2 != NULL)
169 free(copy2);
170 return ret;
171 }
172
173
174 /** Convert a text into a number of type double and multiply it by unit code
175 [kmgtpe] (2^10 to 2^60) or [s] (2048) or [d] (512).
176 (Also accepts capital letters.)
177 @param text Input like "42", "2k", "3.14m" or "-1g"
178 @param flag Bitfield for control purposes:
179 bit0= return -1 rathern than 0 on failure
180 @return The derived double value
181 */
Scanf_io_size(char * text,int flag)182 double Scanf_io_size(char *text, int flag)
183 /*
184 bit0= default value -1 rather than 0
185 */
186 {
187 int c;
188 double ret= 0.0;
189
190 if(flag&1)
191 ret= -1.0;
192 if(text[0]==0)
193 return(ret);
194 sscanf(text,"%lf",&ret);
195 c= text[strlen(text)-1];
196 if(c=='k' || c=='K') ret*= 1024.0;
197 if(c=='m' || c=='M') ret*= 1024.0*1024.0;
198 if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0;
199 if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0;
200 if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0;
201 if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0;
202 if(c=='s' || c=='S') ret*= 2048.0;
203 if(c=='d' || c=='D') ret*= 512.0;
204 return(ret);
205 }
206
207
Decode_date_input_format(struct tm * erg,char * text,int flag)208 int Decode_date_input_format(struct tm *erg, char *text, int flag)
209 /* MMDDhhmm[[CC]YY][.ss]] */
210 {
211 int i,l,year;
212 time_t current_time;
213 struct tm *now;
214
215 current_time= time(0);
216 now= localtime(¤t_time);
217 for(i= 0; i < (int) sizeof(struct tm); i++)
218 ((char *) erg)[i]= ((char *) now)[i];
219
220 l= strlen(text);
221 for(i=0;i<l;i++)
222 if(text[i]<'0'||text[i]>'9')
223 break;
224 if(i!=8 && i!=10 && i!=12)
225 return(0);
226 if(text[i]==0)
227 goto decode;
228 if(text[i]!='.' || l!=15)
229 return(0);
230 i++;
231 if(text[i]<'0'||text[i]>'9')
232 return(0);
233 i++;
234 if(text[i]<'0'||text[i]>'9')
235 return(0);
236
237 decode:;
238 /* MMDDhhmm[[CC]YY][.ss]] */
239 i= 0;
240 erg->tm_mon= 10*(text[0]-'0')+text[1]-'0'-1;
241 erg->tm_mday= 10*(text[2]-'0')+text[3]-'0';
242 erg->tm_hour= 10*(text[4]-'0')+text[5]-'0';
243 erg->tm_min= 10*(text[6]-'0')+text[7]-'0';
244 erg->tm_sec= 0;
245 if(l==8)
246 return(1);
247 if(l>10){
248 year= 1000*(text[8]-'0')+100*(text[9]-'0')+10*(text[10]-'0')+(text[11]-'0');
249 }else{
250 year= 1900+10*(text[8]-'0')+(text[9]-'0');
251 if(year<1970)
252 year+= 100;
253 }
254 erg->tm_year= year-1900;
255 if(l<=12)
256 return(1);
257 erg->tm_sec= 10*(text[13]-'0')+text[14]-'0';
258 return(1);
259 }
260
261
Decode_date_weekday(char * text,int flag)262 int Decode_date_weekday(char *text, int flag)
263 {
264 int i;
265 static char days[][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", ""};
266
267 for(i= 0; days[i][0]!=0; i++)
268 if(strncmp(text,days[i],3)==0)
269 return(i);
270 if((strlen(text)==3 || (strlen(text)==4 && text[3]==',')) &&
271 isalpha(text[0]) && isalpha(text[1]) && isalpha(text[2]))
272 return(7);
273 return(-1);
274 }
275
276
Decode_date_month(char * text,int flag)277 int Decode_date_month(char *text, int flag)
278 {
279 int i;
280 static char months[][4]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
281 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
282
283 for(i= 0; months[i][0]!=0; i++)
284 if(strncmp(text,months[i],3)==0)
285 return(i);
286 return(-1);
287 }
288
289
290 /* @return -1=not a number, -2=not a day , 1 to 31 day of month */
Decode_date_mday(char * text,int flag)291 int Decode_date_mday(char *text, int flag)
292 {
293 int ret, i;
294
295 for(i= 0; text[i]!=0; i++)
296 if(!isdigit(text[i]))
297 return(-1);
298 if(strlen(text)>2 || text[0]==0)
299 return(-2);
300 sscanf(text, "%d", &ret);
301 if(ret<=0 || ret>31)
302 return(-2);
303 return(ret);
304 }
305
Decode_date_hms(char * text,struct tm * erg,int flag)306 int Decode_date_hms(char *text, struct tm *erg, int flag)
307 {
308 int i, hour= -1, minute= -1, second= 0;
309
310 for(i= 0; i<9; i+= 3) {
311 if(i==6&&text[i]==0)
312 break;
313 if(!isdigit(text[i]))
314 return(-1);
315 if(!isdigit(text[i+1]))
316 return(-1);
317 if(text[i+2]!=':' && !(text[i+2]==0 && i>=3))
318 return(-1);
319 if(i==0)
320 sscanf(text+i,"%d",&hour);
321 else if(i==3)
322 sscanf(text+i,"%d",&minute);
323 else
324 sscanf(text+i,"%d",&second);
325 }
326 if(hour<0 || hour>23 || minute<0 || minute>59 || second>59)
327 return(-1);
328 erg->tm_hour= hour;
329 erg->tm_min= minute;
330 erg->tm_sec= second;
331 return(1);
332 }
333
334
335 /* @return -1=not a number, -2=not a year , >=0 years AD */
Decode_date_year(char * text,int flag)336 int Decode_date_year(char *text, int flag)
337 {
338 int ret, i;
339
340 for(i= 0; text[i]!=0; i++)
341 if(!isdigit(text[i]))
342 return(-1);
343 if(strlen(text)!=4)
344 return(-2);
345 sscanf(text, "%d", &ret);
346 if(ret<0 || ret>3000)
347 return(-2);
348 return(ret);
349 }
350
351
Decode_date_timezone(char * text,struct tm * erg,int flag)352 int Decode_date_timezone(char *text, struct tm *erg, int flag)
353 {
354 int i;
355 static char tzs[][5]= {"GMT", "CET", "CEST", "0000", ""};
356
357 for(i= 0; tzs[i][0]!=0; i++)
358 if(strcmp(text,tzs[i])==0) {
359
360 /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */
361
362 return(1);
363 }
364 if(text[0]=='+' || text[0]=='-') {
365 for(i= 1; text[i]!=0; i++)
366 if(!isdigit(text[i]))
367 return(-1);
368 if(i!=5)
369 return(-1);
370
371 /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */
372
373 return(1);
374 } else {
375 for(i= 0; text[i]!=0; i++)
376 if(text[i]<'A' || text[i]>'Z')
377 return(-1);
378 if(i!=3 && i!=4)
379 return(-1);
380 return(2);
381 }
382 }
383
384
Decode_date_output_format(struct tm * erg,char * text,int flag)385 int Decode_date_output_format(struct tm *erg, char *text, int flag)
386 /* Thu Nov 8 09:07:50 CET 2007 */
387 /* Sat, 03 Nov 2007 08:58:30 +0100 */
388 /* Nov 7 23:24 */
389 {
390 int ret, i, argc= 0, seen_year= 0, seen_month= 0, seen_day= 0, seen_time= 0;
391 char **argv= NULL;
392 struct tm *now;
393 time_t timep;
394
395 memset(erg, 0, sizeof(*erg));
396 erg->tm_isdst= -1;
397 ret= Sfile_make_argv("xorriso", text, &argc, &argv, 0);
398 if(ret<=0)
399 goto ex;
400 for(i= 1; i<argc; i++) {
401 if(!seen_month) {
402 ret= Decode_date_month(argv[i], 0);
403 if(ret>=0) {
404 seen_month= 1;
405 erg->tm_mon= ret;
406 continue;
407 }
408 }
409 if(!seen_day) {
410 ret= Decode_date_mday(argv[i], 0);
411 if(ret>0) {
412 seen_day= 1;
413 erg->tm_mday= ret;
414 continue;
415 }
416 if(ret==-2) /* first pure number must be day of month */
417 {ret= 0; goto ex;}
418 }
419 if(!seen_time) {
420 ret= Decode_date_hms(argv[i], erg, 0);
421 if(ret>0) {
422 seen_time= 1;
423 continue;
424 }
425 }
426 if(!seen_year) {
427 ret= Decode_date_year(argv[i], 0);
428 if(ret>0) {
429 erg->tm_year= ret-1900;
430 seen_year= 1;
431 continue;
432 }
433 }
434
435 /* ignorants have to stay at the end of the loop */
436
437 ret= Decode_date_timezone(argv[i], erg, 0);
438 if(ret>=0)
439 continue;
440 ret= Decode_date_weekday(argv[i], 0);
441 if(ret>=0)
442 continue; /* ignore weekdays */
443
444 {ret= 0; goto ex;} /* unrecognizable component */
445 }
446
447 if(!(seen_day && seen_month))
448 {ret= 0; goto ex;}
449 if(!seen_year) { /* then use this year */
450 timep= time(NULL);
451 now= localtime(&timep);
452 erg->tm_year= now->tm_year;
453 }
454 ret= 1;
455 ex:
456 Sfile_make_argv("", "", &argc, &argv, 2); /* release storage */
457 return(ret);
458 }
459
460
Decode_ecma119_format(struct tm * erg,char * text,int flag)461 int Decode_ecma119_format(struct tm *erg, char *text, int flag)
462 /* YYYYMMDDhhmmsscc[LOC] */
463 /* 2010040711405800 */
464 {
465 int i, l, num, utc= 1;
466 struct tm norm_tm;
467
468 memset(erg, 0, sizeof(*erg));
469 erg->tm_isdst= -1;
470 l= strlen(text);
471 if(l == 19) {
472 if(strcmp(text + 16, "LOC") != 0)
473 return(0);
474 utc= 0;
475 l= 16;
476 }
477 if(l != 16)
478 return(0);
479 for(i= 0; i < l; i++)
480 if(text[i] < '0' || text[i] > '9')
481 return(0);
482 num= 0;
483 for(i= 0; i < 4; i++)
484 num= num * 10 + text[i] - '0';
485 if(num < 1970 || num > 3000)
486 return(0);
487 erg->tm_year = num - 1900;
488 erg->tm_mon= 10*(text[4]-'0')+text[5]-'0'-1;
489 if(erg->tm_mon > 12)
490 return(0);
491 erg->tm_mday= 10*(text[6]-'0')+text[7]-'0';
492 if(erg->tm_mday > 31)
493 return(0);
494 erg->tm_hour= 10*(text[8]-'0')+text[9]-'0';
495 if(erg->tm_hour > 23)
496 return(0);
497 erg->tm_min= 10*(text[10]-'0')+text[11]-'0';
498 if(erg->tm_min > 59)
499 return(0);
500 erg->tm_sec= 10*(text[12]-'0')+text[13]-'0';
501 if(erg->tm_sec > 59)
502 return(0);
503 /* Let mktime(3) compute erg->tm_wday and erg->tm_yday */
504 memcpy(&norm_tm, erg, sizeof(struct tm));
505 mktime(&norm_tm);
506 erg->tm_wday= norm_tm.tm_wday;
507 erg->tm_yday= norm_tm.tm_yday;
508 return(1 + !utc);
509 }
510
511
Decode_xorriso_timestamp(struct tm * erg,char * code,int flag)512 int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag)
513 /* 2007.11.07.225624 */
514 {
515 char buf[20];
516 int year,month,day,hour= 0,minute= 0,second= 0, i, l, mem;
517
518 memset(erg, 0, sizeof(*erg));
519 erg->tm_isdst= -1;
520
521 l= strlen(code);
522 if(l>17 || l<10)
523 return(0);
524 strcpy(buf, code);
525 for(i= 0; buf[i]!=0 && i<4; i++)
526 if(!isdigit(buf[i]))
527 return(0);
528 if(buf[4]!='.')
529 return(0);
530 buf[4]= 0;
531 sscanf(buf, "%d", &year);
532 if(year<1900 || year>3000)
533 return(0);
534 if(!(isdigit(buf[5]) && isdigit(buf[6]) && buf[7]=='.'))
535 return(0);
536 buf[7]= 0;
537 sscanf(buf+5, "%d", &month);
538 if(month<1 || month>12)
539 return(0);
540 if(!(isdigit(buf[8]) && isdigit(buf[9]) && (buf[10]=='.' || buf[10]==0)))
541 return(0);
542 buf[10]= 0;
543 sscanf(buf+8, "%d", &day);
544 if(day<1 || day>31)
545 return(0);
546 if(l==10)
547 goto done;
548 if(!(isdigit(buf[11]) && isdigit(buf[12]) &&
549 (isdigit(buf[13]) || buf[13]==0)))
550 return(0);
551 mem= buf[13];
552 buf[13]= 0;
553 sscanf(buf+11, "%d", &hour);
554 buf[13]= mem;
555 if(hour<0 || hour>23)
556 return(0);
557 if(l==13)
558 goto done;
559 if(!(isdigit(buf[13]) && isdigit(buf[14]) &&
560 (isdigit(buf[15]) || buf[15]==0)))
561 return(0);
562 mem= buf[15];
563 buf[15]= 0;
564 sscanf(buf+13, "%d", &minute);
565 buf[15]= mem;
566 if(minute<0 || minute>59)
567 return(0);
568 if(l==15)
569 goto done;
570 if(!(isdigit(buf[15]) && isdigit(buf[16]) && buf[17]==0))
571 return(0);
572 sscanf(buf+15, "%d", &second);
573 if(second<0 || second>59)
574 return(0);
575
576 done:;
577 erg->tm_year= year-1900;
578 erg->tm_mon= month-1;
579 erg->tm_mday= day;
580 erg->tm_hour= hour;
581 erg->tm_min= minute;
582 erg->tm_sec= second;
583 return(1);
584 }
585
586
Decode_timestring(char * code,time_t * date,int flag)587 time_t Decode_timestring(char *code, time_t *date, int flag)
588 {
589 char scale_chr;
590 double value,seconds;
591 struct tm result_tm;
592 int seconds_valid= 0, ret;
593
594 *date= 0;
595 if(code[0]=='-' || code[0]=='+' || code[0]=='=' || code[0]=='@'){
596 if(code[1]==0)
597 return(0);
598 if(!isdigit(code[1]))
599 return(0);
600 value= -1;
601 if(code[0]=='=' || code[0]=='@') {
602 seconds= 0;
603 sscanf(code+1,"%lf",&value);
604 } else {
605 seconds= time(NULL);
606 sscanf(code,"%lf",&value);
607 }
608 scale_chr= code[strlen(code)-1];
609 if(isalpha(scale_chr))
610 scale_chr= tolower(scale_chr);
611 if (scale_chr=='s') seconds+= 1.0*value;
612 else if(scale_chr=='h') seconds+= 3600.0*value;
613 else if(scale_chr=='d') seconds+= 86400.0*value;
614 else if(scale_chr=='w') seconds+= 86400.0*7.0*value;
615 else if(scale_chr=='m') seconds+= 86400.0*31.0*value;
616 else if(scale_chr=='y') seconds+= 86400.0*(365.25*value+1.0);
617 else seconds+= 1.0*value;
618 seconds_valid= 1;
619 goto completed;
620 } else if(Sfile_decode_datestr(&result_tm,code,0)>0) {
621 /* YYMMDD[.hhmm[ss]] */
622 result_tm.tm_isdst= -1;
623 seconds= mktime(&result_tm);
624 seconds_valid= 1;
625 goto completed;
626 } else if(Decode_date_input_format(&result_tm,code,0)>0) {
627 /* MMDDhhmm[[CC]YY][.ss]] */
628 result_tm.tm_isdst= -1;
629 seconds= mktime(&result_tm);
630 seconds_valid= 1;
631 goto completed;
632 } else if(Decode_xorriso_timestamp(&result_tm, code, 0)>0) {
633 /* 2007.11.07.225624 */
634 seconds= mktime(&result_tm);
635 seconds_valid= 1;
636 goto completed;
637 } else if(Decode_date_output_format(&result_tm, code, 0)>0) {
638 /* Thu Nov 8 09:07:50 CET 2007 */;
639 /* Sat, 03 Nov 2007 08:58:30 +0100 */;
640 /* Nov 7 23:24 */;
641 seconds= mktime(&result_tm);
642 seconds_valid= 1;
643 goto completed;
644 } else if((ret= Decode_ecma119_format(&result_tm, code, 0)) > 0) {
645 /* YYYYMMDDhhmmsscc[UTC] */
646 /* 2010040711405800UTC */
647 seconds= mktime(&result_tm);
648 if(ret == 1) {
649
650 #ifdef HAVE_TM_GMTOFF
651 seconds+= result_tm.tm_gmtoff;
652 #else
653 if(result_tm.tm_isdst < 0)
654 result_tm.tm_isdst = 0;
655 #ifndef Libburnia_timezonE
656 #define Libburnia_timezonE timezone
657 #endif
658 seconds-= Libburnia_timezonE - result_tm.tm_isdst * 3600;
659 #endif
660
661 }
662 seconds_valid= 1;
663 goto completed;
664 }
665 return(0);
666 completed:;
667 if(!seconds_valid)
668 return(0);
669 *date= seconds;
670 return(1);
671 }
672
673
674 /* @param flag bit0=with year and seconds
675 bit1-3= form
676 0= ls -l format
677 1= timestamp format YYYY.MM.DD.hhmmss
678 2= Wdy Mon Day hh:mm:ss Year
679 3= Mon Day hh:mm:ss Year
680 4= YYMMDD.hhmmss
681 */
Ftimetxt(time_t t,char timetext[40],int flag)682 char *Ftimetxt(time_t t, char timetext[40], int flag)
683 {
684 char *rpt;
685 struct tm tms, *tmpt;
686 static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
687 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
688 static char days[7][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
689 int form;
690
691 form= (flag>>1)&7;
692 tmpt= localtime_r(&t, &tms);
693 rpt= timetext;
694 rpt[0]= 0;
695 if(tmpt==0)
696 sprintf(rpt+strlen(rpt), "%12.f", (double) t);
697 else if (form==1)
698 sprintf(rpt+strlen(rpt), "%4.4d.%2.2d.%2.2d.%2.2d%2.2d%2.2d",
699 1900+tms.tm_year, tms.tm_mon+1, tms.tm_mday,
700 tms.tm_hour, tms.tm_min, tms.tm_sec);
701 else if (form==2)
702 sprintf(rpt+strlen(rpt), "%s %s %2.2d %2.2d:%2.2d:%2.2d %4.4d",
703 days[tms.tm_wday], months[tms.tm_mon], tms.tm_mday,
704 tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year);
705 else if (form==3)
706 sprintf(rpt+strlen(rpt), "%s %2.2d %2.2d:%2.2d:%2.2d %4.4d",
707 months[tms.tm_mon], tms.tm_mday,
708 tms.tm_hour, tms.tm_min, tms.tm_sec, 1900+tms.tm_year);
709 else if (form == 4) {
710 if(tms.tm_year>99)
711 sprintf(rpt+strlen(rpt), "%c", 'A' + (tms.tm_year - 100) / 10);
712 else
713 sprintf(rpt+strlen(rpt), "%c", '0' + tms.tm_year / 10);
714 sprintf(rpt+strlen(rpt), "%1.1d%2.2d%2.2d.%2.2d%2.2d%2.2d",
715 tms.tm_year % 10, tms.tm_mon + 1, tms.tm_mday,
716 tms.tm_hour, tms.tm_min, tms.tm_sec);
717 } else if (flag&1)
718 sprintf(rpt+strlen(rpt), "%2d %3s %4.4d %2.2d:%2.2d:%2.2d",
719 tms.tm_mday, months[tms.tm_mon], 1900+tms.tm_year,
720 tms.tm_hour, tms.tm_min, tms.tm_sec);
721 else if(time(NULL)-t < 180*86400 && time(NULL)-t >= 0)
722 sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d",
723 months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min);
724 else
725 sprintf(rpt+strlen(rpt), "%3s %2d %4.4d",
726 months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year);
727 return(timetext);
728 }
729
730
731 /* @param flag bit0= single letters */
Ftypetxt(mode_t st_mode,int flag)732 char *Ftypetxt(mode_t st_mode, int flag)
733 {
734 if(flag&1)
735 goto single_letters;
736 if(S_ISDIR(st_mode))
737 return("directory");
738 else if(S_ISREG(st_mode))
739 return("regular_file");
740 else if(S_ISLNK(st_mode))
741 return("symbolic_link");
742 else if(S_ISBLK(st_mode))
743 return("block_device");
744 else if(S_ISCHR(st_mode))
745 return("char_device");
746 else if(S_ISFIFO(st_mode))
747 return("name_pipe");
748 else if(S_ISSOCK(st_mode))
749 return("unix_socket");
750 return("unknown");
751 single_letters:;
752 if(S_ISDIR(st_mode))
753 return("d");
754 else if(S_ISREG(st_mode))
755 return("-");
756 else if(S_ISLNK(st_mode))
757 return("l");
758 else if(S_ISBLK(st_mode))
759 return("b");
760 else if(S_ISCHR(st_mode))
761 return("c");
762 else if(S_ISFIFO(st_mode))
763 return("p");
764 else if(S_ISSOCK(st_mode))
765 return("s");
766 return("?");
767 }
768
769
Wait_for_input(int fd,int microsec,int flag)770 int Wait_for_input(int fd, int microsec, int flag)
771 {
772 struct timeval wt;
773 fd_set rds,wts,exs;
774 int ready;
775
776 FD_ZERO(&rds);
777 FD_ZERO(&wts);
778 FD_ZERO(&exs);
779 FD_SET(fd,&rds);
780 FD_SET(fd,&exs);
781 wt.tv_sec= microsec/1000000;
782 wt.tv_usec= microsec%1000000;
783 ready= select(fd+1,&rds,&wts,&exs,&wt);
784 if(ready<=0)
785 return(0);
786 if(FD_ISSET(fd,&exs))
787 return(-1);
788 if(FD_ISSET(fd,&rds))
789 return(1);
790 return(0);
791 }
792
793
System_uname(char ** sysname,char ** release,char ** version,char ** machine,int flag)794 int System_uname(char **sysname, char **release, char **version,
795 char **machine, int flag)
796 {
797 int ret;
798 static struct utsname uts;
799 static int initialized= 0;
800
801 if(initialized == 0) {
802 ret= uname(&uts);
803 if(ret != 0)
804 initialized = -1;
805 }
806 if(initialized == -1)
807 return(0);
808 if(sysname != NULL)
809 *sysname= uts.sysname;
810 if(release != NULL)
811 *release= uts.release;
812 if(version != NULL)
813 *version= uts.version;
814 if(machine != NULL)
815 *machine= uts.machine;
816 return(1);
817 }
818
819 /* ------------------------------------------------------------------------ */
820
821
822 #ifndef Xorriso_sregex_externaL
823
824 #ifndef Smem_malloC
825 #define Smem_malloC malloc
826 #endif
827 #ifndef Smem_freE
828 #define Smem_freE free
829 #endif
830
831
Sregex_string_cut(char ** handle,char * text,int len,int flag)832 int Sregex_string_cut(char **handle, char *text, int len, int flag)
833 /*
834 bit0= append (text!=NULL)
835 */
836 {
837 int l=0;
838 char *old_handle;
839
840 if((flag&1)&&*handle!=NULL)
841 l+= strlen(*handle);
842 old_handle= *handle;
843 if(text!=NULL) {
844 l+= len;
845 *handle= TSOB_FELD(char,l+1);
846 if(*handle==NULL) {
847 *handle= old_handle;
848 return(0);
849 }
850 if((flag&1) && old_handle!=NULL)
851 strcpy(*handle,old_handle);
852 else
853 (*handle)[0]= 0;
854 if(len>0)
855 strncat(*handle,text,len);
856 } else {
857 *handle= NULL;
858 }
859 if(old_handle!=NULL)
860 Smem_freE(old_handle);
861 return(1);
862 }
863
864
Sregex_string(char ** handle,char * text,int flag)865 int Sregex_string(char **handle, char *text, int flag)
866 /*
867 bit0= append (text!=NULL)
868 */
869 {
870 int ret,l=0;
871
872 if(text!=NULL)
873 l= strlen(text);
874
875 /* #define Sregex_looking_for_contenT 1 */
876 #ifdef Sregex_looking_for_contenT
877 /* a debugging point if a certain text content has to be caught */
878 if(text!=NULL)
879 if(strcmp(text,"clear")==0)
880 ret= 0;
881 #endif
882
883 ret= Sregex_string_cut(handle,text,l,flag&1);
884 return(ret);
885 }
886
887
888 /*
889 vars[][0] points to the variable names, vars[][1] to their contents.
890 start marks the begin of variable names. It must be non-empty. esc before
891 start disables this meaning. start and esc may be equal but else they must
892 have disjoint character sets.
893 end marks the end of a variable name. It may be empty but if non-empty it
894 must not appear in vars[][0].
895 @param flag bit0= Substitute unknown variables by empty text
896 (else copy start,name,end unaltered to result).
897 Parameter end must be non-empty for that.
898 */
Sregex_resolve_var(char * form,char * vars[][2],int num_vars,char * start,char * end,char * esc,char * result,int result_size,int flag)899 int Sregex_resolve_var(char *form, char *vars[][2], int num_vars,
900 char *start, char *end, char *esc,
901 char *result, int result_size, int flag)
902 {
903 int l_e, l_s, l_esc, i, start_equals_esc;
904 char *rpt, *wpt, *spt, *npt, *ept;
905
906 if(start[0] == 0) /* It is not allowed to have no start marker */
907 return(-1);
908 l_s= strlen(start);
909 l_e= strlen(end);
910 l_esc= strlen(esc);
911 start_equals_esc= !strcmp(start, esc);
912 rpt= form;
913 wpt= result;
914 wpt[0]= 0;
915 while(1) {
916
917 /* look for start mark */
918 spt= strstr(rpt, start);
919 if(spt == NULL) {
920 if((wpt - result) + (int) strlen(rpt) >= result_size)
921 return(0);
922 strcpy(wpt, rpt);
923 wpt+= strlen(wpt);
924 break;
925 }
926
927 /* copy cleartext part up to next variable */
928 if((wpt - result) + (spt - rpt) >= result_size)
929 return(0);
930 strncpy(wpt, rpt, spt - rpt);
931 wpt+= spt - rpt;
932 *wpt= 0;
933 rpt= spt;
934 npt= spt + l_s;
935
936 /* handle eventual escape */
937 if(start_equals_esc) {
938 if(strncmp(spt + l_s, esc, l_esc) == 0) {
939 /* copy esc and start */
940 if((wpt - result) + l_esc + l_s >= result_size)
941 return(0);
942 strncpy(wpt, spt, l_esc + l_s);
943 wpt+= l_esc + l_s;
944 rpt+= l_esc + l_s;
945 *wpt= 0;
946 continue;
947 }
948 } else {
949 /* escape would be already copied */
950 if(l_esc > 0 && spt - form >= l_esc) {
951 if(strncmp(spt - l_esc, esc, l_esc) == 0) {
952 /* copy start */
953 if((wpt - result) + l_s >= result_size)
954 return(0);
955 strncpy(wpt, spt, l_s);
956 wpt+= l_s;
957 rpt+= l_s;
958 *wpt= 0;
959 continue;
960 }
961 }
962 }
963
964 /* Memorize eventual end mark for default handling */;
965 ept= NULL;
966 if(l_e > 0)
967 ept= strstr(npt, end);
968
969 /* Look for defined variable name */
970 for(i = 0; i < num_vars; i++) {
971 if(strncmp(npt, vars[i][0], strlen(vars[i][0])) == 0
972 && (l_e == 0 || strncmp(npt + strlen(vars[i][0]), end, l_e) == 0))
973 break;
974 }
975 if(i < num_vars) {
976 /* substitute found variable */
977 if((wpt - result) + (int) strlen(vars[i][1]) >= result_size)
978 return(0);
979 strcpy(wpt, vars[i][1]);
980 rpt= npt + strlen(vars[i][0]) + l_e;
981 } else if((flag & 1) && ept != NULL) {
982 /* skip up to end mark */
983 rpt= ept + l_e;
984 } else if(ept != NULL) {
985 /* copy start,name,end */
986 if((wpt - result) + (ept - rpt) + l_e >= result_size)
987 return(0);
988 strncpy(wpt, rpt, (ept - rpt) + l_e);
989 rpt= ept + l_e;
990 } else {
991 /* copy start marker only */
992 if((wpt - result) + l_s >= result_size)
993 return(0);
994 strncpy(wpt, rpt, l_s);
995 rpt= rpt + l_s;
996 }
997 wpt+= strlen(wpt);
998 *wpt= 0;
999 }
1000 return(1);
1001 }
1002
1003
1004 /* @param flag bit0= only test expression whether compilable
1005 */
Sregex_match(char * pattern,char * text,int flag)1006 int Sregex_match(char *pattern, char *text, int flag)
1007 {
1008 int ret;
1009 char *re_text= NULL;
1010 regex_t re;
1011 regmatch_t match[1];
1012
1013 re_text= TSOB_FELD(char, 2 * SfileadrL);
1014 if(re_text == NULL)
1015 {ret= -1; goto ex;}
1016
1017 Xorriso__bourne_to_reg(pattern, re_text, 0);
1018 ret= regcomp(&re, re_text, 0);
1019 if(ret != 0)
1020 {ret= -1; goto ex;}
1021 if(flag & 1) {
1022 regfree(&re);
1023 {ret= 1; goto ex;}
1024 }
1025 ret= regexec(&re, text, 1, match, 0);
1026 regfree(&re);
1027 if(ret != 0)
1028 {ret= 0; goto ex;}
1029 ret= 1;
1030 ex:;
1031 if(re_text != NULL)
1032 free(re_text);
1033 return(ret);
1034 }
1035
1036
1037 #endif /* Xorriso_sregex_externaL */
1038
1039
1040
1041 /* @param flag bit0= append to out_text rather than overwrite it
1042 bit1= length limit is 10 * SfileadrL rather than 5 *
1043 */
Text_shellsafe(char * in_text,char * out_text,int flag)1044 char *Text_shellsafe(char *in_text, char *out_text, int flag)
1045 {
1046 int l,i,w=0, limit= 5 * SfileadrL;
1047
1048 if(flag&1)
1049 w= strlen(out_text);
1050 if(flag & 2)
1051 limit= 10 * SfileadrL;
1052 /* enclose everything by hard quotes */
1053 l= strlen(in_text);
1054 out_text[w++]= '\'';
1055 for(i=0;i<l;i++){
1056 if(in_text[i]=='\''){
1057 if(w + 7 > limit)
1058 goto overflow;
1059 /* escape hard quote within the text */
1060 out_text[w++]= '\'';
1061 out_text[w++]= '"';
1062 out_text[w++]= '\'';
1063 out_text[w++]= '"';
1064 out_text[w++]= '\'';
1065 } else {
1066 if(w + 3 > limit) {
1067 overflow:;
1068 strncpy(out_text, "'xorriso: TEXT MUCH TOO LONG ... ",33);
1069 break;
1070 }
1071 out_text[w++]= in_text[i];
1072 }
1073 }
1074 out_text[w++]= '\'';
1075 out_text[w++]= 0;
1076 return(out_text);
1077 }
1078
1079
Hex_to_bin(char * hex,int bin_size,int * bin_count,unsigned char * bin_data,int flag)1080 int Hex_to_bin(char *hex,
1081 int bin_size, int *bin_count, unsigned char *bin_data, int flag)
1082 {
1083 int i, l, acc;
1084
1085 l= strlen(hex);
1086 if(((l % 2) && l < 2 * bin_size) || l == 0)
1087 return(-1); /* malformed */
1088 *bin_count= 0;
1089 for(i= 0; i < l; i+= 2) {
1090 if(*bin_count >= bin_size)
1091 return(0); /* overflow */
1092 if(hex[i] >= '0' && hex[i] <= '9')
1093 acc= (hex[i] - '0') << 4;
1094 else if(hex[i] >= 'A' && hex[i] <= 'F')
1095 acc= (hex[i] - 'A' + 10) << 4;
1096 else if(hex[i] >= 'a' && hex[i] <= 'f')
1097 acc= (hex[i] - 'a' + 10) << 4;
1098 else
1099 return(-1);
1100 if(hex[i + 1] >= '0' && hex[i + 1] <= '9')
1101 acc|= (hex[i + 1] - '0');
1102 else if(hex[i + 1] >= 'A' && hex[i + 1] <= 'F')
1103 acc|= (hex[i + 1] - 'A' + 10);
1104 else if(hex[i + 1] >= 'a' && hex[i + 1] <= 'f')
1105 acc|= (hex[i + 1] - 'a' + 10);
1106 else
1107 return(-1);
1108 bin_data[*bin_count]= acc;
1109 (*bin_count)++;
1110 }
1111 return(1);
1112 }
1113
1114
1115 #ifndef Xorriso_fileliste_externaL
1116
1117 /* @param flag bit0= pathspec mode "on" rather than "as_mkisofs"
1118 */
Fileliste__target_source_limit(char * line,char sep,char ** limit_pt,int flag)1119 int Fileliste__target_source_limit(char *line, char sep, char **limit_pt,
1120 int flag)
1121 {
1122 char *npt;
1123
1124 for(npt= line;*npt!=0;npt++) {
1125 if(*npt=='\\') {
1126 if(*(npt + 1) == '=' || (*(npt + 1) == '\\' && !(flag & 1)))
1127 npt++;
1128 continue;
1129 }
1130 if(*npt=='=')
1131 break;
1132 }
1133 if(*npt==0)
1134 npt= NULL;
1135 (*limit_pt)= npt;
1136 return(npt!=NULL);
1137 }
1138
1139
Fileliste__escape_source_path(char * line,int size,int flag)1140 int Fileliste__escape_source_path(char *line, int size, int flag)
1141 {
1142 int l, count= 0, i;
1143 char *wpt;
1144
1145 l= strlen(line);
1146 for(i= 0; i < l; i++)
1147 if(line[i] == '=' || line[i] == '\\')
1148 count++;
1149 if(l + count >= size)
1150 return(0);
1151
1152 wpt= line + l + count;
1153 for(i= l; i >= 0; i--) {
1154 *(wpt--)= line[i];
1155 if(line[i] == '=' || line[i] == '\\')
1156 *(wpt--)= '\\';
1157 }
1158 return(1);
1159 }
1160
1161
Xorriso__bourne_to_reg(char bourne_expr[],char reg_expr[],int flag)1162 int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag)
1163 /* reg_expr should be twice as large as bourne_expr ( + 2 to be exact) */
1164 /* return: 2= bourne_expr is surely a constant */
1165 {
1166 char *wpt,*lpt;
1167 int backslash= 0,is_constant= 1,in_square_brackets= 0;
1168 int first_in_square_brackets=0;
1169
1170 wpt= reg_expr;
1171 lpt= bourne_expr;
1172
1173 *(wpt++)= '^';
1174
1175 while(*lpt!=0){
1176 if(first_in_square_brackets>0)
1177 first_in_square_brackets--;
1178 if(!backslash){
1179 switch(*lpt){
1180 case '?':
1181 *(wpt++)= '.';
1182 is_constant= 0;
1183 break;case '*':
1184 *(wpt++)= '.';
1185 *(wpt++)= '*';
1186 is_constant= 0;
1187 break;case '.':
1188 *(wpt++)= '\\';
1189 *(wpt++)= '.';
1190 break;case '+':
1191 *(wpt++)= '\\';
1192 *(wpt++)= '+';
1193 break;case '[':
1194 *(wpt++)= *lpt;
1195 first_in_square_brackets= 2;
1196 in_square_brackets= 1;
1197 is_constant= 0;
1198 break;case ']':
1199 *(wpt++)= *lpt;
1200 in_square_brackets= 0;
1201 break;case '!':
1202 if(first_in_square_brackets)
1203 *(wpt++)= '^';
1204 else if(in_square_brackets)
1205 *(wpt++)= '!';
1206 else {
1207 *(wpt++)= '\\';
1208 *(wpt++)= '!';
1209 }
1210 break;case '^':
1211 if(in_square_brackets) {
1212 *(wpt++)= '^';
1213 } else {
1214 *(wpt++)= '\\';
1215 *(wpt++)= '^';
1216 }
1217 break;case '$':
1218 *(wpt++)= '\\';
1219 *(wpt++)= '$';
1220 break;case '\\':
1221 backslash= 1;
1222 *(wpt++)= '\\';
1223 is_constant= 0;
1224 break;default:
1225 *(wpt++)= *lpt;
1226 }
1227 } else {
1228 backslash= 0;
1229 *(wpt++)= *lpt;
1230 }
1231 lpt++;
1232 }
1233 *(wpt++)= '$';
1234 *wpt= 0;
1235 return(1+(is_constant>0));
1236 }
1237
1238
1239 #endif /* ! Xorriso_fileliste_externaL */
1240
1241
Xorriso__hide_mode(char * mode,int flag)1242 int Xorriso__hide_mode(char *mode, int flag)
1243 {
1244 char *npt, *cpt;
1245 int l, value= 0;
1246
1247 npt= cpt= mode;
1248 for(; npt!=NULL; cpt= npt+1) {
1249 npt= strchr(cpt,':');
1250 if(npt==NULL)
1251 l= strlen(cpt);
1252 else
1253 l= npt-cpt;
1254 if(l == 0)
1255 continue;
1256 if(l == 2 && strncmp(cpt, "on", l) == 0)
1257 value= 1 | 2 | 4;
1258 else if(l == 6 && strncmp(cpt, "iso_rr", l) == 0)
1259 value |= 1;
1260 else if(l == 6 && strncmp(cpt, "joliet", l) == 0)
1261 value |= 2;
1262 else if(l == 7 && strncmp(cpt, "hfsplus", l) == 0)
1263 value |= 4;
1264 else if(l == 3 && strncmp(cpt, "off", l) == 0)
1265 value= 0;
1266 else
1267 return(-1);
1268 }
1269 return(value);
1270 }
1271
1272
Xorriso__hide_mode_text(int hide_mode,int flag)1273 char *Xorriso__hide_mode_text(int hide_mode, int flag)
1274 {
1275 char *acc= NULL;
1276
1277 acc = calloc(1, 80);
1278 if(acc == NULL)
1279 return(NULL);
1280 acc[0]= 0;
1281 if(hide_mode == 0) {
1282 strcat(acc, "off:");
1283 } else if(hide_mode == 7) {
1284 strcat(acc, "on:");
1285 } else {
1286 if(hide_mode & 1)
1287 strcat(acc, "iso_rr:");
1288 if(hide_mode & 2)
1289 strcat(acc, "joliet:");
1290 if(hide_mode & 4)
1291 strcat(acc, "hfsplus:");
1292 }
1293 if(acc[0])
1294 acc[strlen(acc) - 1]= 0; /* cut off last colon */
1295 return acc;
1296 }
1297
1298
1299 /* @return 0=truncated, 1=ok
1300 */
Xorriso__to_upper(char * in,char * out,int out_size,int flag)1301 int Xorriso__to_upper(char *in, char *out, int out_size, int flag)
1302 {
1303 int i;
1304
1305 for(i= 0; i < out_size - 1 && in[i] != 0; i++)
1306 if(isalpha(in[i]))
1307 out[i]= toupper(in[i]);
1308 else
1309 out[i]= in[i];
1310 out[i]= 0;
1311 return(in[i] == 0);
1312 }
1313
1314
1315 /* @param flag bit0= prepend target_prefix even if source_prefix does not get
1316 removed
1317 */
Xorriso__exchange_prefix(char * source_prefix,char * target_prefix,char * eff_source,char * eff_target,int flag)1318 int Xorriso__exchange_prefix(char *source_prefix, char *target_prefix,
1319 char *eff_source, char *eff_target, int flag)
1320 {
1321 char *source_pt;
1322
1323 strcpy(eff_target, target_prefix);
1324 source_pt= eff_source;
1325 if(source_prefix[0]) {
1326 if(strncmp(source_prefix, eff_source, strlen(source_prefix)) != 0) {
1327 if(!(flag & 1))
1328 return(0);
1329 } else {
1330 source_pt+= strlen(source_prefix);
1331 }
1332 }
1333 strcat(eff_target, source_pt);
1334 return(1);
1335 }
1336
1337