(__nscd_getgr_r): Adjust for protocol change. We now can do the job
authordrepper <drepper>
Fri, 24 Jul 1998 21:32:25 +0000 (21:32 +0000)
committerdrepper <drepper>
Fri, 24 Jul 1998 21:32:25 +0000 (21:32 +0000)
using two readv calls.

nscd/nscd_getgr_r.c

index ec4b8f2..9b3022c 100644 (file)
@@ -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;