Skip to content

Commit 93c9547

Browse files
authored
Add a rustix::fs::chown function. (#825)
* Add a `rustix::fs::chown` function. * Fix compile errors with inferred-type casts.
1 parent 2eedbb2 commit 93c9547

6 files changed

Lines changed: 57 additions & 5 deletions

File tree

src/backend/libc/fs/syscalls.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,14 @@ pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> {
12671267
unsafe { ret(fchmod(borrowed_fd(fd), mode.bits() as c::mode_t)) }
12681268
}
12691269

1270+
#[cfg(not(target_os = "wasi"))]
1271+
pub(crate) fn chown(path: &CStr, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
1272+
unsafe {
1273+
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
1274+
ret(c::chown(c_str(path), ow, gr))
1275+
}
1276+
}
1277+
12701278
#[cfg(linux_kernel)]
12711279
pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
12721280
// Use `c::syscall` rather than `c::fchown` because some libc

src/backend/linux_raw/fs/syscalls.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,30 @@ pub(crate) fn chownat(
158158
}
159159
}
160160

161+
#[inline]
162+
pub(crate) fn chown(path: &CStr, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
163+
// Most architectures have a `chown` syscall.
164+
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
165+
unsafe {
166+
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
167+
ret(syscall_readonly!(__NR_chown, path, c_uint(ow), c_uint(gr)))
168+
}
169+
170+
// Aarch64 and RISC-V don't, so use `fchownat`.
171+
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
172+
unsafe {
173+
let (ow, gr) = crate::ugid::translate_fchown_args(owner, group);
174+
ret(syscall_readonly!(
175+
__NR_fchownat,
176+
raw_fd(AT_FDCWD),
177+
path,
178+
c_uint(ow),
179+
c_uint(gr),
180+
zero()
181+
))
182+
}
183+
}
184+
161185
#[inline]
162186
pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
163187
unsafe {

src/backend/linux_raw/process/syscalls.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,12 @@ pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Res
366366
/// Convert a Rust [`Rlimit`] to a C `rlimit64`.
367367
#[inline]
368368
fn rlimit_from_linux(lim: rlimit64) -> Rlimit {
369-
let current = if lim.rlim_cur == RLIM64_INFINITY as _ {
369+
let current = if lim.rlim_cur as u64 == RLIM64_INFINITY as u64 {
370370
None
371371
} else {
372372
Some(lim.rlim_cur)
373373
};
374-
let maximum = if lim.rlim_max == RLIM64_INFINITY as _ {
374+
let maximum = if lim.rlim_max as u64 == RLIM64_INFINITY as u64 {
375375
None
376376
} else {
377377
Some(lim.rlim_max)
@@ -396,12 +396,12 @@ fn rlimit_to_linux(lim: Rlimit) -> rlimit64 {
396396
/// Like `rlimit_from_linux` but uses Linux's old 32-bit `rlimit`.
397397
#[allow(clippy::useless_conversion)]
398398
fn rlimit_from_linux_old(lim: rlimit) -> Rlimit {
399-
let current = if lim.rlim_cur == RLIM_INFINITY as _ {
399+
let current = if lim.rlim_cur as u32 == RLIM_INFINITY as u32 {
400400
None
401401
} else {
402402
Some(lim.rlim_cur.into())
403403
};
404-
let maximum = if lim.rlim_max == RLIM_INFINITY as _ {
404+
let maximum = if lim.rlim_max as u32 == RLIM_INFINITY as u32 {
405405
None
406406
} else {
407407
Some(lim.rlim_max.into())

src/backend/linux_raw/vdso.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
167167
.as_ptr();
168168
}
169169
DT_SYMENT => {
170-
if d.d_un.d_val != size_of::<Elf_Sym>() as _ {
170+
if d.d_un.d_ptr != size_of::<Elf_Sym>() {
171171
return None; // Failed
172172
}
173173
}

src/fs/abs.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use crate::fs::StatFs;
1616
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
1717
use crate::fs::StatVfs;
1818
use crate::fs::{Mode, OFlags, Stat};
19+
#[cfg(not(target_os = "wasi"))]
20+
use crate::ugid::{Gid, Uid};
1921
use crate::{backend, io, path};
2022
#[cfg(feature = "alloc")]
2123
use {
@@ -280,3 +282,17 @@ pub fn statfs<P: path::Arg>(path: P) -> io::Result<StatFs> {
280282
pub fn statvfs<P: path::Arg>(path: P) -> io::Result<StatVfs> {
281283
path.into_with_c_str(backend::fs::syscalls::statvfs)
282284
}
285+
286+
/// `chown(path, owner, group)`—Sets open file or directory ownership.
287+
///
288+
/// # References
289+
/// - [POSIX]
290+
/// - [Linux]
291+
///
292+
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html
293+
/// [Linux]: https://man7.org/linux/man-pages/man2/chown.2.html
294+
#[cfg(not(target_os = "wasi"))]
295+
#[inline]
296+
pub fn chown<P: path::Arg>(path: P, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
297+
path.into_with_c_str(|path| backend::fs::syscalls::chown(path, owner, group))
298+
}

tests/fs/file.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ fn test_file() {
99
)
1010
.unwrap();
1111

12+
rustix::fs::chown("Cargo.toml", None, None).unwrap();
13+
1214
#[cfg(not(any(target_os = "emscripten", target_os = "android")))]
1315
#[allow(unreachable_patterns)]
1416
match rustix::fs::accessat(
@@ -66,6 +68,8 @@ fn test_file() {
6668
)
6769
.unwrap();
6870

71+
rustix::fs::fchown(&file, None, None).unwrap();
72+
6973
assert_eq!(
7074
rustix::fs::openat(
7175
&file,

0 commit comments

Comments
 (0)