rustix/
ugid.rs

1//! User and Group ID types.
2
3use core::fmt;
4
5use crate::backend::c;
6use crate::ffi;
7
8/// A group identifier as a raw integer.
9pub type RawGid = ffi::c_uint;
10/// A user identifier as a raw integer.
11pub type RawUid = ffi::c_uint;
12
13/// `uid_t`—A Unix user ID.
14#[repr(transparent)]
15#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
16pub struct Uid(RawUid);
17
18/// `gid_t`—A Unix group ID.
19#[repr(transparent)]
20#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
21pub struct Gid(RawGid);
22
23impl Uid {
24    /// A `Uid` corresponding to the root user (uid 0).
25    pub const ROOT: Self = Self(0);
26
27    /// Converts a `RawUid` into a `Uid`.
28    ///
29    /// `raw` must be the value of a valid Unix user ID, and not `-1`.
30    #[inline]
31    pub fn from_raw(raw: RawUid) -> Self {
32        debug_assert_ne!(raw, !0);
33        Self(raw)
34    }
35
36    /// Converts a `RawUid` into a `Uid`.
37    ///
38    /// `raw` must be the value of a valid Unix user ID, and not `-1`.
39    #[inline]
40    pub const fn from_raw_unchecked(raw: RawUid) -> Self {
41        Self(raw)
42    }
43
44    /// Converts a `Uid` into a `RawUid`.
45    #[inline]
46    pub const fn as_raw(self) -> RawUid {
47        self.0
48    }
49
50    /// Test whether this uid represents the root user ([`Uid::ROOT`]).
51    #[inline]
52    pub const fn is_root(self) -> bool {
53        self.0 == Self::ROOT.0
54    }
55}
56
57impl Gid {
58    /// A `Gid` corresponding to the root group (gid 0).
59    pub const ROOT: Self = Self(0);
60
61    /// Converts a `RawGid` into a `Gid`.
62    ///
63    /// `raw` must be the value of a valid Unix group ID, and not `-1`.
64    #[inline]
65    pub fn from_raw(raw: RawGid) -> Self {
66        debug_assert_ne!(raw, !0);
67        Self(raw)
68    }
69
70    /// Converts a `RawGid` into a `Gid`.
71    ///
72    /// `raw` must be the value of a valid Unix group ID, and not `-1`.
73    #[inline]
74    pub const fn from_raw_unchecked(raw: RawGid) -> Self {
75        Self(raw)
76    }
77
78    /// Converts a `Gid` into a `RawGid`.
79    #[inline]
80    pub const fn as_raw(self) -> RawGid {
81        self.0
82    }
83
84    /// Test whether this gid represents the root group ([`Gid::ROOT`]).
85    #[inline]
86    pub const fn is_root(self) -> bool {
87        self.0 == Self::ROOT.0
88    }
89}
90
91impl fmt::Display for Uid {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        self.0.fmt(f)
94    }
95}
96impl fmt::Binary for Uid {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        self.0.fmt(f)
99    }
100}
101impl fmt::Octal for Uid {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        self.0.fmt(f)
104    }
105}
106impl fmt::LowerHex for Uid {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        self.0.fmt(f)
109    }
110}
111impl fmt::UpperHex for Uid {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        self.0.fmt(f)
114    }
115}
116impl fmt::LowerExp for Uid {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        self.0.fmt(f)
119    }
120}
121impl fmt::UpperExp for Uid {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        self.0.fmt(f)
124    }
125}
126
127impl fmt::Display for Gid {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        self.0.fmt(f)
130    }
131}
132impl fmt::Binary for Gid {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        self.0.fmt(f)
135    }
136}
137impl fmt::Octal for Gid {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        self.0.fmt(f)
140    }
141}
142impl fmt::LowerHex for Gid {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        self.0.fmt(f)
145    }
146}
147impl fmt::UpperHex for Gid {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        self.0.fmt(f)
150    }
151}
152impl fmt::LowerExp for Gid {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        self.0.fmt(f)
155    }
156}
157impl fmt::UpperExp for Gid {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        self.0.fmt(f)
160    }
161}
162
163// Return the raw value of the IDs. In case of `None` it returns `!0` since it
164// has the same bit pattern as `-1` indicating no change to the owner/group ID.
165pub(crate) fn translate_fchown_args(
166    owner: Option<Uid>,
167    group: Option<Gid>,
168) -> (c::uid_t, c::gid_t) {
169    let ow = match owner {
170        Some(o) => o.as_raw(),
171        None => !0,
172    };
173
174    let gr = match group {
175        Some(g) => g.as_raw(),
176        None => !0,
177    };
178
179    (ow as c::uid_t, gr as c::gid_t)
180}
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185
186    #[test]
187    fn test_sizes() {
188        assert_eq_size!(RawUid, u32);
189        assert_eq_size!(RawGid, u32);
190        assert_eq_size!(RawUid, libc::uid_t);
191        assert_eq_size!(RawGid, libc::gid_t);
192    }
193}