xref: /openbsd/sbin/fsck/fsutil.c (revision df69c215)
1 /*	$OpenBSD: fsutil.c,v 1.24 2019/06/28 13:32:43 deraadt Exp $	*/
2 /*	$NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <errno.h>
38 #include <fstab.h>
39 #include <limits.h>
40 #include <err.h>
41 
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 
45 #include "fsutil.h"
46 
47 static const char *dev = NULL;
48 static const char *origdev = NULL;
49 static int hot = 0;
50 static int preen = 0;
51 
52 extern char *__progname;
53 
54 static void vmsg(int, const char *, va_list);
55 
56 struct stat stslash;
57 
58 void
checkroot(void)59 checkroot(void)
60 {
61 	if (stat("/", &stslash) == -1) {
62 		xperror("/");
63 		printf("Can't stat root\n");
64 	}
65 }
66 
67 void
setcdevname(const char * cd,const char * ocd,int pr)68 setcdevname(const char *cd, const char *ocd, int pr)
69 {
70 	dev = cd;
71 	origdev = ocd;
72 	preen = pr;
73 }
74 
75 const char *
cdevname(void)76 cdevname(void)
77 {
78 	return dev;
79 }
80 
81 int
hotroot(void)82 hotroot(void)
83 {
84 	return hot;
85 }
86 
87 void
errexit(const char * fmt,...)88 errexit(const char *fmt, ...)
89 {
90 	va_list ap;
91 
92 	va_start(ap, fmt);
93 	(void) vfprintf(stderr, fmt, ap);
94 	va_end(ap);
95 	exit(8);
96 }
97 
98 static void
vmsg(int fatal,const char * fmt,va_list ap)99 vmsg(int fatal, const char *fmt, va_list ap)
100 {
101 	if (!fatal && preen) {
102 		if (origdev)
103 			printf("%s (%s): ", dev, origdev);
104 		else
105 			printf("%s: ", dev);
106 	}
107 
108 	(void) vprintf(fmt, ap);
109 
110 	if (fatal && preen) {
111 		printf("\n");
112 		if (origdev)
113 			printf("%s (%s): ", dev, origdev);
114 		else
115 			printf("%s: ", dev);
116 		printf("UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
117 		    __progname);
118 		exit(8);
119 	}
120 }
121 
122 void
pfatal(const char * fmt,...)123 pfatal(const char *fmt, ...)
124 {
125 	va_list ap;
126 
127 	va_start(ap, fmt);
128 	vmsg(1, fmt, ap);
129 	va_end(ap);
130 }
131 
132 void
pwarn(const char * fmt,...)133 pwarn(const char *fmt, ...)
134 {
135 	va_list ap;
136 
137 	va_start(ap, fmt);
138 	vmsg(0, fmt, ap);
139 	va_end(ap);
140 }
141 
142 void
xperror(const char * s)143 xperror(const char *s)
144 {
145 	pfatal("%s (%s)", s, strerror(errno));
146 }
147 
148 void
panic(const char * fmt,...)149 panic(const char *fmt, ...)
150 {
151 	va_list ap;
152 
153 	va_start(ap, fmt);
154 	vmsg(1, fmt, ap);
155 	va_end(ap);
156 	exit(8);
157 }
158 
159 char *
unrawname(char * name)160 unrawname(char *name)
161 {
162 	char *dp;
163 	struct stat stb;
164 
165 	if ((dp = strrchr(name, '/')) == NULL)
166 		return (name);
167 	if (stat(name, &stb) == -1)
168 		return (name);
169 	if (!S_ISCHR(stb.st_mode))
170 		return (name);
171 	if (dp[1] != 'r')
172 		return (name);
173 	(void)memmove(&dp[1], &dp[2], strlen(&dp[2]) + 1);
174 	return (name);
175 }
176 
177 char *
rawname(char * name)178 rawname(char *name)
179 {
180 	static char rawbuf[PATH_MAX];
181 	char *dp;
182 
183 	if ((dp = strrchr(name, '/')) == NULL)
184 		return (0);
185 	*dp = 0;
186 	(void)strlcpy(rawbuf, name, sizeof rawbuf);
187 	*dp = '/';
188 	(void)strlcat(rawbuf, "/r", sizeof rawbuf);
189 	(void)strlcat(rawbuf, &dp[1], sizeof rawbuf);
190 	return (rawbuf);
191 }
192 
193 char *
blockcheck(char * origname)194 blockcheck(char *origname)
195 {
196 	struct stat stblock, stchar;
197 	char *newname, *raw;
198 	struct fstab *fsp;
199 	int retried = 0;
200 
201 	hot = 0;
202 	newname = origname;
203 retry:
204 	if (stat(newname, &stblock) == -1)
205 		return (origname);
206 
207 	if (S_ISBLK(stblock.st_mode)) {
208 		if (stslash.st_dev == stblock.st_rdev)
209 			hot++;
210 		raw = rawname(newname);
211 		if (stat(raw, &stchar) == -1) {
212 			xperror(raw);
213 			printf("Can't stat %s\n", raw);
214 			return (origname);
215 		}
216 		if (S_ISCHR(stchar.st_mode)) {
217 			return (raw);
218 		} else {
219 			printf("%s is not a character device\n", raw);
220 			return (origname);
221 		}
222 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
223 		newname = unrawname(newname);
224 		retried++;
225 		goto retry;
226 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
227 		newname = fsp->fs_spec;
228 		retried++;
229 		goto retry;
230 	}
231 	/*
232 	 * Not a block or character device, just return name and
233 	 * let the user decide whether to use it.
234 	 */
235 	return (origname);
236 }
237 
238 
239 void *
emalloc(size_t s)240 emalloc(size_t s)
241 {
242 	void *p;
243 
244 	if (s == 0)
245 		err(1, "malloc failed");
246 	p = malloc(s);
247 	if (p == NULL)
248 		err(1, "malloc failed");
249 	return p;
250 }
251 
252 
253 void *
ereallocarray(void * p,size_t n,size_t s)254 ereallocarray(void *p, size_t n, size_t s)
255 {
256 	void *newp;
257 
258 	if (n == 0 || s == 0) {
259 		free(p);
260 		err(1, "realloc failed");
261 	}
262 	newp = reallocarray(p, n, s);
263 	if (newp == NULL) {
264 		free(p);
265 		err(1, "realloc failed");
266 	}
267 	return newp;
268 }
269 
270 
271 char *
estrdup(const char * s)272 estrdup(const char *s)
273 {
274 	char *p = strdup(s);
275 	if (p == NULL)
276 		err(1, "strdup failed");
277 	return p;
278 }
279