xref: /openbsd/sbin/fsck/fsutil.c (revision b166fb0e)
1*b166fb0eSderaadt /*	$OpenBSD: fsutil.c,v 1.3 2001/05/15 22:03:03 deraadt Exp $	*/
287304b87Stholo /*	$NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $	*/
387304b87Stholo 
487304b87Stholo /*
587304b87Stholo  * Copyright (c) 1990, 1993
687304b87Stholo  *	The Regents of the University of California.  All rights reserved.
787304b87Stholo  *
887304b87Stholo  * Redistribution and use in source and binary forms, with or without
987304b87Stholo  * modification, are permitted provided that the following conditions
1087304b87Stholo  * are met:
1187304b87Stholo  * 1. Redistributions of source code must retain the above copyright
1287304b87Stholo  *    notice, this list of conditions and the following disclaimer.
1387304b87Stholo  * 2. Redistributions in binary form must reproduce the above copyright
1487304b87Stholo  *    notice, this list of conditions and the following disclaimer in the
1587304b87Stholo  *    documentation and/or other materials provided with the distribution.
1687304b87Stholo  * 3. All advertising materials mentioning features or use of this software
1787304b87Stholo  *    must display the following acknowledgement:
1887304b87Stholo  *	This product includes software developed by the University of
1987304b87Stholo  *	California, Berkeley and its contributors.
2087304b87Stholo  * 4. Neither the name of the University nor the names of its contributors
2187304b87Stholo  *    may be used to endorse or promote products derived from this software
2287304b87Stholo  *    without specific prior written permission.
2387304b87Stholo  *
2487304b87Stholo  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2587304b87Stholo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2687304b87Stholo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2787304b87Stholo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2887304b87Stholo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2987304b87Stholo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3087304b87Stholo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3187304b87Stholo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3287304b87Stholo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3387304b87Stholo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3487304b87Stholo  * SUCH DAMAGE.
3587304b87Stholo  */
3687304b87Stholo #ifndef lint
3787304b87Stholo static char rcsid[] = "$NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $";
3887304b87Stholo #endif /* not lint */
3987304b87Stholo 
4087304b87Stholo #include <stdio.h>
4187304b87Stholo #include <string.h>
4287304b87Stholo #include <stdlib.h>
43f8629afcSmickey #ifdef __STDC__
4487304b87Stholo #include <stdarg.h>
4587304b87Stholo #else
4687304b87Stholo #include <varargs.h>
4787304b87Stholo #endif
4887304b87Stholo #include <errno.h>
4987304b87Stholo #include <fstab.h>
5087304b87Stholo #include <err.h>
5187304b87Stholo 
5287304b87Stholo #include <sys/types.h>
5387304b87Stholo #include <sys/stat.h>
5487304b87Stholo 
5587304b87Stholo #include "fsutil.h"
5687304b87Stholo 
5787304b87Stholo static const char *dev = NULL;
5887304b87Stholo static int hot = 0;
5987304b87Stholo static int preen = 0;
6087304b87Stholo 
6187304b87Stholo extern char *__progname;
6287304b87Stholo 
6387304b87Stholo static void vmsg __P((int, const char *, va_list));
6487304b87Stholo 
6587304b87Stholo void
6687304b87Stholo setcdevname(cd, pr)
6787304b87Stholo 	const char *cd;
6887304b87Stholo 	int pr;
6987304b87Stholo {
7087304b87Stholo 	dev = cd;
7187304b87Stholo 	preen = pr;
7287304b87Stholo }
7387304b87Stholo 
7487304b87Stholo const char *
7587304b87Stholo cdevname()
7687304b87Stholo {
7787304b87Stholo 	return dev;
7887304b87Stholo }
7987304b87Stholo 
8087304b87Stholo int
8187304b87Stholo hotroot()
8287304b87Stholo {
8387304b87Stholo 	return hot;
8487304b87Stholo }
8587304b87Stholo 
8687304b87Stholo /*VARARGS*/
8787304b87Stholo void
88f8629afcSmickey #ifdef __STDC__
8987304b87Stholo errexit(const char *fmt, ...)
9087304b87Stholo #else
9187304b87Stholo errexit(fmt, va_alist)
9287304b87Stholo 	char *fmt;
9387304b87Stholo 	va_dcl
9487304b87Stholo #endif
9587304b87Stholo {
9687304b87Stholo 	va_list ap;
9787304b87Stholo 
98f8629afcSmickey #ifdef __STDC__
9987304b87Stholo 	va_start(ap, fmt);
10087304b87Stholo #else
10187304b87Stholo 	va_start(ap);
10287304b87Stholo #endif
10387304b87Stholo 	(void) vfprintf(stderr, fmt, ap);
10487304b87Stholo 	va_end(ap);
10587304b87Stholo 	exit(8);
10687304b87Stholo }
10787304b87Stholo 
10887304b87Stholo static void
10987304b87Stholo vmsg(fatal, fmt, ap)
11087304b87Stholo 	int fatal;
11187304b87Stholo 	const char *fmt;
11287304b87Stholo 	va_list ap;
11387304b87Stholo {
11487304b87Stholo 	if (!fatal && preen)
11587304b87Stholo 		(void) printf("%s: ", dev);
11687304b87Stholo 
11787304b87Stholo 	(void) vprintf(fmt, ap);
11887304b87Stholo 
11987304b87Stholo 	if (fatal && preen)
12087304b87Stholo 		(void) printf("\n");
12187304b87Stholo 
12287304b87Stholo 	if (fatal && preen) {
12387304b87Stholo 		(void) printf(
12487304b87Stholo 		    "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
12587304b87Stholo 		    dev, __progname);
12687304b87Stholo 		exit(8);
12787304b87Stholo 	}
12887304b87Stholo }
12987304b87Stholo 
13087304b87Stholo /*VARARGS*/
13187304b87Stholo void
132f8629afcSmickey #ifdef __STDC__
13387304b87Stholo pfatal(const char *fmt, ...)
13487304b87Stholo #else
13587304b87Stholo pfatal(fmt, va_alist)
13687304b87Stholo 	char *fmt;
13787304b87Stholo 	va_dcl
13887304b87Stholo #endif
13987304b87Stholo {
14087304b87Stholo 	va_list ap;
14187304b87Stholo 
142f8629afcSmickey #ifdef __STDC__
14387304b87Stholo 	va_start(ap, fmt);
14487304b87Stholo #else
14587304b87Stholo 	va_start(ap);
14687304b87Stholo #endif
14787304b87Stholo 	vmsg(1, fmt, ap);
14887304b87Stholo 	va_end(ap);
14987304b87Stholo }
15087304b87Stholo 
15187304b87Stholo /*VARARGS*/
15287304b87Stholo void
153f8629afcSmickey #ifdef __STDC__
15487304b87Stholo pwarn(const char *fmt, ...)
15587304b87Stholo #else
15687304b87Stholo pwarn(fmt, va_alist)
15787304b87Stholo 	char *fmt;
15887304b87Stholo 	va_dcl
15987304b87Stholo #endif
16087304b87Stholo {
16187304b87Stholo 	va_list ap;
16287304b87Stholo 
163f8629afcSmickey #ifdef __STDC__
16487304b87Stholo 	va_start(ap, fmt);
16587304b87Stholo #else
16687304b87Stholo 	va_start(ap);
16787304b87Stholo #endif
16887304b87Stholo 	vmsg(0, fmt, ap);
16987304b87Stholo 	va_end(ap);
17087304b87Stholo }
17187304b87Stholo 
17287304b87Stholo void
17387304b87Stholo perror(s)
17487304b87Stholo 	const char *s;
17587304b87Stholo {
17687304b87Stholo 	pfatal("%s (%s)", s, strerror(errno));
17787304b87Stholo }
17887304b87Stholo 
17987304b87Stholo void
180f8629afcSmickey #ifdef __STDC__
18187304b87Stholo panic(const char *fmt, ...)
18287304b87Stholo #else
18387304b87Stholo panic(fmt, va_alist)
18487304b87Stholo 	char *fmt;
18587304b87Stholo 	va_dcl
18687304b87Stholo #endif
18787304b87Stholo {
18887304b87Stholo 	va_list ap;
18987304b87Stholo 
190f8629afcSmickey #ifdef __STDC__
19187304b87Stholo 	va_start(ap, fmt);
19287304b87Stholo #else
19387304b87Stholo 	va_start(ap);
19487304b87Stholo #endif
19587304b87Stholo 	vmsg(1, fmt, ap);
19687304b87Stholo 	va_end(ap);
19787304b87Stholo 	exit(8);
19887304b87Stholo }
19987304b87Stholo 
20087304b87Stholo char *
20187304b87Stholo unrawname(name)
20287304b87Stholo 	char *name;
20387304b87Stholo {
20487304b87Stholo 	char *dp;
20587304b87Stholo 	struct stat stb;
20687304b87Stholo 
20787304b87Stholo 	if ((dp = strrchr(name, '/')) == 0)
20887304b87Stholo 		return (name);
20987304b87Stholo 	if (stat(name, &stb) < 0)
21087304b87Stholo 		return (name);
21187304b87Stholo 	if (!S_ISCHR(stb.st_mode))
21287304b87Stholo 		return (name);
21387304b87Stholo 	if (dp[1] != 'r')
21487304b87Stholo 		return (name);
21587304b87Stholo 	(void)strcpy(&dp[1], &dp[2]);
21687304b87Stholo 	return (name);
21787304b87Stholo }
21887304b87Stholo 
21987304b87Stholo char *
22087304b87Stholo rawname(name)
22187304b87Stholo 	char *name;
22287304b87Stholo {
22387304b87Stholo 	static char rawbuf[32];
22487304b87Stholo 	char *dp;
22587304b87Stholo 
22687304b87Stholo 	if ((dp = strrchr(name, '/')) == 0)
22787304b87Stholo 		return (0);
22887304b87Stholo 	*dp = 0;
22987304b87Stholo 	(void)strcpy(rawbuf, name);
23087304b87Stholo 	*dp = '/';
23187304b87Stholo 	(void)strcat(rawbuf, "/r");
23287304b87Stholo 	(void)strcat(rawbuf, &dp[1]);
23387304b87Stholo 	return (rawbuf);
23487304b87Stholo }
23587304b87Stholo 
23687304b87Stholo char *
23787304b87Stholo blockcheck(origname)
23887304b87Stholo 	char *origname;
23987304b87Stholo {
24087304b87Stholo 	struct stat stslash, stblock, stchar;
24187304b87Stholo 	char *newname, *raw;
24287304b87Stholo 	struct fstab *fsp;
24387304b87Stholo 	int retried = 0;
24487304b87Stholo 
24587304b87Stholo 	hot = 0;
24687304b87Stholo 	if (stat("/", &stslash) < 0) {
24787304b87Stholo 		perror("/");
24887304b87Stholo 		printf("Can't stat root\n");
24987304b87Stholo 		return (origname);
25087304b87Stholo 	}
25187304b87Stholo 	newname = origname;
25287304b87Stholo retry:
25387304b87Stholo 	if (stat(newname, &stblock) < 0) {
25487304b87Stholo 		perror(newname);
25587304b87Stholo 		printf("Can't stat %s\n", newname);
25687304b87Stholo 		return (origname);
25787304b87Stholo 	}
25887304b87Stholo 	if (S_ISBLK(stblock.st_mode)) {
25987304b87Stholo 		if (stslash.st_dev == stblock.st_rdev)
26087304b87Stholo 			hot++;
26187304b87Stholo 		raw = rawname(newname);
26287304b87Stholo 		if (stat(raw, &stchar) < 0) {
26387304b87Stholo 			perror(raw);
26487304b87Stholo 			printf("Can't stat %s\n", raw);
26587304b87Stholo 			return (origname);
26687304b87Stholo 		}
26787304b87Stholo 		if (S_ISCHR(stchar.st_mode)) {
26887304b87Stholo 			return (raw);
26987304b87Stholo 		} else {
27087304b87Stholo 			printf("%s is not a character device\n", raw);
27187304b87Stholo 			return (origname);
27287304b87Stholo 		}
27387304b87Stholo 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
27487304b87Stholo 		newname = unrawname(newname);
27587304b87Stholo 		retried++;
27687304b87Stholo 		goto retry;
27787304b87Stholo 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
27887304b87Stholo 		newname = fsp->fs_spec;
27987304b87Stholo 		retried++;
28087304b87Stholo 		goto retry;
28187304b87Stholo 	}
28287304b87Stholo 	/*
28387304b87Stholo 	 * Not a block or character device, just return name and
28487304b87Stholo 	 * let the user decide whether to use it.
28587304b87Stholo 	 */
28687304b87Stholo 	return (origname);
28787304b87Stholo }
28887304b87Stholo 
28987304b87Stholo 
29087304b87Stholo void *
29187304b87Stholo emalloc(s)
29287304b87Stholo 	size_t s;
29387304b87Stholo {
294*b166fb0eSderaadt 	void *p;
295*b166fb0eSderaadt 
296*b166fb0eSderaadt 	if (s == 0)
297*b166fb0eSderaadt 		err(1, "malloc failed");
298*b166fb0eSderaadt 	p = malloc(s);
29987304b87Stholo 	if (p == NULL)
30087304b87Stholo 		err(1, "malloc failed");
30187304b87Stholo 	return p;
30287304b87Stholo }
30387304b87Stholo 
30487304b87Stholo 
30587304b87Stholo void *
30687304b87Stholo erealloc(p, s)
30787304b87Stholo 	void *p;
30887304b87Stholo 	size_t s;
30987304b87Stholo {
310*b166fb0eSderaadt 	if (s == 0)
311*b166fb0eSderaadt 		err(1, "realloc failed");
31287304b87Stholo 	p = realloc(p, s);
31387304b87Stholo 	if (p == NULL)
31487304b87Stholo 		err(1, "realloc failed");
31587304b87Stholo 	return p;
31687304b87Stholo }
31787304b87Stholo 
31887304b87Stholo 
31987304b87Stholo char *
32087304b87Stholo estrdup(s)
32187304b87Stholo 	const char *s;
32287304b87Stholo {
32387304b87Stholo 	char *p = strdup(s);
32487304b87Stholo 	if (p == NULL)
32587304b87Stholo 		err(1, "strdup failed");
32687304b87Stholo 	return p;
32787304b87Stholo }
328