The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=77eb877714d69ee0279d70eb3331920fba90db95

commit 77eb877714d69ee0279d70eb3331920fba90db95
Author:     John Baldwin <[email protected]>
AuthorDate: 2024-09-04 19:53:17 +0000
Commit:     John Baldwin <[email protected]>
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;

Reply via email to