safe_libc/posix/
grp.rs

1//
2// Created:  Thu 16 Apr 2020 01:57:09 PM PDT
3// Modified: Mon 22 Dec 2025 05:36:58 PM PST
4//
5// Copyright (C) 2020 Robert Gill <rtgill82@gmail.com>
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to
9// deal in the Software without restriction, including without limitation the
10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11// sell copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies of the Software, its documentation and marketing & publicity
16// materials, and acknowledgment shall be given in the documentation, materials
17// and software packages that this Software was used.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25//
26
27use 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}