diff options
Diffstat (limited to 'atomicio.c')
-rw-r--r-- | atomicio.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/atomicio.c b/atomicio.c index f651a292c..f32ff85ba 100644 --- a/atomicio.c +++ b/atomicio.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: atomicio.c,v 1.23 2006/08/03 03:34:41 deraadt Exp $ */ | 1 | /* $OpenBSD: atomicio.c,v 1.25 2007/06/25 12:02:27 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2006 Damien Miller. All rights reserved. | 3 | * Copyright (c) 2006 Damien Miller. All rights reserved. |
4 | * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. | 4 | * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. |
@@ -32,7 +32,11 @@ | |||
32 | #include <sys/uio.h> | 32 | #include <sys/uio.h> |
33 | 33 | ||
34 | #include <errno.h> | 34 | #include <errno.h> |
35 | #ifdef HAVE_POLL_H | ||
36 | #include <poll.h> | ||
37 | #endif | ||
35 | #include <string.h> | 38 | #include <string.h> |
39 | #include <unistd.h> | ||
36 | 40 | ||
37 | #include "atomicio.h" | 41 | #include "atomicio.h" |
38 | 42 | ||
@@ -45,17 +49,24 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) | |||
45 | char *s = _s; | 49 | char *s = _s; |
46 | size_t pos = 0; | 50 | size_t pos = 0; |
47 | ssize_t res; | 51 | ssize_t res; |
52 | struct pollfd pfd; | ||
48 | 53 | ||
54 | pfd.fd = fd; | ||
55 | pfd.events = f == read ? POLLIN : POLLOUT; | ||
49 | while (n > pos) { | 56 | while (n > pos) { |
50 | res = (f) (fd, s + pos, n - pos); | 57 | res = (f) (fd, s + pos, n - pos); |
51 | switch (res) { | 58 | switch (res) { |
52 | case -1: | 59 | case -1: |
53 | #ifdef EWOULDBLOCK | 60 | #ifdef EWOULDBLOCK |
54 | if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) | 61 | if (errno == EINTR || errno == EWOULDBLOCK) |
55 | #else | 62 | #else |
56 | if (errno == EINTR || errno == EAGAIN) | 63 | if (errno == EINTR) |
57 | #endif | 64 | #endif |
58 | continue; | 65 | continue; |
66 | if (errno == EAGAIN) { | ||
67 | (void)poll(&pfd, 1, -1); | ||
68 | continue; | ||
69 | } | ||
59 | return 0; | 70 | return 0; |
60 | case 0: | 71 | case 0: |
61 | errno = EPIPE; | 72 | errno = EPIPE; |
@@ -77,6 +88,7 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, | |||
77 | size_t pos = 0, rem; | 88 | size_t pos = 0, rem; |
78 | ssize_t res; | 89 | ssize_t res; |
79 | struct iovec iov_array[IOV_MAX], *iov = iov_array; | 90 | struct iovec iov_array[IOV_MAX], *iov = iov_array; |
91 | struct pollfd pfd; | ||
80 | 92 | ||
81 | if (iovcnt > IOV_MAX) { | 93 | if (iovcnt > IOV_MAX) { |
82 | errno = EINVAL; | 94 | errno = EINVAL; |
@@ -85,12 +97,22 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, | |||
85 | /* Make a copy of the iov array because we may modify it below */ | 97 | /* Make a copy of the iov array because we may modify it below */ |
86 | memcpy(iov, _iov, iovcnt * sizeof(*_iov)); | 98 | memcpy(iov, _iov, iovcnt * sizeof(*_iov)); |
87 | 99 | ||
100 | pfd.fd = fd; | ||
101 | pfd.events = f == readv ? POLLIN : POLLOUT; | ||
88 | for (; iovcnt > 0 && iov[0].iov_len > 0;) { | 102 | for (; iovcnt > 0 && iov[0].iov_len > 0;) { |
89 | res = (f) (fd, iov, iovcnt); | 103 | res = (f) (fd, iov, iovcnt); |
90 | switch (res) { | 104 | switch (res) { |
91 | case -1: | 105 | case -1: |
92 | if (errno == EINTR || errno == EAGAIN) | 106 | #ifdef EWOULDBLOCK |
107 | if (errno == EINTR || errno == EWOULDBLOCK) | ||
108 | #else | ||
109 | if (errno == EINTR) | ||
110 | #endif | ||
93 | continue; | 111 | continue; |
112 | if (errno == EAGAIN) { | ||
113 | (void)poll(&pfd, 1, -1); | ||
114 | continue; | ||
115 | } | ||
94 | return 0; | 116 | return 0; |
95 | case 0: | 117 | case 0: |
96 | errno = EPIPE; | 118 | errno = EPIPE; |