diff --git a/src/fds.rs b/src/fds.rs index 188690e06..c7f5b13a4 100644 --- a/src/fds.rs +++ b/src/fds.rs @@ -267,18 +267,23 @@ pub fn open_cloexec(path: &CStr, flags: OFlag, mode: nix::sys::stat::Mode) -> ni mod o_search { use super::OFlag; - /// On FreeBSD or MacOS we have O_SEARCH. - #[cfg(any(target_os = "freebsd", target_os = "macos"))] - pub const BEST_O_SEARCH: OFlag = unsafe { OFlag::from_bits_unchecked(libc::O_SEARCH) }; + /// On macOS we have O_SEARCH, which is defined as O_EXEC | O_DIRECTORY, + /// where O_EXEC is 0x40000000. This is only on macOS 12.0+ or later; however + /// prior macOS versions ignores O_EXEC so it is treated the same as O_RDONLY. + #[cfg(target_os = "macos")] + pub const BEST_O_SEARCH: OFlag = + unsafe { OFlag::from_bits_unchecked(libc::O_DIRECTORY | 0x40000000) }; + + /// On FreeBSD, we have O_SEARCH = 0x00040000. + #[cfg(target_os = "freebsd")] + pub const BEST_O_SEARCH: OFlag = unsafe { OFlag::from_bits_unchecked(0x00040000) }; + /// On Linux we can use O_PATH, it has nearly the same semantics. we can use the fd for openat / fchdir, with only requiring /// x permission on the directory. - #[cfg(all( - not(any(target_os = "macos", target_os = "freebsd")), - any(target_os = "linux", target_os = "android") - ))] + #[cfg(any(target_os = "linux", target_os = "android"))] pub const BEST_O_SEARCH: OFlag = unsafe { OFlag::from_bits_unchecked(libc::O_PATH) }; - /// Fall back to O_RDONLY, this is what fish did before. + /// Fall back to O_RDONLY. #[cfg(not(any( target_os = "linux", target_os = "android",