1/* 2 * Utility routines. 3 * 4 * Copyright (C) 2017 Denys Vlasenko 5 * 6 * Licensed under GPLv2, see file LICENSE in this source tree. 7 */ 8 9//kbuild:lib-y += bb_getgroups.o 10 11#include "libbb.h" 12 13gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) 14{ 15 int n = ngroups ? *ngroups : 0; 16 17 /* getgroups may be a bit expensive, try to use it only once */ 18 if (n < 32) 19 n = 32; 20 21 for (;;) { 22// FIXME: ash tries so hard to not die on OOM (when we are called from test), 23// and we spoil it with just one xrealloc here 24 group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0])); 25 n = getgroups(n, group_array); 26 /* 27 * If buffer is too small, kernel does not return new_n > n. 28 * It returns -1 and EINVAL: 29 */ 30 if (n >= 0) { 31 /* Terminator for bb_getgroups(NULL, NULL) usage */ 32 group_array[n] = (gid_t) -1; 33 break; 34 } 35 if (errno == EINVAL) { /* too small? */ 36 /* This is the way to ask kernel how big the array is */ 37 n = getgroups(0, group_array); 38 continue; 39 } 40 /* Some other error (should never happen on Linux) */ 41 bb_perror_msg_and_die("getgroups"); 42 } 43 44 if (ngroups) 45 *ngroups = n; 46 return group_array; 47} 48