xref: /openbsd/sbin/fsck/fsutil.c (revision 7428f312)
1*7428f312Sderaadt /*	$OpenBSD: fsutil.c,v 1.13 2003/09/25 04:15:29 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.
161ef0d710Smillert  * 3. Neither the name of the University nor the names of its contributors
1787304b87Stholo  *    may be used to endorse or promote products derived from this software
1887304b87Stholo  *    without specific prior written permission.
1987304b87Stholo  *
2087304b87Stholo  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2187304b87Stholo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2287304b87Stholo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2387304b87Stholo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2487304b87Stholo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2587304b87Stholo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2687304b87Stholo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2787304b87Stholo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2887304b87Stholo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2987304b87Stholo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3087304b87Stholo  * SUCH DAMAGE.
3187304b87Stholo  */
3287304b87Stholo #ifndef lint
33*7428f312Sderaadt static const char rcsid[] = "$OpenBSD: fsutil.c,v 1.13 2003/09/25 04:15:29 deraadt Exp $";
3487304b87Stholo #endif /* not lint */
3587304b87Stholo 
36f4be0e98Sderaadt #include <sys/param.h>
3787304b87Stholo #include <stdio.h>
3887304b87Stholo #include <string.h>
3987304b87Stholo #include <stdlib.h>
4087304b87Stholo #include <stdarg.h>
4187304b87Stholo #include <errno.h>
4287304b87Stholo #include <fstab.h>
4387304b87Stholo #include <err.h>
4487304b87Stholo 
4587304b87Stholo #include <sys/types.h>
4687304b87Stholo #include <sys/stat.h>
4787304b87Stholo 
4887304b87Stholo #include "fsutil.h"
4987304b87Stholo 
5087304b87Stholo static const char *dev = NULL;
5187304b87Stholo static int hot = 0;
5287304b87Stholo static int preen = 0;
5387304b87Stholo 
5487304b87Stholo extern char *__progname;
5587304b87Stholo 
56c72b5b24Smillert static void vmsg(int, const char *, va_list);
5787304b87Stholo 
5887304b87Stholo void
59bc52e260Sderaadt setcdevname(const char *cd, int pr)
6087304b87Stholo {
6187304b87Stholo 	dev = cd;
6287304b87Stholo 	preen = pr;
6387304b87Stholo }
6487304b87Stholo 
6587304b87Stholo const char *
66bc52e260Sderaadt cdevname(void)
6787304b87Stholo {
6887304b87Stholo 	return dev;
6987304b87Stholo }
7087304b87Stholo 
7187304b87Stholo int
72bc52e260Sderaadt hotroot(void)
7387304b87Stholo {
7487304b87Stholo 	return hot;
7587304b87Stholo }
7687304b87Stholo 
7787304b87Stholo /*VARARGS*/
7887304b87Stholo void
7987304b87Stholo errexit(const char *fmt, ...)
8087304b87Stholo {
8187304b87Stholo 	va_list ap;
8287304b87Stholo 
8387304b87Stholo 	va_start(ap, fmt);
8487304b87Stholo 	(void) vfprintf(stderr, fmt, ap);
8587304b87Stholo 	va_end(ap);
8687304b87Stholo 	exit(8);
8787304b87Stholo }
8887304b87Stholo 
8987304b87Stholo static void
90bc52e260Sderaadt vmsg(int fatal, const char *fmt, va_list ap)
9187304b87Stholo {
9287304b87Stholo 	if (!fatal && preen)
9387304b87Stholo 		(void) printf("%s: ", dev);
9487304b87Stholo 
9587304b87Stholo 	(void) vprintf(fmt, ap);
9687304b87Stholo 
9787304b87Stholo 	if (fatal && preen) {
9862d85a42Sian 		(void) printf("\n");
9987304b87Stholo 		(void) printf(
10087304b87Stholo 		    "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
10187304b87Stholo 		    dev, __progname);
10287304b87Stholo 		exit(8);
10387304b87Stholo 	}
10487304b87Stholo }
10587304b87Stholo 
10687304b87Stholo /*VARARGS*/
10787304b87Stholo void
10887304b87Stholo pfatal(const char *fmt, ...)
10987304b87Stholo {
11087304b87Stholo 	va_list ap;
11187304b87Stholo 
11287304b87Stholo 	va_start(ap, fmt);
11387304b87Stholo 	vmsg(1, fmt, ap);
11487304b87Stholo 	va_end(ap);
11587304b87Stholo }
11687304b87Stholo 
11787304b87Stholo /*VARARGS*/
11887304b87Stholo void
11987304b87Stholo pwarn(const char *fmt, ...)
12087304b87Stholo {
12187304b87Stholo 	va_list ap;
12287304b87Stholo 
12387304b87Stholo 	va_start(ap, fmt);
12487304b87Stholo 	vmsg(0, fmt, ap);
12587304b87Stholo 	va_end(ap);
12687304b87Stholo }
12787304b87Stholo 
12887304b87Stholo void
129bc52e260Sderaadt perror(const char *s)
13087304b87Stholo {
13187304b87Stholo 	pfatal("%s (%s)", s, strerror(errno));
13287304b87Stholo }
13387304b87Stholo 
13487304b87Stholo void
13587304b87Stholo panic(const char *fmt, ...)
13687304b87Stholo {
13787304b87Stholo 	va_list ap;
13887304b87Stholo 
13987304b87Stholo 	va_start(ap, fmt);
14087304b87Stholo 	vmsg(1, fmt, ap);
14187304b87Stholo 	va_end(ap);
14287304b87Stholo 	exit(8);
14387304b87Stholo }
14487304b87Stholo 
14587304b87Stholo char *
146bc52e260Sderaadt unrawname(char *name)
14787304b87Stholo {
14887304b87Stholo 	char *dp;
14987304b87Stholo 	struct stat stb;
15087304b87Stholo 
151f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
15287304b87Stholo 		return (name);
15387304b87Stholo 	if (stat(name, &stb) < 0)
15487304b87Stholo 		return (name);
15587304b87Stholo 	if (!S_ISCHR(stb.st_mode))
15687304b87Stholo 		return (name);
15787304b87Stholo 	if (dp[1] != 'r')
15887304b87Stholo 		return (name);
15936286464Sderaadt 	(void)memmove(&dp[1], &dp[2], strlen(&dp[2]) + 1);
16087304b87Stholo 	return (name);
16187304b87Stholo }
16287304b87Stholo 
16387304b87Stholo char *
164bc52e260Sderaadt rawname(char *name)
16587304b87Stholo {
166f4be0e98Sderaadt 	static char rawbuf[MAXPATHLEN];
16787304b87Stholo 	char *dp;
16887304b87Stholo 
169f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
17087304b87Stholo 		return (0);
17187304b87Stholo 	*dp = 0;
172f4be0e98Sderaadt 	(void)strlcpy(rawbuf, name, sizeof rawbuf);
17387304b87Stholo 	*dp = '/';
174f4be0e98Sderaadt 	(void)strlcat(rawbuf, "/r", sizeof rawbuf);
175f4be0e98Sderaadt 	(void)strlcat(rawbuf, &dp[1], sizeof rawbuf);
17687304b87Stholo 	return (rawbuf);
17787304b87Stholo }
17887304b87Stholo 
17987304b87Stholo char *
180bc52e260Sderaadt blockcheck(char *origname)
18187304b87Stholo {
18287304b87Stholo 	struct stat stslash, stblock, stchar;
18387304b87Stholo 	char *newname, *raw;
18487304b87Stholo 	struct fstab *fsp;
18587304b87Stholo 	int retried = 0;
18687304b87Stholo 
18787304b87Stholo 	hot = 0;
18887304b87Stholo 	if (stat("/", &stslash) < 0) {
18987304b87Stholo 		perror("/");
19087304b87Stholo 		printf("Can't stat root\n");
19187304b87Stholo 		return (origname);
19287304b87Stholo 	}
19387304b87Stholo 	newname = origname;
19487304b87Stholo retry:
19587304b87Stholo 	if (stat(newname, &stblock) < 0) {
19687304b87Stholo 		perror(newname);
19787304b87Stholo 		printf("Can't stat %s\n", newname);
19887304b87Stholo 		return (origname);
19987304b87Stholo 	}
20087304b87Stholo 	if (S_ISBLK(stblock.st_mode)) {
20187304b87Stholo 		if (stslash.st_dev == stblock.st_rdev)
20287304b87Stholo 			hot++;
20387304b87Stholo 		raw = rawname(newname);
20487304b87Stholo 		if (stat(raw, &stchar) < 0) {
20587304b87Stholo 			perror(raw);
20687304b87Stholo 			printf("Can't stat %s\n", raw);
20787304b87Stholo 			return (origname);
20887304b87Stholo 		}
20987304b87Stholo 		if (S_ISCHR(stchar.st_mode)) {
21087304b87Stholo 			return (raw);
21187304b87Stholo 		} else {
21287304b87Stholo 			printf("%s is not a character device\n", raw);
21387304b87Stholo 			return (origname);
21487304b87Stholo 		}
21587304b87Stholo 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
21687304b87Stholo 		newname = unrawname(newname);
21787304b87Stholo 		retried++;
21887304b87Stholo 		goto retry;
21987304b87Stholo 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
22087304b87Stholo 		newname = fsp->fs_spec;
22187304b87Stholo 		retried++;
22287304b87Stholo 		goto retry;
22387304b87Stholo 	}
22487304b87Stholo 	/*
22587304b87Stholo 	 * Not a block or character device, just return name and
22687304b87Stholo 	 * let the user decide whether to use it.
22787304b87Stholo 	 */
22887304b87Stholo 	return (origname);
22987304b87Stholo }
23087304b87Stholo 
23187304b87Stholo 
23287304b87Stholo void *
233bc52e260Sderaadt emalloc(size_t s)
23487304b87Stholo {
235b166fb0eSderaadt 	void *p;
236b166fb0eSderaadt 
237b166fb0eSderaadt 	if (s == 0)
238b166fb0eSderaadt 		err(1, "malloc failed");
239b166fb0eSderaadt 	p = malloc(s);
24087304b87Stholo 	if (p == NULL)
24187304b87Stholo 		err(1, "malloc failed");
24287304b87Stholo 	return p;
24387304b87Stholo }
24487304b87Stholo 
24587304b87Stholo 
24687304b87Stholo void *
247bc52e260Sderaadt erealloc(void *p, size_t s)
24887304b87Stholo {
249*7428f312Sderaadt 	void *newp;
250*7428f312Sderaadt 
251b166fb0eSderaadt 	if (s == 0)
252b166fb0eSderaadt 		err(1, "realloc failed");
253*7428f312Sderaadt 	newp = realloc(p, s);
254*7428f312Sderaadt 	if (newp == NULL) {
255*7428f312Sderaadt 		if (p)
256*7428f312Sderaadt 			free(p);
25787304b87Stholo 		err(1, "realloc failed");
258*7428f312Sderaadt 	}
259*7428f312Sderaadt 	return newp;
26087304b87Stholo }
26187304b87Stholo 
26287304b87Stholo 
26387304b87Stholo char *
264bc52e260Sderaadt estrdup(const char *s)
26587304b87Stholo {
26687304b87Stholo 	char *p = strdup(s);
26787304b87Stholo 	if (p == NULL)
26887304b87Stholo 		err(1, "strdup failed");
26987304b87Stholo 	return p;
27087304b87Stholo }
271