#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub enum UserAndGroupChoice
{
FromUserNameInEtcPasswd(UserName),
FromUserNameInEtcPasswdAndGroupNameInEtcGroup(UserName, GroupName),
FromUserIdentifierInEtcPasswd(UserIdentifier),
FromUserIdentifierAndGroupIdentifier(UserIdentifier, GroupIdentifier),
FromCurrentReal,
FromCurrentEffective,
FromCurrentSavedSet,
}
impl UserAndGroupChoice
{
#[inline(always)]
pub fn to_user_and_group_identifiers(&self, etc_path: &EtcPath) -> Result<(UserIdentifier, GroupIdentifier), UserAndGroupChoiceError>
{
use self::UserAndGroupChoice::*;
match self
{
&FromUserNameInEtcPasswd(ref user_name) => Self::etc_passwd_record_for_user_name(etc_path, user_name),
&FromUserNameInEtcPasswdAndGroupNameInEtcGroup(ref user_name, ref group_name) =>
{
let user_identifier = Self::etc_passwd_record_for_user_name(etc_path, user_name)?.0;
let group_identifier = Self::etc_group_identifier_for_group_name(etc_path, group_name)?;
Ok((user_identifier, group_identifier))
}
&FromUserIdentifierInEtcPasswd(user_identifier) =>
{
Self::etc_passwd_record_for_user_identifier::<(UserIdentifier, GroupIdentifier), _>(etc_path, user_identifier, |etc_passwd_record| Ok((etc_passwd_record.user_identifier, etc_passwd_record.group_identifier)))
}
&FromUserIdentifierAndGroupIdentifier(user_identifier, group_identifier) => Ok((user_identifier, group_identifier)),
&FromCurrentReal => Ok((UserIdentifier::current_real(), GroupIdentifier::current_real())),
&FromCurrentEffective => Ok((UserIdentifier::current_effective(), GroupIdentifier::current_effective())),
&FromCurrentSavedSet => Ok((UserIdentifier::current_effective(), GroupIdentifier::current_effective())),
}
}
#[inline(always)]
pub(crate) fn etc_passwd_record_for_user_identifier<A, F: FnOnce(EtcPasswdRecord) -> Result<A, UserAndGroupChoiceError>>(etc_path: &EtcPath, user_identifier: UserIdentifier, etc_passwd_record_user: F) -> Result<A, UserAndGroupChoiceError>
{
let etc_passwd = EtcPasswd::open(etc_path)?;
let etc_passwd_record = Self::try_find_etc_passwd(etc_passwd.iter(), |etc_passwd_record| etc_passwd_record.user_identifier == user_identifier)?.ok_or(UserAndGroupChoiceError::UserIdentifierNotPresentInEtcPasswd)?;
etc_passwd_record_user(etc_passwd_record)
}
#[inline(always)]
pub(crate) fn etc_group_record_for_group_identifier<A, F: FnOnce(EtcGroupRecord) -> Result<A, UserAndGroupChoiceError>>(etc_path: &EtcPath, group_identifier: GroupIdentifier, etc_group_record_user: F) -> Result<A, UserAndGroupChoiceError>
{
let etc_group = EtcGroup::open(etc_path)?;
let etc_group_record = Self::try_find_etc_group(etc_group.iter(), |etc_group_record| etc_group_record.group_identifier == group_identifier)?.ok_or(UserAndGroupChoiceError::GroupIdentifierNotPresentInEtcGroup)?;
etc_group_record_user(etc_group_record)
}
#[inline(always)]
fn etc_passwd_record_for_user_name(etc_path: &EtcPath, user_name: &UserName) -> Result<(UserIdentifier, GroupIdentifier), UserAndGroupChoiceError>
{
let etc_passwd = EtcPasswd::open(etc_path)?;
let etc_passwd_record = Self::try_find_etc_passwd(etc_passwd.iter(), |etc_passwd_record| etc_passwd_record.has_user_name(user_name))?.ok_or(UserAndGroupChoiceError::UserNameNotPresentInEtcPasswd)?;
Ok((etc_passwd_record.user_identifier, etc_passwd_record.group_identifier))
}
#[inline(always)]
fn etc_group_identifier_for_group_name(etc_path: &EtcPath, group_name: &GroupName) -> Result<GroupIdentifier, UserAndGroupChoiceError>
{
let etc_group = EtcGroup::open(etc_path)?;
match Self::try_find_etc_group(etc_group.iter(), |etc_group_record| etc_group_record.has_group_name(group_name))?
{
None => Err(UserAndGroupChoiceError::GroupNameNotPresentInEtcGroup),
Some(etc_group_record) => Ok(etc_group_record.group_identifier),
}
}
#[inline(always)]
fn try_find_etc_passwd<'a>(iterator: EtcPasswdIterator<'a>, predicate: impl FnOnce(&EtcPasswdRecord<'a>) -> bool + Copy) -> Result<Option<EtcPasswdRecord<'a>>, EtcPasswdParseError>
{
for etc_passwd_record in iterator
{
let etc_passwd_record = etc_passwd_record?;
if predicate(&etc_passwd_record)
{
return Ok(Some(etc_passwd_record))
}
}
Ok(None)
}
#[inline(always)]
fn try_find_etc_group<'a>(iterator: EtcGroupIterator<'a>, predicate: impl FnOnce(&EtcGroupRecord<'a>) -> bool + Copy) -> Result<Option<EtcGroupRecord<'a>>, EtcGroupParseError>
{
for etc_group_record in iterator
{
let etc_group_record = etc_group_record?;
if predicate(&etc_group_record)
{
return Ok(Some(etc_group_record))
}
}
Ok(None)
}
}