xref: /openbsd-src/usr.sbin/rpki-client/io.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: io.c,v 1.11 2020/12/18 16:58:59 claudio Exp $ */
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 
18 #include <sys/queue.h>
19 
20 #include <assert.h>
21 #include <err.h>
22 #include <fcntl.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "extern.h"
29 
30 void
31 io_socket_blocking(int fd)
32 {
33 	int	 fl;
34 
35 	if ((fl = fcntl(fd, F_GETFL, 0)) == -1)
36 		err(1, "fcntl");
37 	if (fcntl(fd, F_SETFL, fl & ~O_NONBLOCK) == -1)
38 		err(1, "fcntl");
39 }
40 
41 void
42 io_socket_nonblocking(int fd)
43 {
44 	int	 fl;
45 
46 	if ((fl = fcntl(fd, F_GETFL, 0)) == -1)
47 		err(1, "fcntl");
48 	if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1)
49 		err(1, "fcntl");
50 }
51 
52 /*
53  * Blocking write of a binary buffer.
54  * Buffers of length zero are simply ignored.
55  */
56 void
57 io_simple_write(int fd, const void *res, size_t sz)
58 {
59 	ssize_t	 ssz;
60 
61 	if (sz == 0)
62 		return;
63 	if ((ssz = write(fd, res, sz)) == -1)
64 		err(1, "write");
65 	else if ((size_t)ssz != sz)
66 		errx(1, "write: short write");
67 }
68 
69 /*
70  * Like io_simple_write() but into a buffer.
71  */
72 void
73 io_simple_buffer(char **b, size_t *bsz,
74 	size_t *bmax, const void *res, size_t sz)
75 {
76 
77 	if (*bsz + sz > *bmax) {
78 		if ((*b = realloc(*b, *bsz + sz)) == NULL)
79 			err(1, NULL);
80 		*bmax = *bsz + sz;
81 	}
82 
83 	memcpy(*b + *bsz, res, sz);
84 	*bsz += sz;
85 }
86 
87 /*
88  * Like io_buf_write() but into a buffer.
89  */
90 void
91 io_buf_buffer(char **b, size_t *bsz,
92 	size_t *bmax, const void *p, size_t sz)
93 {
94 
95 	io_simple_buffer(b, bsz, bmax, &sz, sizeof(size_t));
96 	if (sz > 0)
97 		io_simple_buffer(b, bsz, bmax, p, sz);
98 }
99 
100 /*
101  * Like io_str_write() but into a buffer.
102  */
103 void
104 io_str_buffer(char **b, size_t *bsz, size_t *bmax, const char *p)
105 {
106 	size_t	 sz = (p == NULL) ? 0 : strlen(p);
107 
108 	io_buf_buffer(b, bsz, bmax, p, sz);
109 }
110 
111 /*
112  * Read of a binary buffer that must be on a blocking descriptor.
113  * Does nothing if "sz" is zero.
114  * This will fail and exit on EOF.
115  */
116 void
117 io_simple_read(int fd, void *res, size_t sz)
118 {
119 	ssize_t	 ssz;
120 	char	*tmp;
121 
122 	tmp = res; /* arithmetic on a pointer to void is a GNU extension */
123 again:
124 	if (sz == 0)
125 		return;
126 	if ((ssz = read(fd, tmp, sz)) == -1)
127 		err(1, "read");
128 	else if (ssz == 0)
129 		errx(1, "read: unexpected end of file");
130 	else if ((size_t)ssz == sz)
131 		return;
132 	sz -= ssz;
133 	tmp += ssz;
134 	goto again;
135 }
136 
137 /*
138  * Read a binary buffer, allocating space for it.
139  * If the buffer is zero-sized, this won't allocate "res", but
140  * will still initialise it to NULL.
141  */
142 void
143 io_buf_read_alloc(int fd, void **res, size_t *sz)
144 {
145 
146 	*res = NULL;
147 	io_simple_read(fd, sz, sizeof(size_t));
148 	if (*sz == 0)
149 		return;
150 	if ((*res = malloc(*sz)) == NULL)
151 		err(1, NULL);
152 	io_simple_read(fd, *res, *sz);
153 }
154 
155 /*
156  * Read a string (returns NULL for zero-length strings), allocating
157  * space for it.
158  */
159 void
160 io_str_read(int fd, char **res)
161 {
162 	size_t	 sz;
163 
164 	io_simple_read(fd, &sz, sizeof(size_t));
165 	if (sz == 0) {
166 		*res = NULL;
167 		return;
168 	}
169 	if ((*res = calloc(sz + 1, 1)) == NULL)
170 		err(1, NULL);
171 	io_simple_read(fd, *res, sz);
172 }
173