blob: bcda45d41f913f3c01c6d78f38414a1994071afe [file] [log] [blame]
Andrew Walbran12f61402020-10-14 11:10:53 +01001//! Feature tests for OS functionality
2pub use self::os::*;
3
4#[cfg(any(target_os = "linux", target_os = "android"))]
5mod os {
6 use crate::sys::utsname::uname;
7
8 // Features:
9 // * atomic cloexec on socket: 2.6.27
10 // * pipe2: 2.6.27
11 // * accept4: 2.6.28
12
13 static VERS_UNKNOWN: usize = 1;
14 static VERS_2_6_18: usize = 2;
15 static VERS_2_6_27: usize = 3;
16 static VERS_2_6_28: usize = 4;
17 static VERS_3: usize = 5;
18
19 #[inline]
20 fn digit(dst: &mut usize, b: u8) {
21 *dst *= 10;
22 *dst += (b - b'0') as usize;
23 }
24
25 fn parse_kernel_version() -> usize {
26 let u = uname();
27
28 let mut curr: usize = 0;
29 let mut major: usize = 0;
30 let mut minor: usize = 0;
31 let mut patch: usize = 0;
32
33 for b in u.release().bytes() {
34 if curr >= 3 {
35 break;
36 }
37
38 match b {
39 b'.' | b'-' => {
40 curr += 1;
41 }
42 b'0'..=b'9' => {
43 match curr {
44 0 => digit(&mut major, b),
45 1 => digit(&mut minor, b),
46 _ => digit(&mut patch, b),
47 }
48 }
49 _ => break,
50 }
51 }
52
53 if major >= 3 {
54 VERS_3
55 } else if major >= 2 {
56 if minor >= 7 {
57 VERS_UNKNOWN
58 } else if minor >= 6 {
59 if patch >= 28 {
60 VERS_2_6_28
61 } else if patch >= 27 {
62 VERS_2_6_27
63 } else {
64 VERS_2_6_18
65 }
66 } else {
67 VERS_UNKNOWN
68 }
69 } else {
70 VERS_UNKNOWN
71 }
72 }
73
74 fn kernel_version() -> usize {
75 static mut KERNEL_VERS: usize = 0;
76
77 unsafe {
78 if KERNEL_VERS == 0 {
79 KERNEL_VERS = parse_kernel_version();
80 }
81
82 KERNEL_VERS
83 }
84 }
85
86 /// Check if the OS supports atomic close-on-exec for sockets
87 pub fn socket_atomic_cloexec() -> bool {
88 kernel_version() >= VERS_2_6_27
89 }
90
91 #[test]
92 pub fn test_parsing_kernel_version() {
93 assert!(kernel_version() > 0);
94 }
95}
96
Joel Galensone7950d92021-06-21 14:41:02 -070097#[cfg(any(target_os = "illumos"))]
98mod os {
99 /// Check if the OS supports atomic close-on-exec for sockets
100 pub fn socket_atomic_cloexec() -> bool {
101 true
102 }
103}
104
Andrew Walbran12f61402020-10-14 11:10:53 +0100105#[cfg(any(target_os = "macos", target_os = "freebsd",
106 target_os = "dragonfly", target_os = "ios",
107 target_os = "openbsd", target_os = "netbsd",
Joel Galensone7950d92021-06-21 14:41:02 -0700108 target_os = "redox", target_os = "fuchsia",
109 target_os = "solaris"))]
Andrew Walbran12f61402020-10-14 11:10:53 +0100110mod os {
111 /// Check if the OS supports atomic close-on-exec for sockets
112 pub fn socket_atomic_cloexec() -> bool {
113 false
114 }
115}