• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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