mirror of
https://passt.top/passt
synced 2025-07-28 12:18:00 +02:00
util: Add read_remainder() and read_all_buf()
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. [dgibson: make read_remainder() take const pointer to iovec] Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
71fa736277
commit
e25a93032f
2 changed files with 86 additions and 0 deletions
84
util.c
84
util.c
|
@ -606,6 +606,90 @@ int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip)
|
||||||
return 0;
|
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;
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
errno = ENODATA;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
/* cppcheck-suppress unusedFunction */
|
||||||
|
int read_remainder(int fd, const 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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt == i)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Fill as many of the remaining buffers as we can */
|
||||||
|
rc = readv(fd, &iov[i], cnt - i);
|
||||||
|
if (rc < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
errno = ENODATA;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip = rc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** sockaddr_ntop() - Convert a socket address to text format
|
/** sockaddr_ntop() - Convert a socket address to text format
|
||||||
* @sa: Socket address
|
* @sa: Socket address
|
||||||
* @dst: output buffer, minimum SOCKADDR_STRLEN bytes
|
* @dst: output buffer, minimum SOCKADDR_STRLEN bytes
|
||||||
|
|
2
util.h
2
util.h
|
@ -203,6 +203,8 @@ int fls(unsigned long x);
|
||||||
int write_file(const char *path, const char *buf);
|
int write_file(const char *path, const char *buf);
|
||||||
int write_all_buf(int fd, const void *buf, size_t len);
|
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 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, const struct iovec *iov, size_t cnt, size_t skip);
|
||||||
void close_open_files(int argc, char **argv);
|
void close_open_files(int argc, char **argv);
|
||||||
bool snprintf_check(char *str, size_t size, const char *format, ...);
|
bool snprintf_check(char *str, size_t size, const char *format, ...);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue