From 47efde434db5ffbe56996c8974f81995996f3755 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 16 May 2026 21:45:10 +0900 Subject: [PATCH 1/3] feat: expose mknodat/mkfifoat on Apple targets with weak-linking macOS 13 added mknodat/mkfifoat system calls. Use the same weak-linking pattern as linkat/unlinkat/renameat: resolve the symbol at runtime via dlsym, and fall back to mknod/mkfifo when the symbol is unavailable and dirfd == AT_FDCWD. --- src/backend/libc/fs/syscalls.rs | 32 +++++++++++++++++++++++++++++++- src/fs/at.rs | 2 -- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 71bc8b0ab..743e215c3 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -1196,7 +1196,6 @@ pub(crate) fn chownat( } #[cfg(not(any( - apple, target_os = "espidf", target_os = "horizon", target_os = "redox", @@ -1210,6 +1209,37 @@ pub(crate) fn mknodat( mode: Mode, dev: Dev, ) -> io::Result<()> { + // macOS ≤ 13 lacks `mknodat`. + #[cfg(target_os = "macos")] + unsafe { + weak! { + fn mknodat( + c::c_int, + *const ffi::c_char, + c::mode_t, + c::dev_t + ) -> c::c_int + } + if let Some(libc_mknodat) = mknodat.get() { + return ret(libc_mknodat( + borrowed_fd(dirfd), + c_str(path), + (mode.bits() | file_type.as_raw_mode()) as c::mode_t, + dev.try_into().map_err(|_e| io::Errno::PERM)?, + )); + } + // Otherwise, see if we can emulate the `AT_FDCWD` case. + if borrowed_fd(dirfd) != c::AT_FDCWD { + return Err(io::Errno::NOSYS); + } + ret(c::mknod( + c_str(path), + (mode.bits() | file_type.as_raw_mode()) as c::mode_t, + dev.try_into().map_err(|_e| io::Errno::PERM)?, + )) + } + + #[cfg(not(target_os = "macos"))] unsafe { ret(c::mknodat( borrowed_fd(dirfd), diff --git a/src/fs/at.rs b/src/fs/at.rs index f35ce5aca..63732dc2e 100644 --- a/src/fs/at.rs +++ b/src/fs/at.rs @@ -464,7 +464,6 @@ pub fn fclonefileat( /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/mknodat.html /// [Linux]: https://man7.org/linux/man-pages/man2/mknodat.2.html #[cfg(not(any( - apple, target_os = "espidf", target_os = "horizon", target_os = "vita", @@ -491,7 +490,6 @@ pub fn mknodat( /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkfifoat.html #[cfg(not(any( - apple, target_os = "espidf", target_os = "horizon", target_os = "vita", From 0617d588a0d35e025d9421bce1e429cd3aafb105 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 16 May 2026 21:48:27 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20remove=20macOS=20=E2=89=A4=2013?= =?UTF-8?q?=20fallback=20for=20mknodat/mkfifoat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS 13 and earlier are EOL. Use c::mknodat directly via libc without weak-linking, matching other platforms. --- src/backend/libc/fs/syscalls.rs | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 743e215c3..5f0a55af0 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -1209,37 +1209,6 @@ pub(crate) fn mknodat( mode: Mode, dev: Dev, ) -> io::Result<()> { - // macOS ≤ 13 lacks `mknodat`. - #[cfg(target_os = "macos")] - unsafe { - weak! { - fn mknodat( - c::c_int, - *const ffi::c_char, - c::mode_t, - c::dev_t - ) -> c::c_int - } - if let Some(libc_mknodat) = mknodat.get() { - return ret(libc_mknodat( - borrowed_fd(dirfd), - c_str(path), - (mode.bits() | file_type.as_raw_mode()) as c::mode_t, - dev.try_into().map_err(|_e| io::Errno::PERM)?, - )); - } - // Otherwise, see if we can emulate the `AT_FDCWD` case. - if borrowed_fd(dirfd) != c::AT_FDCWD { - return Err(io::Errno::NOSYS); - } - ret(c::mknod( - c_str(path), - (mode.bits() | file_type.as_raw_mode()) as c::mode_t, - dev.try_into().map_err(|_e| io::Errno::PERM)?, - )) - } - - #[cfg(not(target_os = "macos"))] unsafe { ret(c::mknodat( borrowed_fd(dirfd), From cbd365c63215e5c4f1c81a43b4621a0b252c6489 Mon Sep 17 00:00:00 2001 From: mattsu Date: Sat, 16 May 2026 21:59:00 +0900 Subject: [PATCH 3/3] fix: import Dev and FileType on Apple targets The use declarations for Dev and FileType were gated with cfg(not(apple)), causing compilation failures when mknodat became available on Apple. Remove apple from the exclusion list. --- src/backend/libc/fs/syscalls.rs | 1 - src/fs/at.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 5f0a55af0..009a302de 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -52,7 +52,6 @@ use crate::fs::StatFs; #[cfg(not(any(target_os = "espidf", target_os = "vita")))] use crate::fs::Timestamps; #[cfg(not(any( - apple, target_os = "espidf", target_os = "redox", target_os = "vita", diff --git a/src/fs/at.rs b/src/fs/at.rs index 63732dc2e..896212ced 100644 --- a/src/fs/at.rs +++ b/src/fs/at.rs @@ -20,7 +20,7 @@ use crate::fs::CloneFlags; use crate::fs::RenameFlags; #[cfg(not(target_os = "espidf"))] use crate::fs::Stat; -#[cfg(not(any(apple, target_os = "espidf", target_os = "vita", target_os = "wasi")))] +#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))] use crate::fs::{Dev, FileType}; #[cfg(not(any(target_os = "espidf", target_os = "wasi")))] use crate::fs::{Gid, Uid};