- bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
- blockmap = (char *)calloc(bmapsz, sizeof (char));
- if (blockmap == NULL) {
- printf("cannot alloc %d bytes for blockmap\n", bmapsz);
- exit(1);
- }
- freemap = (char *)calloc(bmapsz, sizeof (char));
- if (freemap == NULL) {
- printf("cannot alloc %d bytes for freemap\n", bmapsz);
- exit(1);
- }
- statemap = (char *)calloc(imax+1, sizeof(char));
- if (statemap == NULL) {
- printf("cannot alloc %d bytes for statemap\n", imax + 1);
- exit(1);
- }
- lncntp = (short *)calloc(imax+1, sizeof(short));
- if (lncntp == NULL) {
- printf("cannot alloc %d bytes for lncntp\n",
- (imax + 1) * sizeof(short));
- exit(1);
- }
- for (c = 0; c < sblock.fs_ncg; c++) {
- cgd = cgdmin(&sblock, c);
- if (c == 0) {
- d = cgbase(&sblock, c);
- cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
- } else
- d = cgsblock(&sblock, c);
- for (; d < cgd; d++)
- setbmap(d);
- }
-
- startinum = imax + 1;
- return (1);
-
-badsb:
- ckfini();
- return (0);
-}
-
-pass1()
-{
- register int c, i, n, j;
- register DINODE *dp;
- int savino, ndb, partial;
-
- pfunc = pass1check;
- inum = 0;
- n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
- for (c = 0; c < sblock.fs_ncg; c++) {
- if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
- continue;
- if (cgrp.cg_magic != CG_MAGIC) {
- pfatal("cg %d: bad magic number\n", c);
- bzero((caddr_t)&cgrp, sblock.fs_cgsize);
- }
- n = 0;
- for (i = 0; i < sblock.fs_ipg; i++, inum++) {
- dp = ginode();
- if (dp == NULL)
- continue;
- n++;
- if (ALLOC) {
- if (!isset(cgrp.cg_iused, i)) {
- if (debug)
- printf("%d bad, not used\n",
- inum);
- inosumbad++;
- }
- n--;
- lastino = inum;
- if (!preen && BADBLK &&
- reply("HOLD BAD BLOCK") == 1) {
- dp->di_size = sblock.fs_fsize;
- dp->di_mode = IFREG|0600;
- inodirty();
- } else if (ftypeok(dp) == 0)
- goto unknown;
- if (dp->di_size < 0) {
- if (debug)
- printf("bad size %d:",
- dp->di_size);
- goto unknown;
- }
- ndb = howmany(dp->di_size, sblock.fs_bsize);
- if (SPECIAL)
- ndb++;
- for (j = ndb; j < NDADDR; j++)
- if (dp->di_db[j] != 0) {
- if (debug)
- printf("bad direct addr: %d\n",
- dp->di_db[j]);
- goto unknown;
- }
- for (j = 0, ndb -= NDADDR; ndb > 0; j++)
- ndb /= NINDIR(&sblock);
- for (; j < NIADDR; j++)
- if (dp->di_ib[j] != 0) {
- if (debug)
- printf("bad indirect addr: %d\n",
- dp->di_ib[j]);
- goto unknown;
- }
- n_files++;
- lncntp[inum] = dp->di_nlink;
- if (dp->di_nlink <= 0) {
- if (badlnp < &badlncnt[MAXLNCNT])
- *badlnp++ = inum;
- else {
- pfatal("LINK COUNT TABLE OVERFLOW");
- if (reply("CONTINUE") == 0)
- errexit("");
- }
- }
- statemap[inum] = DIRCT ? DSTATE : FSTATE;
- badblk = dupblk = 0; filsize = 0; maxblk = 0;
- ckinode(dp, ADDR);
- continue;
- unknown:
- if (!SOCK)
- pfatal("UNKNOWN FILE TYPE I=%u", inum);
- if ((preen && SOCK) || reply("CLEAR") == 1) {
- zapino(dp);
- inodirty();
- inosumbad++;
- }
- } else {
- if (isset(cgrp.cg_iused, i)) {
- if (debug)
- printf("%d bad, marked used\n",
- inum);
- inosumbad++;
- n--;
- }
- partial = 0;
- for (j = 0; j < NDADDR; j++)
- if (dp->di_db[j] != 0)
- partial++;
- for (j = 0; j < NIADDR; j++)
- if (dp->di_ib[j] != 0)
- partial++;
- if (partial || dp->di_mode != 0 ||
- dp->di_size != 0) {
- pfatal("PARTIALLY ALLOCATED INODE I=%u", inum);
- if (reply("CLEAR") == 1) {
- zapino(dp);
- inodirty();
- inosumbad++;
- }
- }
- }
- }
- if (n != cgrp.cg_cs.cs_nifree) {
- if (debug)
- printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
- c, cgrp.cg_cs.cs_nifree, n);
- inosumbad++;
- }
- if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
- || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
- || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
- || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
- sbsumbad++;
- }
-}
-
-pass1check(blk, size)
- daddr_t blk;
- int size;
-{
- register daddr_t *dlp;
- int res = KEEPON;
- int anyout;
-
- anyout = outrange(blk, size);
- for (; size > 0; blk++, size--) {
- if (anyout && outrange(blk, 1)) {
- blkerr("BAD", blk);
- if (++badblk >= MAXBAD) {
- pwarn("EXCESSIVE BAD BLKS I=%u", inum);
- if (preen)
- printf(" (SKIPPING)\n");
- else if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- res = SKIP;
- } else if (getbmap(blk)) {
- blkerr("DUP", blk);
- if (++dupblk >= MAXDUP) {
- pwarn("EXCESSIVE DUP BLKS I=%u", inum);
- if (preen)
- printf(" (SKIPPING)\n");
- else if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- if (enddup >= &duplist[DUPTBLSIZE]) {
- pfatal("DUP TABLE OVERFLOW.");
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- for (dlp = duplist; dlp < muldup; dlp++)
- if (*dlp == blk) {
- *enddup++ = blk;
- break;
- }
- if (dlp >= muldup) {
- *enddup++ = *muldup;
- *muldup++ = blk;
- }
- } else {
- n_blks++;
- setbmap(blk);
- }
- filsize++;
- }
- return (res);
-}
-
-pass1b()
-{
- register int c, i;
- register DINODE *dp;
-
- pfunc = pass1bcheck;
- inum = 0;
- for (c = 0; c < sblock.fs_ncg; c++) {
- for (i = 0; i < sblock.fs_ipg; i++, inum++) {
- dp = ginode();
- if (dp == NULL)
- continue;
- if (statemap[inum] != USTATE &&
- (ckinode(dp, ADDR) & STOP))
- goto out1b;
- }
- }
-out1b:
- flush(&dfile, &inoblk);
-}
-
-pass1bcheck(blk, size)
- daddr_t blk;
- int size;
-{
- register daddr_t *dlp;
- int res = KEEPON;
-
- for (; size > 0; blk++, size--) {
- if (outrange(blk, 1))
- res = SKIP;
- for (dlp = duplist; dlp < muldup; dlp++)
- if (*dlp == blk) {
- blkerr("DUP", blk);
- *dlp = *--muldup;
- *muldup = blk;
- if (muldup == duplist)
- return (STOP);
- }
- }
- return (res);
-}
-
-pass2()
-{
- register DINODE *dp;
-
- inum = ROOTINO;
- thisname = pathp = pathname;
- pfunc = pass2check;
- switch (statemap[inum]) {
-
- case USTATE:
- errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
-
- case FSTATE:
- pfatal("ROOT INODE NOT DIRECTORY");
- if (reply("FIX") == 0 || (dp = ginode()) == NULL)
- errexit("");
- dp->di_mode &= ~IFMT;
- dp->di_mode |= IFDIR;
- inodirty();
- inosumbad++;
- statemap[inum] = DSTATE;
- /* fall into ... */
-
- case DSTATE:
- descend();
- break;
-
- case CLEAR:
- pfatal("DUPS/BAD IN ROOT INODE");
- printf("\n");
- if (reply("CONTINUE") == 0)
- errexit("");
- statemap[inum] = DSTATE;
- descend();
- }
-}
-
-pass2check(dirp)
- register DIRECT *dirp;
-{
- register char *p;
- register n;
- DINODE *dp;
-
- if ((inum = dirp->d_ino) == 0)
- return (KEEPON);
- thisname = pathp;
- if (pathp + dirp->d_namlen >= endpathname) {
- *pathp = '\0';
- errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
- }
- for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; )
- if ((*pathp++ = *p++) == 0) {
- --pathp;
- break;
- }
- *pathp = 0;
- n = 0;
- if (inum > imax || inum <= 0)
- n = direrr("I OUT OF RANGE");
- else {
-again:
- switch (statemap[inum]) {
- case USTATE:
- n = direrr("UNALLOCATED");
- break;
-
- case CLEAR:
- if ((n = direrr("DUP/BAD")) == 1)
- break;
- if ((dp = ginode()) == NULL)
- break;
- statemap[inum] = DIRCT ? DSTATE : FSTATE;
- goto again;
-
- case FSTATE:
- lncntp[inum]--;
- break;
-
- case DSTATE:
- lncntp[inum]--;
- descend();
- break;
- }
- }
- pathp = thisname;
- if (n == 0)
- return (KEEPON);
- dirp->d_ino = 0;
- return (KEEPON|ALTERD);
-}
-
-pass3()
-{
- ino_t savino;
- register DINODE *dp;
-
- for (inum = ROOTINO; inum <= lastino; inum++) {
- if (statemap[inum] == DSTATE) {
- pfunc = findino;
- srchname = "..";
- savino = inum;
- do {
- orphan = inum;
- if ((dp = ginode()) == NULL)
- break;
- filsize = dp->di_size;
- parentdir = 0;
- ckinode(dp, DATA);
- if ((inum = parentdir) == 0)
- break;
- } while (statemap[inum] == DSTATE);
- inum = orphan;
- if (linkup() == 1) {
- thisname = pathp = pathname;
- *pathp++ = '?';
- pfunc = pass2check;
- descend();
- }
- inum = savino;
- }
- }
-}
-
-pass4()
-{
- register int n;
- register ino_t *blp;
-
- pfunc = pass4check;
- for (inum = ROOTINO; inum <= lastino; inum++) {
- switch (statemap[inum]) {
-
- case FSTATE:
- n = lncntp[inum];
- if (n)
- adjust((short)n);
- else {
- for (blp = badlncnt;blp < badlnp; blp++)
- if (*blp == inum) {
- clri("UNREF", 1);
- break;
- }
- }
- break;
-
- case DSTATE:
- clri("UNREF", 1);
- break;
-
- case CLEAR:
- clri("BAD/DUP", 1);
- break;
+ n_ffree = sblock.fs_cstotal.cs_nffree;
+ n_bfree = sblock.fs_cstotal.cs_nbfree;
+ pwarn("%ld files, %ld used, %ld free ",
+ n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
+ printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n",
+ n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize,
+ ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10);
+ if (debug &&
+ (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
+ printf("%ld files missing\n", n_files);
+ if (debug) {
+ n_blks += sblock.fs_ncg *
+ (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
+ n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
+ n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
+ if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
+ printf("%ld blocks missing\n", n_blks);
+ if (duplist != NULL) {
+ printf("The following duplicate blocks remain:");
+ for (dp = duplist; dp; dp = dp->next)
+ printf(" %ld,", dp->dup);
+ printf("\n");