xref: /netbsd-src/sbin/fsck/fsutil.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: fsutil.c,v 1.3 1996/10/22 16:57:51 christos 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 #ifndef lint
36 static char rcsid[] = "$NetBSD: fsutil.c,v 1.3 1996/10/22 16:57:51 christos Exp $";
37 #endif /* not lint */
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #if __STDC__
43 #include <stdarg.h>
44 #else
45 #include <varargs.h>
46 #endif
47 #include <errno.h>
48 #include <fstab.h>
49 #include <err.h>
50 
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 
54 #include "fsutil.h"
55 
56 static const char *dev = NULL;
57 static int hot = 0;
58 static int preen = 0;
59 
60 extern char *__progname;
61 
62 static void vmsg __P((int, const char *, va_list));
63 
64 void
65 setcdevname(cd, pr)
66 	const char *cd;
67 	int pr;
68 {
69 	dev = cd;
70 	preen = pr;
71 }
72 
73 const char *
74 cdevname()
75 {
76 	return dev;
77 }
78 
79 int
80 hotroot()
81 {
82 	return hot;
83 }
84 
85 /*VARARGS*/
86 void
87 #if __STDC__
88 errexit(const char *fmt, ...)
89 #else
90 errexit(va_alist)
91 	va_dcl
92 #endif
93 {
94 	va_list ap;
95 
96 #if __STDC__
97 	va_start(ap, fmt);
98 #else
99 	const char *fmt;
100 
101 	va_start(ap);
102 	fmt = va_arg(ap, const char *);
103 #endif
104 	(void) vfprintf(stderr, fmt, ap);
105 	va_end(ap);
106 	exit(8);
107 }
108 
109 static void
110 vmsg(fatal, fmt, ap)
111 	int fatal;
112 	const char *fmt;
113 	va_list ap;
114 {
115 	if (!fatal && preen)
116 		(void) printf("%s: ", dev);
117 
118 	(void) vprintf(fmt, ap);
119 
120 	if (fatal && preen)
121 		(void) printf("\n");
122 
123 	if (fatal && preen) {
124 		(void) printf(
125 		    "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
126 		    dev, __progname);
127 		exit(8);
128 	}
129 }
130 
131 /*VARARGS*/
132 void
133 #if __STDC__
134 pfatal(const char *fmt, ...)
135 #else
136 pfatal(va_alist)
137 	va_dcl
138 #endif
139 {
140 	va_list ap;
141 
142 #if __STDC__
143 	va_start(ap, fmt);
144 #else
145 	const char *fmt;
146 
147 	va_start(ap);
148 	fmt = va_arg(ap, const char *);
149 #endif
150 	vmsg(1, fmt, ap);
151 	va_end(ap);
152 }
153 
154 /*VARARGS*/
155 void
156 #if __STDC__
157 pwarn(const char *fmt, ...)
158 #else
159 pwarn(va_alist)
160 	va_dcl
161 #endif
162 {
163 	va_list ap;
164 #if __STDC__
165 	va_start(ap, fmt);
166 #else
167 	const char *fmt;
168 
169 	va_start(ap);
170 	fmt = va_arg(ap, const char *);
171 #endif
172 	vmsg(0, fmt, ap);
173 	va_end(ap);
174 }
175 
176 void
177 perror(s)
178 	const char *s;
179 {
180 	pfatal("%s (%s)", s, strerror(errno));
181 }
182 
183 void
184 #if __STDC__
185 panic(const char *fmt, ...)
186 #else
187 panic(va_alist)
188 	va_dcl
189 #endif
190 {
191 	va_list ap;
192 
193 #if __STDC__
194 	va_start(ap, fmt);
195 #else
196 	const char *fmt;
197 
198 	va_start(ap);
199 	fmt = va_arg(ap, const char *);
200 #endif
201 	vmsg(1, fmt, ap);
202 	va_end(ap);
203 	exit(8);
204 }
205 
206 char *
207 unrawname(name)
208 	char *name;
209 {
210 	char *dp;
211 	struct stat stb;
212 
213 	if ((dp = strrchr(name, '/')) == 0)
214 		return (name);
215 	if (stat(name, &stb) < 0)
216 		return (name);
217 	if (!S_ISCHR(stb.st_mode))
218 		return (name);
219 	if (dp[1] != 'r')
220 		return (name);
221 	(void)strcpy(&dp[1], &dp[2]);
222 	return (name);
223 }
224 
225 char *
226 rawname(name)
227 	char *name;
228 {
229 	static char rawbuf[32];
230 	char *dp;
231 
232 	if ((dp = strrchr(name, '/')) == 0)
233 		return (0);
234 	*dp = 0;
235 	(void)strcpy(rawbuf, name);
236 	*dp = '/';
237 	(void)strcat(rawbuf, "/r");
238 	(void)strcat(rawbuf, &dp[1]);
239 	return (rawbuf);
240 }
241 
242 char *
243 blockcheck(origname)
244 	char *origname;
245 {
246 	struct stat stslash, stblock, stchar;
247 	char *newname, *raw;
248 	struct fstab *fsp;
249 	int retried = 0;
250 
251 	hot = 0;
252 	if (stat("/", &stslash) < 0) {
253 		perror("/");
254 		printf("Can't stat root\n");
255 		return (origname);
256 	}
257 	newname = origname;
258 retry:
259 	if (stat(newname, &stblock) < 0) {
260 		perror(newname);
261 		printf("Can't stat %s\n", newname);
262 		return (origname);
263 	}
264 	if (S_ISBLK(stblock.st_mode)) {
265 		if (stslash.st_dev == stblock.st_rdev)
266 			hot++;
267 		raw = rawname(newname);
268 		if (stat(raw, &stchar) < 0) {
269 			perror(raw);
270 			printf("Can't stat %s\n", raw);
271 			return (origname);
272 		}
273 		if (S_ISCHR(stchar.st_mode)) {
274 			return (raw);
275 		} else {
276 			printf("%s is not a character device\n", raw);
277 			return (origname);
278 		}
279 	} else if (S_ISCHR(stblock.st_mode) && !retried) {
280 		newname = unrawname(newname);
281 		retried++;
282 		goto retry;
283 	} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
284 		newname = fsp->fs_spec;
285 		retried++;
286 		goto retry;
287 	}
288 	/*
289 	 * Not a block or character device, just return name and
290 	 * let the user decide whether to use it.
291 	 */
292 	return (origname);
293 }
294 
295 
296 void *
297 emalloc(s)
298 	size_t s;
299 {
300 	void *p = malloc(s);
301 	if (p == NULL)
302 		err(1, "malloc failed");
303 	return p;
304 }
305 
306 
307 void *
308 erealloc(p, s)
309 	void *p;
310 	size_t s;
311 {
312 	p = realloc(p, s);
313 	if (p == NULL)
314 		err(1, "realloc failed");
315 	return p;
316 }
317 
318 
319 char *
320 estrdup(s)
321 	const char *s;
322 {
323 	char *p = strdup(s);
324 	if (p == NULL)
325 		err(1, "strdup failed");
326 	return p;
327 }
328