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>
This commit is contained in:
Patrick Steinhardt
2026-03-03 16:00:21 +01:00
committed by Junio C Hamano
parent 50869da7e6
commit 0b2112ccfc
4 changed files with 59 additions and 0 deletions

View File

@@ -323,6 +323,47 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
return total;
}
ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt)
{
ssize_t total_written = 0;
while (iovcnt) {
ssize_t bytes_written = writev(fd, iov, iovcnt);
if (bytes_written < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return -1;
}
if (!bytes_written) {
errno = ENOSPC;
return -1;
}
total_written += bytes_written;
/*
* We first need to discard any iovec entities that have been
* fully written.
*/
while (iovcnt && (size_t)bytes_written >= iov->iov_len) {
bytes_written -= iov->iov_len;
iov++;
iovcnt--;
}
/*
* Finally, we need to adjust the last iovec in case we have
* performed a partial write.
*/
if (iovcnt && bytes_written) {
iov->iov_base = (char *) iov->iov_base + bytes_written;
iov->iov_len -= bytes_written;
}
}
return total_written;
}
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
{
char *p = buf;

View File

@@ -47,6 +47,15 @@ ssize_t read_in_full(int fd, void *buf, size_t count);
ssize_t write_in_full(int fd, const void *buf, size_t count);
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
/*
* Try to write all iovecs. Returns -1 in case an error occurred with a proper
* errno set, the number of bytes written otherwise.
*
* Note that the iovec will be modified as a result of this call to adjust for
* partial writes!
*/
ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt);
static inline ssize_t write_str_in_full(int fd, const char *str)
{
return write_in_full(fd, str, strlen(str));

View File

@@ -96,6 +96,14 @@ void write_or_die(int fd, const void *buf, size_t count)
}
}
void writev_or_die(int fd, struct iovec *iov, int iovlen)
{
if (writev_in_full(fd, iov, iovlen) < 0) {
check_pipe(errno);
die_errno("writev error");
}
}
void fwrite_or_die(FILE *f, const void *buf, size_t count)
{
if (fwrite(buf, 1, count, f) != count)

View File

@@ -7,6 +7,7 @@ void fprintf_or_die(FILE *, const char *fmt, ...);
void fwrite_or_die(FILE *f, const void *buf, size_t count);
void fflush_or_die(FILE *f);
void write_or_die(int fd, const void *buf, size_t count);
void writev_or_die(int fd, struct iovec *iov, int iovlen);
/*
* These values are used to help identify parts of a repository to fsync.