Skip to content

Commit

Permalink
Add a rustix::fs::chown function. (#825)
Browse files Browse the repository at this point in the history
* Add a `rustix::fs::chown` function.

* Fix compile errors with inferred-type casts.
  • Loading branch information
sunfishcode authored Sep 12, 2023
1 parent 2eedbb2 commit 93c9547
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
8 changes: 8 additions & 0 deletions src/backend/libc/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,14 @@ pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> {
unsafe { ret(fchmod(borrowed_fd(fd), mode.bits() as c::mode_t)) }
}

#[cfg(not(target_os = "wasi"))]
pub(crate) fn chown(path: &CStr, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
unsafe {
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
ret(c::chown(c_str(path), ow, gr))
}
}

#[cfg(linux_kernel)]
pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
// Use `c::syscall` rather than `c::fchown` because some libc
Expand Down
24 changes: 24 additions & 0 deletions src/backend/linux_raw/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,30 @@ pub(crate) fn chownat(
}
}

#[inline]
pub(crate) fn chown(path: &CStr, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
// Most architectures have a `chown` syscall.
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
unsafe {
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
ret(syscall_readonly!(__NR_chown, path, c_uint(ow), c_uint(gr)))
}

// Aarch64 and RISC-V don't, so use `fchownat`.
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
unsafe {
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
ret(syscall_readonly!(
__NR_fchownat,
raw_fd(AT_FDCWD),
path,
c_uint(ow),
c_uint(gr),
zero()
))
}
}

#[inline]
pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
unsafe {
Expand Down
8 changes: 4 additions & 4 deletions src/backend/linux_raw/process/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,12 @@ pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Res
/// Convert a Rust [`Rlimit`] to a C `rlimit64`.
#[inline]
fn rlimit_from_linux(lim: rlimit64) -> Rlimit {
let current = if lim.rlim_cur == RLIM64_INFINITY as _ {
let current = if lim.rlim_cur as u64 == RLIM64_INFINITY as u64 {
None
} else {
Some(lim.rlim_cur)
};
let maximum = if lim.rlim_max == RLIM64_INFINITY as _ {
let maximum = if lim.rlim_max as u64 == RLIM64_INFINITY as u64 {
None
} else {
Some(lim.rlim_max)
Expand All @@ -396,12 +396,12 @@ fn rlimit_to_linux(lim: Rlimit) -> rlimit64 {
/// Like `rlimit_from_linux` but uses Linux's old 32-bit `rlimit`.
#[allow(clippy::useless_conversion)]
fn rlimit_from_linux_old(lim: rlimit) -> Rlimit {
let current = if lim.rlim_cur == RLIM_INFINITY as _ {
let current = if lim.rlim_cur as u32 == RLIM_INFINITY as u32 {
None
} else {
Some(lim.rlim_cur.into())
};
let maximum = if lim.rlim_max == RLIM_INFINITY as _ {
let maximum = if lim.rlim_max as u32 == RLIM_INFINITY as u32 {
None
} else {
Some(lim.rlim_max.into())
Expand Down
2 changes: 1 addition & 1 deletion src/backend/linux_raw/vdso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
.as_ptr();
}
DT_SYMENT => {
if d.d_un.d_val != size_of::<Elf_Sym>() as _ {
if d.d_un.d_ptr != size_of::<Elf_Sym>() {
return None; // Failed
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/fs/abs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::fs::StatFs;
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
use crate::fs::StatVfs;
use crate::fs::{Mode, OFlags, Stat};
#[cfg(not(target_os = "wasi"))]
use crate::ugid::{Gid, Uid};
use crate::{backend, io, path};
#[cfg(feature = "alloc")]
use {
Expand Down Expand Up @@ -280,3 +282,17 @@ pub fn statfs<P: path::Arg>(path: P) -> io::Result<StatFs> {
pub fn statvfs<P: path::Arg>(path: P) -> io::Result<StatVfs> {
path.into_with_c_str(backend::fs::syscalls::statvfs)
}

/// `chown(path, owner, group)`—Sets open file or directory ownership.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html
/// [Linux]: https://man7.org/linux/man-pages/man2/chown.2.html
#[cfg(not(target_os = "wasi"))]
#[inline]
pub fn chown<P: path::Arg>(path: P, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
path.into_with_c_str(|path| backend::fs::syscalls::chown(path, owner, group))
}
4 changes: 4 additions & 0 deletions tests/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ fn test_file() {
)
.unwrap();

rustix::fs::chown("Cargo.toml", None, None).unwrap();

#[cfg(not(any(target_os = "emscripten", target_os = "android")))]
#[allow(unreachable_patterns)]
match rustix::fs::accessat(
Expand Down Expand Up @@ -66,6 +68,8 @@ fn test_file() {
)
.unwrap();

rustix::fs::fchown(&file, None, None).unwrap();

assert_eq!(
rustix::fs::openat(
&file,
Expand Down

0 comments on commit 93c9547

Please sign in to comment.