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