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(&current_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