diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 6cf37f23c57..30eead9b059 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -5,6 +5,7 @@ use super::platform::fs::MetadataExt as _; use crate::fs::{self, OpenOptions, Permissions}; use crate::io; +use crate::os::unix::io::{AsFd, AsRawFd}; use crate::path::Path; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; @@ -924,6 +925,75 @@ fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder { } } +/// Change the owner and group of the specified path. +/// +/// Specifying either the uid or gid as `None` will leave it unchanged. +/// +/// Changing the owner typically requires privileges, such as root or a specific capability. +/// Changing the group typically requires either being the owner and a member of the group, or +/// having privileges. +/// +/// If called on a symbolic link, this will change the owner and group of the link target. To +/// change the owner and group of the link itself, see [`lchown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::chown("/sandbox", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn chown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the file referenced by the specified open file descriptor. +/// +/// For semantics and required privileges, see [`chown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// let f = std::fs::File::open("/file")?; +/// fs::fchown(f, Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the specified path, without dereferencing symbolic links. +/// +/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner +/// and group of the link itself rather than the owner and group of the link target. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::lchown("/symlink", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn lchown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + /// Change the root directory of the current process to the specified path. /// /// This typically requires privileges, such as root or a specific capability. diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 6d7524a733a..a4fff9b2e64 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1416,6 +1416,23 @@ fn fclonefileat( Ok(bytes_copied as u64) } +pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> { + cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))] pub fn chroot(dir: &Path) -> io::Result<()> { let dir = cstr(dir)?;