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 c458873481)

# Conflicts:
#	syscall.c
This commit is contained in:
Andrew Tridgell committed 2026-08-02 21:31:22 +10:00
1 parent da014b91d1
commit deee128cf1
1 file changed
+7 -2
+7 -2
View File
@@ -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;