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
114 buf = shrink_buf(buf)?;
115 Ok(Some(Group { grp, buf }))
116 }
117}
118
119pub fn getgrgid(gid: libc::gid_t) -> Result<Option<Group>> {
120 unsafe {
121 let mut grp: libc::group = zeroed();
122 let mut result: *mut libc::group = ptr::null_mut();
123 let mut bufsize = get_bufsize(BufType::Group);
124 let mut buf = ptr::null_mut();
125
126 loop {
127 buf = realloc(buf, bufsize)?;
128 let buf_i8 = buf as *mut i8;
129 let rv = libc::getgrgid_r(gid, &mut grp, buf_i8, bufsize, &mut result);
130 if !result.is_null() {
131 break;
132 }
133
134 match rv {
135 0 => return Ok(None),
136 _ => {
137 if rv != libc::ERANGE {
138 return Err(Error::new(rv));
139 }
140 bufsize *= 2;
141 }
142 }
143 }
144
145 buf = shrink_buf(buf)?;
146 Ok(Some(Group { grp, buf }))
147 }
148}