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