1 /* $NetBSD: fsutil.c,v 1.7 1998/07/30 17:41:03 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $FreeBSD$ 36 */ 37 38 #include <sys/cdefs.h> 39 #ifndef lint 40 __RCSID("$NetBSD: fsutil.c,v 1.7 1998/07/30 17:41:03 thorpej Exp $"); 41 #endif /* not lint */ 42 43 #include <stdio.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #if __STDC__ 47 #include <stdarg.h> 48 #else 49 #include <varargs.h> 50 #endif 51 #include <errno.h> 52 #include <fstab.h> 53 #include <err.h> 54 55 #include <sys/types.h> 56 #include <sys/stat.h> 57 58 #include "fsutil.h" 59 60 static const char *dev = NULL; 61 static int hot = 0; 62 static int preen = 0; 63 64 extern char *__progname; 65 66 static void vmsg __P((int, const char *, va_list)); 67 68 void 69 setcdevname(cd, pr) 70 const char *cd; 71 int pr; 72 { 73 dev = cd; 74 preen = pr; 75 } 76 77 const char * 78 cdevname() 79 { 80 return dev; 81 } 82 83 int 84 hotroot() 85 { 86 return hot; 87 } 88 89 /*VARARGS*/ 90 void 91 #if __STDC__ 92 errexit(const char *fmt, ...) 93 #else 94 errexit(va_alist) 95 va_dcl 96 #endif 97 { 98 va_list ap; 99 100 #if __STDC__ 101 va_start(ap, fmt); 102 #else 103 const char *fmt; 104 105 va_start(ap); 106 fmt = va_arg(ap, const char *); 107 #endif 108 (void) vfprintf(stderr, fmt, ap); 109 va_end(ap); 110 exit(8); 111 } 112 113 static void 114 vmsg(fatal, fmt, ap) 115 int fatal; 116 const char *fmt; 117 va_list ap; 118 { 119 if (!fatal && preen) 120 (void) printf("%s: ", dev); 121 122 (void) vprintf(fmt, ap); 123 124 if (fatal && preen) 125 (void) printf("\n"); 126 127 if (fatal && preen) { 128 (void) printf( 129 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n", 130 dev, __progname); 131 exit(8); 132 } 133 } 134 135 /*VARARGS*/ 136 void 137 #if __STDC__ 138 pfatal(const char *fmt, ...) 139 #else 140 pfatal(va_alist) 141 va_dcl 142 #endif 143 { 144 va_list ap; 145 146 #if __STDC__ 147 va_start(ap, fmt); 148 #else 149 const char *fmt; 150 151 va_start(ap); 152 fmt = va_arg(ap, const char *); 153 #endif 154 vmsg(1, fmt, ap); 155 va_end(ap); 156 } 157 158 /*VARARGS*/ 159 void 160 #if __STDC__ 161 pwarn(const char *fmt, ...) 162 #else 163 pwarn(va_alist) 164 va_dcl 165 #endif 166 { 167 va_list ap; 168 #if __STDC__ 169 va_start(ap, fmt); 170 #else 171 const char *fmt; 172 173 va_start(ap); 174 fmt = va_arg(ap, const char *); 175 #endif 176 vmsg(0, fmt, ap); 177 va_end(ap); 178 } 179 180 void 181 perror(s) 182 const char *s; 183 { 184 pfatal("%s (%s)", s, strerror(errno)); 185 } 186 187 void 188 #if __STDC__ 189 panic(const char *fmt, ...) 190 #else 191 panic(va_alist) 192 va_dcl 193 #endif 194 { 195 va_list ap; 196 197 #if __STDC__ 198 va_start(ap, fmt); 199 #else 200 const char *fmt; 201 202 va_start(ap); 203 fmt = va_arg(ap, const char *); 204 #endif 205 vmsg(1, fmt, ap); 206 va_end(ap); 207 exit(8); 208 } 209 210 const char * 211 unrawname(name) 212 const char *name; 213 { 214 static char unrawbuf[32]; 215 const char *dp; 216 struct stat stb; 217 218 if ((dp = strrchr(name, '/')) == 0) 219 return (name); 220 if (stat(name, &stb) < 0) 221 return (name); 222 if (!S_ISCHR(stb.st_mode)) 223 return (name); 224 if (dp[1] != 'r') 225 return (name); 226 (void)snprintf(unrawbuf, 32, "%.*s/%s", (int)(dp - name), name, dp + 2); 227 return (unrawbuf); 228 } 229 230 const char * 231 rawname(name) 232 const char *name; 233 { 234 static char rawbuf[32]; 235 const char *dp; 236 237 if ((dp = strrchr(name, '/')) == 0) 238 return (0); 239 (void)snprintf(rawbuf, 32, "%.*s/r%s", (int)(dp - name), name, dp + 1); 240 return (rawbuf); 241 } 242 243 const char * 244 devcheck(origname) 245 const char *origname; 246 { 247 struct stat stslash, stchar; 248 249 if (stat("/", &stslash) < 0) { 250 perror("/"); 251 printf("Can't stat root\n"); 252 return (origname); 253 } 254 if (stat(origname, &stchar) < 0) { 255 perror(origname); 256 printf("Can't stat %s\n", origname); 257 return (origname); 258 } 259 if (!S_ISCHR(stchar.st_mode)) { 260 perror(origname); 261 printf("%s is not a char device\n", origname); 262 } 263 return (origname); 264 } 265 266 #if 0 267 /* 268 * XXX this code is from NetBSD, but fails in FreeBSD because we 269 * don't have blockdevs. I don't think its needed. 270 */ 271 const char * 272 blockcheck(origname) 273 const char *origname; 274 { 275 struct stat stslash, stblock, stchar; 276 const char *newname, *raw; 277 struct fstab *fsp; 278 int retried = 0; 279 280 hot = 0; 281 if (stat("/", &stslash) < 0) { 282 perror("/"); 283 printf("Can't stat root\n"); 284 return (origname); 285 } 286 newname = origname; 287 retry: 288 if (stat(newname, &stblock) < 0) { 289 perror(newname); 290 printf("Can't stat %s\n", newname); 291 return (origname); 292 } 293 if (S_ISBLK(stblock.st_mode)) { 294 if (stslash.st_dev == stblock.st_rdev) 295 hot++; 296 raw = rawname(newname); 297 if (stat(raw, &stchar) < 0) { 298 perror(raw); 299 printf("Can't stat %s\n", raw); 300 return (origname); 301 } 302 if (S_ISCHR(stchar.st_mode)) { 303 return (raw); 304 } else { 305 printf("%s is not a character device\n", raw); 306 return (origname); 307 } 308 } else if (S_ISCHR(stblock.st_mode) && !retried) { 309 newname = unrawname(newname); 310 retried++; 311 goto retry; 312 } else if ((fsp = getfsfile(newname)) != 0 && !retried) { 313 newname = fsp->fs_spec; 314 retried++; 315 goto retry; 316 } 317 /* 318 * Not a block or character device, just return name and 319 * let the user decide whether to use it. 320 */ 321 return (origname); 322 } 323 #endif 324 325 326 void * 327 emalloc(s) 328 size_t s; 329 { 330 void *p; 331 332 p = malloc(s); 333 if (p == NULL) 334 err(1, "malloc failed"); 335 return (p); 336 } 337 338 339 void * 340 erealloc(p, s) 341 void *p; 342 size_t s; 343 { 344 void *q; 345 346 q = realloc(p, s); 347 if (q == NULL) 348 err(1, "realloc failed"); 349 return (q); 350 } 351 352 353 char * 354 estrdup(s) 355 const char *s; 356 { 357 char *p; 358 359 p = strdup(s); 360 if (p == NULL) 361 err(1, "strdup failed"); 362 return (p); 363 } 364