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