diff --git a/CHANGELOG.md b/CHANGELOG.md index 13a7104b8a..7644441d08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#602](https://github.com/nix-rust/nix/pull/774)) ### Changed +- Remove obsolete `pipe2` emulation. All supported platforms support `pipe2` + natively. Users should notice no difference. + ([#777](https://github.com/nix-rust/nix/pull/777)) - Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692)) - Marked `sys::ptrace::ptrace` as `unsafe`. - Changed function signature of `socket()` and `socketpair()`. The `protocol` argument diff --git a/src/unistd.rs b/src/unistd.rs index 401357d3da..686839da01 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -855,10 +855,6 @@ pub fn pipe() -> Result<(RawFd, RawFd)> { } } -// libc only defines `pipe2` in `libc::notbsd`. -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten"))] pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { let mut fds: [c_int; 2] = unsafe { mem::uninitialized() }; @@ -869,52 +865,6 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { Ok((fds[0], fds[1])) } -#[cfg(not(any(target_os = "linux", - target_os = "android", - target_os = "emscripten")))] -pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { - let mut fds: [c_int; 2] = unsafe { mem::uninitialized() }; - - let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; - - try!(Errno::result(res)); - - try!(pipe2_setflags(fds[0], fds[1], flags)); - - Ok((fds[0], fds[1])) -} - -#[cfg(not(any(target_os = "linux", - target_os = "android", - target_os = "emscripten")))] -fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> { - use fcntl::O_NONBLOCK; - use fcntl::FcntlArg::F_SETFL; - - let mut res = Ok(0); - - if flags.contains(O_CLOEXEC) { - res = res - .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC))) - .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC))); - } - - if flags.contains(O_NONBLOCK) { - res = res - .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK))) - .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK))); - } - - match res { - Ok(_) => Ok(()), - Err(e) => { - let _ = close(fd1); - let _ = close(fd2); - Err(e) - } - } -} - /// Truncate a file to a specified length /// /// See also diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 627eb09b0e..a9cbac873d 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -2,6 +2,7 @@ extern crate tempdir; use nix::unistd::*; use nix::unistd::ForkResult::*; +use nix::fcntl; use nix::sys::wait::*; use nix::sys::stat; use std::{env, iter}; @@ -291,3 +292,26 @@ fn test_sysconf_unsupported() { let open_max = sysconf(SysconfVar::_XOPEN_CRYPT); assert!(open_max.expect("sysconf failed").is_none()) } + +// Test that we can create a pair of pipes. No need to verify that they pass +// data; that's the domain of the OS, not nix. +#[test] +fn test_pipe() { + let (fd0, fd1) = pipe().unwrap(); + let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode); + // S_IFIFO means it's a pipe + assert_eq!(m0, stat::S_IFIFO); + let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode); + assert_eq!(m1, stat::S_IFIFO); +} + +// pipe2(2) is the same as pipe(2), except it allows setting some flags. Check +// that we can set a flag. +#[test] +fn test_pipe2() { + let (fd0, fd1) = pipe2(fcntl::O_CLOEXEC).unwrap(); + let f0 = fcntl::FdFlag::from_bits_truncate(fcntl::fcntl(fd0, fcntl::F_GETFD).unwrap()); + assert!(f0.contains(fcntl::FD_CLOEXEC)); + let f1 = fcntl::FdFlag::from_bits_truncate(fcntl::fcntl(fd1, fcntl::F_GETFD).unwrap()); + assert!(f1.contains(fcntl::FD_CLOEXEC)); +}