From a8cf9c5a3ffd1601872d1ab14c5be00fde29209c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Jul 2017 18:49:24 +0200 Subject: libbb: new function bb_getgroups() - allocating wrapper around getgroups() 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 --- libbb/bb_getgroups.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 libbb/bb_getgroups.c (limited to 'libbb/bb_getgroups.c') diff --git a/libbb/bb_getgroups.c b/libbb/bb_getgroups.c new file mode 100644 index 000000000..59ae53738 --- /dev/null +++ b/libbb/bb_getgroups.c @@ -0,0 +1,47 @@ +/* + * 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; +} -- cgit v1.2.3