On Mon, Apr 18, 2005 at 04:44:50AM +0200, Bas van Gompel wrote:

> :  Here is a patch which implements a ``--non-existing'' (``-E'') option
> :  on locate. It's effect is the inverse of ``--existing'' (``-e'').
> 
> :  Along the way I renamed visit_exists_[no]follow to
> :  visit_existing_[no]follow for consistency, and fixed a a few typos in
> :  the description of --nofollow (``treat broken symbolic links /count/
> :  as if they were exi/s/ting'').

I've applied your patch.  Mnay thanks for your contribution.  I did
change a few things though :-

1. Arguments to Texinfo commands are enclosed in {} not (), and so a change 
   to find.texi was required in order for "make" to succeed.

2. I added test suite tests for the -E option (and the -e option).

3. I changed the type of check_existence from into to enum and added
    some comments to locate.c.

I've attached the modified patch, which has already been checked into
CVS.

Regards and thanks again,
James.
Index: doc/find.texi
===================================================================
RCS file: /cvsroot/findutils/findutils/doc/find.texi,v
retrieving revision 1.77
diff -u -r1.77 find.texi
--- doc/find.texi       28 Feb 2005 22:46:23 -0000      1.77
+++ doc/find.texi       18 Apr 2005 08:55:02 -0000
@@ -2673,19 +2673,28 @@
 The way in which broken symbolic links are treated is affected by the
 @samp{-L}, @samp{-P} and @samp{-H} options.
 
[EMAIL PROTECTED] --non-existing
[EMAIL PROTECTED] -E
+Only print out such names which currently do not exist (instead of
+such names which existed when the database was created).  Note that
+this may slow down the program a lot, if there are many matches in the
+database.  The way in which broken symbolic links are treated is
+affected by the @samp{-L}, @samp{-P} and @samp{-H} options.
+
 @item --follow
 @itemx -L
-If testing for the existence of files (with the @samp{-e} option),
-omit broken symbolic links.  This is the default.
+If testing for the existence of files (with the @samp{-e} or @samp{-E}
+options), consider broken symbolic links to be non-existing.  This is
+the default.
 
 
 @item --nofollow
 @itemx -P
 @itemx -H
-If testing for the existence of files (with the @samp{-e} option),
-treat broken symbolic links count as if they were exiting files.  The
[EMAIL PROTECTED] form of this option is provided purely for similarity with
[EMAIL PROTECTED]; the use of @samp{-P} is recommended over @samp{-H}.
+If testing for the existence of files (with the @samp{-e} or @samp{-E}
+options), treat broken symbolic links as if they were existing files.
+The @samp{-H} form of this option is provided purely for similarity
+with @code{find}; the use of @samp{-P} is recommended over @samp{-H}.
 
 @item --ignore-case
 @itemx -i
Index: locate/locate.1
===================================================================
RCS file: /cvsroot/findutils/findutils/locate/locate.1,v
retrieving revision 1.19
diff -u -r1.19 locate.1
--- locate/locate.1     1 Apr 2005 16:19:52 -0000       1.19
+++ locate/locate.1     18 Apr 2005 08:55:02 -0000
@@ -3,10 +3,11 @@
 locate \- list files in databases that match a pattern
 .SH SYNOPSIS
 .B locate
-[\-d path | \-\-database=path] [\-e | \-\-existing] [\-i | \-\-ignore-case]
-[\-0 | \-\-null] [\-c | \-\-count] [\-w | \-\-wholename] [\-b | \-\-basename] 
-[\-l N | \-\-limit=N] [\-S | \-\-statistics] [\-r | \-\-regex ]
-[\-P | \-H | \-\-nofollow] [\-L | \-\-follow] [\-\-version] [\-\-help] 
pattern...
+[\-d path | \-\-database=path] [\-e | \-E | \-\-[non\-]existing] [\-i
+| \-\-ignore-case] [\-0 | \-\-null] [\-c | \-\-count] [\-w | \-\-wholename]
+|\-b | \-\-basename] [\-l N | \-\-limit=N] [\-S | \-\-statistics] [\-r
+| \-\-regex ] [\-P | \-H | \-\-nofollow] [\-L | \-\-follow] [\-\-version]
+[\-\-help] pattern...
 .SH DESCRIPTION
 This manual page
 documents the GNU version of
