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(feature = "alloc")]
12 use alloc::vec::Vec;
13 #[cfg(linux_kernel)]
14 use backend::process::types::RawCpuid;
15 
16 /// The raw integer value of a Unix user ID.
17 pub use crate::ugid::RawUid;
18 
19 /// The raw integer value of a Unix group ID.
20 pub use crate::ugid::RawGid;
21 
22 /// The raw integer value of a Unix process ID.
23 pub use crate::pid::RawPid;
24 
25 pub use crate::pid::Pid;
26 pub use crate::ugid::{Gid, Uid};
27 
28 /// A Linux CPU ID.
29 #[cfg(linux_kernel)]
30 #[repr(transparent)]
31 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
32 pub struct Cpuid(RawCpuid);
33 
34 #[cfg(linux_kernel)]
35 impl Cpuid {
36     /// Converts a `RawCpuid` into a `Cpuid`.
37     ///
38     /// # Safety
39     ///
40     /// `raw` must be the value of a valid Linux CPU ID.
41     #[inline]
from_raw(raw: RawCpuid) -> Self42     pub const unsafe fn from_raw(raw: RawCpuid) -> Self {
43         Self(raw)
44     }
45 
46     /// Converts a `Cpuid` into a `RawCpuid`.
47     #[inline]
as_raw(self) -> RawCpuid48     pub const fn as_raw(self) -> RawCpuid {
49         self.0
50     }
51 }
52 
53 /// `getuid()`—Returns the process' real user ID.
54 ///
55 /// # References
56 ///  - [POSIX]
57 ///  - [Linux]
58 ///
59 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
60 /// [Linux]: https://man7.org/linux/man-pages/man2/getuid.2.html
61 #[inline]
62 #[must_use]
getuid() -> Uid63 pub fn getuid() -> Uid {
64     backend::ugid::syscalls::getuid()
65 }
66 
67 /// `geteuid()`—Returns the process' effective user ID.
68 ///
69 /// # References
70 ///  - [POSIX]
71 ///  - [Linux]
72 ///
73 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
74 /// [Linux]: https://man7.org/linux/man-pages/man2/geteuid.2.html
75 #[inline]
76 #[must_use]
geteuid() -> Uid77 pub fn geteuid() -> Uid {
78     backend::ugid::syscalls::geteuid()
79 }
80 
81 /// `getgid()`—Returns the process' real group ID.
82 ///
83 /// # References
84 ///  - [POSIX]
85 ///  - [Linux]
86 ///
87 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
88 /// [Linux]: https://man7.org/linux/man-pages/man2/getgid.2.html
89 #[inline]
90 #[must_use]
getgid() -> Gid91 pub fn getgid() -> Gid {
92     backend::ugid::syscalls::getgid()
93 }
94 
95 /// `getegid()`—Returns the process' effective group ID.
96 ///
97 /// # References
98 ///  - [POSIX]
99 ///  - [Linux]
100 ///
101 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html
102 /// [Linux]: https://man7.org/linux/man-pages/man2/getegid.2.html
103 #[inline]
104 #[must_use]
getegid() -> Gid105 pub fn getegid() -> Gid {
106     backend::ugid::syscalls::getegid()
107 }
108 
109 /// `getpid()`—Returns the process' ID.
110 ///
111 /// # References
112 ///  - [POSIX]
113 ///  - [Linux]
114 ///
115 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html
116 /// [Linux]: https://man7.org/linux/man-pages/man2/getpid.2.html
117 #[inline]
118 #[must_use]
getpid() -> Pid119 pub fn getpid() -> Pid {
120     backend::pid::syscalls::getpid()
121 }
122 
123 /// `getppid()`—Returns the parent process' ID.
124 ///
125 /// # References
126 ///  - [POSIX]
127 ///  - [Linux]
128 ///
129 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html
130 /// [Linux]: https://man7.org/linux/man-pages/man2/getppid.2.html
131 #[inline]
132 #[must_use]
getppid() -> Option<Pid>133 pub fn getppid() -> Option<Pid> {
134     backend::process::syscalls::getppid()
135 }
136 
137 /// `getpgid(pid)`—Returns the process group ID of the given process.
138 ///
139 /// # References
140 ///  - [POSIX]
141 ///  - [Linux]
142 ///
143 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgid.html
144 /// [Linux]: https://man7.org/linux/man-pages/man2/getpgid.2.html
145 #[inline]
getpgid(pid: Option<Pid>) -> io::Result<Pid>146 pub fn getpgid(pid: Option<Pid>) -> io::Result<Pid> {
147     backend::process::syscalls::getpgid(pid)
148 }
149 
150 /// `setpgid(pid, pgid)`—Sets the process group ID of the given process.
151 ///
152 /// # References
153 ///  - [POSIX]
154 ///  - [Linux]
155 ///
156 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html
157 /// [Linux]: https://man7.org/linux/man-pages/man2/setpgid.2.html
158 #[inline]
setpgid(pid: Option<Pid>, pgid: Option<Pid>) -> io::Result<()>159 pub fn setpgid(pid: Option<Pid>, pgid: Option<Pid>) -> io::Result<()> {
160     backend::process::syscalls::setpgid(pid, pgid)
161 }
162 
163 /// `getpgrp()`—Returns the process' group ID.
164 ///
165 /// # References
166 ///  - [POSIX]
167 ///  - [Linux]
168 ///
169 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html
170 /// [Linux]: https://man7.org/linux/man-pages/man2/getpgrp.2.html
171 #[inline]
172 #[must_use]
getpgrp() -> Pid173 pub fn getpgrp() -> Pid {
174     backend::process::syscalls::getpgrp()
175 }
176 
177 /// `getsid(pid)`—Get the session ID of the given process.
178 ///
179 /// # References
180 ///  - [POSIX]
181 ///  - [Linux]
182 ///
183 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html
184 /// [Linux]: https://man7.org/linux/man-pages/man2/getsid.2.html
185 #[cfg(not(target_os = "redox"))]
186 #[inline]
getsid(pid: Option<Pid>) -> io::Result<Pid>187 pub fn getsid(pid: Option<Pid>) -> io::Result<Pid> {
188     backend::process::syscalls::getsid(pid)
189 }
190 
191 /// `setsid()`—Create a new session.
192 ///
193 /// # References
194 ///  - [POSIX]
195 ///  - [Linux]
196 ///
197 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html
198 /// [Linux]: https://man7.org/linux/man-pages/man2/setsid.2.html
199 #[inline]
setsid() -> io::Result<Pid>200 pub fn setsid() -> io::Result<Pid> {
201     backend::process::syscalls::setsid()
202 }
203 
204 /// `getgroups()`—Return a list of the current user's groups.
205 ///
206 /// # References
207 ///  - [POSIX]
208 ///  - [Linux]
209 ///
210 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgroups.html
211 /// [Linux]: https://man7.org/linux/man-pages/man2/getgroups.2.html
212 #[cfg(feature = "alloc")]
getgroups() -> io::Result<Vec<Gid>>213 pub fn getgroups() -> io::Result<Vec<Gid>> {
214     // This code would benefit from having a better way to read into
215     // uninitialized memory, but that requires `unsafe`.
216     let mut buffer = Vec::with_capacity(8);
217     buffer.resize(buffer.capacity(), Gid::ROOT);
218 
219     loop {
220         let ngroups = backend::process::syscalls::getgroups(&mut buffer)?;
221 
222         let ngroups = ngroups as usize;
223         assert!(ngroups <= buffer.len());
224         if ngroups < buffer.len() {
225             buffer.resize(ngroups, Gid::ROOT);
226             return Ok(buffer);
227         }
228         // Use `Vec` reallocation strategy to grow capacity exponentially.
229         buffer.reserve(1);
230         buffer.resize(buffer.capacity(), Gid::ROOT);
231     }
232 }
233