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