fsutil.c revision 1.8 1 /* $NetBSD: fsutil.c,v 1.8 2000/10/10 20:24:51 is 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
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __RCSID("$NetBSD: fsutil.c,v 1.8 2000/10/10 20:24:51 is Exp $");
39 #endif /* not lint */
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #if __STDC__
45 #include <stdarg.h>
46 #else
47 #include <varargs.h>
48 #endif
49 #include <errno.h>
50 #include <fstab.h>
51 #include <err.h>
52
53 #include <sys/types.h>
54 #include <sys/stat.h>
55
56 #include "fsutil.h"
57
58 static const char *dev = NULL;
59 static int hot = 0;
60 static int preen = 0;
61
62 extern char *__progname;
63
64 static void vmsg __P((int, const char *, va_list))
65 __attribute((__format__(__printf__,2,0)));
66
67 void
68 setcdevname(cd, pr)
69 const char *cd;
70 int pr;
71 {
72 dev = cd;
73 preen = pr;
74 }
75
76 const char *
77 cdevname()
78 {
79 return dev;
80 }
81
82 int
83 hotroot()
84 {
85 return hot;
86 }
87
88 /*VARARGS*/
89 void
90 #if __STDC__
91 errexit(const char *fmt, ...)
92 #else
93 errexit(va_alist)
94 va_dcl
95 #endif
96 {
97 va_list ap;
98
99 #if __STDC__
100 va_start(ap, fmt);
101 #else
102 const char *fmt;
103
104 va_start(ap);
105 fmt = va_arg(ap, const char *);
106 #endif
107 (void) vfprintf(stderr, fmt, ap);
108 va_end(ap);
109 exit(8);
110 }
111
112 static void
113 vmsg(fatal, fmt, ap)
114 int fatal;
115 const char *fmt;
116 va_list ap;
117 {
118 if (!fatal && preen)
119 (void) printf("%s: ", dev);
120
121 (void) vprintf(fmt, ap);
122
123 if (fatal && preen)
124 (void) printf("\n");
125
126 if (fatal && preen) {
127 (void) printf(
128 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
129 dev, __progname);
130 exit(8);
131 }
132 }
133
134 /*VARARGS*/
135 void
136 #if __STDC__
137 pfatal(const char *fmt, ...)
138 #else
139 pfatal(va_alist)
140 va_dcl
141 #endif
142 {
143 va_list ap;
144
145 #if __STDC__
146 va_start(ap, fmt);
147 #else
148 const char *fmt;
149
150 va_start(ap);
151 fmt = va_arg(ap, const char *);
152 #endif
153 vmsg(1, fmt, ap);
154 va_end(ap);
155 }
156
157 /*VARARGS*/
158 void
159 #if __STDC__
160 pwarn(const char *fmt, ...)
161 #else
162 pwarn(va_alist)
163 va_dcl
164 #endif
165 {
166 va_list ap;
167 #if __STDC__
168 va_start(ap, fmt);
169 #else
170 const char *fmt;
171
172 va_start(ap);
173 fmt = va_arg(ap, const char *);
174 #endif
175 vmsg(0, fmt, ap);
176 va_end(ap);
177 }
178
179 void
180 perror(s)
181 const char *s;
182 {
183 pfatal("%s (%s)", s, strerror(errno));
184 }
185
186 void
187 #if __STDC__
188 panic(const char *fmt, ...)
189 #else
190 panic(va_alist)
191 va_dcl
192 #endif
193 {
194 va_list ap;
195
196 #if __STDC__
197 va_start(ap, fmt);
198 #else
199 const char *fmt;
200
201 va_start(ap);
202 fmt = va_arg(ap, const char *);
203 #endif
204 vmsg(1, fmt, ap);
205 va_end(ap);
206 exit(8);
207 }
208
209 const char *
210 unrawname(name)
211 const char *name;
212 {
213 static char unrawbuf[32];
214 const char *dp;
215 struct stat stb;
216
217 if ((dp = strrchr(name, '/')) == 0)
218 return (name);
219 if (stat(name, &stb) < 0)
220 return (name);
221 if (!S_ISCHR(stb.st_mode))
222 return (name);
223 if (dp[1] != 'r')
224 return (name);
225 (void)snprintf(unrawbuf, 32, "%.*s/%s", (int)(dp - name), name, dp + 2);
226 return (unrawbuf);
227 }
228
229 const char *
230 rawname(name)
231 const char *name;
232 {
233 static char rawbuf[32];
234 const char *dp;
235
236 if ((dp = strrchr(name, '/')) == 0)
237 return (0);
238 (void)snprintf(rawbuf, 32, "%.*s/r%s", (int)(dp - name), name, dp + 1);
239 return (rawbuf);
240 }
241
242 const char *
243 blockcheck(origname)
244 const char *origname;
245 {
246 struct stat stslash, stblock, stchar;
247 const 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;
301
302 p = malloc(s);
303 if (p == NULL)
304 err(1, "malloc failed");
305 return (p);
306 }
307
308
309 void *
310 erealloc(p, s)
311 void *p;
312 size_t s;
313 {
314 void *q;
315
316 q = realloc(p, s);
317 if (q == NULL)
318 err(1, "realloc failed");
319 return (q);
320 }
321
322
323 char *
324 estrdup(s)
325 const char *s;
326 {
327 char *p;
328
329 p = strdup(s);
330 if (p == NULL)
331 err(1, "strdup failed");
332 return (p);
333 }
334