xref: /openbsd/usr.sbin/rpki-client/io.c (revision 08db1177)
1*08db1177Sclaudio /*	$OpenBSD: io.c,v 1.12 2021/01/08 08:09:07 claudio Exp $ */
29a7e9e7fSjob /*
39a7e9e7fSjob  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
49a7e9e7fSjob  *
59a7e9e7fSjob  * Permission to use, copy, modify, and distribute this software for any
69a7e9e7fSjob  * purpose with or without fee is hereby granted, provided that the above
79a7e9e7fSjob  * copyright notice and this permission notice appear in all copies.
89a7e9e7fSjob  *
99a7e9e7fSjob  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109a7e9e7fSjob  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119a7e9e7fSjob  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129a7e9e7fSjob  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139a7e9e7fSjob  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149a7e9e7fSjob  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159a7e9e7fSjob  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169a7e9e7fSjob  */
179a7e9e7fSjob 
189a7e9e7fSjob #include <sys/queue.h>
199a7e9e7fSjob 
209a7e9e7fSjob #include <assert.h>
219a7e9e7fSjob #include <err.h>
229a7e9e7fSjob #include <fcntl.h>
239a7e9e7fSjob #include <stdint.h>
249a7e9e7fSjob #include <stdlib.h>
259a7e9e7fSjob #include <string.h>
269a7e9e7fSjob #include <unistd.h>
27*08db1177Sclaudio #include <imsg.h>
289a7e9e7fSjob 
299a7e9e7fSjob #include "extern.h"
309a7e9e7fSjob 
319a7e9e7fSjob void
329a7e9e7fSjob io_socket_blocking(int fd)
339a7e9e7fSjob {
349a7e9e7fSjob 	int	 fl;
359a7e9e7fSjob 
369a7e9e7fSjob 	if ((fl = fcntl(fd, F_GETFL, 0)) == -1)
37498a9228Sbenno 		err(1, "fcntl");
389a7e9e7fSjob 	if (fcntl(fd, F_SETFL, fl & ~O_NONBLOCK) == -1)
39498a9228Sbenno 		err(1, "fcntl");
409a7e9e7fSjob }
419a7e9e7fSjob 
429a7e9e7fSjob void
439a7e9e7fSjob io_socket_nonblocking(int fd)
449a7e9e7fSjob {
459a7e9e7fSjob 	int	 fl;
469a7e9e7fSjob 
479a7e9e7fSjob 	if ((fl = fcntl(fd, F_GETFL, 0)) == -1)
48498a9228Sbenno 		err(1, "fcntl");
499a7e9e7fSjob 	if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1)
50498a9228Sbenno 		err(1, "fcntl");
519a7e9e7fSjob }
529a7e9e7fSjob 
539a7e9e7fSjob /*
549a7e9e7fSjob  * Like io_simple_write() but into a buffer.
559a7e9e7fSjob  */
569a7e9e7fSjob void
57*08db1177Sclaudio io_simple_buffer(struct ibuf *b, const void *res, size_t sz)
589a7e9e7fSjob {
59*08db1177Sclaudio 	if (ibuf_add(b, res, sz) == -1)
60498a9228Sbenno 		err(1, NULL);
619a7e9e7fSjob }
629a7e9e7fSjob 
639a7e9e7fSjob /*
64*08db1177Sclaudio  * Add a sz sized buffer into the io buffer.
659a7e9e7fSjob  */
669a7e9e7fSjob void
67*08db1177Sclaudio io_buf_buffer(struct ibuf *b, const void *p, size_t sz)
689a7e9e7fSjob {
69*08db1177Sclaudio 	if (ibuf_add(b, &sz, sizeof(size_t)) == -1)
70*08db1177Sclaudio 		err(1, NULL);
719a7e9e7fSjob 	if (sz > 0)
72*08db1177Sclaudio 		if (ibuf_add(b, p, sz) == -1)
73*08db1177Sclaudio 			err(1, NULL);
749a7e9e7fSjob }
759a7e9e7fSjob 
769a7e9e7fSjob /*
77*08db1177Sclaudio  * Add a string into the io buffer.
789a7e9e7fSjob  */
799a7e9e7fSjob void
80*08db1177Sclaudio io_str_buffer(struct ibuf *b, const char *p)
819a7e9e7fSjob {
829a7e9e7fSjob 	size_t sz = (p == NULL) ? 0 : strlen(p);
839a7e9e7fSjob 
84*08db1177Sclaudio 	io_buf_buffer(b, p, sz);
859a7e9e7fSjob }
869a7e9e7fSjob 
879a7e9e7fSjob /*
889a7e9e7fSjob  * Read of a binary buffer that must be on a blocking descriptor.
899a7e9e7fSjob  * Does nothing if "sz" is zero.
906959e8e1Sflorian  * This will fail and exit on EOF.
919a7e9e7fSjob  */
929a7e9e7fSjob void
939a7e9e7fSjob io_simple_read(int fd, void *res, size_t sz)
949a7e9e7fSjob {
959a7e9e7fSjob 	ssize_t	 ssz;
96b58ccec3Sbenno 	char	*tmp;
979a7e9e7fSjob 
98b58ccec3Sbenno 	tmp = res; /* arithmetic on a pointer to void is a GNU extension */
999a7e9e7fSjob again:
1009a7e9e7fSjob 	if (sz == 0)
1019a7e9e7fSjob 		return;
102edf80c75Sbenno 	if ((ssz = read(fd, tmp, sz)) == -1)
103498a9228Sbenno 		err(1, "read");
1049a7e9e7fSjob 	else if (ssz == 0)
105498a9228Sbenno 		errx(1, "read: unexpected end of file");
1069a7e9e7fSjob 	else if ((size_t)ssz == sz)
1079a7e9e7fSjob 		return;
1089a7e9e7fSjob 	sz -= ssz;
109b58ccec3Sbenno 	tmp += ssz;
1109a7e9e7fSjob 	goto again;
1119a7e9e7fSjob }
1129a7e9e7fSjob 
1139a7e9e7fSjob /*
1149a7e9e7fSjob  * Read a binary buffer, allocating space for it.
1159a7e9e7fSjob  * If the buffer is zero-sized, this won't allocate "res", but
1169a7e9e7fSjob  * will still initialise it to NULL.
1179a7e9e7fSjob  */
1189a7e9e7fSjob void
1199a7e9e7fSjob io_buf_read_alloc(int fd, void **res, size_t *sz)
1209a7e9e7fSjob {
1219a7e9e7fSjob 
1229a7e9e7fSjob 	*res = NULL;
1239a7e9e7fSjob 	io_simple_read(fd, sz, sizeof(size_t));
1249a7e9e7fSjob 	if (*sz == 0)
1259a7e9e7fSjob 		return;
1269a7e9e7fSjob 	if ((*res = malloc(*sz)) == NULL)
127498a9228Sbenno 		err(1, NULL);
1289a7e9e7fSjob 	io_simple_read(fd, *res, *sz);
1299a7e9e7fSjob }
1309a7e9e7fSjob 
1319a7e9e7fSjob /*
13245a66391Sclaudio  * Read a string (returns NULL for zero-length strings), allocating
1339a7e9e7fSjob  * space for it.
1349a7e9e7fSjob  */
1359a7e9e7fSjob void
1369a7e9e7fSjob io_str_read(int fd, char **res)
1379a7e9e7fSjob {
1389a7e9e7fSjob 	size_t	 sz;
1399a7e9e7fSjob 
1409a7e9e7fSjob 	io_simple_read(fd, &sz, sizeof(size_t));
14145a66391Sclaudio 	if (sz == 0) {
14245a66391Sclaudio 		*res = NULL;
14345a66391Sclaudio 		return;
14445a66391Sclaudio 	}
1459a7e9e7fSjob 	if ((*res = calloc(sz + 1, 1)) == NULL)
146498a9228Sbenno 		err(1, NULL);
1479a7e9e7fSjob 	io_simple_read(fd, *res, sz);
1489a7e9e7fSjob }
149