diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b528ca91..e81e0c0ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#739](https://github.com/nix-rust/nix/pull/739)) - Added nix::sys::ptrace::detach. ([#749](https://github.com/nix-rust/nix/pull/749)) +- Added `nix::unistd::{chown, lchown, fchown, fchownat}` + ([#760](https://github.com/nix-rust/nix/pull/760)) ### Changed - Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692)) diff --git a/src/unistd.rs b/src/unistd.rs index fad51272e0..763de049fd 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -492,6 +492,17 @@ pub fn getcwd() -> Result { } } +// According to the POSIX, -1 is used to indicate that +// owner and group, respectively, are not to be changed. Since uid_t and +// gid_t are unsigned types, we use wrapping_sub to get '-1'. +fn optional_user(val: Option) -> u32 { + val.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1)) +} + +fn optional_group(val: Option) -> u32 { + val.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1)) +} + /// Change the ownership of the file at `path` to be owned by the specified /// `owner` (user) and `group` (see /// [chown(2)](http://man7.org/linux/man-pages/man2/lchown.2.html)). @@ -506,12 +517,57 @@ pub fn getcwd() -> Result { #[inline] pub fn chown(path: &P, owner: Option, group: Option) -> Result<()> { let res = try!(path.with_nix_path(|cstr| { - // According to the POSIX specification, -1 is used to indicate that - // owner and group, respectively, are not to be changed. Since uid_t and - // gid_t are unsigned types, we use wrapping_sub to get '-1'. - unsafe { libc::chown(cstr.as_ptr(), - owner.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1)), - group.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1))) } + unsafe { + libc::chown(cstr.as_ptr(), + optional_user(owner), + optional_group(group)) + } + })); + + Errno::result(res).map(drop) +} + +/// Change ownership of a file +/// (see [lchown(2)](http://man7.org/linux/man-pages/man2/lchown.2.html)). +pub fn lchown(path: &P, owner: Option, group: Option) -> Result<()> { + let res = try!(path.with_nix_path(|cstr| { + unsafe { + libc::lchown(cstr.as_ptr(), + optional_user(owner), + optional_group(group)) + } + })); + + Errno::result(res).map(drop) +} + +/// Change ownership of a file +/// (see [fchown(2)](http://man7.org/linux/man-pages/man2/fchown.2.html)). +pub fn fchown(fd: RawFd, owner: Option, group: Option) -> Result<()> { + let res = unsafe { + libc::fchown(fd, + optional_user(owner), + optional_group(group)) + }; + + Errno::result(res).map(drop) +} + +/// Change ownership of a file +/// (see [fchownat(2)](http://man7.org/linux/man-pages/man2/fchownat.2.html)). +pub fn fchownat(dirfd: RawFd, + pathname: &P, + owner: Option, + group: Option, + flags: AtFlags) -> Result<()> { + let res = try!(pathname.with_nix_path(|cstr| { + unsafe { + libc::fchownat(dirfd, + cstr.as_ptr(), + optional_user(owner), + optional_group(group), + flags.bits()) + } })); Errno::result(res).map(drop)