1 /*
2  * setgroups() for uClibc
3  *
4  * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
5  *
6  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
7  */
8 
9 #include <sys/syscall.h>
10 
11 #ifdef __USE_BSD
12 #include <grp.h>
13 
14 #if defined(__NR_setgroups32)
15 # undef __NR_setgroups
16 # define __NR_setgroups __NR_setgroups32
17 _syscall2(int, setgroups, size_t, size, const gid_t *, list)
18 
19 #elif __WORDSIZE == 64
20 _syscall2(int, setgroups, size_t, size, const gid_t *, list)
21 
22 #else
23 # include <errno.h>
24 # include <stdlib.h>
25 # include <unistd.h>
26 # include <sys/types.h>
27 
28 # define __NR___syscall_setgroups __NR_setgroups
29 static __always_inline _syscall2(int, __syscall_setgroups,
30 				 size_t, size, const __kernel_gid_t *, list)
31 
32 int setgroups(size_t size, const gid_t *groups)
33 {
34 	if (size > (size_t) sysconf(_SC_NGROUPS_MAX)) {
35 ret_error:
36 		__set_errno(EINVAL);
37 		return -1;
38 	} else {
39 		size_t i;
40 		__kernel_gid_t *kernel_groups = NULL;
41 
42 		if (size) {
43 			kernel_groups = (__kernel_gid_t *)malloc(sizeof(*kernel_groups) * size);
44 			if (kernel_groups == NULL)
45 				goto ret_error;
46 		}
47 
48 		for (i = 0; i < size; i++) {
49 			kernel_groups[i] = (groups)[i];
50 			if (groups[i] != (gid_t) ((__kernel_gid_t) groups[i])) {
51 				goto ret_error;
52 			}
53 		}
54 
55 		i = __syscall_setgroups(size, kernel_groups);
56 		free(kernel_groups);
57 		return i;
58 	}
59 }
60 #endif
61 
62 libc_hidden_def(setgroups)
63 #endif
64