From a1ab6a6450a53ec487f9eae7c2549e62d1c85628 Mon Sep 17 00:00:00 2001 From: jay Date: Fri, 30 Nov 2007 10:24:36 +0000 Subject: [PATCH] Fix Savannah bug #20865 (-prune -delete without an explicit -depth is now an error) --- ChangeLog | 15 +++++++++++++++ NEWS | 7 +++++++ find/defs.h | 5 +++++ find/parser.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ find/tree.c | 1 + find/util.c | 1 + 6 files changed, 73 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4805ec4..bc33838 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-11-30 James Youngman + + Fix Savannah bug #20865 (-prune -delete without an explicit + -depth is now an error). + * find/parser.c (check_option_combinations): Diagnose the + situation where -delete and -prune are both used, because -delete + turns on -depth and -depth makes -prune do nothing. + * find/tree.c (build_expression_tree): call + check_option_combinations(). + * find/defs.h (struct options): Add new boolean field + explicit_depth. + Also declare check_option_combinations. + * find/util.c (set_option_defaults): Initialise explicit_depth. + * NEWS: Mention this fix. + 2007-11-29 James Youngman Support the generation of regexprops-generic.texi. diff --git a/NEWS b/NEWS index 9887ffc..d40115d 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,13 @@ messages must also result in a nonzero exit status. foo/ -name foo" now correctly matches foo and printf foo/. See POSIX interp http://www.opengroup.org/austin/interps/uploads/40/14959/AI-186.txt +#20865: Using both -delete and -prune without explicitly using -depth +is now an error. Traditionally, -delete has always turned -depth on +anyway, so this is not a functional change. However, using -depth +(implicitly or explicitly) makes -prune a no-op. This change is +intended to avoid nasty surprises for people who test with +"-print" and then change it to "-delete" when they are happy. + #20803: POSIX requires that -prune always returns true. Previously it returned false when -depth was in effect and true otherwise. diff --git a/find/defs.h b/find/defs.h index d886fa2..c3e330b 100644 --- a/find/defs.h +++ b/find/defs.h @@ -391,6 +391,7 @@ struct parser_table const struct parser_table* find_parser PARAMS((char *search_name)); boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); void pred_sanity_check PARAMS((const struct predicate *predicates)); +void check_option_combinations (const struct predicate *p); void parse_begin_user_args PARAMS((char **args, int argno, const struct predicate *last, const struct predicate *predicates)); void parse_end_user_args PARAMS((char **args, int argno, const struct predicate *last, const struct predicate *predicates)); boolean parse_openparen PARAMS((const struct parser_table* entry, char *argv[], int *arg_ptr)); @@ -530,6 +531,10 @@ struct options { /* If true, process directory before contents. True unless -depth given. */ boolean do_dir_first; + /* If true, -depth was EXPLICITLY set (as opposed to having been turned + * on by -delete, for example). + */ + boolean explicit_depth; /* If >=0, don't descend more than this many levels of subdirectories. */ int maxdepth; diff --git a/find/parser.c b/find/parser.c index 18d26cc..7eaefc1 100644 --- a/find/parser.c +++ b/find/parser.c @@ -349,6 +349,49 @@ static const char *first_nonoption_arg = NULL; static const struct parser_table *noop = NULL; +void +check_option_combinations(const struct predicate *p) +{ + enum { seen_delete=1u, seen_prune=2u }; + unsigned int predicates = 0u; + + while (p) + { + if (p->pred_func == pred_delete) + predicates |= seen_delete; + else if (p->pred_func == pred_prune) + predicates |= seen_prune; + p = p->pred_next; + } + + if ((predicates & seen_prune) && (predicates & seen_delete)) + { + /* The user specified both -delete and -prune. One might test + * this by first doing + * find dirs .... -prune ..... -print + * to fnd out what's going to get deleted, and then switch to + * find dirs .... -prune ..... -delete + * once we are happy. Unfortunately, the -delete action also + * implicitly turns on -depth, which will affect the behaviour + * of -prune (in fact, it makes it a no-op). In this case we + * would like to prevent unfortunate accidents, so we require + * the user to have explicitly used -depth. + * + * We only get away with this because the -delete predicate is not + * in POSIX. If it was, we couldn't issue a fatal error here. + */ + if (!options.explicit_depth) + { + /* This fixes Savannah bug #20865. */ + error (1, 0, _("The -delete action atomatically turns on -depth, " + "but -prune does nothing when -depth is in effect. " + "If you want to carry on anyway, just explicitly use " + "the -depth option.")); + } + } +} + + static const struct parser_table* get_noop(void) { @@ -760,6 +803,7 @@ parse_depth (const struct parser_table* entry, char **argv, int *arg_ptr) (void) argv; options.do_dir_first = false; + options.explicit_depth = true; return parse_noop(entry, argv, arg_ptr); } diff --git a/find/tree.c b/find/tree.c index d12d579..7420c60 100644 --- a/find/tree.c +++ b/find/tree.c @@ -1325,6 +1325,7 @@ build_expression_tree(int argc, char *argv[], int end_of_leading_options) } /* do a sanity check */ + check_option_combinations(predicates); pred_sanity_check(predicates); /* Done parsing the predicates. Build the evaluation tree. */ diff --git a/find/util.c b/find/util.c index 388f9fc..f057f5d 100644 --- a/find/util.c +++ b/find/util.c @@ -923,6 +923,7 @@ set_option_defaults(struct options *p) } p->do_dir_first = true; + p->explicit_depth = false; p->maxdepth = p->mindepth = -1; p->start_time = now(); p->cur_day_start = p->start_time.tv_sec - DAYSECS; -- 2.11.4.GIT