main.c revision 7585
175374Sbp/*
275374Sbp * Copyright (c) 1980, 1986, 1993
375374Sbp *	The Regents of the University of California.  All rights reserved.
475374Sbp *
575374Sbp * Redistribution and use in source and binary forms, with or without
675374Sbp * modification, are permitted provided that the following conditions
775374Sbp * are met:
875374Sbp * 1. Redistributions of source code must retain the above copyright
975374Sbp *    notice, this list of conditions and the following disclaimer.
1075374Sbp * 2. Redistributions in binary form must reproduce the above copyright
1175374Sbp *    notice, this list of conditions and the following disclaimer in the
1275374Sbp *    documentation and/or other materials provided with the distribution.
1375374Sbp * 3. All advertising materials mentioning features or use of this software
1475374Sbp *    must display the following acknowledgement:
1575374Sbp *	This product includes software developed by the University of
1675374Sbp *	California, Berkeley and its contributors.
1775374Sbp * 4. Neither the name of the University nor the names of its contributors
1875374Sbp *    may be used to endorse or promote products derived from this software
1975374Sbp *    without specific prior written permission.
2075374Sbp *
2175374Sbp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2275374Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2375374Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2475374Sbp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2575374Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2675374Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2775374Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2875374Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2975374Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3075374Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3175374Sbp * SUCH DAMAGE.
3275374Sbp */
3375374Sbp
3475374Sbp#ifndef lint
3575374Sbpstatic const char copyright[] =
3675374Sbp"@(#) Copyright (c) 1980, 1986, 1993\n\
3775374Sbp	The Regents of the University of California.  All rights reserved.\n";
3875374Sbp#endif /* not lint */
3975374Sbp
4075374Sbp#ifndef lint
4175374Sbpstatic const char sccsid[] = "@(#)main.c	8.2 (Berkeley) 1/23/94";
4275374Sbp#endif /* not lint */
4375374Sbp
4475374Sbp#include <sys/param.h>
4575374Sbp#include <sys/time.h>
4675374Sbp#include <sys/proc.h>
4775374Sbp#include <sys/mount.h>
4875374Sbp#include <ufs/ufs/dinode.h>
4975374Sbp#include <ufs/ffs/fs.h>
5075374Sbp#include <fstab.h>
5175374Sbp#include <stdlib.h>
5275374Sbp#include <unistd.h>
5375374Sbp#include <string.h>
5475374Sbp#include <ctype.h>
5575374Sbp#include <stdio.h>
5675374Sbp#include "fsck.h"
5775374Sbpstatic int	argtoi __P((int flag, char *req, char *str, int base));
5875374Sbpstatic int	docheck __P((struct fstab *fsp));
5975374Sbpstatic int	checkfilesys __P((char *filesys, char *mntpt, long auxdata,
6075374Sbp				  int child));
6175374Sbp
6275374Sbpint
6375374Sbpmain(argc, argv)
6475374Sbp	int	argc;
6575374Sbp	char	*argv[];
6675374Sbp{
6775374Sbp	int ch;
6875374Sbp	int ret, maxrun = 0;
6975374Sbp	extern char *optarg;
7075374Sbp	extern int optind;
7175374Sbp
7275374Sbp	sync();
7375374Sbp	while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != EOF) {
7475374Sbp		switch (ch) {
7575374Sbp		case 'p':
7675374Sbp			preen++;
7775374Sbp			break;
7875374Sbp
7975374Sbp		case 'b':
8075374Sbp			bflag = argtoi('b', "number", optarg, 10);
8188741Sbp			printf("Alternate super block location: %d\n", bflag);
8288741Sbp			break;
8375374Sbp
8491022Sbp		case 'c':
8575374Sbp			cvtlevel = argtoi('c', "conversion level", optarg, 10);
8675374Sbp			break;
8775374Sbp
8875374Sbp		case 'd':
8975374Sbp			debug++;
9075374Sbp			break;
9175374Sbp
9275374Sbp		case 'f':
9375374Sbp			fflag++;
9475374Sbp			break;
9575374Sbp
9675374Sbp		case 'l':
9775374Sbp			maxrun = argtoi('l', "number", optarg, 10);
9875374Sbp			break;
9975374Sbp
10075374Sbp		case 'm':
10175374Sbp			lfmode = argtoi('m', "mode", optarg, 8);
10275374Sbp			if (lfmode &~ 07777)
10375374Sbp				errexit("bad mode to -m: %o\n", lfmode);
10475374Sbp			printf("** lost+found creation mode %o\n", lfmode);
10575374Sbp			break;
10675374Sbp
10775374Sbp		case 'n':
10875374Sbp		case 'N':
10975374Sbp			nflag++;
11075374Sbp			yflag = 0;
11175374Sbp			break;
11275374Sbp
11375374Sbp		case 'y':
11475374Sbp		case 'Y':
11575374Sbp			yflag++;
11675374Sbp			nflag = 0;
11775374Sbp			break;
11888741Sbp
11975374Sbp		default:
12075374Sbp			errexit("%c option?\n", ch);
12175374Sbp		}
12275374Sbp	}
12375374Sbp	argc -= optind;
12475374Sbp	argv += optind;
12575374Sbp	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
12675374Sbp		(void)signal(SIGINT, catch);
12775374Sbp	if (preen)
12875374Sbp		(void)signal(SIGQUIT, catchquit);
12975374Sbp	if (argc) {
13075374Sbp		while (argc-- > 0)
13175374Sbp			(void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
13275374Sbp		exit(0);
13375374Sbp	}
13475374Sbp	ret = checkfstab(preen, maxrun, docheck, checkfilesys);
13575374Sbp	if (returntosingle)
13675374Sbp		exit(2);
13775374Sbp	exit(ret);
13875374Sbp}
13975374Sbp
14075374Sbpint
14175374Sbpargtoi(flag, req, str, base)
14275374Sbp	int flag;
14375374Sbp	char *req, *str;
14475374Sbp	int base;
14575374Sbp{
14675374Sbp	char *cp;
14775374Sbp	int ret;
14875374Sbp
14975374Sbp	ret = (int)strtol(str, &cp, base);
15075374Sbp	if (cp == str || *cp)
15175374Sbp		errexit("-%c flag requires a %s\n", flag, req);
15275374Sbp	return (ret);
15375374Sbp}
15475374Sbp
15575374Sbp/*
15675374Sbp * Determine whether a filesystem should be checked.
15775374Sbp */
15875374Sbpint
15975374Sbpdocheck(fsp)
16075374Sbp	register struct fstab *fsp;
16175374Sbp{
16275374Sbp
16375374Sbp	if (strcmp(fsp->fs_vfstype, "ufs") ||
16475374Sbp	    (strcmp(fsp->fs_type, FSTAB_RW) &&
16575374Sbp	     strcmp(fsp->fs_type, FSTAB_RO)) ||
16675374Sbp	    fsp->fs_passno == 0)
167102479Sbde		return (0);
16875374Sbp	return (1);
16975374Sbp}
17075374Sbp
17175374Sbp/*
17275374Sbp * Check the specified filesystem.
17375374Sbp */
17475374Sbp/* ARGSUSED */
17575374Sbpint
17675374Sbpcheckfilesys(filesys, mntpt, auxdata, child)
17775374Sbp	char *filesys, *mntpt;
17875374Sbp	long auxdata;
17975374Sbp	int child;
18075374Sbp{
18175374Sbp	daddr_t n_ffree, n_bfree;
18275374Sbp	struct dups *dp;
18375374Sbp	struct zlncnt *zlnp;
18475374Sbp	int cylno;
18575374Sbp
18675374Sbp	if (preen && child)
18775374Sbp		(void)signal(SIGQUIT, voidquit);
18875374Sbp	cdevname = filesys;
18975374Sbp	if (debug && preen)
19075374Sbp		pwarn("starting\n");
19175374Sbp	if (setup(filesys) == 0) {
19275374Sbp		if (preen)
19375374Sbp			pfatal("CAN'T CHECK FILE SYSTEM.");
19475374Sbp		return (0);
19575374Sbp	}
19675374Sbp
19775374Sbp	if (preen && sblock.fs_clean && !fflag) {
19875374Sbp		pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree +
19975374Sbp			sblock.fs_frag * sblock.fs_cstotal.cs_nbfree);
20075374Sbp		printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
20175374Sbp			sblock.fs_cstotal.cs_nffree,
20275374Sbp			sblock.fs_cstotal.cs_nbfree,
20375374Sbp			(float)(sblock.fs_cstotal.cs_nffree * 100) /
20475374Sbp			sblock.fs_dsize);
20575374Sbp		return(0);
20675374Sbp	}
20775374Sbp
20875374Sbp	/*
20975374Sbp	 * 1: scan inodes tallying blocks used
21075374Sbp	 */
21175374Sbp	if (preen == 0) {
21275374Sbp		printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
21375374Sbp		if (hotroot)
21475374Sbp			printf("** Root file system\n");
21575374Sbp		printf("** Phase 1 - Check Blocks and Sizes\n");
21675374Sbp	}
21775374Sbp	pass1();
21875374Sbp
21975374Sbp	/*
22075374Sbp	 * 1b: locate first references to duplicates, if any
22175374Sbp	 */
22275374Sbp	if (duplist) {
22375374Sbp		if (preen)
22475374Sbp			pfatal("INTERNAL ERROR: dups with -p");
22575374Sbp		printf("** Phase 1b - Rescan For More DUPS\n");
22675374Sbp		pass1b();
22775374Sbp	}
22875374Sbp
22975374Sbp	/*
23075374Sbp	 * 2: traverse directories from root to mark all connected directories
23175374Sbp	 */
23275374Sbp	if (preen == 0)
23375374Sbp		printf("** Phase 2 - Check Pathnames\n");
23475374Sbp	pass2();
23575374Sbp
23675374Sbp	/*
23775374Sbp	 * 3: scan inodes looking for disconnected directories
23875374Sbp	 */
23975374Sbp	if (preen == 0)
24075374Sbp		printf("** Phase 3 - Check Connectivity\n");
24175374Sbp	pass3();
24275374Sbp
24375374Sbp	/*
24475374Sbp	 * 4: scan inodes looking for disconnected files; check reference counts
24575374Sbp	 */
24675374Sbp	if (preen == 0)
24775374Sbp		printf("** Phase 4 - Check Reference Counts\n");
24875374Sbp	pass4();
24975374Sbp
25075374Sbp	/*
25175374Sbp	 * 5: check and repair resource counts in cylinder groups
25275374Sbp	 */
25375374Sbp	if (preen == 0)
25475374Sbp		printf("** Phase 5 - Check Cyl groups\n");
25575374Sbp	pass5();
25675374Sbp
25775374Sbp	/*
25875374Sbp	 * print out summary statistics
25975374Sbp	 */
26075374Sbp	n_ffree = sblock.fs_cstotal.cs_nffree;
26175374Sbp	n_bfree = sblock.fs_cstotal.cs_nbfree;
26275374Sbp	pwarn("%ld files, %ld used, %ld free ",
26375374Sbp	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
26475374Sbp	printf("(%ld frags, %ld blocks, %ld.%ld%% fragmentation)\n",
26575374Sbp	    n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize,
26675374Sbp	    ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10);
26775374Sbp	if (debug &&
26875374Sbp	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
26975374Sbp		printf("%ld files missing\n", n_files);
27075374Sbp	if (debug) {
27175374Sbp		n_blks += sblock.fs_ncg *
27275374Sbp			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
27375374Sbp		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
27475374Sbp		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
27575374Sbp		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
27675374Sbp			printf("%ld blocks missing\n", n_blks);
27775374Sbp		if (duplist != NULL) {
27875374Sbp			printf("The following duplicate blocks remain:");
27975374Sbp			for (dp = duplist; dp; dp = dp->next)
28075374Sbp				printf(" %ld,", dp->dup);
28175374Sbp			printf("\n");
28275374Sbp		}
28375374Sbp		if (zlnhead != NULL) {
28475374Sbp			printf("The following zero link count inodes remain:");
28575374Sbp			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
28675374Sbp				printf(" %lu,", zlnp->zlncnt);
28775374Sbp			printf("\n");
28875374Sbp		}
28975374Sbp	}
29075374Sbp	zlnhead = (struct zlncnt *)0;
29175374Sbp	duplist = (struct dups *)0;
29275374Sbp	muldup = (struct dups *)0;
29375374Sbp	inocleanup();
29475374Sbp	if (fsmodified) {
29575374Sbp		(void)time(&sblock.fs_time);
29675374Sbp		sbdirty();
29775374Sbp	}
29875374Sbp	if (cvtlevel && sblk.b_dirty) {
29975374Sbp		/*
30075374Sbp		 * Write out the duplicate super blocks
30175374Sbp		 */
30275374Sbp		for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
30375374Sbp			bwrite(fswritefd, (char *)&sblock,
30475374Sbp			    fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
30575374Sbp	}
30675374Sbp	ckfini();
30775374Sbp	free(blockmap);
30875374Sbp	free(statemap);
30975374Sbp	free((char *)lncntp);
31075374Sbp	if (!fsmodified)
31175374Sbp		return (0);
31275374Sbp	if (!preen)
31375374Sbp		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
31475374Sbp	if (hotroot) {
31575374Sbp		struct statfs stfs_buf;
31675374Sbp		/*
31775374Sbp		 * We modified the root.  Do a mount update on
31875374Sbp		 * it, unless it is read-write, so we can continue.
31975374Sbp		 */
32075374Sbp		if (statfs("/", &stfs_buf) == 0) {
32175374Sbp			long flags = stfs_buf.f_flags;
32275374Sbp			struct ufs_args args;
32375374Sbp			int ret;
32475374Sbp
32575374Sbp			if (flags & MNT_RDONLY) {
32675374Sbp				args.fspec = 0;
32775374Sbp				args.export.ex_flags = 0;
32875374Sbp				args.export.ex_root = 0;
32975374Sbp				flags |= MNT_UPDATE | MNT_RELOAD;
33075374Sbp				ret = mount(MOUNT_UFS, "/", flags, &args);
33175374Sbp				if (ret == 0)
33275374Sbp					return(0);
33375374Sbp			}
33475374Sbp		}
33575374Sbp		if (!preen)
33675374Sbp			printf("\n***** REBOOT NOW *****\n");
33775374Sbp		sync();
33875374Sbp		return (4);
33975374Sbp	}
34075374Sbp	return (0);
34175374Sbp}
34275374Sbp