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