@@ -2,14 +2,99 @@ pub use self::os::*;
2
2
3
3
#[ cfg( target_os = "linux" ) ]
4
4
mod os {
5
- pub fn atomic_cloexec ( ) -> bool {
6
- true // TODO: Not on all kernel versions
5
+ use sys:: utsname:: uname;
6
+
7
+ // Features:
8
+ // * atomic cloexec on socket: 2.6.27
9
+ // * pipe2: 2.6.27
10
+ // * accept4: 2.6.28
11
+
12
+ static VERS_UNKNOWN : uint = 1 ;
13
+ static VERS_2_6_18 : uint = 2 ;
14
+ static VERS_2_6_27 : uint = 3 ;
15
+ static VERS_2_6_28 : uint = 4 ;
16
+ static VERS_3 : uint = 5 ;
17
+
18
+ fn parse_kernel_version ( ) -> uint {
19
+ let u = uname ( ) ;
20
+
21
+ #[ inline]
22
+ fn digit ( dst : & mut uint , b : u8 ) {
23
+ * dst *= 10 ;
24
+ * dst += ( b - b'0' ) as uint ;
25
+ }
26
+
27
+ let mut curr = 0 u;
28
+ let mut major = 0 ;
29
+ let mut minor = 0 ;
30
+ let mut patch = 0 ;
31
+
32
+ for b in u. release ( ) . bytes ( ) {
33
+ if curr >= 3 {
34
+ break ;
35
+ }
36
+
37
+ match b {
38
+ b'.' | b'-' => {
39
+ curr += 1 ;
40
+ }
41
+ b'0' ...b'9' => {
42
+ match curr {
43
+ 0 => digit ( & mut major, b) ,
44
+ 1 => digit ( & mut minor, b) ,
45
+ _ => digit ( & mut patch, b) ,
46
+ }
47
+ }
48
+ _ => break ,
49
+ }
50
+ }
51
+
52
+ if major >= 3 {
53
+ VERS_3
54
+ } else if major >= 2 {
55
+ if minor >= 7 {
56
+ VERS_UNKNOWN
57
+ } else if minor >= 6 {
58
+ if patch >= 28 {
59
+ VERS_2_6_28
60
+ } else if patch >= 27 {
61
+ VERS_2_6_27
62
+ } else {
63
+ VERS_2_6_18
64
+ }
65
+ } else {
66
+ VERS_UNKNOWN
67
+ }
68
+ } else {
69
+ VERS_UNKNOWN
70
+ }
71
+ }
72
+
73
+ fn kernel_version ( ) -> uint {
74
+ static mut KERNEL_VERS : uint = 0 ;
75
+
76
+ unsafe {
77
+ if KERNEL_VERS == 0 {
78
+ KERNEL_VERS = parse_kernel_version ( ) ;
79
+ }
80
+
81
+ KERNEL_VERS
82
+ }
83
+ }
84
+
85
+ pub fn socket_atomic_cloexec ( ) -> bool {
86
+ kernel_version ( ) >= VERS_2_6_27
87
+ }
88
+
89
+ #[ test]
90
+ pub fn test_parsing_kernel_version ( ) {
91
+ assert ! ( kernel_version( ) > 0 ) ;
7
92
}
8
93
}
9
94
10
95
#[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
11
96
mod os {
12
- pub fn atomic_cloexec ( ) -> bool {
97
+ pub fn socket_atomic_cloexec ( ) -> bool {
13
98
false
14
99
}
15
100
}
0 commit comments