From deee128cf1f8101ec4385b21edbdce9d60ff0d3a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Aug 2026 21:31:22 +1000 Subject: [PATCH] syscall: guard do_mknod_atfd()'s mknodat() with HAVE_MKNODAT It used HAVE_MKNOD. Older Darwin has mknod() but not mknodat(), so the call was compiled and then failed to link: "_mknodat", referenced from: _do_mknod_atfd in syscall.o ld: symbol(s) not found for architecture x86_64 Reported on macOS 10.13.6 x86_64, where config.h carries /* #undef HAVE_MKNODAT */ next to #define HAVE_MKNOD 1. The sibling do_mknod_at() already keys off HAVE_MKNODAT and its comment names this exact platform. Both occurrences change together. The second guards return -1; /* mknodat()'s errno (regular/device node) */ against an ENOSYS fallback, so leaving it on HAVE_MKNOD would report "mknodat()'s errno" on a build where the call was never compiled -- a stale errno from whatever ran last. Checked by rewriting config.h the way that platform has it and compiling syscall.c: the parent leaves one unresolved mknodat reference, this leaves none. A FIFO still goes to mkfifoat() where that exists, and a socket still returns EOPNOTSUPP; only the regular/device-node path becomes ENOSYS, which is what a platform without mknodat() can offer. (cherry picked from commit c4588734811307526d58a97a068daf3d0fc083ce) # Conflicts: # syscall.c --- syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/syscall.c b/syscall.c index c5d73cfb..5fe45c85 100644 --- a/syscall.c +++ b/syscall.c @@ -3786,13 +3786,18 @@ int do_mknod_atfd(int dfd, const char *name, mode_t mode, dev_t dev) return (close(fd) < 0) ? -1 : 0; } -#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO +/* HAVE_MKFIFOAT/HAVE_MKNODAT, not HAVE_MKFIFO/HAVE_MKNOD: older Darwin has + * mkfifo() and mknod() but neither *at() form, so keying off the former + * compiles calls that then fail to link (#161). */ +#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFOAT if (S_ISFIFO(mode)) return mkfifoat(dfd, name, mode); #endif -#ifdef HAVE_MKNOD +#ifdef HAVE_MKNODAT return mknodat(dfd, name, mode, dev); #else + /* Must match the guard above: no fd-relative create was compiled, so the + * caller falls back to the path-based variant. */ (void)dev; errno = ENOSYS; return -1;