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