1 //! Unix user, group, and process identifiers.
2 //!
3 //! # Safety
4 //!
5 //! The `Uid`, `Gid`, and `Pid` types can be constructed from raw integers,
6 //! which is marked unsafe because actual OS's assign special meaning to some
7 //! integer values.
8 #![allow(unsafe_code)]
9
10 use crate::{backend, io};
11 #[cfg(any(target_os = "android", target_os = "linux"))]
12 use backend::process::types::RawCpuid;
13
14 /// The raw integer value of a Unix user ID.
15 pub use backend::process::types::RawUid;
16
17 /// The raw integer value of a Unix group ID.
18 pub use backend::process::types::RawGid;
19
20 /// The raw integer value of a Unix process ID.
21 pub use backend::process::types::RawPid;
22
23 /// The raw integer value of a Unix process ID.
24 pub use backend::process::types::RawNonZeroPid;
25
26 /// `uid_t`—A Unix user ID.
27 #[repr(transparent)]
28 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
29 pub struct Uid(RawUid);
30
31 /// `gid_t`—A Unix group ID.
32 #[repr(transparent)]
33 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
34 pub struct Gid(RawGid);
35
36 /// `pid_t`—A non-zero Unix process ID.
37 ///
38 /// This is a pid, and not a pidfd. It is not a file descriptor, and the
39 /// process it refers to could disappear at any time and be replaced by
40 /// another, unrelated, process.
41 #[repr(transparent)]
42 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
43 pub struct Pid(RawNonZeroPid);
44
45 /// A Linux CPU ID.
46 #[cfg(any(target_os = "android", target_os = "linux"))]
47 #[repr(transparent)]
48 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
49 pub struct Cpuid(RawCpuid);
50
51 impl Uid {
52 /// A `Uid` corresponding to the root user (uid 0).
53 pub const ROOT: Self = Self(0);
54
55 /// Converts a `RawUid` into a `Uid`.
56 ///
57 /// # Safety
58 ///
59 /// `raw` must be the value of a valid Unix user ID.
60 #[inline]
from_raw(raw: RawUid) -> Self61 pub const unsafe fn from_raw(raw: RawUid) -> Self {
62 Self(raw)
63 }
64
65 /// Converts a `Uid` into a `RawUid`.
66 #[inline]
as_raw(self) -> RawUid67 pub const fn as_raw(self) -> RawUid {
68 self.0
69 }
70
71 /// Test whether this uid represents the root user (uid 0).
72 #[inline]
is_root(self) -> bool73 pub const fn is_root(self) -> bool {
74 self.0 == Self::ROOT.0
75 }
76 }
77
78 impl Gid {
79 /// A `Gid` corresponding to the root group (gid 0).
80 pub const ROOT: Self = Self(0);
81
82 /// Converts a `RawGid` into a `Gid`.
83 ///
84 /// # Safety
85 ///
86 /// `raw` must be the value of a valid Unix group ID.
87 #[inline]
from_raw(raw: RawGid) -> Self88 pub const unsafe fn from_raw(raw: RawGid) -> Self {
89 Self(raw)
90 }
91
92 /// Converts a `Gid` into a `RawGid`.
93 #[inline]
as_raw(self) -> RawGid94 pub const fn as_raw(self) -> RawGid {
95 self.0
96 }
97
98 /// Test whether this gid represents the root group (gid 0).
99 #[inline]
is_root(self) -> bool100 pub const fn is_root(self) -> bool {
101 self.0 == Self::ROOT.0
102 }
103 }
104
105 impl Pid {
106 /// A `Pid` corresponding to the init process (pid 1).
107 pub const INIT: Self = Self(
108 // Safety: The init process' pid is always valid.
109 unsafe { RawNonZeroPid::new_unchecked(1) },
110 );
111
112 /// Converts a `RawPid` into a `Pid`.
113 ///
114 /// # Safety
115 ///
116 /// `raw` must be the value of a valid Unix process ID, or zero.
117 #[inline]
from_raw(raw: RawPid) -> Option<Self>118 pub const unsafe fn from_raw(raw: RawPid) -> Option<Self> {
119 match RawNonZeroPid::new(raw) {
120 Some(pid) => Some(Self(pid)),
121 None => None,
122 }
123 }
124
125 /// Converts a known non-zero `RawPid` into a `Pid`.
126 ///
127 /// # Safety
128 ///
129 /// `raw` must be the value of a valid Unix process ID. It must not be
130 /// zero.
131 #[inline]
from_raw_nonzero(raw: RawNonZeroPid) -> Self132 pub const unsafe fn from_raw_nonzero(raw: RawNonZeroPid) -> Self {
133 Self(raw)
134 }
135
136 /// Creates a `Pid` holding the ID of the given child process.
137 #[cfg(feature = "std")]
138 #[inline]
from_child(child: &std::process::Child) -> Self139 pub fn from_child(child: &std::process::Child) -> Self {
140 let id = child.id();
141 debug_assert_ne!(id, 0);
142
143 // Safety: We know the returned ID is valid because it came directly
144 // from an OS API.
145 unsafe { Self::from_raw_nonzero(RawNonZeroPid::new_unchecked(id as _)) }
146 }
147
148 /// Converts a `Pid` into a `RawNonZeroPid`.
149 #[inline]
as_raw_nonzero(self) -> RawNonZeroPid150 pub const fn as_raw_nonzero(self) -> RawNonZeroPid {
151 self.0
152 }
153
154 /// Converts an `Option<Pid>` into a `RawPid`.
155 #[inline]
as_raw(pid: Option<Self>) -> RawPid156 pub fn as_raw(pid: Option<Self>) -> RawPid {
157 pid.map_or(0, |pid| pid.0.get())
158 }
159
160 /// Test whether this pid represents the init process (pid 0).
161 #[inline]
is_init(self) -> bool162 pub const fn is_init(self) -> bool {
163 self.0.get() == Self::INIT.0.get()
164 }
165 }
166
167 #[cfg(any(target_os = "android", target_os = "linux"))]
168 impl Cpuid {
169 /// Converts a `RawCpuid` into a `Cpuid`.
170 ///
171 /// # Safety
172 ///
173 /// `raw` must be the value of a valid Linux CPU ID.
174 #[inline]
from_raw(raw: RawCpuid) -> Self175 pub const unsafe fn from_raw(raw: RawCpuid) -> Self {
176 Self(raw)
177 }
178
179 /// Converts a `Cpuid` into a `RawCpuid`.
180 #[inline]
as_raw(self) -> RawCpuid181 pub const fn as_raw(self) -> RawCpuid {
182 self.0
183 }
184 }
185
186 /// `getuid()`—Returns the process' real user ID.
187 ///
188 /// # References
189 /// - [POSIX]
190 /// - [Linux]
191 ///
192 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
193 /// [Linux]: https://man7.org/linux/man-pages/man2/getuid.2.html
194 #[inline]
195 #[must_use]
getuid() -> Uid196 pub fn getuid() -> Uid {
197 backend::process::syscalls::getuid()
198 }
199
200 /// `geteuid()`—Returns the process' effective user ID.
201 ///
202 /// # References
203 /// - [POSIX]
204 /// - [Linux]
205 ///
206 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
207 /// [Linux]: https://man7.org/linux/man-pages/man2/geteuid.2.html
208 #[inline]
209 #[must_use]
geteuid() -> Uid210 pub fn geteuid() -> Uid {
211 backend::process::syscalls::geteuid()
212 }
213
214 /// `getgid()`—Returns the process' real group ID.
215 ///
216 /// # References
217 /// - [POSIX]
218 /// - [Linux]
219 ///
220 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
221 /// [Linux]: https://man7.org/linux/man-pages/man2/getgid.2.html
222 #[inline]
223 #[must_use]
getgid() -> Gid224 pub fn getgid() -> Gid {
225 backend::process::syscalls::getgid()
226 }
227
228 /// `getegid()`—Returns the process' effective group ID.
229 ///
230 /// # References
231 /// - [POSIX]
232 /// - [Linux]
233 ///
234 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html
235 /// [Linux]: https://man7.org/linux/man-pages/man2/getegid.2.html
236 #[inline]
237 #[must_use]
getegid() -> Gid238 pub fn getegid() -> Gid {
239 backend::process::syscalls::getegid()
240 }
241
242 /// `getpid()`—Returns the process' ID.
243 ///
244 /// # References
245 /// - [POSIX]
246 /// - [Linux]
247 ///
248 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html
249 /// [Linux]: https://man7.org/linux/man-pages/man2/getpid.2.html
250 #[inline]
251 #[must_use]
getpid() -> Pid252 pub fn getpid() -> Pid {
253 backend::process::syscalls::getpid()
254 }
255
256 /// `getppid()`—Returns the parent process' ID.
257 ///
258 /// # References
259 /// - [POSIX]
260 /// - [Linux]
261 ///
262 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html
263 /// [Linux]: https://man7.org/linux/man-pages/man2/getppid.2.html
264 #[inline]
265 #[must_use]
getppid() -> Option<Pid>266 pub fn getppid() -> Option<Pid> {
267 backend::process::syscalls::getppid()
268 }
269
270 /// `getpgid(pid)`—Returns the process group ID of the given process.
271 ///
272 /// # References
273 /// - [POSIX]
274 /// - [Linux]
275 ///
276 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgid.html
277 /// [Linux]: https://man7.org/linux/man-pages/man2/getpgid.2.html
278 #[inline]
getpgid(pid: Option<Pid>) -> io::Result<Pid>279 pub fn getpgid(pid: Option<Pid>) -> io::Result<Pid> {
280 backend::process::syscalls::getpgid(pid)
281 }
282
283 /// `getpgrp()`—Returns the process' group ID.
284 ///
285 /// # References
286 /// - [POSIX]
287 /// - [Linux]
288 ///
289 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html
290 /// [Linux]: https://man7.org/linux/man-pages/man2/getpgrp.2.html
291 #[inline]
292 #[must_use]
getpgrp() -> Pid293 pub fn getpgrp() -> Pid {
294 backend::process::syscalls::getpgrp()
295 }
296
297 /// `setsid()`—Create a new session.
298 ///
299 /// # References
300 /// - [POSIX]
301 /// - [Linux]
302 ///
303 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html
304 /// [Linux]: https://man7.org/linux/man-pages/man2/setsid.2.html
305 #[inline]
setsid() -> io::Result<Pid>306 pub fn setsid() -> io::Result<Pid> {
307 backend::process::syscalls::setsid()
308 }
309
310 // translate_fchown_args returns the raw value of the IDs. In case of `None`
311 // it returns `u32::MAX` since it has the same bit pattern as `-1` indicating
312 // no change to the owner/group ID.
translate_fchown_args(owner: Option<Uid>, group: Option<Gid>) -> (u32, u32)313 pub(crate) fn translate_fchown_args(owner: Option<Uid>, group: Option<Gid>) -> (u32, u32) {
314 let ow = match owner {
315 Some(o) => o.as_raw(),
316 None => u32::MAX,
317 };
318
319 let gr = match group {
320 Some(g) => g.as_raw(),
321 None => u32::MAX,
322 };
323
324 (ow, gr)
325 }
326