From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by passt.top (Postfix, from userid 1000) id 50B8D5A0624; Tue, 28 Jan 2025 00:15:32 +0100 (CET) From: Stefano Brivio <sbrivio@redhat.com> To: passt-dev@passt.top Subject: [PATCH 5/7] util: Add read_remainder() and read_all_buf() Date: Tue, 28 Jan 2025 00:15:30 +0100 Message-ID: <20250127231532.672363-6-sbrivio@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250127231532.672363-1-sbrivio@redhat.com> References: <20250127231532.672363-1-sbrivio@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: VAYNYROFJX4CRV5HBNRGUM7POJJUI6PA X-Message-ID-Hash: VAYNYROFJX4CRV5HBNRGUM7POJJUI6PA X-MailFrom: sbrivio@passt.top X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Laurent Vivier <lvivier@redhat.com>, David Gibson <david@gibson.dropbear.id.au> X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt <passt-dev.passt.top> Archived-At: <https://archives.passt.top/passt-dev/20250127231532.672363-6-sbrivio@redhat.com/> Archived-At: <https://passt.top/hyperkitty/list/passt-dev@passt.top/message/VAYNYROFJX4CRV5HBNRGUM7POJJUI6PA/> List-Archive: <https://archives.passt.top/passt-dev/> List-Archive: <https://passt.top/hyperkitty/list/passt-dev@passt.top/> List-Help: <mailto:passt-dev-request@passt.top?subject=help> List-Owner: <mailto:passt-dev-owner@passt.top> List-Post: <mailto:passt-dev@passt.top> List-Subscribe: <mailto:passt-dev-join@passt.top> List-Unsubscribe: <mailto:passt-dev-leave@passt.top> These are symmetric to write_remainder() and write_all_buf() and almost a copy and paste of them, with the most notable differences being reversed reads/writes and a couple of better-safe-than-sorry asserts to keep Coverity happy. I'll use them in the next patch. At least for the moment, they're going to be used for vhost-user mode only, so I'm not unconditionally enabling readv() in the seccomp profile: the caller has to ensure it's there. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> --- util.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 2 ++ 2 files changed, 72 insertions(+) diff --git a/util.c b/util.c index 11973c4..085937b 100644 --- a/util.c +++ b/util.c @@ -606,6 +606,76 @@ int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip) return 0; } +/** + * read_all_buf() - Fill a whole buffer from a file descriptor + * @fd: File descriptor + * @buf: Pointer to base of buffer + * @len: Length of buffer + * + * Return: 0 on success, -1 on error (with errno set) + * + * #syscalls read + */ +int read_all_buf(int fd, void *buf, size_t len) +{ + size_t left = len; + char *p = buf; + + while (left) { + ssize_t rc; + + ASSERT(left <= len); + + do + rc = read(fd, p, left); + while ((rc < 0) && errno == EINTR); + + if (rc < 0) + return -1; + + p += rc; + left -= rc; + } + return 0; +} + +/** + * read_remainder() - Read the tail of an IO vector from a file descriptor + * @fd: File descriptor + * @iov: IO vector + * @cnt: Number of entries in @iov + * @skip: Number of bytes of the vector to skip reading + * + * Return: 0 on success, -1 on error (with errno set) + * + * Note: mode-specific seccomp profiles need to enable readv() to use this. + */ +int read_remainder(int fd, struct iovec *iov, size_t cnt, size_t skip) +{ + size_t i = 0, offset; + + while ((i += iov_skip_bytes(iov + i, cnt - i, skip, &offset)) < cnt) { + ssize_t rc; + + if (offset) { + ASSERT(offset < iov[i].iov_len); + /* Read the remainder of the partially read buffer */ + if (read_all_buf(fd, (char *)iov[i].iov_base + offset, + iov[i].iov_len - offset) < 0) + return -1; + i++; + } + + /* Fill as many of the remaining buffers as we can */ + rc = readv(fd, &iov[i], cnt - i); + if (rc < 0) + return -1; + + skip = rc; + } + return 0; +} + /** sockaddr_ntop() - Convert a socket address to text format * @sa: Socket address * @dst: output buffer, minimum SOCKADDR_STRLEN bytes diff --git a/util.h b/util.h index d02333d..73a7a33 100644 --- a/util.h +++ b/util.h @@ -203,6 +203,8 @@ int fls(unsigned long x); int write_file(const char *path, const char *buf); int write_all_buf(int fd, const void *buf, size_t len); int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip); +int read_all_buf(int fd, void *buf, size_t len); +int read_remainder(int fd, struct iovec *iov, size_t cnt, size_t skip); void close_open_files(int argc, char **argv); bool snprintf_check(char *str, size_t size, const char *format, ...); -- 2.43.0