<sys/socket.h>: turn off MSG_NOSIGNAL
[minix3.git] / sbin / fsck / fsutil.c
blob96c21365912640c15543d9176c5b51cf29fdd82e
1 /* $NetBSD: fsutil.c,v 1.24 2013/01/13 19:53:16 mlelstv Exp $ */
3 /*
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: fsutil.c,v 1.24 2013/01/13 19:53:16 mlelstv Exp $");
35 #endif /* not lint */
37 #include <sys/param.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stdarg.h>
43 #include <errno.h>
44 #include <fstab.h>
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <err.h>
48 #include <util.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
53 #include "fsutil.h"
54 #include "exitvalues.h"
56 static const char *dev = NULL;
57 static int hot = 0;
58 static int preen = 0;
59 int quiet;
60 #define F_ERROR 0x80000000
62 void
63 setcdevname(const char *cd, int pr)
66 dev = cd;
67 preen = pr;
70 const char *
71 cdevname(void)
74 return dev;
77 int
78 hotroot(void)
81 return hot;
84 /*VARARGS*/
85 void
86 errexit(const char *fmt, ...)
88 va_list ap;
90 va_start(ap, fmt);
91 (void) vfprintf(stderr, fmt, ap);
92 va_end(ap);
93 (void)fprintf(stderr, "\n");
94 exit(FSCK_EXIT_CHECK_FAILED);
97 void
98 vmsg(int fatal, const char *fmt, va_list ap)
100 int serr = fatal & F_ERROR;
101 int serrno = errno;
102 fatal &= ~F_ERROR;
104 if (!fatal && preen)
105 (void)printf("%s: ", dev);
106 if (quiet && !preen) {
107 (void)printf("** %s (vmsg)\n", dev);
108 quiet = 0;
111 (void) vprintf(fmt, ap);
112 if (serr)
113 printf(" (%s)", strerror(serrno));
115 if (fatal && preen)
116 (void) printf("\n");
118 if (fatal && preen) {
119 (void) printf(
120 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
121 dev, getprogname());
122 exit(FSCK_EXIT_CHECK_FAILED);
126 /*VARARGS*/
127 void
128 pfatal(const char *fmt, ...)
130 va_list ap;
132 va_start(ap, fmt);
133 vmsg(1, fmt, ap);
134 va_end(ap);
137 /*VARARGS*/
138 void
139 pwarn(const char *fmt, ...)
141 va_list ap;
143 va_start(ap, fmt);
144 vmsg(0, fmt, ap);
145 va_end(ap);
148 void
149 perr(const char *fmt, ...)
151 va_list ap;
153 va_start(ap, fmt);
154 vmsg(1 | F_ERROR, fmt, ap);
155 va_end(ap);
158 void
159 panic(const char *fmt, ...)
161 va_list ap;
163 va_start(ap, fmt);
164 vmsg(1, fmt, ap);
165 va_end(ap);
166 exit(FSCK_EXIT_CHECK_FAILED);
169 const char *
170 blockcheck(const char *origname)
172 #if defined(__minix)
173 return origname;
174 #else
175 struct stat stslash, stblock, stchar;
176 const char *newname, *raw, *cooked;
177 struct fstab *fsp;
178 int retried = 0;
179 ssize_t len;
180 char cbuf[MAXPATHLEN];
181 static char buf[MAXPATHLEN];
183 hot = 0;
184 if (stat("/", &stslash) < 0) {
185 perr("Can't stat `/'");
186 return (origname);
188 len = readlink(origname, cbuf, sizeof(cbuf)-1);
189 if (len == -1) {
190 newname = origname;
191 } else {
192 cbuf[len] = '\0';
193 newname = cbuf;
195 retry:
196 if (stat(newname, &stblock) < 0) {
197 perr("Can't stat `%s'", newname);
198 return origname;
200 if (S_ISBLK(stblock.st_mode)) {
201 if (stslash.st_dev == stblock.st_rdev)
202 hot++;
203 raw = getdiskrawname(buf, sizeof(buf), newname);
204 if (raw == NULL) {
205 perr("Can't convert to raw `%s'", newname);
206 return origname;
208 if (stat(raw, &stchar) < 0) {
209 perr("Can't stat `%s'", raw);
210 return origname;
212 if (S_ISCHR(stchar.st_mode)) {
213 return raw;
214 } else {
215 perr("%s is not a character device\n", raw);
216 return origname;
218 } else if (S_ISCHR(stblock.st_mode) && !retried) {
219 cooked = getdiskcookedname(cbuf, sizeof(cbuf), newname);
220 if (cooked == NULL) {
221 perr("Can't convert to cooked `%s'", newname);
222 return origname;
223 } else
224 newname = cooked;
225 retried++;
226 goto retry;
227 } else if ((fsp = getfsfile(newname)) != 0 && !retried) {
228 newname = getfsspecname(cbuf, sizeof(cbuf), fsp->fs_spec);
229 if (newname == NULL)
230 perr("%s", buf);
231 retried++;
232 goto retry;
235 * Not a block or character device, just return name and
236 * let the user decide whether to use it.
238 return origname;
239 #endif /* defined(__minix) */
242 const char *
243 print_mtime(time_t t)
245 static char b[128];
246 char *p = ctime(&t);
247 if (p != NULL)
248 (void)snprintf(b, sizeof(b), "%12.12s %4.4s ", &p[4], &p[20]);
249 else
250 (void)snprintf(b, sizeof(b), "%lld ", (long long)t);
251 return b;
255 void
256 catch(int n)
258 if (ckfinish) (*ckfinish)(0);
259 _exit(FSCK_EXIT_SIGNALLED);
263 * When preening, allow a single quit to signal
264 * a special exit after filesystem checks complete
265 * so that reboot sequence may be interrupted.
267 void
268 catchquit(int n)
270 static const char msg[] =
271 "returning to single-user after filesystem check\n";
272 int serrno = errno;
274 (void)write(STDOUT_FILENO, msg, sizeof(msg) - 1);
275 returntosingle = 1;
276 (void)signal(SIGQUIT, SIG_DFL);
277 errno = serrno;
281 * Ignore a single quit signal; wait and flush just in case.
282 * Used by child processes in preen.
284 void
285 voidquit(int n)
287 int serrno = errno;
289 sleep(1);
290 (void)signal(SIGQUIT, SIG_IGN);
291 (void)signal(SIGQUIT, SIG_DFL);
292 errno = serrno;