xref: /csrg-svn/sbin/fsck/pass1.c (revision 26481)
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.2 (Berkeley) 03/05/86";
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 			statemap[inumber] = FCLEAR;
136 			if (reply("CLEAR") == 1) {
137 				statemap[inumber] = USTATE;
138 				zapino(dp);
139 				inodirty();
140 			}
141 		}
142 	}
143 }
144 
145 pass1check(idesc)
146 	register struct inodesc *idesc;
147 {
148 	int res = KEEPON;
149 	int anyout, nfrags;
150 	daddr_t blkno = idesc->id_blkno;
151 	register struct dups *dlp;
152 	struct dups *new;
153 
154 	if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) {
155 		blkerr(idesc->id_number, "BAD", blkno);
156 		if (++badblk >= MAXBAD) {
157 			pwarn("EXCESSIVE BAD BLKS I=%u",
158 				idesc->id_number);
159 			if (preen)
160 				printf(" (SKIPPING)\n");
161 			else if (reply("CONTINUE") == 0)
162 				errexit("");
163 			return (STOP);
164 		}
165 	}
166 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
167 		if (anyout && outrange(blkno, 1)) {
168 			res = SKIP;
169 		} else if (!getbmap(blkno)) {
170 			n_blks++;
171 			setbmap(blkno);
172 		} else {
173 			blkerr(idesc->id_number, "DUP", blkno);
174 			if (++dupblk >= MAXDUP) {
175 				pwarn("EXCESSIVE DUP BLKS I=%u",
176 					idesc->id_number);
177 				if (preen)
178 					printf(" (SKIPPING)\n");
179 				else if (reply("CONTINUE") == 0)
180 					errexit("");
181 				return (STOP);
182 			}
183 			new = (struct dups *)malloc(sizeof(struct dups));
184 			if (new == NULL) {
185 				pfatal("DUP TABLE OVERFLOW.");
186 				if (reply("CONTINUE") == 0)
187 					errexit("");
188 				return (STOP);
189 			}
190 			new->dup = blkno;
191 			if (muldup == 0) {
192 				duplist = muldup = new;
193 				new->next = 0;
194 			} else {
195 				new->next = muldup->next;
196 				muldup->next = new;
197 			}
198 			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
199 				if (dlp->dup == blkno)
200 					break;
201 			if (dlp == muldup && dlp->dup != blkno)
202 				muldup = new;
203 		}
204 		/*
205 		 * count the number of blocks found in id_entryno
206 		 */
207 		idesc->id_entryno++;
208 	}
209 	return (res);
210 }
211