1 /* $OpenBSD: fsutil.c,v 1.24 2019/06/28 13:32:43 deraadt Exp $ */
2 /* $NetBSD: fsutil.c,v 1.2 1996/10/03 20:06:31 christos Exp $ */
3
4 /*
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <errno.h>
38 #include <fstab.h>
39 #include <limits.h>
40 #include <err.h>
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #include "fsutil.h"
46
47 static const char *dev = NULL;
48 static const char *origdev = NULL;
49 static int hot = 0;
50 static int preen = 0;
51
52 extern char *__progname;
53
54 static void vmsg(int, const char *, va_list);
55
56 struct stat stslash;
57
58 void
checkroot(void)59 checkroot(void)
60 {
61 if (stat("/", &stslash) == -1) {
62 xperror("/");
63 printf("Can't stat root\n");
64 }
65 }
66
67 void
setcdevname(const char * cd,const char * ocd,int pr)68 setcdevname(const char *cd, const char *ocd, int pr)
69 {
70 dev = cd;
71 origdev = ocd;
72 preen = pr;
73 }
74
75 const char *
cdevname(void)76 cdevname(void)
77 {
78 return dev;
79 }
80
81 int
hotroot(void)82 hotroot(void)
83 {
84 return hot;
85 }
86
87 void
errexit(const char * fmt,...)88 errexit(const char *fmt, ...)
89 {
90 va_list ap;
91
92 va_start(ap, fmt);
93 (void) vfprintf(stderr, fmt, ap);
94 va_end(ap);
95 exit(8);
96 }
97
98 static void
vmsg(int fatal,const char * fmt,va_list ap)99 vmsg(int fatal, const char *fmt, va_list ap)
100 {
101 if (!fatal && preen) {
102 if (origdev)
103 printf("%s (%s): ", dev, origdev);
104 else
105 printf("%s: ", dev);
106 }
107
108 (void) vprintf(fmt, ap);
109
110 if (fatal && preen) {
111 printf("\n");
112 if (origdev)
113 printf("%s (%s): ", dev, origdev);
114 else
115 printf("%s: ", dev);
116 printf("UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
117 __progname);
118 exit(8);
119 }
120 }
121
122 void
pfatal(const char * fmt,...)123 pfatal(const char *fmt, ...)
124 {
125 va_list ap;
126
127 va_start(ap, fmt);
128 vmsg(1, fmt, ap);
129 va_end(ap);
130 }
131
132 void
pwarn(const char * fmt,...)133 pwarn(const char *fmt, ...)
134 {
135 va_list ap;
136
137 va_start(ap, fmt);
138 vmsg(0, fmt, ap);
139 va_end(ap);
140 }
141
142 void
xperror(const char * s)143 xperror(const char *s)
144 {
145 pfatal("%s (%s)", s, strerror(errno));
146 }
147
148 void
panic(const char * fmt,...)149 panic(const char *fmt, ...)
150 {
151 va_list ap;
152
153 va_start(ap, fmt);
154 vmsg(1, fmt, ap);
155 va_end(ap);
156 exit(8);
157 }
158
159 char *
unrawname(char * name)160 unrawname(char *name)
161 {
162 char *dp;
163 struct stat stb;
164
165 if ((dp = strrchr(name, '/')) == NULL)
166 return (name);
167 if (stat(name, &stb) == -1)
168 return (name);
169 if (!S_ISCHR(stb.st_mode))
170 return (name);
171 if (dp[1] != 'r')
172 return (name);
173 (void)memmove(&dp[1], &dp[2], strlen(&dp[2]) + 1);
174 return (name);
175 }
176
177 char *
rawname(char * name)178 rawname(char *name)
179 {
180 static char rawbuf[PATH_MAX];
181 char *dp;
182
183 if ((dp = strrchr(name, '/')) == NULL)
184 return (0);
185 *dp = 0;
186 (void)strlcpy(rawbuf, name, sizeof rawbuf);
187 *dp = '/';
188 (void)strlcat(rawbuf, "/r", sizeof rawbuf);
189 (void)strlcat(rawbuf, &dp[1], sizeof rawbuf);
190 return (rawbuf);
191 }
192
193 char *
blockcheck(char * origname)194 blockcheck(char *origname)
195 {
196 struct stat stblock, stchar;
197 char *newname, *raw;
198 struct fstab *fsp;
199 int retried = 0;
200
201 hot = 0;
202 newname = origname;
203 retry:
204 if (stat(newname, &stblock) == -1)
205 return (origname);
206
207 if (S_ISBLK(stblock.st_mode)) {
208 if (stslash.st_dev == stblock.st_rdev)
209 hot++;
210 raw = rawname(newname);
211 if (stat(raw, &stchar) == -1) {
212 xperror(raw);
213 printf("Can't stat %s\n", raw);
214 return (origname);
215 }
216 if (S_ISCHR(stchar.st_mode)) {
217 return (raw);
218 } else {
219 printf("%s is not a character device\n", raw);
220 return (origname);
221 }
222 } else if (S_ISCHR(stblock.st_mode) && !retried) {
223 newname = unrawname(newname);
224 retried++;
225 goto retry;
226 } else if ((fsp = getfsfile(newname)) != 0 && !retried) {
227 newname = fsp->fs_spec;
228 retried++;
229 goto retry;
230 }
231 /*
232 * Not a block or character device, just return name and
233 * let the user decide whether to use it.
234 */
235 return (origname);
236 }
237
238
239 void *
emalloc(size_t s)240 emalloc(size_t s)
241 {
242 void *p;
243
244 if (s == 0)
245 err(1, "malloc failed");
246 p = malloc(s);
247 if (p == NULL)
248 err(1, "malloc failed");
249 return p;
250 }
251
252
253 void *
ereallocarray(void * p,size_t n,size_t s)254 ereallocarray(void *p, size_t n, size_t s)
255 {
256 void *newp;
257
258 if (n == 0 || s == 0) {
259 free(p);
260 err(1, "realloc failed");
261 }
262 newp = reallocarray(p, n, s);
263 if (newp == NULL) {
264 free(p);
265 err(1, "realloc failed");
266 }
267 return newp;
268 }
269
270
271 char *
estrdup(const char * s)272 estrdup(const char *s)
273 {
274 char *p = strdup(s);
275 if (p == NULL)
276 err(1, "strdup failed");
277 return p;
278 }
279