mirror of
https://github.com/git/git.git
synced 2026-08-09 01:21:47 +00:00
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 Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
42 lines
1.0 KiB
C
42 lines
1.0 KiB
C
#include "../git-compat-util.h"
|
|
#include "../wrapper.h"
|
|
|
|
ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
|
|
{
|
|
size_t sum = 0;
|
|
|
|
if (iovcnt <= 0) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* According to writev(3p), the syscall shall error with EINVAL in case
|
|
* the sum of `iov_len` overflows `ssize_t`.
|
|
*/
|
|
for (int i = 0; i < iovcnt; i++) {
|
|
if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) ||
|
|
unsigned_add_overflows(iov[i].iov_len, sum) ||
|
|
iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
sum += iov[i].iov_len;
|
|
}
|
|
|
|
/*
|
|
* We only ever write the first non-empty vector so that we can
|
|
* guarantee the call to be non-interleaving as guaranteed by POSIX.
|
|
* This works just fine as callers have to loop around writev anyway.
|
|
*/
|
|
for (int i = 0; i < iovcnt; i++) {
|
|
if (!iov[i].iov_len)
|
|
continue;
|
|
return xwrite(fd, iov[i].iov_base, iov[i].iov_len);
|
|
}
|
|
|
|
/* When all iovec members were zero we ought to return 0 according to POSIX. */
|
|
return 0;
|
|
}
|