summaryrefslogtreecommitdiff
path: root/source3/lib/replace.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-07-23 09:22:29 +0000
committerAndrew Tridgell <tridge@samba.org>2002-07-23 09:22:29 +0000
commitfef9d6187ece53ae12670cc56b360e913e08f3bb (patch)
treee02543ae6ff6e09e26018abd740566309fea36f5 /source3/lib/replace.c
parent5b513407c21e6e77d495fafa49a7a5d380087667 (diff)
downloadsamba-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.c66
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