/* libhw/generic/io.h - Device-independent I/O definitions * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #ifndef _LIBHW_GENERIC_IO_H_ #define _LIBHW_GENERIC_IO_H_ #include /* for size_t */ #include /* for ssize_t */ #include /* structs ********************************************************************/ #if __unix__ #include #else struct iovec { void *iov_base; size_t iov_len; }; #endif struct duplex_iovec { void *iov_read_dst; void *iov_write_src; size_t iov_len; }; /* basic interfaces ***********************************************************/ /** * Return bytes-read on success, 0 on EOF, -errno on error; a short * read is *not* an error. */ #define io_reader_LO_IFACE \ LO_FUNC(ssize_t, readv, const struct iovec *iov, int iovcnt) LO_INTERFACE(io_reader) #define io_readv(r, iov, iovcnt) LO_CALL(r, readv, iov, iovcnt) #define io_read(r, buf, count) LO_CALL(r, readv, &((struct iovec){.iov_base = buf, .iov_len = count}), 1) /** * Return `count` on success, -errno on error; a short write *is* an * error. * * Writes are *not* guaranteed to be atomic, so if you have concurrent * writers then you should arrange for a mutex to protect the writer. */ #define io_writer_LO_IFACE \ LO_FUNC(ssize_t, writev, const struct iovec *iov, int iovcnt) LO_INTERFACE(io_writer) #define io_writev(w, iov, iovcnt) LO_CALL(w, writev, iov, iovcnt) #define io_write(w, buf, count) LO_CALL(w, writev, &((struct iovec){.iov_base = buf, .iov_len = count}), 1) /** * Return 0 on success, -errno on error. */ #define io_closer_LO_IFACE \ LO_FUNC(int, close) LO_INTERFACE(io_closer) #define io_close(c) LO_CALL(c, close) /** * All methods return 0 on success, -errno on error. */ #define io_bidi_closer_LO_IFACE \ LO_NEST(io_closer) \ LO_FUNC(int, close_read) \ LO_FUNC(int, close_write) LO_INTERFACE(io_bidi_closer) #define io_close_read(c) LO_CALL(c, close_read) #define io_close_write(c) LO_CALL(c, close_write) /** * Return bytes-read and bytes-written on success, -errno on error; a * short read/write *is* an error. */ #define io_duplex_readwriter_LO_IFACE \ LO_FUNC(void, readwritev, const struct duplex_iovec *iov, int iovcnt) LO_INTERFACE(io_duplex_readwriter) #define io_readwritev(rw, iov, iovcnt) \ LO_CALL(rw, readwritev, iov, iovcnt) /* aggregate interfaces *******************************************************/ #define io_readwriter_LO_IFACE \ LO_NEST(io_reader) \ LO_NEST(io_writer) LO_INTERFACE(io_readwriter) #endif /* _LIBHW_GENERIC_IO_H_ */