]> git.ipfire.org Git - thirdparty/git.git/commitdiff
wrapper: introduce writev(3p) wrappers
authorPatrick Steinhardt <ps@pks.im>
Fri, 13 Mar 2026 06:45:17 +0000 (07:45 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 13 Mar 2026 15:54:14 +0000 (08:54 -0700)
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>
wrapper.c
wrapper.h
write-or-die.c
write-or-die.h

index b794fb20e71879292a3774c7b1ca6fe8dcdd7737..fa40f399b3452d5880760d7508d2117f29ce1b54 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -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;
index 15ac3bab6e974842bb1d24f093e923b34f00f8e2..27519b32d1782db10411c62ead9d066b5ff2a325 100644 (file)
--- a/wrapper.h
+++ b/wrapper.h
@@ -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));
index 01a9a51fa2fcd758b32ffc8f3e75811710804754..5f522fb7287382b22daa6fd761e916162dde7187 100644 (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)
index 65a5c42a47ac8659cd75fbf0c962a27bb73693c5..ae3d7d88b87699fb17da900c312fdb853252f5de 100644 (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.