1#![cfg(unix)]
2#![cfg_attr(
3 all(test, feature = "test-with-lmock"),
4 feature(allocator_api, vec_into_raw_parts)
5)]
6#![doc=include_str!("../README.md")]
7
8use std::cmp;
47use std::convert::{TryFrom, TryInto};
48use std::ffi::{CStr, CString};
49use std::fmt::Debug;
50use std::io;
51use std::io::ErrorKind::{InvalidData, InvalidInput, Other, OutOfMemory};
52use std::mem::MaybeUninit;
53use std::ops::Deref;
54use std::ptr::NonNull;
55
56use libc::{c_char, c_int, c_long, size_t};
57use libc::{gid_t, uid_t};
58
59use derive_deftly::{define_derive_deftly, derive_deftly_adhoc, Deftly};
60use paste::paste;
61use thiserror::Error;
62
63#[macro_use]
64mod conditional;
65#[macro_use]
66pub mod mock;
67#[macro_use]
68mod convert;
69#[macro_use]
70mod generic;
71#[macro_use]
72mod unsafe_;
73#[macro_use]
74mod lmockable;
75
76#[cfg(test)]
77#[macro_use]
78mod test;
79
80pub mod error;
81
82mod private;
83
84use convert::*;
85use error::*;
86use lmockable::*;
87use private::*;
88use unsafe_::*;
89
90pub use generic::*;
91
92type RawSafe = Box<[u8]>;
93
94type Id = libc::uid_t;
102
103macro_rules! common_docs { {} => { r"
111
112Strings are represented as `S`, usually `String`.
113
114
115This struct is non-exhaustive:
116future versions of `pwd-grp` may add fields.
117(For technical reasons this is done with a hidden field
118called `__non_exhaustive`.
119If you use this to bypass the restriction,
120future minor updates to this crate may break your code.)
121
122" } }
123
124#[doc = common_docs!()]
133#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135#[derive(Deftly)]
136#[derive_deftly(TryConvertFrom, FromLibc, Lookup, Blank)]
137#[cfg_attr(all(test, feature = "test-with-lmock"), derive_deftly(MockToLibc))]
138#[deftly(abbrev = "pw")]
139pub struct Passwd<S = String> {
140 pub name: S,
141 pub passwd: S,
142 pub uid: Id,
143 pub gid: Id,
144 pub gecos: S,
145 pub dir: S,
146 pub shell: S,
147 #[doc(hidden)]
148 #[deftly(dummy)]
149 #[cfg_attr(feature = "serde", serde(skip))]
150 pub __non_exhaustive: NonExhaustive,
152}
153
154#[doc = common_docs!()]
163#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
164#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
165#[derive(Deftly)]
166#[derive_deftly(TryConvertFrom, FromLibc, Lookup, Blank)]
167#[cfg_attr(all(test, feature = "test-with-lmock"), derive_deftly(MockToLibc))]
168#[deftly(abbrev = "gr")]
169pub struct Group<S = String> {
170 pub name: S,
171 pub passwd: S,
172 pub gid: Id,
173 pub mem: Box<[S]>,
174 #[doc(hidden)]
175 #[deftly(dummy)]
176 #[cfg_attr(feature = "serde", serde(skip))]
177 pub __non_exhaustive: NonExhaustive,
179}
180
181macro_rules! simple {
182 {
183 fn $getfoobar:ident($key:ident: $keytype:ty) -> $out:ty;
184 $example_key:expr, $example_field:ident
185 } => { paste!{
186 #[doc = stringify!([< $out:lower >])]
188 #[doc = concat!(stringify!([< $key >]))]
190 #[cfg_attr(target_os = "linux", doc = "```")]
202 #[cfg_attr(not(target_os = "linux"), doc = "```no_run")]
203 #[doc = concat!(
204 "let entry = ",
205 "pwd_grp::", stringify!($getfoobar),
206 "(", stringify!($example_key), ")",
207 ".unwrap().unwrap();"
208 )]
209 #[doc = concat!(
210 "assert_eq!(entry.", stringify!($example_field),", 0);"
211 )]
212 pub fn $getfoobar(
214 $key: $keytype,
215 ) -> io::Result<Option<$out<String>>> {
216 generic::PwdGrp.$getfoobar($key)
217 }
218 } };
219}
220
221simple! { fn getpwnam(name: impl AsRef<str>) -> Passwd; "root", uid }
222simple! { fn getpwuid(uid: Id) -> Passwd; 0, uid }
223simple! { fn getgrnam(name: impl AsRef<str>) -> Group; "root", gid }
224simple! { fn getgrgid(gid: Id) -> Group; 0, gid }
225
226macro_rules! define_getid_simple { {
227 $fn:ident: $id:ident. $field:ident, $doc:literal $( $real:literal )?
228} => {
229 define_getid_simple! { @ $fn: $id. Id, $doc }
230}; {
231 $fn:ident: $id:ident. ($( $f:ident )*), $doc:literal $( $real:literal )?
232} => {
233 define_getid_simple! { @ $fn: $id. (Id, Id, Id), $doc }
234}; {
235 @ $fn:ident: $id:ident. $ret:ty, $doc:literal
236} => { paste!{
237 #[doc = $doc]
239
240 pub fn $fn() -> $ret {
241 generic::PwdGrp.$fn()
242 }
243} } }
244
245for_getid_wrappers! { define_getid_simple }
246
247pub fn getgroups() -> io::Result<Vec<Id>> {
262 PwdGrp.getgroups()
263}
264
265#[cfg(not(feature = "minimal-1"))]
266compile_error! { "You must enable at least one pwd-grp crate feature!" }