xref: /netbsd/sbin/fsck_ext2fs/main.c (revision 96ec6919)
1*96ec6919Sjoerg /*	$NetBSD: main.c,v 1.41 2020/04/05 15:25:39 joerg Exp $	*/
2bf07c871Sagc 
3bf07c871Sagc /*
4bf07c871Sagc  * Copyright (c) 1980, 1986, 1993
5bf07c871Sagc  *	The Regents of the University of California.  All rights reserved.
6bf07c871Sagc  *
7bf07c871Sagc  * Redistribution and use in source and binary forms, with or without
8bf07c871Sagc  * modification, are permitted provided that the following conditions
9bf07c871Sagc  * are met:
10bf07c871Sagc  * 1. Redistributions of source code must retain the above copyright
11bf07c871Sagc  *    notice, this list of conditions and the following disclaimer.
12bf07c871Sagc  * 2. Redistributions in binary form must reproduce the above copyright
13bf07c871Sagc  *    notice, this list of conditions and the following disclaimer in the
14bf07c871Sagc  *    documentation and/or other materials provided with the distribution.
15bf07c871Sagc  * 3. Neither the name of the University nor the names of its contributors
16bf07c871Sagc  *    may be used to endorse or promote products derived from this software
17bf07c871Sagc  *    without specific prior written permission.
18bf07c871Sagc  *
19bf07c871Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20bf07c871Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21bf07c871Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22bf07c871Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23bf07c871Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24bf07c871Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25bf07c871Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26bf07c871Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27bf07c871Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28bf07c871Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29bf07c871Sagc  * SUCH DAMAGE.
30bf07c871Sagc  */
318f7c2b37Sbouyer 
328f7c2b37Sbouyer /*
338f7c2b37Sbouyer  * Copyright (c) 1997 Manuel Bouyer.
348f7c2b37Sbouyer  *
358f7c2b37Sbouyer  * Redistribution and use in source and binary forms, with or without
368f7c2b37Sbouyer  * modification, are permitted provided that the following conditions
378f7c2b37Sbouyer  * are met:
388f7c2b37Sbouyer  * 1. Redistributions of source code must retain the above copyright
398f7c2b37Sbouyer  *    notice, this list of conditions and the following disclaimer.
408f7c2b37Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
418f7c2b37Sbouyer  *    notice, this list of conditions and the following disclaimer in the
428f7c2b37Sbouyer  *    documentation and/or other materials provided with the distribution.
438f7c2b37Sbouyer  *
442f853da9Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
452f853da9Sbouyer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
462f853da9Sbouyer  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
472f853da9Sbouyer  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
482f853da9Sbouyer  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
492f853da9Sbouyer  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
502f853da9Sbouyer  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
512f853da9Sbouyer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
522f853da9Sbouyer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
532f853da9Sbouyer  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
548f7c2b37Sbouyer  */
558f7c2b37Sbouyer 
564b836889Slukem #include <sys/cdefs.h>
578f7c2b37Sbouyer #ifndef lint
586543a91fSlukem __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\
596543a91fSlukem  The Regents of the University of California.  All rights reserved.");
608f7c2b37Sbouyer #endif /* not lint */
618f7c2b37Sbouyer 
628f7c2b37Sbouyer #ifndef lint
638f7c2b37Sbouyer #if 0
648f7c2b37Sbouyer static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 1/23/94";
658f7c2b37Sbouyer #else
66*96ec6919Sjoerg __RCSID("$NetBSD: main.c,v 1.41 2020/04/05 15:25:39 joerg Exp $");
678f7c2b37Sbouyer #endif
688f7c2b37Sbouyer #endif /* not lint */
698f7c2b37Sbouyer 
708f7c2b37Sbouyer #include <sys/param.h>
718f7c2b37Sbouyer #include <sys/time.h>
728f7c2b37Sbouyer #include <sys/mount.h>
73e5bc90f4Sfvdl #include <ufs/ufs/ufsmount.h>
748f7c2b37Sbouyer #include <ufs/ext2fs/ext2fs_dinode.h>
758f7c2b37Sbouyer #include <ufs/ext2fs/ext2fs.h>
768f7c2b37Sbouyer #include <fstab.h>
778f7c2b37Sbouyer #include <stdlib.h>
788f7c2b37Sbouyer #include <string.h>
798f7c2b37Sbouyer #include <ctype.h>
808f7c2b37Sbouyer #include <stdio.h>
810369f1ecSkleink #include <time.h>
828f7c2b37Sbouyer #include <unistd.h>
83628f1591Sdrochner #include <signal.h>
848f7c2b37Sbouyer 
858f7c2b37Sbouyer #include "fsck.h"
868f7c2b37Sbouyer #include "extern.h"
878f7c2b37Sbouyer #include "fsutil.h"
88742b48d5Schristos #include "exitvalues.h"
898f7c2b37Sbouyer 
90*96ec6919Sjoerg struct bufarea bufhead;
91*96ec6919Sjoerg struct bufarea sblk;
92*96ec6919Sjoerg struct bufarea asblk;
93*96ec6919Sjoerg struct bufarea *pdirbp;
94*96ec6919Sjoerg struct bufarea *pbp;
95*96ec6919Sjoerg struct bufarea *getdatablk(daddr_t, long);
96*96ec6919Sjoerg struct m_ext2fs sblock;
97*96ec6919Sjoerg struct dups *duplist;
98*96ec6919Sjoerg struct dups *muldup;
99*96ec6919Sjoerg struct zlncnt *zlnhead;
100*96ec6919Sjoerg struct inoinfo **inphead, **inpsort;
101*96ec6919Sjoerg long numdirs, listmax, inplast;
102*96ec6919Sjoerg long	dev_bsize;
103*96ec6919Sjoerg long	secsize;
104*96ec6919Sjoerg char	nflag;
105*96ec6919Sjoerg char	yflag;
106*96ec6919Sjoerg int	bflag;
107*96ec6919Sjoerg int	Uflag;
108*96ec6919Sjoerg int	debug;
109*96ec6919Sjoerg int	preen;
110*96ec6919Sjoerg char	havesb;
111*96ec6919Sjoerg char	skipclean;
112*96ec6919Sjoerg int	fsmodified;
113*96ec6919Sjoerg int	fsreadfd;
114*96ec6919Sjoerg int	fswritefd;
115*96ec6919Sjoerg int	rerun;
116*96ec6919Sjoerg daddr_t	maxfsblock;
117*96ec6919Sjoerg char	*blockmap;
118*96ec6919Sjoerg ino_t	maxino;
119*96ec6919Sjoerg ino_t	lastino;
120*96ec6919Sjoerg char	*statemap;
121*96ec6919Sjoerg u_char	*typemap;
122*96ec6919Sjoerg int16_t	*lncntp;
123*96ec6919Sjoerg ino_t	lfdir;
124*96ec6919Sjoerg daddr_t	n_blks;
125*96ec6919Sjoerg daddr_t	n_files;
126*96ec6919Sjoerg struct	ext2fs_dinode zino;
1278f7c2b37Sbouyer 
12897880e96Schristos static int	argtoi(int, const char *, const char *, int);
129ccde05f0Sxtraeme static int	checkfilesys(const char *, char *, long, int);
130742b48d5Schristos static void	usage(void) __dead;
1318f7c2b37Sbouyer 
1328f7c2b37Sbouyer int
main(int argc,char * argv[])133ccde05f0Sxtraeme main(int argc, char *argv[])
1348f7c2b37Sbouyer {
1358f7c2b37Sbouyer 	int ch;
136742b48d5Schristos 	int ret = FSCK_EXIT_OK;
1378f7c2b37Sbouyer 
138861be3d9Schristos 	ckfinish = ckfini;
1398f7c2b37Sbouyer 	sync();
1408f7c2b37Sbouyer 	skipclean = 1;
141e67b5654Stron 	while ((ch = getopt(argc, argv, "b:dfm:npPqUy")) != -1) {
1428f7c2b37Sbouyer 		switch (ch) {
1438f7c2b37Sbouyer 		case 'b':
1448f7c2b37Sbouyer 			skipclean = 0;
1458f7c2b37Sbouyer 			bflag = argtoi('b', "number", optarg, 10);
1468f7c2b37Sbouyer 			printf("Alternate super block location: %d\n", bflag);
1478f7c2b37Sbouyer 			break;
1488f7c2b37Sbouyer 
1498f7c2b37Sbouyer 		case 'd':
1508f7c2b37Sbouyer 			debug++;
1518f7c2b37Sbouyer 			break;
1528f7c2b37Sbouyer 
1538f7c2b37Sbouyer 		case 'f':
1548f7c2b37Sbouyer 			skipclean = 0;
1558f7c2b37Sbouyer 			break;
1568f7c2b37Sbouyer 
1578f7c2b37Sbouyer 		case 'm':
1588f7c2b37Sbouyer 			lfmode = argtoi('m', "mode", optarg, 8);
1598f7c2b37Sbouyer 			if (lfmode &~ 07777)
160481ad7b0Slukem 				errexit("bad mode to -m: %o", lfmode);
1618f7c2b37Sbouyer 			printf("** lost+found creation mode %o\n", lfmode);
1628f7c2b37Sbouyer 			break;
1638f7c2b37Sbouyer 
1648f7c2b37Sbouyer 		case 'n':
1658f7c2b37Sbouyer 			nflag++;
1668f7c2b37Sbouyer 			yflag = 0;
1678f7c2b37Sbouyer 			break;
1688f7c2b37Sbouyer 
1698f7c2b37Sbouyer 		case 'p':
1708f7c2b37Sbouyer 			preen++;
1718f7c2b37Sbouyer 			break;
1728f7c2b37Sbouyer 
173a73c2bd5Schristos 		case 'P':
174a73c2bd5Schristos 			/* Progress meter not implemented. */
175a73c2bd5Schristos 			break;
176a73c2bd5Schristos 
177e69ce3e4Sdsl 		case 'q':		/* Quiet not implemented */
178e69ce3e4Sdsl 			break;
179e69ce3e4Sdsl 
18059334248Schristos #ifndef SMALL
18159334248Schristos 		case 'U':
18259334248Schristos 			Uflag++;
18359334248Schristos 			break;
18459334248Schristos #endif
18559334248Schristos 
1868f7c2b37Sbouyer 		case 'y':
1878f7c2b37Sbouyer 			yflag++;
1888f7c2b37Sbouyer 			nflag = 0;
1898f7c2b37Sbouyer 			break;
1908f7c2b37Sbouyer 
1918f7c2b37Sbouyer 		default:
1928f7c2b37Sbouyer 			usage();
1938f7c2b37Sbouyer 		}
1948f7c2b37Sbouyer 	}
1958f7c2b37Sbouyer 
1968f7c2b37Sbouyer 	argc -= optind;
1978f7c2b37Sbouyer 	argv += optind;
1988f7c2b37Sbouyer 
1998f7c2b37Sbouyer 	if (!argc)
2008f7c2b37Sbouyer 		usage();
2018f7c2b37Sbouyer 
2028f7c2b37Sbouyer 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
2038f7c2b37Sbouyer 		(void)signal(SIGINT, catch);
2048f7c2b37Sbouyer 	if (preen)
2058f7c2b37Sbouyer 		(void)signal(SIGQUIT, catchquit);
2068f7c2b37Sbouyer 
207742b48d5Schristos 	while (argc-- > 0) {
208742b48d5Schristos 		int nret = checkfilesys(blockcheck(*argv++), 0, 0L, 0);
209742b48d5Schristos 		if (ret < nret)
210742b48d5Schristos 			ret = nret;
211742b48d5Schristos 	}
2128f7c2b37Sbouyer 
213742b48d5Schristos 	return returntosingle ? FSCK_EXIT_UNRESOLVED : ret;
2148f7c2b37Sbouyer }
2158f7c2b37Sbouyer 
2168f7c2b37Sbouyer static int
argtoi(int flag,const char * req,const char * str,int base)21797880e96Schristos argtoi(int flag, const char *req, const char *str, int base)
2188f7c2b37Sbouyer {
2198f7c2b37Sbouyer 	char *cp;
2208f7c2b37Sbouyer 	int ret;
2218f7c2b37Sbouyer 
2228f7c2b37Sbouyer 	ret = (int)strtol(str, &cp, base);
2238f7c2b37Sbouyer 	if (cp == str || *cp)
224481ad7b0Slukem 		errexit("-%c flag requires a %s", flag, req);
2258f7c2b37Sbouyer 	return (ret);
2268f7c2b37Sbouyer }
2278f7c2b37Sbouyer 
2288f7c2b37Sbouyer /*
2298f7c2b37Sbouyer  * Check the specified filesystem.
2308f7c2b37Sbouyer  */
2318f7c2b37Sbouyer /* ARGSUSED */
2328f7c2b37Sbouyer static int
checkfilesys(const char * filesys,char * mntpt,long auxdata,int child)233ccde05f0Sxtraeme checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
2348f7c2b37Sbouyer {
2358f7c2b37Sbouyer 	daddr_t n_bfree;
2368f7c2b37Sbouyer 	struct dups *dp;
2378f7c2b37Sbouyer 	struct zlncnt *zlnp;
23809d4663fSbouyer 	int i;
2398f7c2b37Sbouyer 
2408f7c2b37Sbouyer 	if (preen && child)
2418f7c2b37Sbouyer 		(void)signal(SIGQUIT, voidquit);
2428f7c2b37Sbouyer 	setcdevname(filesys, preen);
2438f7c2b37Sbouyer 	if (debug && preen)
2448f7c2b37Sbouyer 		pwarn("starting\n");
2458f7c2b37Sbouyer 	switch (setup(filesys)) {
2468f7c2b37Sbouyer 	case 0:
2478f7c2b37Sbouyer 		if (preen)
2488f7c2b37Sbouyer 			pfatal("CAN'T CHECK FILE SYSTEM.");
24978876854Smrg 		/* FALLTHROUGH */
2508f7c2b37Sbouyer 	case -1:
251742b48d5Schristos 		return FSCK_EXIT_OK;
2528f7c2b37Sbouyer 	}
2538f7c2b37Sbouyer 	/*
2548f7c2b37Sbouyer 	 * 1: scan inodes tallying blocks used
2558f7c2b37Sbouyer 	 */
2568f7c2b37Sbouyer 	if (preen == 0) {
2575fb6bc4eSbouyer 		if (sblock.e2fs.e2fs_rev > E2FS_REV0) {
2585fb6bc4eSbouyer 			printf("** Last Mounted on %s\n",
2595fb6bc4eSbouyer 			    sblock.e2fs.e2fs_fsmnt);
2605fb6bc4eSbouyer 		}
2618f7c2b37Sbouyer 		if (hotroot())
2628f7c2b37Sbouyer 			printf("** Root file system\n");
2638f7c2b37Sbouyer 		printf("** Phase 1 - Check Blocks and Sizes\n");
2648f7c2b37Sbouyer 	}
2658f7c2b37Sbouyer 	pass1();
2668f7c2b37Sbouyer 
2678f7c2b37Sbouyer 	/*
2688f7c2b37Sbouyer 	 * 1b: locate first references to duplicates, if any
2698f7c2b37Sbouyer 	 */
2708f7c2b37Sbouyer 	if (duplist) {
2718f7c2b37Sbouyer 		if (preen)
2728f7c2b37Sbouyer 			pfatal("INTERNAL ERROR: dups with -p");
2738f7c2b37Sbouyer 		printf("** Phase 1b - Rescan For More DUPS\n");
2748f7c2b37Sbouyer 		pass1b();
2758f7c2b37Sbouyer 	}
2768f7c2b37Sbouyer 
2778f7c2b37Sbouyer 	/*
2788f7c2b37Sbouyer 	 * 2: traverse directories from root to mark all connected directories
2798f7c2b37Sbouyer 	 */
2808f7c2b37Sbouyer 	if (preen == 0)
2818f7c2b37Sbouyer 		printf("** Phase 2 - Check Pathnames\n");
2828f7c2b37Sbouyer 	pass2();
2838f7c2b37Sbouyer 
2848f7c2b37Sbouyer 	/*
2858f7c2b37Sbouyer 	 * 3: scan inodes looking for disconnected directories
2868f7c2b37Sbouyer 	 */
2878f7c2b37Sbouyer 	if (preen == 0)
2888f7c2b37Sbouyer 		printf("** Phase 3 - Check Connectivity\n");
2898f7c2b37Sbouyer 	pass3();
2908f7c2b37Sbouyer 
2918f7c2b37Sbouyer 	/*
2928f7c2b37Sbouyer 	 * 4: scan inodes looking for disconnected files; check reference counts
2938f7c2b37Sbouyer 	 */
2948f7c2b37Sbouyer 	if (preen == 0)
2958f7c2b37Sbouyer 		printf("** Phase 4 - Check Reference Counts\n");
2968f7c2b37Sbouyer 	pass4();
2978f7c2b37Sbouyer 
2988f7c2b37Sbouyer 	/*
2998f7c2b37Sbouyer 	 * 5: check and repair resource counts in cylinder groups
3008f7c2b37Sbouyer 	 */
3018f7c2b37Sbouyer 	if (preen == 0)
3028f7c2b37Sbouyer 		printf("** Phase 5 - Check Cyl groups\n");
3038f7c2b37Sbouyer 	pass5();
3048f7c2b37Sbouyer 
3058f7c2b37Sbouyer 	/*
3068f7c2b37Sbouyer 	 * print out summary statistics
3078f7c2b37Sbouyer 	 */
3088f7c2b37Sbouyer 	n_bfree = sblock.e2fs.e2fs_fbcount;
3098f7c2b37Sbouyer 
310a3ff3a30Sfvdl 	pwarn("%lld files, %lld used, %lld free\n",
311a3ff3a30Sfvdl 	    (long long)n_files, (long long)n_blks, (long long)n_bfree);
3128f7c2b37Sbouyer 	if (debug &&
3138f7c2b37Sbouyer 		/* 9 reserved and unused inodes in FS */
3148f7c2b37Sbouyer 	    (n_files -= maxino - 9 - sblock.e2fs.e2fs_ficount))
315a3ff3a30Sfvdl 		printf("%lld files missing\n", (long long)n_files);
3168f7c2b37Sbouyer 	if (debug) {
31709d4663fSbouyer 		for (i = 0; i < sblock.e2fs_ncg; i++)
31809d4663fSbouyer 			n_blks +=  cgoverhead(i);
3198f7c2b37Sbouyer 		n_blks += sblock.e2fs.e2fs_first_dblock;
3208f7c2b37Sbouyer 		if (n_blks -= maxfsblock - n_bfree)
321a3ff3a30Sfvdl 			printf("%lld blocks missing\n", (long long)n_blks);
3228f7c2b37Sbouyer 		if (duplist != NULL) {
3238f7c2b37Sbouyer 			printf("The following duplicate blocks remain:");
3248f7c2b37Sbouyer 			for (dp = duplist; dp; dp = dp->next)
325a3ff3a30Sfvdl 				printf(" %lld,", (long long)dp->dup);
3268f7c2b37Sbouyer 			printf("\n");
3278f7c2b37Sbouyer 		}
3288f7c2b37Sbouyer 		if (zlnhead != NULL) {
3298f7c2b37Sbouyer 			printf("The following zero link count inodes remain:");
3308f7c2b37Sbouyer 			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
331c4ee9f6dSchristos 				printf(" %llu,",
332c4ee9f6dSchristos 				    (unsigned long long)zlnp->zlncnt);
3338f7c2b37Sbouyer 			printf("\n");
3348f7c2b37Sbouyer 		}
3358f7c2b37Sbouyer 	}
3368f7c2b37Sbouyer 	zlnhead = (struct zlncnt *)0;
3378f7c2b37Sbouyer 	duplist = (struct dups *)0;
3388f7c2b37Sbouyer 	muldup = (struct dups *)0;
3398f7c2b37Sbouyer 	inocleanup();
3408f7c2b37Sbouyer 	if (fsmodified) {
3418f7c2b37Sbouyer 		time_t t;
3428f7c2b37Sbouyer 		(void)time(&t);
3438f7c2b37Sbouyer 		sblock.e2fs.e2fs_wtime = t;
3448f7c2b37Sbouyer 		sblock.e2fs.e2fs_lastfsck = t;
3458f7c2b37Sbouyer 		sbdirty();
3468f7c2b37Sbouyer 	}
3478f7c2b37Sbouyer 	ckfini(1);
3488f7c2b37Sbouyer 	free(blockmap);
3498f7c2b37Sbouyer 	free(statemap);
3508f7c2b37Sbouyer 	free((char *)lncntp);
3518f7c2b37Sbouyer 	if (!fsmodified)
352742b48d5Schristos 		return FSCK_EXIT_OK;
3538f7c2b37Sbouyer 	if (!preen)
3548f7c2b37Sbouyer 		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
3558f7c2b37Sbouyer 	if (rerun)
3568f7c2b37Sbouyer 		printf("\n***** PLEASE RERUN FSCK *****\n");
3578f7c2b37Sbouyer 	if (hotroot()) {
3586bd1d6d4Schristos 		struct statvfs stfs_buf;
3598f7c2b37Sbouyer 		/*
3608f7c2b37Sbouyer 		 * We modified the root.  Do a mount update on
3618f7c2b37Sbouyer 		 * it, unless it is read-write, so we can continue.
3628f7c2b37Sbouyer 		 */
3636bd1d6d4Schristos 		if (statvfs("/", &stfs_buf) == 0) {
3646bd1d6d4Schristos 			long flags = stfs_buf.f_flag;
3658f7c2b37Sbouyer 			struct ufs_args args;
3668f7c2b37Sbouyer 
3678f7c2b37Sbouyer 			if (flags & MNT_RDONLY) {
3688f7c2b37Sbouyer 				args.fspec = 0;
3698f7c2b37Sbouyer 				flags |= MNT_UPDATE | MNT_RELOAD;
370742b48d5Schristos 				if (mount(MOUNT_EXT2FS, "/", flags,
371742b48d5Schristos 				    &args, sizeof args) == 0)
372742b48d5Schristos 					return FSCK_EXIT_OK;
3738f7c2b37Sbouyer 			}
3748f7c2b37Sbouyer 		}
3758f7c2b37Sbouyer 		if (!preen)
3768f7c2b37Sbouyer 			printf("\n***** REBOOT NOW *****\n");
3778f7c2b37Sbouyer 		sync();
378742b48d5Schristos 		return FSCK_EXIT_ROOT_CHANGED;
3798f7c2b37Sbouyer 	}
380742b48d5Schristos 	return FSCK_EXIT_OK;
3818f7c2b37Sbouyer }
3828f7c2b37Sbouyer 
3838f7c2b37Sbouyer static void
usage(void)384ccde05f0Sxtraeme usage(void)
3858f7c2b37Sbouyer {
3868a986b2eScgd 
3878f7c2b37Sbouyer 	(void) fprintf(stderr,
3887dd69b6aSsevan 	    "usage: %s [-dfnpUy] [-b block] [-m mode] filesystem ...\n",
3898a986b2eScgd 	    getprogname());
390742b48d5Schristos 	exit(FSCK_EXIT_USAGE);
3918f7c2b37Sbouyer }
392