xref: /csrg-svn/sbin/fsck/pass1.c (revision 47580)
122048Sdist /*
239976Smckusick  * Copyright (c) 1980, 1986 The Regents of the University of California.
339976Smckusick  * All rights reserved.
439976Smckusick  *
542702Sbostic  * %sccs.include.redist.c%
622048Sdist  */
722048Sdist 
816262Smckusick #ifndef lint
9*47580Smckusick static char sccsid[] = "@(#)pass1.c	5.16 (Berkeley) 03/19/91";
1039976Smckusick #endif /* not lint */
1116262Smckusick 
1216262Smckusick #include <sys/param.h>
1339383Smckusick #include <ufs/dinode.h>
1438337Smckusick #include <ufs/fs.h>
1544934Smckusick #include <stdlib.h>
1644934Smckusick #include <string.h>
1716262Smckusick #include "fsck.h"
1816262Smckusick 
1917937Smckusick static daddr_t badblk;
2017937Smckusick static daddr_t dupblk;
2117937Smckusick int pass1check();
2240021Smckusick struct dinode *getnextinode();
2316262Smckusick 
2416262Smckusick pass1()
2516262Smckusick {
2617937Smckusick 	register int c, i, j;
2739973Smckusick 	register struct dinode *dp;
2821759Smckusick 	struct zlncnt *zlnp;
2939973Smckusick 	int ndb, cgd;
3016262Smckusick 	struct inodesc idesc;
3116262Smckusick 	ino_t inumber;
3216262Smckusick 
3317931Smckusick 	/*
3417931Smckusick 	 * Set file system reserved blocks in used block map.
3517931Smckusick 	 */
3617931Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
3717931Smckusick 		cgd = cgdmin(&sblock, c);
3817931Smckusick 		if (c == 0) {
3917931Smckusick 			i = cgbase(&sblock, c);
4017931Smckusick 			cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
4117931Smckusick 		} else
4217931Smckusick 			i = cgsblock(&sblock, c);
4317931Smckusick 		for (; i < cgd; i++)
4417931Smckusick 			setbmap(i);
4517931Smckusick 	}
4617931Smckusick 	/*
4717931Smckusick 	 * Find all allocated blocks.
4817931Smckusick 	 */
4916262Smckusick 	bzero((char *)&idesc, sizeof(struct inodesc));
5016262Smckusick 	idesc.id_type = ADDR;
5116262Smckusick 	idesc.id_func = pass1check;
5216262Smckusick 	inumber = 0;
5317937Smckusick 	n_files = n_blks = 0;
5440021Smckusick 	resetinodebuf();
5516262Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
5616262Smckusick 		for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
5717937Smckusick 			if (inumber < ROOTINO)
5816262Smckusick 				continue;
5940021Smckusick 			dp = getnextinode(inumber);
6039973Smckusick 			if ((dp->di_mode & IFMT) == 0) {
6117937Smckusick 				if (bcmp((char *)dp->di_db, (char *)zino.di_db,
6217937Smckusick 					NDADDR * sizeof(daddr_t)) ||
6317937Smckusick 				    bcmp((char *)dp->di_ib, (char *)zino.di_ib,
6417937Smckusick 					NIADDR * sizeof(daddr_t)) ||
6517937Smckusick 				    dp->di_mode || dp->di_size) {
6644934Smckusick 					pfatal("PARTIALLY ALLOCATED INODE I=%lu",
6716262Smckusick 						inumber);
6816262Smckusick 					if (reply("CLEAR") == 1) {
6940485Smckusick 						dp = ginode(inumber);
7039973Smckusick 						clearinode(dp);
7116262Smckusick 						inodirty();
7216262Smckusick 					}
7316262Smckusick 				}
7417937Smckusick 				statemap[inumber] = USTATE;
7517937Smckusick 				continue;
7616262Smckusick 			}
7717937Smckusick 			lastino = inumber;
7844934Smckusick 			if (/* dp->di_size < 0 || */
7944934Smckusick 			    dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
8017937Smckusick 				if (debug)
8144934Smckusick 					printf("bad size %lu:", dp->di_size);
8217937Smckusick 				goto unknown;
8317937Smckusick 			}
8428084Smckusick 			if (!preen && (dp->di_mode & IFMT) == IFMT &&
8528084Smckusick 			    reply("HOLD BAD BLOCK") == 1) {
8640485Smckusick 				dp = ginode(inumber);
8728084Smckusick 				dp->di_size = sblock.fs_fsize;
8828084Smckusick 				dp->di_mode = IFREG|0600;
8928084Smckusick 				inodirty();
9028084Smckusick 			}
9117937Smckusick 			ndb = howmany(dp->di_size, sblock.fs_bsize);
9236952Smckusick 			if (ndb < 0) {
9336952Smckusick 				if (debug)
9444934Smckusick 					printf("bad size %lu ndb %d:",
9536952Smckusick 						dp->di_size, ndb);
9636952Smckusick 				goto unknown;
9736952Smckusick 			}
9839973Smckusick 			if ((dp->di_mode & IFMT) == IFBLK ||
9939973Smckusick 			    (dp->di_mode & IFMT) == IFCHR)
10017937Smckusick 				ndb++;
10117937Smckusick 			for (j = ndb; j < NDADDR; j++)
10217937Smckusick 				if (dp->di_db[j] != 0) {
10317937Smckusick 					if (debug)
10444934Smckusick 						printf("bad direct addr: %ld\n",
10517937Smckusick 							dp->di_db[j]);
10617937Smckusick 					goto unknown;
10717937Smckusick 				}
10817937Smckusick 			for (j = 0, ndb -= NDADDR; ndb > 0; j++)
10917937Smckusick 				ndb /= NINDIR(&sblock);
11017937Smckusick 			for (; j < NIADDR; j++)
11117937Smckusick 				if (dp->di_ib[j] != 0) {
11217937Smckusick 					if (debug)
11344934Smckusick 						printf("bad indirect addr: %ld\n",
11417937Smckusick 							dp->di_ib[j]);
11517937Smckusick 					goto unknown;
11617937Smckusick 				}
11728084Smckusick 			if (ftypeok(dp) == 0)
11817937Smckusick 				goto unknown;
11917937Smckusick 			n_files++;
12017937Smckusick 			lncntp[inumber] = dp->di_nlink;
12117937Smckusick 			if (dp->di_nlink <= 0) {
12221759Smckusick 				zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
12321759Smckusick 				if (zlnp == NULL) {
12417937Smckusick 					pfatal("LINK COUNT TABLE OVERFLOW");
12517937Smckusick 					if (reply("CONTINUE") == 0)
12617937Smckusick 						errexit("");
12721759Smckusick 				} else {
12821759Smckusick 					zlnp->zlncnt = inumber;
12921759Smckusick 					zlnp->next = zlnhead;
13021759Smckusick 					zlnhead = zlnp;
13117937Smckusick 				}
13217937Smckusick 			}
13339980Smckusick 			if ((dp->di_mode & IFMT) == IFDIR) {
13441135Smckusick 				if (dp->di_size == 0)
13541135Smckusick 					statemap[inumber] = DCLEAR;
13641135Smckusick 				else
13741135Smckusick 					statemap[inumber] = DSTATE;
13839980Smckusick 				cacheino(dp, inumber);
13939980Smckusick 			} else
14039980Smckusick 				statemap[inumber] = FSTATE;
14139973Smckusick 			badblk = dupblk = 0;
14217937Smckusick 			idesc.id_number = inumber;
14317937Smckusick 			(void)ckinode(dp, &idesc);
14417990Smckusick 			idesc.id_entryno *= btodb(sblock.fs_fsize);
14517990Smckusick 			if (dp->di_blocks != idesc.id_entryno) {
14644934Smckusick 				pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
14717990Smckusick 				    inumber, dp->di_blocks, idesc.id_entryno);
14817937Smckusick 				if (preen)
14917937Smckusick 					printf(" (CORRECTED)\n");
15017937Smckusick 				else if (reply("CORRECT") == 0)
15117937Smckusick 					continue;
15240485Smckusick 				dp = ginode(inumber);
15317990Smckusick 				dp->di_blocks = idesc.id_entryno;
15417937Smckusick 				inodirty();
15517937Smckusick 			}
15617937Smckusick 			continue;
15717937Smckusick 	unknown:
15844934Smckusick 			pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
15926481Smckusick 			statemap[inumber] = FCLEAR;
16017937Smckusick 			if (reply("CLEAR") == 1) {
16126481Smckusick 				statemap[inumber] = USTATE;
16240485Smckusick 				dp = ginode(inumber);
16339973Smckusick 				clearinode(dp);
16417937Smckusick 				inodirty();
16517937Smckusick 			}
16616262Smckusick 		}
16716262Smckusick 	}
16840021Smckusick 	freeinodebuf();
16916262Smckusick }
17016262Smckusick 
17116262Smckusick pass1check(idesc)
17216262Smckusick 	register struct inodesc *idesc;
17316262Smckusick {
17416262Smckusick 	int res = KEEPON;
17516262Smckusick 	int anyout, nfrags;
17616262Smckusick 	daddr_t blkno = idesc->id_blkno;
17721744Smckusick 	register struct dups *dlp;
17821744Smckusick 	struct dups *new;
17916262Smckusick 
18039973Smckusick 	if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
18139973Smckusick 		blkerror(idesc->id_number, "BAD", blkno);
182*47580Smckusick 		if (badblk++ >= MAXBAD) {
18344934Smckusick 			pwarn("EXCESSIVE BAD BLKS I=%lu",
18417931Smckusick 				idesc->id_number);
18517931Smckusick 			if (preen)
18617931Smckusick 				printf(" (SKIPPING)\n");
18717931Smckusick 			else if (reply("CONTINUE") == 0)
18817931Smckusick 				errexit("");
18917931Smckusick 			return (STOP);
19017931Smckusick 		}
19117931Smckusick 	}
19216262Smckusick 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
19339973Smckusick 		if (anyout && chkrange(blkno, 1)) {
19416262Smckusick 			res = SKIP;
19539973Smckusick 		} else if (!testbmap(blkno)) {
19617931Smckusick 			n_blks++;
19717931Smckusick 			setbmap(blkno);
19817931Smckusick 		} else {
19939973Smckusick 			blkerror(idesc->id_number, "DUP", blkno);
200*47580Smckusick 			if (dupblk++ >= MAXDUP) {
20144934Smckusick 				pwarn("EXCESSIVE DUP BLKS I=%lu",
20216262Smckusick 					idesc->id_number);
20316262Smckusick 				if (preen)
20416262Smckusick 					printf(" (SKIPPING)\n");
20516262Smckusick 				else if (reply("CONTINUE") == 0)
20616262Smckusick 					errexit("");
20716262Smckusick 				return (STOP);
20816262Smckusick 			}
20921744Smckusick 			new = (struct dups *)malloc(sizeof(struct dups));
21021744Smckusick 			if (new == NULL) {
21116262Smckusick 				pfatal("DUP TABLE OVERFLOW.");
21216262Smckusick 				if (reply("CONTINUE") == 0)
21316262Smckusick 					errexit("");
21416262Smckusick 				return (STOP);
21516262Smckusick 			}
21621744Smckusick 			new->dup = blkno;
21721744Smckusick 			if (muldup == 0) {
21821744Smckusick 				duplist = muldup = new;
21921744Smckusick 				new->next = 0;
22021744Smckusick 			} else {
22121744Smckusick 				new->next = muldup->next;
22221744Smckusick 				muldup->next = new;
22321744Smckusick 			}
22421744Smckusick 			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
22521744Smckusick 				if (dlp->dup == blkno)
22616262Smckusick 					break;
22721744Smckusick 			if (dlp == muldup && dlp->dup != blkno)
22821744Smckusick 				muldup = new;
22916262Smckusick 		}
23017990Smckusick 		/*
23117990Smckusick 		 * count the number of blocks found in id_entryno
23217990Smckusick 		 */
23317990Smckusick 		idesc->id_entryno++;
23416262Smckusick 	}
23516262Smckusick 	return (res);
23616262Smckusick }
237