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