1 
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3 
4    Copyright 2007-2013 Thomas Schmitt, <scdbackup@gmx.net>
5 
6    Provided under GPL version 2 or later.
7 
8    This file contains the implementation of functions for pattern matching.
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 <fcntl.h>
25 #include <errno.h>
26 
27 #include "xorriso.h"
28 #include "xorriso_private.h"
29 #include "xorrisoburn.h"
30 
31 
32 /* @param flag bit0= do not augment relative structured search by xorriso->wdi
33                bit1= return 2 if bonked at start point by ..
34                      (caller then aborts or retries without bit0)
35                bit2= eventually prepend wdx rather than wdi
36    @return <=0 error, 1= ok, 2= with bit1: relative pattern exceeds start point
37 */
Xorriso_prepare_regex(struct XorrisO * xorriso,char * adr,int flag)38 int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag)
39 {
40  int l,ret,i,count,bonked= 0,is_constant,is_still_relative= 0, adr_size;
41  char *cpt,*npt,*adr_part= NULL, *absolute_adr= NULL, *adr_start,*wd;
42 
43  adr_size= 2 * SfileadrL;
44  Xorriso_alloc_meM(adr_part, char, adr_size);
45  Xorriso_alloc_meM(absolute_adr, char, adr_size);
46 
47  if(flag&4)
48    wd= xorriso->wdx;
49  else
50    wd= xorriso->wdi;
51 
52  if(xorriso->search_mode>=2 && xorriso->search_mode<=4) {
53    if(xorriso->search_mode==3 || xorriso->search_mode==4) {
54      l= strlen(adr)+strlen(wd)+1;
55      if(l * 2 + 2 > ((int) sizeof(xorriso->reg_expr)) || l * 2 + 2 > adr_size){
56        sprintf(xorriso->info_text,"Search pattern too long");
57        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
58        {ret= 0; goto ex;}
59      }
60    }
61    Xorriso_destroy_re(xorriso,0);
62    if(xorriso->structured_search && xorriso->search_mode==3) {
63      if(adr[0]!='/')
64        is_still_relative= 1;
65      if(is_still_relative && !(flag&1)) {
66        /* relative expression : prepend working directory */
67        sprintf(absolute_adr,"%s/%s",wd,adr);
68        adr_start= absolute_adr;
69        xorriso->prepended_wd= 1;
70        is_still_relative= 0;
71      } else
72        adr_start= adr;
73      /* count slashes */;
74      cpt= adr_start;
75      while(*cpt=='/')
76        cpt++;
77      for(i= 0;1;i++) {
78        cpt= strchr(cpt,'/');
79        if(cpt==NULL)
80      break;
81        while(*cpt=='/')
82          cpt++;
83      }
84      count= i+1;
85      xorriso->re= TSOB_FELD(regex_t,count);
86      if(xorriso->re==NULL)
87        {ret= -1; goto ex;}
88      xorriso->re_constants= TSOB_FELD(char *,count);
89      if(xorriso->re_constants==NULL)
90        {ret= -1; goto ex;}
91      for(i= 0;i<count;i++)
92        xorriso->re_constants[i]= NULL;
93      xorriso->re_count= count;
94      xorriso->re_fill= 0;
95 
96      /* loop over slash chunks*/;
97      cpt= adr_start;
98      xorriso->re_fill= 0;
99      while(*cpt=='/')
100        cpt++;
101      for(i= 0;i<count;i++) {
102        npt= strchr(cpt,'/');
103        if(npt==NULL) {
104          if((int) strlen(cpt) >= adr_size)
105            {ret= -1; goto ex;}
106          strcpy(adr_part,cpt);
107        } else {
108          if(npt-cpt >= adr_size)
109            {ret= -1; goto ex;}
110          strncpy(adr_part,cpt,npt-cpt);
111          adr_part[npt-cpt]= 0;
112        }
113 
114        if(adr_part[0]==0)
115          goto next_adr_part;
116        if(adr_part[0]=='.' && adr_part[1]==0 &&
117           (xorriso->re_fill>0 || i<count-1))
118          goto next_adr_part;
119        if(adr_part[0]=='.' && adr_part[1]=='.' && adr_part[2]==0) {
120          /* delete previous part */
121          if(xorriso->re_fill <= 0) {
122            bonked= 1;
123            goto next_adr_part;
124          }
125          if(xorriso->re_constants[xorriso->re_fill-1]!=NULL) {
126            free(xorriso->re_constants[xorriso->re_fill-1]);
127            xorriso->re_constants[xorriso->re_fill-1]= NULL;
128          } else
129            regfree(&(xorriso->re[xorriso->re_fill-1]));
130          (xorriso->re_fill)--;
131          goto next_adr_part;
132        }
133        if(strcmp(adr_part,"*")==0) {
134          adr_part[0]= 0;
135          ret= 2;
136        } else
137          ret= Xorriso__bourne_to_reg(adr_part,xorriso->reg_expr,0);
138        if(ret==2) {
139          if(Sregex_string(&(xorriso->re_constants[xorriso->re_fill]),adr_part,0)
140             <=0)
141            {ret= -1; goto ex;}
142        } else {
143          if(regcomp(&(xorriso->re[xorriso->re_fill]),xorriso->reg_expr,0)!=0)
144            goto cannot_compile;
145        }
146        xorriso->re_fill++;
147 next_adr_part:;
148        if(i==count-1)
149      break;
150        cpt= npt+1;
151        while(*cpt=='/')
152          cpt++;
153      }
154      if(bonked) {
155        if(flag&2)
156          {ret= 2; goto ex;}
157        sprintf(xorriso->info_text, "Your '..' bonked at the %s directory.",
158                is_still_relative ? "working" : "root");
159        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
160        {ret= 0; goto ex;}
161      }
162 
163      Xorriso__bourne_to_reg(adr_start,xorriso->reg_expr,0); /* just for show */
164 
165    } else {
166      is_constant= 0;
167      if(strcmp(adr,"*")==0 || adr[0]==0) {
168        is_constant= 1;
169      } else if(xorriso->search_mode==3 || xorriso->search_mode==4) {
170        ret= Xorriso__bourne_to_reg(adr,xorriso->reg_expr,0);
171        is_constant= (ret==2);
172      } else {
173        if(strlen(adr)>=sizeof(xorriso->reg_expr))
174          {ret= -1; goto ex;}
175        strcpy(xorriso->reg_expr,adr);
176      }
177      xorriso->re_count= 0; /* tells matcher that this is not structured */
178      xorriso->re_constants= TSOB_FELD(char *,1);
179      if(xorriso->re_constants==NULL)
180        {ret= -1; goto ex;}
181      xorriso->re_constants[0]= NULL;
182      if(is_constant) {
183        if(strcmp(adr,"*")==0) {
184          if(Sregex_string(&(xorriso->re_constants[0]),"",0)<=0)
185            {ret= -1; goto ex;}
186        } else {
187          if(Sregex_string(&(xorriso->re_constants[0]),adr,0)<=0)
188            {ret= -1; goto ex;}
189        }
190        xorriso->re_fill= 1;
191      } else {
192        xorriso->re= TSOB_FELD(regex_t,1);
193        if(xorriso->re==NULL)
194          {ret= -1; goto ex;}
195        if(regcomp(&(xorriso->re[0]),xorriso->reg_expr,0)!=0) {
196 cannot_compile:;
197          sprintf(xorriso->info_text, "Cannot compile regular expression : %s",
198                  xorriso->reg_expr);
199          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
200          {ret= 0; goto ex;}
201        }
202      }
203 
204    }
205  }
206  ret= 1;
207 ex:;
208  Xorriso_free_meM(adr_part);
209  Xorriso_free_meM(absolute_adr);
210  return(ret);
211 }
212 
213 
214 /* @param flag bit0= do not shortcut last component of to_match
215                bit1= consider match if regex matches parent of path
216                bit2= retry beginning at failed last component
217 
218  @return 0=match , else no match
219 */
Xorriso_regexec(struct XorrisO * xorriso,char * to_match,int * failed_at,int flag)220 int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at,
221                     int flag)
222 {
223  int ret,i,re_start= 0,reg_nomatch= -1;
224  char *cpt,*npt, *adr_part= NULL, *mpt;
225 
226  Xorriso_alloc_meM(adr_part, char, SfileadrL);
227 
228  reg_nomatch= REG_NOMATCH;
229 
230  *failed_at= 0;
231  if(!(xorriso->structured_search && xorriso->re_count>0)) {
232    if(xorriso->re_constants!=NULL)
233      if(xorriso->re_constants[0]!=NULL) {
234        if(xorriso->re_constants[0][0]==0)
235          {ret= 0; goto ex;}
236        if(strcmp(xorriso->re_constants[0],to_match)!=0)
237          {ret= reg_nomatch; goto ex;}
238        {ret= 0; goto ex;}
239      }
240    ret= regexec(&(xorriso->re[0]),to_match,1,xorriso->match,0);
241    goto ex;
242  }
243 
244  cpt= to_match;
245  while(*cpt=='/')
246   cpt++;
247  if(flag&4)
248    re_start= xorriso->re_failed_at;
249  if(re_start<0)
250    re_start= 0;
251  for(i= re_start;i<xorriso->re_fill;i++) {
252    *failed_at= i;
253    npt= strchr(cpt,'/');
254    if(npt==NULL) {
255      if(i<xorriso->re_fill-1 && !(flag&1))
256        {ret= reg_nomatch; goto ex;} /* this must be the last expression part */
257      mpt= cpt;
258    } else {
259      strncpy(adr_part,cpt,npt-cpt);
260      adr_part[npt-cpt]= 0;
261      mpt= adr_part;
262    }
263    if(xorriso->re_constants[i]!=NULL) {
264      if(xorriso->re_constants[i][0]!=0) /* empty constant matches anything */
265        if(strcmp(xorriso->re_constants[i],mpt)!=0)
266          {ret= reg_nomatch; goto ex;}
267    } else {
268      ret= regexec(&(xorriso->re[i]),mpt,1,xorriso->match,0);
269      if(ret!=0)
270        goto ex;
271    }
272    if(npt==NULL) {
273      if(i>=xorriso->re_fill-1)
274        {ret= 0; goto ex;} /* MATCH */
275      *failed_at= i+1;
276      {ret= reg_nomatch; goto ex;}
277    }
278    cpt= npt+1;
279    while(*cpt=='/')
280      cpt++;
281  }
282  *failed_at= xorriso->re_fill;
283  if(flag & 2)
284    {ret= 0; goto ex;} /* MATCH */
285  ret= reg_nomatch;
286 ex:;
287  Xorriso_free_meM(adr_part);
288  return(ret);
289 }
290 
291 
Xorriso_is_in_patternlist(struct XorrisO * xorriso,struct Xorriso_lsT * patternlist,char * path,int flag)292 int Xorriso_is_in_patternlist(struct XorrisO *xorriso,
293                               struct Xorriso_lsT *patternlist, char *path,
294                               int flag)
295 {
296  int ret, failed_at, i= 0;
297  struct Xorriso_lsT *s;
298 
299  xorriso->search_mode= 3;
300  xorriso->structured_search= 1;
301 
302  for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
303    ret= Xorriso_prepare_regex(xorriso, Xorriso_lst_get_text(s, 0), 0);
304    if(ret <= 0)
305      return(-1);
306    /* Match path or parent of path */
307    ret= Xorriso_regexec(xorriso, path, &failed_at, 2);
308    if(ret == 0)
309      return(i + 1);
310    i++;
311  }
312  return(0);
313 }
314 
315 
Xorriso_get_pattern(struct XorrisO * xorriso,struct Xorriso_lsT * patternlist,int index,int flag)316 char *Xorriso_get_pattern(struct XorrisO *xorriso,
317                           struct Xorriso_lsT *patternlist, int index, int flag)
318 {
319  int i= 0;
320  struct Xorriso_lsT *s;
321 
322  for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
323    if(i == index)
324      return(Xorriso_lst_get_text(s, 0));
325    i++;
326  }
327  return(NULL);
328 }
329 
330 
331 
332 /* @param flag bit2= this is a disk_pattern
333    @return <=0 failure , 1 pattern ok , 2 pattern needed prepended wd */
Xorriso_prepare_expansion_pattern(struct XorrisO * xorriso,char * pattern,int flag)334 int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern,
335                                       int flag)
336 {
337  int ret, prepwd= 0;
338 
339  ret= Xorriso_prepare_regex(xorriso, pattern, 1|2|(flag&4));
340  if(ret==2) {
341    ret= Xorriso_prepare_regex(xorriso, pattern, flag&4);
342    prepwd= 1;
343  }
344  if(ret<=0) {
345    sprintf(xorriso->info_text,
346            "Cannot compile pattern to regular expression:  %s", pattern);
347    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
348    return(0);
349  }
350  return(1+prepwd);
351 }
352 
353 
354 /* @param flag bit0= count results rather than storing them
355                bit1= unexpected change of number is a FATAL event
356    @return <=0 error , 1 is root (end processing) ,
357                        2 is not root (go on processing)
358 */
Xorriso_check_for_root_pattern(struct XorrisO * xorriso,int * filec,char ** filev,int count_limit,off_t * mem,int flag)359 int Xorriso_check_for_root_pattern(struct XorrisO *xorriso,
360                int *filec, char **filev, int count_limit, off_t *mem, int flag)
361 {
362  if(xorriso->re_fill!=0)
363    return(2);
364  /* This is the empty pattern representing root */
365  if(flag&1) {
366    (*filec)++;
367    (*mem)+= 8;
368  } else {
369    if(*filec >= count_limit) {
370      sprintf(xorriso->info_text,
371             "Number of matching files changed unexpectedly (> %d)",
372              count_limit);
373      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
374                          (flag&2 ? "FATAL" : "WARNING"), 0);
375      return(flag&2 ? -1 : 0);
376    }
377    filev[*filec]= strdup("/");
378    if(filev[*filec]==NULL) {
379      Xorriso_no_pattern_memory(xorriso, (off_t) 2, 0);
380      return(-1);
381    }
382    (*filec)++;
383  }
384  return(1);
385 }
386 
387 
388 /* @param flag bit0= count result rather than storing it
389                bit1= unexpected change of number is a FATAL event
390 */
Xorriso_register_matched_adr(struct XorrisO * xorriso,char * adr,int count_limit,int * filec,char ** filev,off_t * mem,int flag)391 int Xorriso_register_matched_adr(struct XorrisO *xorriso,
392                                 char *adr, int count_limit,
393                                 int *filec, char **filev, off_t *mem, int flag)
394 {
395  int l;
396 
397  if(flag&1) {
398    (*filec)++;
399    l= strlen(adr)+1;
400    (*mem)+= sizeof(char *)+l;
401    if(l % sizeof(char *))
402      (*mem)+= sizeof(char *)-(l % sizeof(char *));
403  } else {
404    if(*filec >= count_limit) {
405      sprintf(xorriso->info_text,
406          "Number of matching files changed unexpectedly (> %d)",
407          count_limit);
408      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
409                          (flag&2 ? "FATAL" : "WARNING"), 0);
410      return(flag&2 ? -1 : 0);
411    }
412    filev[*filec]= strdup(adr);
413    if(filev[*filec]==NULL) {
414      Xorriso_no_pattern_memory(xorriso, (off_t) (strlen(adr)+1), 0);
415      return(-1);
416    }
417    (*filec)++;
418  }
419  return(1);
420 }
421 
422 
423 /* @param flag bit0= count results rather than storing them
424                bit1= this is a recursion
425                bit2= prepend wd (automatically done if wd[0]!=0)
426    @return <=0 error , 1 ok , 2 could not open directory
427 */
Xorriso_obtain_pattern_files_x(struct XorrisO * xorriso,char * wd,char * dir_adr,int * filec,char ** filev,int count_limit,off_t * mem,int * dive_count,int flag)428 int Xorriso_obtain_pattern_files_x(
429        struct XorrisO *xorriso, char *wd, char *dir_adr,
430        int *filec, char **filev, int count_limit, off_t *mem,
431        int *dive_count, int flag)
432 {
433  int ret, failed_at, follow_mount, follow_links;
434  struct DirseQ *dirseq= NULL;
435  struct stat stbuf;
436  dev_t dir_dev;
437  char *path;
438  char *adr= NULL, *name= NULL, *path_data= NULL;
439 
440  adr= malloc(SfileadrL);
441  name= malloc(SfileadrL);
442  path_data= malloc(SfileadrL);
443  if(adr==NULL || name==NULL || path_data==NULL) {
444    Xorriso_no_malloc_memory(xorriso, &adr, 0);
445    {ret= -1; goto ex;}
446  }
447  follow_mount= (xorriso->do_follow_mount || xorriso->do_follow_pattern);
448  follow_links= (xorriso->do_follow_links || xorriso->do_follow_pattern);
449  if(!(flag&2))
450    *dive_count= 0;
451  else
452    (*dive_count)++;
453 
454  ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit,
455                                      mem, flag&1);
456  if(ret!=2)
457    goto ex;
458 
459  if(lstat(dir_adr, &stbuf)==-1)
460    {ret= 2; goto ex;}
461  dir_dev= stbuf.st_dev;
462  if(S_ISLNK(stbuf.st_mode)) {
463    if(stat(dir_adr, &stbuf)==-1)
464      {ret= 2; goto ex;}
465    if(dir_dev != stbuf.st_dev && !follow_mount)
466      {ret= 2; goto ex;}
467  }
468  ret= Dirseq_new(&dirseq, dir_adr, 1);
469  if(ret<0) {
470    sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
471    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
472    {ret= -1; goto ex;}
473  }
474  if(ret==0)
475    {ret= 2; goto ex;}
476 
477  while(1) {
478    ret= Dirseq_next_adr(dirseq,name,0);
479    if(ret==0)
480  break;
481    if(ret<0) {
482      sprintf(xorriso->info_text,"Failed to obtain next directory entry");
483      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
484      {ret= -1; goto ex;}
485    }
486 
487    ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4);
488    if(ret<=0)
489      goto ex;
490 
491    ret= Xorriso_regexec(xorriso, adr, &failed_at, 1);
492    if(ret>0) { /* no match */
493      if(failed_at <= *dive_count) /* no hope for a match */
494  continue;
495      path= adr;
496      if(adr[0]!='/') {
497        path= path_data;
498        ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, adr, path, 1|4);
499        if(ret<=0)
500          goto ex;
501      }
502 
503      if(follow_links)
504        ret= stat(path,&stbuf);
505      else
506        ret= lstat(path,&stbuf);
507      if(ret==-1)
508  continue;
509      if(!S_ISDIR(stbuf.st_mode))
510  continue;
511      if(dir_dev != stbuf.st_dev && !follow_mount)
512  continue;
513 
514      /* dive deeper */
515      ret= Xorriso_obtain_pattern_files_x(xorriso, adr, path,
516                            filec, filev, count_limit, mem, dive_count, flag|2);
517      if(ret<=0)
518        goto ex;
519    } else {
520      ret= Xorriso_register_matched_adr(xorriso, adr, count_limit,
521                                        filec, filev, mem, flag&1);
522      if(ret<0)
523        goto ex;
524      if(ret==0)
525  break;
526    }
527  }
528  ret= 1;
529 ex:;
530  if(adr!=NULL)
531    free(adr);
532  if(name!=NULL)
533    free(name);
534  if(path_data!=NULL)
535    free(path_data);
536  Dirseq_destroy(&dirseq,0);
537  if(flag&2)
538    (*dive_count)--;
539  return(ret);
540 }
541 
542 
Xorriso_eval_nonmatch(struct XorrisO * xorriso,char * pattern,int * nonconst_mismatches,off_t * mem,int flag)543 int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern,
544                           int *nonconst_mismatches, off_t *mem, int flag)
545 {
546  int k,l;
547 
548  /* Is this a constant pattern ? */
549  for(k= 0; k<xorriso->re_fill; k++) {
550    if(xorriso->re_constants[k]==NULL)
551  break;
552    if(xorriso->re_constants[k][0]==0)
553  break;
554  }
555  if(k<xorriso->re_fill)
556    (*nonconst_mismatches)++; /* it is not */
557 
558  l= strlen(pattern)+1;
559  (*mem)+= sizeof(char *)+l;
560  if(l % sizeof(char *))
561    (*mem)+= sizeof(char *)-(l % sizeof(char *));
562  return(1);
563 }
564 
565 
566 /* @param flag bit0= a match count !=1 is a SORRY event
567                bit1= a match count !=1 is a FAILURE event
568 */
Xorriso_check_matchcount(struct XorrisO * xorriso,int count,int nonconst_mismatches,int num_patterns,char ** patterns,int flag)569 int Xorriso_check_matchcount(struct XorrisO *xorriso,
570                 int count, int nonconst_mismatches, int num_patterns,
571                 char **patterns, int flag)
572 {
573 
574  if((flag&1) && (count!=1 || nonconst_mismatches)){
575    if(count-nonconst_mismatches>0)
576      sprintf(xorriso->info_text,
577              "Pattern match with more than one file object");
578    else
579      sprintf(xorriso->info_text, "No pattern match with any file object");
580    if(num_patterns==1)
581      sprintf(xorriso->info_text+strlen(xorriso->info_text), ": ");
582    Text_shellsafe(patterns[0], xorriso->info_text, 1);
583    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
584                        (flag&2 ? "FAILURE" : "SORRY"), 0);
585    return(0);
586  }
587  return(1);
588 }
589 
590 
Xorriso_no_pattern_memory(struct XorrisO * xorriso,off_t mem,int flag)591 int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag)
592 {
593  char mem_text[80];
594 
595  Sfile_scale((double) mem, mem_text,5,1e4,1);
596  sprintf(xorriso->info_text,
597          "Cannot allocate enough memory (%s) for pattern expansion",
598          mem_text);
599  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
600  return(1);
601 }
602 
603 
Xorriso_alloc_pattern_mem(struct XorrisO * xorriso,off_t mem,int count,char *** filev,int flag)604 int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem,
605                               int count, char ***filev, int flag)
606 {
607  char mem_text[80], limit_text[80];
608 
609  Sfile_scale((double) mem, mem_text,5,1e4,0);
610  sprintf(xorriso->info_text,
611          "Temporary memory needed for pattern expansion : %s", mem_text);
612  if(!(flag&1))
613    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
614  if(mem > xorriso->temp_mem_limit) {
615    Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1);
616    sprintf(xorriso->info_text,
617            "List of matching file addresses exceeds -temp_mem_limit (%s > %s)",
618            mem_text, limit_text);
619    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
620    return(0);
621  }
622 
623  (*filev)= (char **) calloc(count, sizeof(char *));
624  if(*filev==NULL) {
625    Xorriso_no_pattern_memory(xorriso, mem, 0);
626    return(-1);
627  }
628  return(1);
629 }
630 
631 
632 /* @param flag bit0= a match count !=1 is a FAILURE event
633                bit1= with bit0 tolerate 0 matches if pattern is a constant
634                bit3= do not add unresolved pattern to filev
635 */
Xorriso_expand_disk_pattern(struct XorrisO * xorriso,int num_patterns,char ** patterns,int extra_filec,int * filec,char *** filev,off_t * mem,int flag)636 int Xorriso_expand_disk_pattern(struct XorrisO *xorriso,
637                            int num_patterns, char **patterns, int extra_filec,
638                            int *filec, char ***filev, off_t *mem, int flag)
639 {
640  int ret, count= 0, abs_adr= 0, i, was_count, was_filec;
641  int nonconst_mismatches= 0, dive_count= 0;
642  char *dir_adr= NULL;
643 
644  Xorriso_alloc_meM(dir_adr, char, SfileadrL);
645 
646  *filec= 0;
647  *filev= NULL;
648 
649  xorriso->search_mode= 3;
650  xorriso->structured_search= 1;
651 
652  for(i= 0; i<num_patterns; i++) {
653    abs_adr= 0;
654    ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
655    if(ret<=0)
656      goto ex;
657    if(ret==2)
658      abs_adr= 4;
659 
660    if(patterns[i][0]=='/' || abs_adr) {
661      strcpy(dir_adr, "/");
662      abs_adr= 4;
663    } else {
664      strcpy(dir_adr, xorriso->wdx);
665      if(dir_adr[0]==0)
666        strcpy(dir_adr, "/");
667      ret= Sfile_type(dir_adr, 1|4);
668      if(ret!=2) {
669        Xorriso_msgs_submit(xorriso, 0, dir_adr, 0, "ERRFILE", 0);
670        sprintf(xorriso->info_text, "Address set by -cdx is not a directory: ");
671        Text_shellsafe(dir_adr, xorriso->info_text, 1);
672        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
673        ret= 0; goto ex;
674      }
675    }
676 
677    /* count the matches */
678    was_count= count;
679    ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, &count, NULL, 0,
680                                        mem, &dive_count, 1 | abs_adr);
681    if(ret<=0)
682      goto ex;
683    if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1 &&
684       !(flag & 8)) {
685      count++;
686      ret= Xorriso_eval_nonmatch(xorriso, patterns[i],
687                                 &nonconst_mismatches, mem, 0);
688      if(ret<=0)
689        goto ex;
690    }
691  }
692 
693  ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches,
694                                num_patterns, patterns, (flag&1)|2);
695  if(ret<=0)
696    goto ex;
697 
698  count+= extra_filec;
699  (*mem)+= extra_filec * sizeof(char *);
700 
701  if(count<=0)
702    {ret= !(flag & 8); goto ex;}
703 
704  ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, 0);
705  if(ret<=0)
706    goto ex;
707 
708  /* now store addresses */
709  for(i= 0; i<num_patterns; i++) {
710    abs_adr= 0;
711    ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
712    if(ret<=0)
713      goto ex;
714    if(ret==2)
715      abs_adr= 4;
716 
717    if(patterns[i][0]=='/' || abs_adr) {
718      strcpy(dir_adr, "/");
719      abs_adr= 4;
720    } else {
721      strcpy(dir_adr, xorriso->wdx);
722      if(dir_adr[0]==0)
723        strcpy(dir_adr, "/");
724    }
725 
726    was_filec= *filec;
727    ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, filec, *filev,
728                                        count, mem, &dive_count, abs_adr);
729    if(ret<=0)
730      goto ex;
731 
732    if(was_filec == *filec && strcmp(patterns[i],"*")!=0 && (flag & 3) != 1 &&
733       !(flag & 8)) {
734      (*filev)[*filec]= strdup(patterns[i]);
735      if((*filev)[*filec]==NULL) {
736        (*mem)= strlen(patterns[i])+1;
737        Xorriso_no_pattern_memory(xorriso, *mem, 0);
738        ret= -1; goto ex;
739      }
740      (*filec)++;
741    }
742  }
743 
744  ret= 1;
745 ex:;
746  if(ret<=0) {
747    if(filev!=NULL)
748      Sfile_destroy_argv(&count, filev, 0);
749    *filec= 0;
750  }
751  Xorriso_free_meM(dir_adr);
752  return(ret);
753 }
754 
755 
756 /* @param flag bit0= command without pattern capability
757                bit1= disk_pattern rather than iso_rr_pattern
758 */
Xorriso_warn_of_wildcards(struct XorrisO * xorriso,char * path,int flag)759 int Xorriso_warn_of_wildcards(struct XorrisO *xorriso, char *path, int flag)
760 {
761  static int count_iso= 0, count_disk= 0, max_iso= 3, max_disk= 3;
762 
763  if(strchr(path,'*')!=NULL || strchr(path,'?')!=NULL ||
764     strchr(path,'[')!=NULL) {
765    if(flag & 2) {
766      count_disk++;
767      if(count_disk > max_disk)
768        return(1);
769    } else {
770      count_iso++;
771      if(count_iso > max_iso)
772        return(1);
773    }
774    if(flag&1) {
775      sprintf(xorriso->info_text,
776       "Pattern expansion of wildcards \"*?[\" does not apply to this command");
777    } else {
778      sprintf(xorriso->info_text,
779             "Pattern expansion of wildcards \"*?[\" is disabled by command %s",
780             (flag&2) ? "-disk_pattern or -pathspecs" : "-iso_rr_pattern");
781    }
782    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
783    sprintf(xorriso->info_text,"Pattern seen: ");
784    Text_shellsafe(path, xorriso->info_text, 1);
785    strcat(xorriso->info_text, "\n");
786    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
787    return(1);
788  }
789  return(0);
790 }
791 
792