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. address@hidden --non-existing address@hidden -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 address@hidden form of this option is provided purely for similarity with address@hidden; 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