git: 77eb877714d6 - main - grep: Fix various bugs in recursive tree handling
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 04 Sep 2024 19:53:55 UTC
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=77eb877714d69ee0279d70eb3331920fba90db95
commit 77eb877714d69ee0279d70eb3331920fba90db95
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-09-04 19:53:17 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-09-04 19:53:17 +0000
grep: Fix various bugs in recursive tree handling
The -OpS options were effectively ignored due to a collection of
bugs in the use of fts(3):
- fts_open(3) requires one of FTS_PHYSICAL or FTS_LOGICAL to be
specified, but in the -O case, only FTS_COMFOLLOW was given. Fix
this to use FTS_COMFOLLOW | FTS_PHYSICAL.
- The switch on the entry type returned by fts_read() did not check
for symbolic links, so symbolic links fell into the default case and
were always passed to procfile() even when -p was given. Fix this
by adding cases in the switch statement to explicitly ignore FTS_SL.
- FTS_NOSTAT was passed to fts_open(), so fts_open() couldn't detect
symbolic links when FTS_PHYSICAL was passed, instead both regular
files and symbolic links were returned as FTS_NSOK entries. Fix
by only using FTS_NOSTAT with FTS_LOGICAL.
While here, fix a few other nits:
- Treat FTS_NS as an error like FTS_DNR and FTS_ERR.
- Just ignore FTS_DP. The logic to skip descending into skipped
directories is only relevant when a directory is first visited, not
after the directory has been visited.
- Use warnc instead of warnx + strerror.
PR: 280676
Reviewed by: kevans
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D46255
---
usr.bin/grep/util.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/usr.bin/grep/util.c b/usr.bin/grep/util.c
index 936abc41b3ef..4e1c44b442f2 100644
--- a/usr.bin/grep/util.c
+++ b/usr.bin/grep/util.c
@@ -136,16 +136,16 @@ grep_tree(char **argv)
/* This switch effectively initializes 'fts_flags' */
switch(linkbehave) {
case LINK_EXPLICIT:
- fts_flags = FTS_COMFOLLOW;
+ fts_flags = FTS_COMFOLLOW | FTS_PHYSICAL;
break;
case LINK_SKIP:
fts_flags = FTS_PHYSICAL;
break;
default:
- fts_flags = FTS_LOGICAL;
+ fts_flags = FTS_LOGICAL | FTS_NOSTAT;
}
- fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
+ fts_flags |= FTS_NOCHDIR;
fts = fts_open((argv[0] == NULL) ?
__DECONST(char * const *, wd) : argv, fts_flags, NULL);
@@ -154,15 +154,13 @@ grep_tree(char **argv)
while (errno = 0, (p = fts_read(fts)) != NULL) {
switch (p->fts_info) {
case FTS_DNR:
- /* FALLTHROUGH */
case FTS_ERR:
+ case FTS_NS:
file_err = true;
if(!sflag)
- warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ warnc(p->fts_errno, "%s", p->fts_path);
break;
case FTS_D:
- /* FALLTHROUGH */
- case FTS_DP:
if (dexclude || dinclude)
if (!dir_matching(p->fts_name) ||
!dir_matching(p->fts_path))
@@ -173,6 +171,17 @@ grep_tree(char **argv)
warnx("warning: %s: recursive directory loop",
p->fts_path);
break;
+ case FTS_DP:
+ break;
+ case FTS_SL:
+ /*
+ * Skip symlinks for LINK_EXPLICIT and
+ * LINK_SKIP. Note that due to FTS_COMFOLLOW,
+ * symlinks on the command line are followed
+ * for LINK_EXPLICIT and not reported as
+ * symlinks.
+ */
+ break;
default:
/* Check for file exclusion/inclusion */
ok = true;