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