Raw
1 #include "../git-compat-util.h"
2 #include "../wrapper.h"
3
4 ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
5 {
6 size_t total_written = 0;
7 size_t sum = 0;
8
9 /*
10 * According to writev(3p), the syscall shall error with EINVAL in case
11 * the sum of `iov_len` overflows `ssize_t`.
12 */
13 for (int i = 0; i < iovcnt; i++) {
14 if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) ||
15 iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) {
16 errno = EINVAL;
17 return -1;
18 }
19
20 sum += iov[i].iov_len;
21 }
22
23 for (int i = 0; i < iovcnt; i++) {
24 const char *bytes = iov[i].iov_base;
25 size_t iovec_written = 0;
26
27 while (iovec_written < iov[i].iov_len) {
28 ssize_t bytes_written = xwrite(fd, bytes + iovec_written,
29 iov[i].iov_len - iovec_written);
30 if (bytes_written < 0) {
31 if (total_written)
32 goto out;
33 return bytes_written;
34 }
35 if (!bytes_written)
36 goto out;
37 iovec_written += bytes_written;
38 total_written += bytes_written;
39 }
40 }
41
42 out:
43 return (ssize_t) total_written;
44 }