From fc03b45a715c802d76b46df39ddfe481917abd73 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Thu, 11 Mar 2021 18:17:48 +0000 Subject: [PATCH] POSIX: make readv() and writev() conform to IEEE Std 1003.1-2001 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standardized version of readv() and writev() take an int as the third parameter. Arguably a size_t makes more sense, but the standardization bodies decided otherwise. The non-standard functions of readv_pos() and writev_pos() have been updated for consistency. The corresponding _kern_readv() and _kern_writev() internal functions continue to take the size_t parameter. The ABI will not change, even though on 64 bit machines the size of the count parameter will change from 8 to 4 bytes. The actual use will be slightly different. Like with the size_t argument type, it will not be possible to give a count lower than 0. If the value is less than 0, then the B_BAD_VALUE/EINVAL error will be set. Change-Id: I949c8ed67dbc0b4e209768cbdee554c929fc242e Reviewed-on: https://review.haiku-os.org/c/haiku/+/3770 Reviewed-by: Jérôme Duval --- headers/posix/sys/uio.h | 8 ++++---- headers/private/fs_shell/fssh_uio.h | 8 ++++---- src/system/boot/loader/vfs.cpp | 7 +++++-- src/system/libroot/posix/sys/uio.c | 26 ++++++++++++++++++-------- src/tools/fs_shell/uio.cpp | 16 ++++++++-------- 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/headers/posix/sys/uio.h b/headers/posix/sys/uio.h index 2e637e40f3..ff168ec7ab 100644 --- a/headers/posix/sys/uio.h +++ b/headers/posix/sys/uio.h @@ -19,10 +19,10 @@ typedef struct iovec { extern "C" { #endif -ssize_t readv(int fd, const struct iovec *vector, size_t count); -ssize_t readv_pos(int fd, off_t pos, const struct iovec *vec, size_t count); -ssize_t writev(int fd, const struct iovec *vector, size_t count); -ssize_t writev_pos(int fd, off_t pos, const struct iovec *vec, size_t count); +ssize_t readv(int fd, const struct iovec *vector, int count); +ssize_t readv_pos(int fd, off_t pos, const struct iovec *vec, int count); +ssize_t writev(int fd, const struct iovec *vector, int count); +ssize_t writev_pos(int fd, off_t pos, const struct iovec *vec, int count); #ifdef __cplusplus } diff --git a/headers/private/fs_shell/fssh_uio.h b/headers/private/fs_shell/fssh_uio.h index dc15a9d58c..d20c433702 100644 --- a/headers/private/fs_shell/fssh_uio.h +++ b/headers/private/fs_shell/fssh_uio.h @@ -20,13 +20,13 @@ extern "C" { #endif fssh_ssize_t fssh_readv(int fd, const struct fssh_iovec *vector, - fssh_size_t count); + int count); fssh_ssize_t fssh_readv_pos(int fd, fssh_off_t pos, const struct - fssh_iovec *vec, fssh_size_t count); + fssh_iovec *vec, int count); fssh_ssize_t fssh_writev(int fd, const struct fssh_iovec *vector, - fssh_size_t count); + int count); fssh_ssize_t fssh_writev_pos(int fd, fssh_off_t pos, - const struct fssh_iovec *vec, fssh_size_t count); + const struct fssh_iovec *vec, int count); #ifdef __cplusplus } diff --git a/src/system/boot/loader/vfs.cpp b/src/system/boot/loader/vfs.cpp index 4996fd159f..403878b063 100644 --- a/src/system/boot/loader/vfs.cpp +++ b/src/system/boot/loader/vfs.cpp @@ -986,11 +986,14 @@ write(int fd, const void *buffer, size_t bufferSize) ssize_t -writev(int fd, const struct iovec* vecs, size_t count) +writev(int fd, const struct iovec* vecs, int count) { size_t totalWritten = 0; - for (size_t i = 0; i < count; i++) { + if (count < 0) + RETURN_AND_SET_ERRNO(B_BAD_VALUE); + + for (int i = 0; i < count; i++) { ssize_t written = write(fd, vecs[i].iov_base, vecs[i].iov_len); if (written < 0) return totalWritten == 0 ? written : totalWritten; diff --git a/src/system/libroot/posix/sys/uio.c b/src/system/libroot/posix/sys/uio.c index 177c337608..e0364b9cbf 100644 --- a/src/system/libroot/posix/sys/uio.c +++ b/src/system/libroot/posix/sys/uio.c @@ -14,19 +14,24 @@ ssize_t -readv(int fd, const struct iovec *vecs, size_t count) +readv(int fd, const struct iovec *vecs, int count) { - ssize_t bytes = _kern_readv(fd, -1, vecs, count); + ssize_t bytes; + if (count < 0) { + __set_errno(B_BAD_VALUE); + return -1; + } + bytes = _kern_readv(fd, -1, vecs, count); RETURN_AND_SET_ERRNO(bytes); } ssize_t -readv_pos(int fd, off_t pos, const struct iovec *vecs, size_t count) +readv_pos(int fd, off_t pos, const struct iovec *vecs, int count) { ssize_t bytes; - if (pos < 0) { + if (pos < 0 || count < 0) { __set_errno(B_BAD_VALUE); return -1; } @@ -37,19 +42,24 @@ readv_pos(int fd, off_t pos, const struct iovec *vecs, size_t count) ssize_t -writev(int fd, const struct iovec *vecs, size_t count) +writev(int fd, const struct iovec *vecs, int count) { - ssize_t bytes = _kern_writev(fd, -1, vecs, count); + ssize_t bytes; + if (count < 0) { + __set_errno(B_BAD_VALUE); + return -1; + } + bytes = _kern_writev(fd, -1, vecs, count); RETURN_AND_SET_ERRNO(bytes); } ssize_t -writev_pos(int fd, off_t pos, const struct iovec *vecs, size_t count) +writev_pos(int fd, off_t pos, const struct iovec *vecs, int count) { ssize_t bytes; - if (pos < 0) { + if (pos < 0 || count < 0) { __set_errno(B_BAD_VALUE); return -1; } diff --git a/src/tools/fs_shell/uio.cpp b/src/tools/fs_shell/uio.cpp index 6dd3302791..261f2d23d1 100644 --- a/src/tools/fs_shell/uio.cpp +++ b/src/tools/fs_shell/uio.cpp @@ -19,19 +19,19 @@ #include "partition_support.h" -static const fssh_size_t kMaxIOVecs = 1024; +static const int kMaxIOVecs = 1024; bool -prepare_iovecs(const struct fssh_iovec *vecs, fssh_size_t count, +prepare_iovecs(const struct fssh_iovec *vecs, int count, struct iovec* systemVecs) { - if (count > kMaxIOVecs) { + if (count < 0 || count > kMaxIOVecs) { errno = B_BAD_VALUE; return false; } - for (fssh_size_t i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { systemVecs[i].iov_base = vecs[i].iov_base; systemVecs[i].iov_len = vecs[i].iov_len; } @@ -41,7 +41,7 @@ prepare_iovecs(const struct fssh_iovec *vecs, fssh_size_t count, fssh_ssize_t -fssh_readv(int fd, const struct fssh_iovec *vector, fssh_size_t count) +fssh_readv(int fd, const struct fssh_iovec *vector, int count) { struct iovec systemVecs[kMaxIOVecs]; if (!prepare_iovecs(vector, count, systemVecs)) @@ -62,7 +62,7 @@ fssh_readv(int fd, const struct fssh_iovec *vector, fssh_size_t count) fssh_ssize_t fssh_readv_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, - fssh_size_t count) + int count) { struct iovec systemVecs[kMaxIOVecs]; if (!prepare_iovecs(vec, count, systemVecs)) @@ -77,7 +77,7 @@ fssh_readv_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, fssh_ssize_t -fssh_writev(int fd, const struct fssh_iovec *vector, fssh_size_t count) +fssh_writev(int fd, const struct fssh_iovec *vector, int count) { struct iovec systemVecs[kMaxIOVecs]; if (!prepare_iovecs(vector, count, systemVecs)) @@ -98,7 +98,7 @@ fssh_writev(int fd, const struct fssh_iovec *vector, fssh_size_t count) fssh_ssize_t fssh_writev_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, - fssh_size_t count) + int count) { struct iovec systemVecs[kMaxIOVecs]; if (!prepare_iovecs(vec, count, systemVecs))