xref: /kvmtool/util/read-write.c (revision 6b7deb024d07fec40355b08358d9765c09f658c2)
1 #include "kvm/read-write.h"
2 
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 
8 /* Same as read(2) except that this function never returns EAGAIN or EINTR. */
9 ssize_t xread(int fd, void *buf, size_t count)
10 {
11 	ssize_t nr;
12 
13 restart:
14 	nr = read(fd, buf, count);
15 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
16 		goto restart;
17 
18 	return nr;
19 }
20 
21 /* Same as write(2) except that this function never returns EAGAIN or EINTR. */
22 ssize_t xwrite(int fd, const void *buf, size_t count)
23 {
24 	ssize_t nr;
25 
26 restart:
27 	nr = write(fd, buf, count);
28 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
29 		goto restart;
30 
31 	return nr;
32 }
33 
34 ssize_t read_in_full(int fd, void *buf, size_t count)
35 {
36 	ssize_t total = 0;
37 	char *p = buf;
38 
39 	while (count > 0) {
40 		ssize_t nr;
41 
42 		nr = xread(fd, p, count);
43 		if (nr <= 0) {
44 			if (total > 0)
45 				return total;
46 
47 			return -1;
48 		}
49 
50 		count -= nr;
51 		total += nr;
52 		p += nr;
53 	}
54 
55 	return total;
56 }
57 
58 ssize_t write_in_full(int fd, const void *buf, size_t count)
59 {
60 	const char *p = buf;
61 	ssize_t total = 0;
62 
63 	while (count > 0) {
64 		ssize_t nr;
65 
66 		nr = xwrite(fd, p, count);
67 		if (nr < 0)
68 			return -1;
69 		if (nr == 0) {
70 			errno = ENOSPC;
71 			return -1;
72 		}
73 		count -= nr;
74 		total += nr;
75 		p += nr;
76 	}
77 
78 	return total;
79 }
80 
81 /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
82 ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
83 {
84 	ssize_t nr;
85 
86 restart:
87 	nr = pread(fd, buf, count, offset);
88 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
89 		goto restart;
90 
91 	return nr;
92 }
93 
94 /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
95 ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
96 {
97 	ssize_t nr;
98 
99 restart:
100 	nr = pwrite(fd, buf, count, offset);
101 	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
102 		goto restart;
103 
104 	return nr;
105 }
106 
107 ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
108 {
109 	ssize_t total = 0;
110 	char *p = buf;
111 
112 	while (count > 0) {
113 		ssize_t nr;
114 
115 		nr = xpread(fd, p, count, offset);
116 		if (nr <= 0) {
117 			if (total > 0)
118 				return total;
119 
120 			return -1;
121 		}
122 
123 		count -= nr;
124 		total += nr;
125 		p += nr;
126 		offset += nr;
127 	}
128 
129 	return total;
130 }
131 
132 ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
133 {
134 	const char *p = buf;
135 	ssize_t total = 0;
136 
137 	while (count > 0) {
138 		ssize_t nr;
139 
140 		nr = xpwrite(fd, p, count, offset);
141 		if (nr < 0)
142 			return -1;
143 		if (nr == 0) {
144 			errno = ENOSPC;
145 			return -1;
146 		}
147 		count -= nr;
148 		total += nr;
149 		p += nr;
150 		offset += nr;
151 	}
152 
153 	return total;
154 }
155