Skip to content

Commit 08ea42c

Browse files
authored
Implement umask. (#585)
1 parent ac29c00 commit 08ea42c

File tree

8 files changed

+97
-13
lines changed

8 files changed

+97
-13
lines changed

src/backend/libc/process/syscalls.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
use super::super::c;
44
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
55
use super::super::conv::borrowed_fd;
6-
#[cfg(not(target_os = "wasi"))]
7-
use super::super::conv::ret_pid_t;
86
use super::super::conv::{c_str, ret, ret_c_int, ret_discarded_char_ptr};
7+
#[cfg(not(target_os = "wasi"))]
8+
use super::super::conv::{ret_infallible, ret_pid_t};
99
#[cfg(any(target_os = "android", target_os = "linux"))]
1010
use super::super::conv::{syscall_ret, syscall_ret_u32};
1111
#[cfg(any(
@@ -20,24 +20,25 @@ use crate::fd::BorrowedFd;
2020
#[cfg(target_os = "linux")]
2121
use crate::fd::{AsRawFd, OwnedFd};
2222
use crate::ffi::CStr;
23+
#[cfg(feature = "fs")]
24+
use crate::fs::Mode;
2325
use crate::io;
2426
#[cfg(not(any(target_os = "wasi", target_os = "redox", target_os = "openbsd")))]
2527
use crate::process::{WaitId, WaitidOptions, WaitidStatus};
2628
use core::mem::MaybeUninit;
27-
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
28-
use {
29-
super::super::conv::ret_infallible,
30-
super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY},
31-
crate::process::{Resource, Rlimit},
32-
core::convert::TryInto,
33-
};
3429
#[cfg(target_os = "linux")]
3530
use {super::super::conv::syscall_ret_owned_fd, crate::process::PidfdFlags};
3631
#[cfg(any(target_os = "android", target_os = "linux"))]
3732
use {
3833
super::super::offset::libc_prlimit,
3934
crate::process::{Cpuid, MembarrierCommand, MembarrierQuery},
4035
};
36+
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
37+
use {
38+
super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY},
39+
crate::process::{Resource, Rlimit},
40+
core::convert::TryInto,
41+
};
4142
#[cfg(not(target_os = "wasi"))]
4243
use {
4344
super::types::RawUname,
@@ -220,11 +221,19 @@ pub(crate) fn sched_yield() {
220221
pub(crate) fn uname() -> RawUname {
221222
let mut uname = MaybeUninit::<RawUname>::uninit();
222223
unsafe {
223-
ret(c::uname(uname.as_mut_ptr())).unwrap();
224+
ret_infallible(c::uname(uname.as_mut_ptr()));
224225
uname.assume_init()
225226
}
226227
}
227228

229+
#[cfg(not(target_os = "wasi"))]
230+
#[cfg(feature = "fs")]
231+
#[inline]
232+
pub(crate) fn umask(mask: Mode) -> Mode {
233+
// TODO: Use `from_bits_retain` when we switch to bitflags 2.0.
234+
unsafe { Mode::from_bits_truncate(c::umask(mask.bits() as _) as _) }
235+
}
236+
228237
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
229238
#[inline]
230239
pub(crate) fn nice(inc: i32) -> io::Result<i32> {

src/backend/linux_raw/conv.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616
use super::c;
1717
use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
18-
#[cfg(not(debug_assertions))]
19-
use super::io::errno::decode_usize_infallible;
2018
#[cfg(feature = "runtime")]
2119
use super::io::errno::try_decode_error;
2220
#[cfg(target_pointer_width = "64")]
2321
use super::io::errno::try_decode_u64;
22+
#[cfg(not(debug_assertions))]
23+
use super::io::errno::{decode_c_uint_infallible, decode_usize_infallible};
2424
use super::io::errno::{
2525
try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
2626
try_decode_void_star,
@@ -802,6 +802,25 @@ pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
802802
}
803803
}
804804

805+
/// Convert a `c_uint` returned from a syscall that effectively always
806+
/// returns a `c_uint`.
807+
///
808+
/// # Safety
809+
///
810+
/// This function must only be used with return values from infallible
811+
/// syscalls.
812+
#[inline]
813+
pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint {
814+
#[cfg(debug_assertions)]
815+
{
816+
try_decode_c_uint(raw).unwrap()
817+
}
818+
#[cfg(not(debug_assertions))]
819+
{
820+
decode_c_uint_infallible(raw)
821+
}
822+
}
823+
805824
/// Convert a `usize` returned from a syscall that effectively returns an
806825
/// `OwnedFd` on success.
807826
///

src/backend/linux_raw/io/errno.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ pub(in crate::backend) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Nu
236236
raw.decode_usize()
237237
}
238238

239+
/// Return the contained `c_int` value.
240+
#[cfg(not(debug_assertions))]
241+
#[inline]
242+
pub(in crate::backend) fn decode_c_uint_infallible<Num: RetNumber>(raw: RetReg<Num>) -> c::c_uint {
243+
raw.decode_c_uint()
244+
}
245+
239246
impl Errno {
240247
/// `EACCES`
241248
#[doc(alias = "ACCES")]

src/backend/linux_raw/process/syscalls.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ use linux_raw_sys::general::{
2828
__kernel_gid_t, __kernel_pid_t, __kernel_uid_t, membarrier_cmd, membarrier_cmd_flag, rlimit,
2929
rlimit64, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, RLIM64_INFINITY, RLIM_INFINITY,
3030
};
31+
#[cfg(not(target_os = "wasi"))]
32+
#[cfg(feature = "fs")]
33+
use {super::super::conv::ret_c_uint_infallible, crate::fs::Mode};
3134

3235
#[inline]
3336
pub(crate) fn chdir(filename: &CStr) -> io::Result<()> {
@@ -236,11 +239,20 @@ pub(crate) fn sched_yield() {
236239
pub(crate) fn uname() -> RawUname {
237240
let mut uname = MaybeUninit::<RawUname>::uninit();
238241
unsafe {
239-
ret(syscall!(__NR_uname, &mut uname)).unwrap();
242+
ret_infallible(syscall!(__NR_uname, &mut uname));
240243
uname.assume_init()
241244
}
242245
}
243246

247+
#[cfg(feature = "fs")]
248+
#[inline]
249+
pub(crate) fn umask(mode: Mode) -> Mode {
250+
unsafe {
251+
// TODO: Use `from_bits_retain` when we switch to bitflags 2.0.
252+
Mode::from_bits_truncate(ret_c_uint_infallible(syscall_readonly!(__NR_umask, mode)))
253+
}
254+
}
255+
244256
#[inline]
245257
pub(crate) fn nice(inc: i32) -> io::Result<i32> {
246258
let priority = if inc > -40 && inc < 40 {

src/process/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ mod rlimit;
2727
))]
2828
mod sched;
2929
mod sched_yield;
30+
#[cfg(not(target_os = "wasi"))] // WASI doesn't have umask.
31+
mod umask;
3032
#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname.
3133
mod uname;
3234
#[cfg(not(target_os = "wasi"))]
@@ -60,6 +62,8 @@ pub use rlimit::*;
6062
pub use sched::*;
6163
pub use sched_yield::sched_yield;
6264
#[cfg(not(target_os = "wasi"))]
65+
pub use umask::*;
66+
#[cfg(not(target_os = "wasi"))]
6367
pub use uname::{uname, Uname};
6468
#[cfg(not(target_os = "wasi"))]
6569
pub use wait::*;

src/process/umask.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//! Umask support.
2+
3+
#[cfg(feature = "fs")]
4+
use crate::backend;
5+
#[cfg(feature = "fs")]
6+
use crate::fs::Mode;
7+
8+
/// `umask(mask)`—Set the process file creation mask.
9+
///
10+
/// # References
11+
/// - [POSIX]
12+
/// - [Linux]
13+
///
14+
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html
15+
/// [Linux]: https://man7.org/linux/man-pages/man2/umask.2.html
16+
#[inline]
17+
#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
18+
#[cfg(feature = "fs")]
19+
pub fn umask(mask: Mode) -> Mode {
20+
backend::process::syscalls::umask(mask)
21+
}

tests/process/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ mod procctl;
2626
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
2727
mod rlimit;
2828
mod sched_yield;
29+
#[cfg(not(target_os = "wasi"))] // WASI doesn't have umask.
30+
mod umask;
2931
#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname.
3032
mod uname;
3133
#[cfg(not(target_os = "wasi"))] // WASI doesn't have waitpid.

tests/process/umask.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[cfg(feature = "fs")]
2+
#[test]
3+
fn test_umask() {
4+
use rustix::fs::Mode;
5+
6+
let tmp = Mode::RWXO | Mode::RWXG;
7+
let old = rustix::process::umask(tmp);
8+
let new = rustix::process::umask(old);
9+
assert_eq!(tmp, new);
10+
}

0 commit comments

Comments
 (0)