Blame


1 7a554149 2024-02-18 op /*
2 7a554149 2024-02-18 op * This is free and unencumbered software released into the public domain.
3 7a554149 2024-02-18 op *
4 7a554149 2024-02-18 op * Anyone is free to copy, modify, publish, use, compile, sell, or
5 7a554149 2024-02-18 op * distribute this software, either in source code form or as a compiled
6 7a554149 2024-02-18 op * binary, for any purpose, commercial or non-commercial, and by any
7 7a554149 2024-02-18 op * means.
8 7a554149 2024-02-18 op *
9 7a554149 2024-02-18 op * In jurisdictions that recognize copyright laws, the author or authors
10 7a554149 2024-02-18 op * of this software dedicate any and all copyright interest in the
11 7a554149 2024-02-18 op * software to the public domain. We make this dedication for the benefit
12 7a554149 2024-02-18 op * of the public at large and to the detriment of our heirs and
13 7a554149 2024-02-18 op * successors. We intend this dedication to be an overt act of
14 7a554149 2024-02-18 op * relinquishment in perpetuity of all present and future rights to this
15 7a554149 2024-02-18 op * software under copyright law.
16 7a554149 2024-02-18 op *
17 7a554149 2024-02-18 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 7a554149 2024-02-18 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 7a554149 2024-02-18 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 7a554149 2024-02-18 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 7a554149 2024-02-18 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 7a554149 2024-02-18 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 7a554149 2024-02-18 op * OTHER DEALINGS IN THE SOFTWARE.
24 7a554149 2024-02-18 op */
25 7a554149 2024-02-18 op
26 7a554149 2024-02-18 op #include "compat.h"
27 7a554149 2024-02-18 op
28 7a554149 2024-02-18 op #include <assert.h>
29 7a554149 2024-02-18 op #include <errno.h>
30 7a554149 2024-02-18 op #include <stdarg.h>
31 7a554149 2024-02-18 op #include <stdint.h>
32 7a554149 2024-02-18 op #include <stdio.h>
33 7a554149 2024-02-18 op #include <stdlib.h>
34 7a554149 2024-02-18 op #include <string.h>
35 7a554149 2024-02-18 op #include <tls.h>
36 7a554149 2024-02-18 op #include <unistd.h>
37 7a554149 2024-02-18 op
38 7a554149 2024-02-18 op #include "bufio.h"
39 7a554149 2024-02-18 op
40 7a554149 2024-02-18 op int
41 7a554149 2024-02-18 op buf_init(struct buf *buf)
42 7a554149 2024-02-18 op {
43 7a554149 2024-02-18 op const size_t cap = BIO_CHUNK;
44 7a554149 2024-02-18 op
45 7a554149 2024-02-18 op memset(buf, 0, sizeof(*buf));
46 7a554149 2024-02-18 op if ((buf->buf = malloc(cap)) == NULL)
47 7a554149 2024-02-18 op return (-1);
48 7a554149 2024-02-18 op buf->cap = cap;
49 7a554149 2024-02-18 op return (0);
50 7a554149 2024-02-18 op }
51 7a554149 2024-02-18 op
52 7a554149 2024-02-18 op static int
53 7a554149 2024-02-18 op buf_grow(struct buf *buf)
54 7a554149 2024-02-18 op {
55 7a554149 2024-02-18 op size_t newcap;
56 7a554149 2024-02-18 op void *t;
57 7a554149 2024-02-18 op
58 7a554149 2024-02-18 op newcap = buf->cap + BIO_CHUNK;
59 7a554149 2024-02-18 op t = realloc(buf->buf, newcap);
60 7a554149 2024-02-18 op if (t == NULL)
61 7a554149 2024-02-18 op return (-1);
62 7a554149 2024-02-18 op buf->buf = t;
63 7a554149 2024-02-18 op buf->cap = newcap;
64 7a554149 2024-02-18 op return (0);
65 7a554149 2024-02-18 op }
66 7a554149 2024-02-18 op
67 7a554149 2024-02-18 op int
68 7a554149 2024-02-18 op buf_has_line(struct buf *buf, const char *nl)
69 7a554149 2024-02-18 op {
70 7a554149 2024-02-18 op return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
71 98f8e538 2024-03-22 op }
72 98f8e538 2024-03-22 op
73 98f8e538 2024-03-22 op char *
74 98f8e538 2024-03-22 op buf_getdelim(struct buf *buf, const char *nl, size_t *len)
75 98f8e538 2024-03-22 op {
76 98f8e538 2024-03-22 op uint8_t *endl;
77 98f8e538 2024-03-22 op size_t nlen;
78 98f8e538 2024-03-22 op
79 98f8e538 2024-03-22 op *len = 0;
80 98f8e538 2024-03-22 op
81 98f8e538 2024-03-22 op nlen = strlen(nl);
82 98f8e538 2024-03-22 op if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
83 98f8e538 2024-03-22 op return (NULL);
84 98f8e538 2024-03-22 op *len = endl + nlen - buf->buf;
85 98f8e538 2024-03-22 op *endl = '\0';
86 98f8e538 2024-03-22 op return (buf->buf);
87 7a554149 2024-02-18 op }
88 7a554149 2024-02-18 op
89 7a554149 2024-02-18 op void
90 7a554149 2024-02-18 op buf_drain(struct buf *buf, size_t l)
91 7a554149 2024-02-18 op {
92 7a554149 2024-02-18 op buf->cur = 0;
93 7a554149 2024-02-18 op
94 7a554149 2024-02-18 op if (l >= buf->len) {
95 7a554149 2024-02-18 op buf->len = 0;
96 7a554149 2024-02-18 op return;
97 7a554149 2024-02-18 op }
98 7a554149 2024-02-18 op
99 7a554149 2024-02-18 op memmove(buf->buf, buf->buf + l, buf->len - l);
100 7a554149 2024-02-18 op buf->len -= l;
101 7a554149 2024-02-18 op }
102 7a554149 2024-02-18 op
103 7a554149 2024-02-18 op void
104 7a554149 2024-02-18 op buf_drain_line(struct buf *buf, const char *nl)
105 7a554149 2024-02-18 op {
106 7a554149 2024-02-18 op uint8_t *endln;
107 7a554149 2024-02-18 op size_t nlen;
108 7a554149 2024-02-18 op
109 7a554149 2024-02-18 op nlen = strlen(nl);
110 7a554149 2024-02-18 op if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
111 7a554149 2024-02-18 op return;
112 7a554149 2024-02-18 op buf_drain(buf, endln + nlen - buf->buf);
113 7a554149 2024-02-18 op }
114 7a554149 2024-02-18 op
115 7a554149 2024-02-18 op void
116 7a554149 2024-02-18 op buf_free(struct buf *buf)
117 7a554149 2024-02-18 op {
118 7a554149 2024-02-18 op free(buf->buf);
119 7a554149 2024-02-18 op memset(buf, 0, sizeof(*buf));
120 7a554149 2024-02-18 op }
121 7a554149 2024-02-18 op
122 7a554149 2024-02-18 op int
123 7a554149 2024-02-18 op bufio_init(struct bufio *bio)
124 7a554149 2024-02-18 op {
125 7a554149 2024-02-18 op memset(bio, 0, sizeof(*bio));
126 7a554149 2024-02-18 op bio->fd = -1;
127 7a554149 2024-02-18 op
128 7a554149 2024-02-18 op if (buf_init(&bio->wbuf) == -1)
129 7a554149 2024-02-18 op return (-1);
130 7a554149 2024-02-18 op if (buf_init(&bio->rbuf) == -1) {
131 7a554149 2024-02-18 op buf_free(&bio->wbuf);
132 7a554149 2024-02-18 op return (-1);
133 7a554149 2024-02-18 op }
134 7a554149 2024-02-18 op return (0);
135 7a554149 2024-02-18 op }
136 7a554149 2024-02-18 op
137 0d6af421 2024-02-18 op void
138 0d6af421 2024-02-18 op bufio_free(struct bufio *bio)
139 7a554149 2024-02-18 op {
140 7a554149 2024-02-18 op if (bio->ctx)
141 0d6af421 2024-02-18 op tls_free(bio->ctx);
142 0d6af421 2024-02-18 op bio->ctx = NULL;
143 0d6af421 2024-02-18 op
144 7a554149 2024-02-18 op if (bio->fd != -1)
145 7a554149 2024-02-18 op close(bio->fd);
146 0d6af421 2024-02-18 op bio->fd = -1;
147 7a554149 2024-02-18 op
148 7a554149 2024-02-18 op buf_free(&bio->rbuf);
149 7a554149 2024-02-18 op buf_free(&bio->wbuf);
150 0d6af421 2024-02-18 op }
151 0d6af421 2024-02-18 op
152 0d6af421 2024-02-18 op int
153 8b00d570 2024-02-18 op bufio_close(struct bufio *bio)
154 8b00d570 2024-02-18 op {
155 8b00d570 2024-02-18 op if (bio->ctx == NULL)
156 8b00d570 2024-02-18 op return (0);
157 8b00d570 2024-02-18 op
158 8b00d570 2024-02-18 op switch (tls_close(bio->ctx)) {
159 8b00d570 2024-02-18 op case 0:
160 8b00d570 2024-02-18 op return 0;
161 8b00d570 2024-02-18 op case TLS_WANT_POLLIN:
162 ce023433 2024-02-22 op errno = EAGAIN;
163 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
164 ce023433 2024-02-22 op return (-1);
165 8b00d570 2024-02-18 op case TLS_WANT_POLLOUT:
166 8b00d570 2024-02-18 op errno = EAGAIN;
167 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
168 ce023433 2024-02-22 op return (-1);
169 8b00d570 2024-02-18 op default:
170 8b00d570 2024-02-18 op return (-1);
171 8b00d570 2024-02-18 op }
172 8b00d570 2024-02-18 op }
173 8b00d570 2024-02-18 op
174 8b00d570 2024-02-18 op int
175 0d6af421 2024-02-18 op bufio_reset(struct bufio *bio)
176 0d6af421 2024-02-18 op {
177 0d6af421 2024-02-18 op bufio_free(bio);
178 7a554149 2024-02-18 op return (bufio_init(bio));
179 7a554149 2024-02-18 op }
180 7a554149 2024-02-18 op
181 7a554149 2024-02-18 op void
182 7a554149 2024-02-18 op bufio_set_fd(struct bufio *bio, int fd)
183 7a554149 2024-02-18 op {
184 7a554149 2024-02-18 op bio->fd = fd;
185 7a554149 2024-02-18 op }
186 7a554149 2024-02-18 op
187 7a554149 2024-02-18 op int
188 9c5586a7 2024-02-18 op bufio_starttls(struct bufio *bio, const char *host, int insecure,
189 9c5586a7 2024-02-18 op const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
190 7a554149 2024-02-18 op {
191 7a554149 2024-02-18 op struct tls_config *conf;
192 7a554149 2024-02-18 op
193 7a554149 2024-02-18 op if ((conf = tls_config_new()) == NULL)
194 7a554149 2024-02-18 op return (-1);
195 7a554149 2024-02-18 op
196 7a554149 2024-02-18 op if (insecure) {
197 7a554149 2024-02-18 op tls_config_insecure_noverifycert(conf);
198 7a554149 2024-02-18 op tls_config_insecure_noverifyname(conf);
199 7a554149 2024-02-18 op tls_config_insecure_noverifytime(conf);
200 7a554149 2024-02-18 op }
201 7a554149 2024-02-18 op
202 9c5586a7 2024-02-18 op if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
203 9c5586a7 2024-02-18 op key, keylen) == -1) {
204 9c5586a7 2024-02-18 op tls_config_free(conf);
205 9c5586a7 2024-02-18 op return (-1);
206 9c5586a7 2024-02-18 op }
207 9c5586a7 2024-02-18 op
208 7a554149 2024-02-18 op if ((bio->ctx = tls_client()) == NULL) {
209 7a554149 2024-02-18 op tls_config_free(conf);
210 7a554149 2024-02-18 op return (-1);
211 7a554149 2024-02-18 op }
212 7a554149 2024-02-18 op
213 7a554149 2024-02-18 op if (tls_configure(bio->ctx, conf) == -1) {
214 7a554149 2024-02-18 op tls_config_free(conf);
215 7a554149 2024-02-18 op return (-1);
216 7a554149 2024-02-18 op }
217 7a554149 2024-02-18 op
218 7a554149 2024-02-18 op tls_config_free(conf);
219 7a554149 2024-02-18 op
220 7a554149 2024-02-18 op if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
221 7a554149 2024-02-18 op return (-1);
222 7a554149 2024-02-18 op
223 7a554149 2024-02-18 op return (0);
224 7a554149 2024-02-18 op }
225 7a554149 2024-02-18 op
226 e3693ed9 2024-02-18 op int
227 e3693ed9 2024-02-18 op bufio_ev(struct bufio *bio)
228 7a554149 2024-02-18 op {
229 7a554149 2024-02-18 op short ev;
230 7a554149 2024-02-18 op
231 c4d1f652 2024-03-25 op if (bio->wantev)
232 c4d1f652 2024-03-25 op return (bio->wantev);
233 7a554149 2024-02-18 op
234 ce023433 2024-02-22 op ev = BUFIO_WANT_READ;
235 7a554149 2024-02-18 op if (bio->wbuf.len != 0)
236 ce023433 2024-02-22 op ev |= BUFIO_WANT_WRITE;
237 7a554149 2024-02-18 op
238 7a554149 2024-02-18 op return (ev);
239 7a554149 2024-02-18 op }
240 7a554149 2024-02-18 op
241 0e0994b2 2024-02-18 op int
242 0e0994b2 2024-02-18 op bufio_handshake(struct bufio *bio)
243 0e0994b2 2024-02-18 op {
244 0e0994b2 2024-02-18 op if (bio->ctx == NULL) {
245 0e0994b2 2024-02-18 op errno = EINVAL;
246 0e0994b2 2024-02-18 op return (-1);
247 0e0994b2 2024-02-18 op }
248 0e0994b2 2024-02-18 op
249 0e0994b2 2024-02-18 op switch (tls_handshake(bio->ctx)) {
250 0e0994b2 2024-02-18 op case 0:
251 0e0994b2 2024-02-18 op return (0);
252 0e0994b2 2024-02-18 op case TLS_WANT_POLLIN:
253 ce023433 2024-02-22 op errno = EAGAIN;
254 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
255 ce023433 2024-02-22 op return (-1);
256 0e0994b2 2024-02-18 op case TLS_WANT_POLLOUT:
257 0e0994b2 2024-02-18 op errno = EAGAIN;
258 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
259 ce023433 2024-02-22 op return (-1);
260 0e0994b2 2024-02-18 op default:
261 0e0994b2 2024-02-18 op return (-1);
262 0e0994b2 2024-02-18 op }
263 0e0994b2 2024-02-18 op }
264 0e0994b2 2024-02-18 op
265 7a554149 2024-02-18 op ssize_t
266 7a554149 2024-02-18 op bufio_read(struct bufio *bio)
267 7a554149 2024-02-18 op {
268 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
269 7a554149 2024-02-18 op ssize_t r;
270 7a554149 2024-02-18 op
271 7a554149 2024-02-18 op assert(rbuf->cap >= rbuf->len);
272 7a554149 2024-02-18 op if (rbuf->cap - rbuf->len < BIO_CHUNK) {
273 7a554149 2024-02-18 op if (buf_grow(rbuf) == -1)
274 7a554149 2024-02-18 op return (-1);
275 7a554149 2024-02-18 op }
276 7a554149 2024-02-18 op
277 7a554149 2024-02-18 op if (bio->ctx) {
278 7a554149 2024-02-18 op r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
279 e634cfa6 2024-02-18 op rbuf->cap - rbuf->len);
280 7a554149 2024-02-18 op switch (r) {
281 7a554149 2024-02-18 op case TLS_WANT_POLLIN:
282 ce023433 2024-02-22 op errno = EAGAIN;
283 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
284 ce023433 2024-02-22 op return (-1);
285 7a554149 2024-02-18 op case TLS_WANT_POLLOUT:
286 7a554149 2024-02-18 op errno = EAGAIN;
287 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
288 7a554149 2024-02-18 op return (-1);
289 7a554149 2024-02-18 op case -1:
290 7a554149 2024-02-18 op return (-1);
291 7a554149 2024-02-18 op default:
292 c4d1f652 2024-03-25 op bio->wantev = 0;
293 7a554149 2024-02-18 op rbuf->len += r;
294 7a554149 2024-02-18 op return (r);
295 7a554149 2024-02-18 op }
296 7a554149 2024-02-18 op }
297 7a554149 2024-02-18 op
298 7a554149 2024-02-18 op r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
299 7a554149 2024-02-18 op if (r == -1)
300 7a554149 2024-02-18 op return (-1);
301 7a554149 2024-02-18 op rbuf->len += r;
302 7a554149 2024-02-18 op return (r);
303 b19b8dbc 2024-02-18 op }
304 b19b8dbc 2024-02-18 op
305 b19b8dbc 2024-02-18 op size_t
306 b19b8dbc 2024-02-18 op bufio_drain(struct bufio *bio, void *d, size_t len)
307 b19b8dbc 2024-02-18 op {
308 b19b8dbc 2024-02-18 op struct buf *rbuf = &bio->rbuf;
309 b19b8dbc 2024-02-18 op
310 b19b8dbc 2024-02-18 op if (len > rbuf->len)
311 b19b8dbc 2024-02-18 op len = rbuf->len;
312 b19b8dbc 2024-02-18 op memcpy(d, rbuf->buf, len);
313 b19b8dbc 2024-02-18 op buf_drain(rbuf, len);
314 b19b8dbc 2024-02-18 op return (len);
315 7a554149 2024-02-18 op }
316 7a554149 2024-02-18 op
317 7a554149 2024-02-18 op ssize_t
318 7a554149 2024-02-18 op bufio_write(struct bufio *bio)
319 7a554149 2024-02-18 op {
320 7a554149 2024-02-18 op struct buf *wbuf = &bio->wbuf;
321 7a554149 2024-02-18 op ssize_t w;
322 7a554149 2024-02-18 op
323 7a554149 2024-02-18 op if (bio->ctx) {
324 7a554149 2024-02-18 op switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
325 7a554149 2024-02-18 op case TLS_WANT_POLLIN:
326 ce023433 2024-02-22 op errno = EAGAIN;
327 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
328 ce023433 2024-02-22 op return (-1);
329 7a554149 2024-02-18 op case TLS_WANT_POLLOUT:
330 7a554149 2024-02-18 op errno = EAGAIN;
331 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
332 7a554149 2024-02-18 op return (-1);
333 7a554149 2024-02-18 op case -1:
334 7a554149 2024-02-18 op return (-1);
335 7a554149 2024-02-18 op default:
336 c4d1f652 2024-03-25 op bio->wantev = 0;
337 7a554149 2024-02-18 op buf_drain(wbuf, w);
338 7a554149 2024-02-18 op return (w);
339 7a554149 2024-02-18 op }
340 7a554149 2024-02-18 op }
341 7a554149 2024-02-18 op
342 7a554149 2024-02-18 op w = write(bio->fd, wbuf->buf, wbuf->len);
343 7a554149 2024-02-18 op if (w == -1)
344 7a554149 2024-02-18 op return (-1);
345 7a554149 2024-02-18 op buf_drain(wbuf, w);
346 7a554149 2024-02-18 op return (w);
347 7a554149 2024-02-18 op }
348 7a554149 2024-02-18 op
349 7a554149 2024-02-18 op int
350 7a554149 2024-02-18 op bufio_compose(struct bufio *bio, const void *d, size_t len)
351 7a554149 2024-02-18 op {
352 7a554149 2024-02-18 op struct buf *wbuf = &bio->wbuf;
353 7a554149 2024-02-18 op
354 7a554149 2024-02-18 op while (wbuf->cap - wbuf->len < len) {
355 7a554149 2024-02-18 op if (buf_grow(wbuf) == -1)
356 7a554149 2024-02-18 op return (-1);
357 7a554149 2024-02-18 op }
358 7a554149 2024-02-18 op
359 7a554149 2024-02-18 op memcpy(wbuf->buf + wbuf->len, d, len);
360 7a554149 2024-02-18 op wbuf->len += len;
361 7a554149 2024-02-18 op return (0);
362 7a554149 2024-02-18 op }
363 7a554149 2024-02-18 op
364 7a554149 2024-02-18 op int
365 7a554149 2024-02-18 op bufio_compose_str(struct bufio *bio, const char *str)
366 7a554149 2024-02-18 op {
367 7a554149 2024-02-18 op return (bufio_compose(bio, str, strlen(str)));
368 7a554149 2024-02-18 op }
369 7a554149 2024-02-18 op
370 7a554149 2024-02-18 op int
371 7a554149 2024-02-18 op bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
372 7a554149 2024-02-18 op {
373 7a554149 2024-02-18 op va_list ap;
374 7a554149 2024-02-18 op char *str;
375 7a554149 2024-02-18 op int r;
376 7a554149 2024-02-18 op
377 7a554149 2024-02-18 op va_start(ap, fmt);
378 7a554149 2024-02-18 op r = vasprintf(&str, fmt, ap);
379 7a554149 2024-02-18 op va_end(ap);
380 7a554149 2024-02-18 op
381 7a554149 2024-02-18 op if (r == -1)
382 7a554149 2024-02-18 op return (-1);
383 7a554149 2024-02-18 op r = bufio_compose(bio, str, r);
384 7a554149 2024-02-18 op free(str);
385 7a554149 2024-02-18 op return (r);
386 7a554149 2024-02-18 op }
387 7a554149 2024-02-18 op
388 7a554149 2024-02-18 op void
389 7a554149 2024-02-18 op bufio_rewind_cursor(struct bufio *bio)
390 7a554149 2024-02-18 op {
391 7a554149 2024-02-18 op bio->rbuf.cur = 0;
392 7a554149 2024-02-18 op }
393 7a554149 2024-02-18 op
394 7a554149 2024-02-18 op int
395 7a554149 2024-02-18 op bufio_get_cb(void *d)
396 7a554149 2024-02-18 op {
397 7a554149 2024-02-18 op struct bufio *bio = d;
398 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
399 7a554149 2024-02-18 op
400 7a554149 2024-02-18 op if (rbuf->cur >= rbuf->len)
401 7a554149 2024-02-18 op return (EOF);
402 7a554149 2024-02-18 op return (rbuf->buf[rbuf->cur++]);
403 7a554149 2024-02-18 op }
404 7a554149 2024-02-18 op
405 7a554149 2024-02-18 op int
406 7a554149 2024-02-18 op bufio_peek_cb(void *d)
407 7a554149 2024-02-18 op {
408 7a554149 2024-02-18 op struct bufio *bio = d;
409 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
410 7a554149 2024-02-18 op
411 7a554149 2024-02-18 op if (rbuf->cur >= rbuf->len)
412 7a554149 2024-02-18 op return (EOF);
413 7a554149 2024-02-18 op return (rbuf->buf[rbuf->cur]);
414 7a554149 2024-02-18 op }