1use std::fs;
8use std::io::{BufReader,BufRead};
9
10#[derive(Debug,PartialEq,Clone)]
12pub struct Group {
13 pub name: String,
15 pub gid: u32,
17 pub user_list: Option<Vec<String>>,
19}
20
21
22fn parse_line(line: String) -> Option<Group> {
25 let mut split: Vec<&str> = line.split(':').collect();
26 if split.is_empty() { return None; };
27 split.remove(1);
29 let mut users = Vec::new();
30 if !split[2].is_empty() {
31 let owned_users: Vec<&str> = split[2].split(',').collect();
32 for user in owned_users {
33 users.push(user.to_string());
34 }
35 }
36 let group = Group {
37 name: String::from(split[0]),
38 gid: split[1].parse::<u32>().unwrap(),
39 user_list:
40 if !users.is_empty() { Some(users) }
41 else { None }
42 };
43 return Some(group);
44}
45
46fn read_group() -> Vec<Group> {
48 let mut groups = Vec::new();
49 let file = match fs::File::open("/etc/group") {
50 Ok(s) => { s },
51 Err(e) => { panic!(e.to_string()) }
52 };
53 let file_buffer = BufReader::new(&file);
54 for line in file_buffer.lines() {
55 match line {
56 Ok(l) => {
57 groups.push(parse_line(l).unwrap());
58 },
59 Err(e) => { panic!(e.to_string()) }
60 }
61
62 }
63 return groups;
64}
65
66pub fn get_group_by_gid(gid: u32) -> Option<Group> {
76 for group in read_group() {
77 if group.gid == gid {
78 return Some(group);
79 }
80 }
81 return None;
82}
83
84pub fn get_group_by_name(name: &str) -> Option<Group> {
94 for group in read_group() {
95 if group.name == name {
96 return Some(group);
97 }
98 }
99 return None;
100}
101
102pub fn get_groups() -> Vec<Group> {
104 return read_group();
105}
106
107pub fn get_group_list(user_name: &str, gid: Option<u32>) -> Option<Vec<Group>> {
120 let mut list = Vec::new();
121 for group in read_group().iter() {
122 if gid.is_some() {
123 if group.gid == gid.unwrap() && group.name != user_name {
124 list.push(group.clone());
125 }
126 }
127 if group.user_list.is_some() {
128 let users = group.user_list.clone().unwrap();
129 for user in users {
130 if user == user_name { list.push(group.clone()) }
131 }
132 }
133 }
134 if list.is_empty() { return None; }
135 else { return Some(list); }
136}
137
138#[test]
139fn test_parse_line() {
140 let group = parse_line("hell:x:666:trump".to_string()).unwrap();
141
142 assert_eq!(group.name, "hell".to_string());
143 assert_eq!(group.gid, 666);
144 assert_eq!(group.user_list, Some(vec!["trump".to_string()]));
145}
146
147#[test]
148fn test_read_group() {
149 let groups = read_group();
150 for group in groups {
151 println!("{:?}", group);
152 }
153}
154
155#[test]
156fn test_get_group_by_name() {
157 match get_group_by_name("bin") {
158 Some(group) => {
159 assert_eq!(group.name, "bin".to_string());
160 },
161 None => { }
162 };
163}
164
165#[test]
166fn test_get_group_by_gid() {
167 match get_group_by_gid(1) {
168 Some(group) => {
169 assert_eq!(group.gid, 1);
170 },
171 None => { }
172 };
173}
174
175#[test]
176fn test_get_group_list() {
177 let mut user = String::new();
178 for (key, value) in std::env::vars() {
179 if key == "USER" { user = value }
180 }
181 match get_group_list(&user, None) {
182 Some(list) => {
183 for item in list { println!("{:?}", item); }
184 },
185 None => { }
186 };
187}