findutils-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Findutils-patches] [PATCH] Fix Savannah bug #20865.


From: James Youngman
Subject: [Findutils-patches] [PATCH] Fix Savannah bug #20865.
Date: Wed, 28 Nov 2007 00:24:38 +0000

2007-11-28  James Youngman  <address@hidden>

        Fix Savannah bug #20865.
        * 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.
---
 find/defs.h   |    5 +++++
 find/parser.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 find/tree.c   |    1 +
 find/util.c   |    1 +
 4 files changed, 51 insertions(+), 0 deletions(-)

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;
-- 
1.5.3.6





reply via email to

[Prev in Thread] Current Thread [Next in Thread]