Collin Funk <[email protected]> writes: > Hopefully I am just missing something silly, or perhaps it is not even > worth the effort and using "#ifdef __APPLE__" is enough.
Given that the issue exists on all non-EOL macOS versions, I think I am okay with just using "#ifdef __APPLE__". I am leaning towards applying the attached patch, but will sleep on it and give others a chance to review. Collin
>From 07a80c39c13ce19fbf229104fa9943681acf30c6 Mon Sep 17 00:00:00 2001 Message-ID: <07a80c39c13ce19fbf229104fa9943681acf30c6.1780719116.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Fri, 5 Jun 2026 21:01:26 -0700 Subject: [PATCH v2] install: workaround a macOS bug that prevents reading standard input * src/copy.c (follow_fstatat): Prefer openat and fstat on macOS. * tests/install/stdin.sh: Remove the skip condition added in commit 2632fbf08 (tests: install: avoid failure on FreeBSD/macOS, 2026-06-03). Fixes https://bugs.gnu.org/70411 --- src/copy.c | 26 +++++++++++++++++++++++++- tests/install/stdin.sh | 5 ----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/copy.c b/src/copy.c index a53fb8f8c..252a9c4ab 100644 --- a/src/copy.c +++ b/src/copy.c @@ -186,7 +186,31 @@ emit_debug (const struct cp_options *x) static int follow_fstatat (int dirfd, char const *filename, struct stat *st, int flags) { - int result = fstatat (dirfd, filename, st, flags); + int result = -1; + bool try_fstatat = true; + + /* Work around a macOS bug where stat and fstat give us a different dev/ino. + See the following threads: + <https://bugs.gnu.org/70411> + <https://lists.gnu.org/r/coreutils/2026-06/msg00004.html>. */ +#ifdef __APPLE__ + int open_flags = (O_RDONLY | O_NOCTTY | O_NONBLOCK + | ((flags & AT_SYMLINK_NOFOLLOW) ? O_NOFOLLOW : 0)); + int fd = openat (dirfd, filename, open_flags); + + /* If openat fails, try to use fstatat unless we are certain it will also + fail. E.g., if the given file is not readable openat will fail but + fstatat may succeed. */ + try_fstatat = fd < 0 && errno != ENOENT && errno != ENOTDIR; + if (0 <= fd) + { + result = fstat (fd, st); + close (fd); + } +#endif + + if (result < 0 && try_fstatat) + result = fstatat (dirfd, filename, st, flags); if (DEV_FD_MIGHT_BE_CHR && result == 0 && !(flags & AT_SYMLINK_NOFOLLOW) && S_ISCHR (st->st_mode)) diff --git a/tests/install/stdin.sh b/tests/install/stdin.sh index 2e050059e..4ee8a85c9 100755 --- a/tests/install/stdin.sh +++ b/tests/install/stdin.sh @@ -26,11 +26,6 @@ tty=$(readlink -f /dev/stdin) test -r "$tty" 2>&1 \ || skip_ '/dev/stdin is not readable' -# work around FreeBSD / macOS issue as discussed at: -# https://lists.gnu.org/r/coreutils/2026-06/msg00004.html -test $(stat -L -c%i /dev/stdin) = $(stat -L -c%i - </dev/stdin) || - skip_ '/dev/stdin inode correlation mismatch' - echo a >a || framework_failure_ echo b >b || framework_failure_ -- 2.54.0
