Skip to content

Commit 1970fce

Browse files
pks-tgitster
authored andcommitted
wrapper: introduce writev(3p) wrappers
In the preceding commit we have added a compatibility wrapper for the writev(3p) syscall. Introduce some generic wrappers for this function that we nowadays take for granted in the Git codebase. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3b9b2c2 commit 1970fce

4 files changed

Lines changed: 59 additions & 0 deletions

File tree

wrapper.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,47 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
323323
return total;
324324
}
325325

326+
ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt)
327+
{
328+
ssize_t total_written = 0;
329+
330+
while (iovcnt) {
331+
ssize_t bytes_written = writev(fd, iov, iovcnt);
332+
if (bytes_written < 0) {
333+
if (errno == EINTR || errno == EAGAIN)
334+
continue;
335+
return -1;
336+
}
337+
if (!bytes_written) {
338+
errno = ENOSPC;
339+
return -1;
340+
}
341+
342+
total_written += bytes_written;
343+
344+
/*
345+
* We first need to discard any iovec entities that have been
346+
* fully written.
347+
*/
348+
while (iovcnt && (size_t)bytes_written >= iov->iov_len) {
349+
bytes_written -= iov->iov_len;
350+
iov++;
351+
iovcnt--;
352+
}
353+
354+
/*
355+
* Finally, we need to adjust the last iovec in case we have
356+
* performed a partial write.
357+
*/
358+
if (iovcnt && bytes_written) {
359+
iov->iov_base = (char *) iov->iov_base + bytes_written;
360+
iov->iov_len -= bytes_written;
361+
}
362+
}
363+
364+
return total_written;
365+
}
366+
326367
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
327368
{
328369
char *p = buf;

wrapper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ ssize_t read_in_full(int fd, void *buf, size_t count);
4747
ssize_t write_in_full(int fd, const void *buf, size_t count);
4848
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
4949

50+
/*
51+
* Try to write all iovecs. Returns -1 in case an error occurred with a proper
52+
* errno set, the number of bytes written otherwise.
53+
*
54+
* Note that the iovec will be modified as a result of this call to adjust for
55+
* partial writes!
56+
*/
57+
ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt);
58+
5059
static inline ssize_t write_str_in_full(int fd, const char *str)
5160
{
5261
return write_in_full(fd, str, strlen(str));

write-or-die.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ void write_or_die(int fd, const void *buf, size_t count)
9696
}
9797
}
9898

99+
void writev_or_die(int fd, struct iovec *iov, int iovlen)
100+
{
101+
if (writev_in_full(fd, iov, iovlen) < 0) {
102+
check_pipe(errno);
103+
die_errno("writev error");
104+
}
105+
}
106+
99107
void fwrite_or_die(FILE *f, const void *buf, size_t count)
100108
{
101109
if (fwrite(buf, 1, count, f) != count)

write-or-die.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ void fprintf_or_die(FILE *, const char *fmt, ...);
77
void fwrite_or_die(FILE *f, const void *buf, size_t count);
88
void fflush_or_die(FILE *f);
99
void write_or_die(int fd, const void *buf, size_t count);
10+
void writev_or_die(int fd, struct iovec *iov, int iovlen);
1011

1112
/*
1213
* These values are used to help identify parts of a repository to fsync.

0 commit comments

Comments
 (0)