Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added direct support for fchown and dup3 #957

Closed
wants to merge 9 commits into from
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
44 changes: 24 additions & 20 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -374,26 +373,17 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
///
/// 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<RawFd> {
koutheir marked this conversation as resolved.
Show resolved Hide resolved
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<RawFd> {
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
Expand Down Expand Up @@ -633,6 +623,20 @@ pub fn fchownat<P: ?Sized + NixPath>(
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<Uid>, group: Option<Gid>) -> 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());
Expand Down