• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Feature tests for OS functionality
2 pub use self::os::*;
3 
4 #[cfg(any(target_os = "linux", target_os = "android"))]
5 mod 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]
digit(dst: &mut usize, b: u8)20     fn digit(dst: &mut usize, b: u8) {
21         *dst *= 10;
22         *dst += (b - b'0') as usize;
23     }
24 
parse_kernel_version() -> usize25     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 
kernel_version() -> usize74     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
socket_atomic_cloexec() -> bool87     pub fn socket_atomic_cloexec() -> bool {
88         kernel_version() >= VERS_2_6_27
89     }
90 
91     #[test]
test_parsing_kernel_version()92     pub fn test_parsing_kernel_version() {
93         assert!(kernel_version() > 0);
94     }
95 }
96 
97 #[cfg(any(
98         target_os = "dragonfly",    // Since ???
99         target_os = "freebsd",      // Since 10.0
100         target_os = "illumos",      // Since ???
101         target_os = "netbsd",       // Since 6.0
102         target_os = "openbsd",      // Since 5.7
103         target_os = "redox",        // Since 1-july-2020
104 ))]
105 mod os {
106     /// Check if the OS supports atomic close-on-exec for sockets
socket_atomic_cloexec() -> bool107     pub const fn socket_atomic_cloexec() -> bool {
108         true
109     }
110 }
111 
112 #[cfg(any(target_os = "macos",
113           target_os = "ios",
114           target_os = "fuchsia",
115           target_os = "solaris"))]
116 mod os {
117     /// Check if the OS supports atomic close-on-exec for sockets
socket_atomic_cloexec() -> bool118     pub const fn socket_atomic_cloexec() -> bool {
119         false
120     }
121 }
122