1use super::*;
4
5pub trait PwdGrpString: SealedString + Deref {}
13
14impl PwdGrpString for Box<str> {}
15impl PwdGrpString for Box<[u8]> {}
16impl PwdGrpString for String {}
17impl PwdGrpString for Vec<u8> {}
18
19impl PwdGrpProvider for PwdGrp {}
20
21define_derive_deftly! {
22 Blank for struct, expect items:
23
24 impl<S: Default> $tname<S> {
25 pub fn blank() -> Self {
30 Self { $( ${select1 fmeta(dummy) {
31 $fname: NonExhaustive {},
32 } else {
33 $fname: Default::default(),
34 }})}
35 }
36 }
37}
38
39#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
65#[allow(clippy::exhaustive_structs)] pub struct PwdGrp;
67
68macro_rules! define_generic_entrypoint {
70 {
72 fn $getfoobar:ident($key:ident: $keytype:ty) -> $out:ty;
73 } => { define_generic_entrypoint! {
74 fn $getfoobar($key: $keytype, $keytype; ) -> $out { }
75 } };
76
77 {
79 fn $getfoobar:ident($key:ident) -> $out:ty;
80 } => { define_generic_entrypoint! {
81 fn $getfoobar(
82 $key:
83 impl AsRef<str>,
84 impl AsRef<<S as Deref>::Target>;
85 .as_ref()
86 ) -> $out {
87 let $key: &[u8] = <S as SealedString>::as_u8($key.as_ref());
88 }
89 } };
90
91 {
93 fn $getfoobar:ident(
94 $key:ident:
95 $ktsim:ty,
96 $ktgen:ty;
97 $( $k_as_ref:tt )*
98 ) -> $out:ty {
99 $( $bind_key:tt )*
100 }
101 } => { paste!{
102 #[doc = stringify!([< $out:lower >])]
104 #[doc = concat!(stringify!([< $key >]), ",")]
106 fn $getfoobar<S: PwdGrpString>(
108 &self,
109 $key: $ktgen,
110 ) -> io::Result<Option<$out<S>>> {
111 $( $bind_key )*
112
113 let value = {
114 if let Some(mock) = self.with_mocks(|data| {
115 data.0.[< $out:lower >].iter().find(|ent| {
116 $key == ent.$key $( $k_as_ref )*
117 }).cloned().into()
118 }) {
119 mock
120 } else {
121 [< $getfoobar _inner >](RealLibc, $key)?
122 }
123 };
124
125 value
126 .map(|v| $out::<S>::try_convert_from(v, ""))
127 .transpose()
128 .map_err(<S as SealedString>::handle_error_as_io)
129 }
130 } };
131}
132
133macro_rules! define_getid_wrapper { {
134 $fn:ident: $id:ident. $f:ident, $doc:literal $( $real:literal )?
135} => { define_getid_wrapper! {
136 @ $fn: $id, $doc $($real)?,
137 Id,
138 |mock: mock::RealEffectiveSavedIds| mock.$f,
139} }; {
140 $fn:ident: $id:ident. ($( $f:ident )*), $doc:literal $( $real:literal )?
141} => { define_getid_wrapper! {
142 @ $fn: $id, $doc $($real)?,
143 (Id, Id, Id),
144 |mock: mock::RealEffectiveSavedIds| ( $( mock.$f, )* ),
145} }; {
146 @ $fn:ident: $id:ident, $doc:literal $( $want_real_warn:literal )?,
147 $ret:ty,
148 $if_mock:expr,
149} => { paste!{
150 #[doc = $doc]
152 #[doc = $doc]
156 $(
157 #[doc = $want_real_warn]
159 )?
160 fn $fn(&self) -> $ret {
161 match self.with_mocks(|data| data.0.[< $id s >]) {
162 Some(mock) => ($if_mock)(mock),
163 None => [<$fn _inner>](RealLibc),
164 }
165 }
166} } }
167
168macro_rules! for_getid_wrappers { { $call:ident } => {
169 $call! { getuid: uid. r, "(real) uid" ""}
170 $call! { geteuid: uid. e, "effective uid"}
171 if_cfg_getresuid! {
172 $call! { getresuid: uid. (r e s), "real, effective and saved set-uid" ""}
173 }
174 $call! { getgid: gid. r, "(real) gid" ""}
175 $call! { getegid: gid. e, "effective gid"}
176 if_cfg_getresuid! {
177 $call! { getresgid: gid. (r e s), "real, effective and saved set-gid" ""}
178 }
179} }
180
181pub trait PwdGrpProvider: SealedProvider {
188 define_generic_entrypoint! { fn getpwnam(name) -> Passwd; }
189 define_generic_entrypoint! { fn getpwuid(uid: Id) -> Passwd; }
190 define_generic_entrypoint! { fn getgrnam(name) -> Group; }
191 define_generic_entrypoint! { fn getgrgid(gid: Id) -> Group; }
192 for_getid_wrappers! { define_getid_wrapper }
193
194 fn getgroups(&self) -> io::Result<Vec<Id>> {
196 if let Some(mock) =
197 self.with_mocks(|data| data.0.supplementary_groups.clone())
198 {
199 return Ok(mock);
200 }
201
202 getgroups_inner(RealLibc)
203 }
204}