aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeebs <seebs@seebs.net>2018-01-16 19:11:51 -0600
committerSeebs <seebs@seebs.net>2018-01-16 19:11:51 -0600
commitfffb4fb3be46911e8725dae229f8a4a07ecd9ba8 (patch)
treeaef515c5bc367493824f993fba54c4a2f8ac603d
parentbbebd1e85f4b3f30a355e8721052c568e8408cfc (diff)
downloadpseudo-fffb4fb3be46911e8725dae229f8a4a07ecd9ba8.tar.gz
pseudo-fffb4fb3be46911e8725dae229f8a4a07ecd9ba8.tar.bz2
pseudo-fffb4fb3be46911e8725dae229f8a4a07ecd9ba8.zip
Handle long lines in /etc/group
This allows the pseudo /etc/group to contain extremely long lines, e.g. when a group has a lot of members. Without this, chown and chgrp fail for group names that occur after such long lines. Signed-off-by: Zoltán Böszörményi <zboszor@pr.hu> Signed-off-by: Seebs <seebs@seebs.net> --- ports/darwin/guts/getgrouplist.c | 54 +++++++++++++++++++++++++++----------- ports/linux/guts/getgrouplist.c | 54 +++++++++++++++++++++++++++----------- ports/uids_generic/guts/getgrent.c | 26 +++++++++++++++--- ports/uids_generic/guts/getgrgid.c | 26 +++++++++++++++--- ports/uids_generic/guts/getgrnam.c | 25 +++++++++++++++--- 5 files changed, 146 insertions(+), 39 deletions(-)
-rw-r--r--ChangeLog.txt2
-rw-r--r--ports/darwin/guts/getgrouplist.c54
-rw-r--r--ports/linux/guts/getgrouplist.c54
-rw-r--r--ports/uids_generic/guts/getgrent.c26
-rw-r--r--ports/uids_generic/guts/getgrgid.c26
-rw-r--r--ports/uids_generic/guts/getgrnam.c25
6 files changed, 148 insertions, 39 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 73a12d4..033fdcf 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,6 +1,8 @@
2018-01-16:
* (seebs) rework the LINKAT case significantly but now
it's actually probably right.
+ * (<zboszor@pr.hu>) handle extremely long group names
+ in getgrnam and similar functions.
2017-12-22:
* (seebs) handle the pathological case of LINKAT with
diff --git a/ports/darwin/guts/getgrouplist.c b/ports/darwin/guts/getgrouplist.c
index 85fccc9..c5950bd 100644
--- a/ports/darwin/guts/getgrouplist.c
+++ b/ports/darwin/guts/getgrouplist.c
@@ -9,23 +9,47 @@
int found = 0;
int found_group = 0;
- char buf[PSEUDO_PWD_MAX];
- struct group grp, *gbuf = &grp;
-
- setgrent();
- while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
- int i = 0;
- for (i = 0; gbuf->gr_mem[i]; ++i) {
- if (!strcmp(gbuf->gr_mem[i], name)) {
- if (found < *ngroups)
- groups[found] = gbuf->gr_gid;
- ++found;
- if ((int) gbuf->gr_gid == basegid)
- found_group = 1;
+ size_t buflen = PSEUDO_PWD_MAX;
+ char *buf = NULL;
+ struct group grp;
+
+ rc = ERANGE;
+
+ do {
+ struct group *gbuf = &grp;
+ char *new_buf = buf;
+
+ if (rc == ERANGE)
+ new_buf = realloc(buf, buflen);
+
+ if (!new_buf) {
+ rc = ENOMEM;
+ break;
+ }
+
+ buf = new_buf;
+
+ found = 0;
+ found_group = 0;
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], name)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if ((int) gbuf->gr_gid == basegid)
+ found_group = 1;
+ }
}
}
- }
- endgrent();
+ endgrent();
+
+ if (rc == ERANGE)
+ buflen = buflen << 1;
+ } while (rc == ERANGE);
+ free(buf);
if (!found_group) {
if (found < *ngroups)
groups[found] = basegid;
diff --git a/ports/linux/guts/getgrouplist.c b/ports/linux/guts/getgrouplist.c
index 3489ec9..8b16e47 100644
--- a/ports/linux/guts/getgrouplist.c
+++ b/ports/linux/guts/getgrouplist.c
@@ -9,23 +9,47 @@
int found = 0;
int found_group = 0;
- char buf[PSEUDO_PWD_MAX];
- struct group grp, *gbuf = &grp;
-
- setgrent();
- while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
- int i = 0;
- for (i = 0; gbuf->gr_mem[i]; ++i) {
- if (!strcmp(gbuf->gr_mem[i], user)) {
- if (found < *ngroups)
- groups[found] = gbuf->gr_gid;
- ++found;
- if (gbuf->gr_gid == group)
- found_group = 1;
+ size_t buflen = PSEUDO_PWD_MAX;
+ char *buf = NULL;
+ struct group grp;
+
+ rc = ERANGE;
+
+ do {
+ struct group *gbuf = &grp;
+ char *new_buf = buf;
+
+ if (rc == ERANGE)
+ new_buf = realloc(buf, buflen);
+
+ if (!new_buf) {
+ rc = ENOMEM;
+ break;
+ }
+
+ buf = new_buf;
+
+ found = 0;
+ found_group = 0;
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], user)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if (gbuf->gr_gid == group)
+ found_group = 1;
+ }
}
}
- }
- endgrent();
+ endgrent();
+
+ if (rc == ERANGE)
+ buflen = buflen << 1;
+ } while (rc == ERANGE);
+ free(buf);
if (!found_group) {
if (found < *ngroups)
groups[found] = group;
diff --git a/ports/uids_generic/guts/getgrent.c b/ports/uids_generic/guts/getgrent.c
index e8e07f5..d6592e6 100644
--- a/ports/uids_generic/guts/getgrent.c
+++ b/ports/uids_generic/guts/getgrent.c
@@ -7,10 +7,30 @@
* struct group * rc = NULL;
*/
static struct group grp;
- static char grbuf[PSEUDO_PWD_MAX];
- int r_rc;
+ static size_t grbuflen = PSEUDO_PWD_MAX;
+ static char *grbuf = NULL;
+ int r_rc = ERANGE;
+
+ do {
+ char *new_grbuf = grbuf;
+
+ if (r_rc == ERANGE)
+ new_grbuf = realloc(grbuf, grbuflen);
+
+ if (!new_grbuf) {
+ r_rc = ENOMEM;
+ break;
+ }
+
+ grbuf = new_grbuf;
+
+ r_rc = wrap_getgrent_r(&grp, grbuf, grbuflen, &rc);
+
+ if (r_rc == ERANGE)
+ grbuflen = grbuflen << 1;
+
+ } while (r_rc == ERANGE);
- r_rc = wrap_getgrent_r(&grp, grbuf, PSEUDO_PWD_MAX, &rc);
/* different error return conventions */
if (r_rc != 0) {
errno = r_rc;
diff --git a/ports/uids_generic/guts/getgrgid.c b/ports/uids_generic/guts/getgrgid.c
index c1824e7..0d3dafb 100644
--- a/ports/uids_generic/guts/getgrgid.c
+++ b/ports/uids_generic/guts/getgrgid.c
@@ -7,10 +7,30 @@
* struct group * rc = NULL;
*/
static struct group grp;
- static char grbuf[PSEUDO_PWD_MAX];
- int r_rc;
+ static size_t grbuflen = PSEUDO_PWD_MAX;
+ static char *grbuf = NULL;
+ int r_rc = ERANGE;
+
+ do {
+ char *new_grbuf = grbuf;
+
+ if (r_rc == ERANGE)
+ new_grbuf = realloc(grbuf, grbuflen);
+
+ if (!new_grbuf) {
+ r_rc = ENOMEM;
+ break;
+ }
+
+ grbuf = new_grbuf;
+
+ r_rc = wrap_getgrgid_r(gid, &grp, grbuf, grbuflen, &rc);
+
+ if (r_rc == ERANGE)
+ grbuflen = grbuflen << 1;
+
+ } while (r_rc == ERANGE);
- r_rc = wrap_getgrgid_r(gid, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
/* different error return conventions */
if (r_rc != 0) {
errno = r_rc;
diff --git a/ports/uids_generic/guts/getgrnam.c b/ports/uids_generic/guts/getgrnam.c
index 0e26444..19006ad 100644
--- a/ports/uids_generic/guts/getgrnam.c
+++ b/ports/uids_generic/guts/getgrnam.c
@@ -8,10 +8,29 @@
*/
static struct group grp;
- static char grbuf[PSEUDO_PWD_MAX];
- int r_rc;
+ static size_t grbufsz = PSEUDO_PWD_MAX;
+ static char *grbuf = NULL;
+ int r_rc = ERANGE;
+
+ do {
+ char *new_grbuf = grbuf;
+
+ if (r_rc != 0)
+ new_grbuf = realloc(grbuf, grbufsz);
+
+ if (!new_grbuf) {
+ r_rc = ENOMEM;
+ break;
+ }
+
+ grbuf = new_grbuf;
+
+ r_rc = wrap_getgrnam_r(name, &grp, grbuf, grbufsz, &rc);
+
+ if (r_rc == ERANGE)
+ grbufsz = grbufsz << 1;
+ } while (r_rc == ERANGE);
- r_rc = wrap_getgrnam_r(name, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
/* different error return conventions */
if (r_rc != 0) {
errno = r_rc;