diff options
Diffstat (limited to 'dbus/dbus-sysdeps-util-unix.c')
| -rw-r--r-- | dbus/dbus-sysdeps-util-unix.c | 58 | 
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;        }    } | 
