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