xref: /openbsd-src/sbin/fsck/fsutil.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: fsutil.c,v 1.4 2001/07/03 13:03:44 ian 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. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 #ifndef lint
37 static char rcsid[] = "$NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $";
38 #endif /* not lint */
39 
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #ifdef __STDC__
44 #include <stdarg.h>
45 #else
46 #include <varargs.h>
47 #endif
48 #include <errno.h>
49 #include <fstab.h>
50 #include <err.h>
51 
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 
55 #include "fsutil.h"
56 
57 static const char *dev = NULL;
58 static int hot = 0;
59 static int preen = 0;
60 
61 extern char *__progname;
62 
63 static void vmsg __P((int, const char *, va_list));
64 
65 void
66 setcdevname(cd, pr)
67 	const char *cd;
68 	int pr;
69 {
70 	dev = cd;
71 	preen = pr;
72 }
73 
74 const char *
75 cdevname()
76 {
77 	return dev;
78 }
79 
80 int
81 hotroot()
82 {
83 	return hot;
84 }
85 
86 /*VARARGS*/
87 void
88 #ifdef __STDC__
89 errexit(const char *fmt, ...)
90 #else
91 errexit(fmt, va_alist)
92 	char *fmt;
93 	va_dcl
94 #endif
95 {
96 	va_list ap;
97 
98 #ifdef __STDC__
99 	va_start(ap, fmt);
100 #else
101 	va_start(ap);
102 #endif
103 	(void) vfprintf(stderr, fmt, ap);
104 	va_end(ap);
105 	exit(8);
106 }
107 
108 static void
109 vmsg(fatal, fmt, ap)
110 	int fatal;
111 	const char *fmt;
112 	va_list ap;
113 {
114 	if (!fatal && preen)
115 		(void) printf("%s: ", dev);
116 
117 	(void) vprintf(fmt, ap);
118 
119 	if (fatal && preen) {
120 		(void) printf("\n");
121 		(void) printf(
122 		    "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
123 		    dev, __progname);
124 		exit(8);
125 	}
126 }
127 
128 /*VARARGS*/
129 void
130 #ifdef __STDC__
131 pfatal(const char *fmt, ...)
132 #else
133 pfatal(fmt, va_alist)
134 	char *fmt;
135 	va_dcl
136 #endif
137 {
138 	va_list ap;
139 
140 #ifdef __STDC__
141 	va_start(ap, fmt);
142 #else
143 	va_start(ap);
144 #endif
145 	vmsg(1, fmt, ap);
146 	va_end(ap);
147 }
148 
149 /*VARARGS*/
150 void
151 #ifdef __STDC__
152 pwarn(const char *fmt, ...)
153 #else
154 pwarn(fmt, va_alist)
155 	char *fmt;
156 	va_dcl
157 #endif
158 {
159 	va_list ap;
160 
161 #ifdef __STDC__
162 	va_start(ap, fmt);
163 #else
164 	va_start(ap);
165 #endif
166 	vmsg(0, fmt, ap);
167 	va_end(ap);
168 }
169 
170 void
171 perror(s)
172 	const char *s;
173 {
174 	pfatal("%s (%s)", s, strerror(errno));
175 }
176 
177 void
178 #ifdef __STDC__
179 panic(const char *fmt, ...)
180 #else
181 panic(fmt, va_alist)
182 	char *fmt;
183 	va_dcl
184 #endif
185 {
186 	va_list ap;
187 
188 #ifdef __STDC__
189 	va_start(ap, fmt);
190 #else
191 	va_start(ap);
192 #endif
193 	vmsg(1, fmt, ap);
194 	va_end(ap);
195 	exit(8);
196 }
197 
198 char *
199 unrawname(name)
200 	char *name;
201 {
202 	char *dp;
203 	struct stat stb;
204 
205 	if ((dp = strrchr(name, '/')) == 0)
206 		return (name);
207 	if (stat(name, &stb) < 0)
208 		return (name);
209 	if (!S_ISCHR(stb.st_mode))
210 		return (name);
211 	if (dp[1] != 'r')
212 		return (name);
213 	(void)strcpy(&dp[1], &dp[2]);
214 	return (name);
215 }
216 
217 char *
218 rawname(name)
219 	char *name;
220 {
221 	static char rawbuf[32];
222 	char *dp;
223 
224 	if ((dp = strrchr(name, '/')) == 0)
225 		return (0);
226 	*dp = 0;
227 	(void)strcpy(rawbuf, name);
228 	*dp = '/';
229 	(void)strcat(rawbuf, "/r");
230 	(void)strcat(rawbuf, &dp[1]);
231 	return (rawbuf);
232 }
233 
234 char *
235 blockcheck(origname)
236 	char *origname;
237 {
238 	struct stat stslash, stblock, stchar;
239 	char *newname, *raw;
240 	struct fstab *fsp;
241 	int retried = 0;
242 
243 	hot = 0;
244 	if (stat("/", &stslash) < 0) {
245 		perror("/");
246 		printf("Can't stat root\n");
247 		return (origname);
248 	}
249 	newname = origname;
250 retry:
251 	if (stat(newname, &stblock) < 0) {
252 		perror(newname);
253 		printf("Can't stat %s\n", newname);
254 		return (origname);
255 	}
256 	if (S_ISBLK(stblock.st_mode)) {
257 		if (stslash.st_dev == stblock.st_rdev)
258 			hot++;
259 		raw = rawname(newname);
260 		if (stat(raw, &stchar) < 0) {
261 			perror(raw);
262 			printf("Can't stat %s\n", raw);
263 			return (origname);
264 		}
265 		if (S_ISCHR(stchar.st_mode)) {
266 			return (raw);
267 		} else {
268 			printf("%s is not a character device\n", raw);
269 			return (origname);
270 		}
271 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
272 		newname = unrawname(newname);
273 		retried++;
274 		goto retry;
275 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
276 		newname = fsp->fs_spec;
277 		retried++;
278 		goto retry;
279 	}
280 	/*
281 	 * Not a block or character device, just return name and
282 	 * let the user decide whether to use it.
283 	 */
284 	return (origname);
285 }
286 
287 
288 void *
289 emalloc(s)
290 	size_t s;
291 {
292 	void *p;
293 
294 	if (s == 0)
295 		err(1, "malloc failed");
296 	p = malloc(s);
297 	if (p == NULL)
298 		err(1, "malloc failed");
299 	return p;
300 }
301 
302 
303 void *
304 erealloc(p, s)
305 	void *p;
306 	size_t s;
307 {
308 	if (s == 0)
309 		err(1, "realloc failed");
310 	p = realloc(p, s);
311 	if (p == NULL)
312 		err(1, "realloc failed");
313 	return p;
314 }
315 
316 
317 char *
318 estrdup(s)
319 	const char *s;
320 {
321 	char *p = strdup(s);
322 	if (p == NULL)
323 		err(1, "strdup failed");
324 	return p;
325 }
326