1c4d7847bSPekka Enberg #include "kvm/read-write.h"
2c4d7847bSPekka Enberg
3c4d7847bSPekka Enberg #include <sys/types.h>
4150aa4c0SPekka Enberg #include <sys/uio.h>
5c4d7847bSPekka Enberg #include <unistd.h>
6c4d7847bSPekka Enberg #include <string.h>
7c4d7847bSPekka Enberg #include <errno.h>
8c4d7847bSPekka Enberg
9c4d7847bSPekka Enberg /* Same as read(2) except that this function never returns EAGAIN or EINTR. */
xread(int fd,void * buf,size_t count)10c4d7847bSPekka Enberg ssize_t xread(int fd, void *buf, size_t count)
11c4d7847bSPekka Enberg {
12c4d7847bSPekka Enberg ssize_t nr;
13c4d7847bSPekka Enberg
14c4d7847bSPekka Enberg restart:
15c4d7847bSPekka Enberg nr = read(fd, buf, count);
16c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
17c4d7847bSPekka Enberg goto restart;
18c4d7847bSPekka Enberg
19c4d7847bSPekka Enberg return nr;
20c4d7847bSPekka Enberg }
21c4d7847bSPekka Enberg
22c4d7847bSPekka Enberg /* Same as write(2) except that this function never returns EAGAIN or EINTR. */
xwrite(int fd,const void * buf,size_t count)23c4d7847bSPekka Enberg ssize_t xwrite(int fd, const void *buf, size_t count)
24c4d7847bSPekka Enberg {
25c4d7847bSPekka Enberg ssize_t nr;
26c4d7847bSPekka Enberg
27c4d7847bSPekka Enberg restart:
28c4d7847bSPekka Enberg nr = write(fd, buf, count);
29c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
30c4d7847bSPekka Enberg goto restart;
31c4d7847bSPekka Enberg
32c4d7847bSPekka Enberg return nr;
33c4d7847bSPekka Enberg }
34c4d7847bSPekka Enberg
35*649f9515SAndre Przywara /*
36*649f9515SAndre Przywara * Read in the whole file while not exceeding max_size bytes of the buffer.
37*649f9515SAndre Przywara * Returns -1 (with errno set) in case of an error (ENOMEM if buffer was
38*649f9515SAndre Przywara * too small) or the filesize if the whole file could be read.
39*649f9515SAndre Przywara */
read_file(int fd,char * buf,size_t max_size)40*649f9515SAndre Przywara ssize_t read_file(int fd, char *buf, size_t max_size)
41*649f9515SAndre Przywara {
42*649f9515SAndre Przywara ssize_t ret;
43*649f9515SAndre Przywara char dummy;
44*649f9515SAndre Przywara
45*649f9515SAndre Przywara errno = 0;
46*649f9515SAndre Przywara ret = read_in_full(fd, buf, max_size);
47*649f9515SAndre Przywara
48*649f9515SAndre Przywara /* Probe whether we reached EOF. */
49*649f9515SAndre Przywara if (xread(fd, &dummy, 1) == 0)
50*649f9515SAndre Przywara return ret;
51*649f9515SAndre Przywara
52*649f9515SAndre Przywara errno = ENOMEM;
53*649f9515SAndre Przywara return -1;
54*649f9515SAndre Przywara }
55*649f9515SAndre Przywara
read_in_full(int fd,void * buf,size_t count)56c4d7847bSPekka Enberg ssize_t read_in_full(int fd, void *buf, size_t count)
57c4d7847bSPekka Enberg {
58c4d7847bSPekka Enberg ssize_t total = 0;
59c4d7847bSPekka Enberg char *p = buf;
60c4d7847bSPekka Enberg
61c4d7847bSPekka Enberg while (count > 0) {
62c4d7847bSPekka Enberg ssize_t nr;
63c4d7847bSPekka Enberg
64c4d7847bSPekka Enberg nr = xread(fd, p, count);
65c4d7847bSPekka Enberg if (nr <= 0) {
66c4d7847bSPekka Enberg if (total > 0)
67c4d7847bSPekka Enberg return total;
68c4d7847bSPekka Enberg
69c4d7847bSPekka Enberg return -1;
70c4d7847bSPekka Enberg }
71c4d7847bSPekka Enberg
72c4d7847bSPekka Enberg count -= nr;
73c4d7847bSPekka Enberg total += nr;
74c4d7847bSPekka Enberg p += nr;
75c4d7847bSPekka Enberg }
76c4d7847bSPekka Enberg
77c4d7847bSPekka Enberg return total;
78c4d7847bSPekka Enberg }
79c4d7847bSPekka Enberg
write_in_full(int fd,const void * buf,size_t count)80c4d7847bSPekka Enberg ssize_t write_in_full(int fd, const void *buf, size_t count)
81c4d7847bSPekka Enberg {
82c4d7847bSPekka Enberg const char *p = buf;
83c4d7847bSPekka Enberg ssize_t total = 0;
84c4d7847bSPekka Enberg
85c4d7847bSPekka Enberg while (count > 0) {
86c4d7847bSPekka Enberg ssize_t nr;
87c4d7847bSPekka Enberg
88c4d7847bSPekka Enberg nr = xwrite(fd, p, count);
89c4d7847bSPekka Enberg if (nr < 0)
90c4d7847bSPekka Enberg return -1;
91c4d7847bSPekka Enberg if (nr == 0) {
92c4d7847bSPekka Enberg errno = ENOSPC;
93c4d7847bSPekka Enberg return -1;
94c4d7847bSPekka Enberg }
95c4d7847bSPekka Enberg count -= nr;
96c4d7847bSPekka Enberg total += nr;
97c4d7847bSPekka Enberg p += nr;
98c4d7847bSPekka Enberg }
99c4d7847bSPekka Enberg
100c4d7847bSPekka Enberg return total;
101c4d7847bSPekka Enberg }
1026b7deb02SPekka Enberg
1036b7deb02SPekka Enberg /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
xpread(int fd,void * buf,size_t count,off_t offset)1046b7deb02SPekka Enberg ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
1056b7deb02SPekka Enberg {
1066b7deb02SPekka Enberg ssize_t nr;
1076b7deb02SPekka Enberg
1086b7deb02SPekka Enberg restart:
1096b7deb02SPekka Enberg nr = pread(fd, buf, count, offset);
1106b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
1116b7deb02SPekka Enberg goto restart;
1126b7deb02SPekka Enberg
1136b7deb02SPekka Enberg return nr;
1146b7deb02SPekka Enberg }
1156b7deb02SPekka Enberg
1166b7deb02SPekka Enberg /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
xpwrite(int fd,const void * buf,size_t count,off_t offset)1176b7deb02SPekka Enberg ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
1186b7deb02SPekka Enberg {
1196b7deb02SPekka Enberg ssize_t nr;
1206b7deb02SPekka Enberg
1216b7deb02SPekka Enberg restart:
1226b7deb02SPekka Enberg nr = pwrite(fd, buf, count, offset);
1236b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
1246b7deb02SPekka Enberg goto restart;
1256b7deb02SPekka Enberg
1266b7deb02SPekka Enberg return nr;
1276b7deb02SPekka Enberg }
1286b7deb02SPekka Enberg
pread_in_full(int fd,void * buf,size_t count,off_t offset)1296b7deb02SPekka Enberg ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
1306b7deb02SPekka Enberg {
1316b7deb02SPekka Enberg ssize_t total = 0;
1326b7deb02SPekka Enberg char *p = buf;
1336b7deb02SPekka Enberg
1346b7deb02SPekka Enberg while (count > 0) {
1356b7deb02SPekka Enberg ssize_t nr;
1366b7deb02SPekka Enberg
1376b7deb02SPekka Enberg nr = xpread(fd, p, count, offset);
1386b7deb02SPekka Enberg if (nr <= 0) {
1396b7deb02SPekka Enberg if (total > 0)
1406b7deb02SPekka Enberg return total;
1416b7deb02SPekka Enberg
1426b7deb02SPekka Enberg return -1;
1436b7deb02SPekka Enberg }
1446b7deb02SPekka Enberg
1456b7deb02SPekka Enberg count -= nr;
1466b7deb02SPekka Enberg total += nr;
1476b7deb02SPekka Enberg p += nr;
1486b7deb02SPekka Enberg offset += nr;
1496b7deb02SPekka Enberg }
1506b7deb02SPekka Enberg
1516b7deb02SPekka Enberg return total;
1526b7deb02SPekka Enberg }
1536b7deb02SPekka Enberg
pwrite_in_full(int fd,const void * buf,size_t count,off_t offset)1546b7deb02SPekka Enberg ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
1556b7deb02SPekka Enberg {
1566b7deb02SPekka Enberg const char *p = buf;
1576b7deb02SPekka Enberg ssize_t total = 0;
1586b7deb02SPekka Enberg
1596b7deb02SPekka Enberg while (count > 0) {
1606b7deb02SPekka Enberg ssize_t nr;
1616b7deb02SPekka Enberg
1626b7deb02SPekka Enberg nr = xpwrite(fd, p, count, offset);
1636b7deb02SPekka Enberg if (nr < 0)
1646b7deb02SPekka Enberg return -1;
1656b7deb02SPekka Enberg if (nr == 0) {
1666b7deb02SPekka Enberg errno = ENOSPC;
1676b7deb02SPekka Enberg return -1;
1686b7deb02SPekka Enberg }
1696b7deb02SPekka Enberg count -= nr;
1706b7deb02SPekka Enberg total += nr;
1716b7deb02SPekka Enberg p += nr;
1726b7deb02SPekka Enberg offset += nr;
1736b7deb02SPekka Enberg }
1746b7deb02SPekka Enberg
1756b7deb02SPekka Enberg return total;
1766b7deb02SPekka Enberg }
1771547507fSSasha Levin
1781547507fSSasha Levin /* Same as readv(2) except that this function never returns EAGAIN or EINTR. */
xreadv(int fd,const struct iovec * iov,int iovcnt)1791547507fSSasha Levin ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt)
1801547507fSSasha Levin {
1811547507fSSasha Levin ssize_t nr;
1821547507fSSasha Levin
1831547507fSSasha Levin restart:
1841547507fSSasha Levin nr = readv(fd, iov, iovcnt);
1851547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
1861547507fSSasha Levin goto restart;
1871547507fSSasha Levin
1881547507fSSasha Levin return nr;
1891547507fSSasha Levin }
1901547507fSSasha Levin
1911547507fSSasha Levin /* Same as writev(2) except that this function never returns EAGAIN or EINTR. */
xwritev(int fd,const struct iovec * iov,int iovcnt)1921547507fSSasha Levin ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
1931547507fSSasha Levin {
1941547507fSSasha Levin ssize_t nr;
1951547507fSSasha Levin
1961547507fSSasha Levin restart:
197f42cd9ccSPekka Enberg nr = writev(fd, iov, iovcnt);
1981547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
1991547507fSSasha Levin goto restart;
2001547507fSSasha Levin
2011547507fSSasha Levin return nr;
2021547507fSSasha Levin }
2031547507fSSasha Levin
get_iov_size(const struct iovec * iov,int iovcnt)2041547507fSSasha Levin static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt)
2051547507fSSasha Levin {
2061547507fSSasha Levin size_t size = 0;
2071547507fSSasha Levin while (iovcnt--)
2081547507fSSasha Levin size += (iov++)->iov_len;
2091547507fSSasha Levin
2101547507fSSasha Levin return size;
2111547507fSSasha Levin }
2121547507fSSasha Levin
shift_iovec(const struct iovec ** iov,int * iovcnt,size_t nr,ssize_t * total,size_t * count,off_t * offset)2134c0205d0SSasha Levin static inline void shift_iovec(const struct iovec **iov, int *iovcnt,
2144c0205d0SSasha Levin size_t nr, ssize_t *total, size_t *count, off_t *offset)
2154c0205d0SSasha Levin {
2164c0205d0SSasha Levin while (nr >= (*iov)->iov_len) {
2174c0205d0SSasha Levin nr -= (*iov)->iov_len;
2184c0205d0SSasha Levin *total += (*iov)->iov_len;
2194c0205d0SSasha Levin *count -= (*iov)->iov_len;
2204c0205d0SSasha Levin if (offset)
2214c0205d0SSasha Levin *offset += (*iov)->iov_len;
2224c0205d0SSasha Levin (*iovcnt)--;
2234c0205d0SSasha Levin (*iov)++;
2244c0205d0SSasha Levin }
2254c0205d0SSasha Levin }
2264c0205d0SSasha Levin
readv_in_full(int fd,const struct iovec * iov,int iovcnt)2271547507fSSasha Levin ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt)
2281547507fSSasha Levin {
2291547507fSSasha Levin ssize_t total = 0;
2304c0205d0SSasha Levin size_t count = get_iov_size(iov, iovcnt);
2311547507fSSasha Levin
2321547507fSSasha Levin while (count > 0) {
2331547507fSSasha Levin ssize_t nr;
2341547507fSSasha Levin
2351547507fSSasha Levin nr = xreadv(fd, iov, iovcnt);
2361547507fSSasha Levin if (nr <= 0) {
2371547507fSSasha Levin if (total > 0)
2381547507fSSasha Levin return total;
2391547507fSSasha Levin
2401547507fSSasha Levin return -1;
2411547507fSSasha Levin }
2421547507fSSasha Levin
2434c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
2441547507fSSasha Levin }
2451547507fSSasha Levin
2461547507fSSasha Levin return total;
2471547507fSSasha Levin }
2481547507fSSasha Levin
writev_in_full(int fd,const struct iovec * iov,int iovcnt)2491547507fSSasha Levin ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt)
2501547507fSSasha Levin {
2511547507fSSasha Levin ssize_t total = 0;
2521547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt);
2531547507fSSasha Levin
2541547507fSSasha Levin while (count > 0) {
2551547507fSSasha Levin ssize_t nr;
2561547507fSSasha Levin
2571547507fSSasha Levin nr = xwritev(fd, iov, iovcnt);
2581547507fSSasha Levin if (nr < 0)
2591547507fSSasha Levin return -1;
2601547507fSSasha Levin if (nr == 0) {
2611547507fSSasha Levin errno = ENOSPC;
2621547507fSSasha Levin return -1;
2631547507fSSasha Levin }
2641547507fSSasha Levin
2654c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
2661547507fSSasha Levin }
2671547507fSSasha Levin
2681547507fSSasha Levin return total;
2691547507fSSasha Levin }
2701547507fSSasha Levin
2711547507fSSasha Levin /* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */
xpreadv(int fd,const struct iovec * iov,int iovcnt,off_t offset)2721547507fSSasha Levin ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
2731547507fSSasha Levin {
2741547507fSSasha Levin ssize_t nr;
2751547507fSSasha Levin
2761547507fSSasha Levin restart:
2771547507fSSasha Levin nr = preadv(fd, iov, iovcnt, offset);
2781547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
2791547507fSSasha Levin goto restart;
2801547507fSSasha Levin
2811547507fSSasha Levin return nr;
2821547507fSSasha Levin }
2831547507fSSasha Levin
2841547507fSSasha Levin /* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */
xpwritev(int fd,const struct iovec * iov,int iovcnt,off_t offset)2851547507fSSasha Levin ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
2861547507fSSasha Levin {
2871547507fSSasha Levin ssize_t nr;
2881547507fSSasha Levin
2891547507fSSasha Levin restart:
2901547507fSSasha Levin nr = pwritev(fd, iov, iovcnt, offset);
2911547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
2921547507fSSasha Levin goto restart;
2931547507fSSasha Levin
2941547507fSSasha Levin return nr;
2951547507fSSasha Levin }
2961547507fSSasha Levin
preadv_in_full(int fd,const struct iovec * iov,int iovcnt,off_t offset)2971547507fSSasha Levin ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
2981547507fSSasha Levin {
2991547507fSSasha Levin ssize_t total = 0;
3001547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt);
3011547507fSSasha Levin
3021547507fSSasha Levin while (count > 0) {
3031547507fSSasha Levin ssize_t nr;
3041547507fSSasha Levin
3051547507fSSasha Levin nr = xpreadv(fd, iov, iovcnt, offset);
3061547507fSSasha Levin if (nr <= 0) {
3071547507fSSasha Levin if (total > 0)
3081547507fSSasha Levin return total;
3091547507fSSasha Levin
3101547507fSSasha Levin return -1;
3111547507fSSasha Levin }
3121547507fSSasha Levin
3134c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
3141547507fSSasha Levin }
3151547507fSSasha Levin
3161547507fSSasha Levin return total;
3171547507fSSasha Levin }
3181547507fSSasha Levin
pwritev_in_full(int fd,const struct iovec * iov,int iovcnt,off_t offset)3191547507fSSasha Levin ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
3201547507fSSasha Levin {
3211547507fSSasha Levin ssize_t total = 0;
3221547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt);
3231547507fSSasha Levin
3241547507fSSasha Levin while (count > 0) {
3251547507fSSasha Levin ssize_t nr;
3261547507fSSasha Levin
3271547507fSSasha Levin nr = xpwritev(fd, iov, iovcnt, offset);
3281547507fSSasha Levin if (nr < 0)
3291547507fSSasha Levin return -1;
3301547507fSSasha Levin if (nr == 0) {
3311547507fSSasha Levin errno = ENOSPC;
3321547507fSSasha Levin return -1;
3331547507fSSasha Levin }
3344c0205d0SSasha Levin
3354c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
3361547507fSSasha Levin }
3371547507fSSasha Levin
3381547507fSSasha Levin return total;
3391547507fSSasha Levin }
340