From d315804a1f69977ab2332b41d81668a5da0ee71b Mon Sep 17 00:00:00 2001 From: Anton Ageev Date: Mon, 5 Feb 2018 22:32:15 +0300 Subject: Add fchmod, fchmodat functions. --- src/sys/stat.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/sys/stat.rs') diff --git a/src/sys/stat.rs b/src/sys/stat.rs index 1f0d728a..7bcf1fce 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -122,3 +122,64 @@ pub fn fstatat(dirfd: RawFd, pathname: &P, f: AtFlags) -> R Ok(dst) } +/// Change the file permission bits of the file specified by a file descriptor. +/// +/// # References +/// +/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html). +pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> { + let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) }; + + Errno::result(res).map(|_| ()) +} + +/// Flags for `fchmodat` function. +#[derive(Clone, Copy, Debug)] +pub enum FchmodatFlags { + FollowSymlink, + NoFollowSymlink, +} + +/// Change the file permission bits. +/// +/// The file to be changed is determined relative to the directory associated +/// with the file descriptor `dirfd` or the current working directory +/// if `dirfd` is `None`. +/// +/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link, +/// then the mode of the symbolic link is changed. +/// +/// `fchmod(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to +/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented +/// in the `nix` crate. +/// +/// # References +/// +/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html). +pub fn fchmodat( + dirfd: Option, + path: &P, + mode: Mode, + flag: FchmodatFlags, +) -> Result<()> { + let actual_dirfd = + match dirfd { + None => libc::AT_FDCWD, + Some(fd) => fd, + }; + let atflag = + match flag { + FchmodatFlags::FollowSymlink => AtFlags::empty(), + FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW, + }; + let res = path.with_nix_path(|cstr| unsafe { + libc::fchmodat( + actual_dirfd, + cstr.as_ptr(), + mode.bits() as mode_t, + atflag.bits() as libc::c_int, + ) + })?; + + Errno::result(res).map(|_| ()) +} -- cgit v1.2.3