Commit | Line | Data |
---|---|---|
f6da3aa6 | 1 | /* |
c0c0989a | 2 | * SPDX-License-Identifier: LGPL-2.1-or-later |
f6da3aa6 | 3 | * |
c0c0989a MJ |
4 | * Copyright (C) 2009 Pierre-Marc Fournier |
5 | * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
f6da3aa6 MD |
6 | */ |
7 | ||
b4051ad8 FD |
8 | #include <stddef.h> |
9 | ||
f6da3aa6 MD |
10 | /* write() */ |
11 | #include <unistd.h> | |
12 | ||
9fe043d7 FD |
13 | /* writev() */ |
14 | #include <sys/uio.h> | |
15 | ||
f6da3aa6 MD |
16 | /* send() */ |
17 | #include <sys/types.h> | |
18 | #include <sys/socket.h> | |
19 | ||
20 | #include <errno.h> | |
21 | ||
9d315d6d | 22 | #include "common/patient.h" |
f6da3aa6 MD |
23 | |
24 | /* | |
25 | * This write is patient because it restarts if it was incomplete. | |
26 | */ | |
27 | ||
516d12da | 28 | ssize_t ust_patient_write(int fd, const void *buf, size_t count) |
f6da3aa6 MD |
29 | { |
30 | const char *bufc = (const char *) buf; | |
31 | int result; | |
32 | ||
33 | for(;;) { | |
34 | result = write(fd, bufc, count); | |
35 | if (result == -1 && errno == EINTR) { | |
36 | continue; | |
37 | } | |
38 | if (result <= 0) { | |
39 | return result; | |
40 | } | |
41 | count -= result; | |
42 | bufc += result; | |
43 | ||
44 | if (count == 0) { | |
45 | break; | |
46 | } | |
47 | } | |
48 | ||
49 | return bufc-(const char *)buf; | |
50 | } | |
51 | ||
9fe043d7 FD |
52 | /* |
53 | * The `struct iovec *iov` is not `const` because we modify it to support | |
54 | * partial writes. | |
55 | */ | |
516d12da | 56 | ssize_t ust_patient_writev(int fd, struct iovec *iov, int iovcnt) |
9fe043d7 FD |
57 | { |
58 | ssize_t written, total_written = 0; | |
59 | int curr_element_idx = 0; | |
60 | ||
61 | for(;;) { | |
62 | written = writev(fd, iov + curr_element_idx, | |
63 | iovcnt - curr_element_idx); | |
64 | if (written == -1 && errno == EINTR) { | |
65 | continue; | |
66 | } | |
67 | if (written <= 0) { | |
68 | return written; | |
69 | } | |
70 | ||
71 | total_written += written; | |
72 | ||
73 | /* | |
74 | * If it's not the last element in the vector and we have | |
75 | * written more than the current element size, then increment | |
76 | * the current element index until we reach the element that | |
77 | * was partially written. | |
78 | */ | |
79 | while (curr_element_idx < iovcnt && | |
80 | written >= iov[curr_element_idx].iov_len) { | |
81 | written -= iov[curr_element_idx].iov_len; | |
82 | curr_element_idx++; | |
83 | } | |
84 | ||
85 | /* Maybe we are done. */ | |
86 | if (curr_element_idx >= iovcnt) { | |
87 | break; | |
88 | } | |
89 | ||
90 | /* Update the current element base and size. */ | |
91 | iov[curr_element_idx].iov_base += written; | |
92 | iov[curr_element_idx].iov_len -= written; | |
93 | } | |
94 | ||
95 | return total_written; | |
96 | } | |
97 | ||
516d12da | 98 | ssize_t ust_patient_send(int fd, const void *buf, size_t count, int flags) |
f6da3aa6 MD |
99 | { |
100 | const char *bufc = (const char *) buf; | |
101 | int result; | |
102 | ||
103 | for(;;) { | |
104 | result = send(fd, bufc, count, flags); | |
105 | if (result == -1 && errno == EINTR) { | |
106 | continue; | |
107 | } | |
108 | if (result <= 0) { | |
109 | return result; | |
110 | } | |
111 | count -= result; | |
112 | bufc += result; | |
113 | ||
114 | if (count == 0) { | |
115 | break; | |
116 | } | |
117 | } | |
118 | ||
119 | return bufc - (const char *) buf; | |
120 | } |