#![cfg(unix)]
#![cfg_attr(
all(test, feature = "test-with-lmock"),
feature(allocator_api, vec_into_raw_parts)
)]
#![doc=include_str!("../README.md")]
use std::cmp;
use std::convert::{TryFrom, TryInto};
use std::ffi::{CStr, CString};
use std::fmt::Debug;
use std::io;
use std::io::ErrorKind::{InvalidData, InvalidInput, Other, OutOfMemory};
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::ptr::NonNull;
use libc::{c_char, c_int, c_long, size_t};
use libc::{gid_t, uid_t};
use derive_deftly::{define_derive_deftly, derive_deftly_adhoc, Deftly};
use paste::paste;
use thiserror::Error;
#[macro_use]
mod conditional;
#[macro_use]
pub mod mock;
#[macro_use]
mod convert;
#[macro_use]
mod generic;
#[macro_use]
mod unsafe_;
#[macro_use]
mod lmockable;
#[cfg(test)]
#[macro_use]
mod test;
pub mod error;
mod private;
use convert::*;
use error::*;
use lmockable::*;
use private::*;
use unsafe_::*;
pub use generic::*;
type RawSafe = Box<[u8]>;
type Id = libc::uid_t;
macro_rules! common_docs { {} => { r"
Strings are represented as `S`, usually `String`.
This struct is non-exhaustive:
future versions of `pwd-grp` may add fields.
(For technical reasons this is done with a hidden field
called `__non_exhaustive`.
If you use this to bypass the restriction,
future minor updates to this crate may break your code.)
" } }
#[doc = common_docs!()]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Deftly)]
#[derive_deftly(TryConvertFrom, FromLibc, Lookup, Blank)]
#[cfg_attr(all(test, feature = "test-with-lmock"), derive_deftly(MockToLibc))]
#[deftly(abbrev = "pw")]
pub struct Passwd<S = String> {
pub name: S,
pub passwd: S,
pub uid: Id,
pub gid: Id,
pub gecos: S,
pub dir: S,
pub shell: S,
#[doc(hidden)]
#[deftly(dummy)]
#[cfg_attr(feature = "serde", serde(skip))]
pub __non_exhaustive: NonExhaustive,
}
#[doc = common_docs!()]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Deftly)]
#[derive_deftly(TryConvertFrom, FromLibc, Lookup, Blank)]
#[cfg_attr(all(test, feature = "test-with-lmock"), derive_deftly(MockToLibc))]
#[deftly(abbrev = "gr")]
pub struct Group<S = String> {
pub name: S,
pub passwd: S,
pub gid: Id,
pub mem: Box<[S]>,
#[doc(hidden)]
#[deftly(dummy)]
#[cfg_attr(feature = "serde", serde(skip))]
pub __non_exhaustive: NonExhaustive,
}
macro_rules! simple {
{
fn $getfoobar:ident($key:ident: $keytype:ty) -> $out:ty;
$example_key:expr, $example_field:ident
} => { paste!{
#[doc = stringify!([< $out:lower >])]
#[doc = concat!(stringify!([< $key >]))]
#[cfg_attr(target_os = "linux", doc = "```")]
#[cfg_attr(not(target_os = "linux"), doc = "```no_run")]
#[doc = concat!(
"let entry = ",
"pwd_grp::", stringify!($getfoobar),
"(", stringify!($example_key), ")",
".unwrap().unwrap();"
)]
#[doc = concat!(
"assert_eq!(entry.", stringify!($example_field),", 0);"
)]
pub fn $getfoobar(
$key: $keytype,
) -> io::Result<Option<$out<String>>> {
generic::PwdGrp.$getfoobar($key)
}
} };
}
simple! { fn getpwnam(name: impl AsRef<str>) -> Passwd; "root", uid }
simple! { fn getpwuid(uid: Id) -> Passwd; 0, uid }
simple! { fn getgrnam(name: impl AsRef<str>) -> Group; "root", gid }
simple! { fn getgrgid(gid: Id) -> Group; 0, gid }
macro_rules! define_getid_simple { {
$fn:ident: $id:ident. $field:ident, $doc:literal $( $real:literal )?
} => {
define_getid_simple! { @ $fn: $id. Id, $doc }
}; {
$fn:ident: $id:ident. ($( $f:ident )*), $doc:literal $( $real:literal )?
} => {
define_getid_simple! { @ $fn: $id. (Id, Id, Id), $doc }
}; {
@ $fn:ident: $id:ident. $ret:ty, $doc:literal
} => { paste!{
#[doc = $doc]
pub fn $fn() -> $ret {
generic::PwdGrp.$fn()
}
} } }
for_getid_wrappers! { define_getid_simple }
pub fn getgroups() -> io::Result<Vec<Id>> {
PwdGrp.getgroups()
}
#[cfg(not(feature = "minimal-1"))]
compile_error! { "You must enable at least one pwd-grp crate feature!" }