2
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
4
Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
6
Provided under GPL version 2 or later.
8
This file contains the implementation of classes FindjoB, ExprnodE,
9
ExprtesT which perform tree searches in libisofs or in POSIX filesystem
13
#include "../config.h"
17
#include <sys/types.h>
30
#include "xorriso_private.h"
31
#include "xorrisoburn.h"
34
/* ----------------------- Exprtest ----------------------- */
37
int Exprtest_new( struct ExprtesT **ftest, struct FindjoB *boss, int flag)
41
*ftest= f= TSOB_FELD(struct ExprtesT,1);
53
int Exprtest_destroy(struct ExprtesT **ftest, int flag)
61
if(f->test_type == 1) {
68
} else if(f->test_type == 9) {
69
/* arg1 is not an allocated value */;
82
/* ----------------------- Nttpfnode ----------------------- */
85
int Exprnode_new(struct ExprnodE **fnode, struct FindjoB *job,
86
struct ExprnodE *up, char *origin, int flag)
88
bit0= set invert-property
89
bit1= set use_shortcuts
95
*fnode= n= TSOB_FELD(struct ExprnodE,1);
98
for(i= 0; i < sizeof(n->origin); i++)
100
strncpy(n->origin, origin, sizeof(n->origin) - 1);
102
n->invert= (flag & 1);
104
n->use_shortcuts= !!(flag & 2);
110
n->is_if_then_else= 0;
111
n->true_branch= NULL;
112
n->false_branch= NULL;
115
n->composed_value= -1;
117
ret= Exprtest_new(&(n->test), job, 0);
119
Exprnode_destroy(fnode, 0);
126
int Exprnode_destroy(struct ExprnodE **fnode, int flag)
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);
141
int Exprnode_set_is_if(struct ExprnodE *fnode, int value, int flag)
143
fnode->is_if_then_else= value;
148
int Exprnode_is_if(struct ExprnodE *fnode, int flag)
150
return(fnode->is_if_then_else);
154
int Exprnode_set_branch(struct ExprnodE *fnode, struct ExprnodE *target,
157
bit0= false_branch (else true_branch)
160
struct ExprnodE **branch;
163
branch= &(fnode->false_branch);
165
branch= &(fnode->true_branch);
166
Exprnode_destroy(branch,0);
172
int Exprnode_get_branch(struct ExprnodE *fnode, struct ExprnodE **branch,
175
bit0= false_branch (else true_branch)
179
(*branch)= fnode->false_branch;
181
(*branch)= fnode->true_branch;
186
int Exprnode_is_defined(struct ExprnodE *fnode, int flag)
188
struct ExprtesT *ftest;
197
if(ftest->test_type>=0)
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)
208
return: (also from Exprtest_match() and Exprnode_tree_value() )
212
2 = immediate decision : does not match
213
3 = immediate decision : does match
220
if(fnode->sub!=NULL) {
221
ret= Exprnode_tree_value(xorriso, fnode->sub, -1,
222
node, name, path, boss_stbuf, stbuf, 0);
224
ret= Exprtest_match(xorriso, fnode->test, node, name, path,
225
boss_stbuf, stbuf, 0);
237
int Exprnode_op(int value1, int value2, int op, int flag)
242
ret= value1 || value2 ;
244
ret= value1 && value2 ;
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)
253
bit0-7= testmode: 0=head , 1=filename
254
return: (also from Nntpftest_match() and Nntpfnode_own_value() )
258
2 = immediate decision : does not match
259
3 = immediate decision : does match
266
if(!Exprnode_is_defined(fnode,0))
269
if(fnode->use_shortcuts && fnode->left!=NULL){
270
fnode->composed_value= left_value;
271
if(fnode->left_op==0) {/* OR */
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);
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)
296
if(fnode->composed_value==0)
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)
304
fnode->composed_value= value;
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)
314
if(fnode->composed_value==0)
318
value= Exprnode_tree_value(xorriso, fnode->right,fnode->own_value,
319
node, name, path, boss_stbuf, stbuf, 0);
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);
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;
335
branch= fnode->true_branch;
337
branch= fnode->false_branch;
339
ret= Exprnode_tree_value(xorriso, branch, -1,
340
node, name, path, boss_stbuf, stbuf, 0);
346
fnode->composed_value= ret;
348
return(fnode->composed_value);
352
/* --------------------- Findjob -------------------- */
355
int Findjob_new(struct FindjoB **o, char *start_path, int flag)
360
m= *o= TSOB_FELD(struct FindjoB,1);
368
m->action= 0; /* print */
370
m->target= NULL; /* a mere pointer, not managed memory */
371
m->text_2= NULL; /* a mere pointer, not managed memory */
376
m->start_path= strdup(start_path);
377
if(m->start_path==NULL)
380
m->estim_upper_size= 0;
381
m->estim_lower_size= 0;
386
ret= Exprnode_new(&(m->test_tree), m, NULL, "-find", (m->use_shortcuts)<<1);
389
m->cursor= m->test_tree;
393
Findjob_destroy(o, 0);
398
int Findjob_destroy(struct FindjoB **o, int flag)
405
if(m->test_tree != NULL)
406
Exprnode_destroy(&(m->test_tree), 0);
407
if(m->start_path != NULL)
415
int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag)
417
if(o->start_path!=NULL)
419
if(start_path!=NULL) {
420
o->start_path= strdup(start_path);
421
if(o->start_path==NULL)
429
int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag)
431
*start_path= o->start_path;
436
int Findjob_cursor_complete( struct FindjoB *job, int flag)
442
ret= Exprnode_is_defined(job->cursor,0);
447
int Findjob_is_restrictive(struct FindjoB *job, int flag)
451
if(job->test_tree == NULL)
453
if(!Exprnode_is_defined(job->test_tree, 0))
459
int Findjob_new_node(struct FindjoB *job, struct ExprnodE **fnode,
460
char *origin, int flag)
462
bit0= open new branch
463
bit1= with bit1 : do not register as sub-node of job->cursor
469
ret= Exprnode_new(fnode,job,NULL,origin,
470
job->invert|((job->use_shortcuts)<<1));
476
if(job->cursor!=NULL && !(flag&2)) {
477
if(job->cursor->sub!=NULL) {
478
/* This would become a memory leak */
481
"Program error while parsing -job : sub branch overwrite");
487
f->up= job->cursor->up;
488
f->left= job->cursor;
489
if(job->cursor!=NULL)
490
job->cursor->right= f;
497
/* If an operator is expected : use -and
498
@param flag bit0= prepare for a pseudo-test:
499
if an operator is expected, do nothing and return 2
501
int Findjob_default_and(struct FindjoB *o, int flag)
505
if(Findjob_cursor_complete(o, 0)) {
508
ret= Findjob_and(o, 0);
516
int Findjob_open_bracket(struct FindjoB *job, int flag)
519
struct ExprnodE *fnode;
521
ret= Findjob_default_and(job, 0);
524
ret= Findjob_new_node(job, &fnode, "-sub", 1);
532
int Findjob_close_bracket(struct FindjoB *job, int flag)
534
if(!Findjob_cursor_complete(job, 0)) {
537
"Unary operator or expression expected, closing-bracket found");
541
if(job->cursor->up==NULL){
544
"No bracket open when encountering closing bracket.");
547
job->cursor= job->cursor->up;
552
int Findjob_not(struct FindjoB *job, int flag)
556
ret= Findjob_default_and(job, 0);
559
job->cursor->invert= !job->cursor->invert;
564
int Findjob_and(struct FindjoB *job, int flag)
567
struct ExprnodE *fnode;
569
if(!Findjob_cursor_complete(job, 0)) {
572
"Unary operator or expression expected, binary operator found");
576
ret= Findjob_new_node(job, &fnode, "-and", 0);
579
job->cursor->right_op= 1;
580
job->cursor->assoc= 1; /* compute right side first */
582
fnode->assoc= 0; /* compute left side first */
588
int Findjob_or(struct FindjoB *job, int flag)
591
struct ExprnodE *fnode;
593
if(!Findjob_cursor_complete(job, 0)) {
596
"Unary operator or expression expected, binary operator found");
600
ret= Findjob_new_node(job, &fnode, "-or", 0);
603
job->cursor->right= fnode;
604
job->cursor->right_op= 0;
605
/* if existing : compute left side first */
606
job->cursor->assoc= (job->cursor->left == NULL);
607
fnode->left= job->cursor;
609
fnode->assoc= 0; /* no right side yet : compute left side first */
615
int Findjob_if(struct FindjoB *job, int flag)
618
struct ExprnodE *fnode;
620
ret= Findjob_default_and(job, 0);
623
ret= Findjob_new_node(job, &fnode, "-if", 1);
626
Exprnode_set_is_if(fnode,1,0);
632
int Findjob_then(struct FindjoB *job, int flag)
635
struct ExprnodE *fnode,*branch= NULL;
637
if(! Findjob_cursor_complete(job,0)) {
640
"Unary operator or expression expected, -then-operator found");
643
/* Finding the -if that matches this -then
644
Do not go up one node but look for the leftmost one.
645
If everything is right we are at level of the -if node */
646
while(job->cursor->left!=NULL)
647
job->cursor= job->cursor->left;
648
Exprnode_get_branch(job->cursor, &branch, 0);
649
if(!Exprnode_is_if(job->cursor, 0) || branch != NULL) {
651
sprintf(job->errmsg, "-then-operator found outside its proper range.");
654
ret= Findjob_new_node(job, &fnode, "-then", 1|2);
657
Exprnode_set_branch(job->cursor, fnode, 0);
663
int Findjob_else(struct FindjoB *job, int flag)
666
struct ExprnodE *fnode, *true_branch, *false_branch;
668
if(! Findjob_cursor_complete(job, 0)) {
671
"Unary operator or expression expected, -else-operator found");
674
if(job->cursor->up == NULL)
676
job->cursor= job->cursor->up;
677
Exprnode_get_branch(job->cursor, &true_branch, 0);
678
Exprnode_get_branch(job->cursor, &false_branch, 1);
679
if(!Exprnode_is_if(job->cursor, 0) ||
680
true_branch == NULL || false_branch != NULL) {
683
sprintf(job->errmsg, "-else-operator found outside its proper range.");
686
ret= Findjob_new_node(job, &fnode, "-else", 1 | 2);
689
Exprnode_set_branch(job->cursor, fnode, 1);
695
int Findjob_elseif(struct FindjoB *job, int flag)
698
struct ExprnodE *true_branch, *false_branch;
700
if(!Findjob_cursor_complete(job, 0)) {
703
"Unary operator or expression expected, -elseif-operator found");
706
if(job->cursor->up == NULL)
708
job->cursor= job->cursor->up;
709
Exprnode_get_branch(job->cursor, &true_branch, 0);
710
Exprnode_get_branch(job->cursor, &false_branch, 1);
711
if(!Exprnode_is_if(job->cursor, 0) ||
712
true_branch==NULL || false_branch!=NULL) {
716
"-elseif-operator found outside its proper range.");
719
job->cursor= job->cursor->up;
720
/* -elseif is equivalent to the three-step sequence : -endif -or -if
721
( -endif has already been performed by following job->cursor->up ) */
722
ret= Findjob_or(job, 0);
725
ret= Findjob_if(job, 0);
732
int Findjob_endif(struct FindjoB *job, int flag)
734
struct ExprnodE *true_branch;
736
if(!Findjob_cursor_complete(job,0)) {
739
"Unary operator or expression expected, -endif found");
742
if(job->cursor->up==NULL)
744
/* test wether parent node is -if */
745
job->cursor= job->cursor->up;
746
Exprnode_get_branch(job->cursor, &true_branch, 0);
747
if(!Exprnode_is_if(job->cursor,0) || true_branch == NULL) {
750
sprintf(job->errmsg, "-endif-mark found outside its proper range.");
753
/* go to grand parent node */
754
job->cursor= job->cursor->up;
759
/* @param flag bit0-1= 0= -name , 1= -wholename , 2= -disk_name
761
int Findjob_set_name_expr(struct FindjoB *o, char *name_expr, int flag)
763
char regexpr[2*SfileadrL+2];
768
if(strlen(name_expr)>=SfileadrL)
771
ret= Findjob_default_and(o, 0);
778
else if((flag & 3) == 2)
780
name_re= (regex_t *) calloc(1, sizeof(regex_t));
783
t->arg1= strdup(name_expr);
784
if(t->arg1 == NULL) {
785
free((char *) name_re);
788
Xorriso__bourne_to_reg(name_expr, regexpr, 0);
789
if(regcomp(name_re, regexpr, 0) != 0)
796
int Findjob_set_file_type(struct FindjoB *o, char file_type, int flag)
798
static char known[]= {"bcdpf-lsmeX"};
802
ret= Findjob_default_and(o, 0);
807
if(strchr(known, file_type) == NULL)
811
t->arg1= calloc(1, 1);
814
*((char *) t->arg1)= file_type;
819
/* @param value -1= only without property, 1= only with property
820
@param flag bit0= pseudo-test:
821
if no operator is open, do nothing and return 2
823
int Findjob_set_prop_filter(struct FindjoB *o, int test_type, int value,
829
ret= Findjob_default_and(o, flag & 1);
830
if(ret <= 0 || ret == 2)
834
t->test_type= test_type;
836
t->invert= !t->invert;
841
/* @param value -1= only undamaged files, 1= only damaged files
843
int Findjob_set_damage_filter(struct FindjoB *o, int value, int flag)
847
ret= Findjob_set_prop_filter(o, 3, value, 0);
852
int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count,
858
ret= Findjob_default_and(o, 0);
864
t->arg1= calloc(sizeof(int), 1);
865
t->arg2= calloc(sizeof(int), 1);
866
if(t->arg1 == NULL || t->arg2 == NULL)
868
*((int *) t->arg1)= start_lba;
870
*((int *) t->arg2)= start_lba + count - 1;
872
*((int *) t->arg2)= start_lba - count + 1;
877
int Findjob_set_test_hidden(struct FindjoB *o, int mode, int flag)
882
ret= Findjob_default_and(o, 0);
888
t->arg1= calloc(sizeof(int), 1);
891
*((int *) t->arg1)= mode;
896
/* @param value -1= files without ACL, 1= only files with ACL
898
int Findjob_set_acl_filter(struct FindjoB *o, int value, int flag)
902
ret= Findjob_set_prop_filter(o, 5, value, 0);
907
/* @param value -1= files without xattr, 1= only files with xattr
908
@param flag bit0=-has_any_xattr rather than -has_xattr
910
int Findjob_set_xattr_filter(struct FindjoB *o, int value, int flag)
914
ret= Findjob_set_prop_filter(o, (flag & 1 ? 14 : 6), value, 0);
919
/* @param value -1= files without aaip, 1= only files with aaip
921
int Findjob_set_aaip_filter(struct FindjoB *o, int value, int flag)
925
ret= Findjob_set_prop_filter(o, 7, value, 0);
930
/* @param value -1= files without filter, 1= files with filter
932
int Findjob_set_filter_filter(struct FindjoB *o, int value, int flag)
936
ret= Findjob_set_prop_filter(o, 8, value, 0);
941
int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag)
946
ret= Findjob_default_and(o, 0);
952
t->arg1= wanted_node;
957
int Findjob_set_commit_filter_2(struct FindjoB *o, int flag)
961
ret= Findjob_default_and(o, 0);
965
o->cursor->test->test_type= 10;
970
int Findjob_set_decision(struct FindjoB *o, char *decision, int flag)
975
ret= Findjob_default_and(o, 0);
981
t->arg1= strdup(decision);
988
/* @param value -1= true, 1= false
989
@param flag bit0= pseudo-test:
990
if no operator is open, do nothing and return 2
992
int Findjob_set_false(struct FindjoB *o, int value, int flag)
996
ret= Findjob_set_prop_filter(o, 0, value, flag & 1);
1001
int Findjob_set_prune(struct FindjoB *o, int flag)
1005
ret= Findjob_set_prop_filter(o, 12, 0, 0);
1010
int Findjob_set_found_path(struct FindjoB *o, char *path, int flag)
1012
if(o->found_path != NULL)
1013
free(o->found_path);
1015
o->found_path= strdup(path);
1016
if(o->found_path == NULL)
1019
o->found_path= NULL;
1024
int Findjob_get_found_path(struct FindjoB *o, char **path, int flag)
1026
*path= o->found_path;
1031
int Findjob_get_action(struct FindjoB *o, int flag)
1037
/* @return <0 error, >=0 see above struct FindjoB.action
1039
int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,
1040
uid_t *user, gid_t *group,
1041
mode_t *mode_and, mode_t *mode_or,
1042
int *type, time_t *date, struct FindjoB **subjob,
1049
*mode_and= o->mode_and;
1050
*mode_or= o->mode_or;
1058
int Findjob_test_2(struct XorrisO *xorriso, struct FindjoB *o,
1059
void *node, char *name, char *path,
1060
struct stat *boss_stbuf, struct stat *stbuf, int flag)
1064
ret= Exprnode_tree_value(xorriso, o->test_tree, -1,
1065
node, name, path, boss_stbuf, stbuf, 0);
1074
int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
1083
int Findjob_set_action_type(struct FindjoB *o, int action, int type,
1092
int Findjob_set_action_text_2(struct FindjoB *o, int action, char *target,
1093
char* text_2, int flag)
1102
/* @param flag bit0= recursive
1104
int Findjob_set_action_chown(struct FindjoB *o, uid_t user,int flag)
1110
Findjob_destroy(&(o->subjob), 0);
1111
ret= Findjob_new(&(o->subjob), "", 0);
1114
Findjob_set_action_chown(o->subjob, user, 0);
1124
/* @param flag bit0= recursive
1126
int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag)
1132
Findjob_destroy(&(o->subjob), 0);
1133
ret= Findjob_new(&(o->subjob), "", 0);
1136
Findjob_set_action_chgrp(o->subjob, group, 0);
1146
/* @param flag bit0= recursive
1148
int Findjob_set_action_chmod(struct FindjoB *o,
1149
mode_t mode_and, mode_t mode_or, int flag)
1155
Findjob_destroy(&(o->subjob), 0);
1156
ret= Findjob_new(&(o->subjob), "", 0);
1159
Findjob_set_action_chmod(o->subjob, mode_and, mode_or, 0);
1163
o->mode_and= mode_and;
1164
o->mode_or= mode_or;
1170
/* @param flag bit0= recursive
1172
int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag)
1178
Findjob_destroy(&(o->subjob), 0);
1179
ret= Findjob_new(&(o->subjob), "", 0);
1182
Findjob_set_action_ad(o->subjob, type, date, 0);
1193
int Findjob_set_action_subjob(struct FindjoB *o, int action,
1194
struct FindjoB *subjob, int flag)
1197
Findjob_destroy(&(o->subjob), 0);
1203
int Findjob_set_action_found_path(struct FindjoB *o, int flag)
1206
Findjob_set_found_path(o, NULL, 0);