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