a8cf9c5a3f
function old new delta bb_getgroups - 111 +111 nexpr 843 757 -86 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/1 up/down: 111/-86) Total: 25 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
48 lines
1.1 KiB
C
48 lines
1.1 KiB
C
/*
|
|
* Utility routines.
|
|
*
|
|
* Copyright (C) 2017 Denys Vlasenko
|
|
*
|
|
* Licensed under GPLv2, see file LICENSE in this source tree.
|
|
*/
|
|
|
|
//kbuild:lib-y += bb_getgroups.o
|
|
|
|
#include "libbb.h"
|
|
|
|
gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array)
|
|
{
|
|
int n = ngroups ? *ngroups : 0;
|
|
|
|
/* getgroups may be a bit expensive, try to use it only once */
|
|
if (n < 32)
|
|
n = 32;
|
|
|
|
for (;;) {
|
|
// FIXME: ash tries so hard to not die on OOM (when we are called from test),
|
|
// and we spoil it with just one xrealloc here
|
|
group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0]));
|
|
n = getgroups(n, group_array);
|
|
/*
|
|
* If buffer is too small, kernel does not return new_n > n.
|
|
* It returns -1 and EINVAL:
|
|
*/
|
|
if (n >= 0) {
|
|
/* Terminator for bb_getgroups(NULL, NULL) usage */
|
|
group_array[n] = (gid_t) -1;
|
|
break;
|
|
}
|
|
if (errno == EINVAL) { /* too small? */
|
|
/* This is the way to ask kernel how big the array is */
|
|
n = getgroups(0, group_array);
|
|
continue;
|
|
}
|
|
/* Some other error (should never happen on Linux) */
|
|
bb_perror_msg_and_die("getgroups");
|
|
}
|
|
|
|
if (ngroups)
|
|
*ngroups = n;
|
|
return group_array;
|
|
}
|