util: Add write_remainder() helper

We have several places where we want to write(2) a buffer or buffers and we
handle short write()s by retrying until everything is successfully written.
Add a helper for this in util.c.

This version has some differences from the typical write_all() function.
First, take an IO vector rather than a single buffer, because that will be
useful for some of our cases.  Second, allow it to take an parameter to
skip the first n bytes of the given buffers.  This will be useful for some
of the cases we want, and also falls out quite naturally from the
implementation.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[sbrivio: Minor formatting fixes in write_remainder()]
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-02-28 12:52:03 +11:00 committed by Stefano Brivio
parent 24410b37a4
commit 8bdb0883b4
2 changed files with 36 additions and 0 deletions

35
util.c
View file

@ -19,6 +19,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/ethernet.h> #include <net/ethernet.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/uio.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@ -26,6 +27,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "util.h" #include "util.h"
#include "iov.h"
#include "passt.h" #include "passt.h"
#include "packet.h" #include "packet.h"
#include "log.h" #include "log.h"
@ -574,3 +576,36 @@ int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags,
return clone(fn, stack_area + stack_size / 2, flags, arg); return clone(fn, stack_area + stack_size / 2, flags, arg);
#endif #endif
} }
/* write_remainder() - write the tail of an IO vector to an fd
* @fd: File descriptor
* @iov: IO vector
* @iovcnt: Number of entries in @iov
* @skip: Number of bytes of the vector to skip writing
*
* Return: 0 on success, -1 on error (with errno set)
*
* #syscalls write writev
*/
int write_remainder(int fd, const struct iovec *iov, int iovcnt, size_t skip)
{
int i;
while ((i = iov_skip_bytes(iov, iovcnt, skip, &skip)) < iovcnt) {
ssize_t rc;
if (skip) {
rc = write(fd, (char *)iov[i].iov_base + skip,
iov[i].iov_len - skip);
} else {
rc = writev(fd, &iov[i], iovcnt - i);
}
if (rc < 0)
return -1;
skip += rc;
}
return 0;
}

1
util.h
View file

@ -229,6 +229,7 @@ void write_pidfile(int fd, pid_t pid);
int __daemon(int pidfile_fd, int devnull_fd); int __daemon(int pidfile_fd, int devnull_fd);
int fls(unsigned long x); 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_remainder(int fd, const struct iovec *iov, int iovcnt, size_t skip);
/** /**
* mod_sub() - Modular arithmetic subtraction * mod_sub() - Modular arithmetic subtraction