about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--nscd/connections.c146
-rw-r--r--nscd/nscd_getgr_r.c105
3 files changed, 150 insertions, 110 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c11175214..532f003e20 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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.
+
 1998-07-24  Ulrich Drepper  <drepper@cygnus.com>
 
 	* sysdeps/generic/glob.c (glob): Fix problems with handle tilde.
diff --git a/nscd/connections.c b/nscd/connections.c
index 7fdafe16b2..e11132c514 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 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;