Merge branch 'perf/urgent'
[linux-2.6/x86.git] / tools / kvm / read-write.c
blob737fb26ddfbe014b74af154a851300c75b448843
1 #include "kvm/read-write.h"
3 #include <sys/types.h>
4 #include <sys/uio.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <errno.h>
9 /* Same as read(2) except that this function never returns EAGAIN or EINTR. */
10 ssize_t xread(int fd, void *buf, size_t count)
12 ssize_t nr;
14 restart:
15 nr = read(fd, buf, count);
16 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
17 goto restart;
19 return nr;
22 /* Same as write(2) except that this function never returns EAGAIN or EINTR. */
23 ssize_t xwrite(int fd, const void *buf, size_t count)
25 ssize_t nr;
27 restart:
28 nr = write(fd, buf, count);
29 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
30 goto restart;
32 return nr;
35 ssize_t read_in_full(int fd, void *buf, size_t count)
37 ssize_t total = 0;
38 char *p = buf;
40 while (count > 0) {
41 ssize_t nr;
43 nr = xread(fd, p, count);
44 if (nr <= 0) {
45 if (total > 0)
46 return total;
48 return -1;
51 count -= nr;
52 total += nr;
53 p += nr;
56 return total;
59 ssize_t write_in_full(int fd, const void *buf, size_t count)
61 const char *p = buf;
62 ssize_t total = 0;
64 while (count > 0) {
65 ssize_t nr;
67 nr = xwrite(fd, p, count);
68 if (nr < 0)
69 return -1;
70 if (nr == 0) {
71 errno = ENOSPC;
72 return -1;
74 count -= nr;
75 total += nr;
76 p += nr;
79 return total;
82 /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
83 ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
85 ssize_t nr;
87 restart:
88 nr = pread(fd, buf, count, offset);
89 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
90 goto restart;
92 return nr;
95 /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
96 ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
98 ssize_t nr;
100 restart:
101 nr = pwrite(fd, buf, count, offset);
102 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
103 goto restart;
105 return nr;
108 ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
110 ssize_t total = 0;
111 char *p = buf;
113 while (count > 0) {
114 ssize_t nr;
116 nr = xpread(fd, p, count, offset);
117 if (nr <= 0) {
118 if (total > 0)
119 return total;
121 return -1;
124 count -= nr;
125 total += nr;
126 p += nr;
127 offset += nr;
130 return total;
133 ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
135 const char *p = buf;
136 ssize_t total = 0;
138 while (count > 0) {
139 ssize_t nr;
141 nr = xpwrite(fd, p, count, offset);
142 if (nr < 0)
143 return -1;
144 if (nr == 0) {
145 errno = ENOSPC;
146 return -1;
148 count -= nr;
149 total += nr;
150 p += nr;
151 offset += nr;
154 return total;
157 /* Same as readv(2) except that this function never returns EAGAIN or EINTR. */
158 ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt)
160 ssize_t nr;
162 restart:
163 nr = readv(fd, iov, iovcnt);
164 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
165 goto restart;
167 return nr;
170 /* Same as writev(2) except that this function never returns EAGAIN or EINTR. */
171 ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
173 ssize_t nr;
175 restart:
176 nr = writev(fd, iov, iovcnt);
177 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
178 goto restart;
180 return nr;
183 static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt)
185 size_t size = 0;
186 while (iovcnt--)
187 size += (iov++)->iov_len;
189 return size;
192 static inline void shift_iovec(const struct iovec **iov, int *iovcnt,
193 size_t nr, ssize_t *total, size_t *count, off_t *offset)
195 while (nr >= (*iov)->iov_len) {
196 nr -= (*iov)->iov_len;
197 *total += (*iov)->iov_len;
198 *count -= (*iov)->iov_len;
199 if (offset)
200 *offset += (*iov)->iov_len;
201 (*iovcnt)--;
202 (*iov)++;
206 ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt)
208 ssize_t total = 0;
209 size_t count = get_iov_size(iov, iovcnt);
211 while (count > 0) {
212 ssize_t nr;
214 nr = xreadv(fd, iov, iovcnt);
215 if (nr <= 0) {
216 if (total > 0)
217 return total;
219 return -1;
222 shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
225 return total;
228 ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt)
230 ssize_t total = 0;
231 size_t count = get_iov_size(iov, iovcnt);
233 while (count > 0) {
234 ssize_t nr;
236 nr = xwritev(fd, iov, iovcnt);
237 if (nr < 0)
238 return -1;
239 if (nr == 0) {
240 errno = ENOSPC;
241 return -1;
244 shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
247 return total;
250 /* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */
251 ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
253 ssize_t nr;
255 restart:
256 nr = preadv(fd, iov, iovcnt, offset);
257 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
258 goto restart;
260 return nr;
263 /* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */
264 ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
266 ssize_t nr;
268 restart:
269 nr = pwritev(fd, iov, iovcnt, offset);
270 if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
271 goto restart;
273 return nr;
276 ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
278 ssize_t total = 0;
279 size_t count = get_iov_size(iov, iovcnt);
281 while (count > 0) {
282 ssize_t nr;
284 nr = xpreadv(fd, iov, iovcnt, offset);
285 if (nr <= 0) {
286 if (total > 0)
287 return total;
289 return -1;
292 shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
295 return total;
298 ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
300 ssize_t total = 0;
301 size_t count = get_iov_size(iov, iovcnt);
303 while (count > 0) {
304 ssize_t nr;
306 nr = xpwritev(fd, iov, iovcnt, offset);
307 if (nr < 0)
308 return -1;
309 if (nr == 0) {
310 errno = ENOSPC;
311 return -1;
314 shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
317 return total;