* cygwin.din (getgrouplist): Export.

* grp.cc (get_groups): New static function to run the core functionality
	of initgroups and getgrouplist.
	(initgroups32): Call get_groups and just create supplementary group
	list in cygheap.  Rename name of first argument to "user".  Add an
	assertion to test for a NULL user name.
	(initgroups): Rename name of first argument to "user".
	(getgrouplist): New function.
	* posix.sgml (std-bsd): Add getgrouplist.
	* include/cygwin/grp.h (getgrouplist): Declare.
	* include/cygwin/version.h: Bump API minor number.
This commit is contained in:
Corinna Vinschen
2011-10-28 09:26:42 +00:00
parent c85feb40a2
commit 0c1d8aaaf1
6 changed files with 86 additions and 20 deletions

View File

@@ -13,6 +13,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "cygerrno.h"
@@ -419,40 +420,86 @@ getgroups (int gidsetsize, __gid16_t *grouplist)
return ret;
}
extern "C" int
initgroups32 (const char *name, __gid32_t gid)
/* Core functionality of initgroups and getgrouplist. */
static int
get_groups (const char *user, gid_t gid, cygsidlist &gsids)
{
int ret = -1;
cygheap->user.deimpersonate ();
struct passwd *pw = internal_getpwnam (name);
struct passwd *pw = internal_getpwnam (user);
struct __group32 *gr = internal_getgrgid (gid);
cygsid usersid, grpsid;
if (!usersid.getfrompw (pw) || !grpsid.getfromgr (gr))
set_errno (EINVAL);
else
else if (get_server_groups (gsids, usersid, pw))
{
cygsidlist tmp_gsids (cygsidlist_auto, 12);
if (get_server_groups (tmp_gsids, usersid, pw))
{
tmp_gsids += grpsid;
cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count ());
for (int i = 0; i < tmp_gsids.count (); i++)
new_gsids.sids[i] = tmp_gsids.sids[i];
new_gsids.count (tmp_gsids.count ());
cygheap->user.groups.update_supp (new_gsids);
ret = 0;
}
gsids += grpsid;
ret = 0;
}
cygheap->user.reimpersonate ();
syscall_printf ( "%d = initgroups (%s, %u)", ret, name, gid);
return ret;
}
extern "C" int
initgroups (const char *name, __gid16_t gid)
initgroups32 (const char *user, __gid32_t gid)
{
return initgroups32 (name, gid16togid32(gid));
int ret;
assert (user != NULL);
cygsidlist tmp_gsids (cygsidlist_auto, 12);
if (!(ret = get_groups (user, gid, tmp_gsids)))
{
cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count ());
for (int i = 0; i < tmp_gsids.count (); i++)
new_gsids.sids[i] = tmp_gsids.sids[i];
new_gsids.count (tmp_gsids.count ());
cygheap->user.groups.update_supp (new_gsids);
}
syscall_printf ( "%d = initgroups (%s, %u)", ret, user, gid);
return ret;
}
extern "C" int
initgroups (const char *user, __gid16_t gid)
{
return initgroups32 (user, gid16togid32(gid));
}
extern "C" int
getgrouplist (const char *user, gid_t gid, gid_t *groups, int *ngroups)
{
int ret;
/* Note that it's not defined if groups or ngroups may be NULL!
GLibc does not check the pointers on entry and just uses them.
FreeBSD calls assert for ngroups and allows a NULL groups if
*ngroups is 0. We follow FreeBSD's lead here, but always allow
a NULL groups pointer. */
assert (user != NULL);
assert (ngroups != NULL);
cygsidlist tmp_gsids (cygsidlist_auto, 12);
if (!(ret = get_groups (user, gid, tmp_gsids)))
{
int cnt = 0;
for (int i = 0; i < tmp_gsids.count (); i++)
{
struct __group32 *gr = internal_getgrsid (tmp_gsids.sids[i]);
if (gr)
{
if (groups && cnt < *ngroups)
groups[cnt] = gr->gr_gid;
++cnt;
}
}
if (cnt > *ngroups)
ret = -1;
*ngroups = cnt;
}
syscall_printf ( "%d = getgrouplist (%s, %u, %p, %d)",
ret, user, gid, groups, *ngroups);
return ret;
}
/* setgroups32: standards? */