compat/posix: introduce writev(3p) wrapper

In a subsequent commit we're going to add the first caller to
writev(3p). Introduce a compatibility wrapper for this syscall that we
can use on systems that don't have this syscall.

The syscall exists on modern Unixes like Linux and macOS, and seemingly
even for NonStop according to [1]. It doesn't seem to exist on Windows
though.

[1]: http://nonstoptools.com/manuals/OSS-SystemCalls.pdf
[2]: https://www.gnu.org/software/gnulib/manual/html_node/writev.html

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:20 +01:00
committed by Junio C Hamano
parent a677fed600
commit 50869da7e6
5 changed files with 50 additions and 0 deletions

View File

@@ -2015,6 +2015,10 @@ ifdef NO_PREAD
COMPAT_CFLAGS += -DNO_PREAD
COMPAT_OBJS += compat/pread.o
endif
ifdef NO_WRITEV
COMPAT_CFLAGS += -DNO_WRITEV
COMPAT_OBJS += compat/writev.o
endif
ifdef NO_FAST_WORKING_DIRECTORY
BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
endif

View File

@@ -137,6 +137,9 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/statvfs.h>
#ifndef NO_WRITEV
#include <sys/uio.h>
#endif
#include <termios.h>
#ifndef NO_SYS_SELECT_H
#include <sys/select.h>
@@ -323,6 +326,17 @@ int git_lstat(const char *, struct stat *);
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
#endif
#ifdef NO_WRITEV
#define writev git_writev
#define iovec git_iovec
struct git_iovec {
void *iov_base;
size_t iov_len;
};
ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt);
#endif
#ifdef NO_SETENV
#define setenv gitsetenv
int gitsetenv(const char *, const char *, int);

29
compat/writev.c Normal file
View File

@@ -0,0 +1,29 @@
#include "../git-compat-util.h"
#include "../wrapper.h"
ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
{
size_t total_written = 0;
for (int i = 0; i < iovcnt; i++) {
const char *bytes = iov[i].iov_base;
size_t iovec_written = 0;
while (iovec_written < iov[i].iov_len) {
ssize_t bytes_written = xwrite(fd, bytes + iovec_written,
iov[i].iov_len - iovec_written);
if (bytes_written < 0) {
if (total_written)
goto out;
return bytes_written;
}
if (!bytes_written)
goto out;
iovec_written += bytes_written;
total_written += bytes_written;
}
}
out:
return cast_size_t_to_ssize_t(total_written);
}

View File

@@ -457,6 +457,7 @@ ifeq ($(uname_S),Windows)
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
HAVE_ALLOCA_H = YesPlease
NO_PREAD = YesPlease
NO_WRITEV = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
NO_LIBGEN_H = YesPlease
NO_POLL = YesPlease
@@ -672,6 +673,7 @@ ifeq ($(uname_S),MINGW)
pathsep = ;
HAVE_ALLOCA_H = YesPlease
NO_PREAD = YesPlease
NO_WRITEV = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
NO_LIBGEN_H = YesPlease
NO_POLL = YesPlease

View File

@@ -1405,6 +1405,7 @@ checkfuncs = {
'initgroups' : [],
'strtoumax' : ['strtoumax.c', 'strtoimax.c'],
'pread' : ['pread.c'],
'writev' : ['writev.c'],
}
if host_machine.system() == 'windows'