diff options
Diffstat (limited to 'third_party/rust/nix/src/features.rs')
-rw-r--r-- | third_party/rust/nix/src/features.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/third_party/rust/nix/src/features.rs b/third_party/rust/nix/src/features.rs new file mode 100644 index 0000000000..39d17604e1 --- /dev/null +++ b/third_party/rust/nix/src/features.rs @@ -0,0 +1,126 @@ +//! Feature tests for OS functionality +pub use self::os::*; + +#[cfg(any(target_os = "linux", target_os = "android"))] +mod os { + use crate::sys::utsname::uname; + use crate::Result; + use std::os::unix::ffi::OsStrExt; + + // Features: + // * atomic cloexec on socket: 2.6.27 + // * pipe2: 2.6.27 + // * accept4: 2.6.28 + + static VERS_UNKNOWN: usize = 1; + static VERS_2_6_18: usize = 2; + static VERS_2_6_27: usize = 3; + static VERS_2_6_28: usize = 4; + static VERS_3: usize = 5; + + #[inline] + fn digit(dst: &mut usize, b: u8) { + *dst *= 10; + *dst += (b - b'0') as usize; + } + + fn parse_kernel_version() -> Result<usize> { + let u = uname()?; + + let mut curr: usize = 0; + let mut major: usize = 0; + let mut minor: usize = 0; + let mut patch: usize = 0; + + for &b in u.release().as_bytes() { + if curr >= 3 { + break; + } + + match b { + b'.' | b'-' => { + curr += 1; + } + b'0'..=b'9' => match curr { + 0 => digit(&mut major, b), + 1 => digit(&mut minor, b), + _ => digit(&mut patch, b), + }, + _ => break, + } + } + + Ok(if major >= 3 { + VERS_3 + } else if major >= 2 { + if minor >= 7 { + VERS_UNKNOWN + } else if minor >= 6 { + if patch >= 28 { + VERS_2_6_28 + } else if patch >= 27 { + VERS_2_6_27 + } else { + VERS_2_6_18 + } + } else { + VERS_UNKNOWN + } + } else { + VERS_UNKNOWN + }) + } + + fn kernel_version() -> Result<usize> { + static mut KERNEL_VERS: usize = 0; + + unsafe { + if KERNEL_VERS == 0 { + KERNEL_VERS = parse_kernel_version()?; + } + + Ok(KERNEL_VERS) + } + } + + /// Check if the OS supports atomic close-on-exec for sockets + pub fn socket_atomic_cloexec() -> bool { + kernel_version() + .map(|version| version >= VERS_2_6_27) + .unwrap_or(false) + } + + #[test] + pub fn test_parsing_kernel_version() { + assert!(kernel_version().unwrap() > 0); + } +} + +#[cfg(any( + target_os = "dragonfly", // Since ??? + target_os = "freebsd", // Since 10.0 + target_os = "illumos", // Since ??? + target_os = "netbsd", // Since 6.0 + target_os = "openbsd", // Since 5.7 + target_os = "redox", // Since 1-july-2020 +))] +mod os { + /// Check if the OS supports atomic close-on-exec for sockets + pub const fn socket_atomic_cloexec() -> bool { + true + } +} + +#[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "fuchsia", + target_os = "haiku", + target_os = "solaris" +))] +mod os { + /// Check if the OS supports atomic close-on-exec for sockets + pub const fn socket_atomic_cloexec() -> bool { + false + } +} |