This version is also gentler than its friend packet_read_line()
because it's designed for side channel I/O that should not abort the
program even if the channel is broken.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 cache.h    |  1 +
 pkt-line.c | 35 +++++++++++++++++++++++++++++++++++
 pkt-line.h |  1 +
 wrapper.c  | 21 +++++++++++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/cache.h b/cache.h
index 718e32b..939db46 100644
--- a/cache.h
+++ b/cache.h
@@ -1230,6 +1230,7 @@ extern int write_or_whine_pipe(int fd, const void *buf, 
size_t count, const char
 extern void fsync_or_die(int fd, const char *);
 
 extern ssize_t read_in_full(int fd, void *buf, size_t count);
+extern ssize_t read_in_full_timeout(int fd, void *buf, size_t count, int 
timeout);
 extern ssize_t write_in_full(int fd, const void *buf, size_t count);
 extern ssize_t write_in_full_timeout(int fd, const void *buf, size_t count, 
int timeout);
 static inline ssize_t write_str_in_full(int fd, const char *str)
diff --git a/pkt-line.c b/pkt-line.c
index cf681e9..5a07e97 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -229,3 +229,38 @@ char *packet_read_line_buf(char **src, size_t *src_len, 
int *dst_len)
 {
        return packet_read_line_generic(-1, src, src_len, dst_len);
 }
+
+char *packet_read_line_timeout(int fd, int timeout, int *len_p)
+{
+       char *buf = packet_buffer;
+       int ret, len, buf_len = sizeof(packet_buffer);
+       char linelen[4];
+
+       if (fd == -1)
+               return NULL;
+       if ((ret = read_in_full_timeout(fd, linelen, 4, timeout)) < 0)
+               return NULL;
+       len = packet_length(linelen);
+       if (len < 0) {
+               error("protocol error: bad line length character: %.4s", 
linelen);
+               return NULL;
+       }
+       if (!len) {
+               packet_trace("0000", 4, 0);
+               if (len_p)
+                       *len_p = 0;
+               return "";
+       }
+       len -= 4;
+       if (len >= buf_len) {
+               error("protocol error: bad line length %d", len);
+               return NULL;
+       }
+       if ((ret = read_in_full_timeout(fd, buf, len, timeout)) < 0)
+               return NULL;
+       buf[len] = '\0';
+       if (len_p)
+               *len_p = len;
+       packet_trace(buf, len, 0);
+       return buf;
+}
diff --git a/pkt-line.h b/pkt-line.h
index 4b93a0c..d47dca5 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -69,6 +69,7 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, 
char
  * packet is written to it.
  */
 char *packet_read_line(int fd, int *size);
+char *packet_read_line_timeout(int fd, int timeout, int *size);
 
 /*
  * Same as packet_read_line, but read from a buf rather than a descriptor;
diff --git a/wrapper.c b/wrapper.c
index 9a0e289..9cf10b2 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -193,6 +193,27 @@ ssize_t read_in_full(int fd, void *buf, size_t count)
        return total;
 }
 
+ssize_t read_in_full_timeout(int fd, void *buf, size_t count, int timeout)
+{
+       char *p = buf;
+       ssize_t total = 0;
+       struct pollfd pfd;
+
+       pfd.fd = fd;
+       pfd.events = POLLIN;
+       while (count > 0 && poll(&pfd, 1, timeout) > 0 &&
+              (pfd.revents & POLLIN)) {
+               ssize_t loaded = xread(fd, p, count);
+               if (loaded <= 0)
+                       return -1;
+               count -= loaded;
+               p += loaded;
+               total += loaded;
+       }
+
+       return count ? -1 : total;
+}
+
 ssize_t write_in_full(int fd, const void *buf, size_t count)
 {
        const char *p = buf;
-- 
1.8.5.2.240.g8478abd

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to