unix.c (2154B)
1 #include <errno.h> 2 #include <string.h> 3 #include <sys/uio.h> 4 #include <unistd.h> 5 6 #include "debug.h" 7 #include "rcx.h" 8 #include "unix.h" 9 10 typedef isize (*IoOp)(int, void *, usize); 11 12 static int 13 perform_io(usize *n, IoOp op, int fd, void *buf, usize len) { 14 usize i = 0; 15 16 while (i < len) { 17 isize ret = op(fd, (char *)buf + i, len - i); 18 if (ret < 0) { 19 if (errno == EINTR) continue; 20 break; 21 } else if (ret == 0) { 22 errno = 0; 23 break; 24 } 25 i += ret; 26 } 27 28 if (n) *n = i; 29 return i == len ? 0 : -1; 30 } 31 32 int 33 r_read_all(usize *n, int fd, void *buf, usize len) { 34 return perform_io(n, read, fd, buf, len); 35 } 36 37 int 38 r_write_all(usize *n, int fd, void *buf, usize len) { 39 /* Cast off const-ness of buf argument from write. */ 40 return perform_io(n, (IoOp)write, fd, buf, len); 41 } 42 43 void 44 r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n) { 45 for (usize i = 0; *niov > 0; ++*iov, --*niov) { 46 usize l = MIN((*iov)->iov_len, n); 47 memcpy((char *)dst + i, (*iov)->iov_base, l); 48 (*iov)->iov_base = (char *)(*iov)->iov_base + l; 49 (*iov)->iov_len -= l; 50 i += l; 51 n -= l; 52 53 if ((*iov)->iov_len > 0) break; 54 } 55 56 ASSERT(n == 0); 57 } 58 59 /* Note for future implementation of r_readv_all: Suppose readv completely 60 * fills the first k buffers, and only partially fills the kth buffer. Then 61 * we need to record the original base pointer and length of the kth buffer, 62 * slice off the partially filled part of the kth buffer, and then call 63 * readv again with all but the first k buffers. When the kth buffer eventually 64 * becomes completely filled, restore its original base pointer and length. 65 * (Of course, at this point, some other buffer now may only be partially 66 * filled and we need to repeat this logic.) */ 67 68 int 69 r_writev_all(int fd, struct iovec **iov, usize *niov) { 70 while (*niov > 0) { 71 isize nw = writev(fd, *iov, *niov); 72 if (nw < 0) { 73 if (errno == EINTR) continue; 74 return -1; 75 } 76 77 for (; *niov > 0; ++*iov, --*niov) { 78 usize l = MIN((*iov)->iov_len, nw); 79 (*iov)->iov_base = (char *)(*iov)->iov_base + l; 80 (*iov)->iov_len -= l; 81 nw -= l; 82 83 if ((*iov)->iov_len > 0) break; 84 } 85 86 ASSERT(nw == 0); 87 } 88 89 return 0; 90 } 91