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