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 } 155*1547507fSSasha Levin 156*1547507fSSasha Levin /* Same as readv(2) except that this function never returns EAGAIN or EINTR. */ 157*1547507fSSasha Levin ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt) 158*1547507fSSasha Levin { 159*1547507fSSasha Levin ssize_t nr; 160*1547507fSSasha Levin 161*1547507fSSasha Levin restart: 162*1547507fSSasha Levin nr = readv(fd, iov, iovcnt); 163*1547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 164*1547507fSSasha Levin goto restart; 165*1547507fSSasha Levin 166*1547507fSSasha Levin return nr; 167*1547507fSSasha Levin } 168*1547507fSSasha Levin 169*1547507fSSasha Levin /* Same as writev(2) except that this function never returns EAGAIN or EINTR. */ 170*1547507fSSasha Levin ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt) 171*1547507fSSasha Levin { 172*1547507fSSasha Levin ssize_t nr; 173*1547507fSSasha Levin 174*1547507fSSasha Levin restart: 175*1547507fSSasha Levin nr = write(fd, iov, iovcnt); 176*1547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 177*1547507fSSasha Levin goto restart; 178*1547507fSSasha Levin 179*1547507fSSasha Levin return nr; 180*1547507fSSasha Levin } 181*1547507fSSasha Levin 182*1547507fSSasha Levin static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt) 183*1547507fSSasha Levin { 184*1547507fSSasha Levin size_t size = 0; 185*1547507fSSasha Levin while (iovcnt--) 186*1547507fSSasha Levin size += (iov++)->iov_len; 187*1547507fSSasha Levin 188*1547507fSSasha Levin return size; 189*1547507fSSasha Levin } 190*1547507fSSasha Levin 191*1547507fSSasha Levin ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt) 192*1547507fSSasha Levin { 193*1547507fSSasha Levin ssize_t total = 0; 194*1547507fSSasha Levin ssize_t count = get_iov_size(iov, iovcnt); 195*1547507fSSasha Levin 196*1547507fSSasha Levin while (count > 0) { 197*1547507fSSasha Levin ssize_t nr; 198*1547507fSSasha Levin 199*1547507fSSasha Levin nr = xreadv(fd, iov, iovcnt); 200*1547507fSSasha Levin if (nr <= 0) { 201*1547507fSSasha Levin if (total > 0) 202*1547507fSSasha Levin return total; 203*1547507fSSasha Levin 204*1547507fSSasha Levin return -1; 205*1547507fSSasha Levin } 206*1547507fSSasha Levin 207*1547507fSSasha Levin while ((size_t)nr >= iov->iov_len) { 208*1547507fSSasha Levin nr -= iov->iov_len; 209*1547507fSSasha Levin total += iov->iov_len; 210*1547507fSSasha Levin count -= iov->iov_len; 211*1547507fSSasha Levin iovcnt--; 212*1547507fSSasha Levin iov++; 213*1547507fSSasha Levin } 214*1547507fSSasha Levin } 215*1547507fSSasha Levin 216*1547507fSSasha Levin return total; 217*1547507fSSasha Levin } 218*1547507fSSasha Levin 219*1547507fSSasha Levin ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt) 220*1547507fSSasha Levin { 221*1547507fSSasha Levin ssize_t total = 0; 222*1547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 223*1547507fSSasha Levin 224*1547507fSSasha Levin while (count > 0) { 225*1547507fSSasha Levin ssize_t nr; 226*1547507fSSasha Levin 227*1547507fSSasha Levin nr = xwritev(fd, iov, iovcnt); 228*1547507fSSasha Levin if (nr < 0) 229*1547507fSSasha Levin return -1; 230*1547507fSSasha Levin if (nr == 0) { 231*1547507fSSasha Levin errno = ENOSPC; 232*1547507fSSasha Levin return -1; 233*1547507fSSasha Levin } 234*1547507fSSasha Levin 235*1547507fSSasha Levin while ((size_t)nr >= iov->iov_len) { 236*1547507fSSasha Levin nr -= iov->iov_len; 237*1547507fSSasha Levin total += iov->iov_len; 238*1547507fSSasha Levin count -= iov->iov_len; 239*1547507fSSasha Levin iovcnt--; 240*1547507fSSasha Levin iov++; 241*1547507fSSasha Levin } 242*1547507fSSasha Levin } 243*1547507fSSasha Levin 244*1547507fSSasha Levin return total; 245*1547507fSSasha Levin } 246*1547507fSSasha Levin 247*1547507fSSasha Levin /* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */ 248*1547507fSSasha Levin ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) 249*1547507fSSasha Levin { 250*1547507fSSasha Levin ssize_t nr; 251*1547507fSSasha Levin 252*1547507fSSasha Levin restart: 253*1547507fSSasha Levin nr = preadv(fd, iov, iovcnt, offset); 254*1547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 255*1547507fSSasha Levin goto restart; 256*1547507fSSasha Levin 257*1547507fSSasha Levin return nr; 258*1547507fSSasha Levin } 259*1547507fSSasha Levin 260*1547507fSSasha Levin /* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */ 261*1547507fSSasha Levin ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) 262*1547507fSSasha Levin { 263*1547507fSSasha Levin ssize_t nr; 264*1547507fSSasha Levin 265*1547507fSSasha Levin restart: 266*1547507fSSasha Levin nr = pwritev(fd, iov, iovcnt, offset); 267*1547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 268*1547507fSSasha Levin goto restart; 269*1547507fSSasha Levin 270*1547507fSSasha Levin return nr; 271*1547507fSSasha Levin } 272*1547507fSSasha Levin 273*1547507fSSasha Levin ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) 274*1547507fSSasha Levin { 275*1547507fSSasha Levin ssize_t total = 0; 276*1547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 277*1547507fSSasha Levin 278*1547507fSSasha Levin while (count > 0) { 279*1547507fSSasha Levin ssize_t nr; 280*1547507fSSasha Levin 281*1547507fSSasha Levin nr = xpreadv(fd, iov, iovcnt, offset); 282*1547507fSSasha Levin if (nr <= 0) { 283*1547507fSSasha Levin if (total > 0) 284*1547507fSSasha Levin return total; 285*1547507fSSasha Levin 286*1547507fSSasha Levin return -1; 287*1547507fSSasha Levin } 288*1547507fSSasha Levin 289*1547507fSSasha Levin while ((size_t)nr >= iov->iov_len) { 290*1547507fSSasha Levin nr -= iov->iov_len; 291*1547507fSSasha Levin total += iov->iov_len; 292*1547507fSSasha Levin count -= iov->iov_len; 293*1547507fSSasha Levin iovcnt--; 294*1547507fSSasha Levin iov++; 295*1547507fSSasha Levin } 296*1547507fSSasha Levin } 297*1547507fSSasha Levin 298*1547507fSSasha Levin return total; 299*1547507fSSasha Levin } 300*1547507fSSasha Levin 301*1547507fSSasha Levin ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) 302*1547507fSSasha Levin { 303*1547507fSSasha Levin ssize_t total = 0; 304*1547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 305*1547507fSSasha Levin 306*1547507fSSasha Levin while (count > 0) { 307*1547507fSSasha Levin ssize_t nr; 308*1547507fSSasha Levin 309*1547507fSSasha Levin nr = xpwritev(fd, iov, iovcnt, offset); 310*1547507fSSasha Levin if (nr < 0) 311*1547507fSSasha Levin return -1; 312*1547507fSSasha Levin if (nr == 0) { 313*1547507fSSasha Levin errno = ENOSPC; 314*1547507fSSasha Levin return -1; 315*1547507fSSasha Levin } 316*1547507fSSasha Levin while ((size_t)nr >= iov->iov_len) { 317*1547507fSSasha Levin nr -= iov->iov_len; 318*1547507fSSasha Levin total += iov->iov_len; 319*1547507fSSasha Levin count -= iov->iov_len; 320*1547507fSSasha Levin iovcnt--; 321*1547507fSSasha Levin iov++; 322*1547507fSSasha Levin } 323*1547507fSSasha Levin } 324*1547507fSSasha Levin 325*1547507fSSasha Levin return total; 326*1547507fSSasha Levin } 327