Skip to content

Commit b4ca74d

Browse files
committed
Improve the get_umask implementation
1 parent 34b66a8 commit b4ca74d

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

src/lib.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use std::{
22
fmt::{Debug, Display},
3-
io,
3+
fs, io,
44
};
55

6-
use rustix::{fs::Mode, process::umask};
6+
use rustix::{
7+
fs::{Mode, RawMode},
8+
process::umask,
9+
};
710

811
pub type Result<T = (), E = Exit> = std::result::Result<T, E>;
912

@@ -76,26 +79,31 @@ macro_rules! help_text {
7679
/// Gets the umask of the calling process
7780
pub fn get_umask() -> Mode {
7881
/*
79-
FIXME: Behold the umask abomination, a perfect example of UNIX's "let's make everything
80-
as backwards and painful as possible" design philosophy. This cursed bitmask lives in
81-
kernel space and can ONLY be read by WRITING TO IT because someone in 1973
82-
decided that having a simple getter function was too logical. So here we are, doing
82+
Historical note: The traditional umask() syscall is a perfect example of UNIX's "let's make
83+
everything as backwards and painful as possible" design philosophy. This cursed bitmask
84+
lives in kernel space and could ONLY be read by WRITING TO IT because someone in 1973
85+
decided that having a simple getter function was too logical. The classic approach required
8386
the umask shuffle: set it to 0, capture the old value, then set it back like some
84-
demented atomic operation that's not actually atomic. I mean who needs threads anyway,
85-
it's not like computers will ever be powerful enough to do more things at once,
86-
not for hundreds of years at the very least.
87-
88-
*sigh*
87+
demented atomic operation that's not actually atomic.
8988
90-
We SHOULD read from /proc/self/status like any sane program except nobody does that?
91-
but no - we're stuck with this fossilized turd of an API that makes you modify
92-
global state just to observe it. At least on anything older than 2016 which is more common
93-
than you'd think, sob
89+
Fortunately, modern Linux (kernel 4.7+, 2016) added umask to /proc/self/status, so we
90+
can read it cleanly without the race condition. We fall back to the traditional method
91+
for older systems or non-Linux platforms.
9492
95-
I HATE UNIX
96-
I HATE UNIX
97-
I HATE UNIX
93+
The old way was truly cursed - modifying global state just to observe it. At least
94+
we've mostly escaped that particular circle of UNIX hell on modern systems.
9895
*/
96+
97+
if let Ok(status) = fs::read_to_string("/proc/self/status") {
98+
if let Some(umask) = status
99+
.lines()
100+
.find_map(|line| RawMode::from_str_radix(line.strip_prefix("Umask:")?.trim(), 8).ok())
101+
{
102+
return Mode::from_raw_mode(umask);
103+
}
104+
}
105+
106+
// Fallback method with a possible race condition
99107
let current_umask = umask(Mode::empty());
100108
umask(current_umask);
101109

0 commit comments

Comments
 (0)