if (offset + dst_len > self->size)
return -1;
- if (lseek(self->fd, offset, SEEK_SET) < 0)
- return -1;
-
- if (read_in_full(self->fd, dst, dst_len) < 0)
+ if (pread_in_full(self->fd, dst, dst_len, offset) < 0)
return -1;
return 0;
if (offset + src_len > self->size)
return -1;
- if (lseek(self->fd, offset, SEEK_SET) < 0)
- return -1;
-
- if (write_in_full(self->fd, src, src_len) < 0)
+ if (pwrite_in_full(self->fd, src, src_len, offset) < 0)
return -1;
return 0;
ssize_t read_in_full(int fd, void *buf, size_t count);
ssize_t write_in_full(int fd, const void *buf, size_t count);
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset);
+
#endif /* KVM_READ_WRITE_H */
return total;
}
+
+/* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
+{
+ ssize_t nr;
+
+restart:
+ nr = pread(fd, buf, count, offset);
+ if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+ goto restart;
+
+ return nr;
+}
+
+/* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+ ssize_t nr;
+
+restart:
+ nr = pwrite(fd, buf, count, offset);
+ if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+ goto restart;
+
+ return nr;
+}
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
+{
+ ssize_t total = 0;
+ char *p = buf;
+
+ while (count > 0) {
+ ssize_t nr;
+
+ nr = xpread(fd, p, count, offset);
+ if (nr <= 0) {
+ if (total > 0)
+ return total;
+
+ return -1;
+ }
+
+ count -= nr;
+ total += nr;
+ p += nr;
+ offset += nr;
+ }
+
+ return total;
+}
+
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
+{
+ const char *p = buf;
+ ssize_t total = 0;
+
+ while (count > 0) {
+ ssize_t nr;
+
+ nr = xpwrite(fd, p, count, offset);
+ if (nr < 0)
+ return -1;
+ if (nr == 0) {
+ errno = ENOSPC;
+ return -1;
+ }
+ count -= nr;
+ total += nr;
+ p += nr;
+ offset += nr;
+ }
+
+ return total;
+}