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