major stdio overhaul, using readv/writev, plus other changes
[musl] / src / stdio / __stdio_write.c
1 #include "stdio_impl.h"
2
3 size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
4 {
5         struct iovec iovs[2] = {
6                 { .iov_base = f->wbase, .iov_len = f->wpos-f->wbase },
7                 { .iov_base = (void *)buf, .iov_len = len }
8         };
9         struct iovec *iov = iovs;
10         size_t rem = iov[0].iov_len + iov[1].iov_len;
11         int iovcnt = 2;
12         ssize_t cnt;
13         f->wpos = f->wbase;
14         for (;;) {
15                 cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
16                 if (cnt == rem) return len;
17                 if (cnt < 0) {
18                         f->wpos = f->wbase = f->wend = 0;
19                         f->flags |= F_ERR;
20                         return iovcnt == 2 ? 0 : len-iov[0].iov_len;
21                 }
22                 rem -= cnt;
23                 if (cnt > iov[0].iov_len) {
24                         cnt -= iov[0].iov_len;
25                         iov++; iovcnt--;
26                 }
27                 iov[0].iov_base = (char *)iov[0].iov_base + cnt;
28                 iov[0].iov_len -= cnt;
29         }
30 }