aa59ba1457d92ece99df4ac4daa7acc001d31e12
[lttng-ust.git] / snprintf / patient_write.c
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
20 #include <stddef.h>
21
22 /* write() */
23 #include <unistd.h>
24
25 /* writev() */
26 #include <sys/uio.h>
27
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
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
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 }
This page took 0.031363 seconds and 3 git commands to generate.