Subject: [PATCH] wrapper: Fix a errno discrepancy on NetBSD.

From: Collin Funk <[email-masked]>
Date: Fri, 2 May 2025 16:33:32 -0700

As documented on NetBSD's man page, open with the O_NOFOLLOW flag and a
symlink returns -1 and sets errno to EFTYPE which differs from POSIX.
This patch fixes the following test failure:

$ sh t0602-reffiles-fsck.sh --verbose
--- expect	2025-05-02 23:05:23.920890147 +0000
+++ err	2025-05-02 23:05:23.916794959 +0000
@@ -1 +1 @@
-error: packed-refs: badRefFiletype: not a regular file but a symlink
+error: unable to open '.git/packed-refs': Inappropriate file type or format
not ok 12 - the filetype of packed-refs should be checked

This portability issue was introduced in Commit
cfea2f2da8 (packed-backend: check whether the "packed-refs" is regular file, 2025-02-28)

Signed-off-by: Collin Funk <[email-masked]>
---
 wrapper.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/wrapper.c b/wrapper.c
index 3c79778055..4d448d7c57 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -737,7 +737,19 @@ int is_empty_or_missing_file(const char *filename)
 int open_nofollow(const char *path, int flags)
 {
 #ifdef O_NOFOLLOW
-	return open(path, flags | O_NOFOLLOW);
+	int ret = open(path, flags | O_NOFOLLOW);
+#ifdef __NetBSD__
+	/*
+	 * NetBSD sets errno to EFTYPE when path is a symlink. The only other
+	 * time this errno occurs when O_REGULAR is used. Since we don't use
+	 * it anywhere we can avoid an lstat here.
+	 */
+	if (ret < 0 && errno == EFTYPE) {
+		errno = ELOOP;
+		return -1;
+	}
+#endif
+	return ret;
 #else
 	struct stat st;
 	if (lstat(path, &st) < 0)
-- 
2.49.0