1 /* $NetBSD: main.c,v 1.41 2010/01/06 18:12:37 christos Exp $ */
4 * Copyright (c) 1980, 1986, 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/param.h>
34 #include <sys/mount.h>
35 #include <ufs/ufs/dinode.h>
36 #include <ufs/ufs/ufsmount.h>
37 #include <ufs/lfs/lfs.h>
53 #include "exitvalues.h"
55 volatile sig_atomic_t returntosingle
= 0;
57 static int argtoi(int, const char *, const char *, int);
58 static int checkfilesys(const char *, char *, long, int);
59 static void usage(void);
60 static void efun(int, const char *, ...);
61 extern void (*panic_func
)(int, const char *, va_list);
64 efun(int eval
, const char *fmt
, ...)
73 main(int argc
, char **argv
)
76 int ret
= FSCK_EXIT_OK
;
77 const char *optstring
= "b:dfi:m:npPqUy";
84 while ((ch
= getopt(argc
, argv
, optstring
)) != -1) {
88 bflag
= argtoi('b', "number", optarg
, 0);
89 printf("Alternate super block location: %d\n", bflag
);
101 idaddr
= strtol(optarg
, NULL
, 0);
104 lfmode
= argtoi('m', "mode", optarg
, 8);
106 err(1, "bad mode to -m: %o\n", lfmode
);
107 printf("** lost+found creation mode %o\n", lfmode
);
119 case 'P': /* Progress meter not implemented. */
146 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
147 (void) signal(SIGINT
, catch);
149 (void) signal(SIGQUIT
, catchquit
);
152 int nret
= checkfilesys(blockcheck(*argv
++), 0, 0L, 0);
157 return returntosingle
? FSCK_EXIT_UNRESOLVED
: ret
;
161 argtoi(int flag
, const char *req
, const char *str
, int base
)
166 ret
= (int) strtol(str
, &cp
, base
);
167 if (cp
== str
|| *cp
)
168 err(FSCK_EXIT_USAGE
, "-%c flag requires a %s\n", flag
, req
);
173 * Check the specified filesystem.
178 checkfilesys(const char *filesys
, char *mntpt
, long auxdata
, int child
)
184 (void) signal(SIGQUIT
, voidquit
);
185 setcdevname(filesys
, preen
);
188 switch (setup(filesys
)) {
191 pfatal("CAN'T CHECK FILE SYSTEM.");
197 * For LFS, "preen" means "roll forward". We don't check anything
201 printf("** Last Mounted on %s\n", fs
->lfs_fsmnt
);
203 printf("** Root file system\n");
205 * 0: check segment checksums, inode ranges
207 printf("** Phase 0 - Check Inode Free List\n");
211 * Check inode free list - we do this even if idaddr is set,
212 * since if we're writing we don't want to write a bad list.
218 * 1: scan inodes tallying blocks used
220 printf("** Phase 1 - Check Blocks and Sizes\n");
224 * 2: traverse directories from root to mark all connected directories
226 printf("** Phase 2 - Check Pathnames\n");
230 * 3: scan inodes looking for disconnected directories
232 printf("** Phase 3 - Check Connectivity\n");
236 * 4: scan inodes looking for disconnected files; check reference counts
238 printf("** Phase 4 - Check Reference Counts\n");
243 * 5: check segment byte totals and dirty flags, and cleanerinfo
246 printf("** Phase 5 - Check Segment Block Accounting\n");
249 if (debug
&& !preen
) {
250 if (duplist
!= NULL
) {
251 printf("The following duplicate blocks remain:");
252 for (dp
= duplist
; dp
; dp
= dp
->next
)
253 printf(" %lld,", (long long) dp
->dup
);
256 if (zlnhead
!= NULL
) {
257 printf("The following zero link count inodes remain:");
258 for (zlnp
= zlnhead
; zlnp
; zlnp
= zlnp
->next
)
260 (unsigned long long)zlnp
->zlncnt
);
267 if (reply("ROLL FILESYSTEM FORWARD") == 1) {
268 printf("** Phase 6 - Roll Forward\n");
276 zlnhead
= (struct zlncnt
*) 0;
277 orphead
= (struct zlncnt
*) 0;
278 duplist
= (struct dups
*) 0;
279 muldup
= (struct dups
*) 0;
283 * print out summary statistics
285 pwarn("%llu files, %lld used, %lld free\n",
286 (unsigned long long)n_files
, (long long) n_blks
,
287 (long long) fs
->lfs_bfree
);
293 free((char *)lncntp
);
298 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
300 printf("\n***** PLEASE RERUN FSCK *****\n");
302 struct statvfs stfs_buf
;
304 * We modified the root. Do a mount update on
305 * it, unless it is read-write, so we can continue.
307 if (statvfs("/", &stfs_buf
) == 0) {
308 long flags
= stfs_buf
.f_flag
;
309 struct ufs_args args
;
311 if (flags
& MNT_RDONLY
) {
313 flags
|= MNT_UPDATE
| MNT_RELOAD
;
314 if (mount(MOUNT_LFS
, "/", flags
,
315 &args
, sizeof args
) == 0)
320 printf("\n***** REBOOT NOW *****\n");
322 return FSCK_EXIT_ROOT_CHANGED
;
331 (void) fprintf(stderr
,
332 "Usage: %s [-dfpqU] [-b block] [-m mode] [-y | -n] filesystem ...\n",
334 exit(FSCK_EXIT_USAGE
);