Subject: bug#18892: few test failure with 'grep-2.20.72-d512'

From: Paul Eggert <[email-masked]>
Date: Sun, 02 Nov 2014 22:16:04 -0800

Assaf Gordon wrote:
> Attached is the ktrace+tdump output of running the command.

Thanks, I see the problem now: NetBSD uses a nonstandard errno value when openat 
(fd, "symlink", ... O_NOFOLLOW ...) fails.  I installed the attached, which 
should fix the NetBSD problem.
From a942961860982a7d48487be262556809b0b0b26b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 2 Nov 2014 22:11:34 -0800
Subject: [PATCH] grep: port O_NOFOLLOW errno checking to NetBSD

Problem reported by Assaf Gordon in: http://bugs.gnu.org/18892
* NEWS: Document it.
* src/grep.c (open_symlink_nofollow_error):
New function, which does the right thing on NetBSD.
(grepfile): Use it.
---
 NEWS       |  4 ++++
 src/grep.c | 16 +++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 07a5d54..47af472 100644
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,10 @@ GNU grep NEWS                                    -*- outline -*-
   grep -E rejected unmatched ')', instead of treating it like '\)'.
   [bug present since "the beginning"]
 
+  On NetBSD, grep -r no longer reports "Inappropriate file type or format"
+  when refusing to follow a symbolic link.
+  [bug introduced in grep-2.12]
+
 ** Changes in behavior
 
   The GREP_OPTIONS environment variable is now obsolescent, and grep
diff --git a/src/grep.c b/src/grep.c
index 0a4ac27..8dbf86e 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -1513,13 +1513,27 @@ grepdirent (FTS *fts, FTSENT *ent, bool command_line)
   return grepfile (dirdesc, ent->fts_accpath, follow, command_line);
 }
 
+/* True if errno is ERR after 'open ("symlink", ... O_NOFOLLOW ...)'.
+   POSIX specifies ELOOP, but it's EMLINK on FreeBSD and EFTYPE on NetBSD.  */
+static bool
+open_symlink_nofollow_error (int err)
+{
+  if (err == ELOOP || err == EMLINK)
+    return true;
+#ifdef EFTYPE
+  if (err == EFTYPE)
+    return true;
+#endif
+  return false;
+}
+
 static bool
 grepfile (int dirdesc, char const *name, bool follow, bool command_line)
 {
   int desc = openat_safer (dirdesc, name, O_RDONLY | (follow ? 0 : O_NOFOLLOW));
   if (desc < 0)
     {
-      if (follow || (errno != ELOOP && errno != EMLINK))
+      if (follow || ! open_symlink_nofollow_error (errno))
         suppressible_error (filename, errno);
       return true;
     }
-- 
1.9.3