@@ -943,26 +943,37 @@ pub fn setgid(gid: Gid) -> Result<()> {
943
943
944
944
/// Get the list of supplementary group IDs of the calling process.
945
945
///
946
- /// Note that if the user is added to more group(s) while this call is in
947
- /// progress then an error (EINVAL) will be returned.
948
- ///
949
946
/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
950
947
pub fn getgroups ( ) -> Result < Vec < Gid > > {
951
948
// First get the number of groups so we can size our Vec
952
949
use std:: ptr;
953
950
let ret = unsafe { libc:: getgroups ( 0 , ptr:: null_mut ( ) ) } ;
954
- let size = try!( Errno :: result ( ret) ) ;
951
+ let mut size = try!( Errno :: result ( ret) ) ;
955
952
956
953
// Now actually get the groups
957
954
let mut groups = Vec :: < Gid > :: with_capacity ( size as usize ) ;
958
- // We can coerce a pointer to some `Gid`s as a pointer to some `gid_t`s as
959
- // they have the same representation in memory.
960
- let ret = unsafe { libc:: getgroups ( size, groups. as_mut_ptr ( ) as * mut gid_t ) } ;
961
-
962
- Errno :: result ( ret) . map ( |s| {
963
- unsafe { groups. set_len ( s as usize ) } ;
964
- groups
965
- } )
955
+ loop {
956
+ // We can coerce a pointer to some `Gid`s as a pointer to some `gid_t`s
957
+ // as they have the same representation in memory.
958
+ let ret = unsafe { libc:: getgroups ( size, groups. as_mut_ptr ( ) as * mut gid_t ) } ;
959
+
960
+ match Errno :: result ( ret) {
961
+ Ok ( s) => {
962
+ unsafe { groups. set_len ( s as usize ) } ;
963
+ break
964
+ } ,
965
+ Err ( Error :: Sys ( Errno :: EINVAL ) ) => {
966
+ // EINVAL indicates that size was too small, so trigger a
967
+ // resize of the groups Vec and try again...
968
+ let cap = groups. capacity ( ) ;
969
+ unsafe { groups. set_len ( cap) } ;
970
+ groups. reserve ( 1 ) ;
971
+ size = groups. capacity ( ) as c_int ;
972
+ } ,
973
+ Err ( e) => return Err ( e)
974
+ }
975
+ }
976
+ Ok ( groups)
966
977
}
967
978
968
979
/// Set the list of supplementary group IDs for the calling process.
0 commit comments