[v2,13/23] nscd: Introduce __nscd_read_from_socket client function
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
fail
|
Test failed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-arm |
fail
|
Test failed
|
Commit Message
---
nscd/nscd-client.h | 20 ++++++++++++++++-
nscd/nscd_helper.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 1 deletion(-)
Comments
On 3/20/26 4:42 PM, Florian Weimer wrote:
LGTM.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
> 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);
OK. Pass type, key and keylen to open_socket helper (used by __nscd_get_mapping,
and __nscd_open_socket).
> + 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;
> +}
@@ -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.
@@ -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;
+}