Commit | Line | Data |
---|---|---|
f6da3aa6 MD |
1 | /* |
2 | * Copyright (C) 2009 Pierre-Marc Fournier | |
3 | * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
b4051ad8 FD |
20 | #include <stddef.h> |
21 | ||
f6da3aa6 MD |
22 | /* write() */ |
23 | #include <unistd.h> | |
24 | ||
9fe043d7 FD |
25 | /* writev() */ |
26 | #include <sys/uio.h> | |
27 | ||
f6da3aa6 MD |
28 | /* send() */ |
29 | #include <sys/types.h> | |
30 | #include <sys/socket.h> | |
31 | ||
32 | #include <errno.h> | |
33 | ||
34 | #include <share.h> | |
35 | ||
36 | /* | |
37 | * This write is patient because it restarts if it was incomplete. | |
38 | */ | |
39 | ||
40 | ssize_t patient_write(int fd, const void *buf, size_t count) | |
41 | { | |
42 | const char *bufc = (const char *) buf; | |
43 | int result; | |
44 | ||
45 | for(;;) { | |
46 | result = write(fd, bufc, count); | |
47 | if (result == -1 && errno == EINTR) { | |
48 | continue; | |
49 | } | |
50 | if (result <= 0) { | |
51 | return result; | |
52 | } | |
53 | count -= result; | |
54 | bufc += result; | |
55 | ||
56 | if (count == 0) { | |
57 | break; | |
58 | } | |
59 | } | |
60 | ||
61 | return bufc-(const char *)buf; | |
62 | } | |
63 | ||
9fe043d7 FD |
64 | /* |
65 | * The `struct iovec *iov` is not `const` because we modify it to support | |
66 | * partial writes. | |
67 | */ | |
68 | ssize_t patient_writev(int fd, struct iovec *iov, int iovcnt) | |
69 | { | |
70 | ssize_t written, total_written = 0; | |
71 | int curr_element_idx = 0; | |
72 | ||
73 | for(;;) { | |
74 | written = writev(fd, iov + curr_element_idx, | |
75 | iovcnt - curr_element_idx); | |
76 | if (written == -1 && errno == EINTR) { | |
77 | continue; | |
78 | } | |
79 | if (written <= 0) { | |
80 | return written; | |
81 | } | |
82 | ||
83 | total_written += written; | |
84 | ||
85 | /* | |
86 | * If it's not the last element in the vector and we have | |
87 | * written more than the current element size, then increment | |
88 | * the current element index until we reach the element that | |
89 | * was partially written. | |
90 | */ | |
91 | while (curr_element_idx < iovcnt && | |
92 | written >= iov[curr_element_idx].iov_len) { | |
93 | written -= iov[curr_element_idx].iov_len; | |
94 | curr_element_idx++; | |
95 | } | |
96 | ||
97 | /* Maybe we are done. */ | |
98 | if (curr_element_idx >= iovcnt) { | |
99 | break; | |
100 | } | |
101 | ||
102 | /* Update the current element base and size. */ | |
103 | iov[curr_element_idx].iov_base += written; | |
104 | iov[curr_element_idx].iov_len -= written; | |
105 | } | |
106 | ||
107 | return total_written; | |
108 | } | |
109 | ||
f6da3aa6 MD |
110 | ssize_t patient_send(int fd, const void *buf, size_t count, int flags) |
111 | { | |
112 | const char *bufc = (const char *) buf; | |
113 | int result; | |
114 | ||
115 | for(;;) { | |
116 | result = send(fd, bufc, count, flags); | |
117 | if (result == -1 && errno == EINTR) { | |
118 | continue; | |
119 | } | |
120 | if (result <= 0) { | |
121 | return result; | |
122 | } | |
123 | count -= result; | |
124 | bufc += result; | |
125 | ||
126 | if (count == 0) { | |
127 | break; | |
128 | } | |
129 | } | |
130 | ||
131 | return bufc - (const char *) buf; | |
132 | } |