xref: /kvmtool/util/read-write.c (revision 6b7deb024d07fec40355b08358d9765c09f658c2)
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 }
80*6b7deb02SPekka Enberg 
81*6b7deb02SPekka Enberg /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
82*6b7deb02SPekka Enberg ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
83*6b7deb02SPekka Enberg {
84*6b7deb02SPekka Enberg 	ssize_t nr;
85*6b7deb02SPekka Enberg 
86*6b7deb02SPekka Enberg restart:
87*6b7deb02SPekka Enberg 	nr = pread(fd, buf, count, offset);
88*6b7deb02SPekka Enberg 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
89*6b7deb02SPekka Enberg 		goto restart;
90*6b7deb02SPekka Enberg 
91*6b7deb02SPekka Enberg 	return nr;
92*6b7deb02SPekka Enberg }
93*6b7deb02SPekka Enberg 
94*6b7deb02SPekka Enberg /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
95*6b7deb02SPekka Enberg ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
96*6b7deb02SPekka Enberg {
97*6b7deb02SPekka Enberg 	ssize_t nr;
98*6b7deb02SPekka Enberg 
99*6b7deb02SPekka Enberg restart:
100*6b7deb02SPekka Enberg 	nr = pwrite(fd, buf, count, offset);
101*6b7deb02SPekka Enberg 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
102*6b7deb02SPekka Enberg 		goto restart;
103*6b7deb02SPekka Enberg 
104*6b7deb02SPekka Enberg 	return nr;
105*6b7deb02SPekka Enberg }
106*6b7deb02SPekka Enberg 
107*6b7deb02SPekka Enberg ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
108*6b7deb02SPekka Enberg {
109*6b7deb02SPekka Enberg 	ssize_t total = 0;
110*6b7deb02SPekka Enberg 	char *p = buf;
111*6b7deb02SPekka Enberg 
112*6b7deb02SPekka Enberg 	while (count > 0) {
113*6b7deb02SPekka Enberg 		ssize_t nr;
114*6b7deb02SPekka Enberg 
115*6b7deb02SPekka Enberg 		nr = xpread(fd, p, count, offset);
116*6b7deb02SPekka Enberg 		if (nr <= 0) {
117*6b7deb02SPekka Enberg 			if (total > 0)
118*6b7deb02SPekka Enberg 				return total;
119*6b7deb02SPekka Enberg 
120*6b7deb02SPekka Enberg 			return -1;
121*6b7deb02SPekka Enberg 		}
122*6b7deb02SPekka Enberg 
123*6b7deb02SPekka Enberg 		count -= nr;
124*6b7deb02SPekka Enberg 		total += nr;
125*6b7deb02SPekka Enberg 		p += nr;
126*6b7deb02SPekka Enberg 		offset += nr;
127*6b7deb02SPekka Enberg 	}
128*6b7deb02SPekka Enberg 
129*6b7deb02SPekka Enberg 	return total;
130*6b7deb02SPekka Enberg }
131*6b7deb02SPekka Enberg 
132*6b7deb02SPekka Enberg ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
133*6b7deb02SPekka Enberg {
134*6b7deb02SPekka Enberg 	const char *p = buf;
135*6b7deb02SPekka Enberg 	ssize_t total = 0;
136*6b7deb02SPekka Enberg 
137*6b7deb02SPekka Enberg 	while (count > 0) {
138*6b7deb02SPekka Enberg 		ssize_t nr;
139*6b7deb02SPekka Enberg 
140*6b7deb02SPekka Enberg 		nr = xpwrite(fd, p, count, offset);
141*6b7deb02SPekka Enberg 		if (nr < 0)
142*6b7deb02SPekka Enberg 			return -1;
143*6b7deb02SPekka Enberg 		if (nr == 0) {
144*6b7deb02SPekka Enberg 			errno = ENOSPC;
145*6b7deb02SPekka Enberg 			return -1;
146*6b7deb02SPekka Enberg 		}
147*6b7deb02SPekka Enberg 		count -= nr;
148*6b7deb02SPekka Enberg 		total += nr;
149*6b7deb02SPekka Enberg 		p += nr;
150*6b7deb02SPekka Enberg 		offset += nr;
151*6b7deb02SPekka Enberg 	}
152*6b7deb02SPekka Enberg 
153*6b7deb02SPekka Enberg 	return total;
154*6b7deb02SPekka Enberg }
155