1 use libc::{self, c_int};
2 
3 #[macro_use]
4 pub mod dlsym;
5 
6 #[cfg(any(
7     target_os = "android",
8     target_os = "illumos",
9     target_os = "linux",
10     target_os = "solaris"
11 ))]
12 mod epoll;
13 
14 #[cfg(any(
15     target_os = "android",
16     target_os = "illumos",
17     target_os = "linux",
18     target_os = "solaris"
19 ))]
20 pub use self::epoll::{Events, Selector};
21 
22 #[cfg(any(target_os = "bitrig", target_os = "dragonfly",
23           target_os = "freebsd", target_os = "ios", target_os = "macos",
24           target_os = "netbsd", target_os = "openbsd"))]
25 mod kqueue;
26 
27 #[cfg(any(target_os = "bitrig", target_os = "dragonfly",
28           target_os = "freebsd", target_os = "ios", target_os = "macos",
29           target_os = "netbsd", target_os = "openbsd"))]
30 pub use self::kqueue::{Events, Selector};
31 
32 mod awakener;
33 mod eventedfd;
34 mod io;
35 mod ready;
36 mod tcp;
37 mod udp;
38 mod uio;
39 
40 #[cfg(feature = "with-deprecated")]
41 mod uds;
42 
43 pub use self::awakener::Awakener;
44 pub use self::eventedfd::EventedFd;
45 pub use self::io::{Io, set_nonblock};
46 pub use self::ready::{UnixReady, READY_ALL};
47 pub use self::tcp::{TcpStream, TcpListener};
48 pub use self::udp::UdpSocket;
49 
50 #[cfg(feature = "with-deprecated")]
51 pub use self::uds::UnixSocket;
52 
53 pub use iovec::IoVec;
54 
55 use std::os::unix::io::FromRawFd;
56 
pipe() -> ::io::Result<(Io, Io)>57 pub fn pipe() -> ::io::Result<(Io, Io)> {
58     // Use pipe2 for atomically setting O_CLOEXEC if we can, but otherwise
59     // just fall back to using `pipe`.
60     dlsym!(fn pipe2(*mut c_int, c_int) -> c_int);
61 
62     let mut pipes = [0; 2];
63     unsafe {
64         match pipe2.get() {
65             Some(pipe2_fn) => {
66                 let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
67                 cvt(pipe2_fn(pipes.as_mut_ptr(), flags))?;
68                 Ok((Io::from_raw_fd(pipes[0]), Io::from_raw_fd(pipes[1])))
69             }
70             None => {
71                 cvt(libc::pipe(pipes.as_mut_ptr()))?;
72                 // Ensure the pipe are closed if any of the system calls below
73                 // fail.
74                 let r = Io::from_raw_fd(pipes[0]);
75                 let w = Io::from_raw_fd(pipes[1]);
76                 cvt(libc::fcntl(pipes[0], libc::F_SETFD, libc::FD_CLOEXEC))?;
77                 cvt(libc::fcntl(pipes[1], libc::F_SETFD, libc::FD_CLOEXEC))?;
78                 cvt(libc::fcntl(pipes[0], libc::F_SETFL, libc::O_NONBLOCK))?;
79                 cvt(libc::fcntl(pipes[1], libc::F_SETFL, libc::O_NONBLOCK))?;
80                 Ok((r, w))
81             }
82         }
83     }
84 }
85 
86 trait IsMinusOne {
is_minus_one(&self) -> bool87     fn is_minus_one(&self) -> bool;
88 }
89 
90 impl IsMinusOne for i32 {
is_minus_one(&self) -> bool91     fn is_minus_one(&self) -> bool { *self == -1 }
92 }
93 impl IsMinusOne for isize {
is_minus_one(&self) -> bool94     fn is_minus_one(&self) -> bool { *self == -1 }
95 }
96 
cvt<T: IsMinusOne>(t: T) -> ::io::Result<T>97 fn cvt<T: IsMinusOne>(t: T) -> ::io::Result<T> {
98     use std::io;
99 
100     if t.is_minus_one() {
101         Err(io::Error::last_os_error())
102     } else {
103         Ok(t)
104     }
105 }
106