fsutil.c revision 1.9 1 /* $NetBSD: fsutil.c,v 1.9 2001/02/19 22:56:19 cgd 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.9 2001/02/19 22:56:19 cgd 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 static void vmsg __P((int, const char *, va_list))
63 __attribute((__format__(__printf__,2,0)));
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 #if __STDC__
89 errexit(const char *fmt, ...)
90 #else
91 errexit(va_alist)
92 va_dcl
93 #endif
94 {
95 va_list ap;
96
97 #if __STDC__
98 va_start(ap, fmt);
99 #else
100 const char *fmt;
101
102 va_start(ap);
103 fmt = va_arg(ap, const char *);
104 #endif
105 (void) vfprintf(stderr, fmt, ap);
106 va_end(ap);
107 exit(8);
108 }
109
110 static void
111 vmsg(fatal, fmt, ap)
112 int fatal;
113 const char *fmt;
114 va_list ap;
115 {
116 if (!fatal && preen)
117 (void) printf("%s: ", dev);
118
119 (void) vprintf(fmt, ap);
120
121 if (fatal && preen)
122 (void) printf("\n");
123
124 if (fatal && preen) {
125 (void) printf(
126 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
127 dev, getprogname());
128 exit(8);
129 }
130 }
131
132 /*VARARGS*/
133 void
134 #if __STDC__
135 pfatal(const char *fmt, ...)
136 #else
137 pfatal(va_alist)
138 va_dcl
139 #endif
140 {
141 va_list ap;
142
143 #if __STDC__
144 va_start(ap, fmt);
145 #else
146 const char *fmt;
147
148 va_start(ap);
149 fmt = va_arg(ap, const char *);
150 #endif
151 vmsg(1, fmt, ap);
152 va_end(ap);
153 }
154
155 /*VARARGS*/
156 void
157 #if __STDC__
158 pwarn(const char *fmt, ...)
159 #else
160 pwarn(va_alist)
161 va_dcl
162 #endif
163 {
164 va_list ap;
165 #if __STDC__
166 va_start(ap, fmt);
167 #else
168 const char *fmt;
169
170 va_start(ap);
171 fmt = va_arg(ap, const char *);
172 #endif
173 vmsg(0, fmt, ap);
174 va_end(ap);
175 }
176
177 void
178 perror(s)
179 const char *s;
180 {
181 pfatal("%s (%s)", s, strerror(errno));
182 }
183
184 void
185 #if __STDC__
186 panic(const char *fmt, ...)
187 #else
188 panic(va_alist)
189 va_dcl
190 #endif
191 {
192 va_list ap;
193
194 #if __STDC__
195 va_start(ap, fmt);
196 #else
197 const char *fmt;
198
199 va_start(ap);
200 fmt = va_arg(ap, const char *);
201 #endif
202 vmsg(1, fmt, ap);
203 va_end(ap);
204 exit(8);
205 }
206
207 const char *
208 unrawname(name)
209 const char *name;
210 {
211 static char unrawbuf[32];
212 const char *dp;
213 struct stat stb;
214
215 if ((dp = strrchr(name, '/')) == 0)
216 return (name);
217 if (stat(name, &stb) < 0)
218 return (name);
219 if (!S_ISCHR(stb.st_mode))
220 return (name);
221 if (dp[1] != 'r')
222 return (name);
223 (void)snprintf(unrawbuf, 32, "%.*s/%s", (int)(dp - name), name, dp + 2);
224 return (unrawbuf);
225 }
226
227 const char *
228 rawname(name)
229 const char *name;
230 {
231 static char rawbuf[32];
232 const char *dp;
233
234 if ((dp = strrchr(name, '/')) == 0)
235 return (0);
236 (void)snprintf(rawbuf, 32, "%.*s/r%s", (int)(dp - name), name, dp + 1);
237 return (rawbuf);
238 }
239
240 const char *
241 blockcheck(origname)
242 const char *origname;
243 {
244 struct stat stslash, stblock, stchar;
245 const char *newname, *raw;
246 struct fstab *fsp;
247 int retried = 0;
248
249 hot = 0;
250 if (stat("/", &stslash) < 0) {
251 perror("/");
252 printf("Can't stat root\n");
253 return (origname);
254 }
255 newname = origname;
256 retry:
257 if (stat(newname, &stblock) < 0) {
258 perror(newname);
259 printf("Can't stat %s\n", newname);
260 return (origname);
261 }
262 if (S_ISBLK(stblock.st_mode)) {
263 if (stslash.st_dev == stblock.st_rdev)
264 hot++;
265 raw = rawname(newname);
266 if (stat(raw, &stchar) < 0) {
267 perror(raw);
268 printf("Can't stat %s\n", raw);
269 return (origname);
270 }
271 if (S_ISCHR(stchar.st_mode)) {
272 return (raw);
273 } else {
274 printf("%s is not a character device\n", raw);
275 return (origname);
276 }
277 } else if (S_ISCHR(stblock.st_mode) && !retried) {
278 newname = unrawname(newname);
279 retried++;
280 goto retry;
281 } else if ((fsp = getfsfile(newname)) != 0 && !retried) {
282 newname = fsp->fs_spec;
283 retried++;
284 goto retry;
285 }
286 /*
287 * Not a block or character device, just return name and
288 * let the user decide whether to use it.
289 */
290 return (origname);
291 }
292
293
294 void *
295 emalloc(s)
296 size_t s;
297 {
298 void *p;
299
300 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 void *q;
313
314 q = realloc(p, s);
315 if (q == NULL)
316 err(1, "realloc failed");
317 return (q);
318 }
319
320
321 char *
322 estrdup(s)
323 const char *s;
324 {
325 char *p;
326
327 p = strdup(s);
328 if (p == NULL)
329 err(1, "strdup failed");
330 return (p);
331 }
332