1*79398b25SAndroid Build Coastguard Worker /*
2*79398b25SAndroid Build Coastguard Worker * Create a squashfs filesystem. This is a highly compressed read only
3*79398b25SAndroid Build Coastguard Worker * filesystem.
4*79398b25SAndroid Build Coastguard Worker *
5*79398b25SAndroid Build Coastguard Worker * Copyright (c) 2011, 2012, 2013, 2014
6*79398b25SAndroid Build Coastguard Worker * Phillip Lougher <[email protected]>
7*79398b25SAndroid Build Coastguard Worker *
8*79398b25SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
9*79398b25SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
10*79398b25SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version 2,
11*79398b25SAndroid Build Coastguard Worker * or (at your option) any later version.
12*79398b25SAndroid Build Coastguard Worker *
13*79398b25SAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
14*79398b25SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*79398b25SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*79398b25SAndroid Build Coastguard Worker * GNU General Public License for more details.
17*79398b25SAndroid Build Coastguard Worker *
18*79398b25SAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
19*79398b25SAndroid Build Coastguard Worker * along with this program; if not, write to the Free Software
20*79398b25SAndroid Build Coastguard Worker * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*79398b25SAndroid Build Coastguard Worker *
22*79398b25SAndroid Build Coastguard Worker * action.c
23*79398b25SAndroid Build Coastguard Worker */
24*79398b25SAndroid Build Coastguard Worker
25*79398b25SAndroid Build Coastguard Worker #include <fcntl.h>
26*79398b25SAndroid Build Coastguard Worker #include <dirent.h>
27*79398b25SAndroid Build Coastguard Worker #include <stddef.h>
28*79398b25SAndroid Build Coastguard Worker #include <stdlib.h>
29*79398b25SAndroid Build Coastguard Worker #include <stdio.h>
30*79398b25SAndroid Build Coastguard Worker #include <string.h>
31*79398b25SAndroid Build Coastguard Worker #include <sys/stat.h>
32*79398b25SAndroid Build Coastguard Worker #include <sys/types.h>
33*79398b25SAndroid Build Coastguard Worker #include <unistd.h>
34*79398b25SAndroid Build Coastguard Worker #include <fnmatch.h>
35*79398b25SAndroid Build Coastguard Worker #include <pwd.h>
36*79398b25SAndroid Build Coastguard Worker #include <grp.h>
37*79398b25SAndroid Build Coastguard Worker #include <sys/wait.h>
38*79398b25SAndroid Build Coastguard Worker #include <regex.h>
39*79398b25SAndroid Build Coastguard Worker #include <limits.h>
40*79398b25SAndroid Build Coastguard Worker #include <errno.h>
41*79398b25SAndroid Build Coastguard Worker
42*79398b25SAndroid Build Coastguard Worker #ifndef FNM_EXTMATCH /* glibc extension */
43*79398b25SAndroid Build Coastguard Worker #define FNM_EXTMATCH 0
44*79398b25SAndroid Build Coastguard Worker #endif
45*79398b25SAndroid Build Coastguard Worker
46*79398b25SAndroid Build Coastguard Worker #include "squashfs_fs.h"
47*79398b25SAndroid Build Coastguard Worker #include "mksquashfs.h"
48*79398b25SAndroid Build Coastguard Worker #include "action.h"
49*79398b25SAndroid Build Coastguard Worker #include "error.h"
50*79398b25SAndroid Build Coastguard Worker
51*79398b25SAndroid Build Coastguard Worker /*
52*79398b25SAndroid Build Coastguard Worker * code to parse actions
53*79398b25SAndroid Build Coastguard Worker */
54*79398b25SAndroid Build Coastguard Worker
55*79398b25SAndroid Build Coastguard Worker static char *cur_ptr, *source;
56*79398b25SAndroid Build Coastguard Worker static struct action *fragment_spec = NULL;
57*79398b25SAndroid Build Coastguard Worker static struct action *exclude_spec = NULL;
58*79398b25SAndroid Build Coastguard Worker static struct action *empty_spec = NULL;
59*79398b25SAndroid Build Coastguard Worker static struct action *move_spec = NULL;
60*79398b25SAndroid Build Coastguard Worker static struct action *prune_spec = NULL;
61*79398b25SAndroid Build Coastguard Worker static struct action *other_spec = NULL;
62*79398b25SAndroid Build Coastguard Worker static int fragment_count = 0;
63*79398b25SAndroid Build Coastguard Worker static int exclude_count = 0;
64*79398b25SAndroid Build Coastguard Worker static int empty_count = 0;
65*79398b25SAndroid Build Coastguard Worker static int move_count = 0;
66*79398b25SAndroid Build Coastguard Worker static int prune_count = 0;
67*79398b25SAndroid Build Coastguard Worker static int other_count = 0;
68*79398b25SAndroid Build Coastguard Worker static struct action_entry *parsing_action;
69*79398b25SAndroid Build Coastguard Worker
70*79398b25SAndroid Build Coastguard Worker static struct file_buffer *def_fragment = NULL;
71*79398b25SAndroid Build Coastguard Worker
72*79398b25SAndroid Build Coastguard Worker static struct token_entry token_table[] = {
73*79398b25SAndroid Build Coastguard Worker { "(", TOK_OPEN_BRACKET, 1, },
74*79398b25SAndroid Build Coastguard Worker { ")", TOK_CLOSE_BRACKET, 1 },
75*79398b25SAndroid Build Coastguard Worker { "&&", TOK_AND, 2 },
76*79398b25SAndroid Build Coastguard Worker { "||", TOK_OR, 2 },
77*79398b25SAndroid Build Coastguard Worker { "!", TOK_NOT, 1 },
78*79398b25SAndroid Build Coastguard Worker { ",", TOK_COMMA, 1 },
79*79398b25SAndroid Build Coastguard Worker { "@", TOK_AT, 1},
80*79398b25SAndroid Build Coastguard Worker { " ", TOK_WHITE_SPACE, 1 },
81*79398b25SAndroid Build Coastguard Worker { "\t ", TOK_WHITE_SPACE, 1 },
82*79398b25SAndroid Build Coastguard Worker { "", -1, 0 }
83*79398b25SAndroid Build Coastguard Worker };
84*79398b25SAndroid Build Coastguard Worker
85*79398b25SAndroid Build Coastguard Worker
86*79398b25SAndroid Build Coastguard Worker static struct test_entry test_table[];
87*79398b25SAndroid Build Coastguard Worker
88*79398b25SAndroid Build Coastguard Worker static struct action_entry action_table[];
89*79398b25SAndroid Build Coastguard Worker
90*79398b25SAndroid Build Coastguard Worker static struct expr *parse_expr(int subexp);
91*79398b25SAndroid Build Coastguard Worker
92*79398b25SAndroid Build Coastguard Worker extern char *pathname(struct dir_ent *);
93*79398b25SAndroid Build Coastguard Worker
94*79398b25SAndroid Build Coastguard Worker extern char *subpathname(struct dir_ent *);
95*79398b25SAndroid Build Coastguard Worker
96*79398b25SAndroid Build Coastguard Worker extern int read_file(char *filename, char *type, int (parse_line)(char *));
97*79398b25SAndroid Build Coastguard Worker
98*79398b25SAndroid Build Coastguard Worker /*
99*79398b25SAndroid Build Coastguard Worker * Lexical analyser
100*79398b25SAndroid Build Coastguard Worker */
101*79398b25SAndroid Build Coastguard Worker #define STR_SIZE 256
102*79398b25SAndroid Build Coastguard Worker
get_token(char ** string)103*79398b25SAndroid Build Coastguard Worker static int get_token(char **string)
104*79398b25SAndroid Build Coastguard Worker {
105*79398b25SAndroid Build Coastguard Worker /* string buffer */
106*79398b25SAndroid Build Coastguard Worker static char *str = NULL;
107*79398b25SAndroid Build Coastguard Worker static int size = 0;
108*79398b25SAndroid Build Coastguard Worker
109*79398b25SAndroid Build Coastguard Worker char *str_ptr;
110*79398b25SAndroid Build Coastguard Worker int cur_size, i, quoted;
111*79398b25SAndroid Build Coastguard Worker
112*79398b25SAndroid Build Coastguard Worker while (1) {
113*79398b25SAndroid Build Coastguard Worker if (*cur_ptr == '\0')
114*79398b25SAndroid Build Coastguard Worker return TOK_EOF;
115*79398b25SAndroid Build Coastguard Worker for (i = 0; token_table[i].token != -1; i++)
116*79398b25SAndroid Build Coastguard Worker if (strncmp(cur_ptr, token_table[i].string,
117*79398b25SAndroid Build Coastguard Worker token_table[i].size) == 0)
118*79398b25SAndroid Build Coastguard Worker break;
119*79398b25SAndroid Build Coastguard Worker if (token_table[i].token != TOK_WHITE_SPACE)
120*79398b25SAndroid Build Coastguard Worker break;
121*79398b25SAndroid Build Coastguard Worker cur_ptr ++;
122*79398b25SAndroid Build Coastguard Worker }
123*79398b25SAndroid Build Coastguard Worker
124*79398b25SAndroid Build Coastguard Worker if (token_table[i].token != -1) {
125*79398b25SAndroid Build Coastguard Worker cur_ptr += token_table[i].size;
126*79398b25SAndroid Build Coastguard Worker return token_table[i].token;
127*79398b25SAndroid Build Coastguard Worker }
128*79398b25SAndroid Build Coastguard Worker
129*79398b25SAndroid Build Coastguard Worker /* string */
130*79398b25SAndroid Build Coastguard Worker if(str == NULL) {
131*79398b25SAndroid Build Coastguard Worker str = malloc(STR_SIZE);
132*79398b25SAndroid Build Coastguard Worker if(str == NULL)
133*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
134*79398b25SAndroid Build Coastguard Worker size = STR_SIZE;
135*79398b25SAndroid Build Coastguard Worker }
136*79398b25SAndroid Build Coastguard Worker
137*79398b25SAndroid Build Coastguard Worker /* Initialise string being read */
138*79398b25SAndroid Build Coastguard Worker str_ptr = str;
139*79398b25SAndroid Build Coastguard Worker cur_size = 0;
140*79398b25SAndroid Build Coastguard Worker quoted = 0;
141*79398b25SAndroid Build Coastguard Worker
142*79398b25SAndroid Build Coastguard Worker while(1) {
143*79398b25SAndroid Build Coastguard Worker while(*cur_ptr == '"') {
144*79398b25SAndroid Build Coastguard Worker cur_ptr ++;
145*79398b25SAndroid Build Coastguard Worker quoted = !quoted;
146*79398b25SAndroid Build Coastguard Worker }
147*79398b25SAndroid Build Coastguard Worker
148*79398b25SAndroid Build Coastguard Worker if(*cur_ptr == '\0') {
149*79398b25SAndroid Build Coastguard Worker /* inside quoted string EOF, otherwise end of string */
150*79398b25SAndroid Build Coastguard Worker if(quoted)
151*79398b25SAndroid Build Coastguard Worker return TOK_EOF;
152*79398b25SAndroid Build Coastguard Worker else
153*79398b25SAndroid Build Coastguard Worker break;
154*79398b25SAndroid Build Coastguard Worker }
155*79398b25SAndroid Build Coastguard Worker
156*79398b25SAndroid Build Coastguard Worker if(!quoted) {
157*79398b25SAndroid Build Coastguard Worker for(i = 0; token_table[i].token != -1; i++)
158*79398b25SAndroid Build Coastguard Worker if (strncmp(cur_ptr, token_table[i].string,
159*79398b25SAndroid Build Coastguard Worker token_table[i].size) == 0)
160*79398b25SAndroid Build Coastguard Worker break;
161*79398b25SAndroid Build Coastguard Worker if (token_table[i].token != -1)
162*79398b25SAndroid Build Coastguard Worker break;
163*79398b25SAndroid Build Coastguard Worker }
164*79398b25SAndroid Build Coastguard Worker
165*79398b25SAndroid Build Coastguard Worker if(*cur_ptr == '\\') {
166*79398b25SAndroid Build Coastguard Worker cur_ptr ++;
167*79398b25SAndroid Build Coastguard Worker if(*cur_ptr == '\0')
168*79398b25SAndroid Build Coastguard Worker return TOK_EOF;
169*79398b25SAndroid Build Coastguard Worker }
170*79398b25SAndroid Build Coastguard Worker
171*79398b25SAndroid Build Coastguard Worker if(cur_size + 2 > size) {
172*79398b25SAndroid Build Coastguard Worker char *tmp;
173*79398b25SAndroid Build Coastguard Worker
174*79398b25SAndroid Build Coastguard Worker size = (cur_size + 1 + STR_SIZE) & ~(STR_SIZE - 1);
175*79398b25SAndroid Build Coastguard Worker
176*79398b25SAndroid Build Coastguard Worker tmp = realloc(str, size);
177*79398b25SAndroid Build Coastguard Worker if(tmp == NULL)
178*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
179*79398b25SAndroid Build Coastguard Worker
180*79398b25SAndroid Build Coastguard Worker str_ptr = str_ptr - str + tmp;
181*79398b25SAndroid Build Coastguard Worker str = tmp;
182*79398b25SAndroid Build Coastguard Worker }
183*79398b25SAndroid Build Coastguard Worker
184*79398b25SAndroid Build Coastguard Worker *str_ptr ++ = *cur_ptr ++;
185*79398b25SAndroid Build Coastguard Worker cur_size ++;
186*79398b25SAndroid Build Coastguard Worker }
187*79398b25SAndroid Build Coastguard Worker
188*79398b25SAndroid Build Coastguard Worker *str_ptr = '\0';
189*79398b25SAndroid Build Coastguard Worker *string = str;
190*79398b25SAndroid Build Coastguard Worker return TOK_STRING;
191*79398b25SAndroid Build Coastguard Worker }
192*79398b25SAndroid Build Coastguard Worker
193*79398b25SAndroid Build Coastguard Worker
peek_token(char ** string)194*79398b25SAndroid Build Coastguard Worker static int peek_token(char **string)
195*79398b25SAndroid Build Coastguard Worker {
196*79398b25SAndroid Build Coastguard Worker char *saved = cur_ptr;
197*79398b25SAndroid Build Coastguard Worker int token = get_token(string);
198*79398b25SAndroid Build Coastguard Worker
199*79398b25SAndroid Build Coastguard Worker cur_ptr = saved;
200*79398b25SAndroid Build Coastguard Worker
201*79398b25SAndroid Build Coastguard Worker return token;
202*79398b25SAndroid Build Coastguard Worker }
203*79398b25SAndroid Build Coastguard Worker
204*79398b25SAndroid Build Coastguard Worker
205*79398b25SAndroid Build Coastguard Worker /*
206*79398b25SAndroid Build Coastguard Worker * Expression parser
207*79398b25SAndroid Build Coastguard Worker */
free_parse_tree(struct expr * expr)208*79398b25SAndroid Build Coastguard Worker static void free_parse_tree(struct expr *expr)
209*79398b25SAndroid Build Coastguard Worker {
210*79398b25SAndroid Build Coastguard Worker if(expr->type == ATOM_TYPE) {
211*79398b25SAndroid Build Coastguard Worker int i;
212*79398b25SAndroid Build Coastguard Worker
213*79398b25SAndroid Build Coastguard Worker for(i = 0; i < expr->atom.test->args; i++)
214*79398b25SAndroid Build Coastguard Worker free(expr->atom.argv[i]);
215*79398b25SAndroid Build Coastguard Worker
216*79398b25SAndroid Build Coastguard Worker free(expr->atom.argv);
217*79398b25SAndroid Build Coastguard Worker } else if (expr->type == UNARY_TYPE)
218*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr->unary_op.expr);
219*79398b25SAndroid Build Coastguard Worker else {
220*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr->expr_op.lhs);
221*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr->expr_op.rhs);
222*79398b25SAndroid Build Coastguard Worker }
223*79398b25SAndroid Build Coastguard Worker
224*79398b25SAndroid Build Coastguard Worker free(expr);
225*79398b25SAndroid Build Coastguard Worker }
226*79398b25SAndroid Build Coastguard Worker
227*79398b25SAndroid Build Coastguard Worker
create_expr(struct expr * lhs,int op,struct expr * rhs)228*79398b25SAndroid Build Coastguard Worker static struct expr *create_expr(struct expr *lhs, int op, struct expr *rhs)
229*79398b25SAndroid Build Coastguard Worker {
230*79398b25SAndroid Build Coastguard Worker struct expr *expr;
231*79398b25SAndroid Build Coastguard Worker
232*79398b25SAndroid Build Coastguard Worker if (rhs == NULL) {
233*79398b25SAndroid Build Coastguard Worker free_parse_tree(lhs);
234*79398b25SAndroid Build Coastguard Worker return NULL;
235*79398b25SAndroid Build Coastguard Worker }
236*79398b25SAndroid Build Coastguard Worker
237*79398b25SAndroid Build Coastguard Worker expr = malloc(sizeof(*expr));
238*79398b25SAndroid Build Coastguard Worker if (expr == NULL)
239*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
240*79398b25SAndroid Build Coastguard Worker
241*79398b25SAndroid Build Coastguard Worker expr->type = OP_TYPE;
242*79398b25SAndroid Build Coastguard Worker expr->expr_op.lhs = lhs;
243*79398b25SAndroid Build Coastguard Worker expr->expr_op.rhs = rhs;
244*79398b25SAndroid Build Coastguard Worker expr->expr_op.op = op;
245*79398b25SAndroid Build Coastguard Worker
246*79398b25SAndroid Build Coastguard Worker return expr;
247*79398b25SAndroid Build Coastguard Worker }
248*79398b25SAndroid Build Coastguard Worker
249*79398b25SAndroid Build Coastguard Worker
create_unary_op(struct expr * lhs,int op)250*79398b25SAndroid Build Coastguard Worker static struct expr *create_unary_op(struct expr *lhs, int op)
251*79398b25SAndroid Build Coastguard Worker {
252*79398b25SAndroid Build Coastguard Worker struct expr *expr;
253*79398b25SAndroid Build Coastguard Worker
254*79398b25SAndroid Build Coastguard Worker if (lhs == NULL)
255*79398b25SAndroid Build Coastguard Worker return NULL;
256*79398b25SAndroid Build Coastguard Worker
257*79398b25SAndroid Build Coastguard Worker expr = malloc(sizeof(*expr));
258*79398b25SAndroid Build Coastguard Worker if (expr == NULL)
259*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
260*79398b25SAndroid Build Coastguard Worker
261*79398b25SAndroid Build Coastguard Worker expr->type = UNARY_TYPE;
262*79398b25SAndroid Build Coastguard Worker expr->unary_op.expr = lhs;
263*79398b25SAndroid Build Coastguard Worker expr->unary_op.op = op;
264*79398b25SAndroid Build Coastguard Worker
265*79398b25SAndroid Build Coastguard Worker return expr;
266*79398b25SAndroid Build Coastguard Worker }
267*79398b25SAndroid Build Coastguard Worker
268*79398b25SAndroid Build Coastguard Worker
parse_test(char * name)269*79398b25SAndroid Build Coastguard Worker static struct expr *parse_test(char *name)
270*79398b25SAndroid Build Coastguard Worker {
271*79398b25SAndroid Build Coastguard Worker char *string, **argv = NULL;
272*79398b25SAndroid Build Coastguard Worker int token, args = 0;
273*79398b25SAndroid Build Coastguard Worker int i;
274*79398b25SAndroid Build Coastguard Worker struct test_entry *test;
275*79398b25SAndroid Build Coastguard Worker struct expr *expr;
276*79398b25SAndroid Build Coastguard Worker
277*79398b25SAndroid Build Coastguard Worker for (i = 0; test_table[i].args != -1; i++)
278*79398b25SAndroid Build Coastguard Worker if (strcmp(name, test_table[i].name) == 0)
279*79398b25SAndroid Build Coastguard Worker break;
280*79398b25SAndroid Build Coastguard Worker
281*79398b25SAndroid Build Coastguard Worker test = &test_table[i];
282*79398b25SAndroid Build Coastguard Worker
283*79398b25SAndroid Build Coastguard Worker if (test->args == -1) {
284*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Non-existent test \"%s\"\n", name);
285*79398b25SAndroid Build Coastguard Worker return NULL;
286*79398b25SAndroid Build Coastguard Worker }
287*79398b25SAndroid Build Coastguard Worker
288*79398b25SAndroid Build Coastguard Worker if(parsing_action->type == EXCLUDE_ACTION && !test->exclude_ok) {
289*79398b25SAndroid Build Coastguard Worker fprintf(stderr, "Failed to parse action \"%s\"\n", source);
290*79398b25SAndroid Build Coastguard Worker fprintf(stderr, "Test \"%s\" cannot be used in exclude "
291*79398b25SAndroid Build Coastguard Worker "actions\n", name);
292*79398b25SAndroid Build Coastguard Worker fprintf(stderr, "Use prune action instead ...\n");
293*79398b25SAndroid Build Coastguard Worker return NULL;
294*79398b25SAndroid Build Coastguard Worker }
295*79398b25SAndroid Build Coastguard Worker
296*79398b25SAndroid Build Coastguard Worker expr = malloc(sizeof(*expr));
297*79398b25SAndroid Build Coastguard Worker if (expr == NULL)
298*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
299*79398b25SAndroid Build Coastguard Worker
300*79398b25SAndroid Build Coastguard Worker expr->type = ATOM_TYPE;
301*79398b25SAndroid Build Coastguard Worker
302*79398b25SAndroid Build Coastguard Worker expr->atom.test = test;
303*79398b25SAndroid Build Coastguard Worker expr->atom.data = NULL;
304*79398b25SAndroid Build Coastguard Worker
305*79398b25SAndroid Build Coastguard Worker /*
306*79398b25SAndroid Build Coastguard Worker * If the test has no arguments, then go straight to checking if there's
307*79398b25SAndroid Build Coastguard Worker * enough arguments
308*79398b25SAndroid Build Coastguard Worker */
309*79398b25SAndroid Build Coastguard Worker token = peek_token(&string);
310*79398b25SAndroid Build Coastguard Worker
311*79398b25SAndroid Build Coastguard Worker if (token != TOK_OPEN_BRACKET)
312*79398b25SAndroid Build Coastguard Worker goto skip_args;
313*79398b25SAndroid Build Coastguard Worker
314*79398b25SAndroid Build Coastguard Worker get_token(&string);
315*79398b25SAndroid Build Coastguard Worker
316*79398b25SAndroid Build Coastguard Worker /*
317*79398b25SAndroid Build Coastguard Worker * speculatively read all the arguments, and then see if the
318*79398b25SAndroid Build Coastguard Worker * number of arguments read is the number expected, this handles
319*79398b25SAndroid Build Coastguard Worker * tests with a variable number of arguments
320*79398b25SAndroid Build Coastguard Worker */
321*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
322*79398b25SAndroid Build Coastguard Worker if (token == TOK_CLOSE_BRACKET)
323*79398b25SAndroid Build Coastguard Worker goto skip_args;
324*79398b25SAndroid Build Coastguard Worker
325*79398b25SAndroid Build Coastguard Worker while(1) {
326*79398b25SAndroid Build Coastguard Worker if (token != TOK_STRING) {
327*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected "
328*79398b25SAndroid Build Coastguard Worker "argument\n", TOK_TO_STR(token, string));
329*79398b25SAndroid Build Coastguard Worker goto failed;
330*79398b25SAndroid Build Coastguard Worker }
331*79398b25SAndroid Build Coastguard Worker
332*79398b25SAndroid Build Coastguard Worker argv = realloc(argv, (args + 1) * sizeof(char *));
333*79398b25SAndroid Build Coastguard Worker if (argv == NULL)
334*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
335*79398b25SAndroid Build Coastguard Worker
336*79398b25SAndroid Build Coastguard Worker argv[args ++ ] = strdup(string);
337*79398b25SAndroid Build Coastguard Worker
338*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
339*79398b25SAndroid Build Coastguard Worker
340*79398b25SAndroid Build Coastguard Worker if (token == TOK_CLOSE_BRACKET)
341*79398b25SAndroid Build Coastguard Worker break;
342*79398b25SAndroid Build Coastguard Worker
343*79398b25SAndroid Build Coastguard Worker if (token != TOK_COMMA) {
344*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected "
345*79398b25SAndroid Build Coastguard Worker "\",\" or \")\"\n", TOK_TO_STR(token, string));
346*79398b25SAndroid Build Coastguard Worker goto failed;
347*79398b25SAndroid Build Coastguard Worker }
348*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
349*79398b25SAndroid Build Coastguard Worker }
350*79398b25SAndroid Build Coastguard Worker
351*79398b25SAndroid Build Coastguard Worker skip_args:
352*79398b25SAndroid Build Coastguard Worker /*
353*79398b25SAndroid Build Coastguard Worker * expected number of arguments?
354*79398b25SAndroid Build Coastguard Worker */
355*79398b25SAndroid Build Coastguard Worker if(test->args != -2 && args != test->args) {
356*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected number of arguments, expected %d, "
357*79398b25SAndroid Build Coastguard Worker "got %d\n", test->args, args);
358*79398b25SAndroid Build Coastguard Worker goto failed;
359*79398b25SAndroid Build Coastguard Worker }
360*79398b25SAndroid Build Coastguard Worker
361*79398b25SAndroid Build Coastguard Worker expr->atom.args = args;
362*79398b25SAndroid Build Coastguard Worker expr->atom.argv = argv;
363*79398b25SAndroid Build Coastguard Worker
364*79398b25SAndroid Build Coastguard Worker if (test->parse_args) {
365*79398b25SAndroid Build Coastguard Worker int res = test->parse_args(test, &expr->atom);
366*79398b25SAndroid Build Coastguard Worker
367*79398b25SAndroid Build Coastguard Worker if (res == 0)
368*79398b25SAndroid Build Coastguard Worker goto failed;
369*79398b25SAndroid Build Coastguard Worker }
370*79398b25SAndroid Build Coastguard Worker
371*79398b25SAndroid Build Coastguard Worker return expr;
372*79398b25SAndroid Build Coastguard Worker
373*79398b25SAndroid Build Coastguard Worker failed:
374*79398b25SAndroid Build Coastguard Worker free(argv);
375*79398b25SAndroid Build Coastguard Worker free(expr);
376*79398b25SAndroid Build Coastguard Worker return NULL;
377*79398b25SAndroid Build Coastguard Worker }
378*79398b25SAndroid Build Coastguard Worker
379*79398b25SAndroid Build Coastguard Worker
get_atom()380*79398b25SAndroid Build Coastguard Worker static struct expr *get_atom()
381*79398b25SAndroid Build Coastguard Worker {
382*79398b25SAndroid Build Coastguard Worker char *string;
383*79398b25SAndroid Build Coastguard Worker int token = get_token(&string);
384*79398b25SAndroid Build Coastguard Worker
385*79398b25SAndroid Build Coastguard Worker switch(token) {
386*79398b25SAndroid Build Coastguard Worker case TOK_NOT:
387*79398b25SAndroid Build Coastguard Worker return create_unary_op(get_atom(), token);
388*79398b25SAndroid Build Coastguard Worker case TOK_OPEN_BRACKET:
389*79398b25SAndroid Build Coastguard Worker return parse_expr(1);
390*79398b25SAndroid Build Coastguard Worker case TOK_STRING:
391*79398b25SAndroid Build Coastguard Worker return parse_test(string);
392*79398b25SAndroid Build Coastguard Worker default:
393*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected test "
394*79398b25SAndroid Build Coastguard Worker "operation, \"!\", or \"(\"\n",
395*79398b25SAndroid Build Coastguard Worker TOK_TO_STR(token, string));
396*79398b25SAndroid Build Coastguard Worker return NULL;
397*79398b25SAndroid Build Coastguard Worker }
398*79398b25SAndroid Build Coastguard Worker }
399*79398b25SAndroid Build Coastguard Worker
400*79398b25SAndroid Build Coastguard Worker
parse_expr(int subexp)401*79398b25SAndroid Build Coastguard Worker static struct expr *parse_expr(int subexp)
402*79398b25SAndroid Build Coastguard Worker {
403*79398b25SAndroid Build Coastguard Worker struct expr *expr = get_atom();
404*79398b25SAndroid Build Coastguard Worker
405*79398b25SAndroid Build Coastguard Worker while (expr) {
406*79398b25SAndroid Build Coastguard Worker char *string;
407*79398b25SAndroid Build Coastguard Worker int op = get_token(&string);
408*79398b25SAndroid Build Coastguard Worker
409*79398b25SAndroid Build Coastguard Worker if (op == TOK_EOF) {
410*79398b25SAndroid Build Coastguard Worker if (subexp) {
411*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr);
412*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Expected \"&&\", \"||\" or "
413*79398b25SAndroid Build Coastguard Worker "\")\", got EOF\n");
414*79398b25SAndroid Build Coastguard Worker return NULL;
415*79398b25SAndroid Build Coastguard Worker }
416*79398b25SAndroid Build Coastguard Worker break;
417*79398b25SAndroid Build Coastguard Worker }
418*79398b25SAndroid Build Coastguard Worker
419*79398b25SAndroid Build Coastguard Worker if (op == TOK_CLOSE_BRACKET) {
420*79398b25SAndroid Build Coastguard Worker if (!subexp) {
421*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr);
422*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected \")\", expected "
423*79398b25SAndroid Build Coastguard Worker "\"&&\", \"!!\" or EOF\n");
424*79398b25SAndroid Build Coastguard Worker return NULL;
425*79398b25SAndroid Build Coastguard Worker }
426*79398b25SAndroid Build Coastguard Worker break;
427*79398b25SAndroid Build Coastguard Worker }
428*79398b25SAndroid Build Coastguard Worker
429*79398b25SAndroid Build Coastguard Worker if (op != TOK_AND && op != TOK_OR) {
430*79398b25SAndroid Build Coastguard Worker free_parse_tree(expr);
431*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected "
432*79398b25SAndroid Build Coastguard Worker "\"&&\" or \"||\"\n", TOK_TO_STR(op, string));
433*79398b25SAndroid Build Coastguard Worker return NULL;
434*79398b25SAndroid Build Coastguard Worker }
435*79398b25SAndroid Build Coastguard Worker
436*79398b25SAndroid Build Coastguard Worker expr = create_expr(expr, op, get_atom());
437*79398b25SAndroid Build Coastguard Worker }
438*79398b25SAndroid Build Coastguard Worker
439*79398b25SAndroid Build Coastguard Worker return expr;
440*79398b25SAndroid Build Coastguard Worker }
441*79398b25SAndroid Build Coastguard Worker
442*79398b25SAndroid Build Coastguard Worker
443*79398b25SAndroid Build Coastguard Worker /*
444*79398b25SAndroid Build Coastguard Worker * Action parser
445*79398b25SAndroid Build Coastguard Worker */
parse_action(char * s,int verbose)446*79398b25SAndroid Build Coastguard Worker int parse_action(char *s, int verbose)
447*79398b25SAndroid Build Coastguard Worker {
448*79398b25SAndroid Build Coastguard Worker char *string, **argv = NULL;
449*79398b25SAndroid Build Coastguard Worker int i, token, args = 0;
450*79398b25SAndroid Build Coastguard Worker struct expr *expr;
451*79398b25SAndroid Build Coastguard Worker struct action_entry *action;
452*79398b25SAndroid Build Coastguard Worker void *data = NULL;
453*79398b25SAndroid Build Coastguard Worker struct action **spec_list;
454*79398b25SAndroid Build Coastguard Worker int spec_count;
455*79398b25SAndroid Build Coastguard Worker
456*79398b25SAndroid Build Coastguard Worker cur_ptr = source = s;
457*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
458*79398b25SAndroid Build Coastguard Worker
459*79398b25SAndroid Build Coastguard Worker if (token != TOK_STRING) {
460*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected name\n",
461*79398b25SAndroid Build Coastguard Worker TOK_TO_STR(token, string));
462*79398b25SAndroid Build Coastguard Worker return 0;
463*79398b25SAndroid Build Coastguard Worker }
464*79398b25SAndroid Build Coastguard Worker
465*79398b25SAndroid Build Coastguard Worker for (i = 0; action_table[i].args != -1; i++)
466*79398b25SAndroid Build Coastguard Worker if (strcmp(string, action_table[i].name) == 0)
467*79398b25SAndroid Build Coastguard Worker break;
468*79398b25SAndroid Build Coastguard Worker
469*79398b25SAndroid Build Coastguard Worker if (action_table[i].args == -1) {
470*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Non-existent action \"%s\"\n", string);
471*79398b25SAndroid Build Coastguard Worker return 0;
472*79398b25SAndroid Build Coastguard Worker }
473*79398b25SAndroid Build Coastguard Worker
474*79398b25SAndroid Build Coastguard Worker action = &action_table[i];
475*79398b25SAndroid Build Coastguard Worker
476*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
477*79398b25SAndroid Build Coastguard Worker
478*79398b25SAndroid Build Coastguard Worker if (token == TOK_AT)
479*79398b25SAndroid Build Coastguard Worker goto skip_args;
480*79398b25SAndroid Build Coastguard Worker
481*79398b25SAndroid Build Coastguard Worker if (token != TOK_OPEN_BRACKET) {
482*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected \"(\"\n",
483*79398b25SAndroid Build Coastguard Worker TOK_TO_STR(token, string));
484*79398b25SAndroid Build Coastguard Worker goto failed;
485*79398b25SAndroid Build Coastguard Worker }
486*79398b25SAndroid Build Coastguard Worker
487*79398b25SAndroid Build Coastguard Worker /*
488*79398b25SAndroid Build Coastguard Worker * speculatively read all the arguments, and then see if the
489*79398b25SAndroid Build Coastguard Worker * number of arguments read is the number expected, this handles
490*79398b25SAndroid Build Coastguard Worker * actions with a variable number of arguments
491*79398b25SAndroid Build Coastguard Worker */
492*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
493*79398b25SAndroid Build Coastguard Worker if (token == TOK_CLOSE_BRACKET)
494*79398b25SAndroid Build Coastguard Worker goto skip_args;
495*79398b25SAndroid Build Coastguard Worker
496*79398b25SAndroid Build Coastguard Worker while (1) {
497*79398b25SAndroid Build Coastguard Worker if (token != TOK_STRING) {
498*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected "
499*79398b25SAndroid Build Coastguard Worker "argument\n", TOK_TO_STR(token, string));
500*79398b25SAndroid Build Coastguard Worker goto failed;
501*79398b25SAndroid Build Coastguard Worker }
502*79398b25SAndroid Build Coastguard Worker
503*79398b25SAndroid Build Coastguard Worker argv = realloc(argv, (args + 1) * sizeof(char *));
504*79398b25SAndroid Build Coastguard Worker if (argv == NULL)
505*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
506*79398b25SAndroid Build Coastguard Worker
507*79398b25SAndroid Build Coastguard Worker argv[args ++] = strdup(string);
508*79398b25SAndroid Build Coastguard Worker
509*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
510*79398b25SAndroid Build Coastguard Worker
511*79398b25SAndroid Build Coastguard Worker if (token == TOK_CLOSE_BRACKET)
512*79398b25SAndroid Build Coastguard Worker break;
513*79398b25SAndroid Build Coastguard Worker
514*79398b25SAndroid Build Coastguard Worker if (token != TOK_COMMA) {
515*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected "
516*79398b25SAndroid Build Coastguard Worker "\",\" or \")\"\n", TOK_TO_STR(token, string));
517*79398b25SAndroid Build Coastguard Worker goto failed;
518*79398b25SAndroid Build Coastguard Worker }
519*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
520*79398b25SAndroid Build Coastguard Worker }
521*79398b25SAndroid Build Coastguard Worker
522*79398b25SAndroid Build Coastguard Worker skip_args:
523*79398b25SAndroid Build Coastguard Worker /*
524*79398b25SAndroid Build Coastguard Worker * expected number of arguments?
525*79398b25SAndroid Build Coastguard Worker */
526*79398b25SAndroid Build Coastguard Worker if(action->args != -2 && args != action->args) {
527*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected number of arguments, expected %d, "
528*79398b25SAndroid Build Coastguard Worker "got %d\n", action->args, args);
529*79398b25SAndroid Build Coastguard Worker goto failed;
530*79398b25SAndroid Build Coastguard Worker }
531*79398b25SAndroid Build Coastguard Worker
532*79398b25SAndroid Build Coastguard Worker if (action->parse_args) {
533*79398b25SAndroid Build Coastguard Worker int res = action->parse_args(action, args, argv, &data);
534*79398b25SAndroid Build Coastguard Worker
535*79398b25SAndroid Build Coastguard Worker if (res == 0)
536*79398b25SAndroid Build Coastguard Worker goto failed;
537*79398b25SAndroid Build Coastguard Worker }
538*79398b25SAndroid Build Coastguard Worker
539*79398b25SAndroid Build Coastguard Worker if (token == TOK_CLOSE_BRACKET)
540*79398b25SAndroid Build Coastguard Worker token = get_token(&string);
541*79398b25SAndroid Build Coastguard Worker
542*79398b25SAndroid Build Coastguard Worker if (token != TOK_AT) {
543*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected token \"%s\", expected \"@\"\n",
544*79398b25SAndroid Build Coastguard Worker TOK_TO_STR(token, string));
545*79398b25SAndroid Build Coastguard Worker goto failed;
546*79398b25SAndroid Build Coastguard Worker }
547*79398b25SAndroid Build Coastguard Worker
548*79398b25SAndroid Build Coastguard Worker parsing_action = action;
549*79398b25SAndroid Build Coastguard Worker expr = parse_expr(0);
550*79398b25SAndroid Build Coastguard Worker
551*79398b25SAndroid Build Coastguard Worker if (expr == NULL)
552*79398b25SAndroid Build Coastguard Worker goto failed;
553*79398b25SAndroid Build Coastguard Worker
554*79398b25SAndroid Build Coastguard Worker /*
555*79398b25SAndroid Build Coastguard Worker * choose action list and increment action counter
556*79398b25SAndroid Build Coastguard Worker */
557*79398b25SAndroid Build Coastguard Worker switch(action->type) {
558*79398b25SAndroid Build Coastguard Worker case FRAGMENT_ACTION:
559*79398b25SAndroid Build Coastguard Worker spec_count = fragment_count ++;
560*79398b25SAndroid Build Coastguard Worker spec_list = &fragment_spec;
561*79398b25SAndroid Build Coastguard Worker break;
562*79398b25SAndroid Build Coastguard Worker case EXCLUDE_ACTION:
563*79398b25SAndroid Build Coastguard Worker spec_count = exclude_count ++;
564*79398b25SAndroid Build Coastguard Worker spec_list = &exclude_spec;
565*79398b25SAndroid Build Coastguard Worker break;
566*79398b25SAndroid Build Coastguard Worker case EMPTY_ACTION:
567*79398b25SAndroid Build Coastguard Worker spec_count = empty_count ++;
568*79398b25SAndroid Build Coastguard Worker spec_list = &empty_spec;
569*79398b25SAndroid Build Coastguard Worker break;
570*79398b25SAndroid Build Coastguard Worker case MOVE_ACTION:
571*79398b25SAndroid Build Coastguard Worker spec_count = move_count ++;
572*79398b25SAndroid Build Coastguard Worker spec_list = &move_spec;
573*79398b25SAndroid Build Coastguard Worker break;
574*79398b25SAndroid Build Coastguard Worker case PRUNE_ACTION:
575*79398b25SAndroid Build Coastguard Worker spec_count = prune_count ++;
576*79398b25SAndroid Build Coastguard Worker spec_list = &prune_spec;
577*79398b25SAndroid Build Coastguard Worker break;
578*79398b25SAndroid Build Coastguard Worker default:
579*79398b25SAndroid Build Coastguard Worker spec_count = other_count ++;
580*79398b25SAndroid Build Coastguard Worker spec_list = &other_spec;
581*79398b25SAndroid Build Coastguard Worker }
582*79398b25SAndroid Build Coastguard Worker
583*79398b25SAndroid Build Coastguard Worker *spec_list = realloc(*spec_list, (spec_count + 1) *
584*79398b25SAndroid Build Coastguard Worker sizeof(struct action));
585*79398b25SAndroid Build Coastguard Worker if (*spec_list == NULL)
586*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
587*79398b25SAndroid Build Coastguard Worker
588*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].type = action->type;
589*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].action = action;
590*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].args = args;
591*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].argv = argv;
592*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].expr = expr;
593*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].data = data;
594*79398b25SAndroid Build Coastguard Worker (*spec_list)[spec_count].verbose = verbose;
595*79398b25SAndroid Build Coastguard Worker
596*79398b25SAndroid Build Coastguard Worker return 1;
597*79398b25SAndroid Build Coastguard Worker
598*79398b25SAndroid Build Coastguard Worker failed:
599*79398b25SAndroid Build Coastguard Worker free(argv);
600*79398b25SAndroid Build Coastguard Worker return 0;
601*79398b25SAndroid Build Coastguard Worker }
602*79398b25SAndroid Build Coastguard Worker
603*79398b25SAndroid Build Coastguard Worker
604*79398b25SAndroid Build Coastguard Worker /*
605*79398b25SAndroid Build Coastguard Worker * Evaluate expressions
606*79398b25SAndroid Build Coastguard Worker */
607*79398b25SAndroid Build Coastguard Worker
608*79398b25SAndroid Build Coastguard Worker #define ALLOC_SZ 128
609*79398b25SAndroid Build Coastguard Worker
610*79398b25SAndroid Build Coastguard Worker #define LOG_ENABLE 0
611*79398b25SAndroid Build Coastguard Worker #define LOG_DISABLE 1
612*79398b25SAndroid Build Coastguard Worker #define LOG_PRINT 2
613*79398b25SAndroid Build Coastguard Worker #define LOG_ENABLED 3
614*79398b25SAndroid Build Coastguard Worker
_expr_log(char * string,int cmnd)615*79398b25SAndroid Build Coastguard Worker char *_expr_log(char *string, int cmnd)
616*79398b25SAndroid Build Coastguard Worker {
617*79398b25SAndroid Build Coastguard Worker static char *expr_msg = NULL;
618*79398b25SAndroid Build Coastguard Worker static int cur_size = 0, alloc_size = 0;
619*79398b25SAndroid Build Coastguard Worker int size;
620*79398b25SAndroid Build Coastguard Worker
621*79398b25SAndroid Build Coastguard Worker switch(cmnd) {
622*79398b25SAndroid Build Coastguard Worker case LOG_ENABLE:
623*79398b25SAndroid Build Coastguard Worker expr_msg = malloc(ALLOC_SZ);
624*79398b25SAndroid Build Coastguard Worker alloc_size = ALLOC_SZ;
625*79398b25SAndroid Build Coastguard Worker cur_size = 0;
626*79398b25SAndroid Build Coastguard Worker return expr_msg;
627*79398b25SAndroid Build Coastguard Worker case LOG_DISABLE:
628*79398b25SAndroid Build Coastguard Worker free(expr_msg);
629*79398b25SAndroid Build Coastguard Worker alloc_size = cur_size = 0;
630*79398b25SAndroid Build Coastguard Worker return expr_msg = NULL;
631*79398b25SAndroid Build Coastguard Worker case LOG_ENABLED:
632*79398b25SAndroid Build Coastguard Worker return expr_msg;
633*79398b25SAndroid Build Coastguard Worker default:
634*79398b25SAndroid Build Coastguard Worker if(expr_msg == NULL)
635*79398b25SAndroid Build Coastguard Worker return NULL;
636*79398b25SAndroid Build Coastguard Worker break;
637*79398b25SAndroid Build Coastguard Worker }
638*79398b25SAndroid Build Coastguard Worker
639*79398b25SAndroid Build Coastguard Worker /* if string is empty append '\0' */
640*79398b25SAndroid Build Coastguard Worker size = strlen(string) ? : 1;
641*79398b25SAndroid Build Coastguard Worker
642*79398b25SAndroid Build Coastguard Worker if(alloc_size - cur_size < size) {
643*79398b25SAndroid Build Coastguard Worker /* buffer too small, expand */
644*79398b25SAndroid Build Coastguard Worker alloc_size = (cur_size + size + ALLOC_SZ - 1) & ~(ALLOC_SZ - 1);
645*79398b25SAndroid Build Coastguard Worker
646*79398b25SAndroid Build Coastguard Worker expr_msg = realloc(expr_msg, alloc_size);
647*79398b25SAndroid Build Coastguard Worker if(expr_msg == NULL)
648*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
649*79398b25SAndroid Build Coastguard Worker }
650*79398b25SAndroid Build Coastguard Worker
651*79398b25SAndroid Build Coastguard Worker memcpy(expr_msg + cur_size, string, size);
652*79398b25SAndroid Build Coastguard Worker cur_size += size;
653*79398b25SAndroid Build Coastguard Worker
654*79398b25SAndroid Build Coastguard Worker return expr_msg;
655*79398b25SAndroid Build Coastguard Worker }
656*79398b25SAndroid Build Coastguard Worker
657*79398b25SAndroid Build Coastguard Worker
expr_log_cmnd(int cmnd)658*79398b25SAndroid Build Coastguard Worker char *expr_log_cmnd(int cmnd)
659*79398b25SAndroid Build Coastguard Worker {
660*79398b25SAndroid Build Coastguard Worker return _expr_log(NULL, cmnd);
661*79398b25SAndroid Build Coastguard Worker }
662*79398b25SAndroid Build Coastguard Worker
663*79398b25SAndroid Build Coastguard Worker
expr_log(char * string)664*79398b25SAndroid Build Coastguard Worker char *expr_log(char *string)
665*79398b25SAndroid Build Coastguard Worker {
666*79398b25SAndroid Build Coastguard Worker return _expr_log(string, LOG_PRINT);
667*79398b25SAndroid Build Coastguard Worker }
668*79398b25SAndroid Build Coastguard Worker
669*79398b25SAndroid Build Coastguard Worker
expr_log_atom(struct atom * atom)670*79398b25SAndroid Build Coastguard Worker void expr_log_atom(struct atom *atom)
671*79398b25SAndroid Build Coastguard Worker {
672*79398b25SAndroid Build Coastguard Worker int i;
673*79398b25SAndroid Build Coastguard Worker
674*79398b25SAndroid Build Coastguard Worker if(atom->test->handle_logging)
675*79398b25SAndroid Build Coastguard Worker return;
676*79398b25SAndroid Build Coastguard Worker
677*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
678*79398b25SAndroid Build Coastguard Worker
679*79398b25SAndroid Build Coastguard Worker if(atom->args) {
680*79398b25SAndroid Build Coastguard Worker expr_log("(");
681*79398b25SAndroid Build Coastguard Worker for(i = 0; i < atom->args; i++) {
682*79398b25SAndroid Build Coastguard Worker expr_log(atom->argv[i]);
683*79398b25SAndroid Build Coastguard Worker if (i + 1 < atom->args)
684*79398b25SAndroid Build Coastguard Worker expr_log(",");
685*79398b25SAndroid Build Coastguard Worker }
686*79398b25SAndroid Build Coastguard Worker expr_log(")");
687*79398b25SAndroid Build Coastguard Worker }
688*79398b25SAndroid Build Coastguard Worker }
689*79398b25SAndroid Build Coastguard Worker
690*79398b25SAndroid Build Coastguard Worker
expr_log_match(int match)691*79398b25SAndroid Build Coastguard Worker void expr_log_match(int match)
692*79398b25SAndroid Build Coastguard Worker {
693*79398b25SAndroid Build Coastguard Worker if(match)
694*79398b25SAndroid Build Coastguard Worker expr_log("=True");
695*79398b25SAndroid Build Coastguard Worker else
696*79398b25SAndroid Build Coastguard Worker expr_log("=False");
697*79398b25SAndroid Build Coastguard Worker }
698*79398b25SAndroid Build Coastguard Worker
699*79398b25SAndroid Build Coastguard Worker
eval_expr_log(struct expr * expr,struct action_data * action_data)700*79398b25SAndroid Build Coastguard Worker static int eval_expr_log(struct expr *expr, struct action_data *action_data)
701*79398b25SAndroid Build Coastguard Worker {
702*79398b25SAndroid Build Coastguard Worker int match;
703*79398b25SAndroid Build Coastguard Worker
704*79398b25SAndroid Build Coastguard Worker switch (expr->type) {
705*79398b25SAndroid Build Coastguard Worker case ATOM_TYPE:
706*79398b25SAndroid Build Coastguard Worker expr_log_atom(&expr->atom);
707*79398b25SAndroid Build Coastguard Worker match = expr->atom.test->fn(&expr->atom, action_data);
708*79398b25SAndroid Build Coastguard Worker expr_log_match(match);
709*79398b25SAndroid Build Coastguard Worker break;
710*79398b25SAndroid Build Coastguard Worker case UNARY_TYPE:
711*79398b25SAndroid Build Coastguard Worker expr_log("!");
712*79398b25SAndroid Build Coastguard Worker match = !eval_expr_log(expr->unary_op.expr, action_data);
713*79398b25SAndroid Build Coastguard Worker break;
714*79398b25SAndroid Build Coastguard Worker default:
715*79398b25SAndroid Build Coastguard Worker expr_log("(");
716*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(expr->expr_op.lhs, action_data);
717*79398b25SAndroid Build Coastguard Worker
718*79398b25SAndroid Build Coastguard Worker if ((expr->expr_op.op == TOK_AND && match) ||
719*79398b25SAndroid Build Coastguard Worker (expr->expr_op.op == TOK_OR && !match)) {
720*79398b25SAndroid Build Coastguard Worker expr_log(token_table[expr->expr_op.op].string);
721*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(expr->expr_op.rhs, action_data);
722*79398b25SAndroid Build Coastguard Worker }
723*79398b25SAndroid Build Coastguard Worker expr_log(")");
724*79398b25SAndroid Build Coastguard Worker break;
725*79398b25SAndroid Build Coastguard Worker }
726*79398b25SAndroid Build Coastguard Worker
727*79398b25SAndroid Build Coastguard Worker return match;
728*79398b25SAndroid Build Coastguard Worker }
729*79398b25SAndroid Build Coastguard Worker
730*79398b25SAndroid Build Coastguard Worker
eval_expr(struct expr * expr,struct action_data * action_data)731*79398b25SAndroid Build Coastguard Worker static int eval_expr(struct expr *expr, struct action_data *action_data)
732*79398b25SAndroid Build Coastguard Worker {
733*79398b25SAndroid Build Coastguard Worker int match;
734*79398b25SAndroid Build Coastguard Worker
735*79398b25SAndroid Build Coastguard Worker switch (expr->type) {
736*79398b25SAndroid Build Coastguard Worker case ATOM_TYPE:
737*79398b25SAndroid Build Coastguard Worker match = expr->atom.test->fn(&expr->atom, action_data);
738*79398b25SAndroid Build Coastguard Worker break;
739*79398b25SAndroid Build Coastguard Worker case UNARY_TYPE:
740*79398b25SAndroid Build Coastguard Worker match = !eval_expr(expr->unary_op.expr, action_data);
741*79398b25SAndroid Build Coastguard Worker break;
742*79398b25SAndroid Build Coastguard Worker default:
743*79398b25SAndroid Build Coastguard Worker match = eval_expr(expr->expr_op.lhs, action_data);
744*79398b25SAndroid Build Coastguard Worker
745*79398b25SAndroid Build Coastguard Worker if ((expr->expr_op.op == TOK_AND && match) ||
746*79398b25SAndroid Build Coastguard Worker (expr->expr_op.op == TOK_OR && !match))
747*79398b25SAndroid Build Coastguard Worker match = eval_expr(expr->expr_op.rhs, action_data);
748*79398b25SAndroid Build Coastguard Worker break;
749*79398b25SAndroid Build Coastguard Worker }
750*79398b25SAndroid Build Coastguard Worker
751*79398b25SAndroid Build Coastguard Worker return match;
752*79398b25SAndroid Build Coastguard Worker }
753*79398b25SAndroid Build Coastguard Worker
754*79398b25SAndroid Build Coastguard Worker
eval_expr_top(struct action * action,struct action_data * action_data)755*79398b25SAndroid Build Coastguard Worker static int eval_expr_top(struct action *action, struct action_data *action_data)
756*79398b25SAndroid Build Coastguard Worker {
757*79398b25SAndroid Build Coastguard Worker if(action->verbose) {
758*79398b25SAndroid Build Coastguard Worker int match, n;
759*79398b25SAndroid Build Coastguard Worker
760*79398b25SAndroid Build Coastguard Worker expr_log_cmnd(LOG_ENABLE);
761*79398b25SAndroid Build Coastguard Worker
762*79398b25SAndroid Build Coastguard Worker if(action_data->subpath)
763*79398b25SAndroid Build Coastguard Worker expr_log(action_data->subpath);
764*79398b25SAndroid Build Coastguard Worker
765*79398b25SAndroid Build Coastguard Worker expr_log("=");
766*79398b25SAndroid Build Coastguard Worker expr_log(action->action->name);
767*79398b25SAndroid Build Coastguard Worker
768*79398b25SAndroid Build Coastguard Worker if(action->args) {
769*79398b25SAndroid Build Coastguard Worker expr_log("(");
770*79398b25SAndroid Build Coastguard Worker for (n = 0; n < action->args; n++) {
771*79398b25SAndroid Build Coastguard Worker expr_log(action->argv[n]);
772*79398b25SAndroid Build Coastguard Worker if(n + 1 < action->args)
773*79398b25SAndroid Build Coastguard Worker expr_log(",");
774*79398b25SAndroid Build Coastguard Worker }
775*79398b25SAndroid Build Coastguard Worker expr_log(")");
776*79398b25SAndroid Build Coastguard Worker }
777*79398b25SAndroid Build Coastguard Worker
778*79398b25SAndroid Build Coastguard Worker expr_log("@");
779*79398b25SAndroid Build Coastguard Worker
780*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(action->expr, action_data);
781*79398b25SAndroid Build Coastguard Worker
782*79398b25SAndroid Build Coastguard Worker /*
783*79398b25SAndroid Build Coastguard Worker * Print the evaluated expression log, if the
784*79398b25SAndroid Build Coastguard Worker * result matches the logging specified
785*79398b25SAndroid Build Coastguard Worker */
786*79398b25SAndroid Build Coastguard Worker if((match && (action->verbose & ACTION_LOG_TRUE)) || (!match
787*79398b25SAndroid Build Coastguard Worker && (action->verbose & ACTION_LOG_FALSE)))
788*79398b25SAndroid Build Coastguard Worker progressbar_info("%s\n", expr_log(""));
789*79398b25SAndroid Build Coastguard Worker
790*79398b25SAndroid Build Coastguard Worker expr_log_cmnd(LOG_DISABLE);
791*79398b25SAndroid Build Coastguard Worker
792*79398b25SAndroid Build Coastguard Worker return match;
793*79398b25SAndroid Build Coastguard Worker } else
794*79398b25SAndroid Build Coastguard Worker return eval_expr(action->expr, action_data);
795*79398b25SAndroid Build Coastguard Worker }
796*79398b25SAndroid Build Coastguard Worker
797*79398b25SAndroid Build Coastguard Worker
798*79398b25SAndroid Build Coastguard Worker /*
799*79398b25SAndroid Build Coastguard Worker * Read action file, passing each line to parse_action() for
800*79398b25SAndroid Build Coastguard Worker * parsing.
801*79398b25SAndroid Build Coastguard Worker *
802*79398b25SAndroid Build Coastguard Worker * One action per line, of the form
803*79398b25SAndroid Build Coastguard Worker * action(arg1,arg2)@expr(arg1,arg2)....
804*79398b25SAndroid Build Coastguard Worker *
805*79398b25SAndroid Build Coastguard Worker * Actions can be split across multiple lines using "\".
806*79398b25SAndroid Build Coastguard Worker *
807*79398b25SAndroid Build Coastguard Worker * Blank lines and comment lines indicated by # are supported.
808*79398b25SAndroid Build Coastguard Worker */
parse_action_true(char * s)809*79398b25SAndroid Build Coastguard Worker int parse_action_true(char *s)
810*79398b25SAndroid Build Coastguard Worker {
811*79398b25SAndroid Build Coastguard Worker return parse_action(s, ACTION_LOG_TRUE);
812*79398b25SAndroid Build Coastguard Worker }
813*79398b25SAndroid Build Coastguard Worker
814*79398b25SAndroid Build Coastguard Worker
parse_action_false(char * s)815*79398b25SAndroid Build Coastguard Worker int parse_action_false(char *s)
816*79398b25SAndroid Build Coastguard Worker {
817*79398b25SAndroid Build Coastguard Worker return parse_action(s, ACTION_LOG_FALSE);
818*79398b25SAndroid Build Coastguard Worker }
819*79398b25SAndroid Build Coastguard Worker
820*79398b25SAndroid Build Coastguard Worker
parse_action_verbose(char * s)821*79398b25SAndroid Build Coastguard Worker int parse_action_verbose(char *s)
822*79398b25SAndroid Build Coastguard Worker {
823*79398b25SAndroid Build Coastguard Worker return parse_action(s, ACTION_LOG_VERBOSE);
824*79398b25SAndroid Build Coastguard Worker }
825*79398b25SAndroid Build Coastguard Worker
826*79398b25SAndroid Build Coastguard Worker
parse_action_nonverbose(char * s)827*79398b25SAndroid Build Coastguard Worker int parse_action_nonverbose(char *s)
828*79398b25SAndroid Build Coastguard Worker {
829*79398b25SAndroid Build Coastguard Worker return parse_action(s, ACTION_LOG_NONE);
830*79398b25SAndroid Build Coastguard Worker }
831*79398b25SAndroid Build Coastguard Worker
832*79398b25SAndroid Build Coastguard Worker
read_action_file(char * filename,int verbose)833*79398b25SAndroid Build Coastguard Worker int read_action_file(char *filename, int verbose)
834*79398b25SAndroid Build Coastguard Worker {
835*79398b25SAndroid Build Coastguard Worker switch(verbose) {
836*79398b25SAndroid Build Coastguard Worker case ACTION_LOG_TRUE:
837*79398b25SAndroid Build Coastguard Worker return read_file(filename, "action", parse_action_true);
838*79398b25SAndroid Build Coastguard Worker case ACTION_LOG_FALSE:
839*79398b25SAndroid Build Coastguard Worker return read_file(filename, "action", parse_action_false);
840*79398b25SAndroid Build Coastguard Worker case ACTION_LOG_VERBOSE:
841*79398b25SAndroid Build Coastguard Worker return read_file(filename, "action", parse_action_verbose);
842*79398b25SAndroid Build Coastguard Worker default:
843*79398b25SAndroid Build Coastguard Worker return read_file(filename, "action", parse_action_nonverbose);
844*79398b25SAndroid Build Coastguard Worker }
845*79398b25SAndroid Build Coastguard Worker }
846*79398b25SAndroid Build Coastguard Worker
847*79398b25SAndroid Build Coastguard Worker
848*79398b25SAndroid Build Coastguard Worker /*
849*79398b25SAndroid Build Coastguard Worker * helper to evaluate whether action/test acts on this file type
850*79398b25SAndroid Build Coastguard Worker */
file_type_match(int st_mode,int type)851*79398b25SAndroid Build Coastguard Worker static int file_type_match(int st_mode, int type)
852*79398b25SAndroid Build Coastguard Worker {
853*79398b25SAndroid Build Coastguard Worker switch(type) {
854*79398b25SAndroid Build Coastguard Worker case ACTION_DIR:
855*79398b25SAndroid Build Coastguard Worker return S_ISDIR(st_mode);
856*79398b25SAndroid Build Coastguard Worker case ACTION_REG:
857*79398b25SAndroid Build Coastguard Worker return S_ISREG(st_mode);
858*79398b25SAndroid Build Coastguard Worker case ACTION_ALL:
859*79398b25SAndroid Build Coastguard Worker return S_ISREG(st_mode) || S_ISDIR(st_mode) ||
860*79398b25SAndroid Build Coastguard Worker S_ISCHR(st_mode) || S_ISBLK(st_mode) ||
861*79398b25SAndroid Build Coastguard Worker S_ISFIFO(st_mode) || S_ISSOCK(st_mode);
862*79398b25SAndroid Build Coastguard Worker case ACTION_LNK:
863*79398b25SAndroid Build Coastguard Worker return S_ISLNK(st_mode);
864*79398b25SAndroid Build Coastguard Worker case ACTION_ALL_LNK:
865*79398b25SAndroid Build Coastguard Worker default:
866*79398b25SAndroid Build Coastguard Worker return 1;
867*79398b25SAndroid Build Coastguard Worker }
868*79398b25SAndroid Build Coastguard Worker }
869*79398b25SAndroid Build Coastguard Worker
870*79398b25SAndroid Build Coastguard Worker
871*79398b25SAndroid Build Coastguard Worker /*
872*79398b25SAndroid Build Coastguard Worker * General action evaluation code
873*79398b25SAndroid Build Coastguard Worker */
actions()874*79398b25SAndroid Build Coastguard Worker int actions()
875*79398b25SAndroid Build Coastguard Worker {
876*79398b25SAndroid Build Coastguard Worker return other_count;
877*79398b25SAndroid Build Coastguard Worker }
878*79398b25SAndroid Build Coastguard Worker
879*79398b25SAndroid Build Coastguard Worker
eval_actions(struct dir_info * root,struct dir_ent * dir_ent)880*79398b25SAndroid Build Coastguard Worker void eval_actions(struct dir_info *root, struct dir_ent *dir_ent)
881*79398b25SAndroid Build Coastguard Worker {
882*79398b25SAndroid Build Coastguard Worker int i, match;
883*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
884*79398b25SAndroid Build Coastguard Worker int st_mode = dir_ent->inode->buf.st_mode;
885*79398b25SAndroid Build Coastguard Worker
886*79398b25SAndroid Build Coastguard Worker action_data.name = dir_ent->name;
887*79398b25SAndroid Build Coastguard Worker action_data.pathname = strdup(pathname(dir_ent));
888*79398b25SAndroid Build Coastguard Worker action_data.subpath = strdup(subpathname(dir_ent));
889*79398b25SAndroid Build Coastguard Worker action_data.buf = &dir_ent->inode->buf;
890*79398b25SAndroid Build Coastguard Worker action_data.depth = dir_ent->our_dir->depth;
891*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
892*79398b25SAndroid Build Coastguard Worker action_data.root = root;
893*79398b25SAndroid Build Coastguard Worker
894*79398b25SAndroid Build Coastguard Worker for (i = 0; i < other_count; i++) {
895*79398b25SAndroid Build Coastguard Worker struct action *action = &other_spec[i];
896*79398b25SAndroid Build Coastguard Worker
897*79398b25SAndroid Build Coastguard Worker if (!file_type_match(st_mode, action->action->file_types))
898*79398b25SAndroid Build Coastguard Worker /* action does not operate on this file type */
899*79398b25SAndroid Build Coastguard Worker continue;
900*79398b25SAndroid Build Coastguard Worker
901*79398b25SAndroid Build Coastguard Worker match = eval_expr_top(action, &action_data);
902*79398b25SAndroid Build Coastguard Worker
903*79398b25SAndroid Build Coastguard Worker if (match)
904*79398b25SAndroid Build Coastguard Worker action->action->run_action(action, dir_ent);
905*79398b25SAndroid Build Coastguard Worker }
906*79398b25SAndroid Build Coastguard Worker
907*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
908*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
909*79398b25SAndroid Build Coastguard Worker }
910*79398b25SAndroid Build Coastguard Worker
911*79398b25SAndroid Build Coastguard Worker
912*79398b25SAndroid Build Coastguard Worker /*
913*79398b25SAndroid Build Coastguard Worker * Fragment specific action code
914*79398b25SAndroid Build Coastguard Worker */
eval_frag_actions(struct dir_info * root,struct dir_ent * dir_ent)915*79398b25SAndroid Build Coastguard Worker void *eval_frag_actions(struct dir_info *root, struct dir_ent *dir_ent)
916*79398b25SAndroid Build Coastguard Worker {
917*79398b25SAndroid Build Coastguard Worker int i, match;
918*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
919*79398b25SAndroid Build Coastguard Worker
920*79398b25SAndroid Build Coastguard Worker action_data.name = dir_ent->name;
921*79398b25SAndroid Build Coastguard Worker action_data.pathname = strdup(pathname(dir_ent));
922*79398b25SAndroid Build Coastguard Worker action_data.subpath = strdup(subpathname(dir_ent));
923*79398b25SAndroid Build Coastguard Worker action_data.buf = &dir_ent->inode->buf;
924*79398b25SAndroid Build Coastguard Worker action_data.depth = dir_ent->our_dir->depth;
925*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
926*79398b25SAndroid Build Coastguard Worker action_data.root = root;
927*79398b25SAndroid Build Coastguard Worker
928*79398b25SAndroid Build Coastguard Worker for (i = 0; i < fragment_count; i++) {
929*79398b25SAndroid Build Coastguard Worker match = eval_expr_top(&fragment_spec[i], &action_data);
930*79398b25SAndroid Build Coastguard Worker if (match) {
931*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
932*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
933*79398b25SAndroid Build Coastguard Worker return &fragment_spec[i].data;
934*79398b25SAndroid Build Coastguard Worker }
935*79398b25SAndroid Build Coastguard Worker }
936*79398b25SAndroid Build Coastguard Worker
937*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
938*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
939*79398b25SAndroid Build Coastguard Worker return &def_fragment;
940*79398b25SAndroid Build Coastguard Worker }
941*79398b25SAndroid Build Coastguard Worker
942*79398b25SAndroid Build Coastguard Worker
get_frag_action(void * fragment)943*79398b25SAndroid Build Coastguard Worker void *get_frag_action(void *fragment)
944*79398b25SAndroid Build Coastguard Worker {
945*79398b25SAndroid Build Coastguard Worker struct action *spec_list_end = &fragment_spec[fragment_count];
946*79398b25SAndroid Build Coastguard Worker struct action *action;
947*79398b25SAndroid Build Coastguard Worker
948*79398b25SAndroid Build Coastguard Worker if (fragment == NULL)
949*79398b25SAndroid Build Coastguard Worker return &def_fragment;
950*79398b25SAndroid Build Coastguard Worker
951*79398b25SAndroid Build Coastguard Worker if (fragment_count == 0)
952*79398b25SAndroid Build Coastguard Worker return NULL;
953*79398b25SAndroid Build Coastguard Worker
954*79398b25SAndroid Build Coastguard Worker if (fragment == &def_fragment)
955*79398b25SAndroid Build Coastguard Worker action = &fragment_spec[0] - 1;
956*79398b25SAndroid Build Coastguard Worker else
957*79398b25SAndroid Build Coastguard Worker action = fragment - offsetof(struct action, data);
958*79398b25SAndroid Build Coastguard Worker
959*79398b25SAndroid Build Coastguard Worker if (++action == spec_list_end)
960*79398b25SAndroid Build Coastguard Worker return NULL;
961*79398b25SAndroid Build Coastguard Worker
962*79398b25SAndroid Build Coastguard Worker return &action->data;
963*79398b25SAndroid Build Coastguard Worker }
964*79398b25SAndroid Build Coastguard Worker
965*79398b25SAndroid Build Coastguard Worker
966*79398b25SAndroid Build Coastguard Worker /*
967*79398b25SAndroid Build Coastguard Worker * Exclude specific action code
968*79398b25SAndroid Build Coastguard Worker */
exclude_actions()969*79398b25SAndroid Build Coastguard Worker int exclude_actions()
970*79398b25SAndroid Build Coastguard Worker {
971*79398b25SAndroid Build Coastguard Worker return exclude_count;
972*79398b25SAndroid Build Coastguard Worker }
973*79398b25SAndroid Build Coastguard Worker
974*79398b25SAndroid Build Coastguard Worker
eval_exclude_actions(char * name,char * pathname,char * subpath,struct stat * buf,int depth,struct dir_ent * dir_ent)975*79398b25SAndroid Build Coastguard Worker int eval_exclude_actions(char *name, char *pathname, char *subpath,
976*79398b25SAndroid Build Coastguard Worker struct stat *buf, int depth, struct dir_ent *dir_ent)
977*79398b25SAndroid Build Coastguard Worker {
978*79398b25SAndroid Build Coastguard Worker int i, match = 0;
979*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
980*79398b25SAndroid Build Coastguard Worker
981*79398b25SAndroid Build Coastguard Worker action_data.name = name;
982*79398b25SAndroid Build Coastguard Worker action_data.pathname = pathname;
983*79398b25SAndroid Build Coastguard Worker action_data.subpath = subpath;
984*79398b25SAndroid Build Coastguard Worker action_data.buf = buf;
985*79398b25SAndroid Build Coastguard Worker action_data.depth = depth;
986*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
987*79398b25SAndroid Build Coastguard Worker
988*79398b25SAndroid Build Coastguard Worker for (i = 0; i < exclude_count && !match; i++)
989*79398b25SAndroid Build Coastguard Worker match = eval_expr_top(&exclude_spec[i], &action_data);
990*79398b25SAndroid Build Coastguard Worker
991*79398b25SAndroid Build Coastguard Worker return match;
992*79398b25SAndroid Build Coastguard Worker }
993*79398b25SAndroid Build Coastguard Worker
994*79398b25SAndroid Build Coastguard Worker
995*79398b25SAndroid Build Coastguard Worker /*
996*79398b25SAndroid Build Coastguard Worker * Fragment specific action code
997*79398b25SAndroid Build Coastguard Worker */
frag_action(struct action * action,struct dir_ent * dir_ent)998*79398b25SAndroid Build Coastguard Worker static void frag_action(struct action *action, struct dir_ent *dir_ent)
999*79398b25SAndroid Build Coastguard Worker {
1000*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1001*79398b25SAndroid Build Coastguard Worker
1002*79398b25SAndroid Build Coastguard Worker inode->no_fragments = 0;
1003*79398b25SAndroid Build Coastguard Worker }
1004*79398b25SAndroid Build Coastguard Worker
no_frag_action(struct action * action,struct dir_ent * dir_ent)1005*79398b25SAndroid Build Coastguard Worker static void no_frag_action(struct action *action, struct dir_ent *dir_ent)
1006*79398b25SAndroid Build Coastguard Worker {
1007*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1008*79398b25SAndroid Build Coastguard Worker
1009*79398b25SAndroid Build Coastguard Worker inode->no_fragments = 1;
1010*79398b25SAndroid Build Coastguard Worker }
1011*79398b25SAndroid Build Coastguard Worker
always_frag_action(struct action * action,struct dir_ent * dir_ent)1012*79398b25SAndroid Build Coastguard Worker static void always_frag_action(struct action *action, struct dir_ent *dir_ent)
1013*79398b25SAndroid Build Coastguard Worker {
1014*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1015*79398b25SAndroid Build Coastguard Worker
1016*79398b25SAndroid Build Coastguard Worker inode->always_use_fragments = 1;
1017*79398b25SAndroid Build Coastguard Worker }
1018*79398b25SAndroid Build Coastguard Worker
no_always_frag_action(struct action * action,struct dir_ent * dir_ent)1019*79398b25SAndroid Build Coastguard Worker static void no_always_frag_action(struct action *action, struct dir_ent *dir_ent)
1020*79398b25SAndroid Build Coastguard Worker {
1021*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1022*79398b25SAndroid Build Coastguard Worker
1023*79398b25SAndroid Build Coastguard Worker inode->always_use_fragments = 0;
1024*79398b25SAndroid Build Coastguard Worker }
1025*79398b25SAndroid Build Coastguard Worker
1026*79398b25SAndroid Build Coastguard Worker
1027*79398b25SAndroid Build Coastguard Worker /*
1028*79398b25SAndroid Build Coastguard Worker * Compression specific action code
1029*79398b25SAndroid Build Coastguard Worker */
comp_action(struct action * action,struct dir_ent * dir_ent)1030*79398b25SAndroid Build Coastguard Worker static void comp_action(struct action *action, struct dir_ent *dir_ent)
1031*79398b25SAndroid Build Coastguard Worker {
1032*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1033*79398b25SAndroid Build Coastguard Worker
1034*79398b25SAndroid Build Coastguard Worker inode->noD = inode->noF = 0;
1035*79398b25SAndroid Build Coastguard Worker }
1036*79398b25SAndroid Build Coastguard Worker
uncomp_action(struct action * action,struct dir_ent * dir_ent)1037*79398b25SAndroid Build Coastguard Worker static void uncomp_action(struct action *action, struct dir_ent *dir_ent)
1038*79398b25SAndroid Build Coastguard Worker {
1039*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1040*79398b25SAndroid Build Coastguard Worker
1041*79398b25SAndroid Build Coastguard Worker inode->noD = inode->noF = 1;
1042*79398b25SAndroid Build Coastguard Worker }
1043*79398b25SAndroid Build Coastguard Worker
1044*79398b25SAndroid Build Coastguard Worker
1045*79398b25SAndroid Build Coastguard Worker /*
1046*79398b25SAndroid Build Coastguard Worker * Uid/gid specific action code
1047*79398b25SAndroid Build Coastguard Worker */
parse_uid(char * arg)1048*79398b25SAndroid Build Coastguard Worker static long long parse_uid(char *arg) {
1049*79398b25SAndroid Build Coastguard Worker char *b;
1050*79398b25SAndroid Build Coastguard Worker long long uid = strtoll(arg, &b, 10);
1051*79398b25SAndroid Build Coastguard Worker
1052*79398b25SAndroid Build Coastguard Worker if (*b == '\0') {
1053*79398b25SAndroid Build Coastguard Worker if (uid < 0 || uid >= (1LL << 32)) {
1054*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Uid out of range\n");
1055*79398b25SAndroid Build Coastguard Worker return -1;
1056*79398b25SAndroid Build Coastguard Worker }
1057*79398b25SAndroid Build Coastguard Worker } else {
1058*79398b25SAndroid Build Coastguard Worker struct passwd *passwd = getpwnam(arg);
1059*79398b25SAndroid Build Coastguard Worker
1060*79398b25SAndroid Build Coastguard Worker if (passwd)
1061*79398b25SAndroid Build Coastguard Worker uid = passwd->pw_uid;
1062*79398b25SAndroid Build Coastguard Worker else {
1063*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Invalid uid or unknown user\n");
1064*79398b25SAndroid Build Coastguard Worker return -1;
1065*79398b25SAndroid Build Coastguard Worker }
1066*79398b25SAndroid Build Coastguard Worker }
1067*79398b25SAndroid Build Coastguard Worker
1068*79398b25SAndroid Build Coastguard Worker return uid;
1069*79398b25SAndroid Build Coastguard Worker }
1070*79398b25SAndroid Build Coastguard Worker
1071*79398b25SAndroid Build Coastguard Worker
parse_gid(char * arg)1072*79398b25SAndroid Build Coastguard Worker static long long parse_gid(char *arg) {
1073*79398b25SAndroid Build Coastguard Worker char *b;
1074*79398b25SAndroid Build Coastguard Worker long long gid = strtoll(arg, &b, 10);
1075*79398b25SAndroid Build Coastguard Worker
1076*79398b25SAndroid Build Coastguard Worker if (*b == '\0') {
1077*79398b25SAndroid Build Coastguard Worker if (gid < 0 || gid >= (1LL << 32)) {
1078*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Gid out of range\n");
1079*79398b25SAndroid Build Coastguard Worker return -1;
1080*79398b25SAndroid Build Coastguard Worker }
1081*79398b25SAndroid Build Coastguard Worker } else {
1082*79398b25SAndroid Build Coastguard Worker struct group *group = getgrnam(arg);
1083*79398b25SAndroid Build Coastguard Worker
1084*79398b25SAndroid Build Coastguard Worker if (group)
1085*79398b25SAndroid Build Coastguard Worker gid = group->gr_gid;
1086*79398b25SAndroid Build Coastguard Worker else {
1087*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Invalid gid or unknown group\n");
1088*79398b25SAndroid Build Coastguard Worker return -1;
1089*79398b25SAndroid Build Coastguard Worker }
1090*79398b25SAndroid Build Coastguard Worker }
1091*79398b25SAndroid Build Coastguard Worker
1092*79398b25SAndroid Build Coastguard Worker return gid;
1093*79398b25SAndroid Build Coastguard Worker }
1094*79398b25SAndroid Build Coastguard Worker
1095*79398b25SAndroid Build Coastguard Worker
parse_uid_args(struct action_entry * action,int args,char ** argv,void ** data)1096*79398b25SAndroid Build Coastguard Worker static int parse_uid_args(struct action_entry *action, int args, char **argv,
1097*79398b25SAndroid Build Coastguard Worker void **data)
1098*79398b25SAndroid Build Coastguard Worker {
1099*79398b25SAndroid Build Coastguard Worker long long uid;
1100*79398b25SAndroid Build Coastguard Worker struct uid_info *uid_info;
1101*79398b25SAndroid Build Coastguard Worker
1102*79398b25SAndroid Build Coastguard Worker uid = parse_uid(argv[0]);
1103*79398b25SAndroid Build Coastguard Worker if (uid == -1)
1104*79398b25SAndroid Build Coastguard Worker return 0;
1105*79398b25SAndroid Build Coastguard Worker
1106*79398b25SAndroid Build Coastguard Worker uid_info = malloc(sizeof(struct uid_info));
1107*79398b25SAndroid Build Coastguard Worker if (uid_info == NULL)
1108*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1109*79398b25SAndroid Build Coastguard Worker
1110*79398b25SAndroid Build Coastguard Worker uid_info->uid = uid;
1111*79398b25SAndroid Build Coastguard Worker *data = uid_info;
1112*79398b25SAndroid Build Coastguard Worker
1113*79398b25SAndroid Build Coastguard Worker return 1;
1114*79398b25SAndroid Build Coastguard Worker }
1115*79398b25SAndroid Build Coastguard Worker
1116*79398b25SAndroid Build Coastguard Worker
parse_gid_args(struct action_entry * action,int args,char ** argv,void ** data)1117*79398b25SAndroid Build Coastguard Worker static int parse_gid_args(struct action_entry *action, int args, char **argv,
1118*79398b25SAndroid Build Coastguard Worker void **data)
1119*79398b25SAndroid Build Coastguard Worker {
1120*79398b25SAndroid Build Coastguard Worker long long gid;
1121*79398b25SAndroid Build Coastguard Worker struct gid_info *gid_info;
1122*79398b25SAndroid Build Coastguard Worker
1123*79398b25SAndroid Build Coastguard Worker gid = parse_gid(argv[0]);
1124*79398b25SAndroid Build Coastguard Worker if (gid == -1)
1125*79398b25SAndroid Build Coastguard Worker return 0;
1126*79398b25SAndroid Build Coastguard Worker
1127*79398b25SAndroid Build Coastguard Worker gid_info = malloc(sizeof(struct gid_info));
1128*79398b25SAndroid Build Coastguard Worker if (gid_info == NULL)
1129*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1130*79398b25SAndroid Build Coastguard Worker
1131*79398b25SAndroid Build Coastguard Worker gid_info->gid = gid;
1132*79398b25SAndroid Build Coastguard Worker *data = gid_info;
1133*79398b25SAndroid Build Coastguard Worker
1134*79398b25SAndroid Build Coastguard Worker return 1;
1135*79398b25SAndroid Build Coastguard Worker }
1136*79398b25SAndroid Build Coastguard Worker
1137*79398b25SAndroid Build Coastguard Worker
parse_guid_args(struct action_entry * action,int args,char ** argv,void ** data)1138*79398b25SAndroid Build Coastguard Worker static int parse_guid_args(struct action_entry *action, int args, char **argv,
1139*79398b25SAndroid Build Coastguard Worker void **data)
1140*79398b25SAndroid Build Coastguard Worker {
1141*79398b25SAndroid Build Coastguard Worker long long uid, gid;
1142*79398b25SAndroid Build Coastguard Worker struct guid_info *guid_info;
1143*79398b25SAndroid Build Coastguard Worker
1144*79398b25SAndroid Build Coastguard Worker uid = parse_uid(argv[0]);
1145*79398b25SAndroid Build Coastguard Worker if (uid == -1)
1146*79398b25SAndroid Build Coastguard Worker return 0;
1147*79398b25SAndroid Build Coastguard Worker
1148*79398b25SAndroid Build Coastguard Worker gid = parse_gid(argv[1]);
1149*79398b25SAndroid Build Coastguard Worker if (gid == -1)
1150*79398b25SAndroid Build Coastguard Worker return 0;
1151*79398b25SAndroid Build Coastguard Worker
1152*79398b25SAndroid Build Coastguard Worker guid_info = malloc(sizeof(struct guid_info));
1153*79398b25SAndroid Build Coastguard Worker if (guid_info == NULL)
1154*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1155*79398b25SAndroid Build Coastguard Worker
1156*79398b25SAndroid Build Coastguard Worker guid_info->uid = uid;
1157*79398b25SAndroid Build Coastguard Worker guid_info->gid = gid;
1158*79398b25SAndroid Build Coastguard Worker *data = guid_info;
1159*79398b25SAndroid Build Coastguard Worker
1160*79398b25SAndroid Build Coastguard Worker return 1;
1161*79398b25SAndroid Build Coastguard Worker }
1162*79398b25SAndroid Build Coastguard Worker
1163*79398b25SAndroid Build Coastguard Worker
uid_action(struct action * action,struct dir_ent * dir_ent)1164*79398b25SAndroid Build Coastguard Worker static void uid_action(struct action *action, struct dir_ent *dir_ent)
1165*79398b25SAndroid Build Coastguard Worker {
1166*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1167*79398b25SAndroid Build Coastguard Worker struct uid_info *uid_info = action->data;
1168*79398b25SAndroid Build Coastguard Worker
1169*79398b25SAndroid Build Coastguard Worker inode->buf.st_uid = uid_info->uid;
1170*79398b25SAndroid Build Coastguard Worker }
1171*79398b25SAndroid Build Coastguard Worker
gid_action(struct action * action,struct dir_ent * dir_ent)1172*79398b25SAndroid Build Coastguard Worker static void gid_action(struct action *action, struct dir_ent *dir_ent)
1173*79398b25SAndroid Build Coastguard Worker {
1174*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1175*79398b25SAndroid Build Coastguard Worker struct gid_info *gid_info = action->data;
1176*79398b25SAndroid Build Coastguard Worker
1177*79398b25SAndroid Build Coastguard Worker inode->buf.st_gid = gid_info->gid;
1178*79398b25SAndroid Build Coastguard Worker }
1179*79398b25SAndroid Build Coastguard Worker
guid_action(struct action * action,struct dir_ent * dir_ent)1180*79398b25SAndroid Build Coastguard Worker static void guid_action(struct action *action, struct dir_ent *dir_ent)
1181*79398b25SAndroid Build Coastguard Worker {
1182*79398b25SAndroid Build Coastguard Worker struct inode_info *inode = dir_ent->inode;
1183*79398b25SAndroid Build Coastguard Worker struct guid_info *guid_info = action->data;
1184*79398b25SAndroid Build Coastguard Worker
1185*79398b25SAndroid Build Coastguard Worker inode->buf.st_uid = guid_info->uid;
1186*79398b25SAndroid Build Coastguard Worker inode->buf.st_gid = guid_info->gid;
1187*79398b25SAndroid Build Coastguard Worker
1188*79398b25SAndroid Build Coastguard Worker }
1189*79398b25SAndroid Build Coastguard Worker
1190*79398b25SAndroid Build Coastguard Worker
1191*79398b25SAndroid Build Coastguard Worker /*
1192*79398b25SAndroid Build Coastguard Worker * Mode specific action code
1193*79398b25SAndroid Build Coastguard Worker */
parse_octal_mode_args(int args,char ** argv,void ** data)1194*79398b25SAndroid Build Coastguard Worker static int parse_octal_mode_args(int args, char **argv,
1195*79398b25SAndroid Build Coastguard Worker void **data)
1196*79398b25SAndroid Build Coastguard Worker {
1197*79398b25SAndroid Build Coastguard Worker int n, bytes;
1198*79398b25SAndroid Build Coastguard Worker unsigned int mode;
1199*79398b25SAndroid Build Coastguard Worker struct mode_data *mode_data;
1200*79398b25SAndroid Build Coastguard Worker
1201*79398b25SAndroid Build Coastguard Worker /* octal mode number? */
1202*79398b25SAndroid Build Coastguard Worker n = sscanf(argv[0], "%o%n", &mode, &bytes);
1203*79398b25SAndroid Build Coastguard Worker if (n == 0)
1204*79398b25SAndroid Build Coastguard Worker return -1; /* not an octal number arg */
1205*79398b25SAndroid Build Coastguard Worker
1206*79398b25SAndroid Build Coastguard Worker
1207*79398b25SAndroid Build Coastguard Worker /* check there's no trailing junk */
1208*79398b25SAndroid Build Coastguard Worker if (argv[0][bytes] != '\0') {
1209*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unexpected trailing bytes after octal "
1210*79398b25SAndroid Build Coastguard Worker "mode number\n");
1211*79398b25SAndroid Build Coastguard Worker return 0; /* bad octal number arg */
1212*79398b25SAndroid Build Coastguard Worker }
1213*79398b25SAndroid Build Coastguard Worker
1214*79398b25SAndroid Build Coastguard Worker /* check there's only one argument */
1215*79398b25SAndroid Build Coastguard Worker if (args > 1) {
1216*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Octal mode number is first argument, "
1217*79398b25SAndroid Build Coastguard Worker "expected one argument, got %d\n", args);
1218*79398b25SAndroid Build Coastguard Worker return 0; /* bad octal number arg */
1219*79398b25SAndroid Build Coastguard Worker }
1220*79398b25SAndroid Build Coastguard Worker
1221*79398b25SAndroid Build Coastguard Worker /* check mode is within range */
1222*79398b25SAndroid Build Coastguard Worker if (mode > 07777) {
1223*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Octal mode %o is out of range\n", mode);
1224*79398b25SAndroid Build Coastguard Worker return 0; /* bad octal number arg */
1225*79398b25SAndroid Build Coastguard Worker }
1226*79398b25SAndroid Build Coastguard Worker
1227*79398b25SAndroid Build Coastguard Worker mode_data = malloc(sizeof(struct mode_data));
1228*79398b25SAndroid Build Coastguard Worker if (mode_data == NULL)
1229*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1230*79398b25SAndroid Build Coastguard Worker
1231*79398b25SAndroid Build Coastguard Worker mode_data->operation = ACTION_MODE_OCT;
1232*79398b25SAndroid Build Coastguard Worker mode_data->mode = mode;
1233*79398b25SAndroid Build Coastguard Worker mode_data->next = NULL;
1234*79398b25SAndroid Build Coastguard Worker *data = mode_data;
1235*79398b25SAndroid Build Coastguard Worker
1236*79398b25SAndroid Build Coastguard Worker return 1;
1237*79398b25SAndroid Build Coastguard Worker }
1238*79398b25SAndroid Build Coastguard Worker
1239*79398b25SAndroid Build Coastguard Worker
1240*79398b25SAndroid Build Coastguard Worker /*
1241*79398b25SAndroid Build Coastguard Worker * Parse symbolic mode of format [ugoa]*[[+-=]PERMS]+
1242*79398b25SAndroid Build Coastguard Worker * PERMS = [rwxXst]+ or [ugo]
1243*79398b25SAndroid Build Coastguard Worker */
parse_sym_mode_arg(char * arg,struct mode_data ** head,struct mode_data ** cur)1244*79398b25SAndroid Build Coastguard Worker static int parse_sym_mode_arg(char *arg, struct mode_data **head,
1245*79398b25SAndroid Build Coastguard Worker struct mode_data **cur)
1246*79398b25SAndroid Build Coastguard Worker {
1247*79398b25SAndroid Build Coastguard Worker struct mode_data *mode_data;
1248*79398b25SAndroid Build Coastguard Worker int mode;
1249*79398b25SAndroid Build Coastguard Worker int mask = 0;
1250*79398b25SAndroid Build Coastguard Worker int op;
1251*79398b25SAndroid Build Coastguard Worker char X;
1252*79398b25SAndroid Build Coastguard Worker
1253*79398b25SAndroid Build Coastguard Worker if (arg[0] != 'u' && arg[0] != 'g' && arg[0] != 'o' && arg[0] != 'a') {
1254*79398b25SAndroid Build Coastguard Worker /* no ownership specifiers, default to a */
1255*79398b25SAndroid Build Coastguard Worker mask = 0777;
1256*79398b25SAndroid Build Coastguard Worker goto parse_operation;
1257*79398b25SAndroid Build Coastguard Worker }
1258*79398b25SAndroid Build Coastguard Worker
1259*79398b25SAndroid Build Coastguard Worker /* parse ownership specifiers */
1260*79398b25SAndroid Build Coastguard Worker while(1) {
1261*79398b25SAndroid Build Coastguard Worker switch(*arg) {
1262*79398b25SAndroid Build Coastguard Worker case 'u':
1263*79398b25SAndroid Build Coastguard Worker mask |= 04700;
1264*79398b25SAndroid Build Coastguard Worker break;
1265*79398b25SAndroid Build Coastguard Worker case 'g':
1266*79398b25SAndroid Build Coastguard Worker mask |= 02070;
1267*79398b25SAndroid Build Coastguard Worker break;
1268*79398b25SAndroid Build Coastguard Worker case 'o':
1269*79398b25SAndroid Build Coastguard Worker mask |= 01007;
1270*79398b25SAndroid Build Coastguard Worker break;
1271*79398b25SAndroid Build Coastguard Worker case 'a':
1272*79398b25SAndroid Build Coastguard Worker mask = 07777;
1273*79398b25SAndroid Build Coastguard Worker break;
1274*79398b25SAndroid Build Coastguard Worker default:
1275*79398b25SAndroid Build Coastguard Worker goto parse_operation;
1276*79398b25SAndroid Build Coastguard Worker }
1277*79398b25SAndroid Build Coastguard Worker arg ++;
1278*79398b25SAndroid Build Coastguard Worker }
1279*79398b25SAndroid Build Coastguard Worker
1280*79398b25SAndroid Build Coastguard Worker parse_operation:
1281*79398b25SAndroid Build Coastguard Worker /* trap a symbolic mode with just an ownership specification */
1282*79398b25SAndroid Build Coastguard Worker if(*arg == '\0') {
1283*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Expected one of '+', '-' or '=', got EOF\n");
1284*79398b25SAndroid Build Coastguard Worker goto failed;
1285*79398b25SAndroid Build Coastguard Worker }
1286*79398b25SAndroid Build Coastguard Worker
1287*79398b25SAndroid Build Coastguard Worker while(*arg != '\0') {
1288*79398b25SAndroid Build Coastguard Worker mode = 0;
1289*79398b25SAndroid Build Coastguard Worker X = 0;
1290*79398b25SAndroid Build Coastguard Worker
1291*79398b25SAndroid Build Coastguard Worker switch(*arg) {
1292*79398b25SAndroid Build Coastguard Worker case '+':
1293*79398b25SAndroid Build Coastguard Worker op = ACTION_MODE_ADD;
1294*79398b25SAndroid Build Coastguard Worker break;
1295*79398b25SAndroid Build Coastguard Worker case '-':
1296*79398b25SAndroid Build Coastguard Worker op = ACTION_MODE_REM;
1297*79398b25SAndroid Build Coastguard Worker break;
1298*79398b25SAndroid Build Coastguard Worker case '=':
1299*79398b25SAndroid Build Coastguard Worker op = ACTION_MODE_SET;
1300*79398b25SAndroid Build Coastguard Worker break;
1301*79398b25SAndroid Build Coastguard Worker default:
1302*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Expected one of '+', '-' or '=', got "
1303*79398b25SAndroid Build Coastguard Worker "'%c'\n", *arg);
1304*79398b25SAndroid Build Coastguard Worker goto failed;
1305*79398b25SAndroid Build Coastguard Worker }
1306*79398b25SAndroid Build Coastguard Worker
1307*79398b25SAndroid Build Coastguard Worker arg ++;
1308*79398b25SAndroid Build Coastguard Worker
1309*79398b25SAndroid Build Coastguard Worker /* Parse PERMS */
1310*79398b25SAndroid Build Coastguard Worker if (*arg == 'u' || *arg == 'g' || *arg == 'o') {
1311*79398b25SAndroid Build Coastguard Worker /* PERMS = [ugo] */
1312*79398b25SAndroid Build Coastguard Worker mode = - *arg;
1313*79398b25SAndroid Build Coastguard Worker arg ++;
1314*79398b25SAndroid Build Coastguard Worker } else {
1315*79398b25SAndroid Build Coastguard Worker /* PERMS = [rwxXst]* */
1316*79398b25SAndroid Build Coastguard Worker while(1) {
1317*79398b25SAndroid Build Coastguard Worker switch(*arg) {
1318*79398b25SAndroid Build Coastguard Worker case 'r':
1319*79398b25SAndroid Build Coastguard Worker mode |= 0444;
1320*79398b25SAndroid Build Coastguard Worker break;
1321*79398b25SAndroid Build Coastguard Worker case 'w':
1322*79398b25SAndroid Build Coastguard Worker mode |= 0222;
1323*79398b25SAndroid Build Coastguard Worker break;
1324*79398b25SAndroid Build Coastguard Worker case 'x':
1325*79398b25SAndroid Build Coastguard Worker mode |= 0111;
1326*79398b25SAndroid Build Coastguard Worker break;
1327*79398b25SAndroid Build Coastguard Worker case 's':
1328*79398b25SAndroid Build Coastguard Worker mode |= 06000;
1329*79398b25SAndroid Build Coastguard Worker break;
1330*79398b25SAndroid Build Coastguard Worker case 't':
1331*79398b25SAndroid Build Coastguard Worker mode |= 01000;
1332*79398b25SAndroid Build Coastguard Worker break;
1333*79398b25SAndroid Build Coastguard Worker case 'X':
1334*79398b25SAndroid Build Coastguard Worker X = 1;
1335*79398b25SAndroid Build Coastguard Worker break;
1336*79398b25SAndroid Build Coastguard Worker case '+':
1337*79398b25SAndroid Build Coastguard Worker case '-':
1338*79398b25SAndroid Build Coastguard Worker case '=':
1339*79398b25SAndroid Build Coastguard Worker case '\0':
1340*79398b25SAndroid Build Coastguard Worker mode &= mask;
1341*79398b25SAndroid Build Coastguard Worker goto perms_parsed;
1342*79398b25SAndroid Build Coastguard Worker default:
1343*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Unrecognised permission "
1344*79398b25SAndroid Build Coastguard Worker "'%c'\n", *arg);
1345*79398b25SAndroid Build Coastguard Worker goto failed;
1346*79398b25SAndroid Build Coastguard Worker }
1347*79398b25SAndroid Build Coastguard Worker
1348*79398b25SAndroid Build Coastguard Worker arg ++;
1349*79398b25SAndroid Build Coastguard Worker }
1350*79398b25SAndroid Build Coastguard Worker }
1351*79398b25SAndroid Build Coastguard Worker
1352*79398b25SAndroid Build Coastguard Worker perms_parsed:
1353*79398b25SAndroid Build Coastguard Worker mode_data = malloc(sizeof(*mode_data));
1354*79398b25SAndroid Build Coastguard Worker if (mode_data == NULL)
1355*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1356*79398b25SAndroid Build Coastguard Worker
1357*79398b25SAndroid Build Coastguard Worker mode_data->operation = op;
1358*79398b25SAndroid Build Coastguard Worker mode_data->mode = mode;
1359*79398b25SAndroid Build Coastguard Worker mode_data->mask = mask;
1360*79398b25SAndroid Build Coastguard Worker mode_data->X = X;
1361*79398b25SAndroid Build Coastguard Worker mode_data->next = NULL;
1362*79398b25SAndroid Build Coastguard Worker
1363*79398b25SAndroid Build Coastguard Worker if (*cur) {
1364*79398b25SAndroid Build Coastguard Worker (*cur)->next = mode_data;
1365*79398b25SAndroid Build Coastguard Worker *cur = mode_data;
1366*79398b25SAndroid Build Coastguard Worker } else
1367*79398b25SAndroid Build Coastguard Worker *head = *cur = mode_data;
1368*79398b25SAndroid Build Coastguard Worker }
1369*79398b25SAndroid Build Coastguard Worker
1370*79398b25SAndroid Build Coastguard Worker return 1;
1371*79398b25SAndroid Build Coastguard Worker
1372*79398b25SAndroid Build Coastguard Worker failed:
1373*79398b25SAndroid Build Coastguard Worker return 0;
1374*79398b25SAndroid Build Coastguard Worker }
1375*79398b25SAndroid Build Coastguard Worker
1376*79398b25SAndroid Build Coastguard Worker
parse_sym_mode_args(struct action_entry * action,int args,char ** argv,void ** data)1377*79398b25SAndroid Build Coastguard Worker static int parse_sym_mode_args(struct action_entry *action, int args,
1378*79398b25SAndroid Build Coastguard Worker char **argv, void **data)
1379*79398b25SAndroid Build Coastguard Worker {
1380*79398b25SAndroid Build Coastguard Worker int i, res = 1;
1381*79398b25SAndroid Build Coastguard Worker struct mode_data *head = NULL, *cur = NULL;
1382*79398b25SAndroid Build Coastguard Worker
1383*79398b25SAndroid Build Coastguard Worker for (i = 0; i < args && res; i++)
1384*79398b25SAndroid Build Coastguard Worker res = parse_sym_mode_arg(argv[i], &head, &cur);
1385*79398b25SAndroid Build Coastguard Worker
1386*79398b25SAndroid Build Coastguard Worker *data = head;
1387*79398b25SAndroid Build Coastguard Worker
1388*79398b25SAndroid Build Coastguard Worker return res;
1389*79398b25SAndroid Build Coastguard Worker }
1390*79398b25SAndroid Build Coastguard Worker
1391*79398b25SAndroid Build Coastguard Worker
parse_mode_args(struct action_entry * action,int args,char ** argv,void ** data)1392*79398b25SAndroid Build Coastguard Worker static int parse_mode_args(struct action_entry *action, int args,
1393*79398b25SAndroid Build Coastguard Worker char **argv, void **data)
1394*79398b25SAndroid Build Coastguard Worker {
1395*79398b25SAndroid Build Coastguard Worker int res;
1396*79398b25SAndroid Build Coastguard Worker
1397*79398b25SAndroid Build Coastguard Worker if (args == 0) {
1398*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Mode action expects one or more arguments\n");
1399*79398b25SAndroid Build Coastguard Worker return 0;
1400*79398b25SAndroid Build Coastguard Worker }
1401*79398b25SAndroid Build Coastguard Worker
1402*79398b25SAndroid Build Coastguard Worker res = parse_octal_mode_args(args, argv, data);
1403*79398b25SAndroid Build Coastguard Worker if(res >= 0)
1404*79398b25SAndroid Build Coastguard Worker /* Got an octal mode argument */
1405*79398b25SAndroid Build Coastguard Worker return res;
1406*79398b25SAndroid Build Coastguard Worker else /* not an octal mode argument */
1407*79398b25SAndroid Build Coastguard Worker return parse_sym_mode_args(action, args, argv, data);
1408*79398b25SAndroid Build Coastguard Worker }
1409*79398b25SAndroid Build Coastguard Worker
1410*79398b25SAndroid Build Coastguard Worker
mode_execute(struct mode_data * mode_data,int st_mode)1411*79398b25SAndroid Build Coastguard Worker static int mode_execute(struct mode_data *mode_data, int st_mode)
1412*79398b25SAndroid Build Coastguard Worker {
1413*79398b25SAndroid Build Coastguard Worker int mode = 0;
1414*79398b25SAndroid Build Coastguard Worker
1415*79398b25SAndroid Build Coastguard Worker for (;mode_data; mode_data = mode_data->next) {
1416*79398b25SAndroid Build Coastguard Worker if (mode_data->mode < 0) {
1417*79398b25SAndroid Build Coastguard Worker /* 'u', 'g' or 'o' */
1418*79398b25SAndroid Build Coastguard Worker switch(-mode_data->mode) {
1419*79398b25SAndroid Build Coastguard Worker case 'u':
1420*79398b25SAndroid Build Coastguard Worker mode = (st_mode >> 6) & 07;
1421*79398b25SAndroid Build Coastguard Worker break;
1422*79398b25SAndroid Build Coastguard Worker case 'g':
1423*79398b25SAndroid Build Coastguard Worker mode = (st_mode >> 3) & 07;
1424*79398b25SAndroid Build Coastguard Worker break;
1425*79398b25SAndroid Build Coastguard Worker case 'o':
1426*79398b25SAndroid Build Coastguard Worker mode = st_mode & 07;
1427*79398b25SAndroid Build Coastguard Worker break;
1428*79398b25SAndroid Build Coastguard Worker }
1429*79398b25SAndroid Build Coastguard Worker mode = ((mode << 6) | (mode << 3) | mode) &
1430*79398b25SAndroid Build Coastguard Worker mode_data->mask;
1431*79398b25SAndroid Build Coastguard Worker } else if (mode_data->X &&
1432*79398b25SAndroid Build Coastguard Worker ((st_mode & S_IFMT) == S_IFDIR ||
1433*79398b25SAndroid Build Coastguard Worker (st_mode & 0111)))
1434*79398b25SAndroid Build Coastguard Worker /* X permission, only takes effect if inode is a
1435*79398b25SAndroid Build Coastguard Worker * directory or x is set for some owner */
1436*79398b25SAndroid Build Coastguard Worker mode = mode_data->mode | (0111 & mode_data->mask);
1437*79398b25SAndroid Build Coastguard Worker else
1438*79398b25SAndroid Build Coastguard Worker mode = mode_data->mode;
1439*79398b25SAndroid Build Coastguard Worker
1440*79398b25SAndroid Build Coastguard Worker switch(mode_data->operation) {
1441*79398b25SAndroid Build Coastguard Worker case ACTION_MODE_OCT:
1442*79398b25SAndroid Build Coastguard Worker st_mode = (st_mode & S_IFMT) | mode;
1443*79398b25SAndroid Build Coastguard Worker break;
1444*79398b25SAndroid Build Coastguard Worker case ACTION_MODE_SET:
1445*79398b25SAndroid Build Coastguard Worker st_mode = (st_mode & ~mode_data->mask) | mode;
1446*79398b25SAndroid Build Coastguard Worker break;
1447*79398b25SAndroid Build Coastguard Worker case ACTION_MODE_ADD:
1448*79398b25SAndroid Build Coastguard Worker st_mode |= mode;
1449*79398b25SAndroid Build Coastguard Worker break;
1450*79398b25SAndroid Build Coastguard Worker case ACTION_MODE_REM:
1451*79398b25SAndroid Build Coastguard Worker st_mode &= ~mode;
1452*79398b25SAndroid Build Coastguard Worker }
1453*79398b25SAndroid Build Coastguard Worker }
1454*79398b25SAndroid Build Coastguard Worker
1455*79398b25SAndroid Build Coastguard Worker return st_mode;
1456*79398b25SAndroid Build Coastguard Worker }
1457*79398b25SAndroid Build Coastguard Worker
1458*79398b25SAndroid Build Coastguard Worker
mode_action(struct action * action,struct dir_ent * dir_ent)1459*79398b25SAndroid Build Coastguard Worker static void mode_action(struct action *action, struct dir_ent *dir_ent)
1460*79398b25SAndroid Build Coastguard Worker {
1461*79398b25SAndroid Build Coastguard Worker dir_ent->inode->buf.st_mode = mode_execute(action->data,
1462*79398b25SAndroid Build Coastguard Worker dir_ent->inode->buf.st_mode);
1463*79398b25SAndroid Build Coastguard Worker }
1464*79398b25SAndroid Build Coastguard Worker
1465*79398b25SAndroid Build Coastguard Worker
1466*79398b25SAndroid Build Coastguard Worker /*
1467*79398b25SAndroid Build Coastguard Worker * Empty specific action code
1468*79398b25SAndroid Build Coastguard Worker */
empty_actions()1469*79398b25SAndroid Build Coastguard Worker int empty_actions()
1470*79398b25SAndroid Build Coastguard Worker {
1471*79398b25SAndroid Build Coastguard Worker return empty_count;
1472*79398b25SAndroid Build Coastguard Worker }
1473*79398b25SAndroid Build Coastguard Worker
1474*79398b25SAndroid Build Coastguard Worker
parse_empty_args(struct action_entry * action,int args,char ** argv,void ** data)1475*79398b25SAndroid Build Coastguard Worker static int parse_empty_args(struct action_entry *action, int args,
1476*79398b25SAndroid Build Coastguard Worker char **argv, void **data)
1477*79398b25SAndroid Build Coastguard Worker {
1478*79398b25SAndroid Build Coastguard Worker struct empty_data *empty_data;
1479*79398b25SAndroid Build Coastguard Worker int val;
1480*79398b25SAndroid Build Coastguard Worker
1481*79398b25SAndroid Build Coastguard Worker if (args >= 2) {
1482*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Empty action expects zero or one argument\n");
1483*79398b25SAndroid Build Coastguard Worker return 0;
1484*79398b25SAndroid Build Coastguard Worker }
1485*79398b25SAndroid Build Coastguard Worker
1486*79398b25SAndroid Build Coastguard Worker if (args == 0 || strcmp(argv[0], "all") == 0)
1487*79398b25SAndroid Build Coastguard Worker val = EMPTY_ALL;
1488*79398b25SAndroid Build Coastguard Worker else if (strcmp(argv[0], "source") == 0)
1489*79398b25SAndroid Build Coastguard Worker val = EMPTY_SOURCE;
1490*79398b25SAndroid Build Coastguard Worker else if (strcmp(argv[0], "excluded") == 0)
1491*79398b25SAndroid Build Coastguard Worker val = EMPTY_EXCLUDED;
1492*79398b25SAndroid Build Coastguard Worker else {
1493*79398b25SAndroid Build Coastguard Worker SYNTAX_ERROR("Empty action expects zero arguments, or one"
1494*79398b25SAndroid Build Coastguard Worker "argument containing \"all\", \"source\", or \"excluded\""
1495*79398b25SAndroid Build Coastguard Worker "\n");
1496*79398b25SAndroid Build Coastguard Worker return 0;
1497*79398b25SAndroid Build Coastguard Worker }
1498*79398b25SAndroid Build Coastguard Worker
1499*79398b25SAndroid Build Coastguard Worker empty_data = malloc(sizeof(*empty_data));
1500*79398b25SAndroid Build Coastguard Worker if (empty_data == NULL)
1501*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1502*79398b25SAndroid Build Coastguard Worker
1503*79398b25SAndroid Build Coastguard Worker empty_data->val = val;
1504*79398b25SAndroid Build Coastguard Worker *data = empty_data;
1505*79398b25SAndroid Build Coastguard Worker
1506*79398b25SAndroid Build Coastguard Worker return 1;
1507*79398b25SAndroid Build Coastguard Worker }
1508*79398b25SAndroid Build Coastguard Worker
1509*79398b25SAndroid Build Coastguard Worker
eval_empty_actions(struct dir_info * root,struct dir_ent * dir_ent)1510*79398b25SAndroid Build Coastguard Worker int eval_empty_actions(struct dir_info *root, struct dir_ent *dir_ent)
1511*79398b25SAndroid Build Coastguard Worker {
1512*79398b25SAndroid Build Coastguard Worker int i, match = 0;
1513*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
1514*79398b25SAndroid Build Coastguard Worker struct empty_data *data;
1515*79398b25SAndroid Build Coastguard Worker struct dir_info *dir = dir_ent->dir;
1516*79398b25SAndroid Build Coastguard Worker
1517*79398b25SAndroid Build Coastguard Worker /*
1518*79398b25SAndroid Build Coastguard Worker * Empty action only works on empty directories
1519*79398b25SAndroid Build Coastguard Worker */
1520*79398b25SAndroid Build Coastguard Worker if (dir->count != 0)
1521*79398b25SAndroid Build Coastguard Worker return 0;
1522*79398b25SAndroid Build Coastguard Worker
1523*79398b25SAndroid Build Coastguard Worker action_data.name = dir_ent->name;
1524*79398b25SAndroid Build Coastguard Worker action_data.pathname = strdup(pathname(dir_ent));
1525*79398b25SAndroid Build Coastguard Worker action_data.subpath = strdup(subpathname(dir_ent));
1526*79398b25SAndroid Build Coastguard Worker action_data.buf = &dir_ent->inode->buf;
1527*79398b25SAndroid Build Coastguard Worker action_data.depth = dir_ent->our_dir->depth;
1528*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
1529*79398b25SAndroid Build Coastguard Worker action_data.root = root;
1530*79398b25SAndroid Build Coastguard Worker
1531*79398b25SAndroid Build Coastguard Worker for (i = 0; i < empty_count && !match; i++) {
1532*79398b25SAndroid Build Coastguard Worker data = empty_spec[i].data;
1533*79398b25SAndroid Build Coastguard Worker
1534*79398b25SAndroid Build Coastguard Worker /*
1535*79398b25SAndroid Build Coastguard Worker * determine the cause of the empty directory and evaluate
1536*79398b25SAndroid Build Coastguard Worker * the empty action specified. Three empty actions:
1537*79398b25SAndroid Build Coastguard Worker * - EMPTY_SOURCE: empty action triggers only if the directory
1538*79398b25SAndroid Build Coastguard Worker * was originally empty, i.e directories that are empty
1539*79398b25SAndroid Build Coastguard Worker * only due to excluding are ignored.
1540*79398b25SAndroid Build Coastguard Worker * - EMPTY_EXCLUDED: empty action triggers only if the directory
1541*79398b25SAndroid Build Coastguard Worker * is empty because of excluding, i.e. directories that
1542*79398b25SAndroid Build Coastguard Worker * were originally empty are ignored.
1543*79398b25SAndroid Build Coastguard Worker * - EMPTY_ALL (the default): empty action triggers if the
1544*79398b25SAndroid Build Coastguard Worker * directory is empty, irrespective of the reason, i.e.
1545*79398b25SAndroid Build Coastguard Worker * the directory could have been originally empty or could
1546*79398b25SAndroid Build Coastguard Worker * be empty due to excluding.
1547*79398b25SAndroid Build Coastguard Worker */
1548*79398b25SAndroid Build Coastguard Worker if ((data->val == EMPTY_EXCLUDED && !dir->excluded) ||
1549*79398b25SAndroid Build Coastguard Worker (data->val == EMPTY_SOURCE && dir->excluded))
1550*79398b25SAndroid Build Coastguard Worker continue;
1551*79398b25SAndroid Build Coastguard Worker
1552*79398b25SAndroid Build Coastguard Worker match = eval_expr_top(&empty_spec[i], &action_data);
1553*79398b25SAndroid Build Coastguard Worker }
1554*79398b25SAndroid Build Coastguard Worker
1555*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
1556*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
1557*79398b25SAndroid Build Coastguard Worker
1558*79398b25SAndroid Build Coastguard Worker return match;
1559*79398b25SAndroid Build Coastguard Worker }
1560*79398b25SAndroid Build Coastguard Worker
1561*79398b25SAndroid Build Coastguard Worker
1562*79398b25SAndroid Build Coastguard Worker /*
1563*79398b25SAndroid Build Coastguard Worker * Move specific action code
1564*79398b25SAndroid Build Coastguard Worker */
1565*79398b25SAndroid Build Coastguard Worker static struct move_ent *move_list = NULL;
1566*79398b25SAndroid Build Coastguard Worker
1567*79398b25SAndroid Build Coastguard Worker
move_actions()1568*79398b25SAndroid Build Coastguard Worker int move_actions()
1569*79398b25SAndroid Build Coastguard Worker {
1570*79398b25SAndroid Build Coastguard Worker return move_count;
1571*79398b25SAndroid Build Coastguard Worker }
1572*79398b25SAndroid Build Coastguard Worker
1573*79398b25SAndroid Build Coastguard Worker
move_pathname(struct move_ent * move)1574*79398b25SAndroid Build Coastguard Worker static char *move_pathname(struct move_ent *move)
1575*79398b25SAndroid Build Coastguard Worker {
1576*79398b25SAndroid Build Coastguard Worker struct dir_info *dest;
1577*79398b25SAndroid Build Coastguard Worker char *name, *pathname;
1578*79398b25SAndroid Build Coastguard Worker int res;
1579*79398b25SAndroid Build Coastguard Worker
1580*79398b25SAndroid Build Coastguard Worker dest = (move->ops & ACTION_MOVE_MOVE) ?
1581*79398b25SAndroid Build Coastguard Worker move->dest : move->dir_ent->our_dir;
1582*79398b25SAndroid Build Coastguard Worker name = (move->ops & ACTION_MOVE_RENAME) ?
1583*79398b25SAndroid Build Coastguard Worker move->name : move->dir_ent->name;
1584*79398b25SAndroid Build Coastguard Worker
1585*79398b25SAndroid Build Coastguard Worker if(dest->subpath[0] != '\0')
1586*79398b25SAndroid Build Coastguard Worker res = asprintf(&pathname, "%s/%s", dest->subpath, name);
1587*79398b25SAndroid Build Coastguard Worker else
1588*79398b25SAndroid Build Coastguard Worker res = asprintf(&pathname, "/%s", name);
1589*79398b25SAndroid Build Coastguard Worker
1590*79398b25SAndroid Build Coastguard Worker if(res == -1)
1591*79398b25SAndroid Build Coastguard Worker BAD_ERROR("asprintf failed in move_pathname\n");
1592*79398b25SAndroid Build Coastguard Worker
1593*79398b25SAndroid Build Coastguard Worker return pathname;
1594*79398b25SAndroid Build Coastguard Worker }
1595*79398b25SAndroid Build Coastguard Worker
1596*79398b25SAndroid Build Coastguard Worker
get_comp(char ** pathname)1597*79398b25SAndroid Build Coastguard Worker static char *get_comp(char **pathname)
1598*79398b25SAndroid Build Coastguard Worker {
1599*79398b25SAndroid Build Coastguard Worker char *path = *pathname, *start;
1600*79398b25SAndroid Build Coastguard Worker
1601*79398b25SAndroid Build Coastguard Worker while(*path == '/')
1602*79398b25SAndroid Build Coastguard Worker path ++;
1603*79398b25SAndroid Build Coastguard Worker
1604*79398b25SAndroid Build Coastguard Worker if(*path == '\0')
1605*79398b25SAndroid Build Coastguard Worker return NULL;
1606*79398b25SAndroid Build Coastguard Worker
1607*79398b25SAndroid Build Coastguard Worker start = path;
1608*79398b25SAndroid Build Coastguard Worker while(*path != '/' && *path != '\0')
1609*79398b25SAndroid Build Coastguard Worker path ++;
1610*79398b25SAndroid Build Coastguard Worker
1611*79398b25SAndroid Build Coastguard Worker *pathname = path;
1612*79398b25SAndroid Build Coastguard Worker return strndup(start, path - start);
1613*79398b25SAndroid Build Coastguard Worker }
1614*79398b25SAndroid Build Coastguard Worker
1615*79398b25SAndroid Build Coastguard Worker
lookup_comp(char * comp,struct dir_info * dest)1616*79398b25SAndroid Build Coastguard Worker static struct dir_ent *lookup_comp(char *comp, struct dir_info *dest)
1617*79398b25SAndroid Build Coastguard Worker {
1618*79398b25SAndroid Build Coastguard Worker struct dir_ent *dir_ent;
1619*79398b25SAndroid Build Coastguard Worker
1620*79398b25SAndroid Build Coastguard Worker for(dir_ent = dest->list; dir_ent; dir_ent = dir_ent->next)
1621*79398b25SAndroid Build Coastguard Worker if(strcmp(comp, dir_ent->name) == 0)
1622*79398b25SAndroid Build Coastguard Worker break;
1623*79398b25SAndroid Build Coastguard Worker
1624*79398b25SAndroid Build Coastguard Worker return dir_ent;
1625*79398b25SAndroid Build Coastguard Worker }
1626*79398b25SAndroid Build Coastguard Worker
1627*79398b25SAndroid Build Coastguard Worker
eval_move(struct action_data * action_data,struct move_ent * move,struct dir_info * root,struct dir_ent * dir_ent,char * pathname)1628*79398b25SAndroid Build Coastguard Worker void eval_move(struct action_data *action_data, struct move_ent *move,
1629*79398b25SAndroid Build Coastguard Worker struct dir_info *root, struct dir_ent *dir_ent, char *pathname)
1630*79398b25SAndroid Build Coastguard Worker {
1631*79398b25SAndroid Build Coastguard Worker struct dir_info *dest, *source = dir_ent->our_dir;
1632*79398b25SAndroid Build Coastguard Worker struct dir_ent *comp_ent;
1633*79398b25SAndroid Build Coastguard Worker char *comp, *path = pathname;
1634*79398b25SAndroid Build Coastguard Worker
1635*79398b25SAndroid Build Coastguard Worker /*
1636*79398b25SAndroid Build Coastguard Worker * Walk pathname to get the destination directory
1637*79398b25SAndroid Build Coastguard Worker *
1638*79398b25SAndroid Build Coastguard Worker * Like the mv command, if the last component exists and it
1639*79398b25SAndroid Build Coastguard Worker * is a directory, then move the file into that directory,
1640*79398b25SAndroid Build Coastguard Worker * otherwise, move the file into parent directory of the last
1641*79398b25SAndroid Build Coastguard Worker * component and rename to the last component.
1642*79398b25SAndroid Build Coastguard Worker */
1643*79398b25SAndroid Build Coastguard Worker if (pathname[0] == '/')
1644*79398b25SAndroid Build Coastguard Worker /* absolute pathname, walk from root directory */
1645*79398b25SAndroid Build Coastguard Worker dest = root;
1646*79398b25SAndroid Build Coastguard Worker else
1647*79398b25SAndroid Build Coastguard Worker /* relative pathname, walk from current directory */
1648*79398b25SAndroid Build Coastguard Worker dest = source;
1649*79398b25SAndroid Build Coastguard Worker
1650*79398b25SAndroid Build Coastguard Worker for(comp = get_comp(&pathname); comp; free(comp),
1651*79398b25SAndroid Build Coastguard Worker comp = get_comp(&pathname)) {
1652*79398b25SAndroid Build Coastguard Worker
1653*79398b25SAndroid Build Coastguard Worker if (strcmp(comp, ".") == 0)
1654*79398b25SAndroid Build Coastguard Worker continue;
1655*79398b25SAndroid Build Coastguard Worker
1656*79398b25SAndroid Build Coastguard Worker if (strcmp(comp, "..") == 0) {
1657*79398b25SAndroid Build Coastguard Worker /* if we're in the root directory then ignore */
1658*79398b25SAndroid Build Coastguard Worker if(dest->depth > 1)
1659*79398b25SAndroid Build Coastguard Worker dest = dest->dir_ent->our_dir;
1660*79398b25SAndroid Build Coastguard Worker continue;
1661*79398b25SAndroid Build Coastguard Worker }
1662*79398b25SAndroid Build Coastguard Worker
1663*79398b25SAndroid Build Coastguard Worker /*
1664*79398b25SAndroid Build Coastguard Worker * Look up comp in current directory, if it exists and it is a
1665*79398b25SAndroid Build Coastguard Worker * directory continue walking the pathname, otherwise exit,
1666*79398b25SAndroid Build Coastguard Worker * we've walked as far as we can go, normally this is because
1667*79398b25SAndroid Build Coastguard Worker * we've arrived at the leaf component which we are going to
1668*79398b25SAndroid Build Coastguard Worker * rename source to
1669*79398b25SAndroid Build Coastguard Worker */
1670*79398b25SAndroid Build Coastguard Worker comp_ent = lookup_comp(comp, dest);
1671*79398b25SAndroid Build Coastguard Worker if (comp_ent == NULL || (comp_ent->inode->buf.st_mode & S_IFMT)
1672*79398b25SAndroid Build Coastguard Worker != S_IFDIR)
1673*79398b25SAndroid Build Coastguard Worker break;
1674*79398b25SAndroid Build Coastguard Worker
1675*79398b25SAndroid Build Coastguard Worker dest = comp_ent->dir;
1676*79398b25SAndroid Build Coastguard Worker }
1677*79398b25SAndroid Build Coastguard Worker
1678*79398b25SAndroid Build Coastguard Worker if(comp) {
1679*79398b25SAndroid Build Coastguard Worker /* Leaf component? If so we're renaming to this */
1680*79398b25SAndroid Build Coastguard Worker char *remainder = get_comp(&pathname);
1681*79398b25SAndroid Build Coastguard Worker free(remainder);
1682*79398b25SAndroid Build Coastguard Worker
1683*79398b25SAndroid Build Coastguard Worker if(remainder) {
1684*79398b25SAndroid Build Coastguard Worker /*
1685*79398b25SAndroid Build Coastguard Worker * trying to move source to a subdirectory of
1686*79398b25SAndroid Build Coastguard Worker * comp, but comp either doesn't exist, or it isn't
1687*79398b25SAndroid Build Coastguard Worker * a directory, which is impossible
1688*79398b25SAndroid Build Coastguard Worker */
1689*79398b25SAndroid Build Coastguard Worker if (comp_ent == NULL)
1690*79398b25SAndroid Build Coastguard Worker ERROR("Move action: cannot move %s to %s, no "
1691*79398b25SAndroid Build Coastguard Worker "such directory %s\n",
1692*79398b25SAndroid Build Coastguard Worker action_data->subpath, path, comp);
1693*79398b25SAndroid Build Coastguard Worker else
1694*79398b25SAndroid Build Coastguard Worker ERROR("Move action: cannot move %s to %s, %s "
1695*79398b25SAndroid Build Coastguard Worker "is not a directory\n",
1696*79398b25SAndroid Build Coastguard Worker action_data->subpath, path, comp);
1697*79398b25SAndroid Build Coastguard Worker free(comp);
1698*79398b25SAndroid Build Coastguard Worker return;
1699*79398b25SAndroid Build Coastguard Worker }
1700*79398b25SAndroid Build Coastguard Worker
1701*79398b25SAndroid Build Coastguard Worker /*
1702*79398b25SAndroid Build Coastguard Worker * Multiple move actions triggering on one file can be merged
1703*79398b25SAndroid Build Coastguard Worker * if one is a RENAME and the other is a MOVE. Multiple RENAMEs
1704*79398b25SAndroid Build Coastguard Worker * can only merge if they're doing the same thing
1705*79398b25SAndroid Build Coastguard Worker */
1706*79398b25SAndroid Build Coastguard Worker if(move->ops & ACTION_MOVE_RENAME) {
1707*79398b25SAndroid Build Coastguard Worker if(strcmp(comp, move->name) != 0) {
1708*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move);
1709*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, "
1710*79398b25SAndroid Build Coastguard Worker "conflicting move, already moving "
1711*79398b25SAndroid Build Coastguard Worker "to %s via another move action!\n",
1712*79398b25SAndroid Build Coastguard Worker action_data->subpath, path, conf_path);
1713*79398b25SAndroid Build Coastguard Worker free(conf_path);
1714*79398b25SAndroid Build Coastguard Worker free(comp);
1715*79398b25SAndroid Build Coastguard Worker return;
1716*79398b25SAndroid Build Coastguard Worker }
1717*79398b25SAndroid Build Coastguard Worker free(comp);
1718*79398b25SAndroid Build Coastguard Worker } else {
1719*79398b25SAndroid Build Coastguard Worker move->name = comp;
1720*79398b25SAndroid Build Coastguard Worker move->ops |= ACTION_MOVE_RENAME;
1721*79398b25SAndroid Build Coastguard Worker }
1722*79398b25SAndroid Build Coastguard Worker }
1723*79398b25SAndroid Build Coastguard Worker
1724*79398b25SAndroid Build Coastguard Worker if(dest != source) {
1725*79398b25SAndroid Build Coastguard Worker /*
1726*79398b25SAndroid Build Coastguard Worker * Multiple move actions triggering on one file can be merged
1727*79398b25SAndroid Build Coastguard Worker * if one is a RENAME and the other is a MOVE. Multiple MOVEs
1728*79398b25SAndroid Build Coastguard Worker * can only merge if they're doing the same thing
1729*79398b25SAndroid Build Coastguard Worker */
1730*79398b25SAndroid Build Coastguard Worker if(move->ops & ACTION_MOVE_MOVE) {
1731*79398b25SAndroid Build Coastguard Worker if(dest != move->dest) {
1732*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move);
1733*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, "
1734*79398b25SAndroid Build Coastguard Worker "conflicting move, already moving "
1735*79398b25SAndroid Build Coastguard Worker "to %s via another move action!\n",
1736*79398b25SAndroid Build Coastguard Worker action_data->subpath, path, conf_path);
1737*79398b25SAndroid Build Coastguard Worker free(conf_path);
1738*79398b25SAndroid Build Coastguard Worker return;
1739*79398b25SAndroid Build Coastguard Worker }
1740*79398b25SAndroid Build Coastguard Worker } else {
1741*79398b25SAndroid Build Coastguard Worker move->dest = dest;
1742*79398b25SAndroid Build Coastguard Worker move->ops |= ACTION_MOVE_MOVE;
1743*79398b25SAndroid Build Coastguard Worker }
1744*79398b25SAndroid Build Coastguard Worker }
1745*79398b25SAndroid Build Coastguard Worker }
1746*79398b25SAndroid Build Coastguard Worker
1747*79398b25SAndroid Build Coastguard Worker
subdirectory(struct dir_info * source,struct dir_info * dest)1748*79398b25SAndroid Build Coastguard Worker static int subdirectory(struct dir_info *source, struct dir_info *dest)
1749*79398b25SAndroid Build Coastguard Worker {
1750*79398b25SAndroid Build Coastguard Worker if(source == NULL)
1751*79398b25SAndroid Build Coastguard Worker return 0;
1752*79398b25SAndroid Build Coastguard Worker
1753*79398b25SAndroid Build Coastguard Worker return strlen(source->subpath) <= strlen(dest->subpath) &&
1754*79398b25SAndroid Build Coastguard Worker (dest->subpath[strlen(source->subpath)] == '/' ||
1755*79398b25SAndroid Build Coastguard Worker dest->subpath[strlen(source->subpath)] == '\0') &&
1756*79398b25SAndroid Build Coastguard Worker strncmp(source->subpath, dest->subpath,
1757*79398b25SAndroid Build Coastguard Worker strlen(source->subpath)) == 0;
1758*79398b25SAndroid Build Coastguard Worker }
1759*79398b25SAndroid Build Coastguard Worker
1760*79398b25SAndroid Build Coastguard Worker
eval_move_actions(struct dir_info * root,struct dir_ent * dir_ent)1761*79398b25SAndroid Build Coastguard Worker void eval_move_actions(struct dir_info *root, struct dir_ent *dir_ent)
1762*79398b25SAndroid Build Coastguard Worker {
1763*79398b25SAndroid Build Coastguard Worker int i;
1764*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
1765*79398b25SAndroid Build Coastguard Worker struct move_ent *move = NULL;
1766*79398b25SAndroid Build Coastguard Worker
1767*79398b25SAndroid Build Coastguard Worker action_data.name = dir_ent->name;
1768*79398b25SAndroid Build Coastguard Worker action_data.pathname = strdup(pathname(dir_ent));
1769*79398b25SAndroid Build Coastguard Worker action_data.subpath = strdup(subpathname(dir_ent));
1770*79398b25SAndroid Build Coastguard Worker action_data.buf = &dir_ent->inode->buf;
1771*79398b25SAndroid Build Coastguard Worker action_data.depth = dir_ent->our_dir->depth;
1772*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
1773*79398b25SAndroid Build Coastguard Worker action_data.root = root;
1774*79398b25SAndroid Build Coastguard Worker
1775*79398b25SAndroid Build Coastguard Worker /*
1776*79398b25SAndroid Build Coastguard Worker * Evaluate each move action against the current file. For any
1777*79398b25SAndroid Build Coastguard Worker * move actions that match don't actually perform the move now, but,
1778*79398b25SAndroid Build Coastguard Worker * store it, and execute all the stored move actions together once the
1779*79398b25SAndroid Build Coastguard Worker * directory scan is complete. This is done to ensure each separate
1780*79398b25SAndroid Build Coastguard Worker * move action does not nondeterministically interfere with other move
1781*79398b25SAndroid Build Coastguard Worker * actions. Each move action is considered to act independently, and
1782*79398b25SAndroid Build Coastguard Worker * each move action sees the directory tree in the same state.
1783*79398b25SAndroid Build Coastguard Worker */
1784*79398b25SAndroid Build Coastguard Worker for (i = 0; i < move_count; i++) {
1785*79398b25SAndroid Build Coastguard Worker struct action *action = &move_spec[i];
1786*79398b25SAndroid Build Coastguard Worker int match = eval_expr_top(action, &action_data);
1787*79398b25SAndroid Build Coastguard Worker
1788*79398b25SAndroid Build Coastguard Worker if(match) {
1789*79398b25SAndroid Build Coastguard Worker if(move == NULL) {
1790*79398b25SAndroid Build Coastguard Worker move = malloc(sizeof(*move));
1791*79398b25SAndroid Build Coastguard Worker if(move == NULL)
1792*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
1793*79398b25SAndroid Build Coastguard Worker
1794*79398b25SAndroid Build Coastguard Worker move->ops = 0;
1795*79398b25SAndroid Build Coastguard Worker move->dir_ent = dir_ent;
1796*79398b25SAndroid Build Coastguard Worker }
1797*79398b25SAndroid Build Coastguard Worker eval_move(&action_data, move, root, dir_ent,
1798*79398b25SAndroid Build Coastguard Worker action->argv[0]);
1799*79398b25SAndroid Build Coastguard Worker }
1800*79398b25SAndroid Build Coastguard Worker }
1801*79398b25SAndroid Build Coastguard Worker
1802*79398b25SAndroid Build Coastguard Worker if(move) {
1803*79398b25SAndroid Build Coastguard Worker struct dir_ent *comp_ent;
1804*79398b25SAndroid Build Coastguard Worker struct dir_info *dest;
1805*79398b25SAndroid Build Coastguard Worker char *name;
1806*79398b25SAndroid Build Coastguard Worker
1807*79398b25SAndroid Build Coastguard Worker /*
1808*79398b25SAndroid Build Coastguard Worker * Move contains the result of all triggered move actions.
1809*79398b25SAndroid Build Coastguard Worker * Check the destination doesn't already exist
1810*79398b25SAndroid Build Coastguard Worker */
1811*79398b25SAndroid Build Coastguard Worker if(move->ops == 0) {
1812*79398b25SAndroid Build Coastguard Worker free(move);
1813*79398b25SAndroid Build Coastguard Worker goto finish;
1814*79398b25SAndroid Build Coastguard Worker }
1815*79398b25SAndroid Build Coastguard Worker
1816*79398b25SAndroid Build Coastguard Worker dest = (move->ops & ACTION_MOVE_MOVE) ?
1817*79398b25SAndroid Build Coastguard Worker move->dest : dir_ent->our_dir;
1818*79398b25SAndroid Build Coastguard Worker name = (move->ops & ACTION_MOVE_RENAME) ?
1819*79398b25SAndroid Build Coastguard Worker move->name : dir_ent->name;
1820*79398b25SAndroid Build Coastguard Worker comp_ent = lookup_comp(name, dest);
1821*79398b25SAndroid Build Coastguard Worker if(comp_ent) {
1822*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move);
1823*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, "
1824*79398b25SAndroid Build Coastguard Worker "destination already exists\n",
1825*79398b25SAndroid Build Coastguard Worker action_data.subpath, conf_path);
1826*79398b25SAndroid Build Coastguard Worker free(conf_path);
1827*79398b25SAndroid Build Coastguard Worker free(move);
1828*79398b25SAndroid Build Coastguard Worker goto finish;
1829*79398b25SAndroid Build Coastguard Worker }
1830*79398b25SAndroid Build Coastguard Worker
1831*79398b25SAndroid Build Coastguard Worker /*
1832*79398b25SAndroid Build Coastguard Worker * If we're moving a directory, check we're not moving it to a
1833*79398b25SAndroid Build Coastguard Worker * subdirectory of itself
1834*79398b25SAndroid Build Coastguard Worker */
1835*79398b25SAndroid Build Coastguard Worker if(subdirectory(dir_ent->dir, dest)) {
1836*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move);
1837*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, this is a "
1838*79398b25SAndroid Build Coastguard Worker "subdirectory of itself\n",
1839*79398b25SAndroid Build Coastguard Worker action_data.subpath, conf_path);
1840*79398b25SAndroid Build Coastguard Worker free(conf_path);
1841*79398b25SAndroid Build Coastguard Worker free(move);
1842*79398b25SAndroid Build Coastguard Worker goto finish;
1843*79398b25SAndroid Build Coastguard Worker }
1844*79398b25SAndroid Build Coastguard Worker move->next = move_list;
1845*79398b25SAndroid Build Coastguard Worker move_list = move;
1846*79398b25SAndroid Build Coastguard Worker }
1847*79398b25SAndroid Build Coastguard Worker
1848*79398b25SAndroid Build Coastguard Worker finish:
1849*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
1850*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
1851*79398b25SAndroid Build Coastguard Worker }
1852*79398b25SAndroid Build Coastguard Worker
1853*79398b25SAndroid Build Coastguard Worker
move_dir(struct dir_ent * dir_ent)1854*79398b25SAndroid Build Coastguard Worker static void move_dir(struct dir_ent *dir_ent)
1855*79398b25SAndroid Build Coastguard Worker {
1856*79398b25SAndroid Build Coastguard Worker struct dir_info *dir = dir_ent->dir;
1857*79398b25SAndroid Build Coastguard Worker struct dir_ent *comp_ent;
1858*79398b25SAndroid Build Coastguard Worker
1859*79398b25SAndroid Build Coastguard Worker /* update our directory's subpath name */
1860*79398b25SAndroid Build Coastguard Worker free(dir->subpath);
1861*79398b25SAndroid Build Coastguard Worker dir->subpath = strdup(subpathname(dir_ent));
1862*79398b25SAndroid Build Coastguard Worker
1863*79398b25SAndroid Build Coastguard Worker /* recursively update the subpaths of any sub-directories */
1864*79398b25SAndroid Build Coastguard Worker for(comp_ent = dir->list; comp_ent; comp_ent = comp_ent->next)
1865*79398b25SAndroid Build Coastguard Worker if(comp_ent->dir)
1866*79398b25SAndroid Build Coastguard Worker move_dir(comp_ent);
1867*79398b25SAndroid Build Coastguard Worker }
1868*79398b25SAndroid Build Coastguard Worker
1869*79398b25SAndroid Build Coastguard Worker
move_file(struct move_ent * move_ent)1870*79398b25SAndroid Build Coastguard Worker static void move_file(struct move_ent *move_ent)
1871*79398b25SAndroid Build Coastguard Worker {
1872*79398b25SAndroid Build Coastguard Worker struct dir_ent *dir_ent = move_ent->dir_ent;
1873*79398b25SAndroid Build Coastguard Worker
1874*79398b25SAndroid Build Coastguard Worker if(move_ent->ops & ACTION_MOVE_MOVE) {
1875*79398b25SAndroid Build Coastguard Worker struct dir_ent *comp_ent, *prev = NULL;
1876*79398b25SAndroid Build Coastguard Worker struct dir_info *source = dir_ent->our_dir,
1877*79398b25SAndroid Build Coastguard Worker *dest = move_ent->dest;
1878*79398b25SAndroid Build Coastguard Worker char *filename = pathname(dir_ent);
1879*79398b25SAndroid Build Coastguard Worker
1880*79398b25SAndroid Build Coastguard Worker /*
1881*79398b25SAndroid Build Coastguard Worker * If we're moving a directory, check we're not moving it to a
1882*79398b25SAndroid Build Coastguard Worker * subdirectory of itself
1883*79398b25SAndroid Build Coastguard Worker */
1884*79398b25SAndroid Build Coastguard Worker if(subdirectory(dir_ent->dir, dest)) {
1885*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move_ent);
1886*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, this is a "
1887*79398b25SAndroid Build Coastguard Worker "subdirectory of itself\n",
1888*79398b25SAndroid Build Coastguard Worker subpathname(dir_ent), conf_path);
1889*79398b25SAndroid Build Coastguard Worker free(conf_path);
1890*79398b25SAndroid Build Coastguard Worker return;
1891*79398b25SAndroid Build Coastguard Worker }
1892*79398b25SAndroid Build Coastguard Worker
1893*79398b25SAndroid Build Coastguard Worker /* Remove the file from source directory */
1894*79398b25SAndroid Build Coastguard Worker for(comp_ent = source->list; comp_ent != dir_ent;
1895*79398b25SAndroid Build Coastguard Worker prev = comp_ent, comp_ent = comp_ent->next);
1896*79398b25SAndroid Build Coastguard Worker
1897*79398b25SAndroid Build Coastguard Worker if(prev)
1898*79398b25SAndroid Build Coastguard Worker prev->next = comp_ent->next;
1899*79398b25SAndroid Build Coastguard Worker else
1900*79398b25SAndroid Build Coastguard Worker source->list = comp_ent->next;
1901*79398b25SAndroid Build Coastguard Worker
1902*79398b25SAndroid Build Coastguard Worker source->count --;
1903*79398b25SAndroid Build Coastguard Worker if((comp_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)
1904*79398b25SAndroid Build Coastguard Worker source->directory_count --;
1905*79398b25SAndroid Build Coastguard Worker
1906*79398b25SAndroid Build Coastguard Worker /* Add the file to dest directory */
1907*79398b25SAndroid Build Coastguard Worker comp_ent->next = dest->list;
1908*79398b25SAndroid Build Coastguard Worker dest->list = comp_ent;
1909*79398b25SAndroid Build Coastguard Worker comp_ent->our_dir = dest;
1910*79398b25SAndroid Build Coastguard Worker
1911*79398b25SAndroid Build Coastguard Worker dest->count ++;
1912*79398b25SAndroid Build Coastguard Worker if((comp_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)
1913*79398b25SAndroid Build Coastguard Worker dest->directory_count ++;
1914*79398b25SAndroid Build Coastguard Worker
1915*79398b25SAndroid Build Coastguard Worker /*
1916*79398b25SAndroid Build Coastguard Worker * We've moved the file, and so we can't now use the
1917*79398b25SAndroid Build Coastguard Worker * parent directory's pathname to calculate the pathname
1918*79398b25SAndroid Build Coastguard Worker */
1919*79398b25SAndroid Build Coastguard Worker if(dir_ent->nonstandard_pathname == NULL) {
1920*79398b25SAndroid Build Coastguard Worker dir_ent->nonstandard_pathname = strdup(filename);
1921*79398b25SAndroid Build Coastguard Worker if(dir_ent->source_name) {
1922*79398b25SAndroid Build Coastguard Worker free(dir_ent->source_name);
1923*79398b25SAndroid Build Coastguard Worker dir_ent->source_name = NULL;
1924*79398b25SAndroid Build Coastguard Worker }
1925*79398b25SAndroid Build Coastguard Worker }
1926*79398b25SAndroid Build Coastguard Worker }
1927*79398b25SAndroid Build Coastguard Worker
1928*79398b25SAndroid Build Coastguard Worker if(move_ent->ops & ACTION_MOVE_RENAME) {
1929*79398b25SAndroid Build Coastguard Worker /*
1930*79398b25SAndroid Build Coastguard Worker * If we're using name in conjunction with the parent
1931*79398b25SAndroid Build Coastguard Worker * directory's pathname to calculate the pathname, we need
1932*79398b25SAndroid Build Coastguard Worker * to use source_name to override. Otherwise it's already being
1933*79398b25SAndroid Build Coastguard Worker * over-ridden
1934*79398b25SAndroid Build Coastguard Worker */
1935*79398b25SAndroid Build Coastguard Worker if(dir_ent->nonstandard_pathname == NULL &&
1936*79398b25SAndroid Build Coastguard Worker dir_ent->source_name == NULL)
1937*79398b25SAndroid Build Coastguard Worker dir_ent->source_name = dir_ent->name;
1938*79398b25SAndroid Build Coastguard Worker else
1939*79398b25SAndroid Build Coastguard Worker free(dir_ent->name);
1940*79398b25SAndroid Build Coastguard Worker
1941*79398b25SAndroid Build Coastguard Worker dir_ent->name = move_ent->name;
1942*79398b25SAndroid Build Coastguard Worker }
1943*79398b25SAndroid Build Coastguard Worker
1944*79398b25SAndroid Build Coastguard Worker if(dir_ent->dir)
1945*79398b25SAndroid Build Coastguard Worker /*
1946*79398b25SAndroid Build Coastguard Worker * dir_ent is a directory, and we have to recursively fix-up
1947*79398b25SAndroid Build Coastguard Worker * its subpath, and the subpaths of all of its sub-directories
1948*79398b25SAndroid Build Coastguard Worker */
1949*79398b25SAndroid Build Coastguard Worker move_dir(dir_ent);
1950*79398b25SAndroid Build Coastguard Worker }
1951*79398b25SAndroid Build Coastguard Worker
1952*79398b25SAndroid Build Coastguard Worker
do_move_actions()1953*79398b25SAndroid Build Coastguard Worker void do_move_actions()
1954*79398b25SAndroid Build Coastguard Worker {
1955*79398b25SAndroid Build Coastguard Worker while(move_list) {
1956*79398b25SAndroid Build Coastguard Worker struct move_ent *temp = move_list;
1957*79398b25SAndroid Build Coastguard Worker struct dir_info *dest = (move_list->ops & ACTION_MOVE_MOVE) ?
1958*79398b25SAndroid Build Coastguard Worker move_list->dest : move_list->dir_ent->our_dir;
1959*79398b25SAndroid Build Coastguard Worker char *name = (move_list->ops & ACTION_MOVE_RENAME) ?
1960*79398b25SAndroid Build Coastguard Worker move_list->name : move_list->dir_ent->name;
1961*79398b25SAndroid Build Coastguard Worker struct dir_ent *comp_ent = lookup_comp(name, dest);
1962*79398b25SAndroid Build Coastguard Worker if(comp_ent) {
1963*79398b25SAndroid Build Coastguard Worker char *conf_path = move_pathname(move_list);
1964*79398b25SAndroid Build Coastguard Worker ERROR("Move action: Cannot move %s to %s, "
1965*79398b25SAndroid Build Coastguard Worker "destination already exists\n",
1966*79398b25SAndroid Build Coastguard Worker subpathname(move_list->dir_ent), conf_path);
1967*79398b25SAndroid Build Coastguard Worker free(conf_path);
1968*79398b25SAndroid Build Coastguard Worker } else
1969*79398b25SAndroid Build Coastguard Worker move_file(move_list);
1970*79398b25SAndroid Build Coastguard Worker
1971*79398b25SAndroid Build Coastguard Worker move_list = move_list->next;
1972*79398b25SAndroid Build Coastguard Worker free(temp);
1973*79398b25SAndroid Build Coastguard Worker }
1974*79398b25SAndroid Build Coastguard Worker }
1975*79398b25SAndroid Build Coastguard Worker
1976*79398b25SAndroid Build Coastguard Worker
1977*79398b25SAndroid Build Coastguard Worker /*
1978*79398b25SAndroid Build Coastguard Worker * Prune specific action code
1979*79398b25SAndroid Build Coastguard Worker */
prune_actions()1980*79398b25SAndroid Build Coastguard Worker int prune_actions()
1981*79398b25SAndroid Build Coastguard Worker {
1982*79398b25SAndroid Build Coastguard Worker return prune_count;
1983*79398b25SAndroid Build Coastguard Worker }
1984*79398b25SAndroid Build Coastguard Worker
1985*79398b25SAndroid Build Coastguard Worker
eval_prune_actions(struct dir_info * root,struct dir_ent * dir_ent)1986*79398b25SAndroid Build Coastguard Worker int eval_prune_actions(struct dir_info *root, struct dir_ent *dir_ent)
1987*79398b25SAndroid Build Coastguard Worker {
1988*79398b25SAndroid Build Coastguard Worker int i, match = 0;
1989*79398b25SAndroid Build Coastguard Worker struct action_data action_data;
1990*79398b25SAndroid Build Coastguard Worker
1991*79398b25SAndroid Build Coastguard Worker action_data.name = dir_ent->name;
1992*79398b25SAndroid Build Coastguard Worker action_data.pathname = strdup(pathname(dir_ent));
1993*79398b25SAndroid Build Coastguard Worker action_data.subpath = strdup(subpathname(dir_ent));
1994*79398b25SAndroid Build Coastguard Worker action_data.buf = &dir_ent->inode->buf;
1995*79398b25SAndroid Build Coastguard Worker action_data.depth = dir_ent->our_dir->depth;
1996*79398b25SAndroid Build Coastguard Worker action_data.dir_ent = dir_ent;
1997*79398b25SAndroid Build Coastguard Worker action_data.root = root;
1998*79398b25SAndroid Build Coastguard Worker
1999*79398b25SAndroid Build Coastguard Worker for (i = 0; i < prune_count && !match; i++)
2000*79398b25SAndroid Build Coastguard Worker match = eval_expr_top(&prune_spec[i], &action_data);
2001*79398b25SAndroid Build Coastguard Worker
2002*79398b25SAndroid Build Coastguard Worker free(action_data.pathname);
2003*79398b25SAndroid Build Coastguard Worker free(action_data.subpath);
2004*79398b25SAndroid Build Coastguard Worker
2005*79398b25SAndroid Build Coastguard Worker return match;
2006*79398b25SAndroid Build Coastguard Worker }
2007*79398b25SAndroid Build Coastguard Worker
2008*79398b25SAndroid Build Coastguard Worker
2009*79398b25SAndroid Build Coastguard Worker /*
2010*79398b25SAndroid Build Coastguard Worker * Noop specific action code
2011*79398b25SAndroid Build Coastguard Worker */
noop_action(struct action * action,struct dir_ent * dir_ent)2012*79398b25SAndroid Build Coastguard Worker static void noop_action(struct action *action, struct dir_ent *dir_ent)
2013*79398b25SAndroid Build Coastguard Worker {
2014*79398b25SAndroid Build Coastguard Worker }
2015*79398b25SAndroid Build Coastguard Worker
2016*79398b25SAndroid Build Coastguard Worker
2017*79398b25SAndroid Build Coastguard Worker /*
2018*79398b25SAndroid Build Coastguard Worker * General test evaluation code
2019*79398b25SAndroid Build Coastguard Worker */
2020*79398b25SAndroid Build Coastguard Worker
2021*79398b25SAndroid Build Coastguard Worker /*
2022*79398b25SAndroid Build Coastguard Worker * A number can be of the form [range]number[size]
2023*79398b25SAndroid Build Coastguard Worker * [range] is either:
2024*79398b25SAndroid Build Coastguard Worker * '<' or '-', match on less than number
2025*79398b25SAndroid Build Coastguard Worker * '>' or '+', match on greater than number
2026*79398b25SAndroid Build Coastguard Worker * '' (nothing), match on exactly number
2027*79398b25SAndroid Build Coastguard Worker * [size] is either:
2028*79398b25SAndroid Build Coastguard Worker * '' (nothing), number
2029*79398b25SAndroid Build Coastguard Worker * 'k' or 'K', number * 2^10
2030*79398b25SAndroid Build Coastguard Worker * 'm' or 'M', number * 2^20
2031*79398b25SAndroid Build Coastguard Worker * 'g' or 'G', number * 2^30
2032*79398b25SAndroid Build Coastguard Worker */
parse_number(char * start,long long * size,int * range,char ** error)2033*79398b25SAndroid Build Coastguard Worker static int parse_number(char *start, long long *size, int *range, char **error)
2034*79398b25SAndroid Build Coastguard Worker {
2035*79398b25SAndroid Build Coastguard Worker char *end;
2036*79398b25SAndroid Build Coastguard Worker long long number;
2037*79398b25SAndroid Build Coastguard Worker
2038*79398b25SAndroid Build Coastguard Worker if (*start == '>' || *start == '+') {
2039*79398b25SAndroid Build Coastguard Worker *range = NUM_GREATER;
2040*79398b25SAndroid Build Coastguard Worker start ++;
2041*79398b25SAndroid Build Coastguard Worker } else if (*start == '<' || *start == '-') {
2042*79398b25SAndroid Build Coastguard Worker *range = NUM_LESS;
2043*79398b25SAndroid Build Coastguard Worker start ++;
2044*79398b25SAndroid Build Coastguard Worker } else
2045*79398b25SAndroid Build Coastguard Worker *range = NUM_EQ;
2046*79398b25SAndroid Build Coastguard Worker
2047*79398b25SAndroid Build Coastguard Worker errno = 0; /* To enable failure after call to be determined */
2048*79398b25SAndroid Build Coastguard Worker number = strtoll(start, &end, 10);
2049*79398b25SAndroid Build Coastguard Worker
2050*79398b25SAndroid Build Coastguard Worker if((errno == ERANGE && (number == LLONG_MAX || number == LLONG_MIN))
2051*79398b25SAndroid Build Coastguard Worker || (errno != 0 && number == 0)) {
2052*79398b25SAndroid Build Coastguard Worker /* long long underflow or overflow in conversion, or other
2053*79398b25SAndroid Build Coastguard Worker * conversion error.
2054*79398b25SAndroid Build Coastguard Worker * Note: we don't check for LLONG_MIN and LLONG_MAX only
2055*79398b25SAndroid Build Coastguard Worker * because strtoll can validly return that if the
2056*79398b25SAndroid Build Coastguard Worker * user used these values
2057*79398b25SAndroid Build Coastguard Worker */
2058*79398b25SAndroid Build Coastguard Worker *error = "Long long underflow, overflow or other conversion "
2059*79398b25SAndroid Build Coastguard Worker "error";
2060*79398b25SAndroid Build Coastguard Worker return 0;
2061*79398b25SAndroid Build Coastguard Worker }
2062*79398b25SAndroid Build Coastguard Worker
2063*79398b25SAndroid Build Coastguard Worker if (end == start) {
2064*79398b25SAndroid Build Coastguard Worker /* Couldn't read any number */
2065*79398b25SAndroid Build Coastguard Worker *error = "Number expected";
2066*79398b25SAndroid Build Coastguard Worker return 0;
2067*79398b25SAndroid Build Coastguard Worker }
2068*79398b25SAndroid Build Coastguard Worker
2069*79398b25SAndroid Build Coastguard Worker switch (end[0]) {
2070*79398b25SAndroid Build Coastguard Worker case 'g':
2071*79398b25SAndroid Build Coastguard Worker case 'G':
2072*79398b25SAndroid Build Coastguard Worker number *= 1024;
2073*79398b25SAndroid Build Coastguard Worker case 'm':
2074*79398b25SAndroid Build Coastguard Worker case 'M':
2075*79398b25SAndroid Build Coastguard Worker number *= 1024;
2076*79398b25SAndroid Build Coastguard Worker case 'k':
2077*79398b25SAndroid Build Coastguard Worker case 'K':
2078*79398b25SAndroid Build Coastguard Worker number *= 1024;
2079*79398b25SAndroid Build Coastguard Worker
2080*79398b25SAndroid Build Coastguard Worker if (end[1] != '\0') {
2081*79398b25SAndroid Build Coastguard Worker *error = "Trailing junk after size specifier";
2082*79398b25SAndroid Build Coastguard Worker return 0;
2083*79398b25SAndroid Build Coastguard Worker }
2084*79398b25SAndroid Build Coastguard Worker
2085*79398b25SAndroid Build Coastguard Worker break;
2086*79398b25SAndroid Build Coastguard Worker case '\0':
2087*79398b25SAndroid Build Coastguard Worker break;
2088*79398b25SAndroid Build Coastguard Worker default:
2089*79398b25SAndroid Build Coastguard Worker *error = "Trailing junk after number";
2090*79398b25SAndroid Build Coastguard Worker return 0;
2091*79398b25SAndroid Build Coastguard Worker }
2092*79398b25SAndroid Build Coastguard Worker
2093*79398b25SAndroid Build Coastguard Worker *size = number;
2094*79398b25SAndroid Build Coastguard Worker
2095*79398b25SAndroid Build Coastguard Worker return 1;
2096*79398b25SAndroid Build Coastguard Worker }
2097*79398b25SAndroid Build Coastguard Worker
2098*79398b25SAndroid Build Coastguard Worker
parse_number_arg(struct test_entry * test,struct atom * atom)2099*79398b25SAndroid Build Coastguard Worker static int parse_number_arg(struct test_entry *test, struct atom *atom)
2100*79398b25SAndroid Build Coastguard Worker {
2101*79398b25SAndroid Build Coastguard Worker struct test_number_arg *number;
2102*79398b25SAndroid Build Coastguard Worker long long size;
2103*79398b25SAndroid Build Coastguard Worker int range;
2104*79398b25SAndroid Build Coastguard Worker char *error;
2105*79398b25SAndroid Build Coastguard Worker int res = parse_number(atom->argv[0], &size, &range, &error);
2106*79398b25SAndroid Build Coastguard Worker
2107*79398b25SAndroid Build Coastguard Worker if (res == 0) {
2108*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "%s\n", error);
2109*79398b25SAndroid Build Coastguard Worker return 0;
2110*79398b25SAndroid Build Coastguard Worker }
2111*79398b25SAndroid Build Coastguard Worker
2112*79398b25SAndroid Build Coastguard Worker number = malloc(sizeof(*number));
2113*79398b25SAndroid Build Coastguard Worker if (number == NULL)
2114*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2115*79398b25SAndroid Build Coastguard Worker
2116*79398b25SAndroid Build Coastguard Worker number->range = range;
2117*79398b25SAndroid Build Coastguard Worker number->size = size;
2118*79398b25SAndroid Build Coastguard Worker
2119*79398b25SAndroid Build Coastguard Worker atom->data = number;
2120*79398b25SAndroid Build Coastguard Worker
2121*79398b25SAndroid Build Coastguard Worker return 1;
2122*79398b25SAndroid Build Coastguard Worker }
2123*79398b25SAndroid Build Coastguard Worker
2124*79398b25SAndroid Build Coastguard Worker
parse_range_args(struct test_entry * test,struct atom * atom)2125*79398b25SAndroid Build Coastguard Worker static int parse_range_args(struct test_entry *test, struct atom *atom)
2126*79398b25SAndroid Build Coastguard Worker {
2127*79398b25SAndroid Build Coastguard Worker struct test_range_args *range;
2128*79398b25SAndroid Build Coastguard Worker long long start, end;
2129*79398b25SAndroid Build Coastguard Worker int type;
2130*79398b25SAndroid Build Coastguard Worker int res;
2131*79398b25SAndroid Build Coastguard Worker char *error;
2132*79398b25SAndroid Build Coastguard Worker
2133*79398b25SAndroid Build Coastguard Worker res = parse_number(atom->argv[0], &start, &type, &error);
2134*79398b25SAndroid Build Coastguard Worker if (res == 0) {
2135*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "%s\n", error);
2136*79398b25SAndroid Build Coastguard Worker return 0;
2137*79398b25SAndroid Build Coastguard Worker }
2138*79398b25SAndroid Build Coastguard Worker
2139*79398b25SAndroid Build Coastguard Worker if (type != NUM_EQ) {
2140*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "Range specifier (<, >, -, +) not "
2141*79398b25SAndroid Build Coastguard Worker "expected\n");
2142*79398b25SAndroid Build Coastguard Worker return 0;
2143*79398b25SAndroid Build Coastguard Worker }
2144*79398b25SAndroid Build Coastguard Worker
2145*79398b25SAndroid Build Coastguard Worker res = parse_number(atom->argv[1], &end, &type, &error);
2146*79398b25SAndroid Build Coastguard Worker if (res == 0) {
2147*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "%s\n", error);
2148*79398b25SAndroid Build Coastguard Worker return 0;
2149*79398b25SAndroid Build Coastguard Worker }
2150*79398b25SAndroid Build Coastguard Worker
2151*79398b25SAndroid Build Coastguard Worker if (type != NUM_EQ) {
2152*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "Range specifier (<, >, -, +) not "
2153*79398b25SAndroid Build Coastguard Worker "expected\n");
2154*79398b25SAndroid Build Coastguard Worker return 0;
2155*79398b25SAndroid Build Coastguard Worker }
2156*79398b25SAndroid Build Coastguard Worker
2157*79398b25SAndroid Build Coastguard Worker range = malloc(sizeof(*range));
2158*79398b25SAndroid Build Coastguard Worker if (range == NULL)
2159*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2160*79398b25SAndroid Build Coastguard Worker
2161*79398b25SAndroid Build Coastguard Worker range->start = start;
2162*79398b25SAndroid Build Coastguard Worker range->end = end;
2163*79398b25SAndroid Build Coastguard Worker
2164*79398b25SAndroid Build Coastguard Worker atom->data = range;
2165*79398b25SAndroid Build Coastguard Worker
2166*79398b25SAndroid Build Coastguard Worker return 1;
2167*79398b25SAndroid Build Coastguard Worker }
2168*79398b25SAndroid Build Coastguard Worker
2169*79398b25SAndroid Build Coastguard Worker
2170*79398b25SAndroid Build Coastguard Worker /*
2171*79398b25SAndroid Build Coastguard Worker * Generic test code macro
2172*79398b25SAndroid Build Coastguard Worker */
2173*79398b25SAndroid Build Coastguard Worker #define TEST_FN(NAME, MATCH, CODE) \
2174*79398b25SAndroid Build Coastguard Worker static int NAME##_fn(struct atom *atom, struct action_data *action_data) \
2175*79398b25SAndroid Build Coastguard Worker { \
2176*79398b25SAndroid Build Coastguard Worker /* test operates on MATCH file types only */ \
2177*79398b25SAndroid Build Coastguard Worker if (!file_type_match(action_data->buf->st_mode, MATCH)) \
2178*79398b25SAndroid Build Coastguard Worker return 0; \
2179*79398b25SAndroid Build Coastguard Worker \
2180*79398b25SAndroid Build Coastguard Worker CODE \
2181*79398b25SAndroid Build Coastguard Worker }
2182*79398b25SAndroid Build Coastguard Worker
2183*79398b25SAndroid Build Coastguard Worker /*
2184*79398b25SAndroid Build Coastguard Worker * Generic test code macro testing VAR for size (eq, less than, greater than)
2185*79398b25SAndroid Build Coastguard Worker */
2186*79398b25SAndroid Build Coastguard Worker #define TEST_VAR_FN(NAME, MATCH, VAR) TEST_FN(NAME, MATCH, \
2187*79398b25SAndroid Build Coastguard Worker { \
2188*79398b25SAndroid Build Coastguard Worker int match = 0; \
2189*79398b25SAndroid Build Coastguard Worker struct test_number_arg *number = atom->data; \
2190*79398b25SAndroid Build Coastguard Worker \
2191*79398b25SAndroid Build Coastguard Worker switch (number->range) { \
2192*79398b25SAndroid Build Coastguard Worker case NUM_EQ: \
2193*79398b25SAndroid Build Coastguard Worker match = VAR == number->size; \
2194*79398b25SAndroid Build Coastguard Worker break; \
2195*79398b25SAndroid Build Coastguard Worker case NUM_LESS: \
2196*79398b25SAndroid Build Coastguard Worker match = VAR < number->size; \
2197*79398b25SAndroid Build Coastguard Worker break; \
2198*79398b25SAndroid Build Coastguard Worker case NUM_GREATER: \
2199*79398b25SAndroid Build Coastguard Worker match = VAR > number->size; \
2200*79398b25SAndroid Build Coastguard Worker break; \
2201*79398b25SAndroid Build Coastguard Worker } \
2202*79398b25SAndroid Build Coastguard Worker \
2203*79398b25SAndroid Build Coastguard Worker return match; \
2204*79398b25SAndroid Build Coastguard Worker })
2205*79398b25SAndroid Build Coastguard Worker
2206*79398b25SAndroid Build Coastguard Worker
2207*79398b25SAndroid Build Coastguard Worker /*
2208*79398b25SAndroid Build Coastguard Worker * Generic test code macro testing VAR for range [x, y] (value between x and y
2209*79398b25SAndroid Build Coastguard Worker * inclusive).
2210*79398b25SAndroid Build Coastguard Worker */
2211*79398b25SAndroid Build Coastguard Worker #define TEST_VAR_RANGE_FN(NAME, MATCH, VAR) TEST_FN(NAME##_range, MATCH, \
2212*79398b25SAndroid Build Coastguard Worker { \
2213*79398b25SAndroid Build Coastguard Worker struct test_range_args *range = atom->data; \
2214*79398b25SAndroid Build Coastguard Worker \
2215*79398b25SAndroid Build Coastguard Worker return range->start <= VAR && VAR <= range->end; \
2216*79398b25SAndroid Build Coastguard Worker })
2217*79398b25SAndroid Build Coastguard Worker
2218*79398b25SAndroid Build Coastguard Worker
2219*79398b25SAndroid Build Coastguard Worker /*
2220*79398b25SAndroid Build Coastguard Worker * Name, Pathname and Subpathname test specific code
2221*79398b25SAndroid Build Coastguard Worker */
2222*79398b25SAndroid Build Coastguard Worker
2223*79398b25SAndroid Build Coastguard Worker /*
2224*79398b25SAndroid Build Coastguard Worker * Add a leading "/" if subpathname and pathname lacks it
2225*79398b25SAndroid Build Coastguard Worker */
check_pathname(struct test_entry * test,struct atom * atom)2226*79398b25SAndroid Build Coastguard Worker static int check_pathname(struct test_entry *test, struct atom *atom)
2227*79398b25SAndroid Build Coastguard Worker {
2228*79398b25SAndroid Build Coastguard Worker int res;
2229*79398b25SAndroid Build Coastguard Worker char *name;
2230*79398b25SAndroid Build Coastguard Worker
2231*79398b25SAndroid Build Coastguard Worker if(atom->argv[0][0] != '/') {
2232*79398b25SAndroid Build Coastguard Worker res = asprintf(&name, "/%s", atom->argv[0]);
2233*79398b25SAndroid Build Coastguard Worker if(res == -1)
2234*79398b25SAndroid Build Coastguard Worker BAD_ERROR("asprintf failed in check_pathname\n");
2235*79398b25SAndroid Build Coastguard Worker
2236*79398b25SAndroid Build Coastguard Worker free(atom->argv[0]);
2237*79398b25SAndroid Build Coastguard Worker atom->argv[0] = name;
2238*79398b25SAndroid Build Coastguard Worker }
2239*79398b25SAndroid Build Coastguard Worker
2240*79398b25SAndroid Build Coastguard Worker return 1;
2241*79398b25SAndroid Build Coastguard Worker }
2242*79398b25SAndroid Build Coastguard Worker
2243*79398b25SAndroid Build Coastguard Worker
2244*79398b25SAndroid Build Coastguard Worker TEST_FN(name, ACTION_ALL_LNK, \
2245*79398b25SAndroid Build Coastguard Worker return fnmatch(atom->argv[0], action_data->name,
2246*79398b25SAndroid Build Coastguard Worker FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0;)
2247*79398b25SAndroid Build Coastguard Worker
2248*79398b25SAndroid Build Coastguard Worker TEST_FN(pathname, ACTION_ALL_LNK, \
2249*79398b25SAndroid Build Coastguard Worker return fnmatch(atom->argv[0], action_data->subpath,
2250*79398b25SAndroid Build Coastguard Worker FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0;)
2251*79398b25SAndroid Build Coastguard Worker
2252*79398b25SAndroid Build Coastguard Worker
count_components(char * path)2253*79398b25SAndroid Build Coastguard Worker static int count_components(char *path)
2254*79398b25SAndroid Build Coastguard Worker {
2255*79398b25SAndroid Build Coastguard Worker int count;
2256*79398b25SAndroid Build Coastguard Worker
2257*79398b25SAndroid Build Coastguard Worker for (count = 0; *path != '\0'; count ++) {
2258*79398b25SAndroid Build Coastguard Worker while (*path == '/')
2259*79398b25SAndroid Build Coastguard Worker path ++;
2260*79398b25SAndroid Build Coastguard Worker
2261*79398b25SAndroid Build Coastguard Worker while (*path != '\0' && *path != '/')
2262*79398b25SAndroid Build Coastguard Worker path ++;
2263*79398b25SAndroid Build Coastguard Worker }
2264*79398b25SAndroid Build Coastguard Worker
2265*79398b25SAndroid Build Coastguard Worker return count;
2266*79398b25SAndroid Build Coastguard Worker }
2267*79398b25SAndroid Build Coastguard Worker
2268*79398b25SAndroid Build Coastguard Worker
get_start(char * s,int n)2269*79398b25SAndroid Build Coastguard Worker static char *get_start(char *s, int n)
2270*79398b25SAndroid Build Coastguard Worker {
2271*79398b25SAndroid Build Coastguard Worker int count;
2272*79398b25SAndroid Build Coastguard Worker char *path = s;
2273*79398b25SAndroid Build Coastguard Worker
2274*79398b25SAndroid Build Coastguard Worker for (count = 0; *path != '\0' && count < n; count ++) {
2275*79398b25SAndroid Build Coastguard Worker while (*path == '/')
2276*79398b25SAndroid Build Coastguard Worker path ++;
2277*79398b25SAndroid Build Coastguard Worker
2278*79398b25SAndroid Build Coastguard Worker while (*path != '\0' && *path != '/')
2279*79398b25SAndroid Build Coastguard Worker path ++;
2280*79398b25SAndroid Build Coastguard Worker }
2281*79398b25SAndroid Build Coastguard Worker
2282*79398b25SAndroid Build Coastguard Worker if (count == n)
2283*79398b25SAndroid Build Coastguard Worker *path = '\0';
2284*79398b25SAndroid Build Coastguard Worker
2285*79398b25SAndroid Build Coastguard Worker return s;
2286*79398b25SAndroid Build Coastguard Worker }
2287*79398b25SAndroid Build Coastguard Worker
2288*79398b25SAndroid Build Coastguard Worker
subpathname_fn(struct atom * atom,struct action_data * action_data)2289*79398b25SAndroid Build Coastguard Worker static int subpathname_fn(struct atom *atom, struct action_data *action_data)
2290*79398b25SAndroid Build Coastguard Worker {
2291*79398b25SAndroid Build Coastguard Worker char *path = strdup(action_data->subpath);
2292*79398b25SAndroid Build Coastguard Worker int is_match = fnmatch(atom->argv[0], get_start(path,
2293*79398b25SAndroid Build Coastguard Worker count_components(atom->argv[0])),
2294*79398b25SAndroid Build Coastguard Worker FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0;
2295*79398b25SAndroid Build Coastguard Worker free(path);
2296*79398b25SAndroid Build Coastguard Worker return is_match;
2297*79398b25SAndroid Build Coastguard Worker }
2298*79398b25SAndroid Build Coastguard Worker
2299*79398b25SAndroid Build Coastguard Worker /*
2300*79398b25SAndroid Build Coastguard Worker * Inode attribute test operations using generic
2301*79398b25SAndroid Build Coastguard Worker * TEST_VAR_FN(test name, file scope, attribute name) macro.
2302*79398b25SAndroid Build Coastguard Worker * This is for tests that do not need to be specially handled in any way.
2303*79398b25SAndroid Build Coastguard Worker * They just take a variable and compare it against a number.
2304*79398b25SAndroid Build Coastguard Worker */
2305*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(filesize, ACTION_REG, action_data->buf->st_size)
2306*79398b25SAndroid Build Coastguard Worker
2307*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(dirsize, ACTION_DIR, action_data->buf->st_size)
2308*79398b25SAndroid Build Coastguard Worker
2309*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(size, ACTION_ALL_LNK, action_data->buf->st_size)
2310*79398b25SAndroid Build Coastguard Worker
2311*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(inode, ACTION_ALL_LNK, action_data->buf->st_ino)
2312*79398b25SAndroid Build Coastguard Worker
2313*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(nlink, ACTION_ALL_LNK, action_data->buf->st_nlink)
2314*79398b25SAndroid Build Coastguard Worker
2315*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(fileblocks, ACTION_REG, action_data->buf->st_blocks)
2316*79398b25SAndroid Build Coastguard Worker
2317*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(dirblocks, ACTION_DIR, action_data->buf->st_blocks)
2318*79398b25SAndroid Build Coastguard Worker
2319*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(blocks, ACTION_ALL_LNK, action_data->buf->st_blocks)
2320*79398b25SAndroid Build Coastguard Worker
2321*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(dircount, ACTION_DIR, action_data->dir_ent->dir->count)
2322*79398b25SAndroid Build Coastguard Worker
2323*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(depth, ACTION_ALL_LNK, action_data->depth)
2324*79398b25SAndroid Build Coastguard Worker
2325*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(filesize, ACTION_REG, action_data->buf->st_size)
2326*79398b25SAndroid Build Coastguard Worker
2327*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(dirsize, ACTION_DIR, action_data->buf->st_size)
2328*79398b25SAndroid Build Coastguard Worker
2329*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(size, ACTION_ALL_LNK, action_data->buf->st_size)
2330*79398b25SAndroid Build Coastguard Worker
2331*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(inode, ACTION_ALL_LNK, action_data->buf->st_ino)
2332*79398b25SAndroid Build Coastguard Worker
2333*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(nlink, ACTION_ALL_LNK, action_data->buf->st_nlink)
2334*79398b25SAndroid Build Coastguard Worker
2335*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(fileblocks, ACTION_REG, action_data->buf->st_blocks)
2336*79398b25SAndroid Build Coastguard Worker
2337*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(dirblocks, ACTION_DIR, action_data->buf->st_blocks)
2338*79398b25SAndroid Build Coastguard Worker
2339*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(blocks, ACTION_ALL_LNK, action_data->buf->st_blocks)
2340*79398b25SAndroid Build Coastguard Worker
2341*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(gid, ACTION_ALL_LNK, action_data->buf->st_gid)
2342*79398b25SAndroid Build Coastguard Worker
2343*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(uid, ACTION_ALL_LNK, action_data->buf->st_uid)
2344*79398b25SAndroid Build Coastguard Worker
2345*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(depth, ACTION_ALL_LNK, action_data->depth)
2346*79398b25SAndroid Build Coastguard Worker
2347*79398b25SAndroid Build Coastguard Worker TEST_VAR_RANGE_FN(dircount, ACTION_DIR, action_data->dir_ent->dir->count)
2348*79398b25SAndroid Build Coastguard Worker
2349*79398b25SAndroid Build Coastguard Worker /*
2350*79398b25SAndroid Build Coastguard Worker * uid specific test code
2351*79398b25SAndroid Build Coastguard Worker */
2352*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(uid, ACTION_ALL_LNK, action_data->buf->st_uid)
2353*79398b25SAndroid Build Coastguard Worker
parse_uid_arg(struct test_entry * test,struct atom * atom)2354*79398b25SAndroid Build Coastguard Worker static int parse_uid_arg(struct test_entry *test, struct atom *atom)
2355*79398b25SAndroid Build Coastguard Worker {
2356*79398b25SAndroid Build Coastguard Worker struct test_number_arg *number;
2357*79398b25SAndroid Build Coastguard Worker long long size;
2358*79398b25SAndroid Build Coastguard Worker int range;
2359*79398b25SAndroid Build Coastguard Worker char *error;
2360*79398b25SAndroid Build Coastguard Worker
2361*79398b25SAndroid Build Coastguard Worker if(parse_number(atom->argv[0], &size, &range, &error)) {
2362*79398b25SAndroid Build Coastguard Worker /* managed to fully parse argument as a number */
2363*79398b25SAndroid Build Coastguard Worker if(size < 0 || size > (((long long) 1 << 32) - 1)) {
2364*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "Numeric uid out of "
2365*79398b25SAndroid Build Coastguard Worker "range\n");
2366*79398b25SAndroid Build Coastguard Worker return 0;
2367*79398b25SAndroid Build Coastguard Worker }
2368*79398b25SAndroid Build Coastguard Worker } else {
2369*79398b25SAndroid Build Coastguard Worker /* couldn't parse (fully) as a number, is it a user name? */
2370*79398b25SAndroid Build Coastguard Worker struct passwd *uid = getpwnam(atom->argv[0]);
2371*79398b25SAndroid Build Coastguard Worker if(uid) {
2372*79398b25SAndroid Build Coastguard Worker size = uid->pw_uid;
2373*79398b25SAndroid Build Coastguard Worker range = NUM_EQ;
2374*79398b25SAndroid Build Coastguard Worker } else {
2375*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "Invalid uid or unknown "
2376*79398b25SAndroid Build Coastguard Worker "user\n");
2377*79398b25SAndroid Build Coastguard Worker return 0;
2378*79398b25SAndroid Build Coastguard Worker }
2379*79398b25SAndroid Build Coastguard Worker }
2380*79398b25SAndroid Build Coastguard Worker
2381*79398b25SAndroid Build Coastguard Worker number = malloc(sizeof(*number));
2382*79398b25SAndroid Build Coastguard Worker if(number == NULL)
2383*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2384*79398b25SAndroid Build Coastguard Worker
2385*79398b25SAndroid Build Coastguard Worker number->range = range;
2386*79398b25SAndroid Build Coastguard Worker number->size= size;
2387*79398b25SAndroid Build Coastguard Worker
2388*79398b25SAndroid Build Coastguard Worker atom->data = number;
2389*79398b25SAndroid Build Coastguard Worker
2390*79398b25SAndroid Build Coastguard Worker return 1;
2391*79398b25SAndroid Build Coastguard Worker }
2392*79398b25SAndroid Build Coastguard Worker
2393*79398b25SAndroid Build Coastguard Worker
2394*79398b25SAndroid Build Coastguard Worker /*
2395*79398b25SAndroid Build Coastguard Worker * gid specific test code
2396*79398b25SAndroid Build Coastguard Worker */
2397*79398b25SAndroid Build Coastguard Worker TEST_VAR_FN(gid, ACTION_ALL_LNK, action_data->buf->st_gid)
2398*79398b25SAndroid Build Coastguard Worker
parse_gid_arg(struct test_entry * test,struct atom * atom)2399*79398b25SAndroid Build Coastguard Worker static int parse_gid_arg(struct test_entry *test, struct atom *atom)
2400*79398b25SAndroid Build Coastguard Worker {
2401*79398b25SAndroid Build Coastguard Worker struct test_number_arg *number;
2402*79398b25SAndroid Build Coastguard Worker long long size;
2403*79398b25SAndroid Build Coastguard Worker int range;
2404*79398b25SAndroid Build Coastguard Worker char *error;
2405*79398b25SAndroid Build Coastguard Worker
2406*79398b25SAndroid Build Coastguard Worker if(parse_number(atom->argv[0], &size, &range, &error)) {
2407*79398b25SAndroid Build Coastguard Worker /* managed to fully parse argument as a number */
2408*79398b25SAndroid Build Coastguard Worker if(size < 0 || size > (((long long) 1 << 32) - 1)) {
2409*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "Numeric gid out of "
2410*79398b25SAndroid Build Coastguard Worker "range\n");
2411*79398b25SAndroid Build Coastguard Worker return 0;
2412*79398b25SAndroid Build Coastguard Worker }
2413*79398b25SAndroid Build Coastguard Worker } else {
2414*79398b25SAndroid Build Coastguard Worker /* couldn't parse (fully) as a number, is it a group name? */
2415*79398b25SAndroid Build Coastguard Worker struct group *gid = getgrnam(atom->argv[0]);
2416*79398b25SAndroid Build Coastguard Worker if(gid) {
2417*79398b25SAndroid Build Coastguard Worker size = gid->gr_gid;
2418*79398b25SAndroid Build Coastguard Worker range = NUM_EQ;
2419*79398b25SAndroid Build Coastguard Worker } else {
2420*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 1, "Invalid gid or unknown "
2421*79398b25SAndroid Build Coastguard Worker "group\n");
2422*79398b25SAndroid Build Coastguard Worker return 0;
2423*79398b25SAndroid Build Coastguard Worker }
2424*79398b25SAndroid Build Coastguard Worker }
2425*79398b25SAndroid Build Coastguard Worker
2426*79398b25SAndroid Build Coastguard Worker number = malloc(sizeof(*number));
2427*79398b25SAndroid Build Coastguard Worker if(number == NULL)
2428*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2429*79398b25SAndroid Build Coastguard Worker
2430*79398b25SAndroid Build Coastguard Worker number->range = range;
2431*79398b25SAndroid Build Coastguard Worker number->size= size;
2432*79398b25SAndroid Build Coastguard Worker
2433*79398b25SAndroid Build Coastguard Worker atom->data = number;
2434*79398b25SAndroid Build Coastguard Worker
2435*79398b25SAndroid Build Coastguard Worker return 1;
2436*79398b25SAndroid Build Coastguard Worker }
2437*79398b25SAndroid Build Coastguard Worker
2438*79398b25SAndroid Build Coastguard Worker
2439*79398b25SAndroid Build Coastguard Worker /*
2440*79398b25SAndroid Build Coastguard Worker * Type test specific code
2441*79398b25SAndroid Build Coastguard Worker */
2442*79398b25SAndroid Build Coastguard Worker struct type_entry type_table[] = {
2443*79398b25SAndroid Build Coastguard Worker { S_IFSOCK, 's' },
2444*79398b25SAndroid Build Coastguard Worker { S_IFLNK, 'l' },
2445*79398b25SAndroid Build Coastguard Worker { S_IFREG, 'f' },
2446*79398b25SAndroid Build Coastguard Worker { S_IFBLK, 'b' },
2447*79398b25SAndroid Build Coastguard Worker { S_IFDIR, 'd' },
2448*79398b25SAndroid Build Coastguard Worker { S_IFCHR, 'c' },
2449*79398b25SAndroid Build Coastguard Worker { S_IFIFO, 'p' },
2450*79398b25SAndroid Build Coastguard Worker { 0, 0 },
2451*79398b25SAndroid Build Coastguard Worker };
2452*79398b25SAndroid Build Coastguard Worker
2453*79398b25SAndroid Build Coastguard Worker
parse_type_arg(struct test_entry * test,struct atom * atom)2454*79398b25SAndroid Build Coastguard Worker static int parse_type_arg(struct test_entry *test, struct atom *atom)
2455*79398b25SAndroid Build Coastguard Worker {
2456*79398b25SAndroid Build Coastguard Worker int i;
2457*79398b25SAndroid Build Coastguard Worker
2458*79398b25SAndroid Build Coastguard Worker if (strlen(atom->argv[0]) != 1)
2459*79398b25SAndroid Build Coastguard Worker goto failed;
2460*79398b25SAndroid Build Coastguard Worker
2461*79398b25SAndroid Build Coastguard Worker for(i = 0; type_table[i].type != 0; i++)
2462*79398b25SAndroid Build Coastguard Worker if (type_table[i].type == atom->argv[0][0])
2463*79398b25SAndroid Build Coastguard Worker break;
2464*79398b25SAndroid Build Coastguard Worker
2465*79398b25SAndroid Build Coastguard Worker atom->data = &type_table[i];
2466*79398b25SAndroid Build Coastguard Worker
2467*79398b25SAndroid Build Coastguard Worker if(type_table[i].type != 0)
2468*79398b25SAndroid Build Coastguard Worker return 1;
2469*79398b25SAndroid Build Coastguard Worker
2470*79398b25SAndroid Build Coastguard Worker failed:
2471*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "Unexpected file type, expected 'f', 'd', "
2472*79398b25SAndroid Build Coastguard Worker "'c', 'b', 'l', 's' or 'p'\n");
2473*79398b25SAndroid Build Coastguard Worker return 0;
2474*79398b25SAndroid Build Coastguard Worker }
2475*79398b25SAndroid Build Coastguard Worker
2476*79398b25SAndroid Build Coastguard Worker
type_fn(struct atom * atom,struct action_data * action_data)2477*79398b25SAndroid Build Coastguard Worker static int type_fn(struct atom *atom, struct action_data *action_data)
2478*79398b25SAndroid Build Coastguard Worker {
2479*79398b25SAndroid Build Coastguard Worker struct type_entry *type = atom->data;
2480*79398b25SAndroid Build Coastguard Worker
2481*79398b25SAndroid Build Coastguard Worker return (action_data->buf->st_mode & S_IFMT) == type->value;
2482*79398b25SAndroid Build Coastguard Worker }
2483*79398b25SAndroid Build Coastguard Worker
2484*79398b25SAndroid Build Coastguard Worker
2485*79398b25SAndroid Build Coastguard Worker /*
2486*79398b25SAndroid Build Coastguard Worker * True test specific code
2487*79398b25SAndroid Build Coastguard Worker */
true_fn(struct atom * atom,struct action_data * action_data)2488*79398b25SAndroid Build Coastguard Worker static int true_fn(struct atom *atom, struct action_data *action_data)
2489*79398b25SAndroid Build Coastguard Worker {
2490*79398b25SAndroid Build Coastguard Worker return 1;
2491*79398b25SAndroid Build Coastguard Worker }
2492*79398b25SAndroid Build Coastguard Worker
2493*79398b25SAndroid Build Coastguard Worker
2494*79398b25SAndroid Build Coastguard Worker /*
2495*79398b25SAndroid Build Coastguard Worker * False test specific code
2496*79398b25SAndroid Build Coastguard Worker */
false_fn(struct atom * atom,struct action_data * action_data)2497*79398b25SAndroid Build Coastguard Worker static int false_fn(struct atom *atom, struct action_data *action_data)
2498*79398b25SAndroid Build Coastguard Worker {
2499*79398b25SAndroid Build Coastguard Worker return 0;
2500*79398b25SAndroid Build Coastguard Worker }
2501*79398b25SAndroid Build Coastguard Worker
2502*79398b25SAndroid Build Coastguard Worker
2503*79398b25SAndroid Build Coastguard Worker /*
2504*79398b25SAndroid Build Coastguard Worker * File test specific code
2505*79398b25SAndroid Build Coastguard Worker */
parse_file_arg(struct test_entry * test,struct atom * atom)2506*79398b25SAndroid Build Coastguard Worker static int parse_file_arg(struct test_entry *test, struct atom *atom)
2507*79398b25SAndroid Build Coastguard Worker {
2508*79398b25SAndroid Build Coastguard Worker int res;
2509*79398b25SAndroid Build Coastguard Worker regex_t *preg = malloc(sizeof(regex_t));
2510*79398b25SAndroid Build Coastguard Worker
2511*79398b25SAndroid Build Coastguard Worker if (preg == NULL)
2512*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2513*79398b25SAndroid Build Coastguard Worker
2514*79398b25SAndroid Build Coastguard Worker res = regcomp(preg, atom->argv[0], REG_EXTENDED);
2515*79398b25SAndroid Build Coastguard Worker if (res) {
2516*79398b25SAndroid Build Coastguard Worker char str[1024]; /* overflow safe */
2517*79398b25SAndroid Build Coastguard Worker
2518*79398b25SAndroid Build Coastguard Worker regerror(res, preg, str, 1024);
2519*79398b25SAndroid Build Coastguard Worker free(preg);
2520*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "invalid regex \"%s\" because "
2521*79398b25SAndroid Build Coastguard Worker "\"%s\"\n", atom->argv[0], str);
2522*79398b25SAndroid Build Coastguard Worker return 0;
2523*79398b25SAndroid Build Coastguard Worker }
2524*79398b25SAndroid Build Coastguard Worker
2525*79398b25SAndroid Build Coastguard Worker atom->data = preg;
2526*79398b25SAndroid Build Coastguard Worker
2527*79398b25SAndroid Build Coastguard Worker return 1;
2528*79398b25SAndroid Build Coastguard Worker }
2529*79398b25SAndroid Build Coastguard Worker
2530*79398b25SAndroid Build Coastguard Worker
file_fn(struct atom * atom,struct action_data * action_data)2531*79398b25SAndroid Build Coastguard Worker static int file_fn(struct atom *atom, struct action_data *action_data)
2532*79398b25SAndroid Build Coastguard Worker {
2533*79398b25SAndroid Build Coastguard Worker int child, res, size = 0, status;
2534*79398b25SAndroid Build Coastguard Worker int pipefd[2];
2535*79398b25SAndroid Build Coastguard Worker char *buffer = NULL;
2536*79398b25SAndroid Build Coastguard Worker regex_t *preg = atom->data;
2537*79398b25SAndroid Build Coastguard Worker
2538*79398b25SAndroid Build Coastguard Worker res = pipe(pipefd);
2539*79398b25SAndroid Build Coastguard Worker if (res == -1)
2540*79398b25SAndroid Build Coastguard Worker BAD_ERROR("file_fn pipe failed\n");
2541*79398b25SAndroid Build Coastguard Worker
2542*79398b25SAndroid Build Coastguard Worker child = fork();
2543*79398b25SAndroid Build Coastguard Worker if (child == -1)
2544*79398b25SAndroid Build Coastguard Worker BAD_ERROR("file_fn fork_failed\n");
2545*79398b25SAndroid Build Coastguard Worker
2546*79398b25SAndroid Build Coastguard Worker if (child == 0) {
2547*79398b25SAndroid Build Coastguard Worker /*
2548*79398b25SAndroid Build Coastguard Worker * Child process
2549*79398b25SAndroid Build Coastguard Worker * Connect stdout to pipefd[1] and execute file command
2550*79398b25SAndroid Build Coastguard Worker */
2551*79398b25SAndroid Build Coastguard Worker close(STDOUT_FILENO);
2552*79398b25SAndroid Build Coastguard Worker res = dup(pipefd[1]);
2553*79398b25SAndroid Build Coastguard Worker if (res == -1)
2554*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2555*79398b25SAndroid Build Coastguard Worker
2556*79398b25SAndroid Build Coastguard Worker execlp("file", "file", "-b", action_data->pathname,
2557*79398b25SAndroid Build Coastguard Worker (char *) NULL);
2558*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2559*79398b25SAndroid Build Coastguard Worker }
2560*79398b25SAndroid Build Coastguard Worker
2561*79398b25SAndroid Build Coastguard Worker /*
2562*79398b25SAndroid Build Coastguard Worker * Parent process. Read stdout from file command
2563*79398b25SAndroid Build Coastguard Worker */
2564*79398b25SAndroid Build Coastguard Worker close(pipefd[1]);
2565*79398b25SAndroid Build Coastguard Worker
2566*79398b25SAndroid Build Coastguard Worker do {
2567*79398b25SAndroid Build Coastguard Worker buffer = realloc(buffer, size + 512);
2568*79398b25SAndroid Build Coastguard Worker if (buffer == NULL)
2569*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
2570*79398b25SAndroid Build Coastguard Worker
2571*79398b25SAndroid Build Coastguard Worker res = read_bytes(pipefd[0], buffer + size, 512);
2572*79398b25SAndroid Build Coastguard Worker
2573*79398b25SAndroid Build Coastguard Worker if (res == -1)
2574*79398b25SAndroid Build Coastguard Worker BAD_ERROR("file_fn pipe read error\n");
2575*79398b25SAndroid Build Coastguard Worker
2576*79398b25SAndroid Build Coastguard Worker size += 512;
2577*79398b25SAndroid Build Coastguard Worker
2578*79398b25SAndroid Build Coastguard Worker } while (res == 512);
2579*79398b25SAndroid Build Coastguard Worker
2580*79398b25SAndroid Build Coastguard Worker size = size + res - 512;
2581*79398b25SAndroid Build Coastguard Worker
2582*79398b25SAndroid Build Coastguard Worker buffer[size] = '\0';
2583*79398b25SAndroid Build Coastguard Worker
2584*79398b25SAndroid Build Coastguard Worker res = waitpid(child, &status, 0);
2585*79398b25SAndroid Build Coastguard Worker
2586*79398b25SAndroid Build Coastguard Worker if (res == -1)
2587*79398b25SAndroid Build Coastguard Worker BAD_ERROR("file_fn waitpid failed\n");
2588*79398b25SAndroid Build Coastguard Worker
2589*79398b25SAndroid Build Coastguard Worker if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
2590*79398b25SAndroid Build Coastguard Worker BAD_ERROR("file_fn file returned error\n");
2591*79398b25SAndroid Build Coastguard Worker
2592*79398b25SAndroid Build Coastguard Worker close(pipefd[0]);
2593*79398b25SAndroid Build Coastguard Worker
2594*79398b25SAndroid Build Coastguard Worker res = regexec(preg, buffer, (size_t) 0, NULL, 0);
2595*79398b25SAndroid Build Coastguard Worker
2596*79398b25SAndroid Build Coastguard Worker free(buffer);
2597*79398b25SAndroid Build Coastguard Worker
2598*79398b25SAndroid Build Coastguard Worker return res == 0;
2599*79398b25SAndroid Build Coastguard Worker }
2600*79398b25SAndroid Build Coastguard Worker
2601*79398b25SAndroid Build Coastguard Worker
2602*79398b25SAndroid Build Coastguard Worker /*
2603*79398b25SAndroid Build Coastguard Worker * Exec test specific code
2604*79398b25SAndroid Build Coastguard Worker */
exec_fn(struct atom * atom,struct action_data * action_data)2605*79398b25SAndroid Build Coastguard Worker static int exec_fn(struct atom *atom, struct action_data *action_data)
2606*79398b25SAndroid Build Coastguard Worker {
2607*79398b25SAndroid Build Coastguard Worker int child, i, res, status;
2608*79398b25SAndroid Build Coastguard Worker
2609*79398b25SAndroid Build Coastguard Worker child = fork();
2610*79398b25SAndroid Build Coastguard Worker if (child == -1)
2611*79398b25SAndroid Build Coastguard Worker BAD_ERROR("exec_fn fork_failed\n");
2612*79398b25SAndroid Build Coastguard Worker
2613*79398b25SAndroid Build Coastguard Worker if (child == 0) {
2614*79398b25SAndroid Build Coastguard Worker /*
2615*79398b25SAndroid Build Coastguard Worker * Child process
2616*79398b25SAndroid Build Coastguard Worker * redirect stdin, stdout & stderr to /dev/null and
2617*79398b25SAndroid Build Coastguard Worker * execute atom->argv[0]
2618*79398b25SAndroid Build Coastguard Worker */
2619*79398b25SAndroid Build Coastguard Worker int fd = open("/dev/null", O_RDWR);
2620*79398b25SAndroid Build Coastguard Worker if(fd == -1)
2621*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2622*79398b25SAndroid Build Coastguard Worker
2623*79398b25SAndroid Build Coastguard Worker close(STDIN_FILENO);
2624*79398b25SAndroid Build Coastguard Worker close(STDOUT_FILENO);
2625*79398b25SAndroid Build Coastguard Worker close(STDERR_FILENO);
2626*79398b25SAndroid Build Coastguard Worker for(i = 0; i < 3; i++) {
2627*79398b25SAndroid Build Coastguard Worker res = dup(fd);
2628*79398b25SAndroid Build Coastguard Worker if (res == -1)
2629*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2630*79398b25SAndroid Build Coastguard Worker }
2631*79398b25SAndroid Build Coastguard Worker close(fd);
2632*79398b25SAndroid Build Coastguard Worker
2633*79398b25SAndroid Build Coastguard Worker /*
2634*79398b25SAndroid Build Coastguard Worker * Create environment variables
2635*79398b25SAndroid Build Coastguard Worker * NAME: name of file
2636*79398b25SAndroid Build Coastguard Worker * PATHNAME: pathname of file relative to squashfs root
2637*79398b25SAndroid Build Coastguard Worker * SOURCE_PATHNAME: the pathname of the file in the source
2638*79398b25SAndroid Build Coastguard Worker * directory
2639*79398b25SAndroid Build Coastguard Worker */
2640*79398b25SAndroid Build Coastguard Worker res = setenv("NAME", action_data->name, 1);
2641*79398b25SAndroid Build Coastguard Worker if(res == -1)
2642*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2643*79398b25SAndroid Build Coastguard Worker
2644*79398b25SAndroid Build Coastguard Worker res = setenv("PATHNAME", action_data->subpath, 1);
2645*79398b25SAndroid Build Coastguard Worker if(res == -1)
2646*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2647*79398b25SAndroid Build Coastguard Worker
2648*79398b25SAndroid Build Coastguard Worker res = setenv("SOURCE_PATHNAME", action_data->pathname, 1);
2649*79398b25SAndroid Build Coastguard Worker if(res == -1)
2650*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2651*79398b25SAndroid Build Coastguard Worker
2652*79398b25SAndroid Build Coastguard Worker execl("/bin/sh", "sh", "-c", atom->argv[0], (char *) NULL);
2653*79398b25SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
2654*79398b25SAndroid Build Coastguard Worker }
2655*79398b25SAndroid Build Coastguard Worker
2656*79398b25SAndroid Build Coastguard Worker /*
2657*79398b25SAndroid Build Coastguard Worker * Parent process.
2658*79398b25SAndroid Build Coastguard Worker */
2659*79398b25SAndroid Build Coastguard Worker
2660*79398b25SAndroid Build Coastguard Worker res = waitpid(child, &status, 0);
2661*79398b25SAndroid Build Coastguard Worker
2662*79398b25SAndroid Build Coastguard Worker if (res == -1)
2663*79398b25SAndroid Build Coastguard Worker BAD_ERROR("exec_fn waitpid failed\n");
2664*79398b25SAndroid Build Coastguard Worker
2665*79398b25SAndroid Build Coastguard Worker return WIFEXITED(status) ? WEXITSTATUS(status) == 0 : 0;
2666*79398b25SAndroid Build Coastguard Worker }
2667*79398b25SAndroid Build Coastguard Worker
2668*79398b25SAndroid Build Coastguard Worker
2669*79398b25SAndroid Build Coastguard Worker /*
2670*79398b25SAndroid Build Coastguard Worker * Symbolic link specific test code
2671*79398b25SAndroid Build Coastguard Worker */
2672*79398b25SAndroid Build Coastguard Worker
2673*79398b25SAndroid Build Coastguard Worker /*
2674*79398b25SAndroid Build Coastguard Worker * Walk the supplied pathname and return the directory entry corresponding
2675*79398b25SAndroid Build Coastguard Worker * to the pathname. If any symlinks are encountered whilst walking the
2676*79398b25SAndroid Build Coastguard Worker * pathname, then recursively walk these, to obtain the fully
2677*79398b25SAndroid Build Coastguard Worker * dereferenced canonicalised directory entry.
2678*79398b25SAndroid Build Coastguard Worker *
2679*79398b25SAndroid Build Coastguard Worker * If follow_path fails to walk a pathname either because a component
2680*79398b25SAndroid Build Coastguard Worker * doesn't exist, it is a non directory component when a directory
2681*79398b25SAndroid Build Coastguard Worker * component is expected, a symlink with an absolute path is encountered,
2682*79398b25SAndroid Build Coastguard Worker * or a symlink is encountered which cannot be recursively walked due to
2683*79398b25SAndroid Build Coastguard Worker * the above failures, then return NULL.
2684*79398b25SAndroid Build Coastguard Worker */
follow_path(struct dir_info * dir,char * pathname)2685*79398b25SAndroid Build Coastguard Worker static struct dir_ent *follow_path(struct dir_info *dir, char *pathname)
2686*79398b25SAndroid Build Coastguard Worker {
2687*79398b25SAndroid Build Coastguard Worker char *comp, *path = pathname;
2688*79398b25SAndroid Build Coastguard Worker struct dir_ent *dir_ent = NULL;
2689*79398b25SAndroid Build Coastguard Worker
2690*79398b25SAndroid Build Coastguard Worker /* We cannot follow absolute paths */
2691*79398b25SAndroid Build Coastguard Worker if(pathname[0] == '/')
2692*79398b25SAndroid Build Coastguard Worker return NULL;
2693*79398b25SAndroid Build Coastguard Worker
2694*79398b25SAndroid Build Coastguard Worker for(comp = get_comp(&path); comp; free(comp), comp = get_comp(&path)) {
2695*79398b25SAndroid Build Coastguard Worker if(strcmp(comp, ".") == 0)
2696*79398b25SAndroid Build Coastguard Worker continue;
2697*79398b25SAndroid Build Coastguard Worker
2698*79398b25SAndroid Build Coastguard Worker if(strcmp(comp, "..") == 0) {
2699*79398b25SAndroid Build Coastguard Worker /* Move to parent if we're not in the root directory */
2700*79398b25SAndroid Build Coastguard Worker if(dir->depth > 1) {
2701*79398b25SAndroid Build Coastguard Worker dir = dir->dir_ent->our_dir;
2702*79398b25SAndroid Build Coastguard Worker dir_ent = NULL; /* lazily eval at loop exit */
2703*79398b25SAndroid Build Coastguard Worker continue;
2704*79398b25SAndroid Build Coastguard Worker } else
2705*79398b25SAndroid Build Coastguard Worker /* Failed to walk pathname */
2706*79398b25SAndroid Build Coastguard Worker return NULL;
2707*79398b25SAndroid Build Coastguard Worker }
2708*79398b25SAndroid Build Coastguard Worker
2709*79398b25SAndroid Build Coastguard Worker /* Lookup comp in current directory */
2710*79398b25SAndroid Build Coastguard Worker dir_ent = lookup_comp(comp, dir);
2711*79398b25SAndroid Build Coastguard Worker if(dir_ent == NULL)
2712*79398b25SAndroid Build Coastguard Worker /* Doesn't exist, failed to walk pathname */
2713*79398b25SAndroid Build Coastguard Worker return NULL;
2714*79398b25SAndroid Build Coastguard Worker
2715*79398b25SAndroid Build Coastguard Worker if((dir_ent->inode->buf.st_mode & S_IFMT) == S_IFLNK) {
2716*79398b25SAndroid Build Coastguard Worker /* Symbolic link, try to walk it */
2717*79398b25SAndroid Build Coastguard Worker dir_ent = follow_path(dir, dir_ent->inode->symlink);
2718*79398b25SAndroid Build Coastguard Worker if(dir_ent == NULL)
2719*79398b25SAndroid Build Coastguard Worker /* Failed to follow symlink */
2720*79398b25SAndroid Build Coastguard Worker return NULL;
2721*79398b25SAndroid Build Coastguard Worker }
2722*79398b25SAndroid Build Coastguard Worker
2723*79398b25SAndroid Build Coastguard Worker if((dir_ent->inode->buf.st_mode & S_IFMT) != S_IFDIR)
2724*79398b25SAndroid Build Coastguard Worker /* Cannot walk further */
2725*79398b25SAndroid Build Coastguard Worker break;
2726*79398b25SAndroid Build Coastguard Worker
2727*79398b25SAndroid Build Coastguard Worker dir = dir_ent->dir;
2728*79398b25SAndroid Build Coastguard Worker }
2729*79398b25SAndroid Build Coastguard Worker
2730*79398b25SAndroid Build Coastguard Worker /* We will have exited the loop either because we've processed
2731*79398b25SAndroid Build Coastguard Worker * all the components, which means we've successfully walked the
2732*79398b25SAndroid Build Coastguard Worker * pathname, or because we've hit a non-directory, in which case
2733*79398b25SAndroid Build Coastguard Worker * it's success if this is the leaf component */
2734*79398b25SAndroid Build Coastguard Worker if(comp) {
2735*79398b25SAndroid Build Coastguard Worker free(comp);
2736*79398b25SAndroid Build Coastguard Worker comp = get_comp(&path);
2737*79398b25SAndroid Build Coastguard Worker free(comp);
2738*79398b25SAndroid Build Coastguard Worker if(comp != NULL)
2739*79398b25SAndroid Build Coastguard Worker /* Not a leaf component */
2740*79398b25SAndroid Build Coastguard Worker return NULL;
2741*79398b25SAndroid Build Coastguard Worker } else {
2742*79398b25SAndroid Build Coastguard Worker /* Fully walked pathname, dir_ent contains correct value unless
2743*79398b25SAndroid Build Coastguard Worker * we've walked to the parent ("..") in which case we need
2744*79398b25SAndroid Build Coastguard Worker * to resolve it here */
2745*79398b25SAndroid Build Coastguard Worker if(!dir_ent)
2746*79398b25SAndroid Build Coastguard Worker dir_ent = dir->dir_ent;
2747*79398b25SAndroid Build Coastguard Worker }
2748*79398b25SAndroid Build Coastguard Worker
2749*79398b25SAndroid Build Coastguard Worker return dir_ent;
2750*79398b25SAndroid Build Coastguard Worker }
2751*79398b25SAndroid Build Coastguard Worker
2752*79398b25SAndroid Build Coastguard Worker
exists_fn(struct atom * atom,struct action_data * action_data)2753*79398b25SAndroid Build Coastguard Worker static int exists_fn(struct atom *atom, struct action_data *action_data)
2754*79398b25SAndroid Build Coastguard Worker {
2755*79398b25SAndroid Build Coastguard Worker /*
2756*79398b25SAndroid Build Coastguard Worker * Test if a symlink exists within the output filesystem, that is,
2757*79398b25SAndroid Build Coastguard Worker * the symlink has a relative path, and the relative path refers
2758*79398b25SAndroid Build Coastguard Worker * to an entry within the output filesystem.
2759*79398b25SAndroid Build Coastguard Worker *
2760*79398b25SAndroid Build Coastguard Worker * This test function evaluates the path for symlinks - that is it
2761*79398b25SAndroid Build Coastguard Worker * follows any symlinks in the path (and any symlinks that it contains
2762*79398b25SAndroid Build Coastguard Worker * etc.), to discover the fully dereferenced canonicalised relative
2763*79398b25SAndroid Build Coastguard Worker * path.
2764*79398b25SAndroid Build Coastguard Worker *
2765*79398b25SAndroid Build Coastguard Worker * If any symlinks within the path do not exist or are absolute
2766*79398b25SAndroid Build Coastguard Worker * then the symlink is considered to not exist, as it cannot be
2767*79398b25SAndroid Build Coastguard Worker * fully dereferenced.
2768*79398b25SAndroid Build Coastguard Worker *
2769*79398b25SAndroid Build Coastguard Worker * exists operates on symlinks only, other files by definition
2770*79398b25SAndroid Build Coastguard Worker * exist
2771*79398b25SAndroid Build Coastguard Worker */
2772*79398b25SAndroid Build Coastguard Worker if (!file_type_match(action_data->buf->st_mode, ACTION_LNK))
2773*79398b25SAndroid Build Coastguard Worker return 1;
2774*79398b25SAndroid Build Coastguard Worker
2775*79398b25SAndroid Build Coastguard Worker /* dereference the symlink, and return TRUE if it exists */
2776*79398b25SAndroid Build Coastguard Worker return follow_path(action_data->dir_ent->our_dir,
2777*79398b25SAndroid Build Coastguard Worker action_data->dir_ent->inode->symlink) ? 1 : 0;
2778*79398b25SAndroid Build Coastguard Worker }
2779*79398b25SAndroid Build Coastguard Worker
2780*79398b25SAndroid Build Coastguard Worker
absolute_fn(struct atom * atom,struct action_data * action_data)2781*79398b25SAndroid Build Coastguard Worker static int absolute_fn(struct atom *atom, struct action_data *action_data)
2782*79398b25SAndroid Build Coastguard Worker {
2783*79398b25SAndroid Build Coastguard Worker /*
2784*79398b25SAndroid Build Coastguard Worker * Test if a symlink has an absolute path, which by definition
2785*79398b25SAndroid Build Coastguard Worker * means the symbolic link may be broken (even if the absolute path
2786*79398b25SAndroid Build Coastguard Worker * does point into the filesystem being squashed, because the resultant
2787*79398b25SAndroid Build Coastguard Worker * filesystem can be mounted/unsquashed anywhere, it is unlikely the
2788*79398b25SAndroid Build Coastguard Worker * absolute path will still point to the right place). If you know that
2789*79398b25SAndroid Build Coastguard Worker * an absolute symlink will point to the right place then you don't need
2790*79398b25SAndroid Build Coastguard Worker * to use this function, and/or these symlinks can be excluded by
2791*79398b25SAndroid Build Coastguard Worker * use of other test operators.
2792*79398b25SAndroid Build Coastguard Worker *
2793*79398b25SAndroid Build Coastguard Worker * absolute operates on symlinks only, other files by definition
2794*79398b25SAndroid Build Coastguard Worker * don't have problems
2795*79398b25SAndroid Build Coastguard Worker */
2796*79398b25SAndroid Build Coastguard Worker if (!file_type_match(action_data->buf->st_mode, ACTION_LNK))
2797*79398b25SAndroid Build Coastguard Worker return 0;
2798*79398b25SAndroid Build Coastguard Worker
2799*79398b25SAndroid Build Coastguard Worker return action_data->dir_ent->inode->symlink[0] == '/';
2800*79398b25SAndroid Build Coastguard Worker }
2801*79398b25SAndroid Build Coastguard Worker
2802*79398b25SAndroid Build Coastguard Worker
parse_expr_argX(struct test_entry * test,struct atom * atom,int argno)2803*79398b25SAndroid Build Coastguard Worker static int parse_expr_argX(struct test_entry *test, struct atom *atom,
2804*79398b25SAndroid Build Coastguard Worker int argno)
2805*79398b25SAndroid Build Coastguard Worker {
2806*79398b25SAndroid Build Coastguard Worker /* Call parse_expr to parse argument, which should be an expression */
2807*79398b25SAndroid Build Coastguard Worker
2808*79398b25SAndroid Build Coastguard Worker /* save the current parser state */
2809*79398b25SAndroid Build Coastguard Worker char *save_cur_ptr = cur_ptr;
2810*79398b25SAndroid Build Coastguard Worker char *save_source = source;
2811*79398b25SAndroid Build Coastguard Worker
2812*79398b25SAndroid Build Coastguard Worker cur_ptr = source = atom->argv[argno];
2813*79398b25SAndroid Build Coastguard Worker atom->data = parse_expr(0);
2814*79398b25SAndroid Build Coastguard Worker
2815*79398b25SAndroid Build Coastguard Worker cur_ptr = save_cur_ptr;
2816*79398b25SAndroid Build Coastguard Worker source = save_source;
2817*79398b25SAndroid Build Coastguard Worker
2818*79398b25SAndroid Build Coastguard Worker if(atom->data == NULL) {
2819*79398b25SAndroid Build Coastguard Worker /* parse_expr(0) will have reported the exact syntax error,
2820*79398b25SAndroid Build Coastguard Worker * but, because we recursively evaluated the expression, it
2821*79398b25SAndroid Build Coastguard Worker * will have been reported without the context of the stat
2822*79398b25SAndroid Build Coastguard Worker * test(). So here additionally report our failure to parse
2823*79398b25SAndroid Build Coastguard Worker * the expression in the stat() test to give context */
2824*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "Failed to parse expression\n");
2825*79398b25SAndroid Build Coastguard Worker return 0;
2826*79398b25SAndroid Build Coastguard Worker }
2827*79398b25SAndroid Build Coastguard Worker
2828*79398b25SAndroid Build Coastguard Worker return 1;
2829*79398b25SAndroid Build Coastguard Worker }
2830*79398b25SAndroid Build Coastguard Worker
2831*79398b25SAndroid Build Coastguard Worker
parse_expr_arg0(struct test_entry * test,struct atom * atom)2832*79398b25SAndroid Build Coastguard Worker static int parse_expr_arg0(struct test_entry *test, struct atom *atom)
2833*79398b25SAndroid Build Coastguard Worker {
2834*79398b25SAndroid Build Coastguard Worker return parse_expr_argX(test, atom, 0);
2835*79398b25SAndroid Build Coastguard Worker }
2836*79398b25SAndroid Build Coastguard Worker
2837*79398b25SAndroid Build Coastguard Worker
parse_expr_arg1(struct test_entry * test,struct atom * atom)2838*79398b25SAndroid Build Coastguard Worker static int parse_expr_arg1(struct test_entry *test, struct atom *atom)
2839*79398b25SAndroid Build Coastguard Worker {
2840*79398b25SAndroid Build Coastguard Worker return parse_expr_argX(test, atom, 1);
2841*79398b25SAndroid Build Coastguard Worker }
2842*79398b25SAndroid Build Coastguard Worker
2843*79398b25SAndroid Build Coastguard Worker
stat_fn(struct atom * atom,struct action_data * action_data)2844*79398b25SAndroid Build Coastguard Worker static int stat_fn(struct atom *atom, struct action_data *action_data)
2845*79398b25SAndroid Build Coastguard Worker {
2846*79398b25SAndroid Build Coastguard Worker struct stat buf;
2847*79398b25SAndroid Build Coastguard Worker struct action_data eval_action;
2848*79398b25SAndroid Build Coastguard Worker int match, res;
2849*79398b25SAndroid Build Coastguard Worker
2850*79398b25SAndroid Build Coastguard Worker /* evaluate the expression using the context of the inode
2851*79398b25SAndroid Build Coastguard Worker * pointed to by the symlink. This allows the inode attributes
2852*79398b25SAndroid Build Coastguard Worker * of the file pointed to by the symlink to be evaluated, rather
2853*79398b25SAndroid Build Coastguard Worker * than the symlink itself.
2854*79398b25SAndroid Build Coastguard Worker *
2855*79398b25SAndroid Build Coastguard Worker * Note, stat() deliberately does not evaluate the pathname, name or
2856*79398b25SAndroid Build Coastguard Worker * depth of the symlink, these are left with the symlink values.
2857*79398b25SAndroid Build Coastguard Worker * This allows stat() to be used on any symlink, rather than
2858*79398b25SAndroid Build Coastguard Worker * just symlinks which are contained (if the symlink is *not*
2859*79398b25SAndroid Build Coastguard Worker * contained then pathname, name and depth are meaningless as they
2860*79398b25SAndroid Build Coastguard Worker * are relative to the filesystem being squashed). */
2861*79398b25SAndroid Build Coastguard Worker
2862*79398b25SAndroid Build Coastguard Worker /* if this isn't a symlink then stat will just return the current
2863*79398b25SAndroid Build Coastguard Worker * information, i.e. stat(expr) == expr. This is harmless and
2864*79398b25SAndroid Build Coastguard Worker * is better than returning TRUE or FALSE in a non symlink case */
2865*79398b25SAndroid Build Coastguard Worker res = stat(action_data->pathname, &buf);
2866*79398b25SAndroid Build Coastguard Worker if(res == -1) {
2867*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
2868*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
2869*79398b25SAndroid Build Coastguard Worker expr_log("(");
2870*79398b25SAndroid Build Coastguard Worker expr_log_match(0);
2871*79398b25SAndroid Build Coastguard Worker expr_log(")");
2872*79398b25SAndroid Build Coastguard Worker }
2873*79398b25SAndroid Build Coastguard Worker return 0;
2874*79398b25SAndroid Build Coastguard Worker }
2875*79398b25SAndroid Build Coastguard Worker
2876*79398b25SAndroid Build Coastguard Worker /* fill in the inode values of the file pointed to by the
2877*79398b25SAndroid Build Coastguard Worker * symlink, but, leave everything else the same */
2878*79398b25SAndroid Build Coastguard Worker memcpy(&eval_action, action_data, sizeof(struct action_data));
2879*79398b25SAndroid Build Coastguard Worker eval_action.buf = &buf;
2880*79398b25SAndroid Build Coastguard Worker
2881*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
2882*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
2883*79398b25SAndroid Build Coastguard Worker expr_log("(");
2884*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(atom->data, &eval_action);
2885*79398b25SAndroid Build Coastguard Worker expr_log(")");
2886*79398b25SAndroid Build Coastguard Worker } else
2887*79398b25SAndroid Build Coastguard Worker match = eval_expr(atom->data, &eval_action);
2888*79398b25SAndroid Build Coastguard Worker
2889*79398b25SAndroid Build Coastguard Worker return match;
2890*79398b25SAndroid Build Coastguard Worker }
2891*79398b25SAndroid Build Coastguard Worker
2892*79398b25SAndroid Build Coastguard Worker
readlink_fn(struct atom * atom,struct action_data * action_data)2893*79398b25SAndroid Build Coastguard Worker static int readlink_fn(struct atom *atom, struct action_data *action_data)
2894*79398b25SAndroid Build Coastguard Worker {
2895*79398b25SAndroid Build Coastguard Worker int match = 0;
2896*79398b25SAndroid Build Coastguard Worker struct dir_ent *dir_ent;
2897*79398b25SAndroid Build Coastguard Worker struct action_data eval_action;
2898*79398b25SAndroid Build Coastguard Worker
2899*79398b25SAndroid Build Coastguard Worker /* Dereference the symlink and evaluate the expression in the
2900*79398b25SAndroid Build Coastguard Worker * context of the file pointed to by the symlink.
2901*79398b25SAndroid Build Coastguard Worker * All attributes are updated to refer to the file that is pointed to.
2902*79398b25SAndroid Build Coastguard Worker * Thus the inode attributes, pathname, name and depth all refer to
2903*79398b25SAndroid Build Coastguard Worker * the dereferenced file, and not the symlink.
2904*79398b25SAndroid Build Coastguard Worker *
2905*79398b25SAndroid Build Coastguard Worker * If the symlink cannot be dereferenced because it doesn't exist in
2906*79398b25SAndroid Build Coastguard Worker * the output filesystem, or due to some other failure to
2907*79398b25SAndroid Build Coastguard Worker * walk the pathname (see follow_path above), then FALSE is returned.
2908*79398b25SAndroid Build Coastguard Worker *
2909*79398b25SAndroid Build Coastguard Worker * If you wish to evaluate the inode attributes of symlinks which
2910*79398b25SAndroid Build Coastguard Worker * exist in the source filestem (but not in the output filesystem then
2911*79398b25SAndroid Build Coastguard Worker * use stat instead (see above).
2912*79398b25SAndroid Build Coastguard Worker *
2913*79398b25SAndroid Build Coastguard Worker * readlink operates on symlinks only */
2914*79398b25SAndroid Build Coastguard Worker if (!file_type_match(action_data->buf->st_mode, ACTION_LNK))
2915*79398b25SAndroid Build Coastguard Worker goto finish;
2916*79398b25SAndroid Build Coastguard Worker
2917*79398b25SAndroid Build Coastguard Worker /* dereference the symlink, and get the directory entry it points to */
2918*79398b25SAndroid Build Coastguard Worker dir_ent = follow_path(action_data->dir_ent->our_dir,
2919*79398b25SAndroid Build Coastguard Worker action_data->dir_ent->inode->symlink);
2920*79398b25SAndroid Build Coastguard Worker if(dir_ent == NULL)
2921*79398b25SAndroid Build Coastguard Worker goto finish;
2922*79398b25SAndroid Build Coastguard Worker
2923*79398b25SAndroid Build Coastguard Worker eval_action.name = dir_ent->name;
2924*79398b25SAndroid Build Coastguard Worker eval_action.pathname = strdup(pathname(dir_ent));
2925*79398b25SAndroid Build Coastguard Worker eval_action.subpath = strdup(subpathname(dir_ent));
2926*79398b25SAndroid Build Coastguard Worker eval_action.buf = &dir_ent->inode->buf;
2927*79398b25SAndroid Build Coastguard Worker eval_action.depth = dir_ent->our_dir->depth;
2928*79398b25SAndroid Build Coastguard Worker eval_action.dir_ent = dir_ent;
2929*79398b25SAndroid Build Coastguard Worker eval_action.root = action_data->root;
2930*79398b25SAndroid Build Coastguard Worker
2931*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
2932*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
2933*79398b25SAndroid Build Coastguard Worker expr_log("(");
2934*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(atom->data, &eval_action);
2935*79398b25SAndroid Build Coastguard Worker expr_log(")");
2936*79398b25SAndroid Build Coastguard Worker } else
2937*79398b25SAndroid Build Coastguard Worker match = eval_expr(atom->data, &eval_action);
2938*79398b25SAndroid Build Coastguard Worker
2939*79398b25SAndroid Build Coastguard Worker free(eval_action.pathname);
2940*79398b25SAndroid Build Coastguard Worker free(eval_action.subpath);
2941*79398b25SAndroid Build Coastguard Worker
2942*79398b25SAndroid Build Coastguard Worker return match;
2943*79398b25SAndroid Build Coastguard Worker
2944*79398b25SAndroid Build Coastguard Worker finish:
2945*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
2946*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
2947*79398b25SAndroid Build Coastguard Worker expr_log("(");
2948*79398b25SAndroid Build Coastguard Worker expr_log_match(0);
2949*79398b25SAndroid Build Coastguard Worker expr_log(")");
2950*79398b25SAndroid Build Coastguard Worker }
2951*79398b25SAndroid Build Coastguard Worker
2952*79398b25SAndroid Build Coastguard Worker return 0;
2953*79398b25SAndroid Build Coastguard Worker }
2954*79398b25SAndroid Build Coastguard Worker
2955*79398b25SAndroid Build Coastguard Worker
eval_fn(struct atom * atom,struct action_data * action_data)2956*79398b25SAndroid Build Coastguard Worker static int eval_fn(struct atom *atom, struct action_data *action_data)
2957*79398b25SAndroid Build Coastguard Worker {
2958*79398b25SAndroid Build Coastguard Worker int match;
2959*79398b25SAndroid Build Coastguard Worker char *path = atom->argv[0];
2960*79398b25SAndroid Build Coastguard Worker struct dir_ent *dir_ent = action_data->dir_ent;
2961*79398b25SAndroid Build Coastguard Worker struct stat *buf = action_data->buf;
2962*79398b25SAndroid Build Coastguard Worker struct action_data eval_action;
2963*79398b25SAndroid Build Coastguard Worker
2964*79398b25SAndroid Build Coastguard Worker /* Follow path (arg1) and evaluate the expression (arg2)
2965*79398b25SAndroid Build Coastguard Worker * in the context of the file discovered. All attributes are updated
2966*79398b25SAndroid Build Coastguard Worker * to refer to the file that is pointed to.
2967*79398b25SAndroid Build Coastguard Worker *
2968*79398b25SAndroid Build Coastguard Worker * This test operation allows you to add additional context to the
2969*79398b25SAndroid Build Coastguard Worker * evaluation of the file being scanned, such as "if current file is
2970*79398b25SAndroid Build Coastguard Worker * XXX and the parent is YYY, then ..." Often times you need or
2971*79398b25SAndroid Build Coastguard Worker * want to test a combination of file status
2972*79398b25SAndroid Build Coastguard Worker *
2973*79398b25SAndroid Build Coastguard Worker * If the file referenced by the path does not exist in
2974*79398b25SAndroid Build Coastguard Worker * the output filesystem, or some other failure is experienced in
2975*79398b25SAndroid Build Coastguard Worker * walking the path (see follow_path above), then FALSE is returned.
2976*79398b25SAndroid Build Coastguard Worker *
2977*79398b25SAndroid Build Coastguard Worker * If you wish to evaluate the inode attributes of files which
2978*79398b25SAndroid Build Coastguard Worker * exist in the source filestem (but not in the output filesystem then
2979*79398b25SAndroid Build Coastguard Worker * use stat instead (see above). */
2980*79398b25SAndroid Build Coastguard Worker
2981*79398b25SAndroid Build Coastguard Worker /* try to follow path, and get the directory entry it points to */
2982*79398b25SAndroid Build Coastguard Worker if(path[0] == '/') {
2983*79398b25SAndroid Build Coastguard Worker /* absolute, walk from root - first skip the leading / */
2984*79398b25SAndroid Build Coastguard Worker while(path[0] == '/')
2985*79398b25SAndroid Build Coastguard Worker path ++;
2986*79398b25SAndroid Build Coastguard Worker if(path[0] == '\0')
2987*79398b25SAndroid Build Coastguard Worker dir_ent = action_data->root->dir_ent;
2988*79398b25SAndroid Build Coastguard Worker else
2989*79398b25SAndroid Build Coastguard Worker dir_ent = follow_path(action_data->root, path);
2990*79398b25SAndroid Build Coastguard Worker } else {
2991*79398b25SAndroid Build Coastguard Worker /* relative, if first component is ".." walk from parent,
2992*79398b25SAndroid Build Coastguard Worker * otherwise walk from dir_ent.
2993*79398b25SAndroid Build Coastguard Worker * Note: this has to be handled here because follow_path
2994*79398b25SAndroid Build Coastguard Worker * will quite correctly refuse to execute ".." on anything
2995*79398b25SAndroid Build Coastguard Worker * which isn't a directory */
2996*79398b25SAndroid Build Coastguard Worker if(strncmp(path, "..", 2) == 0 && (path[2] == '\0' ||
2997*79398b25SAndroid Build Coastguard Worker path[2] == '/')) {
2998*79398b25SAndroid Build Coastguard Worker /* walk from parent */
2999*79398b25SAndroid Build Coastguard Worker path += 2;
3000*79398b25SAndroid Build Coastguard Worker while(path[0] == '/')
3001*79398b25SAndroid Build Coastguard Worker path ++;
3002*79398b25SAndroid Build Coastguard Worker if(path[0] == '\0')
3003*79398b25SAndroid Build Coastguard Worker dir_ent = dir_ent->our_dir->dir_ent;
3004*79398b25SAndroid Build Coastguard Worker else
3005*79398b25SAndroid Build Coastguard Worker dir_ent = follow_path(dir_ent->our_dir, path);
3006*79398b25SAndroid Build Coastguard Worker } else if(!file_type_match(buf->st_mode, ACTION_DIR))
3007*79398b25SAndroid Build Coastguard Worker dir_ent = NULL;
3008*79398b25SAndroid Build Coastguard Worker else
3009*79398b25SAndroid Build Coastguard Worker dir_ent = follow_path(dir_ent->dir, path);
3010*79398b25SAndroid Build Coastguard Worker }
3011*79398b25SAndroid Build Coastguard Worker
3012*79398b25SAndroid Build Coastguard Worker if(dir_ent == NULL) {
3013*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
3014*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
3015*79398b25SAndroid Build Coastguard Worker expr_log("(");
3016*79398b25SAndroid Build Coastguard Worker expr_log(atom->argv[0]);
3017*79398b25SAndroid Build Coastguard Worker expr_log(",");
3018*79398b25SAndroid Build Coastguard Worker expr_log_match(0);
3019*79398b25SAndroid Build Coastguard Worker expr_log(")");
3020*79398b25SAndroid Build Coastguard Worker }
3021*79398b25SAndroid Build Coastguard Worker
3022*79398b25SAndroid Build Coastguard Worker return 0;
3023*79398b25SAndroid Build Coastguard Worker }
3024*79398b25SAndroid Build Coastguard Worker
3025*79398b25SAndroid Build Coastguard Worker eval_action.name = dir_ent->name;
3026*79398b25SAndroid Build Coastguard Worker eval_action.pathname = strdup(pathname(dir_ent));
3027*79398b25SAndroid Build Coastguard Worker eval_action.subpath = strdup(subpathname(dir_ent));
3028*79398b25SAndroid Build Coastguard Worker eval_action.buf = &dir_ent->inode->buf;
3029*79398b25SAndroid Build Coastguard Worker eval_action.depth = dir_ent->our_dir->depth;
3030*79398b25SAndroid Build Coastguard Worker eval_action.dir_ent = dir_ent;
3031*79398b25SAndroid Build Coastguard Worker eval_action.root = action_data->root;
3032*79398b25SAndroid Build Coastguard Worker
3033*79398b25SAndroid Build Coastguard Worker if(expr_log_cmnd(LOG_ENABLED)) {
3034*79398b25SAndroid Build Coastguard Worker expr_log(atom->test->name);
3035*79398b25SAndroid Build Coastguard Worker expr_log("(");
3036*79398b25SAndroid Build Coastguard Worker expr_log(eval_action.subpath);
3037*79398b25SAndroid Build Coastguard Worker expr_log(",");
3038*79398b25SAndroid Build Coastguard Worker match = eval_expr_log(atom->data, &eval_action);
3039*79398b25SAndroid Build Coastguard Worker expr_log(")");
3040*79398b25SAndroid Build Coastguard Worker } else
3041*79398b25SAndroid Build Coastguard Worker match = eval_expr(atom->data, &eval_action);
3042*79398b25SAndroid Build Coastguard Worker
3043*79398b25SAndroid Build Coastguard Worker free(eval_action.pathname);
3044*79398b25SAndroid Build Coastguard Worker free(eval_action.subpath);
3045*79398b25SAndroid Build Coastguard Worker
3046*79398b25SAndroid Build Coastguard Worker return match;
3047*79398b25SAndroid Build Coastguard Worker }
3048*79398b25SAndroid Build Coastguard Worker
3049*79398b25SAndroid Build Coastguard Worker
3050*79398b25SAndroid Build Coastguard Worker /*
3051*79398b25SAndroid Build Coastguard Worker * Perm specific test code
3052*79398b25SAndroid Build Coastguard Worker */
parse_perm_args(struct test_entry * test,struct atom * atom)3053*79398b25SAndroid Build Coastguard Worker static int parse_perm_args(struct test_entry *test, struct atom *atom)
3054*79398b25SAndroid Build Coastguard Worker {
3055*79398b25SAndroid Build Coastguard Worker int res = 1, mode, op, i;
3056*79398b25SAndroid Build Coastguard Worker char *arg;
3057*79398b25SAndroid Build Coastguard Worker struct mode_data *head = NULL, *cur = NULL;
3058*79398b25SAndroid Build Coastguard Worker struct perm_data *perm_data;
3059*79398b25SAndroid Build Coastguard Worker
3060*79398b25SAndroid Build Coastguard Worker if(atom->args == 0) {
3061*79398b25SAndroid Build Coastguard Worker TEST_SYNTAX_ERROR(test, 0, "One or more arguments expected\n");
3062*79398b25SAndroid Build Coastguard Worker return 0;
3063*79398b25SAndroid Build Coastguard Worker }
3064*79398b25SAndroid Build Coastguard Worker
3065*79398b25SAndroid Build Coastguard Worker switch(atom->argv[0][0]) {
3066*79398b25SAndroid Build Coastguard Worker case '-':
3067*79398b25SAndroid Build Coastguard Worker op = PERM_ALL;
3068*79398b25SAndroid Build Coastguard Worker arg = atom->argv[0] + 1;
3069*79398b25SAndroid Build Coastguard Worker break;
3070*79398b25SAndroid Build Coastguard Worker case '/':
3071*79398b25SAndroid Build Coastguard Worker op = PERM_ANY;
3072*79398b25SAndroid Build Coastguard Worker arg = atom->argv[0] + 1;
3073*79398b25SAndroid Build Coastguard Worker break;
3074*79398b25SAndroid Build Coastguard Worker default:
3075*79398b25SAndroid Build Coastguard Worker op = PERM_EXACT;
3076*79398b25SAndroid Build Coastguard Worker arg = atom->argv[0];
3077*79398b25SAndroid Build Coastguard Worker break;
3078*79398b25SAndroid Build Coastguard Worker }
3079*79398b25SAndroid Build Coastguard Worker
3080*79398b25SAndroid Build Coastguard Worker /* try to parse as an octal number */
3081*79398b25SAndroid Build Coastguard Worker res = parse_octal_mode_args(atom->args, atom->argv, (void **) &head);
3082*79398b25SAndroid Build Coastguard Worker if(res == -1) {
3083*79398b25SAndroid Build Coastguard Worker /* parse as sym mode argument */
3084*79398b25SAndroid Build Coastguard Worker for(i = 0; i < atom->args && res; i++, arg = atom->argv[i])
3085*79398b25SAndroid Build Coastguard Worker res = parse_sym_mode_arg(arg, &head, &cur);
3086*79398b25SAndroid Build Coastguard Worker }
3087*79398b25SAndroid Build Coastguard Worker
3088*79398b25SAndroid Build Coastguard Worker if (res == 0)
3089*79398b25SAndroid Build Coastguard Worker goto finish;
3090*79398b25SAndroid Build Coastguard Worker
3091*79398b25SAndroid Build Coastguard Worker /*
3092*79398b25SAndroid Build Coastguard Worker * Evaluate the symbolic mode against a permission of 0000 octal
3093*79398b25SAndroid Build Coastguard Worker */
3094*79398b25SAndroid Build Coastguard Worker mode = mode_execute(head, 0);
3095*79398b25SAndroid Build Coastguard Worker
3096*79398b25SAndroid Build Coastguard Worker perm_data = malloc(sizeof(struct perm_data));
3097*79398b25SAndroid Build Coastguard Worker if (perm_data == NULL)
3098*79398b25SAndroid Build Coastguard Worker MEM_ERROR();
3099*79398b25SAndroid Build Coastguard Worker
3100*79398b25SAndroid Build Coastguard Worker perm_data->op = op;
3101*79398b25SAndroid Build Coastguard Worker perm_data->mode = mode;
3102*79398b25SAndroid Build Coastguard Worker
3103*79398b25SAndroid Build Coastguard Worker atom->data = perm_data;
3104*79398b25SAndroid Build Coastguard Worker
3105*79398b25SAndroid Build Coastguard Worker finish:
3106*79398b25SAndroid Build Coastguard Worker while(head) {
3107*79398b25SAndroid Build Coastguard Worker struct mode_data *tmp = head;
3108*79398b25SAndroid Build Coastguard Worker head = head->next;
3109*79398b25SAndroid Build Coastguard Worker free(tmp);
3110*79398b25SAndroid Build Coastguard Worker }
3111*79398b25SAndroid Build Coastguard Worker
3112*79398b25SAndroid Build Coastguard Worker return res;
3113*79398b25SAndroid Build Coastguard Worker }
3114*79398b25SAndroid Build Coastguard Worker
3115*79398b25SAndroid Build Coastguard Worker
perm_fn(struct atom * atom,struct action_data * action_data)3116*79398b25SAndroid Build Coastguard Worker static int perm_fn(struct atom *atom, struct action_data *action_data)
3117*79398b25SAndroid Build Coastguard Worker {
3118*79398b25SAndroid Build Coastguard Worker struct perm_data *perm_data = atom->data;
3119*79398b25SAndroid Build Coastguard Worker struct stat *buf = action_data->buf;
3120*79398b25SAndroid Build Coastguard Worker
3121*79398b25SAndroid Build Coastguard Worker switch(perm_data->op) {
3122*79398b25SAndroid Build Coastguard Worker case PERM_EXACT:
3123*79398b25SAndroid Build Coastguard Worker return (buf->st_mode & ~S_IFMT) == perm_data->mode;
3124*79398b25SAndroid Build Coastguard Worker case PERM_ALL:
3125*79398b25SAndroid Build Coastguard Worker return (buf->st_mode & perm_data->mode) == perm_data->mode;
3126*79398b25SAndroid Build Coastguard Worker case PERM_ANY:
3127*79398b25SAndroid Build Coastguard Worker default:
3128*79398b25SAndroid Build Coastguard Worker /*
3129*79398b25SAndroid Build Coastguard Worker * if no permission bits are set in perm_data->mode match
3130*79398b25SAndroid Build Coastguard Worker * on any file, this is to be consistent with find, which
3131*79398b25SAndroid Build Coastguard Worker * does this to be consistent with the behaviour of
3132*79398b25SAndroid Build Coastguard Worker * -perm -000
3133*79398b25SAndroid Build Coastguard Worker */
3134*79398b25SAndroid Build Coastguard Worker return perm_data->mode == 0 || (buf->st_mode & perm_data->mode);
3135*79398b25SAndroid Build Coastguard Worker }
3136*79398b25SAndroid Build Coastguard Worker }
3137*79398b25SAndroid Build Coastguard Worker
3138*79398b25SAndroid Build Coastguard Worker
3139*79398b25SAndroid Build Coastguard Worker #ifdef SQUASHFS_TRACE
dump_parse_tree(struct expr * expr)3140*79398b25SAndroid Build Coastguard Worker static void dump_parse_tree(struct expr *expr)
3141*79398b25SAndroid Build Coastguard Worker {
3142*79398b25SAndroid Build Coastguard Worker int i;
3143*79398b25SAndroid Build Coastguard Worker
3144*79398b25SAndroid Build Coastguard Worker if(expr->type == ATOM_TYPE) {
3145*79398b25SAndroid Build Coastguard Worker printf("%s", expr->atom.test->name);
3146*79398b25SAndroid Build Coastguard Worker if(expr->atom.args) {
3147*79398b25SAndroid Build Coastguard Worker printf("(");
3148*79398b25SAndroid Build Coastguard Worker for(i = 0; i < expr->atom.args; i++) {
3149*79398b25SAndroid Build Coastguard Worker printf("%s", expr->atom.argv[i]);
3150*79398b25SAndroid Build Coastguard Worker if (i + 1 < expr->atom.args)
3151*79398b25SAndroid Build Coastguard Worker printf(",");
3152*79398b25SAndroid Build Coastguard Worker }
3153*79398b25SAndroid Build Coastguard Worker printf(")");
3154*79398b25SAndroid Build Coastguard Worker }
3155*79398b25SAndroid Build Coastguard Worker } else if (expr->type == UNARY_TYPE) {
3156*79398b25SAndroid Build Coastguard Worker printf("%s", token_table[expr->unary_op.op].string);
3157*79398b25SAndroid Build Coastguard Worker dump_parse_tree(expr->unary_op.expr);
3158*79398b25SAndroid Build Coastguard Worker } else {
3159*79398b25SAndroid Build Coastguard Worker printf("(");
3160*79398b25SAndroid Build Coastguard Worker dump_parse_tree(expr->expr_op.lhs);
3161*79398b25SAndroid Build Coastguard Worker printf("%s", token_table[expr->expr_op.op].string);
3162*79398b25SAndroid Build Coastguard Worker dump_parse_tree(expr->expr_op.rhs);
3163*79398b25SAndroid Build Coastguard Worker printf(")");
3164*79398b25SAndroid Build Coastguard Worker }
3165*79398b25SAndroid Build Coastguard Worker }
3166*79398b25SAndroid Build Coastguard Worker
3167*79398b25SAndroid Build Coastguard Worker
dump_action_list(struct action * spec_list,int spec_count)3168*79398b25SAndroid Build Coastguard Worker void dump_action_list(struct action *spec_list, int spec_count)
3169*79398b25SAndroid Build Coastguard Worker {
3170*79398b25SAndroid Build Coastguard Worker int i;
3171*79398b25SAndroid Build Coastguard Worker
3172*79398b25SAndroid Build Coastguard Worker for (i = 0; i < spec_count; i++) {
3173*79398b25SAndroid Build Coastguard Worker printf("%s", spec_list[i].action->name);
3174*79398b25SAndroid Build Coastguard Worker if (spec_list[i].args) {
3175*79398b25SAndroid Build Coastguard Worker int n;
3176*79398b25SAndroid Build Coastguard Worker
3177*79398b25SAndroid Build Coastguard Worker printf("(");
3178*79398b25SAndroid Build Coastguard Worker for (n = 0; n < spec_list[i].args; n++) {
3179*79398b25SAndroid Build Coastguard Worker printf("%s", spec_list[i].argv[n]);
3180*79398b25SAndroid Build Coastguard Worker if (n + 1 < spec_list[i].args)
3181*79398b25SAndroid Build Coastguard Worker printf(",");
3182*79398b25SAndroid Build Coastguard Worker }
3183*79398b25SAndroid Build Coastguard Worker printf(")");
3184*79398b25SAndroid Build Coastguard Worker }
3185*79398b25SAndroid Build Coastguard Worker printf("=");
3186*79398b25SAndroid Build Coastguard Worker dump_parse_tree(spec_list[i].expr);
3187*79398b25SAndroid Build Coastguard Worker printf("\n");
3188*79398b25SAndroid Build Coastguard Worker }
3189*79398b25SAndroid Build Coastguard Worker }
3190*79398b25SAndroid Build Coastguard Worker
3191*79398b25SAndroid Build Coastguard Worker
dump_actions()3192*79398b25SAndroid Build Coastguard Worker void dump_actions()
3193*79398b25SAndroid Build Coastguard Worker {
3194*79398b25SAndroid Build Coastguard Worker dump_action_list(exclude_spec, exclude_count);
3195*79398b25SAndroid Build Coastguard Worker dump_action_list(fragment_spec, fragment_count);
3196*79398b25SAndroid Build Coastguard Worker dump_action_list(other_spec, other_count);
3197*79398b25SAndroid Build Coastguard Worker dump_action_list(move_spec, move_count);
3198*79398b25SAndroid Build Coastguard Worker dump_action_list(empty_spec, empty_count);
3199*79398b25SAndroid Build Coastguard Worker }
3200*79398b25SAndroid Build Coastguard Worker #else
dump_actions()3201*79398b25SAndroid Build Coastguard Worker void dump_actions()
3202*79398b25SAndroid Build Coastguard Worker {
3203*79398b25SAndroid Build Coastguard Worker }
3204*79398b25SAndroid Build Coastguard Worker #endif
3205*79398b25SAndroid Build Coastguard Worker
3206*79398b25SAndroid Build Coastguard Worker
3207*79398b25SAndroid Build Coastguard Worker static struct test_entry test_table[] = {
3208*79398b25SAndroid Build Coastguard Worker { "name", 1, name_fn, NULL, 1},
3209*79398b25SAndroid Build Coastguard Worker { "pathname", 1, pathname_fn, check_pathname, 1, 0},
3210*79398b25SAndroid Build Coastguard Worker { "subpathname", 1, subpathname_fn, check_pathname, 1, 0},
3211*79398b25SAndroid Build Coastguard Worker { "filesize", 1, filesize_fn, parse_number_arg, 1, 0},
3212*79398b25SAndroid Build Coastguard Worker { "dirsize", 1, dirsize_fn, parse_number_arg, 1, 0},
3213*79398b25SAndroid Build Coastguard Worker { "size", 1, size_fn, parse_number_arg, 1, 0},
3214*79398b25SAndroid Build Coastguard Worker { "inode", 1, inode_fn, parse_number_arg, 1, 0},
3215*79398b25SAndroid Build Coastguard Worker { "nlink", 1, nlink_fn, parse_number_arg, 1, 0},
3216*79398b25SAndroid Build Coastguard Worker { "fileblocks", 1, fileblocks_fn, parse_number_arg, 1, 0},
3217*79398b25SAndroid Build Coastguard Worker { "dirblocks", 1, dirblocks_fn, parse_number_arg, 1, 0},
3218*79398b25SAndroid Build Coastguard Worker { "blocks", 1, blocks_fn, parse_number_arg, 1, 0},
3219*79398b25SAndroid Build Coastguard Worker { "gid", 1, gid_fn, parse_gid_arg, 1, 0},
3220*79398b25SAndroid Build Coastguard Worker { "uid", 1, uid_fn, parse_uid_arg, 1, 0},
3221*79398b25SAndroid Build Coastguard Worker { "depth", 1, depth_fn, parse_number_arg, 1, 0},
3222*79398b25SAndroid Build Coastguard Worker { "dircount", 1, dircount_fn, parse_number_arg, 0, 0},
3223*79398b25SAndroid Build Coastguard Worker { "filesize_range", 2, filesize_range_fn, parse_range_args, 1, 0},
3224*79398b25SAndroid Build Coastguard Worker { "dirsize_range", 2, dirsize_range_fn, parse_range_args, 1, 0},
3225*79398b25SAndroid Build Coastguard Worker { "size_range", 2, size_range_fn, parse_range_args, 1, 0},
3226*79398b25SAndroid Build Coastguard Worker { "inode_range", 2, inode_range_fn, parse_range_args, 1, 0},
3227*79398b25SAndroid Build Coastguard Worker { "nlink_range", 2, nlink_range_fn, parse_range_args, 1, 0},
3228*79398b25SAndroid Build Coastguard Worker { "fileblocks_range", 2, fileblocks_range_fn, parse_range_args, 1, 0},
3229*79398b25SAndroid Build Coastguard Worker { "dirblocks_range", 2, dirblocks_range_fn, parse_range_args, 1, 0},
3230*79398b25SAndroid Build Coastguard Worker { "blocks_range", 2, blocks_range_fn, parse_range_args, 1, 0},
3231*79398b25SAndroid Build Coastguard Worker { "gid_range", 2, gid_range_fn, parse_range_args, 1, 0},
3232*79398b25SAndroid Build Coastguard Worker { "uid_range", 2, uid_range_fn, parse_range_args, 1, 0},
3233*79398b25SAndroid Build Coastguard Worker { "depth_range", 2, depth_range_fn, parse_range_args, 1, 0},
3234*79398b25SAndroid Build Coastguard Worker { "dircount_range", 2, dircount_range_fn, parse_range_args, 0, 0},
3235*79398b25SAndroid Build Coastguard Worker { "type", 1, type_fn, parse_type_arg, 1, 0},
3236*79398b25SAndroid Build Coastguard Worker { "true", 0, true_fn, NULL, 1, 0},
3237*79398b25SAndroid Build Coastguard Worker { "false", 0, false_fn, NULL, 1, 0},
3238*79398b25SAndroid Build Coastguard Worker { "file", 1, file_fn, parse_file_arg, 1, 0},
3239*79398b25SAndroid Build Coastguard Worker { "exec", 1, exec_fn, NULL, 1, 0},
3240*79398b25SAndroid Build Coastguard Worker { "exists", 0, exists_fn, NULL, 0, 0},
3241*79398b25SAndroid Build Coastguard Worker { "absolute", 0, absolute_fn, NULL, 0, 0},
3242*79398b25SAndroid Build Coastguard Worker { "stat", 1, stat_fn, parse_expr_arg0, 1, 1},
3243*79398b25SAndroid Build Coastguard Worker { "readlink", 1, readlink_fn, parse_expr_arg0, 0, 1},
3244*79398b25SAndroid Build Coastguard Worker { "eval", 2, eval_fn, parse_expr_arg1, 0, 1},
3245*79398b25SAndroid Build Coastguard Worker { "perm", -2, perm_fn, parse_perm_args, 1, 0},
3246*79398b25SAndroid Build Coastguard Worker { "", -1 }
3247*79398b25SAndroid Build Coastguard Worker };
3248*79398b25SAndroid Build Coastguard Worker
3249*79398b25SAndroid Build Coastguard Worker
3250*79398b25SAndroid Build Coastguard Worker static struct action_entry action_table[] = {
3251*79398b25SAndroid Build Coastguard Worker { "fragment", FRAGMENT_ACTION, 1, ACTION_REG, NULL, NULL},
3252*79398b25SAndroid Build Coastguard Worker { "exclude", EXCLUDE_ACTION, 0, ACTION_ALL_LNK, NULL, NULL},
3253*79398b25SAndroid Build Coastguard Worker { "fragments", FRAGMENTS_ACTION, 0, ACTION_REG, NULL, frag_action},
3254*79398b25SAndroid Build Coastguard Worker { "no-fragments", NO_FRAGMENTS_ACTION, 0, ACTION_REG, NULL,
3255*79398b25SAndroid Build Coastguard Worker no_frag_action},
3256*79398b25SAndroid Build Coastguard Worker { "always-use-fragments", ALWAYS_FRAGS_ACTION, 0, ACTION_REG, NULL,
3257*79398b25SAndroid Build Coastguard Worker always_frag_action},
3258*79398b25SAndroid Build Coastguard Worker { "dont-always-use-fragments", NO_ALWAYS_FRAGS_ACTION, 0, ACTION_REG,
3259*79398b25SAndroid Build Coastguard Worker NULL, no_always_frag_action},
3260*79398b25SAndroid Build Coastguard Worker { "compressed", COMPRESSED_ACTION, 0, ACTION_REG, NULL, comp_action},
3261*79398b25SAndroid Build Coastguard Worker { "uncompressed", UNCOMPRESSED_ACTION, 0, ACTION_REG, NULL,
3262*79398b25SAndroid Build Coastguard Worker uncomp_action},
3263*79398b25SAndroid Build Coastguard Worker { "uid", UID_ACTION, 1, ACTION_ALL_LNK, parse_uid_args, uid_action},
3264*79398b25SAndroid Build Coastguard Worker { "gid", GID_ACTION, 1, ACTION_ALL_LNK, parse_gid_args, gid_action},
3265*79398b25SAndroid Build Coastguard Worker { "guid", GUID_ACTION, 2, ACTION_ALL_LNK, parse_guid_args, guid_action},
3266*79398b25SAndroid Build Coastguard Worker { "mode", MODE_ACTION, -2, ACTION_ALL, parse_mode_args, mode_action },
3267*79398b25SAndroid Build Coastguard Worker { "empty", EMPTY_ACTION, -2, ACTION_DIR, parse_empty_args, NULL},
3268*79398b25SAndroid Build Coastguard Worker { "move", MOVE_ACTION, 1, ACTION_ALL_LNK, NULL, NULL},
3269*79398b25SAndroid Build Coastguard Worker { "prune", PRUNE_ACTION, 0, ACTION_ALL_LNK, NULL, NULL},
3270*79398b25SAndroid Build Coastguard Worker { "chmod", MODE_ACTION, -2, ACTION_ALL, parse_mode_args, mode_action },
3271*79398b25SAndroid Build Coastguard Worker { "noop", NOOP_ACTION, 0, ACTION_ALL, NULL, noop_action },
3272*79398b25SAndroid Build Coastguard Worker { "", 0, -1, 0, NULL, NULL}
3273*79398b25SAndroid Build Coastguard Worker };
3274