diff options
author | Andrew Tridgell <tridge@samba.org> | 2002-07-23 09:22:29 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2002-07-23 09:22:29 +0000 |
commit | fef9d6187ece53ae12670cc56b360e913e08f3bb (patch) | |
tree | e02543ae6ff6e09e26018abd740566309fea36f5 /source3/lib/replace.c | |
parent | 5b513407c21e6e77d495fafa49a7a5d380087667 (diff) | |
download | samba-fef9d6187ece53ae12670cc56b360e913e08f3bb.tar.gz samba-fef9d6187ece53ae12670cc56b360e913e08f3bb.tar.bz2 samba-fef9d6187ece53ae12670cc56b360e913e08f3bb.zip |
implemented getgrouplist() for systems that don't have it and use it
in get_alias_user_groups(). The old method used getgrent() which is
extremely slow when the number of groups is large
(This used to be commit 44e92b6523ca2c119c2562df22eb71138dca9d9d)
Diffstat (limited to 'source3/lib/replace.c')
-rw-r--r-- | source3/lib/replace.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/source3/lib/replace.c b/source3/lib/replace.c index 2cc7d48adb..e2664accfa 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -428,3 +428,69 @@ char *rep_inet_ntoa(struct in_addr ip) } #endif /* HAVE_SYSLOG */ #endif /* HAVE_VSYSLOG */ + + +#ifndef HAVE_GETGROUPLIST +/* + This is a *much* faster way of getting the list of groups for a user + without changing the current supplemenrary group list. The old + method used getgrent() which could take 20 minutes on a really big + network with hundeds of thousands of groups and users. The new method + takes a couple of seconds. + + NOTE!! this function only works if it is called as root! + */ + int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) +{ + gid_t *gids_saved; + int ret, ngrp_saved; + + /* work out how many groups we need to save */ + ngrp_saved = getgroups(0, NULL); + if (ngrp_saved == -1) { + /* this shouldn't happen */ + return -1; + } + + gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1)); + if (!gids_saved) { + errno = ENOMEM; + return -1; + } + + ngrp_saved = getgroups(ngrp_saved, gids_saved); + if (ngrp_saved == -1) { + free(gids_saved); + /* very strange! */ + return -1; + } + + if (initgroups(user, gid) != 0) { + free(gids_saved); + return -1; + } + + /* this must be done to cope with systems that put the current egid in the + return from getgroups() */ + save_re_gid(); + set_effective_gid(gid); + setgid(gid); + + ret = getgroups(*grpcnt, groups); + if (ret >= 0) { + *grpcnt = ret; + } + + restore_re_gid(); + + if (setgroups(ngrp_saved, gids_saved) != 0) { + /* yikes! */ + DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); + free(gids_saved); + return -1; + } + + free(gids_saved); + return ret; +} +#endif |