aboutgitcodebugslistschat
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/util.c b/util.c
index 73c9d51..b64c29e 100644
--- a/util.c
+++ b/util.c
@@ -722,31 +722,54 @@ int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags,
* @iov: IO vector
* @iovcnt: Number of entries in @iov
* @skip: Number of bytes of the vector to skip writing
+ * @length: Maximum number of bytes of the vector to write
*
* Return: 0 on success, -1 on error (with errno set)
*
* #syscalls writev
*/
-int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip)
+int write_remainder(int fd, const struct iovec *iov, size_t iovcnt,
+ size_t skip, size_t length)
{
size_t i = 0, offset;
- while ((i += iov_skip_bytes(iov + i, iovcnt - i, skip, &offset)) < iovcnt) {
+ while (length &&
+ (i += iov_skip_bytes(iov + i, iovcnt - i, skip, &offset)) < iovcnt) {
ssize_t rc;
+ size_t end;
if (offset) {
+ size_t len = MIN(length, iov[i].iov_len - offset);
+
/* Write the remainder of the partially written buffer */
if (write_all_buf(fd, (char *)iov[i].iov_base + offset,
- iov[i].iov_len - offset) < 0)
+ len) < 0)
return -1;
+
+ length -= len;
i++;
+
+ if (!length || i >= iovcnt)
+ break;
+ }
+
+ end = iov_skip_bytes(iov + i, iovcnt - i, length, NULL);
+
+ /* Write a trailing partial buffer */
+ if (!end) {
+ size_t len = MIN(length, iov[i].iov_len);
+
+ if (write_all_buf(fd, iov[i].iov_base, len) < 0)
+ return -1;
+ break;
}
/* Write as much of the remaining whole buffers as we can */
- rc = writev(fd, &iov[i], iovcnt - i);
+ rc = writev(fd, &iov[i], end);
if (rc < 0)
return -1;
+ length -= rc;
skip = rc;
}
return 0;