xref: /openbsd/sbin/fsck/fsutil.c (revision f4be0e98)
1*f4be0e98Sderaadt /*	$OpenBSD: fsutil.c,v 1.8 2002/09/06 21:16:16 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 
40*f4be0e98Sderaadt #include <sys/param.h>
4187304b87Stholo #include <stdio.h>
4287304b87Stholo #include <string.h>
4387304b87Stholo #include <stdlib.h>
4487304b87Stholo #include <stdarg.h>
4587304b87Stholo #include <errno.h>
4687304b87Stholo #include <fstab.h>
4787304b87Stholo #include <err.h>
4887304b87Stholo 
4987304b87Stholo #include <sys/types.h>
5087304b87Stholo #include <sys/stat.h>
5187304b87Stholo 
5287304b87Stholo #include "fsutil.h"
5387304b87Stholo 
5487304b87Stholo static const char *dev = NULL;
5587304b87Stholo static int hot = 0;
5687304b87Stholo static int preen = 0;
5787304b87Stholo 
5887304b87Stholo extern char *__progname;
5987304b87Stholo 
60c72b5b24Smillert static void vmsg(int, const char *, va_list);
6187304b87Stholo 
6287304b87Stholo void
63bc52e260Sderaadt setcdevname(const char *cd, int pr)
6487304b87Stholo {
6587304b87Stholo 	dev = cd;
6687304b87Stholo 	preen = pr;
6787304b87Stholo }
6887304b87Stholo 
6987304b87Stholo const char *
70bc52e260Sderaadt cdevname(void)
7187304b87Stholo {
7287304b87Stholo 	return dev;
7387304b87Stholo }
7487304b87Stholo 
7587304b87Stholo int
76bc52e260Sderaadt hotroot(void)
7787304b87Stholo {
7887304b87Stholo 	return hot;
7987304b87Stholo }
8087304b87Stholo 
8187304b87Stholo /*VARARGS*/
8287304b87Stholo void
8387304b87Stholo errexit(const char *fmt, ...)
8487304b87Stholo {
8587304b87Stholo 	va_list ap;
8687304b87Stholo 
8787304b87Stholo 	va_start(ap, fmt);
8887304b87Stholo 	(void) vfprintf(stderr, fmt, ap);
8987304b87Stholo 	va_end(ap);
9087304b87Stholo 	exit(8);
9187304b87Stholo }
9287304b87Stholo 
9387304b87Stholo static void
94bc52e260Sderaadt vmsg(int fatal, const char *fmt, va_list ap)
9587304b87Stholo {
9687304b87Stholo 	if (!fatal && preen)
9787304b87Stholo 		(void) printf("%s: ", dev);
9887304b87Stholo 
9987304b87Stholo 	(void) vprintf(fmt, ap);
10087304b87Stholo 
10187304b87Stholo 	if (fatal && preen) {
10262d85a42Sian 		(void) printf("\n");
10387304b87Stholo 		(void) printf(
10487304b87Stholo 		    "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
10587304b87Stholo 		    dev, __progname);
10687304b87Stholo 		exit(8);
10787304b87Stholo 	}
10887304b87Stholo }
10987304b87Stholo 
11087304b87Stholo /*VARARGS*/
11187304b87Stholo void
11287304b87Stholo pfatal(const char *fmt, ...)
11387304b87Stholo {
11487304b87Stholo 	va_list ap;
11587304b87Stholo 
11687304b87Stholo 	va_start(ap, fmt);
11787304b87Stholo 	vmsg(1, fmt, ap);
11887304b87Stholo 	va_end(ap);
11987304b87Stholo }
12087304b87Stholo 
12187304b87Stholo /*VARARGS*/
12287304b87Stholo void
12387304b87Stholo pwarn(const char *fmt, ...)
12487304b87Stholo {
12587304b87Stholo 	va_list ap;
12687304b87Stholo 
12787304b87Stholo 	va_start(ap, fmt);
12887304b87Stholo 	vmsg(0, fmt, ap);
12987304b87Stholo 	va_end(ap);
13087304b87Stholo }
13187304b87Stholo 
13287304b87Stholo void
133bc52e260Sderaadt perror(const char *s)
13487304b87Stholo {
13587304b87Stholo 	pfatal("%s (%s)", s, strerror(errno));
13687304b87Stholo }
13787304b87Stholo 
13887304b87Stholo void
13987304b87Stholo panic(const char *fmt, ...)
14087304b87Stholo {
14187304b87Stholo 	va_list ap;
14287304b87Stholo 
14387304b87Stholo 	va_start(ap, fmt);
14487304b87Stholo 	vmsg(1, fmt, ap);
14587304b87Stholo 	va_end(ap);
14687304b87Stholo 	exit(8);
14787304b87Stholo }
14887304b87Stholo 
14987304b87Stholo char *
150bc52e260Sderaadt unrawname(char *name)
15187304b87Stholo {
15287304b87Stholo 	char *dp;
15387304b87Stholo 	struct stat stb;
15487304b87Stholo 
155*f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
15687304b87Stholo 		return (name);
15787304b87Stholo 	if (stat(name, &stb) < 0)
15887304b87Stholo 		return (name);
15987304b87Stholo 	if (!S_ISCHR(stb.st_mode))
16087304b87Stholo 		return (name);
16187304b87Stholo 	if (dp[1] != 'r')
16287304b87Stholo 		return (name);
16387304b87Stholo 	(void)strcpy(&dp[1], &dp[2]);
16487304b87Stholo 	return (name);
16587304b87Stholo }
16687304b87Stholo 
16787304b87Stholo char *
168bc52e260Sderaadt rawname(char *name)
16987304b87Stholo {
170*f4be0e98Sderaadt 	static char rawbuf[MAXPATHLEN];
17187304b87Stholo 	char *dp;
17287304b87Stholo 
173*f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
17487304b87Stholo 		return (0);
17587304b87Stholo 	*dp = 0;
176*f4be0e98Sderaadt 	(void)strlcpy(rawbuf, name, sizeof rawbuf);
17787304b87Stholo 	*dp = '/';
178*f4be0e98Sderaadt 	(void)strlcat(rawbuf, "/r", sizeof rawbuf);
179*f4be0e98Sderaadt 	(void)strlcat(rawbuf, &dp[1], sizeof rawbuf);
18087304b87Stholo 	return (rawbuf);
18187304b87Stholo }
18287304b87Stholo 
18387304b87Stholo char *
184bc52e260Sderaadt blockcheck(char *origname)
18587304b87Stholo {
18687304b87Stholo 	struct stat stslash, stblock, stchar;
18787304b87Stholo 	char *newname, *raw;
18887304b87Stholo 	struct fstab *fsp;
18987304b87Stholo 	int retried = 0;
19087304b87Stholo 
19187304b87Stholo 	hot = 0;
19287304b87Stholo 	if (stat("/", &stslash) < 0) {
19387304b87Stholo 		perror("/");
19487304b87Stholo 		printf("Can't stat root\n");
19587304b87Stholo 		return (origname);
19687304b87Stholo 	}
19787304b87Stholo 	newname = origname;
19887304b87Stholo retry:
19987304b87Stholo 	if (stat(newname, &stblock) < 0) {
20087304b87Stholo 		perror(newname);
20187304b87Stholo 		printf("Can't stat %s\n", newname);
20287304b87Stholo 		return (origname);
20387304b87Stholo 	}
20487304b87Stholo 	if (S_ISBLK(stblock.st_mode)) {
20587304b87Stholo 		if (stslash.st_dev == stblock.st_rdev)
20687304b87Stholo 			hot++;
20787304b87Stholo 		raw = rawname(newname);
20887304b87Stholo 		if (stat(raw, &stchar) < 0) {
20987304b87Stholo 			perror(raw);
21087304b87Stholo 			printf("Can't stat %s\n", raw);
21187304b87Stholo 			return (origname);
21287304b87Stholo 		}
21387304b87Stholo 		if (S_ISCHR(stchar.st_mode)) {
21487304b87Stholo 			return (raw);
21587304b87Stholo 		} else {
21687304b87Stholo 			printf("%s is not a character device\n", raw);
21787304b87Stholo 			return (origname);
21887304b87Stholo 		}
21987304b87Stholo 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
22087304b87Stholo 		newname = unrawname(newname);
22187304b87Stholo 		retried++;
22287304b87Stholo 		goto retry;
22387304b87Stholo 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
22487304b87Stholo 		newname = fsp->fs_spec;
22587304b87Stholo 		retried++;
22687304b87Stholo 		goto retry;
22787304b87Stholo 	}
22887304b87Stholo 	/*
22987304b87Stholo 	 * Not a block or character device, just return name and
23087304b87Stholo 	 * let the user decide whether to use it.
23187304b87Stholo 	 */
23287304b87Stholo 	return (origname);
23387304b87Stholo }
23487304b87Stholo 
23587304b87Stholo 
23687304b87Stholo void *
237bc52e260Sderaadt emalloc(size_t s)
23887304b87Stholo {
239b166fb0eSderaadt 	void *p;
240b166fb0eSderaadt 
241b166fb0eSderaadt 	if (s == 0)
242b166fb0eSderaadt 		err(1, "malloc failed");
243b166fb0eSderaadt 	p = malloc(s);
24487304b87Stholo 	if (p == NULL)
24587304b87Stholo 		err(1, "malloc failed");
24687304b87Stholo 	return p;
24787304b87Stholo }
24887304b87Stholo 
24987304b87Stholo 
25087304b87Stholo void *
251bc52e260Sderaadt erealloc(void *p, size_t s)
25287304b87Stholo {
253b166fb0eSderaadt 	if (s == 0)
254b166fb0eSderaadt 		err(1, "realloc failed");
25587304b87Stholo 	p = realloc(p, s);
25687304b87Stholo 	if (p == NULL)
25787304b87Stholo 		err(1, "realloc failed");
25887304b87Stholo 	return p;
25987304b87Stholo }
26087304b87Stholo 
26187304b87Stholo 
26287304b87Stholo char *
263bc52e260Sderaadt estrdup(const char *s)
26487304b87Stholo {
26587304b87Stholo 	char *p = strdup(s);
26687304b87Stholo 	if (p == NULL)
26787304b87Stholo 		err(1, "strdup failed");
26887304b87Stholo 	return p;
26987304b87Stholo }
270