git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 11/19] pkt-line: provide a generic reading function with options

From
Jeff King <peff@peff.net>
Date
Feb 20, 2013, 20:02 UTC
Message-ID
<20130220200210.GK25647@sigill.intra.peff.net>
In-Reply-To
<20130220195147.GA25332@sigill.intra.peff.net>

Originally we had a single function for reading packetized data: packet_read_line. Commit 46284dd grew a more "gentle" form, packet_read, that returns an error instead of dying upon reading a truncated input stream. However, it is not clear from the names which should be called, or what the difference is.

Let's instead make packet_read be a generic public interface that can take option flags, and update the single callsite that uses it. This is less code, more clear, and paves the way for introducing more options into the generic interface later. The function signature is changed, so there should be no hidden conflicts with topics in flight.

While we're at it, we'll document how error conditions are handled based on the options, and rename the confusing "return_line_fail" option to "gentle_on_eof". While we are cleaning up the names, we can drop the "return_line_fail" checks in packet_read_internal entirely. They look like this:

  ret = safe_read(..., return_line_fail);
  if (return_line_fail && ret < 0)
	  ...

The check for return_line_fail is a no-op; safe_read will only ever return an error value if return_line_fail was true in the first place.

Signed-off-by: Jeff King <peff@peff.net>
---
 connect.c  |  3 ++-
 pkt-line.c | 21 ++++++++-------------
 pkt-line.h | 27 ++++++++++++++++++++++++++-
 3 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/connect.c b/connect.c
index 49e56ba..0aa202f 100644
--- a/connect.c
+++ b/connect.c
@@ -76,7 +76,8 @@ struct ref **get_remote_heads(int in, struct ref **list,
 		char *name;
 		int len, name_len;
 
-		len = packet_read(in, buffer, sizeof(buffer));
+		len = packet_read(in, buffer, sizeof(buffer),
+				  PACKET_READ_GENTLE_ON_EOF);
 		if (len < 0)
 			die_initial_contact(got_at_least_one_head);
 
diff --git a/pkt-line.c b/pkt-line.c
index 699c2dd..8700cf8 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -103,13 +103,13 @@ static int safe_read(int fd, void *buffer, unsigned size, int return_line_fail)
 	strbuf_add(buf, buffer, n);
 }
 
