Skip to content

Commit 02bc079

Browse files
committed
Expose pipe and pipe2
1 parent 57fae07 commit 02bc079

File tree

1 file changed

+96
-3
lines changed

1 file changed

+96
-3
lines changed

src/unistd.rs

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use std::ptr;
1+
use std::{mem, ptr};
22
use std::c_str::{CString, ToCStr};
33
use libc::{c_char, c_void, c_int, size_t};
4-
use fcntl::{Fd, OFlag};
4+
use fcntl::{fcntl, Fd, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC, F_SETFD, F_SETFL};
55
use errno::{SysResult, SysError, from_ffi};
66

77
#[cfg(target_os = "linux")]
88
pub use self::linux::*;
99

1010
mod ffi {
1111
use libc::{c_char, c_int, size_t};
12-
pub use libc::{close, read, write};
12+
pub use libc::{close, read, write, pipe};
1313

1414
extern {
1515
// duplicate a file descriptor
@@ -151,6 +151,99 @@ pub fn write(fd: Fd, buf: &[u8]) -> SysResult<uint> {
151151
return Ok(res as uint)
152152
}
153153

154+
pub fn pipe() -> SysResult<(Fd, Fd)> {
155+
unsafe {
156+
let mut res;
157+
let mut fds: [c_int, ..2] = mem::uninitialized();
158+
159+
res = ffi::pipe(fds.as_mut_ptr());
160+
161+
if res < 0 {
162+
return Err(SysError::last());
163+
}
164+
165+
Ok((fds[0], fds[1]))
166+
}
167+
}
168+
169+
#[cfg(target_os = "linux")]
170+
pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> {
171+
type F = unsafe extern "C" fn(fds: *mut c_int, flags: c_int) -> c_int;
172+
173+
extern {
174+
#[linkage = "extern_weak"]
175+
static pipe2: *const ();
176+
}
177+
178+
let feat_atomic = !pipe2.is_null();
179+
180+
unsafe {
181+
let mut res;
182+
let mut fds: [c_int, ..2] = mem::uninitialized();
183+
184+
if feat_atomic {
185+
res = mem::transmute::<*const (), F>(pipe2)(
186+
fds.as_mut_ptr(), flags.bits());
187+
} else {
188+
res = ffi::pipe(fds.as_mut_ptr());
189+
}
190+
191+
if res < 0 {
192+
return Err(SysError::last());
193+
}
194+
195+
if !feat_atomic {
196+
try!(pipe2_setflags(fds[0], fds[1], flags));
197+
}
198+
199+
Ok((fds[0], fds[1]))
200+
}
201+
}
202+
203+
#[cfg(target_os = "macos")]
204+
#[cfg(target_os = "ios")]
205+
pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> {
206+
unsafe {
207+
let mut res;
208+
let mut fds: [c_int, ..2] = mem::uninitialized();
209+
210+
res = ffi::pipe(fds.as_mut_ptr());
211+
212+
if res < 0 {
213+
return Err(SysError::last());
214+
}
215+
216+
try!(pipe2_setflags(fds[0], fds[1], flags));
217+
218+
Ok((fds[0], fds[1]))
219+
}
220+
}
221+
222+
fn pipe2_setflags(fd1: Fd, fd2: Fd, flags: OFlag) -> SysResult<()> {
223+
let mut res = Ok(());
224+
225+
if flags.contains(O_CLOEXEC) {
226+
res = res
227+
.and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
228+
.and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
229+
}
230+
231+
if flags.contains(O_NONBLOCK) {
232+
res = res
233+
.and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
234+
.and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
235+
}
236+
237+
match res {
238+
Ok(_) => Ok(()),
239+
Err(e) => {
240+
let _ = close(fd1);
241+
let _ = close(fd2);
242+
return Err(e);
243+
}
244+
}
245+
}
246+
154247
#[cfg(target_os = "linux")]
155248
mod linux {
156249
use std::path::Path;

0 commit comments

Comments
 (0)