On 2025-11-16 22:57, Bruno Haible wrote:
These two new tests fail on NetBSD 10.0:

Thanks, I installed the attached which fixed things for me on NetBSD 10.0.
From 20074698382b7e4f049f52bbdeaf6a39508a8601 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Mon, 17 Nov 2025 16:28:24 -0800
Subject: [PATCH] openat2: follow OS re EFTYPE/EMLINK/ELOOP
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

On FreeBSD and NetBSD, have openat2 behave like openat
with respect to whether O_NOFOLLOW fails with EMLINK and EFTYPE
when opening a symlink.  Although these openat implementations
do not conform to POSIX, their behavior is arguably more useful
than the POSIX behavior so let’s have openat2 be consistent with
openat rather than matching the GNU/Linux behavior.
This should fix a test failure reported by Bruno Haible in:
https://lists.gnu.org/r/bug-gnulib/2025-11/msg00183.html
* lib/fcntl.in.h (_GL_OPENAT_ESYMLINK): New macro.
* lib/openat2.c (do_openat2): Use it instead of ELOOP.
* tests/test-openat2.c (is_nofollow_error):
Use it; this makes the tests pickier on FreeBSD and NetBSD,
as they now require local behavior.
---
 ChangeLog            | 17 +++++++++++++++++
 lib/fcntl.in.h       |  9 +++++++++
 lib/openat2.c        |  6 +++---
 tests/test-openat2.c | 10 +---------
 4 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d6350250e8..823398850d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2025-11-17  Paul Eggert  <[email protected]>
+
+	openat2: follow OS re EFTYPE/EMLINK/ELOOP
+	On FreeBSD and NetBSD, have openat2 behave like openat
+	with respect to whether O_NOFOLLOW fails with EMLINK and EFTYPE
+	when opening a symlink.  Although these openat implementations
+	do not conform to POSIX, their behavior is arguably more useful
+	than the POSIX behavior so let’s have openat2 be consistent with
+	openat rather than matching the GNU/Linux behavior.
+	This should fix a test failure reported by Bruno Haible in:
+	https://lists.gnu.org/r/bug-gnulib/2025-11/msg00183.html
+	* lib/fcntl.in.h (_GL_OPENAT_ESYMLINK): New macro.
+	* lib/openat2.c (do_openat2): Use it instead of ELOOP.
+	* tests/test-openat2.c (is_nofollow_error):
+	Use it; this makes the tests pickier on FreeBSD and NetBSD,
+	as they now require local behavior.
+
 2025-11-17  Bruno Haible  <[email protected]>
 
 	readutmp, boot-time tests: Fix test failure in CentOS 7 CI environments.
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 3fbbf4b0e4..bcb5606b13 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -495,6 +495,15 @@ _GL_WARN_ON_USE (openat2, "openat2 is not portable - "
 # define AT_NO_AUTOMOUNT 0
 #endif
 
+/* errno when openat+O_NOFOLLOW fails because the file is a symlink.  */
+#if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __DragonFly__
+# define _GL_OPENAT_ESYMLINK EMLINK
+#elif defined __NetBSD__
+# define _GL_OPENAT_ESYMLINK EFTYPE
+#else
+# define _GL_OPENAT_ESYMLINK ELOOP
+#endif
+
 #endif /* _@GUARD_PREFIX@_FCNTL_H */
 #endif /* _@GUARD_PREFIX@_FCNTL_H */
 #endif
diff --git a/lib/openat2.c b/lib/openat2.c
index 9281e7a1a2..d616b80a55 100644
--- a/lib/openat2.c
+++ b/lib/openat2.c
@@ -333,7 +333,7 @@ do_openat2 (int *fd, char const *filename,
           if (subfd < 0)
             {
               int openerr = negative_errno ();
-              if (! ((openerr == -ELOOP)
+              if (! ((openerr == -_GL_OPENAT_ESYMLINK)
                      | (!!(subflags & O_DIRECTORY) & (openerr == -ENOTDIR))))
                 return openerr;
 
@@ -363,7 +363,7 @@ do_openat2 (int *fd, char const *filename,
                 }
 
               if (maxlinks <= 0)
-                return -ELOOP;
+                return -_GL_OPENAT_ESYMLINK;
               maxlinks--;
 
               /* A symlink and the symlink loop count is not exhausted.
@@ -386,7 +386,7 @@ do_openat2 (int *fd, char const *filename,
                   if (r < 0)
                     return negative_errno ();
                   if (st.f_type == S_MAGIC_PROC)
-                    return -ELOOP;
+                    return -_GL_OPENAT_ESYMLINK;
                 }
 #endif
 
diff --git a/tests/test-openat2.c b/tests/test-openat2.c
index 3f9dc70039..12830a0bc9 100644
--- a/tests/test-openat2.c
+++ b/tests/test-openat2.c
@@ -333,15 +333,7 @@ do_test_flags (void)
 static bool
 is_nofollow_error (int err)
 {
-#ifdef EFTYPE /* NetBSD openat+O_NOFOLLOW on symlink */
-  if (err == EFTYPE)
-    return true;
-#endif
-#ifdef EMLINK /* FreeBSD openat+O_NOFOLLOW on symlink */
-  if (err == EMLINK)
-    return true;
-#endif
-  return err == ELOOP;
+  return err == _GL_OPENAT_ESYMLINK;
 }
 
 static void
-- 
2.51.0

Reply via email to