[PATCH v2 13/23] nscd: Introduce __nscd_read_from_socket client function

Florian Weimer fweimer@redhat.com
Fri Mar 20 20:42:28 GMT 2026


---
 nscd/nscd-client.h | 20 ++++++++++++++++-
 nscd/nscd_helper.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h
index c507933acb..10284e8ef2 100644
--- a/nscd/nscd-client.h
+++ b/nscd/nscd-client.h
@@ -366,11 +366,29 @@ struct mapped_database
   __libc_rwlock_define (, lock);
 };
 
-/* Open socket connection to nscd server.  */
+/* Open socket connection to nscd server, send the request, and read
+   the start of the response (update to RESPONSELEN bytes).  If the
+   procided response buffer is exceeded, the socket is left open, so
+   that more data can be read.  */
 extern int __nscd_open_socket (const char *key, size_t keylen,
 			       request_type type, void *response,
 			       size_t responselen) attribute_hidden;
 
+/* Open a socket to nscd, send the request, and read the full
+   response.  *RESPONSE is grown as necessary.
+
+   A non-negative return value indicates the number of response bytes
+   stored at RESPONSE->data.  The response includes only the struct
+   *_response_header and the data that follows it, not struct
+   datahead.
+
+   On error, return a negative errno code.  */
+struct scratch_buffer;
+ssize_t __nscd_read_from_socket (const char *key, size_t keylen,
+				 request_type type,
+				 struct scratch_buffer *response)
+  attribute_hidden;
+
 /* Acquire reference to the mapping for DB (see <nscd-dbtype.h>).  On
    success, return a pointer to the mapping descriptor, and lock the
    mapping.
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 9bd0e7818e..ed2d8d09da 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -37,6 +37,7 @@
 #include <kernel-features.h>
 #include <nss.h>
 #include <struct___timespec64.h>
+#include <scratch_buffer.h>
 
 #include "nscd-client.h"
 #include "nscd-dbtype.h"
@@ -612,3 +613,55 @@ __nscd_open_socket (const char *key, size_t keylen, request_type type,
 
   return -1;
 }
+
+ssize_t
+__nscd_read_from_socket (const char *key, size_t keylen, request_type type,
+			 struct scratch_buffer *response)
+{
+  if (keylen > MAXKEYLEN)
+    return -ENAMETOOLONG;
+
+  int sock = open_socket (type, key, keylen);
+  if (sock < 0)
+    return sock;
+
+  /* The nscd stream protocol does not size information in a way that
+     is independent of request type.  However, there is only one
+     request per connection, so the code below simply reads all data
+     that is available before end of stream.  */
+
+  ssize_t ret = 0;		/* Number of bytes read, or -1 on error.  */
+  while (true)
+    {
+      /* Wait for data.  Give up on timeout.  */
+      if (wait_on_socket (sock, 5 * 1000) == 0)
+	break;
+      size_t remaining = response->length - ret;
+      ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response->data + ret,
+						   remaining));
+      if (nbytes < 0)
+	{
+	  ret = -errno;
+	  break;
+	}
+      if (nbytes == 0)
+	/* The end of the stream marks the end of packet.  We cannot
+	   tell if the data was truncated because nscd went away
+	   unexpectedly.  This will be recognized by the caller during
+	   packet parsing.  */
+	break;
+
+      /* Try reading more data in the next iteration after growing the
+	 buffer.  */
+      ret += nbytes;
+      if (ret == response->length && !scratch_buffer_grow_preserve (response))
+	{
+	  ret = -ENOMEM;
+	  break;
+	}
+    }
+
+  __close_nocancel_nostatus (sock);
+
+  return ret;
+}
-- 
2.53.0




More information about the Libc-alpha mailing list