summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--lib/mgetgroups.c31
-rw-r--r--lib/mgetgroups.h1
-rw-r--r--modules/mgetgroups1
4 files changed, 36 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 15bdded150..48e102661f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2009-12-04 Eric Blake <ebb9@byu.net>
+ mgetgroups: add xgetgroups, and avoid ENOSYS failures
+ * lib/mgetgroups.h (xgetgroups): New prototype.
+ * lib/mgetgroups.c (xgetgroups): New wrapper.
+ (mgetgroups): Handle ENOSYS.
+ * modules/mgetgroups (Depends-on): Add realloc.
+ Reported by Scott Harrison <scott.gnu.2009@scottrix.co.uk>.
+
mgetgroups: avoid argument promotion issues with -1
* lib/mgetgroups.c (mgetgroups): A cast is required when checking
for invalid gid_t.
diff --git a/lib/mgetgroups.c b/lib/mgetgroups.c
index 9a733d5984..7a61db41d9 100644
--- a/lib/mgetgroups.c
+++ b/lib/mgetgroups.c
@@ -116,13 +116,24 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups)
max_n_groups = (username
? getugroups (0, NULL, username, gid)
- : getgroups (0, NULL) + (gid != (gid_t) -1));
+ : getgroups (0, NULL));
- /* If we failed to count groups with NULL for a buffer,
- try again with a non-NULL one, just in case. */
+ /* If we failed to count groups because there is no supplemental
+ group support, then return an array containing just GID.
+ Otherwise, we fail for the same reason. */
if (max_n_groups < 0)
- max_n_groups = 5;
+ {
+ if (errno == ENOSYS && (g = realloc_groupbuf (NULL, 1)))
+ {
+ *groups = g;
+ *g = gid;
+ return gid != (gid_t) -1;
+ }
+ return -1;
+ }
+ if (!username && gid != (gid_t) -1)
+ max_n_groups++;
g = realloc_groupbuf (NULL, max_n_groups);
if (g == NULL)
return -1;
@@ -133,6 +144,7 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups)
if (ng < 0)
{
+ /* Failure is unexpected, but handle it anyway. */
int saved_errno = errno;
free (g);
errno = saved_errno;
@@ -147,3 +159,14 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups)
*groups = g;
return ng;
}
+
+/* Like mgetgroups, but call xalloc_die on allocation failure. */
+
+int
+xgetgroups (char const *username, gid_t gid, gid_t **groups)
+{
+ int result = mgetgroups (username, gid, groups);
+ if (result == -1 && errno == ENOMEM)
+ xalloc_die ();
+ return result;
+}
diff --git a/lib/mgetgroups.h b/lib/mgetgroups.h
index 909d84c645..4868d28815 100644
--- a/lib/mgetgroups.h
+++ b/lib/mgetgroups.h
@@ -17,3 +17,4 @@
#include <sys/types.h>
int mgetgroups (const char *username, gid_t gid, gid_t **groups);
+int xgetgroups (const char *username, gid_t gid, gid_t **groups);
diff --git a/modules/mgetgroups b/modules/mgetgroups
index 58ef74086a..cd249dba31 100644
--- a/modules/mgetgroups
+++ b/modules/mgetgroups
@@ -9,6 +9,7 @@ m4/mgetgroups.m4
Depends-on:
getgroups
getugroups
+realloc
xalloc
configure.ac: