summaryrefslogtreecommitdiff
path: root/nscd/nscd_getgr_r.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-07-24 21:32:39 +0000
committerUlrich Drepper <drepper@redhat.com>1998-07-24 21:32:39 +0000
commit264d5b944dca563c8b948392942d1ea33d221723 (patch)
treefdbba5a3dab20a3ada3736e48802867b6a6c6816 /nscd/nscd_getgr_r.c
parent6c202c68704b50016c4faba8d6445ab542b5f301 (diff)
Update.
1998-07-24 21:29 Ulrich Drepper <drepper@cygnus.com> * nscd/connections.c (pw_send_answer): Make one single writev call. (gr_send_answer): Do the work in two writev calls. This change changes the protocol. * nscd/nscd_getgr_r.c (__nscd_getgr_r): Adjust for protocol change. We now can do the job using two readv calls.
Diffstat (limited to 'nscd/nscd_getgr_r.c')
-rw-r--r--nscd/nscd_getgr_r.c105
1 files changed, 63 insertions, 42 deletions
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index ec4b8f21c4..9b3022c764 100644
--- a/nscd/nscd_getgr_r.c
+++ b/nscd/nscd_getgr_r.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include "nscd.h"
@@ -139,83 +140,103 @@ __nscd_getgr_r (const char *key, request_type type, struct group *resultbuf,
if (gr_resp.found == 1)
{
- size_t i;
+ struct iovec *vec;
+ size_t *len;
char *p = buffer;
+ int nblocks;
+ size_t total_len;
+ uintptr_t align;
- if (buflen < gr_resp.gr_name_len + 1)
+ /* A first check whether the buffer is sufficently large is possible. */
+ if (buflen < gr_resp.gr_name_len + 1 + gr_resp.gr_passwd_len + 1)
{
__set_errno (ERANGE);
__close (sock);
return -1;
}
- resultbuf->gr_name = p;
+
+ /* Allocate the IOVEC. */
+ vec = alloca ((2 + gr_resp.gr_mem_len) * sizeof (struct iovec));
+ len = alloca (gr_resp.gr_mem_len * sizeof (size_t));
+
+ vec[0].iov_base = resultbuf->gr_name = p;
+ vec[0].iov_len = gr_resp.gr_name_len;
+ total_len = gr_resp.gr_name_len;
p += gr_resp.gr_name_len + 1;
- buflen -= (gr_resp.gr_name_len + 1);
- nbytes = __read (sock, resultbuf->gr_name, gr_resp.gr_name_len);
- if (nbytes != gr_resp.gr_name_len)
- {
- __close (sock);
- return 1;
- }
- resultbuf->gr_name[gr_resp.gr_name_len] = '\0';
- if (buflen < gr_resp.gr_passwd_len + 1)
+ vec[1].iov_base = resultbuf->gr_passwd = p;
+ vec[1].iov_len = gr_resp.gr_passwd_len;
+ total_len += gr_resp.gr_passwd_len;
+ p += gr_resp.gr_passwd_len + 1;
+ buflen -= total_len;
+ nblocks = 2;
+
+ if (gr_resp.gr_mem_len > 0)
{
- __set_errno (ERANGE);
- __close (sock);
- return -1;
+ vec[2].iov_base = len;
+ vec[2].iov_len = gr_resp.gr_mem_len * sizeof (size_t);
+ total_len += gr_resp.gr_mem_len * sizeof (size_t);
+ nblocks = 3;
}
- resultbuf->gr_passwd = p;
- p += gr_resp.gr_passwd_len + 1;
- buflen -= (gr_resp.gr_passwd_len + 1);
- nbytes = __read (sock, resultbuf->gr_passwd, gr_resp.gr_passwd_len);
- if (nbytes != gr_resp.gr_passwd_len)
+
+ /* Get this data. */
+ if (__readv (sock, vec, nblocks) != total_len)
{
__close (sock);
return 1;
}
+
+ /* Now we know the sizes. First terminate the strings we just read. */
+ resultbuf->gr_name[gr_resp.gr_name_len] = '\0';
resultbuf->gr_passwd[gr_resp.gr_passwd_len] = '\0';
resultbuf->gr_gid = gr_resp.gr_gid;
- if (buflen < ((gr_resp.gr_mem_len + 1) * sizeof (char *)))
+ /* Now allocate the buffer the array for the group members. We must
+ align the pointer. */
+ align = ((__alignof__ (char *) - (p - ((char *) 0)))
+ & (__alignof__ (char *) - 1));
+ if (align + (1 + gr_resp.gr_mem_len) * sizeof (char *) > buflen)
{
__set_errno (ERANGE);
__close (sock);
return -1;
}
- resultbuf->gr_mem = (char **)p;
- p += ((gr_resp.gr_mem_len + 1) * sizeof (char *));
- buflen -= ((gr_resp.gr_mem_len + 1) * sizeof (char *));
+ p += align;
+ resultbuf->gr_mem = (char **) p;
+ p += (1 + gr_resp.gr_mem_len) * sizeof (char *);
+ buflen -= align + (1 + gr_resp.gr_mem_len) * sizeof (char *);
resultbuf->gr_mem[gr_resp.gr_mem_len] = NULL;
- for (i = 0; i < gr_resp.gr_mem_len; ++i)
+ if (gr_resp.gr_mem_len > 0)
{
- size_t len;
- nbytes = __read (sock, &len, sizeof (len));
- if (nbytes != sizeof (len))
+ /* Prepare reading the group members. */
+ size_t i;
+
+ total_len = 0;
+ for (i = 0; i < gr_resp.gr_mem_len; ++i)
{
- __close (sock);
- return 1;
+ if (len[i] >= buflen)
+ {
+ __set_errno (ERANGE);
+ __close (sock);
+ return -1;
+ }
+
+ vec[i].iov_base = resultbuf->gr_mem[i] = p;
+ vec[i].iov_len = len[i];
+ total_len += len[i];
+ buflen -= len[i];
+ p += len[i];
+ *p++ = '\0';
}
- if (buflen < (len + 1))
+ if (__readv (sock, vec, gr_resp.gr_mem_len) != total_len)
{
- __set_errno (ERANGE);
__close (sock);
return -1;
}
- resultbuf->gr_mem[i] = p;
- p += len + 1;
- buflen -= (len + 1);
- nbytes = __read (sock, resultbuf->gr_mem[i], len);
- resultbuf->gr_mem[i][len] = '\0';
- if (nbytes != len)
- {
- __close (sock);
- return 1;
- }
}
__close (sock);
return 0;