use std::fs::File;
use std::io::{BufRead, BufReader};
use std::str::FromStr;
use crate::error::{Error, ErrorKind};
#[derive(Debug, Default, Clone)]
pub struct Group {
pub name: String,
pub passwd: String,
pub gid: nc::gid_t,
pub mem: Vec<String>,
}
impl FromStr for Group {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 4 {
return Err(Error::from_string(
ErrorKind::PwdGroupError,
format!("Invalid group entry: {}", s),
));
}
let gid = parts[2].parse()?;
let mem = parts[3]
.split(",")
.map(|name| name.trim().to_string())
.collect();
Ok(Self {
name: parts[0].to_string(),
passwd: parts[1].to_string(),
gid,
mem,
})
}
}
#[derive(Debug)]
pub struct GroupIter {
reader: BufReader<File>,
}
pub fn getgrent() -> Result<GroupIter, Error> {
let fd = File::open("/etc/group")?;
let reader = BufReader::new(fd);
Ok(GroupIter { reader })
}
impl Iterator for GroupIter {
type Item = Group;
fn next(&mut self) -> Option<Self::Item> {
let mut line = String::new();
let len = self.reader.read_line(&mut line);
if len.is_err() {
return None;
}
match Group::from_str(&line.trim()) {
Ok(p) => Some(p),
Err(err) => {
log::error!("{:?}", err);
None
}
}
}
}
pub fn getgrgid(gid: nc::gid_t) -> Result<Option<Group>, Error> {
let iter = getgrent()?;
for g in iter {
if g.gid == gid {
return Ok(Some(g));
}
}
Ok(None)
}
pub fn getgrname(name: &str) -> Result<Option<Group>, Error> {
let iter = getgrent()?;
for g in iter {
if g.name == name {
return Ok(Some(g));
}
}
Ok(None)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_group_iter() {
let iter = getgrent();
assert!(iter.is_ok());
let mut iter = iter.unwrap();
let g0 = iter.next();
println!("g0: {:#?}", g0);
assert!(g0.is_some());
}
#[test]
fn test_getgrgid() {
let mail_gid = 8;
let g = getgrgid(mail_gid);
assert!(g.is_ok());
let g = g.unwrap();
assert!(g.is_some());
let g = g.unwrap();
assert_eq!(g.gid, mail_gid);
}
#[test]
fn test_getgrname() {
let mail_name = "mail";
let g = getgrname(mail_name);
assert!(g.is_ok());
let g = g.unwrap();
assert!(g.is_some());
let g = g.unwrap();
assert_eq!(g.name, mail_name);
}
}