Coverage Report

Created: 2025-11-16 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.30.1/src/features.rs
Line
Count
Source
1
//! Feature tests for OS functionality
2
pub use self::os::*;
3
4
#[cfg(any(linux_android, target_os = "emscripten"))]
5
mod os {
6
    use crate::sys::utsname::uname;
7
    use crate::Result;
8
    use std::os::unix::ffi::OsStrExt;
9
    use std::sync::atomic::{AtomicUsize, Ordering};
10
11
    // Features:
12
    // * atomic cloexec on socket: 2.6.27
13
    // * pipe2: 2.6.27
14
    // * accept4: 2.6.28
15
16
    static VERS_UNKNOWN: usize = 1;
17
    static VERS_2_6_18: usize = 2;
18
    static VERS_2_6_27: usize = 3;
19
    static VERS_2_6_28: usize = 4;
20
    static VERS_3: usize = 5;
21
22
    #[inline]
23
0
    fn digit(dst: &mut usize, b: u8) {
24
0
        *dst *= 10;
25
0
        *dst += (b - b'0') as usize;
26
0
    }
27
28
0
    fn parse_kernel_version() -> Result<usize> {
29
0
        let u = uname()?;
30
31
0
        let mut curr: usize = 0;
32
0
        let mut major: usize = 0;
33
0
        let mut minor: usize = 0;
34
0
        let mut patch: usize = 0;
35
36
0
        for &b in u.release().as_bytes() {
37
0
            if curr >= 3 {
38
0
                break;
39
0
            }
40
41
0
            match b {
42
0
                b'.' | b'-' => {
43
0
                    curr += 1;
44
0
                }
45
0
                b'0'..=b'9' => match curr {
46
0
                    0 => digit(&mut major, b),
47
0
                    1 => digit(&mut minor, b),
48
0
                    _ => digit(&mut patch, b),
49
                },
50
0
                _ => break,
51
            }
52
        }
53
54
0
        Ok(if major >= 3 {
55
0
            VERS_3
56
0
        } else if major >= 2 {
57
0
            if minor >= 7 {
58
0
                VERS_UNKNOWN
59
0
            } else if minor >= 6 {
60
0
                if patch >= 28 {
61
0
                    VERS_2_6_28
62
0
                } else if patch >= 27 {
63
0
                    VERS_2_6_27
64
                } else {
65
0
                    VERS_2_6_18
66
                }
67
            } else {
68
0
                VERS_UNKNOWN
69
            }
70
        } else {
71
0
            VERS_UNKNOWN
72
        })
73
0
    }
74
75
0
    fn kernel_version() -> Result<usize> {
76
        static KERNEL_VERS: AtomicUsize = AtomicUsize::new(0);
77
0
        let mut kernel_vers = KERNEL_VERS.load(Ordering::Relaxed);
78
79
0
        if kernel_vers == 0 {
80
0
            kernel_vers = parse_kernel_version()?;
81
0
            KERNEL_VERS.store(kernel_vers, Ordering::Relaxed);
82
0
        }
83
84
0
        Ok(kernel_vers)
85
0
    }
86
87
    /// Check if the OS supports atomic close-on-exec for sockets
88
0
    pub fn socket_atomic_cloexec() -> bool {
89
0
        kernel_version()
90
0
            .map(|version| version >= VERS_2_6_27)
91
0
            .unwrap_or(false)
92
0
    }
93
94
    #[test]
95
    fn test_parsing_kernel_version() {
96
        assert!(kernel_version().unwrap() > 0);
97
    }
98
}
99
100
#[cfg(any(
101
        freebsdlike,                // FreeBSD since 10.0 DragonFlyBSD since ???
102
        netbsdlike,                 // NetBSD since 6.0 OpenBSD since 5.7
103
        target_os = "hurd",         // Since glibc 2.28
104
        target_os = "illumos",      // Since ???
105
        target_os = "redox",        // Since 1-july-2020
106
        target_os = "cygwin",
107
))]
108
mod os {
109
    /// Check if the OS supports atomic close-on-exec for sockets
110
    pub const fn socket_atomic_cloexec() -> bool {
111
        true
112
    }
113
}
114
115
#[cfg(any(
116
    target_os = "aix",
117
    apple_targets,
118
    target_os = "fuchsia",
119
    target_os = "haiku",
120
    target_os = "solaris"
121
))]
122
mod os {
123
    /// Check if the OS supports atomic close-on-exec for sockets
124
    pub const fn socket_atomic_cloexec() -> bool {
125
        false
126
    }
127
}