1 
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3 
4    Copyright 2007-2016 Thomas Schmitt, <scdbackup@gmx.net>
5 
6    Provided under GPL version 2 or later.
7 
8    This file contains the implementation of classes FindjoB, ExprnodE,
9    ExprtesT which perform tree searches in libisofs or in POSIX filesystem
10 */
11 
12 #ifdef HAVE_CONFIG_H
13 #include "../config.h"
14 #endif
15 
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <time.h>
25 #include <dirent.h>
26 #include <errno.h>
27 
28 
29 #include "xorriso.h"
30 #include "xorriso_private.h"
31 #include "xorrisoburn.h"
32 
33 
34 /* ----------------------- Exprtest ----------------------- */
35 
36 
Exprtest_new(struct ExprtesT ** ftest,struct FindjoB * boss,int flag)37 int Exprtest_new( struct ExprtesT **ftest, struct FindjoB *boss, int flag)
38 {
39  struct ExprtesT *f;
40 
41  *ftest= f= TSOB_FELD(struct ExprtesT,1);
42  if(f==NULL)
43    return(-1);
44  f->boss= boss;
45  f->invert= 0;
46  f->test_type= -1;
47  f->arg1= NULL;
48  f->arg2= NULL;
49  return(1);
50 }
51 
52 
Exprtest_destroy(struct ExprtesT ** ftest,int flag)53 int Exprtest_destroy(struct ExprtesT **ftest, int flag)
54 {
55  struct ExprtesT *f;
56 
57  f= *ftest;
58  if(f==NULL)
59    return(0);
60 
61  if(f->test_type == 1 || f->test_type == 13 || f->test_type == 16) {
62    if(f->arg1 != NULL)
63      free(f->arg1);
64    if(f->arg2 != NULL) {
65      regfree(f->arg2);
66      free(f->arg2);
67    }
68  } else if(f->test_type == 9) {
69    /* arg1 is not an allocated value */;
70  } else {
71    if(f->arg1 != NULL)
72      free(f->arg1);
73    if(f->arg2 != NULL)
74      free(f->arg2);
75  }
76  free((char *) f);
77  *ftest= NULL;
78  return(1);
79 }
80 
81 
82 /* ----------------------- Nttpfnode ----------------------- */
83 
84 
Exprnode_new(struct ExprnodE ** fnode,struct FindjoB * job,struct ExprnodE * up,char * origin,int flag)85 int Exprnode_new(struct ExprnodE **fnode, struct FindjoB *job,
86                  struct ExprnodE *up, char *origin, int flag)
87 /*
88  bit0= set invert-property
89  bit1= set use_shortcuts
90 */
91 {
92  struct ExprnodE *n;
93  int ret,i;
94 
95  *fnode= n= TSOB_FELD(struct ExprnodE,1);
96  if(n == NULL)
97    return(-1);
98  for(i= 0; i < (int) sizeof(n->origin); i++)
99    n->origin[i]= 0;
100  strncpy(n->origin, origin, sizeof(n->origin) - 1);
101  n->up= up;
102  n->invert= (flag & 1);
103  n->assoc= 0;
104  n->use_shortcuts= !!(flag & 2);
105  n->left= NULL;
106  n->left_op= -1;
107  n->right= NULL;
108  n->right_op= -1;
109  n->sub= NULL;
110  n->is_if_then_else= 0;
111  n->true_branch= NULL;
112  n->false_branch= NULL;
113  n->test= NULL;
114  n->own_value= -1;
115  n->composed_value= -1;
116 
117  ret= Exprtest_new(&(n->test), job, 0);
118  if(ret<=0){
119    Exprnode_destroy(fnode, 0);
120    return(-1);
121  }
122  return(1);
123 }
124 
125 
Exprnode_destroy(struct ExprnodE ** fnode,int flag)126 int Exprnode_destroy(struct ExprnodE **fnode, int flag)
127 {
128  if(*fnode == NULL)
129    return(0);
130  Exprnode_destroy(&((*fnode)->right),0);
131  Exprnode_destroy(&((*fnode)->sub),0);
132  Exprnode_destroy(&((*fnode)->true_branch),0);
133  Exprnode_destroy(&((*fnode)->false_branch),0);
134  Exprtest_destroy(&((*fnode)->test),0);
135  free((char *) *fnode);
136  *fnode= NULL;
137  return(1);
138 }
139 
140 
Exprnode_set_is_if(struct ExprnodE * fnode,int value,int flag)141 int Exprnode_set_is_if(struct ExprnodE *fnode, int value, int flag)
142 {
143  fnode->is_if_then_else= value;
144  return(1);
145 }
146 
147 
Exprnode_is_if(struct ExprnodE * fnode,int flag)148 int Exprnode_is_if(struct ExprnodE *fnode, int flag)
149 {
150   return(fnode->is_if_then_else);
151 }
152 
153 
Exprnode_set_branch(struct ExprnodE * fnode,struct ExprnodE * target,int flag)154 int Exprnode_set_branch(struct ExprnodE *fnode, struct ExprnodE *target,
155                         int flag)
156 /*
157  bit0= false_branch (else true_branch)
158 */
159 {
160  struct ExprnodE **branch;
161 
162  if(flag&1)
163    branch= &(fnode->false_branch);
164  else
165    branch= &(fnode->true_branch);
166  Exprnode_destroy(branch,0);
167  (*branch)= target;
168  return(1);
169 }
170 
171 
Exprnode_get_branch(struct ExprnodE * fnode,struct ExprnodE ** branch,int flag)172 int Exprnode_get_branch(struct ExprnodE *fnode, struct ExprnodE **branch,
173                         int flag)
174 /*
175  bit0= false_branch (else true_branch)
176 */
177 {
178  if(flag&1)
179    (*branch)= fnode->false_branch;
180  else
181    (*branch)= fnode->true_branch;
182  return(1);
183 }
184 
185 
Exprnode_is_defined(struct ExprnodE * fnode,int flag)186 int Exprnode_is_defined(struct ExprnodE *fnode, int flag)
187 {
188  struct ExprtesT *ftest;
189 
190  if(fnode==NULL)
191    return(0);
192  if(fnode->sub!=NULL)
193    return(1);
194  ftest= fnode->test;
195  if(ftest==NULL)
196    return(0);
197  if(ftest->test_type>=0)
198    return(1);
199  return(0);
200 }
201 
202 
Exprnode_own_value(struct XorrisO * xorriso,struct ExprnodE * fnode,void * node,char * name,char * path,struct stat * boss_stbuf,struct stat * stbuf,int flag)203 int Exprnode_own_value(struct XorrisO *xorriso, struct ExprnodE *fnode,
204                        void *node, char *name, char *path,
205                        struct stat *boss_stbuf, struct stat *stbuf, int flag)
206 /*
207 flag:
208 return: (also from Exprtest_match() and Exprnode_tree_value() )
209  <0 = error
210   0 = does not match
211   1 = does match
212   2 = immediate decision : does not match
213   3 = immediate decision : does match
214 */
215 {
216  int ret;
217 
218  if(fnode==NULL)
219    return(1);
220  if(fnode->sub!=NULL) {
221    ret= Exprnode_tree_value(xorriso, fnode->sub, -1,
222                             node, name, path, boss_stbuf, stbuf, 0);
223  } else {
224    ret= Exprtest_match(xorriso, fnode->test, node, name, path,
225                        boss_stbuf, stbuf, 0);
226  }
227  if(ret<0)
228    return(ret);
229  if(ret>1)
230    return(ret);
231  if(fnode->invert)
232    ret= !ret;
233  return(ret);
234 }
235 
236 
Exprnode_op(int value1,int value2,int op,int flag)237 int Exprnode_op(int value1, int value2, int op, int flag)
238 {
239  int ret;
240 
241  if(op==0)
242    ret= value1 || value2 ;
243  else
244    ret= value1 && value2 ;
245  return(ret);
246 }
247 
248 
Exprnode_tree_value(struct XorrisO * xorriso,struct ExprnodE * fnode,int left_value,void * node,char * name,char * path,struct stat * boss_stbuf,struct stat * stbuf,int flag)249 int Exprnode_tree_value(struct XorrisO *xorriso, struct ExprnodE *fnode,
250                         int left_value, void *node, char *name, char *path,
251                         struct stat *boss_stbuf, struct stat *stbuf, int flag)
252 /*
253  bit0-7= testmode: 0=head , 1=filename
254 return: (also from Nntpftest_match() and Nntpfnode_own_value() )
255  <0 = error
256   0 = does not match
257   1 = does match
258   2 = immediate decision : does not match
259   3 = immediate decision : does match
260 */
261 {
262  int value= 1,ret;
263 
264  if(fnode==NULL)
265    return(1);
266  if(!Exprnode_is_defined(fnode,0))
267    return(1);
268 
269  if(fnode->use_shortcuts && fnode->left!=NULL){
270    fnode->composed_value= left_value;
271    if(fnode->left_op==0) {/* OR */
272      if(left_value!=0)
273        goto ex;
274    } else {                /* AND */
275      if(left_value==0)
276        goto ex;
277    }
278  }
279  fnode->composed_value= fnode->own_value=
280     Exprnode_own_value(xorriso, fnode, node, name, path, boss_stbuf, stbuf, 0);
281  if(fnode->own_value < 0 || fnode->own_value > 1)
282    return(fnode->own_value);
283 
284  if(fnode->assoc == 0){ /* left associative */
285    if(fnode->left != NULL && left_value >= 0)
286      fnode->composed_value=
287        Exprnode_op(left_value, fnode->own_value, fnode->left_op, 0);
288    /* compute right value */
289    /* is the right value relevant ? */
290    if(fnode->right!=NULL){
291      if(fnode->use_shortcuts){
292        if(fnode->right_op==0) {/* OR */
293          if(fnode->composed_value!=0)
294            goto ex;
295        } else {                /* AND */
296          if(fnode->composed_value==0)
297            goto ex;
298        }
299      }
300      value= Exprnode_tree_value(xorriso, fnode->right,fnode->composed_value,
301                                node, name, path, boss_stbuf, stbuf, 0);
302      if(value<0 || value>1)
303        return(value);
304      fnode->composed_value= value;
305    }
306  }else{ /* right associative */
307    if(fnode->right!=NULL){
308      /* is the right value relevant ? */
309      if(fnode->use_shortcuts){
310        if(fnode->right_op==0) {/* OR */
311          if(fnode->composed_value!=0)
312            goto ex;
313        } else {                /* AND */
314          if(fnode->composed_value==0)
315            goto ex;
316        }
317      }
318      value= Exprnode_tree_value(xorriso, fnode->right,fnode->own_value,
319                                node, name, path, boss_stbuf, stbuf, 0);
320      if(value<0||value>1)
321        return(value);
322    } else
323      value= fnode->own_value;
324    fnode->composed_value= value;
325    if(fnode->left!=NULL && left_value>=0)
326      fnode->composed_value=
327        Exprnode_op(left_value,fnode->composed_value,fnode->left_op,0);
328  }
329 ex:
330  ret= fnode->composed_value;
331  if(fnode->is_if_then_else) {
332    /* The if-condition is evaluated. Now follow the chosen branch */
333    struct ExprnodE *branch;
334    if(ret>0)
335      branch= fnode->true_branch;
336    else
337      branch= fnode->false_branch;
338    if(branch!=NULL) {
339      ret= Exprnode_tree_value(xorriso, branch, -1,
340                               node, name, path, boss_stbuf, stbuf, 0);
341      if(ret<0)
342        return(ret);
343      if(ret>1)
344        return(ret);
345    }
346    fnode->composed_value= ret;
347  }
348  return(fnode->composed_value);
349 }
350 
351 
352 /* --------------------- Findjob -------------------- */
353 
354 
Findjob_new(struct FindjoB ** o,char * start_path,int flag)355 int Findjob_new(struct FindjoB **o, char *start_path, int flag)
356 {
357  struct FindjoB *m;
358  int ret;
359 
360  m= *o= TSOB_FELD(struct FindjoB,1);
361  if(m==NULL)
362    return(-1);
363  m->start_path= NULL;
364  m->test_tree= NULL;
365  m->cursor= NULL;
366  m->invert= 0;
367  m->use_shortcuts= 1;
368  m->action= 0; /* print */
369  m->prune= 0;
370  m->use_pattern= 1;
371  m->target= NULL; /* a mere pointer, not managed memory */
372  m->text_2= NULL; /* a mere pointer, not managed memory */
373  m->user= 0;
374  m->group= 0;
375  m->type= 0;
376  m->date= 0;
377  m->start_path= strdup(start_path);
378  if(m->start_path==NULL)
379    goto failed;
380  m->found_path= NULL;
381  m->estim_upper_size= 0;
382  m->estim_lower_size= 0;
383  m->subjob= NULL;
384  m->errmsg[0]= 0;
385  m->errn= 0;
386  m->match_count= 0;
387  m->depth= 0;
388 
389  ret= Exprnode_new(&(m->test_tree), m, NULL, "-find", (m->use_shortcuts)<<1);
390  if(ret<=0)
391    goto failed;
392  m->cursor= m->test_tree;
393  return(1);
394 
395 failed:;
396  Findjob_destroy(o, 0);
397  return(-1);
398 }
399 
400 
Findjob_destroy(struct FindjoB ** o,int flag)401 int Findjob_destroy(struct FindjoB **o, int flag)
402 {
403  struct FindjoB *m;
404 
405  m= *o;
406  if(m==NULL)
407    return(0);
408  if(m->test_tree != NULL)
409    Exprnode_destroy(&(m->test_tree), 0);
410  if(m->start_path != NULL)
411    free(m->start_path);
412  if(m->found_path != NULL)
413    free(m->found_path);
414  free((char *) *o);
415  *o= NULL;
416  return(1);
417 }
418 
419 
Findjob_set_start_path(struct FindjoB * o,char * start_path,int flag)420 int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag)
421 {
422  if(o->start_path!=NULL)
423    free(o->start_path);
424  if(start_path!=NULL) {
425    o->start_path= strdup(start_path);
426    if(o->start_path==NULL)
427      return(-1);
428  } else
429    o->start_path= NULL;
430  return(1);
431 }
432 
433 
Findjob_get_start_path(struct FindjoB * o,char ** start_path,int flag)434 int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag)
435 {
436  *start_path= o->start_path;
437  return(1);
438 }
439 
440 
Findjob_cursor_complete(struct FindjoB * job,int flag)441 int Findjob_cursor_complete( struct FindjoB *job, int flag)
442 {
443  int ret;
444 
445  if(job==NULL)
446    return(0);
447  ret= Exprnode_is_defined(job->cursor,0);
448  return(ret);
449 }
450 
451 
Findjob_is_restrictive(struct FindjoB * job,int flag)452 int Findjob_is_restrictive(struct FindjoB *job, int flag)
453 {
454  if(job == NULL)
455    return(0);
456  if(job->test_tree == NULL)
457    return(0);
458  if(!Exprnode_is_defined(job->test_tree, 0))
459    return(0);
460  return(1);
461 }
462 
463 
Findjob_new_node(struct FindjoB * job,struct ExprnodE ** fnode,char * origin,int flag)464 int Findjob_new_node(struct FindjoB *job, struct ExprnodE **fnode,
465                      char *origin, int flag)
466 /*
467  bit0= open new branch
468  bit1= with bit0 : do not register as sub-node of job->cursor
469 */
470 {
471  int ret;
472  struct ExprnodE *f;
473 
474  ret= Exprnode_new(fnode,job,NULL,origin,
475                    job->invert|((job->use_shortcuts)<<1));
476  if(ret<=0)
477    return(ret);
478  f= *fnode;
479  if(flag&1) {
480    f->up= job->cursor;
481    if(job->cursor!=NULL && !(flag&2)) {
482      if(job->cursor->sub!=NULL) {
483        /* This would become a memory leak */
484        job->errn= -2;
485        sprintf(job->errmsg,
486                "Program error while parsing -job : sub branch overwrite");
487        Exprnode_destroy(fnode, 0);
488        return(0);
489      } else
490        job->cursor->sub= f;
491    }
492  } else {
493    if(job->cursor != NULL)
494      f->up= job->cursor->up;
495    f->left= job->cursor;
496    if(job->cursor!=NULL)
497      job->cursor->right= f;
498  }
499  job->invert= 0;
500  return(1);
501 }
502 
503 
504 /* If an operator is expected : use -and
505    @param flag bit0= prepare for a pseudo-test:
506                      if an operator is expected, do nothing and return 2
507                bit1= use -or rather than -and
508 */
Findjob_default_and(struct FindjoB * o,int flag)509 int Findjob_default_and(struct FindjoB *o, int flag)
510 {
511  int ret;
512 
513  if(Findjob_cursor_complete(o, 0)) {
514    if(flag & 1)
515      return(2);
516    if(flag & 2) {
517      ret= Findjob_or(o, 0);
518    } else {
519      ret= Findjob_and(o, 0);
520    }
521    if(ret <= 0)
522      return(ret);
523  }
524  return(1);
525 }
526 
527 
Findjob_open_bracket(struct FindjoB * job,int flag)528 int Findjob_open_bracket(struct FindjoB *job, int flag)
529 {
530  int ret;
531  struct ExprnodE *fnode;
532 
533  ret= Findjob_default_and(job, 0);
534  if(ret <= 0)
535    return(ret);
536  ret= Findjob_new_node(job, &fnode, "-sub", 1);
537  if(ret <= 0)
538    return(ret);
539  job->cursor= fnode;
540  return(1);
541 }
542 
543 
Findjob_close_bracket(struct FindjoB * job,int flag)544 int Findjob_close_bracket(struct FindjoB *job, int flag)
545 {
546  if(!Findjob_cursor_complete(job, 0)) {
547    job->errn= -3;
548    sprintf(job->errmsg,
549      "Unary operator or expression expected, closing-bracket found");
550    return(0);
551  }
552 
553  if(job->cursor->up==NULL){
554    job->errn= -1;
555    sprintf(job->errmsg,
556            "No bracket open when encountering closing bracket.");
557    return(0);
558  }
559  job->cursor= job->cursor->up;
560  return(1);
561 }
562 
563 
Findjob_not(struct FindjoB * job,int flag)564 int Findjob_not(struct FindjoB *job, int flag)
565 {
566  int ret;
567 
568  ret= Findjob_default_and(job, 0);
569  if(ret <= 0)
570    return(ret);
571  job->cursor->invert= !job->cursor->invert;
572  return(1);
573 }
574 
575 
Findjob_and(struct FindjoB * job,int flag)576 int Findjob_and(struct FindjoB *job, int flag)
577 {
578  int ret;
579  struct ExprnodE *fnode;
580 
581  if(!Findjob_cursor_complete(job, 0)) {
582    job->errn= -3;
583    sprintf(job->errmsg,
584            "Unary operator or expression expected, binary operator found");
585    return(0);
586  }
587 
588  ret= Findjob_new_node(job, &fnode, "-and", 0);
589  if(ret<=0)
590    return(ret);
591  job->cursor->right_op= 1;
592  job->cursor->assoc= 1;        /* compute right side first */
593  fnode->left_op= 1;
594  fnode->assoc= 0;              /* compute left side first */
595  job->cursor= fnode;
596  return(1);
597 }
598 
599 
Findjob_or(struct FindjoB * job,int flag)600 int Findjob_or(struct FindjoB *job, int flag)
601 {
602  int ret;
603  struct ExprnodE *fnode;
604 
605  if(!Findjob_cursor_complete(job, 0)) {
606    job->errn= -3;
607    sprintf(job->errmsg,
608            "Unary operator or expression expected, binary operator found");
609    return(0);
610  }
611 
612  ret= Findjob_new_node(job, &fnode, "-or", 0);
613  if(ret<=0)
614    return(ret);
615  job->cursor->right= fnode;
616  job->cursor->right_op= 0;
617                                     /* if existing : compute left side first */
618  job->cursor->assoc= (job->cursor->left == NULL);
619  fnode->left= job->cursor;
620  fnode->left_op= 0;
621  fnode->assoc= 0;            /* no right side yet : compute left side first */
622  job->cursor= fnode;
623  return(1);
624 }
625 
626 
Findjob_if(struct FindjoB * job,int flag)627 int Findjob_if(struct FindjoB *job, int flag)
628 {
629  int ret;
630  struct ExprnodE *fnode;
631 
632  ret= Findjob_default_and(job, 0);
633  if(ret <= 0)
634    return(ret);
635  ret= Findjob_new_node(job, &fnode, "-if", 1);
636  if(ret<=0)
637    return(ret);
638  Exprnode_set_is_if(fnode,1,0);
639  job->cursor= fnode;
640  return(1);
641 }
642 
643 
Findjob_then(struct FindjoB * job,int flag)644 int Findjob_then(struct FindjoB *job, int flag)
645 {
646  int ret;
647  struct ExprnodE *fnode,*branch= NULL;
648 
649  if(! Findjob_cursor_complete(job,0)) {
650    job->errn= -3;
651    sprintf(job->errmsg,
652            "Unary operator or expression expected, -then-operator found");
653    return(0);
654  }
655  /* Finding the -if that matches this -then
656     Do not go up one node but look for the leftmost one.
657     If everything is right we are at level of the -if node */
658  while(job->cursor->left!=NULL)
659    job->cursor= job->cursor->left;
660  Exprnode_get_branch(job->cursor, &branch, 0);
661  if(!Exprnode_is_if(job->cursor, 0) || branch != NULL) {
662    job->errn= -5;
663    sprintf(job->errmsg, "-then-operator found outside its proper range.");
664    return(0);
665  }
666  ret= Findjob_new_node(job, &fnode, "-then", 1|2);
667  if(ret <= 0)
668    return(ret);
669  Exprnode_set_branch(job->cursor, fnode, 0);
670  job->cursor= fnode;
671  return(1);
672 }
673 
674 
Findjob_else(struct FindjoB * job,int flag)675 int Findjob_else(struct FindjoB *job, int flag)
676 {
677  int ret;
678  struct ExprnodE *fnode, *true_branch, *false_branch;
679 
680  if(! Findjob_cursor_complete(job, 0)) {
681    job->errn= -3;
682    sprintf(job->errmsg,
683            "Unary operator or expression expected, -else-operator found");
684    return(0);
685  }
686  if(job->cursor->up == NULL)
687    goto improper_range;
688  job->cursor= job->cursor->up;
689  Exprnode_get_branch(job->cursor, &true_branch, 0);
690  Exprnode_get_branch(job->cursor, &false_branch, 1);
691  if(!Exprnode_is_if(job->cursor, 0) ||
692     true_branch == NULL || false_branch != NULL) {
693 improper_range:;
694    job->errn= -5;
695    sprintf(job->errmsg, "-else-operator found outside its proper range.");
696    return(0);
697  }
698  ret= Findjob_new_node(job, &fnode, "-else", 1 | 2);
699  if(ret <= 0)
700    return(ret);
701  Exprnode_set_branch(job->cursor, fnode, 1);
702  job->cursor= fnode;
703  return(1);
704 }
705 
706 
Findjob_elseif(struct FindjoB * job,int flag)707 int Findjob_elseif(struct FindjoB *job, int flag)
708 {
709  int ret;
710  struct ExprnodE *true_branch, *false_branch;
711 
712  if(!Findjob_cursor_complete(job, 0)) {
713    job->errn= -3;
714    sprintf(job->errmsg,
715            "Unary operator or expression expected, -elseif-operator found");
716    return(0);
717  }
718  if(job->cursor->up == NULL)
719    goto improper_range;
720  job->cursor= job->cursor->up;
721  Exprnode_get_branch(job->cursor, &true_branch, 0);
722  Exprnode_get_branch(job->cursor, &false_branch, 1);
723  if(!Exprnode_is_if(job->cursor, 0) ||
724     true_branch==NULL || false_branch!=NULL) {
725 improper_range:;
726    job->errn= -5;
727    sprintf(job->errmsg,
728            "-elseif-operator found outside its proper range.");
729    return(0);
730  }
731  job->cursor= job->cursor->up;
732  /* -elseif is equivalent to the three-step sequence :  -endif -or -if
733     ( -endif has already been performed by following job->cursor->up ) */
734  ret= Findjob_or(job, 0);
735  if(ret <= 0)
736    return(0);
737  ret= Findjob_if(job, 0);
738  if(ret <= 0)
739    return(0);
740  return(1);
741 }
742 
743 
Findjob_endif(struct FindjoB * job,int flag)744 int Findjob_endif(struct FindjoB *job, int flag)
745 {
746  struct ExprnodE *true_branch;
747 
748  if(!Findjob_cursor_complete(job,0)) {
749    job->errn= -3;
750    sprintf(job->errmsg,
751            "Unary operator or expression expected, -endif found");
752    return(0);
753  }
754  if(job->cursor->up==NULL)
755    goto improper_range;
756  /* test wether parent node is -if */
757  job->cursor= job->cursor->up;
758  Exprnode_get_branch(job->cursor, &true_branch, 0);
759  if(!Exprnode_is_if(job->cursor,0) || true_branch == NULL) {
760 improper_range:;
761    job->errn= -5;
762    sprintf(job->errmsg, "-endif-mark found outside its proper range.");
763    return(0);
764  }
765  /* go to grand parent node */
766  job->cursor= job->cursor->up;
767  return(1);
768 }
769 
770 
771 /* @param flag bit0-1: 0= -name , 1= -wholename , 2= -disk_name , 3= -disk_path
772 */
Findjob_set_name_expr(struct FindjoB * o,char * name_expr,int flag)773 int Findjob_set_name_expr(struct FindjoB *o, char *name_expr, int flag)
774 {
775  char *regexpr= NULL;
776  regex_t *name_re;
777  struct ExprtesT *t;
778  int ret;
779 
780  regexpr= TSOB_FELD(char, 2*SfileadrL+2);
781  if(regexpr == NULL)
782    {ret= -1; goto ex;}
783  if(strlen(name_expr)>=SfileadrL)
784    {ret= 0; goto ex;};
785 
786  ret= Findjob_default_and(o, 0);
787  if(ret <= 0)
788    goto ex;
789  t= o->cursor->test;
790  t->test_type= 1;
791  if ((flag & 3) == 1)
792    t->test_type= 13;
793  else if((flag & 3) == 2)
794    t->test_type= 16;
795  else if((flag & 3) == 3)
796    t->test_type= 20;
797  t->arg1= strdup(name_expr);
798  if(t->arg1 == NULL)
799    {ret= -1; goto ex;};
800 
801  if((flag & 3) == 3)
802    {ret= 1; goto ex;}
803 
804  name_re= (regex_t *) calloc(1, sizeof(regex_t));
805  if(name_re == NULL)
806    {ret= -1; goto ex;};
807  Xorriso__bourne_to_reg(name_expr, regexpr, 0);
808  if(regcomp(name_re, regexpr, 0) != 0) {
809    free((char *) name_re);
810    {ret= 0; goto ex;};
811  }
812  t->arg2= name_re;
813  ret= 1;
814 ex:;
815  Xorriso_free_meM(regexpr);
816  return(ret);
817 }
818 
819 
Findjob_set_file_type(struct FindjoB * o,char file_type,int flag)820 int Findjob_set_file_type(struct FindjoB *o, char file_type, int flag)
821 {
822  static char known[]= {"bcdpf-lsmeX"};
823  struct ExprtesT *t;
824  int ret;
825 
826  ret= Findjob_default_and(o, 0);
827  if(ret <= 0)
828    return(ret);
829 
830  if(file_type != 0)
831    if(strchr(known, file_type) == NULL)
832      return(0);
833  t= o->cursor->test;
834  t->test_type= 2;
835  t->arg1= calloc(1, 1);
836  if(t->arg1 == NULL)
837    return(-1);
838  *((char *) t->arg1)= file_type;
839  return(1);
840 }
841 
842 
843 /* @param value -1= only without property, 1= only with property
844    @param flag bit0= pseudo-test:
845                      if no operator is open, do nothing and return 2
846 */
Findjob_set_prop_filter(struct FindjoB * o,int test_type,int value,int flag)847 int Findjob_set_prop_filter(struct FindjoB *o, int test_type, int value,
848                             int flag)
849 {
850  struct ExprtesT *t;
851  int ret;
852 
853  ret= Findjob_default_and(o, flag & 1);
854  if(ret <= 0 || ret == 2)
855    return(ret);
856 
857  t= o->cursor->test;
858  t->test_type= test_type;
859  if(value < 0)
860    t->invert= !t->invert;
861  return(1);
862 }
863 
864 
865 /* @param value -1= only undamaged files, 1= only damaged files
866 */
Findjob_set_damage_filter(struct FindjoB * o,int value,int flag)867 int Findjob_set_damage_filter(struct FindjoB *o, int value, int flag)
868 {
869  int ret;
870 
871  ret= Findjob_set_prop_filter(o, 3, value, 0);
872  return(ret);
873 }
874 
875 
Findjob_set_num_filter(struct FindjoB * o,int test_type,int num1,int num2,int flag)876 int Findjob_set_num_filter(struct FindjoB *o, int test_type,
877                            int num1, int num2, int flag)
878 {
879  struct ExprtesT *t;
880  int ret;
881 
882  ret= Findjob_default_and(o, 0);
883  if(ret <= 0)
884    return(ret);
885 
886  t= o->cursor->test;
887  t->test_type= test_type;
888  t->arg1= calloc(sizeof(int), 1);
889  t->arg2= calloc(sizeof(int), 1);
890  if(t->arg1 == NULL || t->arg2 == NULL)
891    return(-1);
892  *((int *) t->arg1)= num1;
893  *((int *) t->arg2)= num2;
894  return(1);
895 }
896 
897 
Findjob_set_lba_range(struct FindjoB * o,int start_lba,int count,int flag)898 int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count,
899                           int flag)
900 {
901  int ret, end_lba;
902 
903  if(start_lba > 0)
904    end_lba= start_lba + count - 1;
905  else
906    end_lba= start_lba - count + 1;
907  ret= Findjob_set_num_filter(o, 4, start_lba, end_lba, 0);
908  return(ret);
909 }
910 
911 
Findjob_set_test_hidden(struct FindjoB * o,int mode,int flag)912 int Findjob_set_test_hidden(struct FindjoB *o, int mode, int flag)
913 {
914  struct ExprtesT *t;
915  int ret;
916 
917  ret= Findjob_default_and(o, 0);
918  if(ret <= 0)
919    return(ret);
920 
921  t= o->cursor->test;
922  t->test_type= 17;
923  t->arg1= calloc(sizeof(int), 1);
924  if(t->arg1 == NULL)
925    return(-1);
926  *((int *) t->arg1)= mode;
927  return(1);
928 }
929 
930 
931 /* @param value -1= files without ACL, 1= only files with ACL
932 */
Findjob_set_acl_filter(struct FindjoB * o,int value,int flag)933 int Findjob_set_acl_filter(struct FindjoB *o, int value, int flag)
934 {
935  int ret;
936 
937  ret= Findjob_set_prop_filter(o, 5, value, 0);
938  return(ret);
939 }
940 
941 
942 /* @param value -1= files without xattr, 1= only files with xattr
943    @param flag bit0=-has_any_xattr rather than -has_xattr
944 */
Findjob_set_xattr_filter(struct FindjoB * o,int value,int flag)945 int Findjob_set_xattr_filter(struct FindjoB *o, int value, int flag)
946 {
947  int ret;
948 
949  ret= Findjob_set_prop_filter(o, (flag & 1 ? 14 : 6), value, 0);
950  return(ret);
951 }
952 
953 
954 /* @param value -1= files without aaip, 1= only files with aaip
955 */
Findjob_set_aaip_filter(struct FindjoB * o,int value,int flag)956 int Findjob_set_aaip_filter(struct FindjoB *o, int value, int flag)
957 {
958  int ret;
959 
960  ret= Findjob_set_prop_filter(o, 7, value, 0);
961  return(ret);
962 }
963 
964 
965 /* @param value -1= files without filter, 1= files with filter
966 */
Findjob_set_filter_filter(struct FindjoB * o,int value,int flag)967 int Findjob_set_filter_filter(struct FindjoB *o, int value, int flag)
968 {
969  int ret;
970 
971  ret= Findjob_set_prop_filter(o, 8, value, 0);
972  return(ret);
973 }
974 
975 
Findjob_set_crtp_filter(struct FindjoB * o,char * creator,char * hfs_type,int flag)976 int Findjob_set_crtp_filter(struct FindjoB *o, char *creator, char *hfs_type,
977                             int flag)
978 {
979  struct ExprtesT *t;
980  int ret;
981 
982  ret= Findjob_default_and(o, 0);
983  if(ret <= 0)
984    return(ret);
985 
986  t= o->cursor->test;
987  t->test_type= 18;
988  t->arg1= calloc(1, strlen(creator) + 1);
989  t->arg2= calloc(1, strlen(hfs_type) + 1);
990  if(t->arg1 == NULL || t->arg2 == NULL)
991    return(-1);
992  strcpy(t->arg1, creator);
993  strcpy(t->arg2, hfs_type);
994  return(1);
995 }
996 
997 
Findjob_set_bless_filter(struct XorrisO * xorriso,struct FindjoB * o,char * blessing,int flag)998 int Findjob_set_bless_filter(struct XorrisO *xorriso, struct FindjoB *o,
999                              char *blessing, int flag)
1000 {
1001  struct ExprtesT *t;
1002  int ret;
1003 
1004  ret= Findjob_default_and(o, 0);
1005  if(ret <= 0)
1006    return(ret);
1007 
1008  t= o->cursor->test;
1009  t->test_type= 19;
1010  t->arg1= calloc(1, sizeof(int));
1011  if(t->arg1 == NULL)
1012    return(-1);
1013  ret= Xorriso_hfsplus_bless(xorriso, "", NULL, blessing, 4 | 8);
1014  if(ret <= 0)
1015    return(ret);
1016  *((int *) t->arg1)= ret - 1;
1017  return(1);
1018 }
1019 
1020 
Findjob_set_wanted_node(struct FindjoB * o,void * wanted_node,int flag)1021 int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag)
1022 {
1023  struct ExprtesT *t;
1024  int ret;
1025 
1026  ret= Findjob_default_and(o, 0);
1027  if(ret <= 0)
1028    return(ret);
1029 
1030  t= o->cursor->test;
1031  t->test_type= 9;
1032  t->arg1= wanted_node;
1033  return(1);
1034 }
1035 
1036 
Findjob_set_commit_filter_2(struct FindjoB * o,int flag)1037 int Findjob_set_commit_filter_2(struct FindjoB *o, int flag)
1038 {
1039  int ret;
1040 
1041  ret= Findjob_default_and(o, 0);
1042  if(ret <= 0)
1043    return(ret);
1044 
1045  o->cursor->test->test_type= 10;
1046  return(1);
1047 }
1048 
1049 
Findjob_set_arg1(struct FindjoB * o,int test_type,char * arg1,int flag)1050 int Findjob_set_arg1(struct FindjoB *o, int test_type, char *arg1, int flag)
1051 {
1052  struct ExprtesT *t;
1053  int ret, hflag= 0;
1054 
1055  if(test_type == 23)
1056    hflag= 2; /* prepend -or rather than -and */
1057  ret= Findjob_default_and(o, hflag);
1058  if(ret <= 0)
1059    return(ret);
1060  t= o->cursor->test;
1061  t->test_type= test_type;
1062  t->arg1= strdup(arg1);
1063  if(t->arg1 == NULL)
1064    return(-1);
1065  return(1);
1066 }
1067 
1068 
1069 /* @param value -1= true, 1= false
1070    @param flag bit0= pseudo-test:
1071                      if no operator is open, do nothing and return 2
1072 */
Findjob_set_false(struct FindjoB * o,int value,int flag)1073 int Findjob_set_false(struct FindjoB *o, int value, int flag)
1074 {
1075  int ret;
1076 
1077  ret= Findjob_set_prop_filter(o, 0, value, flag & 1);
1078  return(ret);
1079 }
1080 
1081 
Findjob_set_prune(struct FindjoB * o,int flag)1082 int Findjob_set_prune(struct FindjoB *o, int flag)
1083 {
1084  int ret;
1085 
1086  ret= Findjob_set_prop_filter(o, 12, 0, 0);
1087  return(ret);
1088 }
1089 
1090 
Findjob_set_found_path(struct FindjoB * o,char * path,int flag)1091 int Findjob_set_found_path(struct FindjoB *o, char *path, int flag)
1092 {
1093  if(o->found_path != NULL)
1094    free(o->found_path);
1095  if(path != NULL) {
1096    o->found_path= strdup(path);
1097    if(o->found_path == NULL)
1098      return(-1);
1099  } else
1100    o->found_path= NULL;
1101  return(1);
1102 }
1103 
1104 
Findjob_get_found_path(struct FindjoB * o,char ** path,int flag)1105 int Findjob_get_found_path(struct FindjoB *o, char **path, int flag)
1106 {
1107  *path= o->found_path;
1108  return(1);
1109 }
1110 
1111 
Findjob_get_last_data_file_block(struct FindjoB * o,uint32_t * lba,int flag)1112 int Findjob_get_last_data_file_block(struct FindjoB *o, uint32_t *lba,
1113                                      int flag)
1114 {
1115  *lba= o->last_data_file_block;
1116  return(1);
1117 }
1118 
1119 
Findjob_get_action(struct FindjoB * o,int flag)1120 int Findjob_get_action(struct FindjoB *o, int flag)
1121 {
1122  return(o->action);
1123 }
1124 
1125 
1126 /* @return <0 error, >=0 see above struct FindjoB.action
1127 */
Findjob_get_action_parms(struct FindjoB * o,char ** target,char ** text_2,uid_t * user,gid_t * group,mode_t * mode_and,mode_t * mode_or,int * type,time_t * date,struct FindjoB ** subjob,int flag)1128 int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,
1129                              uid_t *user, gid_t *group,
1130                              mode_t *mode_and, mode_t *mode_or,
1131                              int *type, time_t *date, struct FindjoB **subjob,
1132                              int flag)
1133 {
1134  *target= o->target;
1135  *text_2= o->text_2;
1136  *user= o->user;
1137  *group= o->group;
1138  *mode_and= o->mode_and;
1139  *mode_or= o->mode_or;
1140  *type= o->type;
1141  *date= o->date;
1142  *subjob= o->subjob;
1143  return(o->action);
1144 }
1145 
1146 
Findjob_test_2(struct XorrisO * xorriso,struct FindjoB * o,void * node,char * name,char * path,struct stat * boss_stbuf,struct stat * stbuf,int flag)1147 int Findjob_test_2(struct XorrisO *xorriso, struct FindjoB *o,
1148                    void *node, char *name, char *path,
1149                    struct stat *boss_stbuf, struct stat *stbuf, int flag)
1150 {
1151  int ret;
1152 
1153  ret= Exprnode_tree_value(xorriso, o->test_tree, -1,
1154                           node, name, path, boss_stbuf, stbuf, 0);
1155  if(ret == 3)
1156    ret= 1;
1157  else if(ret == 2)
1158    ret= 0;
1159  return(ret);
1160 }
1161 
1162 
Findjob_set_action_target(struct FindjoB * o,int action,char * target,int flag)1163 int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
1164                               int flag)
1165 {
1166  o->action= action;
1167  o->target= target;
1168  return(1);
1169 }
1170 
1171 
Findjob_set_action_type(struct FindjoB * o,int action,int type,int flag)1172 int Findjob_set_action_type(struct FindjoB *o, int action, int type,
1173                               int flag)
1174 {
1175  o->action= action;
1176  o->type= type;
1177  return(1);
1178 }
1179 
1180 
Findjob_set_action_text_2(struct FindjoB * o,int action,char * target,char * text_2,int flag)1181 int Findjob_set_action_text_2(struct FindjoB *o, int action, char *target,
1182                               char* text_2, int flag)
1183 {
1184  o->action= action;
1185  o->target= target;
1186  o->text_2= text_2;
1187  return(1);
1188 }
1189 
1190 
1191 /* @param flag bit0= recursive
1192 */
Findjob_set_action_chown(struct FindjoB * o,uid_t user,int flag)1193 int Findjob_set_action_chown(struct FindjoB *o, uid_t user,int flag)
1194 {
1195  int ret;
1196 
1197  if(flag&1) {
1198    o->action= 0;
1199    Findjob_destroy(&(o->subjob), 0);
1200    ret= Findjob_new(&(o->subjob), "", 0);
1201    if(ret<=0)
1202      return(-1);
1203    Findjob_set_action_chown(o->subjob, user, 0);
1204    o->action= 9;
1205  } else {
1206    o->action= 4;
1207    o->user= user;
1208  }
1209  return(1);
1210 }
1211 
1212 
1213 /* @param flag bit0= recursive
1214 */
Findjob_set_action_chgrp(struct FindjoB * o,gid_t group,int flag)1215 int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag)
1216 {
1217  int ret;
1218 
1219  if(flag&1) {
1220    o->action= 0;
1221    Findjob_destroy(&(o->subjob), 0);
1222    ret= Findjob_new(&(o->subjob), "", 0);
1223    if(ret<=0)
1224      return(-1);
1225    Findjob_set_action_chgrp(o->subjob, group, 0);
1226    o->action= 10;
1227  } else {
1228    o->action= 5;
1229    o->group= group;
1230  }
1231  return(1);
1232 }
1233 
1234 
1235 /* @param flag bit0= recursive
1236 */
Findjob_set_action_chmod(struct FindjoB * o,mode_t mode_and,mode_t mode_or,int flag)1237 int Findjob_set_action_chmod(struct FindjoB *o,
1238                              mode_t mode_and, mode_t mode_or, int flag)
1239 {
1240  int ret;
1241 
1242  if(flag&1) {
1243    o->action= 0;
1244    Findjob_destroy(&(o->subjob), 0);
1245    ret= Findjob_new(&(o->subjob), "", 0);
1246    if(ret<=0)
1247      return(-1);
1248    Findjob_set_action_chmod(o->subjob, mode_and, mode_or, 0);
1249    o->action= 11;
1250  } else {
1251    o->action= 6;
1252    o->mode_and= mode_and;
1253    o->mode_or= mode_or;
1254  }
1255  return(1);
1256 }
1257 
1258 
1259 /* @param flag bit0= recursive
1260 */
Findjob_set_action_ad(struct FindjoB * o,int type,time_t date,int flag)1261 int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag)
1262 {
1263  int ret;
1264 
1265  if(flag&1) {
1266    o->action= 0;
1267    Findjob_destroy(&(o->subjob), 0);
1268    ret= Findjob_new(&(o->subjob), "", 0);
1269    if(ret<=0)
1270      return(-1);
1271    Findjob_set_action_ad(o->subjob, type, date, 0);
1272    o->action= 12;
1273  } else {
1274    o->action= 7;
1275    o->type= type;
1276    o->date= date;
1277  }
1278  return(1);
1279 }
1280 
1281 
Findjob_set_action_subjob(struct FindjoB * o,int action,struct FindjoB * subjob,int flag)1282 int Findjob_set_action_subjob(struct FindjoB *o, int action,
1283                               struct FindjoB *subjob, int flag)
1284 {
1285  o->action= action;
1286  Findjob_destroy(&(o->subjob), 0);
1287  o->subjob= subjob;
1288  return(1);
1289 }
1290 
1291 
Findjob_set_action_found_path(struct FindjoB * o,int flag)1292 int Findjob_set_action_found_path(struct FindjoB *o, int flag)
1293 {
1294  o->action= 23;
1295  Findjob_set_found_path(o, NULL, 0);
1296  return(1);
1297 }
1298 
1299