rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

commit c0ac5a44102417bc091976e713435e92550034c3
parent 71d8b53e71761d15fe2cc6f06797872bcd4c9b35
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Sat, 14 Jan 2023 12:53:49 -0800

Improve unix.h docs; handle EOF for read_all

Diffstat:
Minc/rcx/unix.h | 29++++++++++++++++-------------
Msrc/unix.c | 29++++++++++++++---------------
2 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/inc/rcx/unix.h b/inc/rcx/unix.h @@ -4,28 +4,31 @@ #include "rcx/def.h" -/* Read exactly len bytes from fd into buf and return 0 on success. On failure - * (any error except EINTR), return -1 and set errno in the same manner as - * read(2). In either case, if n is not NULL, set *n to the number of bytes - * actually read (which is less than len iff an error occurred). */ +/* On success, read exactly len bytes from fd into buf and return 0. On failure + * (i.e., any error except EINTR, or EOF before len bytes are read into buf), + * return -1 and set errno in the same manner as read(2), or set errno to 0 in + * the case of premature EOF. In either case, if n is not NULL, set *n to the + * number of bytes actually read (which is less than len iff an error or + * premature EOF occurred). */ int r_read_all(usize *n, int fd, void *buf, usize len); -/* Write exactly len bytes from buf to fd and return 0 on success. On failure - * (any error except EINTR), return -1 and set errno in the same manner as +/* On success, write exactly len bytes from buf to fd and return 0. On failure + * (i.e, any error except EINTR), return -1 and set errno in the same manner as * write(2). In either case, if n is not NULL, set *n to the number of bytes * actually written (which is less than len iff an error occurred). */ int r_write_all(usize *n, int fd, void *buf, usize len); -/* Copy n bytes from (*src, *niov) to dst. Increment the base pointer and +/* Copy n bytes from (*iov, *niov) to dst. Increment the base pointer and * decrement the length in each iovec according to the number of bytes copied. - * If there are fewer than n bytes in (*src, *niov), behaviour is undefined. */ -void r_iovec_gather(void *dst, struct iovec **src, usize *niov, usize n); + * There must be at least n bytes in (*iov, *niov). */ +void r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n); /* TODO */ /* int r_readv_all(int fd, struct iovec **iov, usize *niov); */ -/* Write all bytes from (*iov, *niov) to fd and return 0 on succes. On failure - * (any error except EINTR), return -1 and set errno in the same manner as - * writev(2). Increment the base pointer and decrement the length in each iovec - * according to the number of bytes actually written. */ +/* On success, write all bytes from (*iov, *niov) to fd and return 0. On + * failure (i.e., any error except EINTR), return -1 and set errno in the same + * manner as writev(2). In either case, increment the base pointer and + * decrement the length in each iovec according to the number of bytes actually + * written. */ int r_writev_all(int fd, struct iovec **iov, usize *niov); diff --git a/src/unix.c b/src/unix.c @@ -8,19 +8,21 @@ typedef isize (*IoOp)(int, void *, usize); -// TODO: handle ret == 0 and do-while -> while static int perform_io(usize *n, IoOp op, int fd, void *buf, usize len) { usize i = 0; - do { + while (i < len) { isize ret = op(fd, (char *)buf + i, len - i); if (ret < 0) { if (errno == EINTR) continue; break; + } else if (ret == 0) { + errno = 0; + break; } i += ret; - } while (i < len); + } if (n) *n = i; return i == len ? 0 : -1; @@ -38,22 +40,19 @@ r_write_all(usize *n, int fd, void *buf, usize len) { } void -r_iovec_gather(void *dst, struct iovec **src, usize *niov, usize n) { - if (n == 0) return; - - for (usize i = 0;;) { - assert(*niov > 0); - - usize l = MIN((*src)->iov_len, n); - memcpy((char *)dst + i, (*src)->iov_base, l); - (*src)->iov_base = (char *)(*src)->iov_base + l; - (*src)->iov_len -= l; +r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n) { + for (usize i = 0; *niov > 0; ++*iov, --*niov) { + usize l = MIN((*iov)->iov_len, n); + memcpy((char *)dst + i, (*iov)->iov_base, l); + (*iov)->iov_base = (char *)(*iov)->iov_base + l; + (*iov)->iov_len -= l; i += l; n -= l; - if (n == 0) break; - ++*src, --*niov; + if ((*iov)->iov_len > 0) break; } + + assert(n == 0); } /* Note for future implementation of r_readv_all: Suppose readv completely