xref: /openbsd/sbin/fsck/fsutil.c (revision df69c215)
1*df69c215Sderaadt /*	$OpenBSD: fsutil.c,v 1.24 2019/06/28 13:32:43 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 
3387304b87Stholo #include <stdio.h>
3487304b87Stholo #include <string.h>
3587304b87Stholo #include <stdlib.h>
3687304b87Stholo #include <stdarg.h>
3787304b87Stholo #include <errno.h>
3887304b87Stholo #include <fstab.h>
39b9fc9a72Sderaadt #include <limits.h>
4087304b87Stholo #include <err.h>
4187304b87Stholo 
4287304b87Stholo #include <sys/types.h>
4387304b87Stholo #include <sys/stat.h>
4487304b87Stholo 
4587304b87Stholo #include "fsutil.h"
4687304b87Stholo 
4787304b87Stholo static const char *dev = NULL;
48e729ad4aSjsing static const char *origdev = NULL;
4987304b87Stholo static int hot = 0;
5087304b87Stholo static int preen = 0;
5187304b87Stholo 
5287304b87Stholo extern char *__progname;
5387304b87Stholo 
54c72b5b24Smillert static void vmsg(int, const char *, va_list);
5587304b87Stholo 
56c9112980Sderaadt struct stat stslash;
57c9112980Sderaadt 
58c9112980Sderaadt void
checkroot(void)59c9112980Sderaadt checkroot(void)
60c9112980Sderaadt {
61*df69c215Sderaadt 	if (stat("/", &stslash) == -1) {
62c9112980Sderaadt 		xperror("/");
63c9112980Sderaadt 		printf("Can't stat root\n");
64c9112980Sderaadt 	}
65c9112980Sderaadt }
66c9112980Sderaadt 
6787304b87Stholo void
setcdevname(const char * cd,const char * ocd,int pr)68e729ad4aSjsing setcdevname(const char *cd, const char *ocd, int pr)
6987304b87Stholo {
7087304b87Stholo 	dev = cd;
71e729ad4aSjsing 	origdev = ocd;
7287304b87Stholo 	preen = pr;
7387304b87Stholo }
7487304b87Stholo 
7587304b87Stholo const char *
cdevname(void)76bc52e260Sderaadt cdevname(void)
7787304b87Stholo {
7887304b87Stholo 	return dev;
7987304b87Stholo }
8087304b87Stholo 
8187304b87Stholo int
hotroot(void)82bc52e260Sderaadt hotroot(void)
8387304b87Stholo {
8487304b87Stholo 	return hot;
8587304b87Stholo }
8687304b87Stholo 
8787304b87Stholo void
errexit(const char * fmt,...)8887304b87Stholo errexit(const char *fmt, ...)
8987304b87Stholo {
9087304b87Stholo 	va_list ap;
9187304b87Stholo 
9287304b87Stholo 	va_start(ap, fmt);
9387304b87Stholo 	(void) vfprintf(stderr, fmt, ap);
9487304b87Stholo 	va_end(ap);
9587304b87Stholo 	exit(8);
9687304b87Stholo }
9787304b87Stholo 
9887304b87Stholo static void
vmsg(int fatal,const char * fmt,va_list ap)99bc52e260Sderaadt vmsg(int fatal, const char *fmt, va_list ap)
10087304b87Stholo {
101e729ad4aSjsing 	if (!fatal && preen) {
102e729ad4aSjsing 		if (origdev)
103e729ad4aSjsing 			printf("%s (%s): ", dev, origdev);
104e729ad4aSjsing 		else
105e729ad4aSjsing 			printf("%s: ", dev);
106e729ad4aSjsing 	}
10787304b87Stholo 
10887304b87Stholo 	(void) vprintf(fmt, ap);
109986047b3Sthib 
11087304b87Stholo 	if (fatal && preen) {
111e729ad4aSjsing 		printf("\n");
112e729ad4aSjsing 		if (origdev)
113e729ad4aSjsing 			printf("%s (%s): ", dev, origdev);
114e729ad4aSjsing 		else
115e729ad4aSjsing 			printf("%s: ", dev);
116e729ad4aSjsing 		printf("UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
117e729ad4aSjsing 		    __progname);
11887304b87Stholo 		exit(8);
11987304b87Stholo 	}
12087304b87Stholo }
12187304b87Stholo 
12287304b87Stholo void
pfatal(const char * fmt,...)12387304b87Stholo pfatal(const char *fmt, ...)
12487304b87Stholo {
12587304b87Stholo 	va_list ap;
12687304b87Stholo 
12787304b87Stholo 	va_start(ap, fmt);
12887304b87Stholo 	vmsg(1, fmt, ap);
12987304b87Stholo 	va_end(ap);
13087304b87Stholo }
13187304b87Stholo 
13287304b87Stholo void
pwarn(const char * fmt,...)13387304b87Stholo pwarn(const char *fmt, ...)
13487304b87Stholo {
13587304b87Stholo 	va_list ap;
13687304b87Stholo 
13787304b87Stholo 	va_start(ap, fmt);
13887304b87Stholo 	vmsg(0, fmt, ap);
13987304b87Stholo 	va_end(ap);
14087304b87Stholo }
14187304b87Stholo 
14287304b87Stholo void
xperror(const char * s)143dd133929Sthib xperror(const char *s)
14487304b87Stholo {
14587304b87Stholo 	pfatal("%s (%s)", s, strerror(errno));
14687304b87Stholo }
14787304b87Stholo 
14887304b87Stholo void
panic(const char * fmt,...)14987304b87Stholo panic(const char *fmt, ...)
15087304b87Stholo {
15187304b87Stholo 	va_list ap;
15287304b87Stholo 
15387304b87Stholo 	va_start(ap, fmt);
15487304b87Stholo 	vmsg(1, fmt, ap);
15587304b87Stholo 	va_end(ap);
15687304b87Stholo 	exit(8);
15787304b87Stholo }
15887304b87Stholo 
15987304b87Stholo char *
unrawname(char * name)160bc52e260Sderaadt unrawname(char *name)
16187304b87Stholo {
16287304b87Stholo 	char *dp;
16387304b87Stholo 	struct stat stb;
16487304b87Stholo 
165f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
16687304b87Stholo 		return (name);
167*df69c215Sderaadt 	if (stat(name, &stb) == -1)
16887304b87Stholo 		return (name);
16987304b87Stholo 	if (!S_ISCHR(stb.st_mode))
17087304b87Stholo 		return (name);
17187304b87Stholo 	if (dp[1] != 'r')
17287304b87Stholo 		return (name);
17336286464Sderaadt 	(void)memmove(&dp[1], &dp[2], strlen(&dp[2]) + 1);
17487304b87Stholo 	return (name);
17587304b87Stholo }
17687304b87Stholo 
17787304b87Stholo char *
rawname(char * name)178bc52e260Sderaadt rawname(char *name)
17987304b87Stholo {
180b9fc9a72Sderaadt 	static char rawbuf[PATH_MAX];
18187304b87Stholo 	char *dp;
18287304b87Stholo 
183f4be0e98Sderaadt 	if ((dp = strrchr(name, '/')) == NULL)
18487304b87Stholo 		return (0);
18587304b87Stholo 	*dp = 0;
186f4be0e98Sderaadt 	(void)strlcpy(rawbuf, name, sizeof rawbuf);
18787304b87Stholo 	*dp = '/';
188f4be0e98Sderaadt 	(void)strlcat(rawbuf, "/r", sizeof rawbuf);
189f4be0e98Sderaadt 	(void)strlcat(rawbuf, &dp[1], sizeof rawbuf);
19087304b87Stholo 	return (rawbuf);
19187304b87Stholo }
19287304b87Stholo 
19387304b87Stholo char *
blockcheck(char * origname)194bc52e260Sderaadt blockcheck(char *origname)
19587304b87Stholo {
196c9112980Sderaadt 	struct stat stblock, stchar;
19787304b87Stholo 	char *newname, *raw;
19887304b87Stholo 	struct fstab *fsp;
19987304b87Stholo 	int retried = 0;
20087304b87Stholo 
20187304b87Stholo 	hot = 0;
20287304b87Stholo 	newname = origname;
20387304b87Stholo retry:
204*df69c215Sderaadt 	if (stat(newname, &stblock) == -1)
20587304b87Stholo 		return (origname);
2067cbafe7eSgrunk 
20787304b87Stholo 	if (S_ISBLK(stblock.st_mode)) {
20887304b87Stholo 		if (stslash.st_dev == stblock.st_rdev)
20987304b87Stholo 			hot++;
21087304b87Stholo 		raw = rawname(newname);
211*df69c215Sderaadt 		if (stat(raw, &stchar) == -1) {
212dd133929Sthib 			xperror(raw);
21387304b87Stholo 			printf("Can't stat %s\n", raw);
21487304b87Stholo 			return (origname);
21587304b87Stholo 		}
21687304b87Stholo 		if (S_ISCHR(stchar.st_mode)) {
21787304b87Stholo 			return (raw);
21887304b87Stholo 		} else {
21987304b87Stholo 			printf("%s is not a character device\n", raw);
22087304b87Stholo 			return (origname);
22187304b87Stholo 		}
22287304b87Stholo 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
22387304b87Stholo 		newname = unrawname(newname);
22487304b87Stholo 		retried++;
22587304b87Stholo 		goto retry;
22687304b87Stholo 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
22787304b87Stholo 		newname = fsp->fs_spec;
22887304b87Stholo 		retried++;
22987304b87Stholo 		goto retry;
23087304b87Stholo 	}
23187304b87Stholo 	/*
23287304b87Stholo 	 * Not a block or character device, just return name and
23387304b87Stholo 	 * let the user decide whether to use it.
23487304b87Stholo 	 */
23587304b87Stholo 	return (origname);
23687304b87Stholo }
23787304b87Stholo 
23887304b87Stholo 
23987304b87Stholo void *
emalloc(size_t s)240bc52e260Sderaadt emalloc(size_t s)
24187304b87Stholo {
242b166fb0eSderaadt 	void *p;
243b166fb0eSderaadt 
244b166fb0eSderaadt 	if (s == 0)
245b166fb0eSderaadt 		err(1, "malloc failed");
246b166fb0eSderaadt 	p = malloc(s);
24787304b87Stholo 	if (p == NULL)
24887304b87Stholo 		err(1, "malloc failed");
24987304b87Stholo 	return p;
25087304b87Stholo }
25187304b87Stholo 
25287304b87Stholo 
25387304b87Stholo void *
ereallocarray(void * p,size_t n,size_t s)254119ae1adSderaadt ereallocarray(void *p, size_t n, size_t s)
25587304b87Stholo {
2567428f312Sderaadt 	void *newp;
2577428f312Sderaadt 
25834c2ea26Sderaadt 	if (n == 0 || s == 0) {
25934c2ea26Sderaadt 		free(p);
260b166fb0eSderaadt 		err(1, "realloc failed");
26134c2ea26Sderaadt 	}
262119ae1adSderaadt 	newp = reallocarray(p, n, s);
2637428f312Sderaadt 	if (newp == NULL) {
2647428f312Sderaadt 		free(p);
26587304b87Stholo 		err(1, "realloc failed");
2667428f312Sderaadt 	}
2677428f312Sderaadt 	return newp;
26887304b87Stholo }
26987304b87Stholo 
27087304b87Stholo 
27187304b87Stholo char *
estrdup(const char * s)272bc52e260Sderaadt estrdup(const char *s)
27387304b87Stholo {
27487304b87Stholo 	char *p = strdup(s);
27587304b87Stholo 	if (p == NULL)
27687304b87Stholo 		err(1, "strdup failed");
27787304b87Stholo 	return p;
27887304b87Stholo }
279