3535#[ cfg( any( target_os = "freebsd" , target_vendor = "apple" ) ) ]
3636use libc:: time_t;
3737use libc:: { c_char, c_int, gid_t, uid_t} ;
38- use libc:: { getgrgid, getgrnam, getgroups } ;
38+ use libc:: { getgrgid, getgrnam} ;
3939use libc:: { getpwnam, getpwuid, group, passwd} ;
4040
4141use std:: ffi:: { CStr , CString } ;
@@ -57,42 +57,6 @@ unsafe extern "C" {
5757 ) -> c_int ;
5858}
5959
60- /// From: `<https://man7.org/linux/man-pages/man2/getgroups.2.html>`
61- /// > getgroups( ) returns the supplementary group IDs of the calling
62- /// > process in list.
63- /// > If size is zero, list is not modified, but the total number of
64- /// > supplementary group IDs for the process is returned. This allows
65- /// > the caller to determine the size of a dynamically allocated list
66- /// > to be used in a further call to getgroups().
67- pub fn get_groups ( ) -> IOResult < Vec < gid_t > > {
68- let mut groups = Vec :: new ( ) ;
69- loop {
70- let ngroups = match unsafe { getgroups ( 0 , ptr:: null_mut ( ) ) } {
71- -1 => return Err ( IOError :: last_os_error ( ) ) ,
72- // Not just optimization; 0 would mess up the next call
73- 0 => return Ok ( Vec :: new ( ) ) ,
74- n => n,
75- } ;
76-
77- // This is a small buffer, so we can afford to zero-initialize it and
78- // use safe Vec operations
79- groups. resize ( ngroups. try_into ( ) . unwrap ( ) , 0 ) ;
80- let res = unsafe { getgroups ( ngroups, groups. as_mut_ptr ( ) ) } ;
81- if res == -1 {
82- let err = IOError :: last_os_error ( ) ;
83- if err. raw_os_error ( ) == Some ( libc:: EINVAL ) {
84- // Number of groups has increased, retry
85- } else {
86- return Err ( err) ;
87- }
88- } else {
89- // Number of groups may have decreased
90- groups. truncate ( res. try_into ( ) . unwrap ( ) ) ;
91- return Ok ( groups) ;
92- }
93- }
94- }
95-
9660/// The list of group IDs returned from GNU's `groups` and GNU's `id --groups`
9761 /// starts with the effective group ID ( egid) .
9862/// This is a wrapper for `get_groups()` to mimic this behavior.
@@ -116,8 +80,9 @@ pub fn get_groups() -> IOResult<Vec<gid_t>> {
11680/// > history of a process and its parents could affect the details of
11781/// > the result.)
11882#[ cfg( all( unix, not( target_os = "redox" ) , feature = "process" ) ) ]
119- pub fn get_groups_gnu ( arg_id : Option < u32 > ) -> IOResult < Vec < gid_t > > {
120- let groups = get_groups ( ) ?;
83+ pub fn get_groups_gnu ( arg_id : Option < u32 > ) -> IOResult < Vec < rustix:: process:: RawGid > > {
84+ let groups = rustix:: process:: getgroups ( )
85+ . map ( |g| g. into_iter ( ) . map ( rustix:: fs:: Gid :: as_raw) . collect ( ) ) ?;
12186 let egid = arg_id. unwrap_or_else ( crate :: features:: process:: getegid) ;
12287 Ok ( sort_groups ( groups, egid) )
12388}
@@ -383,7 +348,11 @@ mod test {
383348
384349 #[ test]
385350 fn test_entries_get_groups_gnu ( ) {
386- if let Ok ( mut groups) = get_groups ( ) {
351+ if let Ok ( mut groups) = rustix:: process:: getgroups ( ) . map ( |g| {
352+ g. into_iter ( )
353+ . map ( rustix:: fs:: Gid :: as_raw)
354+ . collect :: < Vec < _ > > ( )
355+ } ) {
387356 if let Some ( last) = groups. pop ( ) {
388357 groups. insert ( 0 , last) ;
389358 assert_eq ! ( get_groups_gnu( Some ( last) ) . unwrap( ) , groups) ;
0 commit comments