Skip to content

Commit 723d279

Browse files
Rollup merge of #88953 - joshtriplett:chown, r=dtolnay
Add chown functions to std::os::unix::fs to change the owner and group of files This is a straightforward wrapper that uses the existing helpers for C string handling and errno handling. Having this available is convenient for UNIX utility programs written in Rust, and avoids having to call unsafe functions like `libc::chown` directly and handle errors manually, in a program that may otherwise be entirely safe code. In addition, these functions provide a more Rustic interface by accepting appropriate traits and using `None` rather than `-1`.
2 parents 6f5c098 + 862d89e commit 723d279

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

library/std/src/os/unix/fs.rs

+70
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use super::platform::fs::MetadataExt as _;
66
use crate::fs::{self, OpenOptions, Permissions};
77
use crate::io;
8+
use crate::os::unix::io::{AsFd, AsRawFd};
89
use crate::path::Path;
910
use crate::sys;
1011
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
@@ -924,6 +925,75 @@ impl DirBuilderExt for fs::DirBuilder {
924925
}
925926
}
926927

928+
/// Change the owner and group of the specified path.
929+
///
930+
/// Specifying either the uid or gid as `None` will leave it unchanged.
931+
///
932+
/// Changing the owner typically requires privileges, such as root or a specific capability.
933+
/// Changing the group typically requires either being the owner and a member of the group, or
934+
/// having privileges.
935+
///
936+
/// If called on a symbolic link, this will change the owner and group of the link target. To
937+
/// change the owner and group of the link itself, see [`lchown`].
938+
///
939+
/// # Examples
940+
///
941+
/// ```no_run
942+
/// #![feature(unix_chown)]
943+
/// use std::os::unix::fs;
944+
///
945+
/// fn main() -> std::io::Result<()> {
946+
/// fs::chown("/sandbox", Some(0), Some(0))?;
947+
/// Ok(())
948+
/// }
949+
/// ```
950+
#[unstable(feature = "unix_chown", issue = "88989")]
951+
pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
952+
sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
953+
}
954+
955+
/// Change the owner and group of the file referenced by the specified open file descriptor.
956+
///
957+
/// For semantics and required privileges, see [`chown`].
958+
///
959+
/// # Examples
960+
///
961+
/// ```no_run
962+
/// #![feature(unix_chown)]
963+
/// use std::os::unix::fs;
964+
///
965+
/// fn main() -> std::io::Result<()> {
966+
/// let f = std::fs::File::open("/file")?;
967+
/// fs::fchown(f, Some(0), Some(0))?;
968+
/// Ok(())
969+
/// }
970+
/// ```
971+
#[unstable(feature = "unix_chown", issue = "88989")]
972+
pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
973+
sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
974+
}
975+
976+
/// Change the owner and group of the specified path, without dereferencing symbolic links.
977+
///
978+
/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner
979+
/// and group of the link itself rather than the owner and group of the link target.
980+
///
981+
/// # Examples
982+
///
983+
/// ```no_run
984+
/// #![feature(unix_chown)]
985+
/// use std::os::unix::fs;
986+
///
987+
/// fn main() -> std::io::Result<()> {
988+
/// fs::lchown("/symlink", Some(0), Some(0))?;
989+
/// Ok(())
990+
/// }
991+
/// ```
992+
#[unstable(feature = "unix_chown", issue = "88989")]
993+
pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
994+
sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
995+
}
996+
927997
/// Change the root directory of the current process to the specified path.
928998
///
929999
/// This typically requires privileges, such as root or a specific capability.

library/std/src/sys/unix/fs.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,23 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
14161416
Ok(bytes_copied as u64)
14171417
}
14181418

1419+
pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
1420+
let path = cstr(path)?;
1421+
cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
1422+
Ok(())
1423+
}
1424+
1425+
pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
1426+
cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?;
1427+
Ok(())
1428+
}
1429+
1430+
pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
1431+
let path = cstr(path)?;
1432+
cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
1433+
Ok(())
1434+
}
1435+
14191436
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
14201437
pub fn chroot(dir: &Path) -> io::Result<()> {
14211438
let dir = cstr(dir)?;

0 commit comments

Comments
 (0)