This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Here is a patch that implements getgrouplist() from 4.4 BSD. We really need this to handle supplementary group ID's in the Hurd and implementing it outside glibc would be pretty hard. I added the prototype to <grp.h> since that is where initgroups() and setgroups() live. On *BSD all these functions live in <unistd.h>, so perhaps we should also add these prototypes there. Mark Index: ChangeLog from Mark Kettenis <kettenis@gnu.org> * grp/initgroups.c (initgroups): Factor out re-usable code into... (internal_getgrouplist): ... new function. (getgrouplist): New function. * grp/grp.h (getgrouplist): New prototype. * grp/Versions [2.2.4]: Add getgrouplist. Index: grp/initgroups.c =================================================================== RCS file: /cvs/glibc/libc/grp/initgroups.c,v retrieving revision 1.24 diff -u -p -r1.24 initgroups.c --- grp/initgroups.c 2001/04/17 03:34:06 1.24 +++ grp/initgroups.c 2001/06/07 19:42:10 @@ -136,51 +136,19 @@ compat_call (service_user *nip, const ch return NSS_STATUS_SUCCESS; } -/* Initialize the group set for the current user - by reading the group database and using all groups - of which USER is a member. Also include GROUP. */ -int -initgroups (user, group) - const char *user; - gid_t group; +static int +internal_getgrouplist (const char *user, gid_t group, long int *size, + gid_t **groupsp, long int limit) { -#if defined NGROUPS_MAX && NGROUPS_MAX == 0 - - /* No extra groups allowed. */ - return 0; - -#else - service_user *nip = NULL; initgroups_dyn_function fct; enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; /* Start is one, because we have the first group as parameter. */ long int start = 1; - long int size; - gid_t *groups; - int result; - /* We always use sysconf even if NGROUPS_MAX is defined. That way, the - limit can be raised in the kernel configuration without having to - recompile libc. */ - long int limit = __sysconf (_SC_NGROUPS_MAX); + *groupsp[0] = group; - if (limit > 0) - size = limit; - else - { - /* No fixed limit on groups. Pick a starting buffer size. */ - size = 16; - } - - groups = (gid_t *) malloc (size * sizeof (gid_t)); - if (__builtin_expect (groups == NULL, 0)) - /* No more memory. */ - return -1; - - groups[0] = group; - if (__nss_group_database != NULL) { no_more = 0; @@ -196,14 +164,14 @@ initgroups (user, group) if (fct == NULL) { - status = compat_call (nip, user, group, &start, &size, &groups, + status = compat_call (nip, user, group, &start, size, groupsp, limit, &errno); if (nss_next_action (nip, NSS_STATUS_UNAVAIL) != NSS_ACTION_CONTINUE) break; } else - status = DL_CALL_FCT (fct, (user, group, &start, &size, &groups, + status = DL_CALL_FCT (fct, (user, group, &start, size, groupsp, limit, &errno)); /* This is really only for debugging. */ @@ -220,10 +188,81 @@ initgroups (user, group) nip = nip->next; } + return start; +} + +/* Store at most *NGROUPS members of the group set for USER into + *GROUPS. Also include GROUP. The actual number of groups found is + returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. */ +int +getgrouplist (const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + gid_t *newgroups; + long int size = *ngroups; + int result; + + newgroups = (gid_t *) malloc (size * sizeof (gid_t)); + if (__builtin_expect (newgroups == NULL, 0)) + /* No more memory. */ + return -1; + + result = internal_getgrouplist (user, group, &size, &newgroups, -1); + if (result > *ngroups) + { + *ngroups = result; + result = -1; + } + else + *ngroups = result; + + memcpy (groups, newgroups, *ngroups * sizeof (gid_t)); + + free (newgroups); + return result; +} + +/* Initialize the group set for the current user + by reading the group database and using all groups + of which USER is a member. Also include GROUP. */ +int +initgroups (const char *user, gid_t group) +{ +#if defined NGROUPS_MAX && NGROUPS_MAX == 0 + + /* No extra groups allowed. */ + return 0; + +#else + + long int size; + gid_t *groups; + int ngroups; + int result; + + /* We always use sysconf even if NGROUPS_MAX is defined. That way, the + limit can be raised in the kernel configuration without having to + recompile libc. */ + long int limit = __sysconf (_SC_NGROUPS_MAX); + + if (limit > 0) + size = limit; + else + { + /* No fixed limit on groups. Pick a starting buffer size. */ + size = 16; + } + + groups = (gid_t *) malloc (size * sizeof (gid_t)); + if (__builtin_expect (groups == NULL, 0)) + /* No more memory. */ + return -1; + + ngroups = internal_getgrouplist (user, group, &size, &groups, limit); + /* Try to set the maximum number of groups the kernel can handle. */ do - result = setgroups (start, groups); - while (result == -1 && errno == EINVAL && --start > 0); + result = setgroups (ngroups, groups); + while (result == -1 && errno == EINVAL && --ngroups > 0); free (groups); Index: grp/grp.h =================================================================== RCS file: /cvs/glibc/libc/grp/grp.h,v retrieving revision 1.28 diff -u -p -r1.28 grp.h --- grp/grp.h 2000/02/28 04:24:18 1.28 +++ grp/grp.h 2001/06/07 19:42:10 @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,95,96,97,98,99,2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,95,96,97,98,99,2000,01 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -135,6 +135,12 @@ extern int fgetgrent_r (FILE *__restrict /* Set the group set for the current user to GROUPS (N of them). */ extern int setgroups (size_t __n, __const __gid_t *__groups) __THROW; + +/* Store at most *NGROUPS members of the group set for USER into + *GROUPS. Also include GROUP. The actual number of groups found is + returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. */ +extern int getgrouplist (__const char *__user, __gid_t __group, + __gid_t *__groups, int *__ngroups) __THROW; /* Initialize the group set for the current user by reading the group database and using all groups Index: grp/Versions =================================================================== RCS file: /cvs/glibc/libc/grp/Versions,v retrieving revision 1.3 diff -u -p -r1.3 Versions --- grp/Versions 1999/07/09 20:47:25 1.3 +++ grp/Versions 2001/06/07 19:42:10 @@ -24,4 +24,8 @@ libc { # g* getgrent_r; getgrgid_r; getgrnam_r; } + GLIBC_2.2.4 { + # g* + getgrouplist; + } }
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |