]> git.ipfire.org Git - thirdparty/git.git/blobdiff - pkt-line.c
Merge branch 'en/ort-perf-batch-9'
[thirdparty/git.git] / pkt-line.c
index d633005ef746ad1eb7445cb75401e0c3f55a2312..0194137528c3ce909ab76f55200e2ed31ce742f7 100644 (file)
@@ -196,17 +196,26 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...)
 
 static int packet_write_gently(const int fd_out, const char *buf, size_t size)
 {
-       static char packet_write_buffer[LARGE_PACKET_MAX];
+       char header[4];
        size_t packet_size;
 
-       if (size > sizeof(packet_write_buffer) - 4)
+       if (size > LARGE_PACKET_DATA_MAX)
                return error(_("packet write failed - data exceeds max packet size"));
 
        packet_trace(buf, size, 1);
        packet_size = size + 4;
-       set_packet_header(packet_write_buffer, packet_size);
-       memcpy(packet_write_buffer + 4, buf, size);
-       if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
+
+       set_packet_header(header, packet_size);
+
+       /*
+        * Write the header and the buffer in 2 parts so that we do
+        * not need to allocate a buffer or rely on a static buffer.
+        * This also avoids putting a large buffer on the stack which
+        * might have multi-threading issues.
+        */
+
+       if (write_in_full(fd_out, header, 4) < 0 ||
+           write_in_full(fd_out, buf, size) < 0)
                return error(_("packet write failed"));
        return 0;
 }
@@ -242,26 +251,27 @@ void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len)
        packet_trace(data, len, 1);
 }
 
-int write_packetized_from_fd(int fd_in, int fd_out)
+int write_packetized_from_fd_no_flush(int fd_in, int fd_out)
 {
-       static char buf[LARGE_PACKET_DATA_MAX];
+       char *buf = xmalloc(LARGE_PACKET_DATA_MAX);
        int err = 0;
        ssize_t bytes_to_write;
 
        while (!err) {
-               bytes_to_write = xread(fd_in, buf, sizeof(buf));
-               if (bytes_to_write < 0)
+               bytes_to_write = xread(fd_in, buf, LARGE_PACKET_DATA_MAX);
+               if (bytes_to_write < 0) {
+                       free(buf);
                        return COPY_READ_ERROR;
+               }
                if (bytes_to_write == 0)
                        break;
                err = packet_write_gently(fd_out, buf, bytes_to_write);
        }
-       if (!err)
-               err = packet_flush_gently(fd_out);
+       free(buf);
        return err;
 }
 
-int write_packetized_from_buf(const char *src_in, size_t len, int fd_out)
+int write_packetized_from_buf_no_flush(const char *src_in, size_t len, int fd_out)
 {
        int err = 0;
        size_t bytes_written = 0;
@@ -277,8 +287,6 @@ int write_packetized_from_buf(const char *src_in, size_t len, int fd_out)
                err = packet_write_gently(fd_out, src_in + bytes_written, bytes_to_write);
                bytes_written += bytes_to_write;
        }
-       if (!err)
-               err = packet_flush_gently(fd_out);
        return err;
 }
 
@@ -298,8 +306,11 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
                *src_size -= ret;
        } else {
                ret = read_in_full(fd, dst, size);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
+                               return error_errno(_("read error"));
                        die_errno(_("read error"));
+               }
        }
 
        /* And complain if we didn't get enough bytes to satisfy the read. */
@@ -307,6 +318,8 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
                if (options & PACKET_READ_GENTLE_ON_EOF)
                        return -1;
 
+               if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
+                       return error(_("the remote end hung up unexpectedly"));
                die(_("the remote end hung up unexpectedly"));
        }
 
@@ -335,6 +348,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
        len = packet_length(linelen);
 
        if (len < 0) {
+               if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
+                       return error(_("protocol error: bad line length "
+                                      "character: %.4s"), linelen);
                die(_("protocol error: bad line length character: %.4s"), linelen);
        } else if (!len) {
                packet_trace("0000", 4, 0);
@@ -349,12 +365,19 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
                *pktlen = 0;
                return PACKET_READ_RESPONSE_END;
        } else if (len < 4) {
+               if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
+                       return error(_("protocol error: bad line length %d"),
+                                    len);
                die(_("protocol error: bad line length %d"), len);
        }
 
        len -= 4;
-       if ((unsigned)len >= size)
+       if ((unsigned)len >= size) {
+               if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
+                       return error(_("protocol error: bad line length %d"),
+                                    len);
                die(_("protocol error: bad line length %d"), len);
+       }
 
        if (get_packet_data(fd, src_buffer, src_len, buffer, len, options) < 0) {
                *pktlen = -1;
@@ -421,7 +444,7 @@ 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);
 }
 
-ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
+ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out, int options)
 {
        int packet_len;
 
@@ -437,7 +460,7 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
                         * that there is already room for the extra byte.
                         */
                        sb_out->buf + sb_out->len, LARGE_PACKET_DATA_MAX+1,
-                       PACKET_READ_GENTLE_ON_EOF);
+                       options);
                if (packet_len <= 0)
                        break;
                sb_out->len += packet_len;