fsutil.c revision 1.3 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