xref: /third_party/rust/crates/rustix/src/process/id.rs (revision b8a62b91)
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
10use crate::{backend, io};
11#[cfg(any(target_os = "android", target_os = "linux"))]
12use backend::process::types::RawCpuid;
13
14/// The raw integer value of a Unix user ID.
15pub use backend::process::types::RawUid;
16
17/// The raw integer value of a Unix group ID.
18pub use backend::process::types::RawGid;
19
20/// The raw integer value of a Unix process ID.
21pub use backend::process::types::RawPid;
22
23/// The raw integer value of a Unix process ID.
24pub use backend::process::types::RawNonZeroPid;
25
26/// `uid_t`—A Unix user ID.
27#[repr(transparent)]
28#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
29pub struct Uid(RawUid);
30
31/// `gid_t`—A Unix group ID.
32#[repr(transparent)]
33#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
34pub 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)]
43pub 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)]
49pub struct Cpuid(RawCpuid);
50
51impl 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]
61    pub const unsafe fn from_raw(raw: RawUid) -> Self {
62        Self(raw)
63    }
64
65    /// Converts a `Uid` into a `RawUid`.
66    #[inline]
67    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]
73    pub const fn is_root(self) -> bool {
74        self.0 == Self::ROOT.0
75    }
76}
77
78impl 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]
88    pub const unsafe fn from_raw(raw: RawGid) -> Self {
89        Self(raw)
90    }
91
92    /// Converts a `Gid` into a `RawGid`.
93    #[inline]
94    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]
100    pub const fn is_root(self) -> bool {
101        self.0 == Self::ROOT.0
102    }
103}
104
105impl 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]
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]
132    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]
139    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]
150    pub const fn as_raw_nonzero(self) -> RawNonZeroPid {
151        self.0
152    }
153
154    /// Converts an `Option<Pid>` into a `RawPid`.
155    #[inline]
156    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]
162    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"))]
168impl 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]
175    pub const unsafe fn from_raw(raw: RawCpuid) -> Self {
176        Self(raw)
177    }
178
179    /// Converts a `Cpuid` into a `RawCpuid`.
180    #[inline]
181    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]
196pub 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]
210pub 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]
224pub 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]
238pub 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]
252pub 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]
266pub 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]
279pub 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]
293pub 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]
306pub 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.
313pub(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