-static int safe_read(int fd, void *buffer, unsigned size, int return_line_fail)
+static int safe_read(int fd, void *buffer, unsigned size, int options)
 {
 	ssize_t ret = read_in_full(fd, buffer, size);
 	if (ret < 0)
 		die_errno("read error");
 	else if (ret < size) {
-		if (return_line_fail)
+		if (options & PACKET_READ_GENTLE_ON_EOF)
 			return -1;
 
 		die("The remote end hung up unexpectedly");
@@ -143,13 +143,13 @@ static int packet_read_internal(int fd, char *buffer, unsigned size, int return_
 	return len;
 }
 
-static int packet_read_internal(int fd, char *buffer, unsigned size, int return_line_fail)
+int packet_read(int fd, char *buffer, unsigned size, int options)
 {
 	int len, ret;
 	char linelen[4];
 
-	ret = safe_read(fd, linelen, 4, return_line_fail);
-	if (return_line_fail && ret < 0)
+	ret = safe_read(fd, linelen, 4, options);
+	if (ret < 0)
 		return ret;
 	len = packet_length(linelen);
 	if (len < 0)
@@ -161,22 +161,17 @@ int packet_read_line(int fd, char *buffer, unsigned size)
 	len -= 4;
 	if (len >= size)
 		die("protocol error: bad line length %d", len);
-	ret = safe_read(fd, buffer, len, return_line_fail);
-	if (return_line_fail && ret < 0)
+	ret = safe_read(fd, buffer, len, options);
+	if (ret < 0)
 		return ret;
 	buffer[len] = 0;
 	packet_trace(buffer, len, 0);
 	return len;
 }
 
-int packet_read(int fd, char *buffer, unsigned size)
-{
-	return packet_read_internal(fd, buffer, size, 1);
-}
-
 int packet_read_line(int fd, char *buffer, unsigned size)
 {
-	return packet_read_internal(fd, buffer, size, 0);
+	return packet_read(fd, buffer, size, 0);
 }
 
 int packet_get_line(struct strbuf *out,
diff --git a/pkt-line.h b/pkt-line.h
index 3b6c19c..8cd326c 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -24,8 +24,33 @@ int packet_read_line(int fd, char *buffer, unsigned size);
 void packet_buf_flush(struct strbuf *buf);
 void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
 
+/*
+ * Read a packetized line from the descriptor into the buffer, which must be at
+ * least size bytes long. The return value specifies the number of bytes read
+ * into the buffer.
+ *
+ * If options does not contain PACKET_READ_GENTLE_ON_EOF, we will die under any
+ * of the following conditions:
+ *
+ *   1. Read error from descriptor.
+ *
+ *   2. Protocol error from the remote (e.g., bogus length characters).
+ *
+ *   3. Receiving a packet larger than "size" bytes.
+ *
+ *   4. Truncated output from the remote (e.g., we expected a packet but got
+ *      EOF, or we got a partial packet followed by EOF).
+ *
+ * If options does contain PACKET_READ_GENTLE_ON_EOF, we will not die on
+ * condition 4 (truncated input), but instead return -1. However, we will still
+ * die for the other 3 conditions.
+ */
+#define PACKET_READ_GENTLE_ON_EOF (1u<<0)
+int packet_read(int fd, char *buffer, unsigned size, int options);
+
+/* Historical convenience wrapper for packet_read that sets no options */
 int packet_read_line(int fd, char *buffer, unsigned size);
-int packet_read(int fd, char *buffer, unsigned size);
+
 int packet_get_line(struct strbuf *out, char **src_buf, size_t *src_len);
 
 #endif
-- 
1.8.2.rc0.9.g352092c
Previous: Jeff KingNext: Jeff King
Message 31 of 40 in “[PATCHv3 0/19] pkt-line cleanups and fixes”
  1. Jeff KingFeb 20, 2013
  2. 01/19 upload-pack: use get_sha1_hex to parse "shallow" linesJeff King, Feb 20, 2013
  3. 02/19 upload-pack: do not add duplicate objects to shallow listJeff King, Feb 20, 2013
  4. 03/19 upload-pack: remove packet debugging harnessJeff King, Feb 20, 2013
  5. 04/19 fetch-pack: fix out-of-bounds buffer offset in get_ackJeff King, Feb 20, 2013
  6. 05/19 send-pack: prefer prefixcmp over memcmp in receive_statusJeff King, Feb 20, 2013
  7. 06/19 upload-archive: do not copy repo nameJeff King, Feb 20, 2013
  8. 07/19 upload-archive: use argv_array to store client argumentsJeff King, Feb 20, 2013
  9. 08/19 write_or_die: raise SIGPIPE when we get EPIPEJeff King, Feb 20, 2013
  10. Jonathan NiederFeb 20, 2013
  11. Jeff KingFeb 20, 2013
  12. Jonathan NiederFeb 20, 2013
  13. Jeff KingFeb 20, 2013
  14. Jonathan NiederFeb 20, 2013
  15. Jeff KingFeb 20, 2013
  16. Junio C HamanoFeb 20, 2013
  17. [BUG] MSVC: error box when interrupting `gitlog` by quitting lessMarat Radchenko, Mar 28, 2014
  18. Marat RadchenkoMar 28, 2014
  19. Jeff KingMar 28, 2014
  20. Marat RadchenkoMar 28, 2014
  21. Jeff KingMar 28, 2014
  22. Johannes SixtMar 28, 2014
  23. MSVC: link in invalidcontinue.obj for better POSIX compatibilityMarat Radchenko, Mar 28, 2014
  24. Junio C HamanoMar 28, 2014
  25. Marat RadchenkoMar 28, 2014
  26. Junio C HamanoMar 28, 2014
  27. MSVC: link in invalidcontinue.obj for better POSIX compatibilityMarat Radchenko, Mar 28, 2014
  28. Junio C HamanoMar 28, 2014
  29. 09/19 pkt-line: move a misplaced commentJeff King, Feb 20, 2013
  30. 10/19 pkt-line: drop safe_write functionJeff King, Feb 20, 2013
  31. 11/19 pkt-line: provide a generic reading function with optionsJeff King, Feb 20, 2013
  32. 12/19 pkt-line: teach packet_read_line to chomp newlinesJeff King, Feb 20, 2013
  33. 13/19 pkt-line: move LARGE_PACKET_MAX definition from sidebandJeff King, Feb 20, 2013
  34. 14/19 pkt-line: provide a LARGE_PACKET_MAX static bufferJeff King, Feb 20, 2013
  35. 15/19 pkt-line: share buffer/descriptor reading implementationJeff King, Feb 20, 2013
  36. Eric SunshineFeb 22, 2013
  37. 16/19 teach get_remote_heads to read from a memory bufferJeff King, Feb 20, 2013
  38. 17/19 remote-curl: pass buffer straight to get_remote_headsJeff King, Feb 20, 2013
  39. 18/19 remote-curl: move ref-parsing code up in fileJeff King, Feb 20, 2013
  40. 19/19 remote-curl: always parse incoming refsJeff King, Feb 20, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.