From 77c34ca18e8a1e20b2a466e27d7eb3136d8bf08a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Jun 2026 14:46:38 +1000 Subject: [PATCH] build: fall back to do_mknod() when mknodat() is unavailable (#896) do_mknod_at() (the symlink-race-safe variant used by a non-chrooted daemon receiver) calls mknodat()/mkfifoat(), but the at-variant was gated only on AT_FDCWD. Older Darwin declares AT_FDCWD without mknodat(), so the build failed with "mknodat undeclared". Probe mknodat()/mkfifoat() in configure and require HAVE_MKNODAT for the at-variant; without it do_mknod_at() falls back to do_mknod(), exactly as it already does where AT_FDCWD is missing. Linux keeps the mknodat path since HAVE_MKNODAT is defined there. Thanks to @debohman for the report (#896). Fixes: #896 (cherry picked from commit 24d75c04e43b81d3af538002684999264f591876) --- configure.ac | 2 +- syscall.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4062651d..ff7c9aeb 100644 --- a/configure.ac +++ b/configure.ac @@ -888,7 +888,7 @@ AC_FUNC_UTIME_NULL AC_FUNC_ALLOCA AC_CHECK_FUNCS(waitpid wait4 getcwd chown chmod lchmod mknod mkfifo \ fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \ - chflags getattrlist mktime innetgr linkat \ + chflags getattrlist mktime innetgr linkat mknodat mkfifoat \ memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \ strlcat strlcpy stpcpy strtol mallinfo mallinfo2 getgroups setgroups geteuid getegid \ setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \ diff --git a/syscall.c b/syscall.c index 4f456807..95be2ac4 100644 --- a/syscall.c +++ b/syscall.c @@ -535,7 +535,9 @@ int do_mknod(const char *pathname, mode_t mode, dev_t dev) */ int do_mknod_at(const char *pathname, mode_t mode, dev_t dev) { -#ifdef AT_FDCWD + /* HAVE_MKNODAT: older Darwin declares AT_FDCWD but not mknodat(), so + * the at-variant won't build there; fall back to do_mknod() (#896). */ +#if defined(AT_FDCWD) && defined(HAVE_MKNODAT) extern int am_daemon, am_chrooted; char dirpath[MAXPATHLEN]; const char *bname; @@ -597,7 +599,7 @@ int do_mknod_at(const char *pathname, mode_t mode, dev_t dev) return ret; } -#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO +#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO && defined HAVE_MKFIFOAT if (S_ISFIFO(mode)) ret = mkfifoat(dfd, bname, mode); else