@@ -982,6 +982,49 @@ pub fn setgid(gid: Gid) -> Result<()> {
982982 Errno :: result ( res) . map ( drop)
983983}
984984
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+
9851028/// Set the list of supplementary group IDs for the calling process.
9861029///
9871030/// *Note:* On macOS, `getgroups()` may not return the same group list set by
0 commit comments