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>... */ 51int snprintf_ss(char *restrict, size_t, const char *restrict, ...) 52 __printflike(3, 4); 53int 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 */ 61ssize_t 62read_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 */ 85ssize_t 86pread_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 116void 117err_ss(int exit_value, const char *msg) 118{ 119 warn_ss(msg); 120 _Exit(exit_value); 121} 122 123void 124errx_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 134void 135warn_ss(const char *msg) 136{ 137 int error = errno; 138 139 warnx_ss("%s: %s", msg, strerror(error)); 140 141 errno = error; 142} 143 144void 145warnx_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 154void 155vwarnx_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 174void 175block_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 183void 184restore_sigmask(const sigset_t *sigmask) 185{ 186 187 (void)sigprocmask(SIG_SETMASK, sigmask, NULL); 188} 189