Commit | Line | Data |
---|---|---|
528b0614 DF |
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 | |
2785316e | 8 | static char sccsid[] = "@(#)icheck.c 5.5 (Berkeley) %G%"; |
528b0614 DF |
9 | #endif not lint |
10 | ||
b42940ce KM |
11 | /* |
12 | * icheck | |
13 | */ | |
14 | #define NB 500 | |
b42940ce | 15 | #define MAXFN 500 |
c312eebd | 16 | #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) |
b42940ce | 17 | |
2785316e KB |
18 | #include <sys/param.h> |
19 | #include <sys/time.h> | |
20 | #include <sys/vnode.h> | |
21 | #include <ufs/inode.h> | |
22 | #include <ufs/fs.h> | |
b42940ce KM |
23 | #ifndef STANDALONE |
24 | #include <stdio.h> | |
25 | #endif | |
b42940ce | 26 | |
b42940ce KM |
27 | union { |
28 | struct fs sb; | |
ed4adff6 | 29 | char pad[SBSIZE]; |
b42940ce KM |
30 | } sbun; |
31 | #define sblock sbun.sb | |
32 | ||
33 | union { | |
34 | struct cg cg; | |
b6407c9d | 35 | char pad[MAXBSIZE]; |
b42940ce KM |
36 | } cgun; |
37 | #define cgrp cgun.cg | |
38 | ||
ed4adff6 KM |
39 | struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; |
40 | ||
b42940ce | 41 | daddr_t blist[NB]; |
211b1482 | 42 | daddr_t fsblist[NB]; |
b42940ce KM |
43 | char *bmap; |
44 | ||
b42940ce KM |
45 | int mflg; |
46 | int dflg; | |
47 | int fi; | |
48 | ino_t ino; | |
49 | int cginit; | |
50 | ||
51 | ino_t nrfile; | |
52 | ino_t ndfile; | |
53 | ino_t nbfile; | |
54 | ino_t ncfile; | |
ea47352d | 55 | ino_t nlfile; |
ed4adff6 | 56 | ino_t nsfile; |
b42940ce KM |
57 | |
58 | daddr_t nblock; | |
59 | daddr_t nfrag; | |
b42940ce | 60 | daddr_t nindir; |
b42940ce KM |
61 | daddr_t niindir; |
62 | ||
63 | daddr_t nffree; | |
b42940ce KM |
64 | daddr_t nbfree; |
65 | ||
66 | daddr_t ndup; | |
67 | ||
68 | int nerror; | |
a66ab591 | 69 | long dev_bsize = 1; |
b42940ce KM |
70 | |
71 | long atol(); | |
b42940ce KM |
72 | #ifndef STANDALONE |
73 | char *malloc(); | |
19f19804 | 74 | char *calloc(); |
b42940ce KM |
75 | #endif |
76 | ||
77 | main(argc, argv) | |
19f19804 KM |
78 | int argc; |
79 | char *argv[]; | |
b42940ce KM |
80 | { |
81 | register i; | |
82 | long n; | |
83 | ||
84 | blist[0] = -1; | |
85 | #ifndef STANDALONE | |
86 | while (--argc) { | |
87 | argv++; | |
88 | if (**argv=='-') | |
89 | switch ((*argv)[1]) { | |
90 | case 'd': | |
91 | dflg++; | |
92 | continue; | |
93 | ||
94 | case 'm': | |
95 | mflg++; | |
96 | continue; | |
97 | ||
b42940ce KM |
98 | case 'b': |
99 | for(i=0; i<NB; i++) { | |
100 | n = atol(argv[1]); | |
101 | if(n == 0) | |
102 | break; | |
103 | blist[i] = n; | |
104 | argv++; | |
105 | argc--; | |
106 | } | |
107 | blist[i] = -1; | |
108 | continue; | |
109 | ||
110 | default: | |
111 | printf("Bad flag\n"); | |
112 | } | |
113 | check(*argv); | |
114 | } | |
115 | #else | |
116 | { | |
117 | static char fname[128]; | |
118 | ||
119 | printf("File: "); | |
120 | gets(fname); | |
121 | check(fname); | |
122 | } | |
123 | #endif | |
124 | return(nerror); | |
125 | } | |
126 | ||
127 | check(file) | |
19f19804 | 128 | char *file; |
b42940ce KM |
129 | { |
130 | register i, j, c; | |
131 | daddr_t d, cgd, cbase, b; | |
132 | long n; | |
211b1482 | 133 | char buf[BUFSIZ]; |
b42940ce | 134 | |
ed4adff6 | 135 | fi = open(file, 0); |
b42940ce | 136 | if (fi < 0) { |
19f19804 | 137 | perror(file); |
b42940ce KM |
138 | nerror |= 04; |
139 | return; | |
140 | } | |
141 | printf("%s:\n", file); | |
142 | nrfile = 0; | |
143 | ndfile = 0; | |
144 | ncfile = 0; | |
145 | nbfile = 0; | |
ea47352d | 146 | nlfile = 0; |
ed4adff6 | 147 | nsfile = 0; |
b42940ce KM |
148 | |
149 | nblock = 0; | |
150 | nfrag = 0; | |
b42940ce | 151 | nindir = 0; |
b42940ce KM |
152 | niindir = 0; |
153 | ||
154 | ndup = 0; | |
155 | #ifndef STANDALONE | |
156 | sync(); | |
157 | #endif | |
b6407c9d KM |
158 | getsb(&sblock, file); |
159 | if (nerror) | |
b42940ce | 160 | return; |
211b1482 KM |
161 | for (n=0; blist[n] != -1; n++) |
162 | fsblist[n] = dbtofsb(&sblock, blist[n]); | |
b42940ce | 163 | ino = 0; |
19f19804 | 164 | n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); |
b42940ce KM |
165 | #ifdef STANDALONE |
166 | bmap = NULL; | |
167 | #else | |
168 | bmap = malloc((unsigned)n); | |
169 | #endif | |
170 | if (bmap==NULL) { | |
171 | printf("Not enough core; duplicates unchecked\n"); | |
172 | dflg++; | |
b42940ce KM |
173 | } |
174 | ino = 0; | |
175 | cginit = 1; | |
bf541624 KM |
176 | if (!dflg) { |
177 | for (i = 0; i < (unsigned)n; i++) | |
b42940ce | 178 | bmap[i] = 0; |
bf541624 | 179 | for (c = 0; c < sblock.fs_ncg; c++) { |
6994bf5d | 180 | cgd = cgtod(&sblock, c); |
bf541624 KM |
181 | if (c == 0) |
182 | d = cgbase(&sblock, c); | |
183 | else | |
184 | d = cgsblock(&sblock, c); | |
9bd38ba8 | 185 | (void)sprintf(buf, "spare super block %d", c); |
bf541624 | 186 | for (; d < cgd; d += sblock.fs_frag) |
211b1482 | 187 | chk(d, buf, sblock.fs_bsize); |
6994bf5d | 188 | d = cgimin(&sblock, c); |
9bd38ba8 | 189 | (void)sprintf(buf, "cylinder group %d", c); |
b42940ce | 190 | while (cgd < d) { |
211b1482 | 191 | chk(cgd, buf, sblock.fs_bsize); |
b6407c9d | 192 | cgd += sblock.fs_frag; |
b42940ce | 193 | } |
6994bf5d | 194 | d = cgdmin(&sblock, c); |
211b1482 KM |
195 | i = INOPB(&sblock); |
196 | for (; cgd < d; cgd += sblock.fs_frag) { | |
9bd38ba8 | 197 | (void)sprintf(buf, "inodes %d-%d", ino, ino + i); |
211b1482 KM |
198 | chk(cgd, buf, sblock.fs_bsize); |
199 | ino += i; | |
200 | } | |
b42940ce | 201 | if (c == 0) { |
bf541624 KM |
202 | d += howmany(sblock.fs_cssize, sblock.fs_fsize); |
203 | for (; cgd < d; cgd++) | |
204 | chk(cgd, "csum", sblock.fs_fsize); | |
b42940ce KM |
205 | } |
206 | } | |
207 | } | |
211b1482 | 208 | ino = 0; |
b42940ce KM |
209 | cginit = 0; |
210 | for (c = 0; c < sblock.fs_ncg; c++) { | |
ed4adff6 KM |
211 | for (i = 0; |
212 | i < sblock.fs_ipg / INOPF(&sblock); | |
213 | i += sblock.fs_frag) { | |
214 | bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), | |
215 | (char *)itab, sblock.fs_bsize); | |
216 | for (j = 0; j < INOPB(&sblock); j++) { | |
217 | pass1(&itab[j]); | |
218 | ino++; | |
219 | } | |
b42940ce KM |
220 | } |
221 | } | |
222 | ino = 0; | |
223 | #ifndef STANDALONE | |
224 | sync(); | |
225 | #endif | |
b42940ce | 226 | nffree = 0; |
b42940ce KM |
227 | nbfree = 0; |
228 | for (c = 0; c < sblock.fs_ncg; c++) { | |
6994bf5d KM |
229 | cbase = cgbase(&sblock, c); |
230 | bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, | |
b6407c9d | 231 | sblock.fs_cgsize); |
ed4adff6 | 232 | if (!cg_chkmagic(&cgrp)) |
bf541624 | 233 | printf("cg %d: bad magic number\n", c); |
b6407c9d | 234 | for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { |
ed4adff6 | 235 | if (isblock(&sblock, cg_blksfree(&cgrp), |
b6407c9d | 236 | b / sblock.fs_frag)) { |
b42940ce | 237 | nbfree++; |
211b1482 | 238 | chk(cbase+b, "free block", sblock.fs_bsize); |
b42940ce | 239 | } else { |
b6407c9d | 240 | for (d = 0; d < sblock.fs_frag; d++) |
ed4adff6 | 241 | if (isset(cg_blksfree(&cgrp), b+d)) { |
211b1482 | 242 | chk(cbase+b+d, "free frag", sblock.fs_fsize); |
b42940ce | 243 | nffree++; |
b42940ce KM |
244 | } |
245 | } | |
246 | } | |
247 | } | |
248 | close(fi); | |
249 | #ifndef STANDALONE | |
250 | if (bmap) | |
251 | free(bmap); | |
252 | #endif | |
253 | ||
ed4adff6 | 254 | i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; |
b42940ce | 255 | #ifndef STANDALONE |
ed4adff6 KM |
256 | printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", |
257 | i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); | |
b42940ce | 258 | #else |
ed4adff6 KM |
259 | printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", |
260 | i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); | |
b42940ce | 261 | #endif |
b6407c9d | 262 | n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; |
b42940ce KM |
263 | #ifdef STANDALONE |
264 | printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", | |
265 | n, nindir, niindir, nblock, nfrag); | |
b6407c9d | 266 | printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, |
b42940ce KM |
267 | nbfree, nffree); |
268 | #else | |
269 | printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", | |
270 | n, nindir, niindir, nblock, nfrag); | |
b6407c9d | 271 | printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, |
b42940ce KM |
272 | nbfree, nffree); |
273 | #endif | |
274 | if(!dflg) { | |
275 | n = 0; | |
955f6ff8 | 276 | for (d = 0; d < sblock.fs_size; d++) |
b6407c9d | 277 | if(!duped(d, sblock.fs_fsize)) { |
b42940ce KM |
278 | if(mflg) |
279 | printf("%ld missing\n", d); | |
280 | n++; | |
281 | } | |
282 | printf("missing%5ld\n", n); | |
283 | } | |
284 | } | |
285 | ||
286 | pass1(ip) | |
955f6ff8 | 287 | register struct dinode *ip; |
b42940ce | 288 | { |
b6407c9d KM |
289 | daddr_t ind1[MAXNINDIR]; |
290 | daddr_t ind2[MAXNINDIR]; | |
07670f7d KM |
291 | daddr_t db, ib; |
292 | register int i, j, k, siz; | |
211b1482 KM |
293 | int lbn; |
294 | char buf[BUFSIZ]; | |
b42940ce KM |
295 | |
296 | i = ip->di_mode & IFMT; | |
0947395d | 297 | if(i == 0) |
b42940ce | 298 | return; |
b42940ce KM |
299 | switch (i) { |
300 | case IFCHR: | |
301 | ncfile++; | |
302 | return; | |
303 | case IFBLK: | |
304 | nbfile++; | |
305 | return; | |
306 | case IFDIR: | |
307 | ndfile++; | |
308 | break; | |
309 | case IFREG: | |
310 | nrfile++; | |
311 | break; | |
ed4adff6 KM |
312 | case IFSOCK: |
313 | nsfile++; | |
314 | break; | |
ea47352d KM |
315 | case IFLNK: |
316 | nlfile++; | |
317 | break; | |
b42940ce KM |
318 | default: |
319 | printf("bad mode %u\n", ino); | |
320 | return; | |
321 | } | |
955f6ff8 KM |
322 | for (i = 0; i < NDADDR; i++) { |
323 | db = ip->di_db[i]; | |
324 | if (db == 0) | |
b42940ce | 325 | continue; |
b6407c9d | 326 | siz = dblksize(&sblock, ip, i); |
9bd38ba8 | 327 | (void)sprintf(buf, "logical data block %d", i); |
211b1482 | 328 | chk(db, buf, siz); |
b6407c9d | 329 | if (siz == sblock.fs_bsize) |
07670f7d KM |
330 | nblock++; |
331 | else | |
b6407c9d | 332 | nfrag += howmany(siz, sblock.fs_fsize); |
b42940ce | 333 | } |
955f6ff8 KM |
334 | for(i = 0; i < NIADDR; i++) { |
335 | ib = ip->di_ib[i]; | |
211b1482 | 336 | if (ib == 0) |
955f6ff8 | 337 | continue; |
b6407c9d | 338 | if (chk(ib, "1st indirect", sblock.fs_bsize)) |
b42940ce | 339 | continue; |
b6407c9d | 340 | bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); |
b42940ce | 341 | nindir++; |
b6407c9d | 342 | for (j = 0; j < NINDIR(&sblock); j++) { |
955f6ff8 KM |
343 | ib = ind1[j]; |
344 | if (ib == 0) | |
b42940ce | 345 | continue; |
955f6ff8 | 346 | if (i == 0) { |
211b1482 KM |
347 | lbn = NDADDR + j; |
348 | siz = dblksize(&sblock, ip, lbn); | |
9bd38ba8 | 349 | (void)sprintf(buf, "logical data block %d", lbn); |
211b1482 | 350 | chk(ib, buf, siz); |
b6407c9d | 351 | if (siz == sblock.fs_bsize) |
07670f7d KM |
352 | nblock++; |
353 | else | |
b6407c9d | 354 | nfrag += howmany(siz, sblock.fs_fsize); |
b42940ce KM |
355 | continue; |
356 | } | |
b6407c9d | 357 | if (chk(ib, "2nd indirect", sblock.fs_bsize)) |
955f6ff8 | 358 | continue; |
b6407c9d KM |
359 | bread(fsbtodb(&sblock, ib), (char *)ind2, |
360 | sblock.fs_bsize); | |
b42940ce | 361 | niindir++; |
b6407c9d | 362 | for (k = 0; k < NINDIR(&sblock); k++) { |
955f6ff8 KM |
363 | ib = ind2[k]; |
364 | if (ib == 0) | |
b42940ce | 365 | continue; |
211b1482 KM |
366 | lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; |
367 | siz = dblksize(&sblock, ip, lbn); | |
9bd38ba8 | 368 | (void)sprintf(buf, "logical data block %d", lbn); |
211b1482 | 369 | chk(ib, buf, siz); |
b6407c9d | 370 | if (siz == sblock.fs_bsize) |
07670f7d KM |
371 | nblock++; |
372 | else | |
b6407c9d | 373 | nfrag += howmany(siz, sblock.fs_fsize); |
b42940ce | 374 | } |
b42940ce KM |
375 | } |
376 | } | |
377 | } | |
378 | ||
07670f7d | 379 | chk(bno, s, size) |
955f6ff8 KM |
380 | daddr_t bno; |
381 | char *s; | |
07670f7d | 382 | int size; |
b42940ce KM |
383 | { |
384 | register n, cg; | |
3352e84a | 385 | int frags; |
b42940ce | 386 | |
6994bf5d | 387 | cg = dtog(&sblock, bno); |
bf541624 | 388 | if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { |
b42940ce KM |
389 | printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); |
390 | return(1); | |
391 | } | |
211b1482 KM |
392 | frags = numfrags(&sblock, size); |
393 | if (frags == sblock.fs_frag) { | |
07670f7d KM |
394 | if (duped(bno, size)) { |
395 | printf("%ld dup block; inode=%u, class=%s\n", | |
396 | bno, ino, s); | |
b6407c9d | 397 | ndup += sblock.fs_frag; |
07670f7d KM |
398 | } |
399 | } else { | |
3352e84a | 400 | for (n = 0; n < frags; n++) { |
b6407c9d | 401 | if (duped(bno + n, sblock.fs_fsize)) { |
07670f7d KM |
402 | printf("%ld dup frag; inode=%u, class=%s\n", |
403 | bno, ino, s); | |
404 | ndup++; | |
405 | } | |
406 | } | |
b42940ce KM |
407 | } |
408 | for (n=0; blist[n] != -1; n++) | |
211b1482 KM |
409 | if (fsblist[n] >= bno && fsblist[n] < bno + frags) |
410 | printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", | |
411 | blist[n], fsblist[n] - bno, frags, ino, s); | |
b42940ce KM |
412 | return(0); |
413 | } | |
414 | ||
07670f7d | 415 | duped(bno, size) |
955f6ff8 | 416 | daddr_t bno; |
07670f7d | 417 | int size; |
b42940ce | 418 | { |
b42940ce KM |
419 | if(dflg) |
420 | return(0); | |
b6407c9d | 421 | if (size != sblock.fs_fsize && size != sblock.fs_bsize) |
07670f7d | 422 | printf("bad size %d to duped\n", size); |
b6407c9d | 423 | if (size == sblock.fs_fsize) { |
955f6ff8 KM |
424 | if (isset(bmap, bno)) |
425 | return(1); | |
426 | setbit(bmap, bno); | |
427 | return (0); | |
428 | } | |
b6407c9d | 429 | if (bno % sblock.fs_frag != 0) |
955f6ff8 | 430 | printf("bad bno %d to duped\n", bno); |
b6407c9d | 431 | if (isblock(&sblock, bmap, bno/sblock.fs_frag)) |
955f6ff8 | 432 | return (1); |
b6407c9d | 433 | setblock(&sblock, bmap, bno/sblock.fs_frag); |
b42940ce KM |
434 | return(0); |
435 | } | |
436 | ||
b6407c9d KM |
437 | getsb(fs, file) |
438 | register struct fs *fs; | |
439 | char *file; | |
440 | { | |
bf541624 | 441 | int i, j, size; |
b6407c9d | 442 | |
a66ab591 | 443 | if (bread(SBOFF, fs, SBSIZE)) { |
b6407c9d KM |
444 | printf("bad super block"); |
445 | perror(file); | |
446 | nerror |= 04; | |
447 | return; | |
448 | } | |
449 | if (fs->fs_magic != FS_MAGIC) { | |
450 | printf("%s: bad magic number\n", file); | |
451 | nerror |= 04; | |
452 | return; | |
453 | } | |
a66ab591 | 454 | dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); |
bf541624 KM |
455 | for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { |
456 | size = sblock.fs_cssize - i < sblock.fs_bsize ? | |
457 | sblock.fs_cssize - i : sblock.fs_bsize; | |
458 | sblock.fs_csp[j] = (struct csum *)calloc(1, size); | |
459 | bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), | |
460 | (char *)fs->fs_csp[j], size); | |
b6407c9d KM |
461 | } |
462 | } | |
463 | ||
b42940ce | 464 | bread(bno, buf, cnt) |
955f6ff8 KM |
465 | daddr_t bno; |
466 | char *buf; | |
b42940ce KM |
467 | { |
468 | register i; | |
469 | ||
a66ab591 | 470 | lseek(fi, bno * dev_bsize, 0); |
b42940ce | 471 | if ((i = read(fi, buf, cnt)) != cnt) { |
b6407c9d | 472 | for(i=0; i<sblock.fs_bsize; i++) |
b42940ce | 473 | buf[i] = 0; |
b6407c9d KM |
474 | return (1); |
475 | } | |
476 | return (0); | |
477 | } | |
478 | ||
479 | /* | |
3969097b | 480 | * check if a block is available |
b6407c9d | 481 | */ |
b6407c9d KM |
482 | isblock(fs, cp, h) |
483 | struct fs *fs; | |
484 | unsigned char *cp; | |
485 | int h; | |
486 | { | |
487 | unsigned char mask; | |
488 | ||
489 | switch (fs->fs_frag) { | |
490 | case 8: | |
491 | return (cp[h] == 0xff); | |
492 | case 4: | |
493 | mask = 0x0f << ((h & 0x1) << 2); | |
494 | return ((cp[h >> 1] & mask) == mask); | |
495 | case 2: | |
496 | mask = 0x03 << ((h & 0x3) << 1); | |
497 | return ((cp[h >> 2] & mask) == mask); | |
498 | case 1: | |
499 | mask = 0x01 << (h & 0x7); | |
500 | return ((cp[h >> 3] & mask) == mask); | |
501 | default: | |
3969097b KM |
502 | #ifdef STANDALONE |
503 | printf("isblock bad fs_frag %d\n", fs->fs_frag); | |
504 | #else | |
b6407c9d | 505 | fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); |
3969097b KM |
506 | #endif |
507 | return; | |
508 | } | |
509 | } | |
510 | ||
3969097b KM |
511 | /* |
512 | * put a block into the map | |
513 | */ | |
b6407c9d KM |
514 | setblock(fs, cp, h) |
515 | struct fs *fs; | |
516 | unsigned char *cp; | |
517 | int h; | |
518 | { | |
519 | switch (fs->fs_frag) { | |
520 | case 8: | |
521 | cp[h] = 0xff; | |
522 | return; | |
523 | case 4: | |
524 | cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); | |
525 | return; | |
526 | case 2: | |
527 | cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); | |
528 | return; | |
529 | case 1: | |
530 | cp[h >> 3] |= (0x01 << (h & 0x7)); | |
531 | return; | |
532 | default: | |
3969097b KM |
533 | #ifdef STANDALONE |
534 | printf("setblock bad fs_frag %d\n", fs->fs_frag); | |
535 | #else | |
b6407c9d | 536 | fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); |
3969097b | 537 | #endif |
b6407c9d | 538 | return; |
b42940ce KM |
539 | } |
540 | } |