@@ -982,6 +982,49 @@ pub fn setgid(gid: Gid) -> Result<()> {
982
982
Errno :: result ( res) . map ( drop)
983
983
}
984
984
985
+ /// Get the list of supplementary group IDs of the calling process.
986
+ ///
987
+ /// *Note:* On macOS, `getgroups()` behavior differs somewhat from other Unix
988
+ /// platforms. It returns the current group access list for the user associated
989
+ /// with the effective user id of the process; the group access list may change
990
+ /// over the lifetime of the process, and it is not affected by calls to
991
+ /// `setgroups()`.
992
+ ///
993
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
994
+ pub fn getgroups ( ) -> Result < Vec < Gid > > {
995
+ // First get the number of groups so we can size our Vec
996
+ use std:: ptr;
997
+ let ret = unsafe { libc:: getgroups ( 0 , ptr:: null_mut ( ) ) } ;
998
+ let mut size = Errno :: result ( ret) ?;
999
+
1000
+ // Now actually get the groups. We try multiple times in case the number of
1001
+ // groups has changed since the first call to getgroups() and the buffer is
1002
+ // now too small
1003
+ let mut groups = Vec :: < Gid > :: with_capacity ( size as usize ) ;
1004
+ loop {
1005
+ // FIXME: On the platforms we currently support, the `Gid` struct has
1006
+ // the same representation in memory as a bare `gid_t`. This is not
1007
+ // necessarily the case on all Rust platforms, though. See RFC 1785.
1008
+ let ret = unsafe { libc:: getgroups ( size, groups. as_mut_ptr ( ) as * mut gid_t ) } ;
1009
+
1010
+ match Errno :: result ( ret) {
1011
+ Ok ( s) => {
1012
+ unsafe { groups. set_len ( s as usize ) } ;
1013
+ return Ok ( groups) ;
1014
+ } ,
1015
+ Err ( Error :: Sys ( Errno :: EINVAL ) ) => {
1016
+ // EINVAL indicates that size was too small, so trigger a
1017
+ // resize of the groups Vec and try again...
1018
+ let cap = groups. capacity ( ) ;
1019
+ unsafe { groups. set_len ( cap) } ;
1020
+ groups. reserve ( 1 ) ;
1021
+ size = groups. capacity ( ) as c_int ;
1022
+ } ,
1023
+ Err ( e) => return Err ( e)
1024
+ }
1025
+ }
1026
+ }
1027
+
985
1028
/// Set the list of supplementary group IDs for the calling process.
986
1029
///
987
1030
/// *Note:* On macOS, `getgroups()` may not return the same group list set by
0 commit comments