1 1.6 riastrad /* $NetBSD: utils.c,v 1.6 2017/03/21 13:56:38 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /*- 4 1.1 riastrad * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 1.1 riastrad * All rights reserved. 6 1.1 riastrad * 7 1.1 riastrad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 riastrad * by Taylor R. Campbell. 9 1.1 riastrad * 10 1.1 riastrad * Redistribution and use in source and binary forms, with or without 11 1.1 riastrad * modification, are permitted provided that the following conditions 12 1.1 riastrad * are met: 13 1.1 riastrad * 1. Redistributions of source code must retain the above copyright 14 1.1 riastrad * notice, this list of conditions and the following disclaimer. 15 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 riastrad * notice, this list of conditions and the following disclaimer in the 17 1.1 riastrad * documentation and/or other materials provided with the distribution. 18 1.1 riastrad * 19 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 riastrad */ 31 1.1 riastrad 32 1.1 riastrad #include <sys/cdefs.h> 33 1.6 riastrad __RCSID("$NetBSD: utils.c,v 1.6 2017/03/21 13:56:38 riastradh Exp $"); 34 1.1 riastrad 35 1.1 riastrad #include <sys/types.h> 36 1.1 riastrad 37 1.1 riastrad #include <assert.h> 38 1.1 riastrad #include <err.h> 39 1.1 riastrad #include <errno.h> 40 1.1 riastrad #include <inttypes.h> 41 1.1 riastrad #include <limits.h> 42 1.2 riastrad #include <signal.h> 43 1.1 riastrad #include <stdio.h> 44 1.1 riastrad #include <stdlib.h> 45 1.1 riastrad #include <string.h> 46 1.1 riastrad #include <unistd.h> 47 1.1 riastrad 48 1.3 riastrad #include "common.h" 49 1.3 riastrad 50 1.1 riastrad /* XXX Seems to be missing from <stdio.h>... */ 51 1.1 riastrad int snprintf_ss(char *restrict, size_t, const char *restrict, ...) 52 1.1 riastrad __printflike(3, 4); 53 1.1 riastrad int vsnprintf_ss(char *restrict, size_t, const char *restrict, va_list) 54 1.1 riastrad __printflike(3, 0); 55 1.1 riastrad 56 1.1 riastrad #include "utils.h" 57 1.1 riastrad 58 1.1 riastrad /* 59 1.1 riastrad * Read, returning partial data only at end of file. 60 1.1 riastrad */ 61 1.1 riastrad ssize_t 62 1.6 riastrad read_block(int fd, void *buf, size_t len) 63 1.1 riastrad { 64 1.6 riastrad char *p = buf; 65 1.6 riastrad size_t n = len; 66 1.6 riastrad const char *const end __diagused = p + n; 67 1.6 riastrad ssize_t nread = 0; 68 1.1 riastrad 69 1.6 riastrad while (0 < n && (nread = read(fd, p, n)) != 0) { 70 1.6 riastrad if (nread == -1) 71 1.1 riastrad return -1; 72 1.6 riastrad p += MIN(n, (size_t)nread); 73 1.6 riastrad n -= MIN(n, (size_t)nread); 74 1.6 riastrad assert(p + n == end); 75 1.1 riastrad } 76 1.1 riastrad 77 1.6 riastrad assert(n == 0 || nread == 0); /* complete read or EOF */ 78 1.6 riastrad return len - n; 79 1.1 riastrad } 80 1.1 riastrad 81 1.1 riastrad /* 82 1.3 riastrad * Read from a specified position, returning partial data only at end 83 1.3 riastrad * of file. 84 1.3 riastrad */ 85 1.3 riastrad ssize_t 86 1.6 riastrad pread_block(int fd, void *buf, size_t len, off_t fdpos) 87 1.3 riastrad { 88 1.6 riastrad char *p = buf; 89 1.6 riastrad size_t n = len; 90 1.6 riastrad const char *const end __diagused = p + n; 91 1.6 riastrad ssize_t nread = 0; 92 1.3 riastrad 93 1.4 riastrad assert(0 <= fdpos); 94 1.6 riastrad assert(n <= OFF_MAX - (uintmax_t)fdpos); 95 1.6 riastrad const off_t endpos __diagused = fdpos + n; 96 1.3 riastrad 97 1.6 riastrad while (0 < n && (nread = pread(fd, p, n, fdpos)) != 0) { 98 1.6 riastrad if (nread == -1) 99 1.3 riastrad return -1; 100 1.6 riastrad fdpos += MIN(n, (size_t)nread); 101 1.6 riastrad p += MIN(n, (size_t)nread); 102 1.6 riastrad n -= MIN(n, (size_t)nread); 103 1.6 riastrad assert(p + n == end); 104 1.6 riastrad assert(fdpos + (off_t)n == endpos); 105 1.3 riastrad } 106 1.3 riastrad 107 1.6 riastrad assert(n == 0 || nread == 0); /* complete read or EOF */ 108 1.6 riastrad return len - n; 109 1.3 riastrad } 110 1.3 riastrad 111 1.3 riastrad /* 112 1.1 riastrad * Signal-safe err/warn utilities. The errno varieties are limited to 113 1.1 riastrad * having no format arguments for reasons of laziness. 114 1.1 riastrad */ 115 1.1 riastrad 116 1.1 riastrad void 117 1.1 riastrad err_ss(int exit_value, const char *msg) 118 1.1 riastrad { 119 1.1 riastrad warn_ss(msg); 120 1.1 riastrad _Exit(exit_value); 121 1.1 riastrad } 122 1.1 riastrad 123 1.1 riastrad void 124 1.1 riastrad errx_ss(int exit_value, const char *format, ...) 125 1.1 riastrad { 126 1.1 riastrad va_list va; 127 1.1 riastrad 128 1.1 riastrad va_start(va, format); 129 1.1 riastrad vwarnx_ss(format, va); 130 1.1 riastrad va_end(va); 131 1.1 riastrad _Exit(exit_value); 132 1.1 riastrad } 133 1.1 riastrad 134 1.1 riastrad void 135 1.1 riastrad warn_ss(const char *msg) 136 1.1 riastrad { 137 1.1 riastrad int error = errno; 138 1.1 riastrad 139 1.1 riastrad warnx_ss("%s: %s", msg, strerror(error)); 140 1.1 riastrad 141 1.1 riastrad errno = error; 142 1.1 riastrad } 143 1.1 riastrad 144 1.1 riastrad void 145 1.1 riastrad warnx_ss(const char *format, ...) 146 1.1 riastrad { 147 1.1 riastrad va_list va; 148 1.1 riastrad 149 1.1 riastrad va_start(va, format); 150 1.1 riastrad vwarnx_ss(format, va); 151 1.1 riastrad va_end(va); 152 1.1 riastrad } 153 1.1 riastrad 154 1.1 riastrad void 155 1.1 riastrad vwarnx_ss(const char *format, va_list va) 156 1.1 riastrad { 157 1.1 riastrad char buf[128]; 158 1.1 riastrad 159 1.1 riastrad (void)strlcpy(buf, getprogname(), sizeof(buf)); 160 1.1 riastrad (void)strlcat(buf, ": ", sizeof(buf)); 161 1.1 riastrad 162 1.1 riastrad const int n = vsnprintf_ss(&buf[strlen(buf)], (sizeof(buf) - 163 1.1 riastrad strlen(buf)), format, va); 164 1.1 riastrad if (n <= 0) { 165 1.1 riastrad const char fallback[] = 166 1.1 riastrad "vndcompress: Help! I'm trapped in a signal handler!\n"; 167 1.1 riastrad (void)write(STDERR_FILENO, fallback, __arraycount(fallback)); 168 1.1 riastrad } else { 169 1.1 riastrad (void)strlcat(buf, "\n", sizeof(buf)); 170 1.1 riastrad (void)write(STDERR_FILENO, buf, strlen(buf)); 171 1.1 riastrad } 172 1.1 riastrad } 173 1.2 riastrad 174 1.2 riastrad void 175 1.2 riastrad block_signals(sigset_t *old_sigmask) 176 1.2 riastrad { 177 1.2 riastrad sigset_t block; 178 1.2 riastrad 179 1.2 riastrad (void)sigfillset(&block); 180 1.2 riastrad (void)sigprocmask(SIG_BLOCK, &block, old_sigmask); 181 1.2 riastrad } 182 1.2 riastrad 183 1.2 riastrad void 184 1.2 riastrad restore_sigmask(const sigset_t *sigmask) 185 1.2 riastrad { 186 1.2 riastrad 187 1.2 riastrad (void)sigprocmask(SIG_SETMASK, sigmask, NULL); 188 1.2 riastrad } 189