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