summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-sysdeps-util-unix.c
diff options
context:
space:
mode:
authorMarc Brockschmidt <he@debian.org>2008-07-28 16:09:53 -0400
committerColin Walters <walters@verbum.org>2008-07-28 16:14:18 -0400
commit9d51f086b05df196b94234d6a0d388594feedd73 (patch)
tree7dab91cd2603b1f6a67febdeb7e0433bc86fa034 /dbus/dbus-sysdeps-util-unix.c
parent121c6b13a35759ee590551cfb9978e9f20766a12 (diff)
Bug 16727: Handle ERANGE for getgr; fixes user in many groups
Patch originally from Noèl Köthe. Modified by Colin Walters <walters@verbum.org> * dbus/dbus-sysdeps-unix.c, dbus/dbus-sysdeps-unix-utils.c: Use a while() loop to reallocate buffer if we get ERANGE return. This fixes the case where a user is in a large number of groups.
Diffstat (limited to 'dbus/dbus-sysdeps-util-unix.c')
-rw-r--r--dbus/dbus-sysdeps-util-unix.c58
1 files changed, 46 insertions, 12 deletions
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 9ff3fbc1..55eb9346 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -828,31 +828,65 @@ fill_group_info (DBusGroupInfo *info,
{
struct group *g;
int result;
- char buf[1024];
+ size_t buflen;
+ char *buf;
struct group g_str;
+ dbus_bool_t b;
- g = NULL;
-#ifdef HAVE_POSIX_GETPWNAM_R
+ /* retrieve maximum needed size for buf */
+ buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
- if (group_c_str)
- result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
- &g);
- else
- result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
- &g);
+ if (buflen <= 0)
+ buflen = 1024;
+
+ result = -1;
+ while (1)
+ {
+ buf = dbus_malloc (buflen);
+ if (buf == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return FALSE;
+ }
+
+ g = NULL;
+#ifdef HAVE_POSIX_GETPWNAM_R
+ if (group_c_str)
+ result = getgrnam_r (group_c_str, &g_str, buf, buflen,
+ &g);
+ else
+ result = getgrgid_r (gid, &g_str, buf, buflen,
+ &g);
#else
- g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
- result = 0;
+ g = getgrnam_r (group_c_str, &g_str, buf, buflen);
+ result = 0;
#endif /* !HAVE_POSIX_GETPWNAM_R */
+ /* Try a bigger buffer if ERANGE was returned:
+ https://bugs.freedesktop.org/show_bug.cgi?id=16727
+ */
+ if (result == ERANGE && buflen < 512 * 1024)
+ {
+ dbus_free (buf);
+ buflen *= 2;
+ }
+ else
+ {
+ break;
+ }
+ }
+
if (result == 0 && g == &g_str)
{
- return fill_user_info_from_group (g, info, error);
+ b = fill_user_info_from_group (g, info, error);
+ dbus_free (buf);
+ return b;
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
+ dbus_free (buf);
return FALSE;
}
}