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