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