[PATCH 4/7] alfred: gpsd: handle short reads on the unix socket

Sven Eckelmann <[email protected]> Tue, 28 Jul 2026 15:32:13 +0200
Newsgroups org.open-mesh.lists.batman
Message-ID <[email protected]>
The answer of the alfred daemon is received over a SOCK_STREAM unix socket
which doesn't preserve message boundaries. read() can therefore return less
than the requested number of bytes. Such a short read was treated like an
end of stream, the current packet was dropped and the answer loop
terminated.

Retry the read until the requested amount of data, end of stream or a real
error was received (ignoring temporary interruptions EINTR).

Fixes: 2b901d69d8fb ("alfred: Add support for passing location information over alfred.")
Signed-off-by: Sven Eckelmann <[email protected]>
---
 gpsd/alfred-gpsd.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/gpsd/alfred-gpsd.c b/gpsd/alfred-gpsd.c
index 6456e74..43a3a83 100644
--- a/gpsd/alfred-gpsd.c
+++ b/gpsd/alfred-gpsd.c
@@ -139,6 +139,30 @@ static int gpsd_request_data(struct globals *globals)
 	return globals->unix_sock;
 }
 
+static ssize_t read_full(int fd, void *buf, size_t count)
+{
+	size_t read_len = 0;
+	uint8_t *pos = buf;
+	ssize_t ret;
+
+	while (read_len < count) {
+		ret = read(fd, pos + read_len, count - read_len);
+		if (ret < 0) {
+			if (errno == EINTR)
+				continue;
+
+			return ret;
+		}
+
+		if (ret == 0)
+			break;
+
+		read_len += ret;
+	}
+
+	return read_len;
+}
+
 static struct gpsd_v1 *gpsd_receive_answer_packet(int sock, uint16_t *len,
 						  uint8_t *source)
 {
@@ -149,7 +173,7 @@ static struct gpsd_v1 *gpsd_receive_answer_packet(int sock, uint16_t *len,
 	int ret;
 	int l;
 
-	ret = read(sock, buf, sizeof(*tlv));
+	ret = read_full(sock, buf, sizeof(*tlv));
 	if (ret < 0)
 		return NULL;
 
@@ -171,7 +195,7 @@ static struct gpsd_v1 *gpsd_receive_answer_packet(int sock, uint16_t *len,
 		return NULL;
 
 	/* read the rest of the packet */
-	ret = read(sock, buf + sizeof(*tlv), l);
+	ret = read_full(sock, buf + sizeof(*tlv), l);
 	if (ret < l)
 		return NULL;
 

-- 
2.47.3