@@ -80,13 +81,19 @@
 .B locate 
 has checked that it exists, but before you use it.
 .TP
+.I "\-E, \-\-non\-existing"
+Only print out such names that currently do not exist (instead of such names
+that existed when the database was created).
+Note that this may slow down the program a lot, if there are many matches
+in the database.
+.TP
 .I "\-L, \-\-follow"
-If testing for the existence of files (with the \-e option), omit
-broken symbolic links.   This is the default.
+If testing for the existence of files (with the \-e or \-E options),
+consider broken symbolic links to be non-existing.   This is the default.
 .TP
 .I "\-P, \-H, \-\-nofollow"
-If testing for the existence of files (with the \-e option), treat
-broken symbolic links count as if they were exiting files.  The \-H
+If testing for the existence of files (with the \-e or \-E options), treat
+broken symbolic links as if they were existing files.  The \-H
 form of this option is provided purely for similarity with
 .BR find ;
 the use of \-P is recommended over \-H.
Index: locate/locate.c
===================================================================
RCS file: /cvsroot/findutils/findutils/locate/locate.c,v
retrieving revision 1.43
diff -u -r1.43 locate.c
--- locate/locate.c     4 Mar 2005 10:39:13 -0000       1.43
+++ locate/locate.c     18 Apr 2005 08:55:02 -0000
@@ -135,8 +135,23 @@
 
 #define WARN_SECONDS ((SECONDS_PER_UNIT) * (WARN_NUMBER_UNITS))
 
+enum visit_result
+  {
+    VISIT_CONTINUE = 1,  /* please call the next visitor */
+    VISIT_ACCEPTED = 2,  /* accepted, call no futher callbacks for this file */
+    VISIT_REJECTED = 4,  /* rejected, process next file. */
+    VISIT_ABORT    = 8   /* rejected, process no more files. */
+  };
+
+enum ExistenceCheckType 
+  {
+    ACCEPT_EITHER,             /* Corresponds to lack of -E/-e option */
+    ACCEPT_EXISTING,           /* Corresponds to option -e */
+    ACCEPT_NON_EXISTING                /* Corresponds to option -E */
+  };
+
 /* Check for existence of files before printing them out? */
-static int check_existence = 0;
+enum ExistenceCheckType check_existence = ACCEPT_EITHER;
 
 static int follow_symlinks = 1;
 
@@ -231,15 +246,6 @@
   *dest = 0;
 }
 
-enum visit_result
-  {
-    VISIT_CONTINUE = 1,  /* please call the next visitor */
-    VISIT_ACCEPTED = 2,  /* accepted, call no futher callbacks for this file */
-    VISIT_REJECTED = 4,  /* rejected, process next file. */
-    VISIT_ABORT    = 8   /* rejected, process no more files. */
-  };
-
-
 struct locate_stats
 {
   uintmax_t compressed_bytes;
@@ -330,9 +336,11 @@
   return VISIT_CONTINUE;
 }
 
+/* visit_existing_follow implements -L -e */
 static int
-visit_exists_follow(const char *munged_filename,
-                   const char *original_filename, void *context)
+visit_existing_follow(const char *munged_filename,
+                     const char *original_filename,
+                     void *context)
 {
   struct stat st;
   (void) context;
@@ -353,9 +361,36 @@
     }
 }
 
+/* visit_existing_follow implements -L -E */
+static int
+visit_non_existing_follow(const char *munged_filename,
+                         const char *original_filename,
+                         void *context)
+{
+  struct stat st;
+  (void) context;
+  (void) munged_filename;
+
+  /* munged_filename has been converted in some way (to lower case,
+   * or is just the base name of the file), and original_filename has not.  
+   * Hence only original_filename is still actually the name of the file 
+   * whose existence we would need to check.
+   */
+  if (stat(original_filename, &st) == 0)
+    {
+      return VISIT_REJECTED;
+    }
+  else
+    {
+      return VISIT_CONTINUE;
+    }
+}
+
+/* visit_existing_nofollow implements -P -e */
 static int
