Mercurial > hg > toybox
annotate toys/pending/find.c @ 875:2650f5f56bab
More find cleanup
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Sun, 21 Apr 2013 23:45:35 +0200 |
parents | c326f55c74bd |
children | b042cd34e564 |
rev | line source |
---|---|
814 | 1 /* vi: set sw=4 ts=4: |
2 * | |
3 * find.c - find files matching a criteria | |
4 * | |
5 * Copyright 2012 Tim Bird <tbird20d@gmail.com> | |
6 * | |
7 * See http://opengroup.org/onlinepubs/9699919799/utilities/find.html | |
8 | |
815
0c5b15cf4911
A couple quick fixes to find so I can try it out.
Rob Landley <rob@landley.net>
parents:
814
diff
changeset
|
9 USE_FIND(NEWTOY(find, "?", TOYFLAG_USR|TOYFLAG_BIN)) |
814 | 10 |
11 config FIND | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
12 bool "find" |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
13 default n |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
14 help |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
15 usage: find [<dir>] [<options] |
814 | 16 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
17 -name <pattern> match pattern |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
18 -type [fcdl] match file type |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
19 !, -a, -o not, and , or |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
20 (, ) group expressions |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
21 -mtime [-+]n match file modification time (to within 24 hours) |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
22 \t\t +=greater (older) than, -=less (younger) than |
814 | 23 */ |
24 | |
25 /* To Do: | |
26 * -exec action | |
27 */ | |
28 | |
849 | 29 #define FOR_find |
814 | 30 #include "toys.h" |
31 | |
32 struct filter_node { | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
33 struct filter_node *next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
34 int op; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
35 union { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
36 char *name_regex; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
37 struct { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
38 char time_op; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
39 time_t time; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
40 } t; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
41 mode_t type; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
42 struct { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
43 int arg_path_index; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
44 char **exec_args; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
45 } e; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
46 } data; |
814 | 47 }; |
48 | |
874 | 49 GLOBALS( |
50 char *dir; | |
51 struct filter_node *filter_root; | |
52 ) | |
53 | |
54 #define SECONDS_PER_DAY (24*60*60) | |
814 | 55 |
56 /* filter operation types */ | |
57 #define OP_UNKNOWN 0 | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
58 #define OP_OR 2 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
59 #define OP_AND 3 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
60 #define OP_NOT 4 |
814 | 61 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
62 #define LPAREN 1 |
814 | 63 #define RPAREN 5 |
64 | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
65 #define MAX_OP 5 |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
66 |
814 | 67 #define CHECK_NAME 7 |
68 #define CHECK_MTIME 8 | |
69 #define CHECK_TYPE 9 | |
70 | |
71 #define ACTION_PRINT 20 | |
72 #define ACTION_PRINT0 21 | |
73 #define ACTION_EXEC 22 | |
74 | |
874 | 75 #define IS_ACTION(x) (x >= 20) |
76 | |
814 | 77 #define TEST_LT 0 |
78 #define TEST_EQ 1 | |
79 #define TEST_GT 2 | |
80 | |
81 /* executes the command for a filter node | |
875 | 82 returns 0 for failure or 1 for success |
814 | 83 */ |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
84 static int do_exec(struct filter_node *filter, struct dirtree *node) |
814 | 85 { |
849 | 86 char *path = NULL; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
87 char **arg_array; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
88 pid_t pid; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
89 int status; |
814 | 90 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
91 arg_array = filter->data.e.exec_args; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
92 if (filter->data.e.arg_path_index) { |
875 | 93 int plen; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
94 path = dirtree_path(node, &plen); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
95 arg_array[filter->data.e.arg_path_index] = path; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
96 } |
816
3a7defbc671e
Remove more debug code from find.
Rob Landley <rob@landley.net>
parents:
815
diff
changeset
|
97 |
849 | 98 if (!(pid = fork())) xexec(arg_array); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
99 free(path); |
849 | 100 waitpid(pid, &status, 0); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
101 |
875 | 102 return !WEXITSTATUS(status); |
814 | 103 } |
104 | |
105 /* prefix evaluator */ | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
106 /* returns 0 for failure or 1 for success */ |
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
107 static int evaluate(struct filter_node *filter, struct dirtree *node, |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
108 struct filter_node **fnext) |
814 | 109 { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
110 int result; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
111 int op; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
112 static int skip = 0; |
814 | 113 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
114 /* if no filters, success */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
115 if (!filter) { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
116 *fnext = NULL; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
117 return 1; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
118 } |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
119 op = filter->op; |
814 | 120 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
121 if (op==OP_NOT) return !evaluate(filter->next, node, fnext); |
849 | 122 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
123 if (op==OP_OR || op==OP_AND) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
124 result = evaluate(filter->next, node, fnext); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
125 if(!skip) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
126 if (op==OP_OR) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
127 skip = result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
128 result = evaluate(*fnext, node, fnext) || result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
129 } else { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
130 skip = !result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
131 result = evaluate(*fnext, node, fnext) && result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
132 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
133 skip = 0; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
134 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
135 else result = evaluate(*fnext, node, fnext); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
136 return result; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
137 } |
849 | 138 |
139 // we're down to single operations, mark our position | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
140 *fnext = filter->next; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
141 if(skip) return 0; |
849 | 142 |
143 // TODO: Do a regex comparison | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
144 if (op==CHECK_NAME) |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
145 return !strcmp(filter->data.name_regex, node->name); |
849 | 146 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
147 if (op==CHECK_MTIME) { |
875 | 148 time_t node_time = node->st.st_mtime/SECONDS_PER_DAY; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
149 result = 1; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
150 switch (filter->data.t.time_op) { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
151 /* do time compare here */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
152 case TEST_LT: |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
153 /* FIXTHIS - should result be < or <= ?*/ |
849 | 154 if (node_time > filter->data.t.time) result = 0; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
155 break; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
156 case TEST_GT: |
849 | 157 if (node_time < filter->data.t.time) result = 0; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
158 break; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
159 case TEST_EQ: |
849 | 160 if (node_time != filter->data.t.time) result = 0; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
161 break; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
162 default: |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
163 /* how'd I get here? */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
164 result = 0; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
165 break; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
166 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
167 return result; |
814 | 168 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
169 } |
875 | 170 if (op==CHECK_TYPE) return (node->st.st_mode & S_IFMT) == filter->data.type; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
171 |
814 | 172 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
173 if (op==ACTION_PRINT || op==ACTION_PRINT0) { |
875 | 174 char *path; |
175 int plen = 0; | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
176 char terminator = (op==ACTION_PRINT)*'\n'; |
849 | 177 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
178 path = dirtree_path(node, &plen); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
179 printf("%s%c", path, terminator); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
180 free(path); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
181 return 1; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
182 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
183 |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
184 if (op==ACTION_EXEC) return !do_exec(filter, node); |
849 | 185 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
186 error_msg("Ran out of operations in filter list!"); |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
187 return 1; |
814 | 188 } |
189 | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
190 static int check_node_callback(struct dirtree *node) |
814 | 191 { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
192 struct filter_node *junk; |
814 | 193 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
194 /* only recurse on "." at the root */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
195 /* so, don't recurse on 1) non-root "." and 2) any ".." */ |
816
3a7defbc671e
Remove more debug code from find.
Rob Landley <rob@landley.net>
parents:
815
diff
changeset
|
196 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
197 if (node->name[0] == '.' && |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
198 ((!node->name[1] && node->parent) || |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
199 (node->name[1]=='.' && !node->name[2]))) |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
200 return 0; |
814 | 201 |
875 | 202 evaluate(TT.filter_root, node, &junk); |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
203 return DIRTREE_RECURSE; |
814 | 204 } |
205 | |
206 | |
847
2506cbdccd20
Partial cleanup of find
Felix Janda <felix.janda@posteo.de>
parents:
816
diff
changeset
|
207 static void build_filter_list(void) |
814 | 208 { |
849 | 209 struct filter_node *node_list, *op_stack, *node, *op_node, *next; |
874 | 210 char **arg; |
211 int j; | |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
212 int prevop = 0; |
875 | 213 int have_action = 0; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
214 |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
215 /* part optargs here and build a filter list in prefix format */ |
814 | 216 |
849 | 217 TT.dir = "."; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
218 node_list = NULL; |
874 | 219 for (arg = toys.optargs; *arg; arg++) { |
220 struct { | |
221 char *arg; | |
222 int op; | |
223 int extrarg; | |
224 } arg_map[] = {{"-o", OP_OR, 0}, | |
225 {"-a", OP_AND, 0}, | |
226 {"!", OP_NOT, 0}, | |
227 {"(", LPAREN, 0}, | |
228 {")", RPAREN, 0}, | |
229 {"-name", CHECK_NAME, 1}, | |
230 {"-mtime", CHECK_MTIME, 1}, | |
231 {"-type", CHECK_TYPE, 1}, | |
232 {"-print", ACTION_PRINT, 0}, | |
233 {"-print0", ACTION_PRINT0, 0}, | |
234 {"-exec", ACTION_EXEC, 1} | |
235 }; | |
236 mode_t types[]={S_IFREG,S_IFDIR,S_IFCHR,S_IFBLK,S_IFLNK,S_IFSOCK,S_IFIFO}; | |
237 char **arg_array; | |
238 node = (struct filter_node *) xmalloc(sizeof(struct filter_node)); | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
239 node->op = OP_UNKNOWN; |
874 | 240 for (j=0; j < sizeof(arg_map)/sizeof(*arg_map); j++) { |
241 if (!strcmp(*arg, arg_map[j].arg)) { | |
242 node->op = arg_map[j].op; | |
243 if (arg_map[j].extrarg && !*(++arg)) | |
244 error_exit("Missing argument to %s", arg_map[j].arg); | |
245 break; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
246 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
247 } |
814 | 248 |
874 | 249 switch(node->op) { |
250 case CHECK_NAME: | |
251 node->data.name_regex = *arg; | |
252 break; | |
253 case CHECK_MTIME: | |
254 switch(**arg) { | |
255 case '+': | |
256 node->data.t.time_op=TEST_GT; | |
257 arg++; | |
258 break; | |
259 case '-': | |
260 node->data.t.time_op=TEST_LT; | |
261 arg++; | |
262 break; | |
263 default: | |
264 node->data.t.time_op=TEST_EQ; | |
265 break; | |
266 } | |
267 /* convert to days (very crudely) */ | |
268 node->data.t.time = atoi(*arg)/SECONDS_PER_DAY; | |
269 break; | |
270 case CHECK_TYPE: | |
271 if (-1 == (j = stridx("fdcblsp", **arg))) | |
272 error_exit("bad type '%s'", *arg); | |
273 else node->data.type = types[j]; | |
274 break; | |
275 case ACTION_EXEC: | |
276 arg_array = xmalloc(sizeof(char *)); | |
277 for (j = 0; *arg && strcmp(*arg, ";"); j++) { | |
278 /* new method */ | |
279 arg_array = xrealloc(arg_array, sizeof(char *) * (j+2)); | |
280 arg_array[j] = *arg; | |
281 if (!strcmp(*arg, "{}")) node->data.e.arg_path_index = j; | |
849 | 282 |
874 | 283 arg++; |
284 } | |
285 if (!*arg) error_exit("need ';' in exec"); | |
286 arg_array[j] = 0; | |
287 node->data.e.exec_args = arg_array; | |
288 break; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
289 } |
874 | 290 |
875 | 291 have_action |= IS_ACTION(node->op); |
814 | 292 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
293 if (node->op == OP_UNKNOWN) { |
874 | 294 if (**arg == '-') error_exit("bad option '%s'", *arg); |
295 else TT.dir = *arg; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
296 } else { |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
297 // add OP_AND where necessary |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
298 if (node_list) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
299 int o1 = node_list->op, o2 = node->op; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
300 if ((o1>MAX_OP && o2>MAX_OP) || |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
301 (o1==RPAREN && o2>=OP_NOT && o2!=RPAREN) || |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
302 (o1>=OP_NOT && o1!=LPAREN && o2==LPAREN)) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
303 struct filter_node *n = (struct filter_node *) |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
304 xmalloc(sizeof(struct filter_node)); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
305 n->op = OP_AND; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
306 n->next = node_list; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
307 node_list = n; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
308 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
309 } |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
310 /* push node */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
311 node->next = node_list;; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
312 node_list = node; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
313 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
314 |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
315 } |
814 | 316 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
317 /* now convert from infix to prefix */ |
875 | 318 if(have_action) TT.filter_root = NULL; |
319 else TT.filter_root = &(struct filter_node){0, ACTION_PRINT}; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
320 op_stack = NULL; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
321 node = node_list; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
322 while( node ) { |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
323 int op = node->op; |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
324 next = node->next; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
325 if (op==LPAREN || op==RPAREN) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
326 free(node); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
327 node = 0; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
328 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
329 if (op<=MAX_OP) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
330 if (prevop > op) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
331 /* pop opstack to output */ |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
332 op_node = op_stack; |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
333 while (op_node) { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
334 /* remove from op_stack */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
335 op_stack = op_node->next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
336 /* push to output */ |
874 | 337 op_node->next = TT.filter_root; |
338 TT.filter_root = op_node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
339 /* get next node */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
340 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
341 } |
867
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
342 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
343 if (node) { |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
344 /* push to opstack */ |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
345 node->next = op_stack; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
346 op_stack = node; |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
347 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
348 prevop = op*(op!=RPAREN); |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
349 } |
1700c6bfc8f5
find: Improve operator processing
Felix Janda <felix.janda@posteo.de>
parents:
849
diff
changeset
|
350 else { |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
351 /* push to output */ |
874 | 352 node->next = TT.filter_root; |
353 TT.filter_root = node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
354 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
355 node = next; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
356 } |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
357 /* end of input - push opstack to output */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
358 /* pop opstack to output till empty */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
359 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
360 while (op_node) { |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
361 op_stack = op_node->next; |
874 | 362 op_node->next = TT.filter_root; |
363 TT.filter_root = op_node; | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
364 op_node = op_stack; |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
365 } |
875 | 366 if(!have_action) { |
367 node = TT.filter_root; | |
368 TT.filter_root = (struct filter_node*) xmalloc(sizeof(struct filter_node)); | |
369 TT.filter_root->next = node; | |
370 TT.filter_root->op = OP_AND; | |
371 } | |
814 | 372 } |
373 | |
374 void find_main(void) | |
375 { | |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
376 /* parse filters, if present */ |
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
377 build_filter_list(); |
814 | 378 |
848
feea7a8ecbb1
Redo find's indenting from tabs to two spaces.
Rob Landley <rob@landley.net>
parents:
847
diff
changeset
|
379 /* FIXTHIS - parse actions, if present */ |
814 | 380 |
849 | 381 dirtree_read(TT.dir, check_node_callback); |
814 | 382 } |