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