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 <pclouds@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html