xref: /original-bsd/sbin/fsck/pass1.c (revision 444dc9d9)
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.5 (Berkeley) 03/02/89";
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 			    dp->di_size + sblock.fs_bsize - 1 < 0) {
74 				if (debug)
75 					printf("bad size %d:", dp->di_size);
76 				goto unknown;
77 			}
78 			if (!preen && (dp->di_mode & IFMT) == IFMT &&
79 			    reply("HOLD BAD BLOCK") == 1) {
80 				dp->di_size = sblock.fs_fsize;
81 				dp->di_mode = IFREG|0600;
82 				inodirty();
83 			}
84 			ndb = howmany(dp->di_size, sblock.fs_bsize);
85 			if (ndb < 0) {
86 				if (debug)
87 					printf("bad size %d ndb %d:",
88 						dp->di_size, ndb);
89 				goto unknown;
90 			}
91 			if (SPECIAL(dp))
92 				ndb++;
93 			for (j = ndb; j < NDADDR; j++)
94 				if (dp->di_db[j] != 0) {
95 					if (debug)
96 						printf("bad direct addr: %d\n",
97 							dp->di_db[j]);
98 					goto unknown;
99 				}
100 			for (j = 0, ndb -= NDADDR; ndb > 0; j++)
101 				ndb /= NINDIR(&sblock);
102 			for (; j < NIADDR; j++)
103 				if (dp->di_ib[j] != 0) {
104 					if (debug)
105 						printf("bad indirect addr: %d\n",
106 							dp->di_ib[j]);
107 					goto unknown;
108 				}
109 			if (ftypeok(dp) == 0)
110 				goto unknown;
111 			n_files++;
112 			lncntp[inumber] = dp->di_nlink;
113 			if (dp->di_nlink <= 0) {
114 				zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
115 				if (zlnp == NULL) {
116 					pfatal("LINK COUNT TABLE OVERFLOW");
117 					if (reply("CONTINUE") == 0)
118 						errexit("");
119 				} else {
120 					zlnp->zlncnt = inumber;
121 					zlnp->next = zlnhead;
122 					zlnhead = zlnp;
123 				}
124 			}
125 			statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE;
126 			badblk = dupblk = 0; maxblk = 0;
127 			idesc.id_number = inumber;
128 			(void)ckinode(dp, &idesc);
129 			idesc.id_entryno *= btodb(sblock.fs_fsize);
130 			if (dp->di_blocks != idesc.id_entryno) {
131 				pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
132 				    inumber, dp->di_blocks, idesc.id_entryno);
133 				if (preen)
134 					printf(" (CORRECTED)\n");
135 				else if (reply("CORRECT") == 0)
136 					continue;
137 				dp->di_blocks = idesc.id_entryno;
138 				inodirty();
139 			}
140 			continue;
141 	unknown:
142 			pfatal("UNKNOWN FILE TYPE I=%u", inumber);
143 			statemap[inumber] = FCLEAR;
144 			if (reply("CLEAR") == 1) {
145 				statemap[inumber] = USTATE;
146 				zapino(dp);
147 				inodirty();
148 			}
149 		}
150 	}
151 }
152 
153 pass1check(idesc)
154 	register struct inodesc *idesc;
155 {
156 	int res = KEEPON;
157 	int anyout, nfrags;
158 	daddr_t blkno = idesc->id_blkno;
159 	register struct dups *dlp;
160 	struct dups *new;
161 
162 	if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) {
163 		blkerr(idesc->id_number, "BAD", blkno);
164 		if (++badblk >= MAXBAD) {
165 			pwarn("EXCESSIVE BAD BLKS I=%u",
166 				idesc->id_number);
167 			if (preen)
168 				printf(" (SKIPPING)\n");
169 			else if (reply("CONTINUE") == 0)
170 				errexit("");
171 			return (STOP);
172 		}
173 	}
174 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
175 		if (anyout && outrange(blkno, 1)) {
176 			res = SKIP;
177 		} else if (!getbmap(blkno)) {
178 			n_blks++;
179 			setbmap(blkno);
180 		} else {
181 			blkerr(idesc->id_number, "DUP", blkno);
182 			if (++dupblk >= MAXDUP) {
183 				pwarn("EXCESSIVE DUP BLKS I=%u",
184 					idesc->id_number);
185 				if (preen)
186 					printf(" (SKIPPING)\n");
187 				else if (reply("CONTINUE") == 0)
188 					errexit("");
189 				return (STOP);
190 			}
191 			new = (struct dups *)malloc(sizeof(struct dups));
192 			if (new == NULL) {
193 				pfatal("DUP TABLE OVERFLOW.");
194 				if (reply("CONTINUE") == 0)
195 					errexit("");
196 				return (STOP);
197 			}
198 			new->dup = blkno;
199 			if (muldup == 0) {
200 				duplist = muldup = new;
201 				new->next = 0;
202 			} else {
203 				new->next = muldup->next;
204 				muldup->next = new;
205 			}
206 			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
207 				if (dlp->dup == blkno)
208 					break;
209 			if (dlp == muldup && dlp->dup != blkno)
210 				muldup = new;
211 		}
212 		/*
213 		 * count the number of blocks found in id_entryno
214 		 */
215 		idesc->id_entryno++;
216 	}
217 	return (res);
218 }
219