Commit | Line | Data |
---|---|---|
76797561 | 1 | /* |
21e5ab9a KB |
2 | * Copyright (c) 1980, 1986, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
fe32782c | 4 | * |
ad787160 C |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
76797561 DF |
32 | */ |
33 | ||
19052d90 | 34 | #ifndef lint |
ad787160 | 35 | static char sccsid[] = "@(#)pass1.c 8.1 (Berkeley) 6/5/93"; |
fe32782c | 36 | #endif /* not lint */ |
19052d90 KM |
37 | |
38 | #include <sys/param.h> | |
44357263 | 39 | #include <sys/time.h> |
558b3a30 | 40 | #include <ufs/ufs/dinode.h> |
bab4bc3e | 41 | #include <ufs/ufs/dir.h> |
558b3a30 | 42 | #include <ufs/ffs/fs.h> |
d72e970b KM |
43 | #include <stdlib.h> |
44 | #include <string.h> | |
19052d90 KM |
45 | #include "fsck.h" |
46 | ||
993a756c KM |
47 | static daddr_t badblk; |
48 | static daddr_t dupblk; | |
49 | int pass1check(); | |
a0cb24a2 | 50 | struct dinode *getnextinode(); |
19052d90 KM |
51 | |
52 | pass1() | |
53 | { | |
19052d90 | 54 | ino_t inumber; |
bab4bc3e KM |
55 | int c, i, cgd; |
56 | struct inodesc idesc; | |
19052d90 | 57 | |
7718c0e6 KM |
58 | /* |
59 | * Set file system reserved blocks in used block map. | |
60 | */ | |
61 | for (c = 0; c < sblock.fs_ncg; c++) { | |
62 | cgd = cgdmin(&sblock, c); | |
63 | if (c == 0) { | |
64 | i = cgbase(&sblock, c); | |
65 | cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); | |
66 | } else | |
67 | i = cgsblock(&sblock, c); | |
68 | for (; i < cgd; i++) | |
69 | setbmap(i); | |
70 | } | |
71 | /* | |
72 | * Find all allocated blocks. | |
73 | */ | |
19052d90 KM |
74 | bzero((char *)&idesc, sizeof(struct inodesc)); |
75 | idesc.id_type = ADDR; | |
76 | idesc.id_func = pass1check; | |
77 | inumber = 0; | |
993a756c | 78 | n_files = n_blks = 0; |
a0cb24a2 | 79 | resetinodebuf(); |
19052d90 | 80 | for (c = 0; c < sblock.fs_ncg; c++) { |
19052d90 | 81 | for (i = 0; i < sblock.fs_ipg; i++, inumber++) { |
993a756c | 82 | if (inumber < ROOTINO) |
19052d90 | 83 | continue; |
bab4bc3e KM |
84 | checkinode(inumber, &idesc); |
85 | } | |
86 | } | |
87 | freeinodebuf(); | |
88 | } | |
89 | ||
90 | checkinode(inumber, idesc) | |
91 | ino_t inumber; | |
92 | register struct inodesc *idesc; | |
93 | { | |
94 | register struct dinode *dp; | |
95 | struct zlncnt *zlnp; | |
96 | int ndb, j; | |
97 | mode_t mode; | |
98 | char symbuf[MAXSYMLINKLEN]; | |
99 | ||
100 | dp = getnextinode(inumber); | |
101 | mode = dp->di_mode & IFMT; | |
102 | if (mode == 0) { | |
103 | if (bcmp((char *)dp->di_db, (char *)zino.di_db, | |
104 | NDADDR * sizeof(daddr_t)) || | |
105 | bcmp((char *)dp->di_ib, (char *)zino.di_ib, | |
106 | NIADDR * sizeof(daddr_t)) || | |
107 | dp->di_mode || dp->di_size) { | |
108 | pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); | |
993a756c | 109 | if (reply("CLEAR") == 1) { |
0b4b70a9 | 110 | dp = ginode(inumber); |
569ec282 | 111 | clearinode(dp); |
993a756c | 112 | inodirty(); |
19052d90 KM |
113 | } |
114 | } | |
bab4bc3e KM |
115 | statemap[inumber] = USTATE; |
116 | return; | |
117 | } | |
118 | lastino = inumber; | |
119 | if (/* dp->di_size < 0 || */ | |
120 | dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { | |
121 | if (debug) | |
122 | printf("bad size %qu:", dp->di_size); | |
123 | goto unknown; | |
124 | } | |
125 | if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { | |
126 | dp = ginode(inumber); | |
127 | dp->di_size = sblock.fs_fsize; | |
128 | dp->di_mode = IFREG|0600; | |
129 | inodirty(); | |
130 | } | |
131 | ndb = howmany(dp->di_size, sblock.fs_bsize); | |
132 | if (ndb < 0) { | |
133 | if (debug) | |
134 | printf("bad size %qu ndb %d:", | |
135 | dp->di_size, ndb); | |
136 | goto unknown; | |
137 | } | |
138 | if (mode == IFBLK || mode == IFCHR) | |
139 | ndb++; | |
140 | if (mode == IFLNK) { | |
a0cb9f5b KM |
141 | if (doinglevel2 && |
142 | dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && | |
143 | dp->di_blocks != 0) { | |
bab4bc3e KM |
144 | if (bread(fsreadfd, symbuf, |
145 | fsbtodb(&sblock, dp->di_db[0]), | |
146 | (long)dp->di_size) != 0) | |
147 | errexit("cannot read symlink"); | |
a0cb9f5b KM |
148 | if (debug) { |
149 | symbuf[dp->di_size] = 0; | |
150 | printf("convert symlink %d(%s) of size %d\n", | |
151 | inumber, symbuf, (long)dp->di_size); | |
152 | } | |
bab4bc3e KM |
153 | dp = ginode(inumber); |
154 | bcopy(symbuf, (caddr_t)dp->di_shortlink, | |
155 | (long)dp->di_size); | |
156 | dp->di_blocks = 0; | |
157 | inodirty(); | |
158 | } | |
a0cb9f5b KM |
159 | /* |
160 | * Fake ndb value so direct/indirect block checks below | |
161 | * will detect any garbage after symlink string. | |
162 | */ | |
163 | if (dp->di_size < sblock.fs_maxsymlinklen) { | |
bab4bc3e | 164 | ndb = howmany(dp->di_size, sizeof(daddr_t)); |
a0cb9f5b KM |
165 | if (ndb > NDADDR) { |
166 | j = ndb - NDADDR; | |
167 | for (ndb = 1; j > 1; j--) | |
168 | ndb *= NINDIR(&sblock); | |
169 | ndb += NDADDR; | |
170 | } | |
171 | } | |
bab4bc3e KM |
172 | } |
173 | for (j = ndb; j < NDADDR; j++) | |
174 | if (dp->di_db[j] != 0) { | |
175 | if (debug) | |
176 | printf("bad direct addr: %ld\n", dp->di_db[j]); | |
177 | goto unknown; | |
178 | } | |
179 | for (j = 0, ndb -= NDADDR; ndb > 0; j++) | |
180 | ndb /= NINDIR(&sblock); | |
181 | for (; j < NIADDR; j++) | |
182 | if (dp->di_ib[j] != 0) { | |
183 | if (debug) | |
184 | printf("bad indirect addr: %ld\n", | |
185 | dp->di_ib[j]); | |
186 | goto unknown; | |
187 | } | |
188 | if (ftypeok(dp) == 0) | |
189 | goto unknown; | |
190 | n_files++; | |
191 | lncntp[inumber] = dp->di_nlink; | |
192 | if (dp->di_nlink <= 0) { | |
193 | zlnp = (struct zlncnt *)malloc(sizeof *zlnp); | |
194 | if (zlnp == NULL) { | |
195 | pfatal("LINK COUNT TABLE OVERFLOW"); | |
196 | if (reply("CONTINUE") == 0) | |
197 | errexit(""); | |
198 | } else { | |
199 | zlnp->zlncnt = inumber; | |
200 | zlnp->next = zlnhead; | |
201 | zlnhead = zlnp; | |
202 | } | |
203 | } | |
204 | if (mode == IFDIR) { | |
205 | if (dp->di_size == 0) | |
206 | statemap[inumber] = DCLEAR; | |
207 | else | |
208 | statemap[inumber] = DSTATE; | |
209 | cacheino(dp, inumber); | |
210 | } else | |
211 | statemap[inumber] = FSTATE; | |
212 | typemap[inumber] = IFTODT(mode); | |
be6e94c6 KM |
213 | if (doinglevel2 && |
214 | (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { | |
bab4bc3e KM |
215 | dp = ginode(inumber); |
216 | dp->di_uid = dp->di_ouid; | |
217 | dp->di_ouid = -1; | |
218 | dp->di_gid = dp->di_ogid; | |
219 | dp->di_ogid = -1; | |
220 | inodirty(); | |
221 | } | |
222 | badblk = dupblk = 0; | |
223 | idesc->id_number = inumber; | |
224 | (void)ckinode(dp, idesc); | |
225 | idesc->id_entryno *= btodb(sblock.fs_fsize); | |
226 | if (dp->di_blocks != idesc->id_entryno) { | |
227 | pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", | |
228 | inumber, dp->di_blocks, idesc->id_entryno); | |
229 | if (preen) | |
230 | printf(" (CORRECTED)\n"); | |
231 | else if (reply("CORRECT") == 0) | |
232 | return; | |
233 | dp = ginode(inumber); | |
234 | dp->di_blocks = idesc->id_entryno; | |
235 | inodirty(); | |
236 | } | |
237 | return; | |
238 | unknown: | |
239 | pfatal("UNKNOWN FILE TYPE I=%lu", inumber); | |
240 | statemap[inumber] = FCLEAR; | |
241 | if (reply("CLEAR") == 1) { | |
242 | statemap[inumber] = USTATE; | |
243 | dp = ginode(inumber); | |
244 | clearinode(dp); | |
245 | inodirty(); | |
19052d90 KM |
246 | } |
247 | } | |
248 | ||
249 | pass1check(idesc) | |
250 | register struct inodesc *idesc; | |
251 | { | |
19052d90 KM |
252 | int res = KEEPON; |
253 | int anyout, nfrags; | |
254 | daddr_t blkno = idesc->id_blkno; | |
62e6c152 KM |
255 | register struct dups *dlp; |
256 | struct dups *new; | |
19052d90 | 257 | |
569ec282 KM |
258 | if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { |
259 | blkerror(idesc->id_number, "BAD", blkno); | |
3752dfc6 | 260 | if (badblk++ >= MAXBAD) { |
d72e970b | 261 | pwarn("EXCESSIVE BAD BLKS I=%lu", |
7718c0e6 KM |
262 | idesc->id_number); |
263 | if (preen) | |
264 | printf(" (SKIPPING)\n"); | |
265 | else if (reply("CONTINUE") == 0) | |
266 | errexit(""); | |
267 | return (STOP); | |
268 | } | |
269 | } | |
19052d90 | 270 | for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { |
569ec282 | 271 | if (anyout && chkrange(blkno, 1)) { |
19052d90 | 272 | res = SKIP; |
569ec282 | 273 | } else if (!testbmap(blkno)) { |
7718c0e6 KM |
274 | n_blks++; |
275 | setbmap(blkno); | |
276 | } else { | |
569ec282 | 277 | blkerror(idesc->id_number, "DUP", blkno); |
3752dfc6 | 278 | if (dupblk++ >= MAXDUP) { |
d72e970b | 279 | pwarn("EXCESSIVE DUP BLKS I=%lu", |
19052d90 KM |
280 | idesc->id_number); |
281 | if (preen) | |
282 | printf(" (SKIPPING)\n"); | |
283 | else if (reply("CONTINUE") == 0) | |
284 | errexit(""); | |
285 | return (STOP); | |
286 | } | |
62e6c152 KM |
287 | new = (struct dups *)malloc(sizeof(struct dups)); |
288 | if (new == NULL) { | |
19052d90 KM |
289 | pfatal("DUP TABLE OVERFLOW."); |
290 | if (reply("CONTINUE") == 0) | |
291 | errexit(""); | |
292 | return (STOP); | |
293 | } | |
62e6c152 KM |
294 | new->dup = blkno; |
295 | if (muldup == 0) { | |
296 | duplist = muldup = new; | |
297 | new->next = 0; | |
298 | } else { | |
299 | new->next = muldup->next; | |
300 | muldup->next = new; | |
19052d90 | 301 | } |
62e6c152 KM |
302 | for (dlp = duplist; dlp != muldup; dlp = dlp->next) |
303 | if (dlp->dup == blkno) | |
304 | break; | |
305 | if (dlp == muldup && dlp->dup != blkno) | |
306 | muldup = new; | |
19052d90 | 307 | } |
f0ed004a KM |
308 | /* |
309 | * count the number of blocks found in id_entryno | |
310 | */ | |
311 | idesc->id_entryno++; | |
19052d90 KM |
312 | } |
313 | return (res); | |
314 | } |