xref: /csrg-svn/sbin/fsck/main.c (revision 51532)
122047Sdist /*
239976Smckusick  * Copyright (c) 1980, 1986 The Regents of the University of California.
339976Smckusick  * All rights reserved.
439976Smckusick  *
542701Sbostic  * %sccs.include.redist.c%
622047Sdist  */
722047Sdist 
812728Ssam #ifndef lint
922047Sdist char copyright[] =
1039976Smckusick "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
1122047Sdist  All rights reserved.\n";
1239976Smckusick #endif /* not lint */
134428Smckusic 
1422047Sdist #ifndef lint
15*51532Sbostic static char sccsid[] = "@(#)main.c	5.29 (Berkeley) 11/04/91";
1639976Smckusick #endif /* not lint */
1722047Sdist 
186489Smckusick #include <sys/param.h>
19*51532Sbostic #include <ufs/ufs/dinode.h>
20*51532Sbostic #include <ufs/ffs/fs.h>
2117930Smckusick #include <fstab.h>
2244933Smckusick #include <stdlib.h>
2342041Sbostic #include <string.h>
2436827Smckusick #include <ctype.h>
2541417Smckusick #include <stdio.h>
2616257Smckusick #include "fsck.h"
274236Smckusick 
2839165Sbostic void	catch(), catchquit(), voidquit();
2924679Skarels int	returntosingle;
3017930Smckusick 
3117930Smckusick main(argc, argv)
3217930Smckusick 	int	argc;
3317930Smckusick 	char	*argv[];
3417930Smckusick {
3544933Smckusick 	int ch;
3641099Smckusick 	int ret, maxrun = 0;
3741417Smckusick 	extern int docheck(), checkfilesys();
3841417Smckusick 	extern char *optarg;
3941417Smckusick 	extern int optind;
4017930Smckusick 
4117930Smckusick 	sync();
4241417Smckusick 	while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) {
4341417Smckusick 		switch (ch) {
4417930Smckusick 		case 'p':
4517930Smckusick 			preen++;
4617930Smckusick 			break;
4717930Smckusick 
4817930Smckusick 		case 'b':
4944933Smckusick 			bflag = argtoi('b', "number", optarg, 10);
5017930Smckusick 			printf("Alternate super block location: %d\n", bflag);
5117930Smckusick 			break;
5217930Smckusick 
5334139Smckusick 		case 'c':
5434139Smckusick 			cvtflag++;
5534139Smckusick 			break;
5634139Smckusick 
5717930Smckusick 		case 'd':
5817930Smckusick 			debug++;
5917930Smckusick 			break;
6017930Smckusick 
6137216Skarels 		case 'l':
6244933Smckusick 			maxrun = argtoi('l', "number", optarg, 10);
6337216Skarels 			break;
6437216Skarels 
6536827Smckusick 		case 'm':
6644933Smckusick 			lfmode = argtoi('m', "mode", optarg, 8);
6736827Smckusick 			if (lfmode &~ 07777)
6836827Smckusick 				errexit("bad mode to -m: %o\n", lfmode);
6936827Smckusick 			printf("** lost+found creation mode %o\n", lfmode);
7036827Smckusick 			break;
7136827Smckusick 
7239972Smckusick 		case 'n':
7317930Smckusick 		case 'N':
7417930Smckusick 			nflag++;
7517930Smckusick 			yflag = 0;
7617930Smckusick 			break;
7717930Smckusick 
7839972Smckusick 		case 'y':
7917930Smckusick 		case 'Y':
8017930Smckusick 			yflag++;
8117930Smckusick 			nflag = 0;
8217930Smckusick 			break;
8317930Smckusick 
8417930Smckusick 		default:
8541417Smckusick 			errexit("%c option?\n", ch);
8617930Smckusick 		}
8717930Smckusick 	}
8841417Smckusick 	argc -= optind;
8941417Smckusick 	argv += optind;
9017930Smckusick 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
9117930Smckusick 		(void)signal(SIGINT, catch);
9224679Skarels 	if (preen)
9324679Skarels 		(void)signal(SIGQUIT, catchquit);
9417930Smckusick 	if (argc) {
9541417Smckusick 		while (argc-- > 0)
9645027Skarels 			(void)checkfilesys(*argv++, (char *)0, 0L, 0);
9717930Smckusick 		exit(0);
9817930Smckusick 	}
9941099Smckusick 	ret = checkfstab(preen, maxrun, docheck, checkfilesys);
10024679Skarels 	if (returntosingle)
10124679Skarels 		exit(2);
10241099Smckusick 	exit(ret);
10317930Smckusick }
10417930Smckusick 
10544933Smckusick argtoi(flag, req, str, base)
10644933Smckusick 	int flag;
10744933Smckusick 	char *req, *str;
10844933Smckusick 	int base;
10944933Smckusick {
11044933Smckusick 	char *cp;
11144933Smckusick 	int ret;
11244933Smckusick 
11344933Smckusick 	ret = (int)strtol(str, &cp, base);
11444933Smckusick 	if (cp == str || *cp)
11544933Smckusick 		errexit("-%c flag requires a %s\n", flag, req);
11644933Smckusick 	return (ret);
11744933Smckusick }
11844933Smckusick 
11941099Smckusick /*
12041099Smckusick  * Determine whether a filesystem should be checked.
12141099Smckusick  */
12241099Smckusick docheck(fsp)
12341099Smckusick 	register struct fstab *fsp;
12437216Skarels {
12537216Skarels 
12641099Smckusick 	if (strcmp(fsp->fs_vfstype, "ufs") ||
12741099Smckusick 	    (strcmp(fsp->fs_type, FSTAB_RW) &&
12841099Smckusick 	     strcmp(fsp->fs_type, FSTAB_RO)) ||
12941099Smckusick 	    fsp->fs_passno == 0)
13041099Smckusick 		return (0);
13141099Smckusick 	return (1);
13237216Skarels }
13337216Skarels 
13441099Smckusick /*
13541099Smckusick  * Check the specified filesystem.
13641099Smckusick  */
13741099Smckusick /* ARGSUSED */
13845027Skarels checkfilesys(filesys, mntpt, auxdata, child)
13941099Smckusick 	char *filesys, *mntpt;
14041099Smckusick 	long auxdata;
14137216Skarels {
14217936Smckusick 	daddr_t n_ffree, n_bfree;
14321760Smckusick 	struct dups *dp;
14426479Smckusick 	struct zlncnt *zlnp;
1454236Smckusick 
14645027Skarels 	if (preen && child)
14745027Skarels 		(void)signal(SIGQUIT, voidquit);
1489255Smckusick 	devname = filesys;
14937216Skarels 	if (debug && preen)
15037216Skarels 		pwarn("starting\n");
1519255Smckusick 	if (setup(filesys) == 0) {
1524236Smckusick 		if (preen)
1539255Smckusick 			pfatal("CAN'T CHECK FILE SYSTEM.");
15441099Smckusick 		return (0);
1554236Smckusick 	}
15617936Smckusick 	/*
15717936Smckusick 	 * 1: scan inodes tallying blocks used
15817936Smckusick 	 */
1596837Smckusick 	if (preen == 0) {
1606837Smckusick 		printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
1614236Smckusick 		if (hotroot)
1624236Smckusick 			printf("** Root file system\n");
1634236Smckusick 		printf("** Phase 1 - Check Blocks and Sizes\n");
1644236Smckusick 	}
1659255Smckusick 	pass1();
1669255Smckusick 
16717936Smckusick 	/*
16817936Smckusick 	 * 1b: locate first references to duplicates, if any
16917936Smckusick 	 */
17021743Smckusick 	if (duplist) {
1719255Smckusick 		if (preen)
1729255Smckusick 			pfatal("INTERNAL ERROR: dups with -p");
1739255Smckusick 		printf("** Phase 1b - Rescan For More DUPS\n");
1749255Smckusick 		pass1b();
1759255Smckusick 	}
1769255Smckusick 
17717936Smckusick 	/*
17817936Smckusick 	 * 2: traverse directories from root to mark all connected directories
17917936Smckusick 	 */
1809255Smckusick 	if (preen == 0)
1819255Smckusick 		printf("** Phase 2 - Check Pathnames\n");
1829255Smckusick 	pass2();
1839255Smckusick 
18417936Smckusick 	/*
18517936Smckusick 	 * 3: scan inodes looking for disconnected directories
18617936Smckusick 	 */
1879255Smckusick 	if (preen == 0)
1889255Smckusick 		printf("** Phase 3 - Check Connectivity\n");
1899255Smckusick 	pass3();
1909255Smckusick 
19117936Smckusick 	/*
19217936Smckusick 	 * 4: scan inodes looking for disconnected files; check reference counts
19317936Smckusick 	 */
1949255Smckusick 	if (preen == 0)
1959255Smckusick 		printf("** Phase 4 - Check Reference Counts\n");
1969255Smckusick 	pass4();
1979255Smckusick 
19817936Smckusick 	/*
19917936Smckusick 	 * 5: check and repair resource counts in cylinder groups
20017936Smckusick 	 */
2019255Smckusick 	if (preen == 0)
2029255Smckusick 		printf("** Phase 5 - Check Cyl groups\n");
2039255Smckusick 	pass5();
2049255Smckusick 
20517936Smckusick 	/*
20617936Smckusick 	 * print out summary statistics
20717936Smckusick 	 */
20817936Smckusick 	n_ffree = sblock.fs_cstotal.cs_nffree;
20917936Smckusick 	n_bfree = sblock.fs_cstotal.cs_nbfree;
21044933Smckusick 	pwarn("%ld files, %ld used, %ld free ",
21125288Smckusick 	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
21244933Smckusick 	printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
21325288Smckusick 	    n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
21439972Smckusick 	if (debug &&
21539972Smckusick 	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
21644933Smckusick 		printf("%ld files missing\n", n_files);
21717936Smckusick 	if (debug) {
21817936Smckusick 		n_blks += sblock.fs_ncg *
21917936Smckusick 			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
22017936Smckusick 		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
22117936Smckusick 		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
22239972Smckusick 		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
22344933Smckusick 			printf("%ld blocks missing\n", n_blks);
22421760Smckusick 		if (duplist != NULL) {
22521760Smckusick 			printf("The following duplicate blocks remain:");
22621760Smckusick 			for (dp = duplist; dp; dp = dp->next)
22744933Smckusick 				printf(" %ld,", dp->dup);
22821760Smckusick 			printf("\n");
22921760Smckusick 		}
23026479Smckusick 		if (zlnhead != NULL) {
23126479Smckusick 			printf("The following zero link count inodes remain:");
23226479Smckusick 			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
23344933Smckusick 				printf(" %lu,", zlnp->zlncnt);
23426479Smckusick 			printf("\n");
23526479Smckusick 		}
2369255Smckusick 	}
23726479Smckusick 	zlnhead = (struct zlncnt *)0;
23826479Smckusick 	duplist = (struct dups *)0;
23951354Smckusick 	muldup = (struct dups *)0;
24039980Smckusick 	inocleanup();
24139972Smckusick 	if (fsmodified) {
24214952Smckusick 		(void)time(&sblock.fs_time);
2439255Smckusick 		sbdirty();
2449255Smckusick 	}
2459255Smckusick 	ckfini();
2469255Smckusick 	free(blockmap);
2479255Smckusick 	free(statemap);
24814952Smckusick 	free((char *)lncntp);
24939972Smckusick 	if (!fsmodified)
25041099Smckusick 		return (0);
25113729Sroot 	if (!preen) {
25213729Sroot 		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
25313729Sroot 		if (hotroot)
25413729Sroot 			printf("\n***** REBOOT UNIX *****\n");
2559255Smckusick 	}
25613729Sroot 	if (hotroot) {
25713729Sroot 		sync();
25841099Smckusick 		return (4);
25913729Sroot 	}
26017930Smckusick 	return (0);
26117930Smckusick }
262