Git fork

wrapper: NetBSD gives EFTYPE and FreeBSD gives EMFILE where POSIX uses ELOOP

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

FreeBSD has the same issue for EMLINK instead of EFTYPE.

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

Signed-off-by: Collin Funk <collin.funk1@gmail.com>
Acked-by: brian m. carlson <sandals@crustytoothpaste.net>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Collin Funk and committed by
Junio C Hamano
f47bcc34 d50a5e89

+20 -1
+20 -1
wrapper.c
··· 737 737 int open_nofollow(const char *path, int flags) 738 738 { 739 739 #ifdef O_NOFOLLOW 740 - return open(path, flags | O_NOFOLLOW); 740 + int ret = open(path, flags | O_NOFOLLOW); 741 + /* 742 + * NetBSD sets errno to EFTYPE when path is a symlink. The only other 743 + * time this errno occurs when O_REGULAR is used. Since we don't use 744 + * it anywhere we can avoid an lstat here. FreeBSD does the same with 745 + * EMLINK. 746 + */ 747 + # ifdef __NetBSD__ 748 + # define SYMLINK_ERRNO EFTYPE 749 + # elif defined(__FreeBSD__) 750 + # define SYMLINK_ERRNO EMLINK 751 + # endif 752 + # if SYMLINK_ERRNO 753 + if (ret < 0 && errno == SYMLINK_ERRNO) { 754 + errno = ELOOP; 755 + return -1; 756 + } 757 + # undef SYMLINK_ERRNO 758 + # endif 759 + return ret; 741 760 #else 742 761 struct stat st; 743 762 if (lstat(path, &st) < 0)