Annotation of src/usr.bin/rsync/io.c, Revision 1.16
1.16 ! benno 1: /* $Id: io.c,v 1.15 2019/03/31 09:26:05 deraadt Exp $ */
1.1 benno 2: /*
3: * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <sys/stat.h>
18:
19: #include <assert.h>
20: #include <endian.h>
21: #include <errno.h>
22: #include <poll.h>
23: #include <stdint.h>
24: #include <stdio.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
28:
29: #include "extern.h"
1.7 florian 30:
31: /*
32: * A non-blocking check to see whether there's POLLIN data in fd.
33: * Returns <0 on failure, 0 if there's no data, >0 if there is.
34: */
1.1 benno 35: int
36: io_read_check(struct sess *sess, int fd)
37: {
38: struct pollfd pfd;
39:
40: pfd.fd = fd;
41: pfd.events = POLLIN;
42:
43: if (poll(&pfd, 1, 0) < 0) {
1.16 ! benno 44: ERR("poll");
1.1 benno 45: return -1;
46: }
1.7 florian 47: return (pfd.revents & POLLIN);
1.1 benno 48: }
49:
50: /*
51: * Write buffer to non-blocking descriptor.
52: * Returns zero on failure, non-zero on success (zero or more bytes).
1.7 florian 53: * On success, fills in "sz" with the amount written.
1.1 benno 54: */
55: static int
1.5 deraadt 56: io_write_nonblocking(struct sess *sess, int fd, const void *buf, size_t bsz,
57: size_t *sz)
1.1 benno 58: {
59: struct pollfd pfd;
60: ssize_t wsz;
1.6 florian 61: int c;
1.1 benno 62:
63: *sz = 0;
64:
1.4 deraadt 65: if (bsz == 0)
1.1 benno 66: return 1;
67:
68: pfd.fd = fd;
69: pfd.events = POLLOUT;
70:
1.7 florian 71: /* Poll and check for all possible errors. */
72:
1.6 florian 73: if ((c = poll(&pfd, 1, POLL_TIMEOUT)) == -1) {
1.16 ! benno 74: ERR("poll");
1.1 benno 75: return 0;
1.6 florian 76: } else if (c == 0) {
1.16 ! benno 77: ERRX("poll: timeout");
1.6 florian 78: return 0;
1.7 florian 79: } else if ((pfd.revents & (POLLERR|POLLNVAL))) {
1.16 ! benno 80: ERRX("poll: bad fd");
1.1 benno 81: return 0;
82: } else if ((pfd.revents & POLLHUP)) {
1.16 ! benno 83: ERRX("poll: hangup");
1.1 benno 84: return 0;
1.3 deraadt 85: } else if (!(pfd.revents & POLLOUT)) {
1.16 ! benno 86: ERRX("poll: unknown event");
1.1 benno 87: return 0;
88: }
89:
1.7 florian 90: /* Now the non-blocking write. */
91:
1.1 benno 92: if ((wsz = write(fd, buf, bsz)) < 0) {
1.16 ! benno 93: ERR("write");
1.1 benno 94: return 0;
95: }
96:
97: *sz = wsz;
98: return 1;
99: }
100:
101: /*
102: * Blocking write of the full size of the buffer.
103: * Returns 0 on failure, non-zero on success (all bytes written).
104: */
105: static int
1.5 deraadt 106: io_write_blocking(struct sess *sess, int fd, const void *buf, size_t sz)
1.1 benno 107: {
108: size_t wsz;
109: int c;
110:
111: while (sz > 0) {
112: c = io_write_nonblocking(sess, fd, buf, sz, &wsz);
1.3 deraadt 113: if (!c) {
1.16 ! benno 114: ERRX1("io_write_nonblocking");
1.1 benno 115: return 0;
1.4 deraadt 116: } else if (wsz == 0) {
1.16 ! benno 117: ERRX("io_write_nonblocking: short write");
1.1 benno 118: return 0;
119: }
120: buf += wsz;
121: sz -= wsz;
122: }
123:
124: return 1;
125: }
126:
127: /*
128: * Write "buf" of size "sz" to non-blocking descriptor.
129: * Returns zero on failure, non-zero on success (all bytes written to
130: * the descriptor).
131: */
132: int
133: io_write_buf(struct sess *sess, int fd, const void *buf, size_t sz)
134: {
135: int32_t tag, tagbuf;
136: size_t wsz;
137: int c;
138:
1.3 deraadt 139: if (!sess->mplex_writes) {
1.1 benno 140: c = io_write_blocking(sess, fd, buf, sz);
141: sess->total_write += sz;
142: return c;
143: }
144:
145: while (sz > 0) {
146: wsz = sz & 0xFFFFFF;
147: tag = (7 << 24) + wsz;
148: tagbuf = htole32(tag);
1.3 deraadt 149: if (!io_write_blocking(sess, fd, &tagbuf, sizeof(tagbuf))) {
1.16 ! benno 150: ERRX1("io_write_blocking");
1.1 benno 151: return 0;
152: }
1.3 deraadt 153: if (!io_write_blocking(sess, fd, buf, wsz)) {
1.16 ! benno 154: ERRX1("io_write_blocking");
1.1 benno 155: return 0;
156: }
157: sess->total_write += wsz;
158: sz -= wsz;
159: buf += wsz;
160: }
161:
162: return 1;
163: }
164:
165: /*
166: * Write "line" (NUL-terminated) followed by a newline.
167: * Returns zero on failure, non-zero on succcess.
168: */
169: int
170: io_write_line(struct sess *sess, int fd, const char *line)
171: {
172:
1.3 deraadt 173: if (!io_write_buf(sess, fd, line, strlen(line)))
1.16 ! benno 174: ERRX1("io_write_buf");
1.3 deraadt 175: else if (!io_write_byte(sess, fd, '\n'))
1.16 ! benno 176: ERRX1("io_write_byte");
1.1 benno 177: else
178: return 1;
179:
180: return 0;
181: }
182:
183: /*
184: * Read buffer from non-blocking descriptor.
185: * Returns zero on failure, non-zero on success (zero or more bytes).
186: */
187: static int
188: io_read_nonblocking(struct sess *sess,
189: int fd, void *buf, size_t bsz, size_t *sz)
190: {
191: struct pollfd pfd;
192: ssize_t rsz;
1.6 florian 193: int c;
1.1 benno 194:
195: *sz = 0;
196:
1.4 deraadt 197: if (bsz == 0)
1.1 benno 198: return 1;
199:
200: pfd.fd = fd;
201: pfd.events = POLLIN;
202:
1.7 florian 203: /* Poll and check for all possible errors. */
204:
1.6 florian 205: if ((c = poll(&pfd, 1, POLL_TIMEOUT)) == -1) {
1.16 ! benno 206: ERR("poll");
1.1 benno 207: return 0;
1.6 florian 208: } else if (c == 0) {
1.16 ! benno 209: ERRX("poll: timeout");
1.6 florian 210: return 0;
1.7 florian 211: } else if ((pfd.revents & (POLLERR|POLLNVAL))) {
1.16 ! benno 212: ERRX("poll: bad fd");
1.1 benno 213: return 0;
1.3 deraadt 214: } else if (!(pfd.revents & (POLLIN|POLLHUP))) {
1.16 ! benno 215: ERRX("poll: unknown event");
1.1 benno 216: return 0;
217: }
218:
1.7 florian 219: /* Now the non-blocking read, checking for EOF. */
220:
1.1 benno 221: if ((rsz = read(fd, buf, bsz)) < 0) {
1.16 ! benno 222: ERR("read");
1.1 benno 223: return 0;
1.4 deraadt 224: } else if (rsz == 0) {
1.16 ! benno 225: ERRX("unexpected end of file");
1.1 benno 226: return 0;
227: }
228:
229: *sz = rsz;
230: return 1;
231: }
232:
233: /*
234: * Blocking read of the full size of the buffer.
235: * This can be called from either the error type message or a regular
236: * message---or for that matter, multiplexed or not.
237: * Returns 0 on failure, non-zero on success (all bytes read).
238: */
239: static int
240: io_read_blocking(struct sess *sess,
241: int fd, void *buf, size_t sz)
242: {
243: size_t rsz;
244: int c;
245:
246: while (sz > 0) {
247: c = io_read_nonblocking(sess, fd, buf, sz, &rsz);
1.3 deraadt 248: if (!c) {
1.16 ! benno 249: ERRX1("io_read_nonblocking");
1.1 benno 250: return 0;
1.4 deraadt 251: } else if (rsz == 0) {
1.16 ! benno 252: ERRX("io_read_nonblocking: short read");
1.1 benno 253: return 0;
254: }
255: buf += rsz;
256: sz -= rsz;
257: }
258:
259: return 1;
260: }
261:
262: /*
263: * When we do a lot of writes in a row (such as when the sender emits
264: * the file list), the server might be sending us multiplexed log
265: * messages.
266: * If it sends too many, it clogs the socket.
267: * This function looks into the read buffer and clears out any log
268: * messages pending.
269: * If called when there are valid data reads available, this function
270: * does nothing.
271: * Returns zero on failure, non-zero on success.
272: */
273: int
274: io_read_flush(struct sess *sess, int fd)
275: {
276: int32_t tagbuf, tag;
277: char mpbuf[1024];
278:
279: if (sess->mplex_read_remain)
280: return 1;
281:
282: /*
283: * First, read the 4-byte multiplex tag.
284: * The first byte is the tag identifier (7 for normal
285: * data, !7 for out-of-band data), the last three are
286: * for the remaining data size.
287: */
288:
1.3 deraadt 289: if (!io_read_blocking(sess, fd, &tagbuf, sizeof(tagbuf))) {
1.16 ! benno 290: ERRX1("io_read_blocking");
1.1 benno 291: return 0;
292: }
293: tag = le32toh(tagbuf);
294: sess->mplex_read_remain = tag & 0xFFFFFF;
295: tag >>= 24;
1.4 deraadt 296: if (tag == 7)
1.1 benno 297: return 1;
298:
299: tag -= 7;
300:
301: if (sess->mplex_read_remain > sizeof(mpbuf)) {
1.16 ! benno 302: ERRX("multiplex buffer overflow");
1.1 benno 303: return 0;
1.4 deraadt 304: } else if (sess->mplex_read_remain == 0)
1.1 benno 305: return 1;
306:
1.12 benno 307: if (!io_read_blocking(sess, fd, mpbuf, sess->mplex_read_remain)) {
1.16 ! benno 308: ERRX1("io_read_blocking");
1.1 benno 309: return 0;
310: }
1.4 deraadt 311: if (mpbuf[sess->mplex_read_remain - 1] == '\n')
1.1 benno 312: mpbuf[--sess->mplex_read_remain] = '\0';
313:
314: /*
315: * Always print the server's messages, as the server
316: * will control its own log levelling.
317: */
318:
1.16 ! benno 319: LOG0("%.*s", (int)sess->mplex_read_remain, mpbuf);
1.1 benno 320: sess->mplex_read_remain = 0;
321:
1.2 benno 322: /*
1.1 benno 323: * I only know that a tag of one means an error.
324: * This means that we should exit.
325: */
326:
1.4 deraadt 327: if (tag == 1) {
1.16 ! benno 328: ERRX1("error from remote host");
1.1 benno 329: return 0;
330: }
331: return 1;
332: }
333:
334: /*
335: * Read buffer from non-blocking descriptor, possibly in multiplex read
336: * mode.
337: * Returns zero on failure, non-zero on success (all bytes read from
338: * the descriptor).
339: */
340: int
341: io_read_buf(struct sess *sess, int fd, void *buf, size_t sz)
342: {
343: size_t rsz;
344: int c;
345:
346: /* If we're not multiplexing, read directly. */
347:
1.3 deraadt 348: if (!sess->mplex_reads) {
1.4 deraadt 349: assert(sess->mplex_read_remain == 0);
1.1 benno 350: c = io_read_blocking(sess, fd, buf, sz);
351: sess->total_read += sz;
352: return c;
353: }
354:
355: while (sz > 0) {
356: /*
357: * First, check to see if we have any regular data
358: * hanging around waiting to be read.
359: * If so, read the lesser of that data and whatever
360: * amount we currently want.
361: */
362:
363: if (sess->mplex_read_remain) {
364: rsz = sess->mplex_read_remain < sz ?
365: sess->mplex_read_remain : sz;
1.3 deraadt 366: if (!io_read_blocking(sess, fd, buf, rsz)) {
1.16 ! benno 367: ERRX1("io_read_blocking");
1.1 benno 368: return 0;
369: }
370: sz -= rsz;
371: sess->mplex_read_remain -= rsz;
372: buf += rsz;
373: sess->total_read += rsz;
374: continue;
375: }
376:
1.4 deraadt 377: assert(sess->mplex_read_remain == 0);
1.3 deraadt 378: if (!io_read_flush(sess, fd)) {
1.16 ! benno 379: ERRX1("io_read_flush");
1.1 benno 380: return 0;
381: }
382: }
383:
384: return 1;
385: }
386:
1.7 florian 387: /*
388: * Like io_write_buf(), but for a long (which is a composite type).
389: * Returns zero on failure, non-zero on success.
390: */
1.1 benno 391: int
1.15 deraadt 392: io_write_ulong(struct sess *sess, int fd, uint64_t val)
1.1 benno 393: {
1.15 deraadt 394: uint64_t nv;
395: int64_t sval = (int64_t)val;
1.1 benno 396:
397: /* Short-circuit: send as an integer if possible. */
398:
1.15 deraadt 399: if (sval <= INT32_MAX && sval >= 0) {
1.7 florian 400: if (!io_write_int(sess, fd, (int32_t)val)) {
1.16 ! benno 401: ERRX1("io_write_int");
1.7 florian 402: return 0;
403: }
404: return 1;
405: }
1.1 benno 406:
1.15 deraadt 407: /* Otherwise, pad with -1 32-bit, then send 64-bit. */
1.1 benno 408:
409: nv = htole64(val);
410:
1.14 deraadt 411: if (!io_write_int(sess, fd, -1))
1.16 ! benno 412: ERRX1("io_write_int");
1.3 deraadt 413: else if (!io_write_buf(sess, fd, &nv, sizeof(int64_t)))
1.16 ! benno 414: ERRX1("io_write_buf");
1.1 benno 415: else
416: return 1;
417:
418: return 0;
419: }
420:
1.15 deraadt 421: int
422: io_write_long(struct sess *sess, int fd, int64_t val)
423: {
424: return io_write_ulong(sess, fd, (uint64_t)val);
425: }
426:
1.7 florian 427: /*
1.15 deraadt 428: * Like io_write_buf(), but for an unsigned integer.
1.7 florian 429: * Returns zero on failure, non-zero on success.
430: */
1.1 benno 431: int
1.15 deraadt 432: io_write_uint(struct sess *sess, int fd, uint32_t val)
1.1 benno 433: {
1.15 deraadt 434: uint32_t nv;
1.1 benno 435:
436: nv = htole32(val);
437:
1.15 deraadt 438: if (!io_write_buf(sess, fd, &nv, sizeof(uint32_t))) {
1.16 ! benno 439: ERRX1("io_write_buf");
1.1 benno 440: return 0;
441: }
442: return 1;
443: }
444:
445: /*
1.15 deraadt 446: * Like io_write_buf(), but for an integer.
447: * Returns zero on failure, non-zero on success.
448: */
449: int
450: io_write_int(struct sess *sess, int fd, int32_t val)
451: {
452: return io_write_uint(sess, fd, (uint32_t)val);
453: }
454:
455: /*
1.1 benno 456: * A simple assertion-protected memory copy from th einput "val" or size
457: * "valsz" into our buffer "buf", full size "buflen", position "bufpos".
458: * Increases our "bufpos" appropriately.
459: * This has no return value, but will assert() if the size of the buffer
460: * is insufficient for the new data.
461: */
462: void
1.2 benno 463: io_buffer_buf(struct sess *sess, void *buf,
1.1 benno 464: size_t *bufpos, size_t buflen, const void *val, size_t valsz)
465: {
466:
467: assert(*bufpos + valsz <= buflen);
468: memcpy(buf + *bufpos, val, valsz);
469: *bufpos += valsz;
470: }
471:
472: /*
1.7 florian 473: * Like io_buffer_buf(), but also accomodating for multiplexing codes.
474: * This should NEVER be passed to io_write_buf(), but instead passed
475: * directly to a write operation.
476: */
477: void
478: io_lowbuffer_buf(struct sess *sess, void *buf,
479: size_t *bufpos, size_t buflen, const void *val, size_t valsz)
480: {
481: int32_t tagbuf;
482:
1.9 deraadt 483: if (valsz == 0)
1.7 florian 484: return;
485:
486: if (!sess->mplex_writes) {
487: io_buffer_buf(sess, buf, bufpos, buflen, val, valsz);
488: return;
489: }
490:
491: assert(*bufpos + valsz + sizeof(int32_t) <= buflen);
492: assert(valsz == (valsz & 0xFFFFFF));
493: tagbuf = htole32((7 << 24) + valsz);
494:
495: io_buffer_int(sess, buf, bufpos, buflen, tagbuf);
496: io_buffer_buf(sess, buf, bufpos, buflen, val, valsz);
497: }
498:
499: /*
500: * Allocate the space needed for io_lowbuffer_buf() and friends.
501: * This should be called for *each* lowbuffer operation, so:
502: * io_lowbuffer_alloc(... sizeof(int32_t));
503: * io_lowbuffer_int(...);
504: * io_lowbuffer_alloc(... sizeof(int32_t));
505: * io_lowbuffer_int(...);
506: * And not sizeof(int32_t) * 2 or whatnot.
507: * Returns zero on failure, non-zero on succes.
508: */
509: int
510: io_lowbuffer_alloc(struct sess *sess, void **buf,
511: size_t *bufsz, size_t *bufmax, size_t sz)
512: {
513: void *pp;
514: size_t extra;
515:
516: extra = sess->mplex_writes ? sizeof(int32_t) : 0;
517:
518: if (*bufsz + sz + extra > *bufmax) {
519: pp = realloc(*buf, *bufsz + sz + extra);
520: if (pp == NULL) {
1.16 ! benno 521: ERR("realloc");
1.7 florian 522: return 0;
523: }
524: *buf = pp;
525: *bufmax = *bufsz + sz + extra;
526: }
527: *bufsz += sz + extra;
528: return 1;
529: }
530:
531: /*
532: * Like io_lowbuffer_buf(), but for a single integer.
533: */
534: void
535: io_lowbuffer_int(struct sess *sess, void *buf,
536: size_t *bufpos, size_t buflen, int32_t val)
537: {
538: int32_t nv = htole32(val);
539:
540: io_lowbuffer_buf(sess, buf, bufpos, buflen, &nv, sizeof(int32_t));
541: }
542:
543: /*
544: * Like io_buffer_buf(), but for a single integer.
1.1 benno 545: */
546: void
1.2 benno 547: io_buffer_int(struct sess *sess, void *buf,
1.1 benno 548: size_t *bufpos, size_t buflen, int32_t val)
549: {
550: int32_t nv = htole32(val);
551:
1.4 deraadt 552: io_buffer_buf(sess, buf, bufpos, buflen, &nv, sizeof(int32_t));
1.1 benno 553: }
554:
1.7 florian 555: /*
556: * Like io_read_buf(), but for a long >=0.
557: * Returns zero on failure, non-zero on success.
558: */
1.1 benno 559: int
1.15 deraadt 560: io_read_long(struct sess *sess, int fd, int64_t *val)
1.1 benno 561: {
1.15 deraadt 562: uint64_t uoval;
1.1 benno 563:
1.15 deraadt 564: if (!io_read_ulong(sess, fd, &uoval)) {
1.16 ! benno 565: ERRX1("io_read_long");
1.1 benno 566: return 0;
567: }
1.15 deraadt 568: *val = (int64_t)uoval;
569: if (*val < 0) {
1.16 ! benno 570: ERRX1("io_read_long negative");
1.15 deraadt 571: return 0;
572: }
1.1 benno 573: return 1;
574: }
575:
1.7 florian 576: /*
577: * Like io_read_buf(), but for a long.
578: * Returns zero on failure, non-zero on success.
579: */
1.1 benno 580: int
1.15 deraadt 581: io_read_ulong(struct sess *sess, int fd, uint64_t *val)
1.1 benno 582: {
1.15 deraadt 583: uint64_t oval;
584: int32_t sval;
1.1 benno 585:
586: /* Start with the short-circuit: read as an int. */
587:
1.3 deraadt 588: if (!io_read_int(sess, fd, &sval)) {
1.16 ! benno 589: ERRX1("io_read_int");
1.1 benno 590: return 0;
1.13 deraadt 591: } else if (sval != -1) {
1.15 deraadt 592: *val = (uint64_t)le32toh(sval);
1.1 benno 593: return 1;
594: }
595:
1.15 deraadt 596: /* If the int is -1, read as 64 bits. */
1.1 benno 597:
1.15 deraadt 598: if (!io_read_buf(sess, fd, &oval, sizeof(uint64_t))) {
1.16 ! benno 599: ERRX1("io_read_buf");
1.1 benno 600: return 0;
601: }
602:
603: *val = le64toh(oval);
604: return 1;
605: }
606:
607: /*
608: * One thing we often need to do is read a size_t.
609: * These are transmitted as int32_t, so make sure that the value
610: * transmitted is not out of range.
611: * FIXME: I assume that size_t can handle int32_t's max.
1.7 florian 612: * Returns zero on failure, non-zero on success.
1.1 benno 613: */
614: int
615: io_read_size(struct sess *sess, int fd, size_t *val)
616: {
617: int32_t oval;
618:
1.3 deraadt 619: if (!io_read_int(sess, fd, &oval)) {
1.16 ! benno 620: ERRX1("io_read_int");
1.1 benno 621: return 0;
622: } else if (oval < 0) {
1.16 ! benno 623: ERRX("io_read_size: negative value");
1.1 benno 624: return 0;
625: }
626:
627: *val = oval;
628: return 1;
629: }
630:
1.7 florian 631: /*
632: * Like io_read_buf(), but for an integer.
633: * Returns zero on failure, non-zero on success.
634: */
1.1 benno 635: int
1.15 deraadt 636: io_read_uint(struct sess *sess, int fd, uint32_t *val)
1.1 benno 637: {
1.15 deraadt 638: uint32_t oval;
1.1 benno 639:
1.15 deraadt 640: if (!io_read_buf(sess, fd, &oval, sizeof(uint32_t))) {
1.16 ! benno 641: ERRX1("io_read_buf");
1.1 benno 642: return 0;
643: }
644:
645: *val = le32toh(oval);
646: return 1;
1.15 deraadt 647: }
648:
649: int
650: io_read_int(struct sess *sess, int fd, int32_t *val)
651: {
652: return io_read_uint(sess, fd, (uint32_t *)val);
1.1 benno 653: }
654:
655: /*
656: * Copies "valsz" from "buf", full size "bufsz" at position" bufpos",
657: * into "val".
658: * Calls assert() if the source doesn't have enough data.
659: * Increases "bufpos" to the new position.
660: */
661: void
1.2 benno 662: io_unbuffer_buf(struct sess *sess, const void *buf,
1.1 benno 663: size_t *bufpos, size_t bufsz, void *val, size_t valsz)
664: {
665:
666: assert(*bufpos + valsz <= bufsz);
667: memcpy(val, buf + *bufpos, valsz);
668: *bufpos += valsz;
669: }
670:
671: /*
1.7 florian 672: * Calls io_unbuffer_buf() and converts.
1.1 benno 673: */
674: void
1.2 benno 675: io_unbuffer_int(struct sess *sess, const void *buf,
1.1 benno 676: size_t *bufpos, size_t bufsz, int32_t *val)
677: {
678: int32_t oval;
679:
1.5 deraadt 680: io_unbuffer_buf(sess, buf, bufpos, bufsz, &oval, sizeof(int32_t));
1.1 benno 681: *val = le32toh(oval);
682: }
683:
1.7 florian 684: /*
685: * Calls io_unbuffer_buf() and converts.
686: */
1.1 benno 687: int
1.2 benno 688: io_unbuffer_size(struct sess *sess, const void *buf,
1.1 benno 689: size_t *bufpos, size_t bufsz, size_t *val)
690: {
691: int32_t oval;
692:
693: io_unbuffer_int(sess, buf, bufpos, bufsz, &oval);
694: if (oval < 0) {
1.16 ! benno 695: ERRX("io_unbuffer_size: negative value");
1.1 benno 696: return 0;
697: }
698: *val = oval;
699: return 1;
700: }
701:
1.7 florian 702: /*
703: * Like io_read_buf(), but for a single byte >=0.
704: * Returns zero on failure, non-zero on success.
705: */
1.1 benno 706: int
707: io_read_byte(struct sess *sess, int fd, uint8_t *val)
708: {
709:
1.3 deraadt 710: if (!io_read_buf(sess, fd, val, sizeof(uint8_t))) {
1.16 ! benno 711: ERRX1("io_read_buf");
1.1 benno 712: return 0;
713: }
714: return 1;
715: }
716:
1.7 florian 717: /*
718: * Like io_write_buf(), but for a single byte.
719: * Returns zero on failure, non-zero on success.
720: */
1.1 benno 721: int
722: io_write_byte(struct sess *sess, int fd, uint8_t val)
723: {
724:
1.3 deraadt 725: if (!io_write_buf(sess, fd, &val, sizeof(uint8_t))) {
1.16 ! benno 726: ERRX1("io_write_buf");
1.1 benno 727: return 0;
728: }
729: return 1;
730: }