@@ -40,4 +40,6 @@ int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec
off_t offset, int ev, void *param);
#endif
+int pseek(int fd, off_t offset);
+
#endif /* KVM_READ_WRITE_H */
@@ -352,3 +352,43 @@ restart:
return ret;
}
#endif
+
+/*
+ * A wrapper around lseek(fd, offset, SEEK_CUR), which can cope with being
+ * used on non-seekable file descriptors like pipes or sockets. If offset
+ * is positive, it will skip over the requested number of bytes by reading
+ * them into a dummy buffer.
+ */
+#define BUF_SIZE 256
+int pseek(int fd, off_t offset)
+{
+ off_t ret;
+ int to_read;
+ char skip_buf[BUF_SIZE];
+
+ ret = lseek(fd, offset, SEEK_CUR);
+ if (ret != (off_t)-1)
+ return 0;
+
+ if (errno != ESPIPE)
+ return -1;
+
+ if (offset < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ while (offset > 0) {
+ to_read = offset > BUF_SIZE ? BUF_SIZE : offset;
+ ret = read(fd, skip_buf, to_read);
+ if (ret == -1 && errno != EINTR)
+ return -1;
+ if (ret == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ offset -= ret;
+ }
+
+ return 0;
+}
pseek is a wrapper around lseek(2), which can cope with non-seekable file descriptors. The limitation is of course that we only can seek forward and only relative to the current position (hence the whence parameter is missing). In this case pseek will do dummy reads to skip over the requested amount of data. Signed-off-by: Andre Przywara <andre.przywara@arm.com> --- include/kvm/read-write.h | 2 ++ util/read-write.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)