#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; }