passwd_rs/
group.rs

1use std::ffi::{CStr, CString};
2use std::io;
3use std::os::raw::*;
4use std::ptr;
5
6/// Group struct
7pub struct Group {
8	/// Group name
9	pub name: String,
10	/// Group password
11	pub password: Option<String>,
12	/// Group ID
13	pub gid: c_uint,
14
15	/// Members of group
16	pub members: Vec<String>,
17}
18
19// Raw
20#[repr(C)]
21struct Raw {
22	gr_name: *const c_char,
23	gr_passwd: *const c_char,
24	gr_gid: c_uint,
25
26	gr_mem: *const *const c_char,
27}
28extern "C" {
29	fn getgrnam(name: *const c_char) -> *const Raw;
30	fn getgrgid(gid: c_uint) -> *const Raw;
31}
32
33impl Group {
34	unsafe fn convert(s: *const Raw) -> io::Result<Self> {
35		if s == ptr::null() {
36			return Err(io::Error::last_os_error());
37		}
38
39		let name = match CStr::from_ptr((*s).gr_name).to_str() {
40			Err(_) => return Err(io::Error::from(io::ErrorKind::InvalidData)),
41			Ok(o) => o.to_string(),
42		};
43		let passwd = match CStr::from_ptr((*s).gr_passwd).to_str() {
44			Err(_) => None,
45			Ok(o) => Some(o.to_string()),
46		};
47		let gid = (*s).gr_gid;
48
49		let mut members = Vec::new();
50		if (*s).gr_mem != ptr::null() {
51			for i in 0.. {
52				let memeber_ptr = *(*s).gr_mem.offset(i);
53				if memeber_ptr != ptr::null() {
54					match CStr::from_ptr(memeber_ptr).to_str() {
55						Ok(o) => members.push(o.to_string()),
56						Err(_) => continue,
57					}
58				} else {
59					break;
60				}
61			}
62		}
63
64		Ok(Self {
65			name,
66			password: passwd,
67			gid,
68			members,
69		})
70	}
71
72	/// Get group information by group name
73	pub fn new_from_groupname(username: &str) -> io::Result<Self> {
74		unsafe {
75			let raw = match CString::new(username) {
76				Err(_) => return Err(io::Error::from(io::ErrorKind::InvalidData)),
77				Ok(o) => o,
78			};
79
80			Self::convert(getgrnam(raw.as_ptr()))
81		}
82	}
83
84	/// Get group information by group ID
85	pub fn new_from_gid(gid: c_uint) -> io::Result<Self> {
86		unsafe { Self::convert(getgrgid(gid)) }
87	}
88
89	/// Convert members array (`Vector`) to `String`
90	pub fn display_members(&self) -> String {
91		let mut m = String::new();
92		for member in &self.members {
93			m.push_str(format!("{} ", member).as_str());
94		}
95
96		m
97	}
98}