summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/grp.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-05-07 11:00:00 +0000
committerCorinna Vinschen <corinna@vinschen.de>2014-05-07 11:00:00 +0000
commit20de26ebf982c2645b724b126b103cc8629f51eb (patch)
tree001c4a35d6f4467cc2f0df3840009a2793e434a2 /winsup/cygwin/grp.cc
parentfc3a3524b243956ad1c483a7436ddd37849ce2a9 (diff)
downloadcygnal-20de26ebf982c2645b724b126b103cc8629f51eb.tar.gz
cygnal-20de26ebf982c2645b724b126b103cc8629f51eb.tar.bz2
cygnal-20de26ebf982c2645b724b126b103cc8629f51eb.zip
* grp.cc (pwdgrp::parse_group): Set grp.len. Drop generating any
gr_mem entries. (getgrgid_r): Don't try to copy gr_mem entries. Always set gr_mem to an empty list. (getgrnam_r): Ditto. (app_gr): New static struct to store group data propagated to the calling application via getgrgid/getgrnam. (getgr_cp): Fill app_gr and return pointer to app_gr.g. (getgrgid32): Call getgr_cp. (getgrnam32): Ditto. * passwd.cc (pwdgrp::parse_passwd): Set res.len. (app_pw): New static struct to store passwd data propagated to the calling application via getpwuid/getpwnam. (getpw_cp): Fill app_pw and return pointer to app_pw.p. (getpwuid32): Cal getpw_cp. (getpwnam): Ditto. * pwdgrp.h (struct pg_pwd): Add len member. (struct pg_grp): Ditto.
Diffstat (limited to 'winsup/cygwin/grp.cc')
-rw-r--r--winsup/cygwin/grp.cc83
1 files changed, 49 insertions, 34 deletions
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index fadadff64..3ccdbee0f 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -38,23 +38,14 @@ pwdgrp::parse_group ()
if (!*grp.g.gr_name)
return false;
grp.g.gr_passwd = next_str (':');
+ /* Note that lptr points to the first byte of the gr_gid field.
+ We deliberately ignore the gr_gid and gr_mem entries when copying
+ the buffer content since they are not referenced anymore. */
+ grp.len = lptr - grp.g.gr_name;
if (!next_num (grp.g.gr_gid))
return false;
- int n;
- char *dp = raw_ptr ();
- for (n = 0; *next_str (','); n++)
- continue;
+ /* Don't generate gr_mem entries. */
grp.g.gr_mem = &null_ptr;
- if (n)
- {
- char **namearray = (char **) ccalloc (HEAP_BUF, n + 1, sizeof (char *));
- if (namearray)
- {
- for (int i = 0; i < n; i++, dp = strchr (dp, '\0') + 1)
- namearray[i] = dp;
- grp.g.gr_mem = namearray;
- }
- }
grp.sid.getfromgr (&grp.g);
return true;
}
@@ -228,32 +219,60 @@ getgrgid_r (gid_t gid, struct group *grp, char *buffer, size_t bufsize,
if (!tempgr)
return 0;
- /* check needed buffer size. */
- int i;
+ /* Check needed buffer size. Deliberately ignore gr_mem. */
size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+ 2 + sizeof (char *);
- for (i = 0; tempgr->gr_mem[i]; ++i)
- needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
if (needsize > bufsize)
return ERANGE;
- /* make a copy of tempgr */
+ /* Make a copy of tempgr. Deliberately ignore gr_mem. */
*result = grp;
grp->gr_gid = tempgr->gr_gid;
buffer = stpcpy (grp->gr_name = buffer, tempgr->gr_name);
buffer = stpcpy (grp->gr_passwd = buffer + 1, tempgr->gr_passwd);
grp->gr_mem = (char **) (buffer + 1);
- buffer = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
- for (i = 0; tempgr->gr_mem[i]; ++i)
- buffer = stpcpy (grp->gr_mem[i] = buffer, tempgr->gr_mem[i]) + 1;
- grp->gr_mem[i] = NULL;
+ grp->gr_mem[0] = NULL;
return 0;
}
+/* getgrgid/getgrnam are not reentrant. */
+static struct {
+ struct group g;
+ char *buf;
+ size_t bufsiz;
+} app_gr;
+
+static struct group *
+getgr_cp (struct group *tempgr)
+{
+ if (!tempgr)
+ return NULL;
+ pg_grp *gr = (pg_grp *) tempgr;
+ if (app_gr.bufsiz < gr->len)
+ {
+ char *newbuf = (char *) realloc (app_gr.buf, gr->len);
+ if (!newbuf)
+ {
+ set_errno (ENOMEM);
+ return NULL;
+ }
+ app_gr.buf = newbuf;
+ app_gr.bufsiz = gr->len;
+ }
+ memcpy (app_gr.buf, gr->g.gr_name, gr->len);
+ memcpy (&app_gr.g, &gr->g, sizeof gr->g);
+ ptrdiff_t diff = app_gr.buf - gr->g.gr_name;
+ app_gr.g.gr_name += diff;
+ app_gr.g.gr_passwd += diff;
+ return &app_gr.g;
+}
+
extern "C" struct group *
getgrgid32 (gid_t gid)
{
- return internal_getgrgid (gid);
+ struct group *tempgr = internal_getgrgid (gid);
+ pthread_testcancel ();
+ return getgr_cp (tempgr);
}
#ifdef __x86_64__
@@ -282,32 +301,28 @@ getgrnam_r (const char *nam, struct group *grp, char *buffer,
if (!tempgr)
return 0;
- /* check needed buffer size. */
- int i;
+ /* Check needed buffer size. Deliberately ignore gr_mem. */
size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+ 2 + sizeof (char *);
- for (i = 0; tempgr->gr_mem[i]; ++i)
- needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
if (needsize > bufsize)
return ERANGE;
- /* make a copy of tempgr */
+ /* Make a copy of tempgr. Deliberately ignore gr_mem. */
*result = grp;
grp->gr_gid = tempgr->gr_gid;
buffer = stpcpy (grp->gr_name = buffer, tempgr->gr_name);
buffer = stpcpy (grp->gr_passwd = buffer + 1, tempgr->gr_passwd);
grp->gr_mem = (char **) (buffer + 1);
- buffer = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
- for (i = 0; tempgr->gr_mem[i]; ++i)
- buffer = stpcpy (grp->gr_mem[i] = buffer, tempgr->gr_mem[i]) + 1;
- grp->gr_mem[i] = NULL;
+ grp->gr_mem[0] = NULL;
return 0;
}
extern "C" struct group *
getgrnam32 (const char *name)
{
- return internal_getgrnam (name);
+ struct group *tempgr = internal_getgrnam (name);
+ pthread_testcancel ();
+ return getgr_cp (tempgr);
}
#ifdef __x86_64__