1use std::ffi::{CStr,CString};
28use std::ptr;
29
30use crate::errno::{Error,Result};
31use crate::stdlib::realloc;
32use crate::util::*;
33
34pub struct Group {
35 grp: libc::group,
36 buf: *mut libc::c_void
37}
38
39impl Group {
40 pub fn gr_name(&self) -> &CStr {
41 unsafe { CStr::from_ptr(self.grp.gr_name) }
42 }
43
44 pub fn gr_passwd(&self) -> &CStr {
45 unsafe { CStr::from_ptr(self.grp.gr_passwd) }
46 }
47
48 pub fn gr_gid(&self) -> libc::gid_t {
49 self.grp.gr_gid
50 }
51
52 pub fn gr_mem(&self) -> Option<Vec<&CStr>> {
53 unsafe {
54 if (*self.grp.gr_mem).is_null() {
55 return None;
56 }
57
58 let mut vec = Vec::new();
59 let mut p = self.grp.gr_mem;
60 while !(*p).is_null() {
61 vec.push(CStr::from_ptr(*p));
62 p = p.add(1);
63 }
64
65 Some(vec)
66 }
67 }
68}
69
70impl Drop for Group {
71 fn drop(&mut self) {
72 unsafe { libc::free(self.buf); }
73 }
74}
75
76pub fn getgid() -> libc::gid_t {
77 unsafe { libc::getgid() }
78}
79
80pub fn getegid() -> libc::gid_t {
81 unsafe { libc::getegid() }
82}
83
84pub fn getgrnam<T: Into<Vec<u8>>>(name: T) -> Result<Option<Group>> {
85 let cstring = CString::new(name)?;
86 let cstr = cstring.as_c_str();
87
88 unsafe {
89 let mut grp: libc::group = zeroed();
90 let mut result: *mut libc::group = ptr::null_mut();
91 let mut bufsize = get_bufsize(BufType::Group);
92 let mut buf = ptr::null_mut();
93
94 loop {
95 buf = realloc(buf, bufsize)?;
96 let buf_i8 = buf as *mut i8;
97 let rv = libc::getgrnam_r(cstr.as_ptr(), &mut grp,
98 buf_i8, bufsize, &mut result);
99 if !result.is_null() {
100 break;
101 }
102
103 match rv {
104 0 => return Ok(None),
105 _ => {
106 if rv != libc::ERANGE {
107 return Err(Error::new(rv));
108 }
109 bufsize *= 2;
110 }
111 }
112 }
113 Ok(Some(Group { grp, buf }))
114 }
115}
116
117pub fn getgrgid(gid: libc::gid_t) -> Result<Option<Group>> {
118 unsafe {
119 let mut grp: libc::group = zeroed();
120 let mut result: *mut libc::group = ptr::null_mut();
121 let mut bufsize = get_bufsize(BufType::Group);
122 let mut buf = ptr::null_mut();
123
124 loop {
125 buf = realloc(buf, bufsize)?;
126 let buf_i8 = buf as *mut i8;
127 let rv = libc::getgrgid_r(gid, &mut grp, buf_i8, bufsize, &mut result);
128 if !result.is_null() {
129 break;
130 }
131
132 match rv {
133 0 => return Ok(None),
134 _ => {
135 if rv != libc::ERANGE {
136 return Err(Error::new(rv));
137 }
138 bufsize *= 2;
139 }
140 }
141 }
142 Ok(Some(Group { grp, buf }))
143 }
144}