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 + + * 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 * 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]; + /* 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; - /* 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)); + 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; - } + /* 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; - while (grp->gr_mem[l]) + 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; + 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; } - if (write (sock[conn], grp->gr_mem[l], len) != len) - { - dbg_log (_("write incomplete on send response: %s"), - strerror (errno)); - return; - } - ++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 #include #include +#include #include #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) - { - __set_errno (ERANGE); - __close (sock); - return -1; - } - resultbuf->gr_passwd = p; + 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 -= (gr_resp.gr_passwd_len + 1); - nbytes = __read (sock, resultbuf->gr_passwd, gr_resp.gr_passwd_len); - if (nbytes != gr_resp.gr_passwd_len) + buflen -= total_len; + nblocks = 2; + + if (gr_resp.gr_mem_len > 0) + { + 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; + } + + /* 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;