1c4d7847bSPekka Enberg #include "kvm/read-write.h" 2c4d7847bSPekka Enberg 3c4d7847bSPekka Enberg #include <sys/types.h> 4c4d7847bSPekka Enberg #include <unistd.h> 5c4d7847bSPekka Enberg #include <string.h> 6c4d7847bSPekka Enberg #include <errno.h> 7c4d7847bSPekka Enberg 8c4d7847bSPekka Enberg /* Same as read(2) except that this function never returns EAGAIN or EINTR. */ 9c4d7847bSPekka Enberg ssize_t xread(int fd, void *buf, size_t count) 10c4d7847bSPekka Enberg { 11c4d7847bSPekka Enberg ssize_t nr; 12c4d7847bSPekka Enberg 13c4d7847bSPekka Enberg restart: 14c4d7847bSPekka Enberg nr = read(fd, buf, count); 15c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 16c4d7847bSPekka Enberg goto restart; 17c4d7847bSPekka Enberg 18c4d7847bSPekka Enberg return nr; 19c4d7847bSPekka Enberg } 20c4d7847bSPekka Enberg 21c4d7847bSPekka Enberg /* Same as write(2) except that this function never returns EAGAIN or EINTR. */ 22c4d7847bSPekka Enberg ssize_t xwrite(int fd, const void *buf, size_t count) 23c4d7847bSPekka Enberg { 24c4d7847bSPekka Enberg ssize_t nr; 25c4d7847bSPekka Enberg 26c4d7847bSPekka Enberg restart: 27c4d7847bSPekka Enberg nr = write(fd, buf, count); 28c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 29c4d7847bSPekka Enberg goto restart; 30c4d7847bSPekka Enberg 31c4d7847bSPekka Enberg return nr; 32c4d7847bSPekka Enberg } 33c4d7847bSPekka Enberg 34c4d7847bSPekka Enberg ssize_t read_in_full(int fd, void *buf, size_t count) 35c4d7847bSPekka Enberg { 36c4d7847bSPekka Enberg ssize_t total = 0; 37c4d7847bSPekka Enberg char *p = buf; 38c4d7847bSPekka Enberg 39c4d7847bSPekka Enberg while (count > 0) { 40c4d7847bSPekka Enberg ssize_t nr; 41c4d7847bSPekka Enberg 42c4d7847bSPekka Enberg nr = xread(fd, p, count); 43c4d7847bSPekka Enberg if (nr <= 0) { 44c4d7847bSPekka Enberg if (total > 0) 45c4d7847bSPekka Enberg return total; 46c4d7847bSPekka Enberg 47c4d7847bSPekka Enberg return -1; 48c4d7847bSPekka Enberg } 49c4d7847bSPekka Enberg 50c4d7847bSPekka Enberg count -= nr; 51c4d7847bSPekka Enberg total += nr; 52c4d7847bSPekka Enberg p += nr; 53c4d7847bSPekka Enberg } 54c4d7847bSPekka Enberg 55c4d7847bSPekka Enberg return total; 56c4d7847bSPekka Enberg } 57c4d7847bSPekka Enberg 58c4d7847bSPekka Enberg ssize_t write_in_full(int fd, const void *buf, size_t count) 59c4d7847bSPekka Enberg { 60c4d7847bSPekka Enberg const char *p = buf; 61c4d7847bSPekka Enberg ssize_t total = 0; 62c4d7847bSPekka Enberg 63c4d7847bSPekka Enberg while (count > 0) { 64c4d7847bSPekka Enberg ssize_t nr; 65c4d7847bSPekka Enberg 66c4d7847bSPekka Enberg nr = xwrite(fd, p, count); 67c4d7847bSPekka Enberg if (nr < 0) 68c4d7847bSPekka Enberg return -1; 69c4d7847bSPekka Enberg if (nr == 0) { 70c4d7847bSPekka Enberg errno = ENOSPC; 71c4d7847bSPekka Enberg return -1; 72c4d7847bSPekka Enberg } 73c4d7847bSPekka Enberg count -= nr; 74c4d7847bSPekka Enberg total += nr; 75c4d7847bSPekka Enberg p += nr; 76c4d7847bSPekka Enberg } 77c4d7847bSPekka Enberg 78c4d7847bSPekka Enberg return total; 79c4d7847bSPekka Enberg } 806b7deb02SPekka Enberg 816b7deb02SPekka Enberg /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */ 826b7deb02SPekka Enberg ssize_t xpread(int fd, void *buf, size_t count, off_t offset) 836b7deb02SPekka Enberg { 846b7deb02SPekka Enberg ssize_t nr; 856b7deb02SPekka Enberg 866b7deb02SPekka Enberg restart: 876b7deb02SPekka Enberg nr = pread(fd, buf, count, offset); 886b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 896b7deb02SPekka Enberg goto restart; 906b7deb02SPekka Enberg 916b7deb02SPekka Enberg return nr; 926b7deb02SPekka Enberg } 936b7deb02SPekka Enberg 946b7deb02SPekka Enberg /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */ 956b7deb02SPekka Enberg ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) 966b7deb02SPekka Enberg { 976b7deb02SPekka Enberg ssize_t nr; 986b7deb02SPekka Enberg 996b7deb02SPekka Enberg restart: 1006b7deb02SPekka Enberg nr = pwrite(fd, buf, count, offset); 1016b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1026b7deb02SPekka Enberg goto restart; 1036b7deb02SPekka Enberg 1046b7deb02SPekka Enberg return nr; 1056b7deb02SPekka Enberg } 1066b7deb02SPekka Enberg 1076b7deb02SPekka Enberg ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset) 1086b7deb02SPekka Enberg { 1096b7deb02SPekka Enberg ssize_t total = 0; 1106b7deb02SPekka Enberg char *p = buf; 1116b7deb02SPekka Enberg 1126b7deb02SPekka Enberg while (count > 0) { 1136b7deb02SPekka Enberg ssize_t nr; 1146b7deb02SPekka Enberg 1156b7deb02SPekka Enberg nr = xpread(fd, p, count, offset); 1166b7deb02SPekka Enberg if (nr <= 0) { 1176b7deb02SPekka Enberg if (total > 0) 1186b7deb02SPekka Enberg return total; 1196b7deb02SPekka Enberg 1206b7deb02SPekka Enberg return -1; 1216b7deb02SPekka Enberg } 1226b7deb02SPekka Enberg 1236b7deb02SPekka Enberg count -= nr; 1246b7deb02SPekka Enberg total += nr; 1256b7deb02SPekka Enberg p += nr; 1266b7deb02SPekka Enberg offset += nr; 1276b7deb02SPekka Enberg } 1286b7deb02SPekka Enberg 1296b7deb02SPekka Enberg return total; 1306b7deb02SPekka Enberg } 1316b7deb02SPekka Enberg 1326b7deb02SPekka Enberg ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset) 1336b7deb02SPekka Enberg { 1346b7deb02SPekka Enberg const char *p = buf; 1356b7deb02SPekka Enberg ssize_t total = 0; 1366b7deb02SPekka Enberg 1376b7deb02SPekka Enberg while (count > 0) { 1386b7deb02SPekka Enberg ssize_t nr; 1396b7deb02SPekka Enberg 1406b7deb02SPekka Enberg nr = xpwrite(fd, p, count, offset); 1416b7deb02SPekka Enberg if (nr < 0) 1426b7deb02SPekka Enberg return -1; 1436b7deb02SPekka Enberg if (nr == 0) { 1446b7deb02SPekka Enberg errno = ENOSPC; 1456b7deb02SPekka Enberg return -1; 1466b7deb02SPekka Enberg } 1476b7deb02SPekka Enberg count -= nr; 1486b7deb02SPekka Enberg total += nr; 1496b7deb02SPekka Enberg p += nr; 1506b7deb02SPekka Enberg offset += nr; 1516b7deb02SPekka Enberg } 1526b7deb02SPekka Enberg 1536b7deb02SPekka Enberg return total; 1546b7deb02SPekka Enberg } 1551547507fSSasha Levin 1561547507fSSasha Levin /* Same as readv(2) except that this function never returns EAGAIN or EINTR. */ 1571547507fSSasha Levin ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt) 1581547507fSSasha Levin { 1591547507fSSasha Levin ssize_t nr; 1601547507fSSasha Levin 1611547507fSSasha Levin restart: 1621547507fSSasha Levin nr = readv(fd, iov, iovcnt); 1631547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1641547507fSSasha Levin goto restart; 1651547507fSSasha Levin 1661547507fSSasha Levin return nr; 1671547507fSSasha Levin } 1681547507fSSasha Levin 1691547507fSSasha Levin /* Same as writev(2) except that this function never returns EAGAIN or EINTR. */ 1701547507fSSasha Levin ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt) 1711547507fSSasha Levin { 1721547507fSSasha Levin ssize_t nr; 1731547507fSSasha Levin 1741547507fSSasha Levin restart: 1751547507fSSasha Levin nr = write(fd, iov, iovcnt); 1761547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1771547507fSSasha Levin goto restart; 1781547507fSSasha Levin 1791547507fSSasha Levin return nr; 1801547507fSSasha Levin } 1811547507fSSasha Levin 1821547507fSSasha Levin static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt) 1831547507fSSasha Levin { 1841547507fSSasha Levin size_t size = 0; 1851547507fSSasha Levin while (iovcnt--) 1861547507fSSasha Levin size += (iov++)->iov_len; 1871547507fSSasha Levin 1881547507fSSasha Levin return size; 1891547507fSSasha Levin } 1901547507fSSasha Levin 191*4c0205d0SSasha Levin static inline void shift_iovec(const struct iovec **iov, int *iovcnt, 192*4c0205d0SSasha Levin size_t nr, ssize_t *total, size_t *count, off_t *offset) 193*4c0205d0SSasha Levin { 194*4c0205d0SSasha Levin while (nr >= (*iov)->iov_len) { 195*4c0205d0SSasha Levin nr -= (*iov)->iov_len; 196*4c0205d0SSasha Levin *total += (*iov)->iov_len; 197*4c0205d0SSasha Levin *count -= (*iov)->iov_len; 198*4c0205d0SSasha Levin if (offset) 199*4c0205d0SSasha Levin *offset += (*iov)->iov_len; 200*4c0205d0SSasha Levin (*iovcnt)--; 201*4c0205d0SSasha Levin (*iov)++; 202*4c0205d0SSasha Levin } 203*4c0205d0SSasha Levin } 204*4c0205d0SSasha Levin 2051547507fSSasha Levin ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt) 2061547507fSSasha Levin { 2071547507fSSasha Levin ssize_t total = 0; 208*4c0205d0SSasha Levin size_t count = get_iov_size(iov, iovcnt); 2091547507fSSasha Levin 2101547507fSSasha Levin while (count > 0) { 2111547507fSSasha Levin ssize_t nr; 2121547507fSSasha Levin 2131547507fSSasha Levin nr = xreadv(fd, iov, iovcnt); 2141547507fSSasha Levin if (nr <= 0) { 2151547507fSSasha Levin if (total > 0) 2161547507fSSasha Levin return total; 2171547507fSSasha Levin 2181547507fSSasha Levin return -1; 2191547507fSSasha Levin } 2201547507fSSasha Levin 221*4c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL); 2221547507fSSasha Levin } 2231547507fSSasha Levin 2241547507fSSasha Levin return total; 2251547507fSSasha Levin } 2261547507fSSasha Levin 2271547507fSSasha Levin ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt) 2281547507fSSasha Levin { 2291547507fSSasha Levin ssize_t total = 0; 2301547507fSSasha 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 = xwritev(fd, iov, iovcnt); 2361547507fSSasha Levin if (nr < 0) 2371547507fSSasha Levin return -1; 2381547507fSSasha Levin if (nr == 0) { 2391547507fSSasha Levin errno = ENOSPC; 2401547507fSSasha Levin return -1; 2411547507fSSasha Levin } 2421547507fSSasha Levin 243*4c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL); 2441547507fSSasha Levin } 2451547507fSSasha Levin 2461547507fSSasha Levin return total; 2471547507fSSasha Levin } 2481547507fSSasha Levin 2491547507fSSasha Levin /* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */ 2501547507fSSasha Levin ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2511547507fSSasha Levin { 2521547507fSSasha Levin ssize_t nr; 2531547507fSSasha Levin 2541547507fSSasha Levin restart: 2551547507fSSasha Levin nr = preadv(fd, iov, iovcnt, offset); 2561547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 2571547507fSSasha Levin goto restart; 2581547507fSSasha Levin 2591547507fSSasha Levin return nr; 2601547507fSSasha Levin } 2611547507fSSasha Levin 2621547507fSSasha Levin /* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */ 2631547507fSSasha Levin ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2641547507fSSasha Levin { 2651547507fSSasha Levin ssize_t nr; 2661547507fSSasha Levin 2671547507fSSasha Levin restart: 2681547507fSSasha Levin nr = pwritev(fd, iov, iovcnt, offset); 2691547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 2701547507fSSasha Levin goto restart; 2711547507fSSasha Levin 2721547507fSSasha Levin return nr; 2731547507fSSasha Levin } 2741547507fSSasha Levin 2751547507fSSasha Levin ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2761547507fSSasha Levin { 2771547507fSSasha Levin ssize_t total = 0; 2781547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 2791547507fSSasha Levin 2801547507fSSasha Levin while (count > 0) { 2811547507fSSasha Levin ssize_t nr; 2821547507fSSasha Levin 2831547507fSSasha Levin nr = xpreadv(fd, iov, iovcnt, offset); 2841547507fSSasha Levin if (nr <= 0) { 2851547507fSSasha Levin if (total > 0) 2861547507fSSasha Levin return total; 2871547507fSSasha Levin 2881547507fSSasha Levin return -1; 2891547507fSSasha Levin } 2901547507fSSasha Levin 291*4c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset); 2921547507fSSasha Levin } 2931547507fSSasha Levin 2941547507fSSasha Levin return total; 2951547507fSSasha Levin } 2961547507fSSasha Levin 2971547507fSSasha Levin ssize_t pwritev_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 = xpwritev(fd, iov, iovcnt, offset); 3061547507fSSasha Levin if (nr < 0) 3071547507fSSasha Levin return -1; 3081547507fSSasha Levin if (nr == 0) { 3091547507fSSasha Levin errno = ENOSPC; 3101547507fSSasha Levin return -1; 3111547507fSSasha Levin } 312*4c0205d0SSasha Levin 313*4c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset); 3141547507fSSasha Levin } 3151547507fSSasha Levin 3161547507fSSasha Levin return total; 3171547507fSSasha Levin } 318