1 /* $OpenBSD: fsutil.c,v 1.22 2015/09/27 05:25:00 guenther Exp $ */ 2 /* $NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <stdlib.h> 36 #include <stdarg.h> 37 #include <errno.h> 38 #include <fstab.h> 39 #include <limits.h> 40 #include <err.h> 41 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 45 #include "fsutil.h" 46 47 static const char *dev = NULL; 48 static const char *origdev = NULL; 49 static int hot = 0; 50 static int preen = 0; 51 52 extern char *__progname; 53 54 static void vmsg(int, const char *, va_list); 55 56 void 57 setcdevname(const char *cd, const char *ocd, int pr) 58 { 59 dev = cd; 60 origdev = ocd; 61 preen = pr; 62 } 63 64 const char * 65 cdevname(void) 66 { 67 return dev; 68 } 69 70 int 71 hotroot(void) 72 { 73 return hot; 74 } 75 76 void 77 errexit(const char *fmt, ...) 78 { 79 va_list ap; 80 81 va_start(ap, fmt); 82 (void) vfprintf(stderr, fmt, ap); 83 va_end(ap); 84 exit(8); 85 } 86 87 static void 88 vmsg(int fatal, const char *fmt, va_list ap) 89 { 90 if (!fatal && preen) { 91 if (origdev) 92 printf("%s (%s): ", dev, origdev); 93 else 94 printf("%s: ", dev); 95 } 96 97 (void) vprintf(fmt, ap); 98 99 if (fatal && preen) { 100 printf("\n"); 101 if (origdev) 102 printf("%s (%s): ", dev, origdev); 103 else 104 printf("%s: ", dev); 105 printf("UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n", 106 __progname); 107 exit(8); 108 } 109 } 110 111 void 112 pfatal(const char *fmt, ...) 113 { 114 va_list ap; 115 116 va_start(ap, fmt); 117 vmsg(1, fmt, ap); 118 va_end(ap); 119 } 120 121 void 122 pwarn(const char *fmt, ...) 123 { 124 va_list ap; 125 126 va_start(ap, fmt); 127 vmsg(0, fmt, ap); 128 va_end(ap); 129 } 130 131 void 132 xperror(const char *s) 133 { 134 pfatal("%s (%s)", s, strerror(errno)); 135 } 136 137 void 138 panic(const char *fmt, ...) 139 { 140 va_list ap; 141 142 va_start(ap, fmt); 143 vmsg(1, fmt, ap); 144 va_end(ap); 145 exit(8); 146 } 147 148 char * 149 unrawname(char *name) 150 { 151 char *dp; 152 struct stat stb; 153 154 if ((dp = strrchr(name, '/')) == NULL) 155 return (name); 156 if (stat(name, &stb) < 0) 157 return (name); 158 if (!S_ISCHR(stb.st_mode)) 159 return (name); 160 if (dp[1] != 'r') 161 return (name); 162 (void)memmove(&dp[1], &dp[2], strlen(&dp[2]) + 1); 163 return (name); 164 } 165 166 char * 167 rawname(char *name) 168 { 169 static char rawbuf[PATH_MAX]; 170 char *dp; 171 172 if ((dp = strrchr(name, '/')) == NULL) 173 return (0); 174 *dp = 0; 175 (void)strlcpy(rawbuf, name, sizeof rawbuf); 176 *dp = '/'; 177 (void)strlcat(rawbuf, "/r", sizeof rawbuf); 178 (void)strlcat(rawbuf, &dp[1], sizeof rawbuf); 179 return (rawbuf); 180 } 181 182 char * 183 blockcheck(char *origname) 184 { 185 struct stat stslash, stblock, stchar; 186 char *newname, *raw; 187 struct fstab *fsp; 188 int retried = 0; 189 190 hot = 0; 191 if (stat("/", &stslash) < 0) { 192 xperror("/"); 193 printf("Can't stat root\n"); 194 return (origname); 195 } 196 newname = origname; 197 retry: 198 if (stat(newname, &stblock) < 0) 199 return (origname); 200 201 if (S_ISBLK(stblock.st_mode)) { 202 if (stslash.st_dev == stblock.st_rdev) 203 hot++; 204 raw = rawname(newname); 205 if (stat(raw, &stchar) < 0) { 206 xperror(raw); 207 printf("Can't stat %s\n", raw); 208 return (origname); 209 } 210 if (S_ISCHR(stchar.st_mode)) { 211 return (raw); 212 } else { 213 printf("%s is not a character device\n", raw); 214 return (origname); 215 } 216 } else if (S_ISCHR(stblock.st_mode) && !retried) { 217 newname = unrawname(newname); 218 retried++; 219 goto retry; 220 } else if ((fsp = getfsfile(newname)) != 0 && !retried) { 221 newname = fsp->fs_spec; 222 retried++; 223 goto retry; 224 } 225 /* 226 * Not a block or character device, just return name and 227 * let the user decide whether to use it. 228 */ 229 return (origname); 230 } 231 232 233 void * 234 emalloc(size_t s) 235 { 236 void *p; 237 238 if (s == 0) 239 err(1, "malloc failed"); 240 p = malloc(s); 241 if (p == NULL) 242 err(1, "malloc failed"); 243 return p; 244 } 245 246 247 void * 248 ereallocarray(void *p, size_t n, size_t s) 249 { 250 void *newp; 251 252 if (n == 0 || s == 0) { 253 free(p); 254 err(1, "realloc failed"); 255 } 256 newp = reallocarray(p, n, s); 257 if (newp == NULL) { 258 free(p); 259 err(1, "realloc failed"); 260 } 261 return newp; 262 } 263 264 265 char * 266 estrdup(const char *s) 267 { 268 char *p = strdup(s); 269 if (p == NULL) 270 err(1, "strdup failed"); 271 return p; 272 } 273