From: Lars Schneider <larsxschneider@xxxxxxxxx> Sometimes pkt-line data is already available in a buffer and it would be a waste of resources to write the packet using packet_write() which would copy the existing buffer into a strbuf before writing it. If the caller has control over the buffer creation then the PKTLINE_DATA_START macro can be used to skip the header and write directly into the data section of a pkt-line (PKTLINE_DATA_LEN bytes would be the maximum). direct_packet_write() would take this buffer, adjust the pkt-line header and write it. If the caller has no control over the buffer creation then direct_packet_write_data() can be used. This function creates a pkt-line header. Afterwards the header and the data buffer are written using two consecutive write calls. Both functions have a gentle parameter that indicates if Git should die in case of a write error (gentle set to 0) or return with a error (gentle set to 1). Signed-off-by: Lars Schneider <larsxschneider@xxxxxxxxx> --- pkt-line.c | 42 ++++++++++++++++++++++++++++++++++++++++++ pkt-line.h | 5 +++++ 2 files changed, 47 insertions(+) diff --git a/pkt-line.c b/pkt-line.c index 177dc73..aa158ba 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -136,6 +136,48 @@ void packet_write(int fd, const char *fmt, ...) write_or_die(fd, buf.buf, buf.len); } +int direct_packet_write(int fd, char *buf, size_t size, int gentle) +{ + int ret = 0; + if (size > LARGE_PACKET_MAX) { + if (gentle) + return 0; + else + die("protocol error: impossibly long line"); + } + packet_trace(buf + 4, size - 4, 1); + set_packet_header(buf, size); + if (gentle) + ret = !write_or_whine_pipe(fd, buf, size, "pkt-line"); + else + write_or_die(fd, buf, size); + return ret; +} + +int direct_packet_write_data(int fd, const char *data, size_t size, int gentle) +{ + int ret = 0; + char hdr[PKTLINE_HEADER_LEN]; + if (size > PKTLINE_DATA_MAXLEN) { + if (gentle) + return 0; + else + die("protocol error: impossibly long line"); + } + set_packet_header(hdr, PKTLINE_HEADER_LEN + size); + packet_trace(data, size, 1); + if (gentle) { + ret = ( + !write_or_whine_pipe(fd, hdr, PKTLINE_HEADER_LEN, "pkt-line header") || + !write_or_whine_pipe(fd, data, size, "pkt-line data") + ); + } else { + write_or_die(fd, hdr, PKTLINE_HEADER_LEN); + write_or_die(fd, data, size); + } + return ret; +} + void packet_buf_write(struct strbuf *buf, const char *fmt, ...) { va_list args; diff --git a/pkt-line.h b/pkt-line.h index 3cb9d91..ed64511 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -23,6 +23,8 @@ void packet_flush(int fd); void packet_write(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); void packet_buf_flush(struct strbuf *buf); void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +int direct_packet_write(int fd, char *buf, size_t size, int gentle); +int direct_packet_write_data(int fd, const char *data, size_t size, int gentle); /* * Read a packetized line into the buffer, which must be at least size bytes @@ -77,6 +79,9 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size); #define DEFAULT_PACKET_MAX 1000 #define LARGE_PACKET_MAX 65520 +#define PKTLINE_HEADER_LEN 4 +#define PKTLINE_DATA_START(pkt) ((pkt) + PKTLINE_HEADER_LEN) +#define PKTLINE_DATA_MAXLEN (LARGE_PACKET_MAX - PKTLINE_HEADER_LEN) extern char packet_buffer[LARGE_PACKET_MAX]; #endif -- 2.9.0 -- 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