fsutil.c revision 1.11 1 /* $NetBSD: fsutil.c,v 1.11 2001/11/09 07:50:19 lukem 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.11 2001/11/09 07:50:19 lukem Exp $");
39 #endif /* not lint */
40
41 #include <sys/param.h>
42
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <stdarg.h>
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 static void vmsg(int, const char *, va_list)
61 __attribute((__format__(__printf__,2,0)));
62
63 void
64 setcdevname(const char *cd, int pr)
65 {
66
67 dev = cd;
68 preen = pr;
69 }
70
71 const char *
72 cdevname(void)
73 {
74
75 return dev;
76 }
77
78 int
79 hotroot(void)
80 {
81
82 return hot;
83 }
84
85 /*VARARGS*/
86 void
87 errexit(const char *fmt, ...)
88 {
89 va_list ap;
90
91 va_start(ap, fmt);
92 (void) vfprintf(stderr, fmt, ap);
93 va_end(ap);
94 exit(8);
95 }
96
97 static void
98 vmsg(int fatal, const char *fmt, va_list ap)
99 {
100
101 if (!fatal && preen)
102 (void) printf("%s: ", dev);
103
104 (void) vprintf(fmt, ap);
105
106 if (fatal && preen)
107 (void) printf("\n");
108
109 if (fatal && preen) {
110 (void) printf(
111 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
112 dev, getprogname());
113 exit(8);
114 }
115 }
116
117 /*VARARGS*/
118 void
119 pfatal(const char *fmt, ...)
120 {
121 va_list ap;
122
123 va_start(ap, fmt);
124 vmsg(1, fmt, ap);
125 va_end(ap);
126 }
127
128 /*VARARGS*/
129 void
130 pwarn(const char *fmt, ...)
131 {
132 va_list ap;
133
134 va_start(ap, fmt);
135 vmsg(0, fmt, ap);
136 va_end(ap);
137 }
138
139 void
140 perror(const char *s)
141 {
142
143 pfatal("%s (%s)", s, strerror(errno));
144 }
145
146 void
147 panic(const char *fmt, ...)
148 {
149 va_list ap;
150
151 va_start(ap, fmt);
152 vmsg(1, fmt, ap);
153 va_end(ap);
154 exit(8);
155 }
156
157 const char *
158 unrawname(const char *name)
159 {
160 static char unrawbuf[MAXPATHLEN];
161 const char *dp;
162 struct stat stb;
163
164 if ((dp = strrchr(name, '/')) == 0)
165 return (name);
166 if (stat(name, &stb) < 0)
167 return (name);
168 if (!S_ISCHR(stb.st_mode))
169 return (name);
170 if (dp[1] != 'r')
171 return (name);
172 (void)snprintf(unrawbuf, sizeof(unrawbuf), "%.*s/%s",
173 (int)(dp - name), name, dp + 2);
174 return (unrawbuf);
175 }
176
177 const char *
178 rawname(const char *name)
179 {
180 static char rawbuf[MAXPATHLEN];
181 const char *dp;
182
183 if ((dp = strrchr(name, '/')) == 0)
184 return (0);
185 (void)snprintf(rawbuf, sizeof(rawbuf), "%.*s/r%s",
186 (int)(dp - name), name, dp + 1);
187 return (rawbuf);
188 }
189
190 const char *
191 blockcheck(const char *origname)
192 {
193 struct stat stslash, stblock, stchar;
194 const char *newname, *raw;
195 struct fstab *fsp;
196 int retried = 0;
197
198 hot = 0;
199 if (stat("/", &stslash) < 0) {
200 perror("/");
201 printf("Can't stat root\n");
202 return (origname);
203 }
204 newname = origname;
205 retry:
206 if (stat(newname, &stblock) < 0) {
207 perror(newname);
208 printf("Can't stat %s\n", newname);
209 return (origname);
210 }
211 if (S_ISBLK(stblock.st_mode)) {
212 if (stslash.st_dev == stblock.st_rdev)
213 hot++;
214 raw = rawname(newname);
215 if (stat(raw, &stchar) < 0) {
216 perror(raw);
217 printf("Can't stat %s\n", raw);
218 return (origname);
219 }
220 if (S_ISCHR(stchar.st_mode)) {
221 return (raw);
222 } else {
223 printf("%s is not a character device\n", raw);
224 return (origname);
225 }
226 } else if (S_ISCHR(stblock.st_mode) && !retried) {
227 newname = unrawname(newname);
228 retried++;
229 goto retry;
230 } else if ((fsp = getfsfile(newname)) != 0 && !retried) {
231 newname = fsp->fs_spec;
232 retried++;
233 goto retry;
234 }
235 /*
236 * Not a block or character device, just return name and
237 * let the user decide whether to use it.
238 */
239 return (origname);
240 }
241
242
243 void *
244 emalloc(size_t s)
245 {
246 void *p;
247
248 p = malloc(s);
249 if (p == NULL)
250 err(1, "malloc failed");
251 return (p);
252 }
253
254
255 void *
256 erealloc(void *p, size_t s)
257 {
258 void *q;
259
260 q = realloc(p, s);
261 if (q == NULL)
262 err(1, "realloc failed");
263 return (q);
264 }
265
266
267 char *
268 estrdup(const char *s)
269 {
270 char *p;
271
272 p = strdup(s);
273 if (p == NULL)
274 err(1, "strdup failed");
275 return (p);
276 }
277