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. */ 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. */ 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 */ 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 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 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. */ 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. */ 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 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 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. */ 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. */ 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 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 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 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 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. */ 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. */ 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 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 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 } 3401664498dSSasha Levin 3411664498dSSasha Levin #ifdef CONFIG_HAS_AIO 3421664498dSSasha Levin int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, 3431664498dSSasha Levin off_t offset, int ev, void *param) 3441664498dSSasha Levin { 3451664498dSSasha Levin struct iocb *ios[1] = { iocb }; 3460ecc970fSAsias He int ret; 3471664498dSSasha Levin 3481664498dSSasha Levin io_prep_pwritev(iocb, fd, iov, iovcnt, offset); 3491664498dSSasha Levin io_set_eventfd(iocb, ev); 3501664498dSSasha Levin iocb->data = param; 3511664498dSSasha Levin 3520ecc970fSAsias He restart: 3530ecc970fSAsias He ret = io_submit(ctx, 1, ios); 3540ecc970fSAsias He if (ret == -EAGAIN) 3550ecc970fSAsias He goto restart; 3560ecc970fSAsias He return ret; 3571664498dSSasha Levin } 3581664498dSSasha Levin 3591664498dSSasha Levin int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, 3601664498dSSasha Levin off_t offset, int ev, void *param) 3611664498dSSasha Levin { 3621664498dSSasha Levin struct iocb *ios[1] = { iocb }; 3630ecc970fSAsias He int ret; 3641664498dSSasha Levin 3651664498dSSasha Levin io_prep_preadv(iocb, fd, iov, iovcnt, offset); 3661664498dSSasha Levin io_set_eventfd(iocb, ev); 3671664498dSSasha Levin iocb->data = param; 3681664498dSSasha Levin 3690ecc970fSAsias He restart: 3700ecc970fSAsias He ret = io_submit(ctx, 1, ios); 3710ecc970fSAsias He if (ret == -EAGAIN) 3720ecc970fSAsias He goto restart; 3730ecc970fSAsias He return ret; 3741664498dSSasha Levin } 3751664498dSSasha Levin #endif 376