diff options
author | Carl Lerche <me@carllerche.com> | 2014-10-06 22:02:26 -0700 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2014-10-06 22:02:26 -0700 |
commit | 7c4fa8232df48dc324119ff8d742a35458dec02e (patch) | |
tree | 8bbf26a4bd015eb7989900c2d470f9a2824d8e12 | |
parent | 2b08916431fb5dc9791c9074e310c7a7d22b37e6 (diff) | |
download | nix-7c4fa8232df48dc324119ff8d742a35458dec02e.zip |
Implement dup3
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/unistd.rs | 44 |
2 files changed, 34 insertions, 11 deletions
@@ -2,6 +2,7 @@ #![feature(globs)] #![feature(linkage)] +#![feature(if_let)] #![allow(non_camel_case_types)] extern crate libc; diff --git a/src/unistd.rs b/src/unistd.rs index c793bf4c..14e6e66e 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -18,9 +18,6 @@ mod ffi { pub fn dup(oldfd: c_int) -> c_int; pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int; - // TODO: dup3 is only available in newer linux kernels and possibly a few *bsds - // pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; - // change working directory // doc: http://man7.org/linux/man-pages/man2/chdir.2.html pub fn chdir(path: *const c_char) -> c_int; @@ -98,19 +95,44 @@ pub fn dup2(oldfd: Fd, newfd: Fd) -> SysResult<Fd> { Ok(res) } -/* -Same TODO as above -#[inline] pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { - let res = unsafe { ffi::dup3(oldfd, newfd, flags.bits()) }; + use errno::EINVAL; - if res < 0 { - return Err(SysError::last()); + type F = unsafe extern "C" fn(c_int, c_int, c_int) -> c_int; + + extern { + #[linkage = "extern_weak"] + static dup3: *const (); } - Ok(res) + if !dup3.is_null() { + let res = unsafe { + mem::transmute::<*const (), F>(dup3)( + oldfd, newfd, flags.bits()) + }; + + if res < 0 { + return Err(SysError::last()); + } + + Ok(res) + } else { + if oldfd == newfd { + return Err(SysError { kind: EINVAL }); + } + + let fd = try!(dup2(oldfd, newfd)); + + if flags.contains(O_CLOEXEC) { + if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) { + let _ = close(fd); + return Err(e); + } + } + + Ok(fd) + } } -*/ #[inline] pub fn chdir<S: ToCStr>(path: S) -> SysResult<()> { |