summaryrefslogtreecommitdiff
path: root/libudev/libudev-util-private.c
diff options
context:
space:
mode:
Diffstat (limited to 'libudev/libudev-util-private.c')
-rw-r--r--libudev/libudev-util-private.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/libudev/libudev-util-private.c b/libudev/libudev-util-private.c
index f7daa9460b..021734d772 100644
--- a/libudev/libudev-util-private.c
+++ b/libudev/libudev-util-private.c
@@ -149,8 +149,8 @@ uid_t util_lookup_user(struct udev *udev, const char *user)
gid_t util_lookup_group(struct udev *udev, const char *group)
{
char *endptr;
- int buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
- char buf[buflen];
+ int buflen;
+ char *buf;
struct group grbuf;
struct group *gr;
gid_t gid = 0;
@@ -161,15 +161,31 @@ gid_t util_lookup_group(struct udev *udev, const char *group)
if (endptr[0] == '\0')
return gid;
- errno = 0;
- getgrnam_r(group, &grbuf, buf, buflen, &gr);
- if (gr != NULL)
- return gr->gr_gid;
- if (errno == 0 || errno == ENOENT || errno == ESRCH)
- err(udev, "specified group '%s' unknown\n", group);
- else
- err(udev, "error resolving group '%s': %m\n", group);
- return 0;
+ buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (buflen < 0)
+ buflen = 1000;
+ buf = NULL;
+ gid = 0;
+ for (;;) {
+ buf = realloc(buf, buflen);
+ if (!buf)
+ break;
+ errno = 0;
+ getgrnam_r(group, &grbuf, buf, buflen, &gr);
+ if (gr != NULL)
+ gid = gr->gr_gid;
+ else if (errno == ERANGE) {
+ buflen *= 2;
+ continue;
+ }
+ else if (errno == 0 || errno == ENOENT || errno == ESRCH)
+ err(udev, "specified group '%s' unknown\n", group);
+ else
+ err(udev, "error resolving group '%s': %m\n", group);
+ break;
+ }
+ free(buf);
+ return gid;
}
/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */