1 | //! User and Group ID types. |
2 | |
3 | use crate::backend::c; |
4 | use crate::ffi; |
5 | |
6 | /// A group identifier as a raw integer. |
7 | pub type RawGid = ffi::c_uint; |
8 | /// A user identifier as a raw integer. |
9 | pub type RawUid = ffi::c_uint; |
10 | |
11 | /// `uid_t`—A Unix user ID. |
12 | #[repr (transparent)] |
13 | #[derive (Copy, Clone, Eq, PartialEq, Debug, Hash)] |
14 | pub struct Uid(RawUid); |
15 | |
16 | /// `gid_t`—A Unix group ID. |
17 | #[repr (transparent)] |
18 | #[derive (Copy, Clone, Eq, PartialEq, Debug, Hash)] |
19 | pub struct Gid(RawGid); |
20 | |
21 | impl Uid { |
22 | /// A `Uid` corresponding to the root user (uid 0). |
23 | pub const ROOT: Self = Self(0); |
24 | |
25 | /// Converts a `RawUid` into a `Uid`. |
26 | /// |
27 | /// `raw` must be the value of a valid Unix user ID, and not `-1`. |
28 | #[inline ] |
29 | pub fn from_raw(raw: RawUid) -> Self { |
30 | debug_assert_ne!(raw, !0); |
31 | Self(raw) |
32 | } |
33 | |
34 | /// Converts a `RawUid` into a `Uid`. |
35 | /// |
36 | /// `raw` must be the value of a valid Unix user ID, and not `-1`. |
37 | #[inline ] |
38 | pub const fn from_raw_unchecked(raw: RawUid) -> Self { |
39 | Self(raw) |
40 | } |
41 | |
42 | /// Converts a `Uid` into a `RawUid`. |
43 | #[inline ] |
44 | pub const fn as_raw(self) -> RawUid { |
45 | self.0 |
46 | } |
47 | |
48 | /// Test whether this uid represents the root user ([`Uid::ROOT`]). |
49 | #[inline ] |
50 | pub const fn is_root(self) -> bool { |
51 | self.0 == Self::ROOT.0 |
52 | } |
53 | } |
54 | |
55 | impl Gid { |
56 | /// A `Gid` corresponding to the root group (gid 0). |
57 | pub const ROOT: Self = Self(0); |
58 | |
59 | /// Converts a `RawGid` into a `Gid`. |
60 | /// |
61 | /// `raw` must be the value of a valid Unix group ID, and not `-1`. |
62 | #[inline ] |
63 | pub fn from_raw(raw: RawGid) -> Self { |
64 | debug_assert_ne!(raw, !0); |
65 | Self(raw) |
66 | } |
67 | |
68 | /// Converts a `RawGid` into a `Gid`. |
69 | /// |
70 | /// `raw` must be the value of a valid Unix group ID, and not `-1`. |
71 | #[inline ] |
72 | pub const fn from_raw_unchecked(raw: RawGid) -> Self { |
73 | Self(raw) |
74 | } |
75 | |
76 | /// Converts a `Gid` into a `RawGid`. |
77 | #[inline ] |
78 | pub const fn as_raw(self) -> RawGid { |
79 | self.0 |
80 | } |
81 | |
82 | /// Test whether this gid represents the root group ([`Gid::ROOT`]). |
83 | #[inline ] |
84 | pub const fn is_root(self) -> bool { |
85 | self.0 == Self::ROOT.0 |
86 | } |
87 | } |
88 | |
89 | // Return the raw value of the IDs. In case of `None` it returns `!0` since it |
90 | // has the same bit pattern as `-1` indicating no change to the owner/group ID. |
91 | pub(crate) fn translate_fchown_args( |
92 | owner: Option<Uid>, |
93 | group: Option<Gid>, |
94 | ) -> (c::uid_t, c::gid_t) { |
95 | let ow: i32 = match owner { |
96 | Some(o: Uid) => o.as_raw(), |
97 | None => !0, |
98 | }; |
99 | |
100 | let gr: i32 = match group { |
101 | Some(g: Gid) => g.as_raw(), |
102 | None => !0, |
103 | }; |
104 | |
105 | (ow as c::uid_t, gr as c::gid_t) |
106 | } |
107 | |
108 | #[cfg (test)] |
109 | mod tests { |
110 | use super::*; |
111 | |
112 | #[test ] |
113 | fn test_sizes() { |
114 | assert_eq_size!(RawUid, u32); |
115 | assert_eq_size!(RawGid, u32); |
116 | assert_eq_size!(RawUid, libc::uid_t); |
117 | assert_eq_size!(RawGid, libc::gid_t); |
118 | } |
119 | } |
120 | |