xref: /csrg-svn/sbin/fsck/pass1.c (revision 16262)
1*16262Smckusick #ifndef lint
2*16262Smckusick static char version[] = "@(#)pass1.c	3.1 (Berkeley) 03/31/84";
3*16262Smckusick #endif
4*16262Smckusick 
5*16262Smckusick #include <sys/param.h>
6*16262Smckusick #include <sys/inode.h>
7*16262Smckusick #include <sys/fs.h>
8*16262Smckusick #include "fsck.h"
9*16262Smckusick 
10*16262Smckusick int	pass1check();
11*16262Smckusick 
12*16262Smckusick pass1()
13*16262Smckusick {
14*16262Smckusick 	register int c, i, n, j;
15*16262Smckusick 	register DINODE *dp;
16*16262Smckusick 	int ndb, partial;
17*16262Smckusick 	struct inodesc idesc;
18*16262Smckusick 	ino_t inumber;
19*16262Smckusick 
20*16262Smckusick 	bzero((char *)&idesc, sizeof(struct inodesc));
21*16262Smckusick 	idesc.id_type = ADDR;
22*16262Smckusick 	idesc.id_func = pass1check;
23*16262Smckusick 	inumber = 0;
24*16262Smckusick 	n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
25*16262Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
26*16262Smckusick 		if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
27*16262Smckusick 			continue;
28*16262Smckusick 		if (cgrp.cg_magic != CG_MAGIC) {
29*16262Smckusick 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
30*16262Smckusick 			bzero((char *)&cgrp, (int)sblock.fs_cgsize);
31*16262Smckusick 		}
32*16262Smckusick 		n = 0;
33*16262Smckusick 		for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
34*16262Smckusick 			dp = ginode(inumber);
35*16262Smckusick 			if (dp == NULL)
36*16262Smckusick 				continue;
37*16262Smckusick 			n++;
38*16262Smckusick 			if (ALLOC) {
39*16262Smckusick 				if (!isset(cgrp.cg_iused, i)) {
40*16262Smckusick 					if (debug)
41*16262Smckusick 						printf("%d bad, not used\n",
42*16262Smckusick 						    inumber);
43*16262Smckusick 					inosumbad++;
44*16262Smckusick 				}
45*16262Smckusick 				n--;
46*16262Smckusick 				lastino = inumber;
47*16262Smckusick 				if (!preen && (dp->di_mode & IFMT) == IFMT &&
48*16262Smckusick 				    reply("HOLD BAD BLOCK") == 1) {
49*16262Smckusick 					dp->di_size = sblock.fs_fsize;
50*16262Smckusick 					dp->di_mode = IFREG|0600;
51*16262Smckusick 					inodirty();
52*16262Smckusick 				} else if (ftypeok(dp) == 0)
53*16262Smckusick 					goto unknown;
54*16262Smckusick 				if (dp->di_size < 0) {
55*16262Smckusick 					if (debug)
56*16262Smckusick 						printf("bad size %d:",
57*16262Smckusick 							dp->di_size);
58*16262Smckusick 					goto unknown;
59*16262Smckusick 				}
60*16262Smckusick 				ndb = howmany(dp->di_size, sblock.fs_bsize);
61*16262Smckusick 				if (SPECIAL)
62*16262Smckusick 					ndb++;
63*16262Smckusick 				for (j = ndb; j < NDADDR; j++)
64*16262Smckusick 					if (dp->di_db[j] != 0) {
65*16262Smckusick 						if (debug)
66*16262Smckusick 							printf("bad direct addr: %d\n",
67*16262Smckusick 								dp->di_db[j]);
68*16262Smckusick 						goto unknown;
69*16262Smckusick 					}
70*16262Smckusick 				for (j = 0, ndb -= NDADDR; ndb > 0; j++)
71*16262Smckusick 					ndb /= NINDIR(&sblock);
72*16262Smckusick 				for (; j < NIADDR; j++)
73*16262Smckusick 					if (dp->di_ib[j] != 0) {
74*16262Smckusick 						if (debug)
75*16262Smckusick 							printf("bad indirect addr: %d\n",
76*16262Smckusick 								dp->di_ib[j]);
77*16262Smckusick 						goto unknown;
78*16262Smckusick 					}
79*16262Smckusick 				n_files++;
80*16262Smckusick 				lncntp[inumber] = dp->di_nlink;
81*16262Smckusick 				if (dp->di_nlink <= 0) {
82*16262Smckusick 					if (badlnp < &badlncnt[MAXLNCNT])
83*16262Smckusick 						*badlnp++ = inumber;
84*16262Smckusick 					else {
85*16262Smckusick 						pfatal("LINK COUNT TABLE OVERFLOW");
86*16262Smckusick 						if (reply("CONTINUE") == 0)
87*16262Smckusick 							errexit("");
88*16262Smckusick 					}
89*16262Smckusick 				}
90*16262Smckusick 				statemap[inumber] = DIRCT ? DSTATE : FSTATE;
91*16262Smckusick 				badblk = dupblk = 0; maxblk = 0;
92*16262Smckusick 				idesc.id_number = inumber;
93*16262Smckusick 				idesc.id_filesize = 0;
94*16262Smckusick 				(void)ckinode(dp, &idesc);
95*16262Smckusick 				idesc.id_filesize *= btodb(sblock.fs_fsize);
96*16262Smckusick 				if (dp->di_blocks != idesc.id_filesize) {
97*16262Smckusick 					pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
98*16262Smckusick 					    inumber, dp->di_blocks,
99*16262Smckusick 					    idesc.id_filesize);
100*16262Smckusick 					if (preen)
101*16262Smckusick 						printf(" (CORRECTED)\n");
102*16262Smckusick 					else if (reply("CORRECT") == 0)
103*16262Smckusick 						continue;
104*16262Smckusick 					dp->di_blocks = idesc.id_filesize;
105*16262Smckusick 					inodirty();
106*16262Smckusick 				}
107*16262Smckusick 				continue;
108*16262Smckusick 		unknown:
109*16262Smckusick 				pfatal("UNKNOWN FILE TYPE I=%u", inumber);
110*16262Smckusick 				if (reply("CLEAR") == 1) {
111*16262Smckusick 					zapino(dp);
112*16262Smckusick 					inodirty();
113*16262Smckusick 					inosumbad++;
114*16262Smckusick 				}
115*16262Smckusick 			} else {
116*16262Smckusick 				if (isset(cgrp.cg_iused, i)) {
117*16262Smckusick 					if (debug)
118*16262Smckusick 						printf("%d bad, marked used\n",
119*16262Smckusick 						    inumber);
120*16262Smckusick 					inosumbad++;
121*16262Smckusick 					n--;
122*16262Smckusick 				}
123*16262Smckusick 				partial = 0;
124*16262Smckusick 				for (j = 0; j < NDADDR; j++)
125*16262Smckusick 					if (dp->di_db[j] != 0)
126*16262Smckusick 						partial++;
127*16262Smckusick 				for (j = 0; j < NIADDR; j++)
128*16262Smckusick 					if (dp->di_ib[j] != 0)
129*16262Smckusick 						partial++;
130*16262Smckusick 				if (partial || dp->di_mode != 0 ||
131*16262Smckusick 				    dp->di_size != 0) {
132*16262Smckusick 					pfatal("PARTIALLY ALLOCATED INODE I=%u",
133*16262Smckusick 						inumber);
134*16262Smckusick 					if (reply("CLEAR") == 1) {
135*16262Smckusick 						zapino(dp);
136*16262Smckusick 						inodirty();
137*16262Smckusick 						inosumbad++;
138*16262Smckusick 					}
139*16262Smckusick 				}
140*16262Smckusick 			}
141*16262Smckusick 		}
142*16262Smckusick 		if (n != cgrp.cg_cs.cs_nifree) {
143*16262Smckusick 			if (debug)
144*16262Smckusick 				printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
145*16262Smckusick 				    c, cgrp.cg_cs.cs_nifree, n);
146*16262Smckusick 			inosumbad++;
147*16262Smckusick 		}
148*16262Smckusick 		if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
149*16262Smckusick 		  || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
150*16262Smckusick 		  || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
151*16262Smckusick 		  || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
152*16262Smckusick 			sbsumbad++;
153*16262Smckusick 	}
154*16262Smckusick }
155*16262Smckusick 
156*16262Smckusick pass1check(idesc)
157*16262Smckusick 	register struct inodesc *idesc;
158*16262Smckusick {
159*16262Smckusick 	register daddr_t *dlp;
160*16262Smckusick 	int res = KEEPON;
161*16262Smckusick 	int anyout, nfrags;
162*16262Smckusick 	daddr_t blkno = idesc->id_blkno;
163*16262Smckusick 
164*16262Smckusick 	anyout = outrange(blkno, idesc->id_numfrags);
165*16262Smckusick 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
166*16262Smckusick 		if (anyout && outrange(blkno, 1)) {
167*16262Smckusick 			blkerr(idesc->id_number, "BAD", blkno);
168*16262Smckusick 			if (++badblk >= MAXBAD) {
169*16262Smckusick 				pwarn("EXCESSIVE BAD BLKS I=%u",
170*16262Smckusick 					idesc->id_number);
171*16262Smckusick 				if (preen)
172*16262Smckusick 					printf(" (SKIPPING)\n");
173*16262Smckusick 				else if (reply("CONTINUE") == 0)
174*16262Smckusick 					errexit("");
175*16262Smckusick 				return (STOP);
176*16262Smckusick 			}
177*16262Smckusick 			res = SKIP;
178*16262Smckusick 		} else if (getbmap(blkno)) {
179*16262Smckusick 			blkerr(idesc->id_number, "DUP", blkno);
180*16262Smckusick 			if (++dupblk >= MAXDUP) {
181*16262Smckusick 				pwarn("EXCESSIVE DUP BLKS I=%u",
182*16262Smckusick 					idesc->id_number);
183*16262Smckusick 				if (preen)
184*16262Smckusick 					printf(" (SKIPPING)\n");
185*16262Smckusick 				else if (reply("CONTINUE") == 0)
186*16262Smckusick 					errexit("");
187*16262Smckusick 				return (STOP);
188*16262Smckusick 			}
189*16262Smckusick 			if (enddup >= &duplist[DUPTBLSIZE]) {
190*16262Smckusick 				pfatal("DUP TABLE OVERFLOW.");
191*16262Smckusick 				if (reply("CONTINUE") == 0)
192*16262Smckusick 					errexit("");
193*16262Smckusick 				return (STOP);
194*16262Smckusick 			}
195*16262Smckusick 			for (dlp = duplist; dlp < muldup; dlp++)
196*16262Smckusick 				if (*dlp == blkno) {
197*16262Smckusick 					*enddup++ = blkno;
198*16262Smckusick 					break;
199*16262Smckusick 				}
200*16262Smckusick 			if (dlp >= muldup) {
201*16262Smckusick 				*enddup++ = *muldup;
202*16262Smckusick 				*muldup++ = blkno;
203*16262Smckusick 			}
204*16262Smckusick 		} else {
205*16262Smckusick 			n_blks++;
206*16262Smckusick 			setbmap(blkno);
207*16262Smckusick 		}
208*16262Smckusick 		idesc->id_filesize++;
209*16262Smckusick 	}
210*16262Smckusick 	return (res);
211*16262Smckusick }
212