-visit_exists_nofollow(const char *munged_filename,
-                     const char *original_filename, void *context)
+visit_existing_nofollow(const char *munged_filename,
+                       const char *original_filename,
+                       void *context)
 {
   struct stat st;
   (void) context;
@@ -376,8 +411,35 @@
     }
 }
 
+/* visit_existing_nofollow implements -P -E */
 static int
-visit_substring_match_nocasefold(const char *munged_filename, const char 
*original_filename, void *context)
+visit_non_existing_nofollow(const char *munged_filename,
+                           const char *original_filename,
+                           void *context)
+{
+  struct stat st;
+  (void) context;
+  (void) munged_filename;
+
+  /* munged_filename has been converted in some way (to lower case,
+   * or is just the base name of the file), and original_filename has not.  
+   * Hence only original_filename is still actually the name of the file 
+   * whose existence we would need to check.
+   */
+  if (lstat(original_filename, &st) == 0)
+    {
+      return VISIT_REJECTED;
+    }
+  else
+    {
+      return VISIT_CONTINUE;
+    }
+}
+
+static int
+visit_substring_match_nocasefold(const char *munged_filename,
+                                const char *original_filename,
+                                void *context)
 {
   const char *pattern = context;
   (void) original_filename;
@@ -389,7 +451,9 @@
 }
 
 static int
