use std::fs;
use std::io::{BufReader,BufRead};
#[derive(Debug,PartialEq,Clone)]
pub struct Group {
pub name: String,
pub gid: u32,
pub user_list: Option<Vec<String>>,
}
fn parse_line(line: String) -> Option<Group> {
let mut split: Vec<&str> = line.split(':').collect();
if split.is_empty() { return None; };
split.remove(1);
let mut users = Vec::new();
if !split[2].is_empty() {
let owned_users: Vec<&str> = split[2].split(',').collect();
for user in owned_users {
users.push(user.to_string());
}
}
let group = Group {
name: String::from(split[0]),
gid: split[1].parse::<u32>().unwrap(),
user_list:
if !users.is_empty() { Some(users) }
else { None }
};
return Some(group);
}
fn read_group() -> Vec<Group> {
let mut groups = Vec::new();
let file = match fs::File::open("/etc/group") {
Ok(s) => { s },
Err(e) => { panic!(e.to_string()) }
};
let file_buffer = BufReader::new(&file);
for line in file_buffer.lines() {
match line {
Ok(l) => {
groups.push(parse_line(l).unwrap());
},
Err(e) => { panic!(e.to_string()) }
}
}
return groups;
}
pub fn get_group_by_gid(gid: u32) -> Option<Group> {
for group in read_group() {
if group.gid == gid {
return Some(group);
}
}
return None;
}
pub fn get_group_by_name(name: &str) -> Option<Group> {
for group in read_group() {
if group.name == name {
return Some(group);
}
}
return None;
}
pub fn get_groups() -> Vec<Group> {
return read_group();
}
pub fn get_group_list(user_name: &str, gid: Option<u32>) -> Option<Vec<Group>> {
let mut list = Vec::new();
for group in read_group().iter() {
if gid.is_some() {
if group.gid == gid.unwrap() && group.name != user_name {
list.push(group.clone());
}
}
if group.user_list.is_some() {
let users = group.user_list.clone().unwrap();
for user in users {
if user == user_name { list.push(group.clone()) }
}
}
}
if list.is_empty() { return None; }
else { return Some(list); }
}
#[test]
fn test_parse_line() {
let group = parse_line("hell:x:666:trump".to_string()).unwrap();
assert_eq!(group.name, "hell".to_string());
assert_eq!(group.gid, 666);
assert_eq!(group.user_list, Some(vec!["trump".to_string()]));
}
#[test]
fn test_read_group() {
let groups = read_group();
for group in groups {
println!("{:?}", group);
}
}
#[test]
fn test_get_group_by_name() {
match get_group_by_name("bin") {
Some(group) => {
assert_eq!(group.name, "bin".to_string());
},
None => { }
};
}
#[test]
fn test_get_group_by_gid() {
match get_group_by_gid(1) {
Some(group) => {
assert_eq!(group.gid, 1);
},
None => { }
};
}
#[test]
fn test_get_group_list() {
let mut user = String::new();
for (key, value) in std::env::vars() {
if key == "USER" { user = value }
}
match get_group_list(&user, None) {
Some(list) => {
for item in list { println!("{:?}", item); }
},
None => { }
};
}