@@ -1047,6 +1047,49 @@ pub fn setgid(gid: Gid) -> Result<()> {
1047
1047
Errno :: result ( res) . map ( drop)
1048
1048
}
1049
1049
1050
+ /// Get the list of supplementary group IDs of the calling process.
1051
+ ///
1052
+ /// *Note:* On macOS, `getgroups()` behavior differs somewhat from other Unix
1053
+ /// platforms. It returns the current group access list for the user associated
1054
+ /// with the effective user id of the process; the group access list may change
1055
+ /// over the lifetime of the process, and it is not affected by calls to
1056
+ /// `setgroups()`.
1057
+ ///
1058
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
1059
+ pub fn getgroups ( ) -> Result < Vec < Gid > > {
1060
+ // First get the number of groups so we can size our Vec
1061
+ use std:: ptr;
1062
+ let ret = unsafe { libc:: getgroups ( 0 , ptr:: null_mut ( ) ) } ;
1063
+ let mut size = Errno :: result ( ret) ?;
1064
+
1065
+ // Now actually get the groups. We try multiple times in case the number of
1066
+ // groups has changed since the first call to getgroups() and the buffer is
1067
+ // now too small
1068
+ let mut groups = Vec :: < Gid > :: with_capacity ( size as usize ) ;
1069
+ loop {
1070
+ // FIXME: On the platforms we currently support, the `Gid` struct has
1071
+ // the same representation in memory as a bare `gid_t`. This is not
1072
+ // necessarily the case on all Rust platforms, though. See RFC 1785.
1073
+ let ret = unsafe { libc:: getgroups ( size, groups. as_mut_ptr ( ) as * mut gid_t ) } ;
1074
+
1075
+ match Errno :: result ( ret) {
1076
+ Ok ( s) => {
1077
+ unsafe { groups. set_len ( s as usize ) } ;
1078
+ return Ok ( groups) ;
1079
+ } ,
1080
+ Err ( Error :: Sys ( Errno :: EINVAL ) ) => {
1081
+ // EINVAL indicates that size was too small, so trigger a
1082
+ // resize of the groups Vec and try again...
1083
+ let cap = groups. capacity ( ) ;
1084
+ unsafe { groups. set_len ( cap) } ;
1085
+ groups. reserve ( 1 ) ;
1086
+ size = groups. capacity ( ) as c_int ;
1087
+ } ,
1088
+ Err ( e) => return Err ( e)
1089
+ }
1090
+ }
1091
+ }
1092
+
1050
1093
/// Set the list of supplementary group IDs for the calling process.
1051
1094
///
1052
1095
/// *Note:* On macOS, `getgroups()` may not return the same group list set by
0 commit comments