-visit_substring_match_casefold(const char *munged_filename, const char 
*original_filename, void *context)
+visit_substring_match_casefold(const char *munged_filename,
+                              const char *original_filename,
+                              void *context)
 {
   struct casefolder * p = context;
   size_t len = strlen(munged_filename);
@@ -411,7 +475,9 @@
 
 
 static int
-visit_globmatch_nofold(const char *munged_filename, const char 
*original_filename, void *context)
+visit_globmatch_nofold(const char *munged_filename,
+                      const char *original_filename,
+                      void *context)
 {
   const char *glob = context;
   (void) original_filename;
@@ -423,7 +489,9 @@
 
 
 static int
-visit_globmatch_casefold(const char *munged_filename, const char 
*original_filename, void *context)
+visit_globmatch_casefold(const char *munged_filename,
+                        const char *original_filename,
+                        void *context)
 {
   const char *glob = context;
   (void) original_filename;
@@ -435,7 +503,9 @@
 
 
 static int
-visit_regex(const char *munged_filename, const char *original_filename, void 
*context)
+visit_regex(const char *munged_filename,
+           const char *original_filename,
+           void *context)
 {
   struct regular_expression *p = context;
   (void) original_filename;
@@ -448,7 +518,9 @@
 
 
 static int
-visit_stats(const char *munged_filename, const char *original_filename, void 
*context)
+visit_stats(const char *munged_filename,
+           const char *original_filename,
+           void *context)
 {
   struct locate_stats *p = context;
   size_t len = strlen(original_filename);
@@ -611,21 +683,31 @@
            }
        }
 
-      /* We add visit_exists_*() as late as possible to reduce the
+      /* We add visit_existing_*() as late as possible to reduce the
        * number of stat() calls.
        */
-      if (check_existence)
+      switch (check_existence)
        {
-         visitfunc f;
-         if (follow_symlinks)
-           f = visit_exists_follow;
-         else
-           f = visit_exists_nofollow;
+       case ACCEPT_EXISTING:
+         if (follow_symlinks)  /* -L, default */
+           add_visitor(visit_existing_follow, NULL);
+         else                  /* -P */
+           add_visitor(visit_existing_nofollow, NULL);
+         break;
          
-         add_visitor(f, NULL);
+       case ACCEPT_NON_EXISTING:
+         if (follow_symlinks)  /* -L, default */
+           add_visitor(visit_non_existing_follow, NULL);
+         else                  /* -P */
+           add_visitor(visit_non_existing_nofollow, NULL);
+         break;
+
+       case ACCEPT_EITHER:     /* Default, neither -E nor -e */
+         /* do nothing; no extra processing. */
+         break;
        }
       
-
+      
       if (enable_print)
        add_visitor(visit_justprint, NULL);
     }
@@ -778,7 +860,7 @@
      FILE *stream;
 {
   fprintf (stream, _("\
-Usage: %s [-d path | --database=path] [-e | --existing]\n\
+Usage: %s [-d path | --database=path] [-e | -E | --[non-]existing]\n\
       [-i | --ignore-case] [-w | --wholename] [-b | --basename] \n\
       [--limit=N | -l N] [-S | --statistics] [-0 | --null] [-c | --count]\n\
       [-P | -H | --nofollow] [-L | --follow] [-m | --mmap ] [ -s | --stdio ]\n\
@@ -791,6 +873,7 @@
 {
   {"database", required_argument, NULL, 'd'},
   {"existing", no_argument, NULL, 'e'},
+  {"non-existing", no_argument, NULL, 'E'},
   {"ignore-case", no_argument, NULL, 'i'},
   {"help", no_argument, NULL, 'h'},
   {"version", no_argument, NULL, 'v'},
@@ -839,9 +922,9 @@
   if (dbpath == NULL)
     dbpath = LOCATE_DB;
 
-  check_existence = 0;
+  check_existence = ACCEPT_EITHER;
 
-  while ((optc = getopt_long (argc, argv, "bcd:eil:rsm0SwHPL", longopts, (int 
*) 0)) != -1)
+  while ((optc = getopt_long (argc, argv, "bcd:eEil:rsm0SwHPL", longopts, (int 
*) 0)) != -1)
     switch (optc)
       {
       case '0':
@@ -862,7 +945,11 @@
        break;
 
       case 'e':
-       check_existence = 1;
+       check_existence = ACCEPT_EXISTING;
+       break;
+
+      case 'E':
+       check_existence = ACCEPT_NON_EXISTING;
        break;
 
       case 'i':
Index: locate/testsuite/Makefile.am
===================================================================
RCS file: /cvsroot/findutils/findutils/locate/testsuite/Makefile.am,v
retrieving revision 1.7
diff -u -r1.7 Makefile.am
--- locate/testsuite/Makefile.am        6 Feb 2005 10:16:34 -0000       1.7
+++ locate/testsuite/Makefile.am        18 Apr 2005 08:55:02 -0000
@@ -10,12 +10,24 @@
 locate.gnu/ignore_case1.exp \
 locate.gnu/ignore_case2.exp \
 locate.gnu/ignore_case3.exp \
-locate.gnu/regex1.exp
+locate.gnu/regex1.exp \
+locate.gnu/exists1.exp \
+locate.gnu/exists2.exp \
+locate.gnu/exists3.exp \
+locate.gnu/notexists1.exp \
+locate.gnu/notexists2.exp \
+locate.gnu/notexists3.exp
 
 EXTRA_DIST_XO = \
 locate.gnu/ignore_case1.xo \
 locate.gnu/ignore_case2.xo \
-locate.gnu/ignore_case3.xo
+locate.gnu/ignore_case3.xo \
+locate.gnu/exists1.xo \
+locate.gnu/exists2.xo \
+locate.gnu/exists3.xo \
+locate.gnu/notexists1.xo \
+locate.gnu/notexists2.xo \
+locate.gnu/notexists3.xo
 
 
 EXTRA_DIST = $(EXTRA_DIST_EXP) $(EXTRA_DIST_XO)
Index: locate/testsuite/config/unix.exp
===================================================================
RCS file: /cvsroot/findutils/findutils/locate/testsuite/config/unix.exp,v
retrieving revision 1.9
diff -u -r1.9 unix.exp
--- locate/testsuite/config/unix.exp    31 Jan 2005 23:40:27 -0000      1.9
+++ locate/testsuite/config/unix.exp    18 Apr 2005 08:55:04 -0000
@@ -154,7 +154,9 @@
 # Run locate and leave the output in $comp_output.
 # Called by individual test scripts.
 proc locate_start { passfail updatedb_options locate_options
-                   {updatedb_infile ""} {locate_infile ""}} {
+                   {updatedb_infile ""} {locate_infile ""}
+                   { between_hook "" }
+               } {
     global verbose
     global LOCATE
     global LOCATEFLAGS
@@ -203,6 +205,7 @@
     }
 
     catch "exec $updatedb_cmd" comp_output
+    eval $between_hook
     catch "exec $locate_cmd" comp_output
     if {$comp_output != ""} then {
        send_log "$comp_output\n"
Index: locate/testsuite/locate.gnu/exists1.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/exists1.exp
diff -N locate/testsuite/locate.gnu/exists1.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists1.exp     18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,8 @@
+# tests for -e: make sure we print a file if it exists.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred
+locate_start p "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -e fred" {}
+
Index: locate/testsuite/locate.gnu/exists1.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/exists1.xo
diff -N locate/testsuite/locate.gnu/exists1.xo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists1.xo      18 Apr 2005 08:55:04 -0000
@@ -0,0 +1 @@
+tmp/subdir/fred
Index: locate/testsuite/locate.gnu/exists2.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/exists2.exp
diff -N locate/testsuite/locate.gnu/exists2.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists2.exp     18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,9 @@
+# tests for -e: make sure we do not print a file if it does not exist.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred1
+exec touch $tmp/subdir/fred2
+locate_start p "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -e fred" {} {} { exec rm "tmp/subdir/fred2" } 
+
Index: locate/testsuite/locate.gnu/exists2.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/exists2.xo
diff -N locate/testsuite/locate.gnu/exists2.xo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists2.xo      18 Apr 2005 08:55:04 -0000
@@ -0,0 +1 @@
+tmp/subdir/fred1
Index: locate/testsuite/locate.gnu/exists3.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/exists3.exp
diff -N locate/testsuite/locate.gnu/exists3.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists3.exp     18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,9 @@
+# tests for -e: make sure we do not print a file if it does not exist.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred1
+exec touch $tmp/subdir/fred2
+locate_start p "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -e fred" {} {} { exec rm "tmp/subdir/fred1" } 
+
Index: locate/testsuite/locate.gnu/exists3.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/exists3.xo
diff -N locate/testsuite/locate.gnu/exists3.xo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/exists3.xo      18 Apr 2005 08:55:04 -0000
@@ -0,0 +1 @@
+tmp/subdir/fred2
Index: locate/testsuite/locate.gnu/notexists1.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists1.exp
diff -N locate/testsuite/locate.gnu/notexists1.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/notexists1.exp  18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,10 @@
+# tests for -E: make sure we don't print a file if it exists.
+# Since there are no matches in this case, we expect a nonzero
+# return value as well.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred
+locate_start f "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -E fred" {}
+
Index: locate/testsuite/locate.gnu/notexists1.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists1.xo
diff -N locate/testsuite/locate.gnu/notexists1.xo
Index: locate/testsuite/locate.gnu/notexists2.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists2.exp
diff -N locate/testsuite/locate.gnu/notexists2.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/notexists2.exp  18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,9 @@
+# tests for -E: make sure we do print a file if it does not exist.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred1
+exec touch $tmp/subdir/fred2
+locate_start p "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -E fred" {} {} { exec rm "tmp/subdir/fred2" } 
+
Index: locate/testsuite/locate.gnu/notexists2.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists2.xo
diff -N locate/testsuite/locate.gnu/notexists2.xo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/notexists2.xo   18 Apr 2005 08:55:04 -0000
@@ -0,0 +1 @@
+tmp/subdir/fred2
Index: locate/testsuite/locate.gnu/notexists3.exp
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists3.exp
diff -N locate/testsuite/locate.gnu/notexists3.exp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/notexists3.exp  18 Apr 2005 08:55:04 -0000
@@ -0,0 +1,9 @@
+# tests for -E: make sure we do not print a file if it does not exist.
+set tmp "tmp"
+exec rm -rf $tmp
+exec mkdir $tmp
+exec mkdir $tmp/subdir
+exec touch $tmp/subdir/fred1
+exec touch $tmp/subdir/fred2
+locate_start p "--changecwd=. --output=$tmp/locatedb --localpaths=tmp/subdir/" 
"--database=$tmp/locatedb -E fred" {} {} { exec rm "tmp/subdir/fred1" } 
+
Index: locate/testsuite/locate.gnu/notexists3.xo
===================================================================
RCS file: locate/testsuite/locate.gnu/notexists3.xo
diff -N locate/testsuite/locate.gnu/notexists3.xo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ locate/testsuite/locate.gnu/notexists3.xo   18 Apr 2005 08:55:04 -0000
@@ -0,0 +1 @@
+tmp/subdir/fred1
_______________________________________________
Bug-findutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-findutils

Reply via email to