1 /* $NetBSD: fsutil.c,v 1.20 2011/06/09 19:57:50 christos Exp $ */
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
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
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: fsutil.c,v 1.20 2011/06/09 19:57:50 christos Exp $");
37 #include <sys/param.h>
49 #include <sys/types.h>
53 #include "exitvalues.h"
55 static const char *dev
= NULL
;
59 #define F_ERROR 0x80000000
62 setcdevname(const char *cd
, int pr
)
85 errexit(const char *fmt
, ...)
90 (void) vfprintf(stderr
, fmt
, ap
);
92 (void)fprintf(stderr
, "\n");
93 exit(FSCK_EXIT_CHECK_FAILED
);
97 vmsg(int fatal
, const char *fmt
, va_list ap
)
99 int serr
= fatal
& F_ERROR
;
104 (void)printf("%s: ", dev
);
105 if (quiet
&& !preen
) {
106 (void)printf("** %s (vmsg)\n", dev
);
110 (void) vprintf(fmt
, ap
);
112 printf(" (%s)", strerror(serrno
));
117 if (fatal
&& preen
) {
119 "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
121 exit(FSCK_EXIT_CHECK_FAILED
);
127 pfatal(const char *fmt
, ...)
138 pwarn(const char *fmt
, ...)
148 perr(const char *fmt
, ...)
153 vmsg(1 | F_ERROR
, fmt
, ap
);
158 panic(const char *fmt
, ...)
165 exit(FSCK_EXIT_CHECK_FAILED
);
169 unrawname(const char *name
)
171 static char unrawbuf
[MAXPATHLEN
];
175 if ((dp
= strrchr(name
, '/')) == 0)
177 if (stat(name
, &stb
) < 0)
179 if (!S_ISCHR(stb
.st_mode
))
183 (void)snprintf(unrawbuf
, sizeof(unrawbuf
), "%.*s/%s",
184 (int)(dp
- name
), name
, dp
+ 2);
189 rawname(const char *name
)
191 static char rawbuf
[MAXPATHLEN
];
194 if ((dp
= strrchr(name
, '/')) == 0)
196 (void)snprintf(rawbuf
, sizeof(rawbuf
), "%.*s/r%s",
197 (int)(dp
- name
), name
, dp
+ 1);
202 blockcheck(const char *origname
)
207 struct stat stslash
, stblock
, stchar
;
208 const char *newname
, *raw
;
213 if (stat("/", &stslash
) < 0) {
214 perr("Can't stat `/'");
219 if (stat(newname
, &stblock
) < 0) {
220 perr("Can't stat `%s'", newname
);
223 if (S_ISBLK(stblock
.st_mode
)) {
224 if (stslash
.st_dev
== stblock
.st_rdev
)
226 raw
= strdup(newname
);
227 raw
= rawname(newname
);
228 if (stat(raw
, &stchar
) < 0) {
229 perr("Can't stat `%s'", raw
);
232 if (S_ISCHR(stchar
.st_mode
)) {
235 printf("%s is not a character device\n", raw
);
238 } else if (S_ISCHR(stblock
.st_mode
) && !retried
) {
239 newname
= unrawname(newname
);
242 } else if ((fsp
= getfsfile(newname
)) != 0 && !retried
) {
243 newname
= fsp
->fs_spec
;
248 * Not a block or character device, just return name and
249 * let the user decide whether to use it.
256 print_mtime(time_t t
)
261 (void)snprintf(b
, sizeof(b
), "%12.12s %4.4s ", &p
[4], &p
[20]);
263 (void)snprintf(b
, sizeof(b
), "%lld ", (long long)t
);
271 if (ckfinish
) (*ckfinish
)(0);
272 _exit(FSCK_EXIT_SIGNALLED
);
276 * When preening, allow a single quit to signal
277 * a special exit after filesystem checks complete
278 * so that reboot sequence may be interrupted.
283 static const char msg
[] =
284 "returning to single-user after filesystem check\n";
287 (void)write(STDOUT_FILENO
, msg
, sizeof(msg
) - 1);
289 (void)signal(SIGQUIT
, SIG_DFL
);
294 * Ignore a single quit signal; wait and flush just in case.
295 * Used by child processes in preen.
303 (void)signal(SIGQUIT
, SIG_IGN
);
304 (void)signal(SIGQUIT
, SIG_DFL
);