diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b1543f4f0..02dc117fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,10 +25,16 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#956](https://github.com/nix-rust/nix/pull/956)) - Added a `fchownat` wrapper. ([#955](https://github.com/nix-rust/nix/pull/955)) +- Added a `fchown` wrapper. + ([#957](https://github.com/nix-rust/nix/pull/957)) ### Changed - Increased required Rust version to 1.22.1/ ([#900](https://github.com/nix-rust/nix/pull/900)) +- Changed the `dup3` wrapper to perform a direct call to the system call `dup3` instead of emulating + it via `dup2` and `fcntl` which could cause a race condition. The `dup3` system call is supported + on the following platforms: Fuchsia, Emscripten, FreeBSD, Linux, Solaris, NetBSD, OpenBSD. + ([#957](https://github.com/nix-rust/nix/pull/957)) ### Fixed - Made `preadv` take immutable slice of IoVec. @@ -37,6 +43,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#918](https://github.com/nix-rust/nix/pull/918)) ### Removed +- Removed the `dup3` wrapper on OSX, which was emulated via `dup2` and `fcntl`, which could cause + a race condition. The `dup3` system call is not supported on OSX. + ([#957](https://github.com/nix-rust/nix/pull/957)) ## [0.11.0] 2018-06-01 diff --git a/src/unistd.rs b/src/unistd.rs index d5192977fd..ffd423fd33 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2,8 +2,7 @@ use errno::{self, Errno}; use {Error, Result, NixPath}; -use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag}; -use fcntl::FcntlArg::F_SETFD; +use fcntl::{AtFlags, at_rawfd, OFlag}; use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t}; use std::{fmt, mem, ptr}; @@ -374,26 +373,17 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { /// /// This function behaves similar to `dup2()` but allows for flags to be /// specified. +#[cfg(any(target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris"))] pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { - dup3_polyfill(oldfd, newfd, flags) -} + let res = unsafe { libc::dup3(oldfd, newfd, flags.bits()) }; -#[inline] -fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { - if oldfd == newfd { - return Err(Error::Sys(Errno::EINVAL)); - } - - let fd = try!(dup2(oldfd, newfd)); - - if flags.contains(OFlag::O_CLOEXEC) { - if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) { - let _ = close(fd); - return Err(e); - } - } - - Ok(fd) + Errno::result(res) } /// Change the current working directory of the calling process (see @@ -633,6 +623,20 @@ pub fn fchownat( Errno::result(res).map(|_| ()) } +/// Change the ownership of the file specified by the file descriptor `fd` to be owned by the +/// specified `owner` (user) and `group` (see +/// [fchown(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)). +/// +/// The owner/group for the provided path name will not be modified if `None` is +/// provided for that argument. Ownership change will be attempted for the path +/// only if `Some` owner/group is provided. +pub fn fchown(fd: RawFd, owner: Option, group: Option) -> Result<()> { + let (uid, gid) = chown_raw_ids(owner, group); + let res = unsafe { libc::fchown(fd, uid, gid) }; + + Errno::result(res).map(drop) +} + fn to_exec_array(args: &[CString]) -> Vec<*const c_char> { let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect(); args_p.push(ptr::null());