aboutsummaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
Diffstat (limited to 'nscd')
-rw-r--r--nscd/connections.c146
-rw-r--r--nscd/nscd_getgr_r.c105
2 files changed, 141 insertions, 110 deletions
diff --git a/nscd/connections.c b/nscd/connections.c
index 7fdafe1..e11132c 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -157,7 +157,7 @@ handle_new_request (int **connp, request_header **reqp, char **key)
read_polls[i].fd = -1;
}
}
-
+
if (found == 0)
{
dbg_log (_("No sockets with data found !"));
@@ -320,7 +320,10 @@ init_sockets (void)
void
pw_send_answer (int conn, struct passwd *pwd)
{
+ struct iovec vec[6];
pw_response_header resp;
+ size_t total_len;
+ int nblocks;
resp.version = NSCD_VERSION;
if (pwd != NULL)
@@ -352,40 +355,42 @@ pw_send_answer (int conn, struct passwd *pwd)
return;
}
- /* Send response header. */
- if (write (sock[conn], &resp, sizeof (pw_response_header)) !=
- sizeof (pw_response_header))
- {
- dbg_log (_("write incomplete on send response: %s"), strerror (errno));
- return;
- }
+ /* Add response header. */
+ vec[0].iov_base = &resp;
+ vec[0].iov_len = sizeof (pw_response_header);
+ total_len = sizeof (pw_response_header);
+ nblocks = 1;
if (resp.found)
{
- struct iovec vec[5];
-
- /* Send pw_name. */
- vec[0].iov_base = pwd->pw_name;
- vec[0].iov_len = resp.pw_name_len;
- /* Send pw_passwd. */
- vec[1].iov_base = pwd->pw_passwd;
- vec[1].iov_len = resp.pw_passwd_len;
- /* Send pw_gecos. */
- vec[2].iov_base = pwd->pw_gecos;
- vec[2].iov_len = resp.pw_gecos_len;
- /* Send pw_dir. */
- vec[3].iov_base = pwd->pw_dir;
- vec[3].iov_len = resp.pw_dir_len;
- /* Send pw_shell. */
- vec[4].iov_base = pwd->pw_shell;
- vec[4].iov_len = resp.pw_shell_len;
-
- if (writev (sock[conn], vec, 5) != (resp.pw_name_len + resp.pw_passwd_len
- + resp.pw_gecos_len + resp.pw_dir_len
- + resp.pw_shell_len))
- dbg_log (_("write incomplete on send passwd answer: %s"),
- strerror (errno));
+ /* Add pw_name. */
+ vec[1].iov_base = pwd->pw_name;
+ vec[1].iov_len = resp.pw_name_len;
+ total_len += resp.pw_name_len;
+ /* Add pw_passwd. */
+ vec[2].iov_base = pwd->pw_passwd;
+ vec[2].iov_len = resp.pw_passwd_len;
+ total_len += resp.pw_passwd_len;
+ /* Add pw_gecos. */
+ vec[3].iov_base = pwd->pw_gecos;
+ vec[3].iov_len = resp.pw_gecos_len;
+ total_len += resp.pw_gecos_len;
+ /* Add pw_dir. */
+ vec[4].iov_base = pwd->pw_dir;
+ vec[4].iov_len = resp.pw_dir_len;
+ total_len += resp.pw_dir_len;
+ /* Add pw_shell. */
+ vec[5].iov_base = pwd->pw_shell;
+ vec[5].iov_len = resp.pw_shell_len;
+ total_len += resp.pw_shell_len;
+
+ nblocks = 6;
}
+
+ /* Send all the data. */
+ if (writev (sock[conn], vec, nblocks) != total_len)
+ dbg_log (_("write incomplete on send passwd answer: %s"),
+ strerror (errno));
}
void
@@ -419,7 +424,11 @@ pw_send_disabled (int conn)
void
gr_send_answer (int conn, struct group *grp)
{
+ struct iovec *vec;
+ size_t *len;
gr_response_header resp;
+ size_t total_len;
+ int nblocks;
resp.version = NSCD_VERSION;
if (grp != NULL)
@@ -447,54 +456,55 @@ gr_send_answer (int conn, struct group *grp)
return;
}
- /* Send response header. */
- if (write (sock[conn], &resp, sizeof (gr_response_header))
- != sizeof (gr_response_header))
- {
- dbg_log (_("write incomplete on send response: %s"), strerror (errno));
- return;
- }
+ /* We have no fixed number of records so allocate the IOV here. */
+ vec = alloca ((3 + 1 + resp.gr_mem_len) * sizeof (struct iovec));
+ len = alloca (resp.gr_mem_len * sizeof (size_t));
+
+ /* Add response header. */
+ vec[0].iov_base = &resp;
+ vec[0].iov_len = sizeof (gr_response_header);
+ total_len = sizeof (gr_response_header);
+ nblocks = 1;
if (resp.found)
{
unsigned int l = 0;
- /* Send gr_name. */
- if (write (sock[conn], grp->gr_name, resp.gr_name_len)
- != resp.gr_name_len)
- {
- dbg_log (_("write incomplete on send response: %s"),
- strerror (errno));
- return;
- }
- /* Send gr_passwd. */
- if (write (sock[conn], grp->gr_passwd, resp.gr_passwd_len)
- != resp.gr_passwd_len)
- {
- dbg_log (_("write incomplete on send response: %s"),
- strerror (errno));
- return;
- }
-
- while (grp->gr_mem[l])
+ /* Add gr_name. */
+ vec[1].iov_base = grp->gr_name;
+ vec[1].iov_len = resp.gr_name_len;
+ total_len += resp.gr_name_len;
+ /* Add gr_passwd. */
+ vec[2].iov_base = grp->gr_passwd;
+ vec[2].iov_len = resp.gr_passwd_len;
+ total_len += resp.gr_passwd_len;
+ nblocks = 3;
+
+ if (grp->gr_mem[l])
{
- size_t len = strlen (grp->gr_mem[l]);
+ vec[3].iov_base = len;
+ vec[3].iov_len = resp.gr_mem_len * sizeof (size_t);
+ total_len += resp.gr_mem_len * sizeof (size_t);
+ nblocks = 4;
- if (write (sock[conn], &len, sizeof (len)) != sizeof (len))
+ do
{
- dbg_log (_("write incomplete on send response: %s"),
- strerror (errno));
- return;
- }
- if (write (sock[conn], grp->gr_mem[l], len) != len)
- {
- dbg_log (_("write incomplete on send response: %s"),
- strerror (errno));
- return;
+ len[l] = strlen (grp->gr_mem[l]);
+
+ vec[nblocks].iov_base = grp->gr_mem[l];
+ vec[nblocks].iov_len = len[l];
+ total_len += len[l];
+
+ ++nblocks;
}
- ++l;
+ while (grp->gr_mem[++l]);
}
}
+
+ /* Send all the data. */
+ if (writev (sock[conn], vec, nblocks) != total_len)
+ dbg_log (_("write incomplete on send group answer: %s"),
+ strerror (errno));
}
void
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index ec4b8f2..9b3022c 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;