update for new file system
[unix-history] / usr / src / sbin / icheck / icheck.c
index 86a16d2..8d8574a 100644 (file)
@@ -1,18 +1,24 @@
-static char *sccsid = "@(#)icheck.c    1.10 (Berkeley) %G%";
+static char *sccsid = "@(#)icheck.c    2.4 (Berkeley) %G%";
 
 /*
  * icheck
  */
 #define        NB      500
 #define        MAXFN   500
 
 /*
  * icheck
  */
 #define        NB      500
 #define        MAXFN   500
-#define MAXNINDIR (MAXBSIZE / sizeof (daddr_t))
+#define        MAXNINDIR       (MAXBSIZE / sizeof (daddr_t))
 
 #ifndef STANDALONE
 #include <stdio.h>
 #endif
 
 #ifndef STANDALONE
 #include <stdio.h>
 #endif
+#ifndef SIMFS
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/fs.h>
+#else
 #include "../h/param.h"
 #include "../h/inode.h"
 #include "../h/fs.h"
 #include "../h/param.h"
 #include "../h/inode.h"
 #include "../h/fs.h"
+#endif
 
 union {
        struct  fs sb;
 
 union {
        struct  fs sb;
@@ -28,6 +34,7 @@ union {
 
 struct dinode  itab[MAXIPG];
 daddr_t        blist[NB];
 
 struct dinode  itab[MAXIPG];
 daddr_t        blist[NB];
+daddr_t        fsblist[NB];
 char   *bmap;
 
 int    mflg;
 char   *bmap;
 
 int    mflg;
@@ -41,7 +48,7 @@ ino_t nrfile;
 ino_t  ndfile;
 ino_t  nbfile;
 ino_t  ncfile;
 ino_t  ndfile;
 ino_t  nbfile;
 ino_t  ncfile;
-ino_t  nmcfile;
+ino_t  nlfile;
 
 daddr_t        nblock;
 daddr_t        nfrag;
 
 daddr_t        nblock;
 daddr_t        nfrag;
@@ -124,6 +131,7 @@ check(file)
        register i, j, c;
        daddr_t d, cgd, cbase, b;
        long n;
        register i, j, c;
        daddr_t d, cgd, cbase, b;
        long n;
+       char buf[BUFSIZ];
 
        fi = open(file, sflg ? 2 : 0);
        if (fi < 0) {
 
        fi = open(file, sflg ? 2 : 0);
        if (fi < 0) {
@@ -136,7 +144,7 @@ check(file)
        ndfile = 0;
        ncfile = 0;
        nbfile = 0;
        ndfile = 0;
        ncfile = 0;
        nbfile = 0;
-       nmcfile = 0;
+       nlfile = 0;
 
        nblock = 0;
        nfrag = 0;
 
        nblock = 0;
        nfrag = 0;
@@ -150,6 +158,8 @@ check(file)
        getsb(&sblock, file);
        if (nerror)
                return;
        getsb(&sblock, file);
        if (nerror)
                return;
+       for (n=0; blist[n] != -1; n++)
+               fsblist[n] = dbtofsb(&sblock, blist[n]);
        ino = 0;
        n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
 #ifdef STANDALONE
        ino = 0;
        n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
 #ifdef STANDALONE
@@ -167,32 +177,42 @@ check(file)
        }
        ino = 0;
        cginit = 1;
        }
        ino = 0;
        cginit = 1;
-       if(!dflg) {
-               for (i=0; i<(unsigned)n; i++)
+       if (!dflg) {
+               for (i = 0; i < (unsigned)n; i++)
                        bmap[i] = 0;
                        bmap[i] = 0;
-               for (c=0; c < sblock.fs_ncg; c++) {
-                       cgd = cgtod(c, &sblock);
-                       for (d = cgbase(c, &sblock); d < cgd; d += sblock.fs_frag)
-                               chk(d, "badcg", sblock.fs_bsize);
-                       d = cgimin(c, &sblock);
+               for (c = 0; c < sblock.fs_ncg; c++) {
+                       cgd = cgtod(&sblock, c);
+                       if (c == 0)
+                               d = cgbase(&sblock, c);
+                       else
+                               d = cgsblock(&sblock, c);
+                       sprintf(buf, "spare super block %d", c);
+                       for (; d < cgd; d += sblock.fs_frag)
+                               chk(d, buf, sblock.fs_bsize);
+                       d = cgimin(&sblock, c);
+                       sprintf(buf, "cylinder group %d", c);
                        while (cgd < d) {
                        while (cgd < d) {
-                               chk(cgd, "cg", sblock.fs_bsize);
+                               chk(cgd, buf, sblock.fs_bsize);
                                cgd += sblock.fs_frag;
                        }
                                cgd += sblock.fs_frag;
                        }
-                       d = cgdmin(c, &sblock);
-                       for (; cgd < d; cgd += sblock.fs_frag)
-                               chk(cgd, "inode", sblock.fs_bsize);
+                       d = cgdmin(&sblock, c);
+                       i = INOPB(&sblock);
+                       for (; cgd < d; cgd += sblock.fs_frag) {
+                               sprintf(buf, "inodes %d-%d", ino, ino + i);
+                               chk(cgd, buf, sblock.fs_bsize);
+                               ino += i;
+                       }
                        if (c == 0) {
                        if (c == 0) {
-                               d += howmany(sblock.fs_cssize, sblock.fs_bsize)
-                                   * sblock.fs_frag;
-                               for (; cgd < d; cgd += sblock.fs_frag)
-                                       chk(cgd, "csum", sblock.fs_bsize);
+                               d += howmany(sblock.fs_cssize, sblock.fs_fsize);
+                               for (; cgd < d; cgd++)
+                                       chk(cgd, "csum", sblock.fs_fsize);
                        }
                }
        }
                        }
                }
        }
+       ino = 0;
        cginit = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
        cginit = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
-               bread(fsbtodb(&sblock, cgimin(c,&sblock)), (char *)itab,
+               bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
                    sblock.fs_ipg * sizeof (struct dinode));
                for (j=0; j < sblock.fs_ipg; j++) {
                        pass1(&itab[j]);
                    sblock.fs_ipg * sizeof (struct dinode));
                for (j=0; j < sblock.fs_ipg; j++) {
                        pass1(&itab[j]);
@@ -215,18 +235,20 @@ check(file)
        nffree = 0;
        nbfree = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
        nffree = 0;
        nbfree = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
-               cbase = cgbase(c,&sblock);
-               bread(fsbtodb(&sblock, cgtod(c,&sblock)), (char *)&cgrp,
+               cbase = cgbase(&sblock, c);
+               bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp,
                        sblock.fs_cgsize);
                        sblock.fs_cgsize);
+               if (cgrp.cg_magic != CG_MAGIC)
+                       printf("cg %d: bad magic number\n", c);
                for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
                        if (isblock(&sblock, cgrp.cg_free,
                            b / sblock.fs_frag)) {
                                nbfree++;
                for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
                        if (isblock(&sblock, cgrp.cg_free,
                            b / sblock.fs_frag)) {
                                nbfree++;
-                               chk(cbase+b, "block", sblock.fs_bsize);
+                               chk(cbase+b, "free block", sblock.fs_bsize);
                        } else {
                                for (d = 0; d < sblock.fs_frag; d++)
                                        if (isset(cgrp.cg_free, b+d)) {
                        } else {
                                for (d = 0; d < sblock.fs_frag; d++)
                                        if (isset(cgrp.cg_free, b+d)) {
-                                               chk(cbase+b+d, "frag", sblock.fs_fsize);
+                                               chk(cbase+b+d, "free frag", sblock.fs_fsize);
                                                nffree++;
                                        }
                        }
                                                nffree++;
                                        }
                        }
@@ -238,13 +260,13 @@ check(file)
                free(bmap);
 #endif
 
                free(bmap);
 #endif
 
-       i = nrfile + ndfile + ncfile + nbfile + nmcfile;
+       i = nrfile + ndfile + ncfile + nbfile + nlfile;
 #ifndef STANDALONE
 #ifndef STANDALONE
-       printf("files %6u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n",
-               i, nrfile, ndfile, nbfile, ncfile, nmcfile);
+       printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
+               i, nrfile, ndfile, nbfile, ncfile, nlfile);
 #else
 #else
-       printf("files %u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n",
-               i, nrfile, ndfile, nbfile, ncfile, nmcfile);
+       printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
+               i, nrfile, ndfile, nbfile, ncfile, nlfile);
 #endif
        n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
 #ifdef STANDALONE
 #endif
        n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
 #ifdef STANDALONE
@@ -277,6 +299,8 @@ pass1(ip)
        daddr_t ind2[MAXNINDIR];
        daddr_t db, ib;
        register int i, j, k, siz;
        daddr_t ind2[MAXNINDIR];
        daddr_t db, ib;
        register int i, j, k, siz;
+       int lbn;
+       char buf[BUFSIZ];
 
        i = ip->di_mode & IFMT;
        if(i == 0)
 
        i = ip->di_mode & IFMT;
        if(i == 0)
@@ -294,6 +318,9 @@ pass1(ip)
        case IFREG:
                nrfile++;
                break;
        case IFREG:
                nrfile++;
                break;
+       case IFLNK:
+               nlfile++;
+               break;
        default:
                printf("bad mode %u\n", ino);
                return;
        default:
                printf("bad mode %u\n", ino);
                return;
@@ -303,7 +330,8 @@ pass1(ip)
                if (db == 0)
                        continue;
                siz = dblksize(&sblock, ip, i);
                if (db == 0)
                        continue;
                siz = dblksize(&sblock, ip, i);
-               chk(db, "data (block)", siz);
+               sprintf(buf, "logical data block %d", i);
+               chk(db, buf, siz);
                if (siz == sblock.fs_bsize)
                        nblock++;
                else
                if (siz == sblock.fs_bsize)
                        nblock++;
                else
@@ -311,7 +339,7 @@ pass1(ip)
        }
        for(i = 0; i < NIADDR; i++) {
                ib = ip->di_ib[i];
        }
        for(i = 0; i < NIADDR; i++) {
                ib = ip->di_ib[i];
-               if(ib == 0)
+               if (ib == 0)
                        continue;
                if (chk(ib, "1st indirect", sblock.fs_bsize))
                        continue;
                        continue;
                if (chk(ib, "1st indirect", sblock.fs_bsize))
                        continue;
@@ -322,8 +350,10 @@ pass1(ip)
                        if (ib == 0)
                                continue;
                        if (i == 0) {
                        if (ib == 0)
                                continue;
                        if (i == 0) {
-                               siz = dblksize(&sblock, ip, NDADDR + j);
-                               chk(ib, "data (large)", siz);
+                               lbn = NDADDR + j;
+                               siz = dblksize(&sblock, ip, lbn);
+                               sprintf(buf, "logical data block %d", lbn);
+                               chk(ib, buf, siz);
                                if (siz == sblock.fs_bsize)
                                        nblock++;
                                else
                                if (siz == sblock.fs_bsize)
                                        nblock++;
                                else
@@ -339,9 +369,10 @@ pass1(ip)
                                ib = ind2[k];
                                if (ib == 0)
                                        continue;
                                ib = ind2[k];
                                if (ib == 0)
                                        continue;
-                               siz = dblksize(&sblock, ip,
-                                   NDADDR + NINDIR(&sblock) * (i + j) + k);
-                               chk(ib, "data (huge)", siz);
+                               lbn = NDADDR + NINDIR(&sblock) * (i + j) + k;
+                               siz = dblksize(&sblock, ip, lbn);
+                               sprintf(buf, "logical data block %d", lbn);
+                               chk(ib, buf, siz);
                                if (siz == sblock.fs_bsize)
                                        nblock++;
                                else
                                if (siz == sblock.fs_bsize)
                                        nblock++;
                                else
@@ -357,21 +388,22 @@ chk(bno, s, size)
        int size;
 {
        register n, cg;
        int size;
 {
        register n, cg;
+       int frags;
 
 
-       cg = dtog(bno, &sblock);
-       if (cginit==0 &&
-           bno<cgdmin(cg,&sblock) || bno >= sblock.fs_frag * sblock.fs_size) {
+       cg = dtog(&sblock, bno);
+       if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) {
                printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
                return(1);
        }
                printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
                return(1);
        }
-       if (size == sblock.fs_bsize) {
+       frags = numfrags(&sblock, size);
+       if (frags == sblock.fs_frag) {
                if (duped(bno, size)) {
                        printf("%ld dup block; inode=%u, class=%s\n",
                            bno, ino, s);
                        ndup += sblock.fs_frag;
                }
        } else {
                if (duped(bno, size)) {
                        printf("%ld dup block; inode=%u, class=%s\n",
                            bno, ino, s);
                        ndup += sblock.fs_frag;
                }
        } else {
-               for (n = 0; n < size / sblock.fs_fsize; n++) {
+               for (n = 0; n < frags; n++) {
                        if (duped(bno + n, sblock.fs_fsize)) {
                                printf("%ld dup frag; inode=%u, class=%s\n",
                                    bno, ino, s);
                        if (duped(bno + n, sblock.fs_fsize)) {
                                printf("%ld dup frag; inode=%u, class=%s\n",
                                    bno, ino, s);
@@ -380,8 +412,9 @@ chk(bno, s, size)
                }
        }
        for (n=0; blist[n] != -1; n++)
                }
        }
        for (n=0; blist[n] != -1; n++)
-               if (bno == blist[n])
-                       printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
+               if (fsblist[n] >= bno && fsblist[n] < bno + frags)
+                       printf("%ld arg; frag %d of %d, inode=%u, class=%s\n",
+                               blist[n], fsblist[n] - bno, frags, ino, s);
        return(0);
 }
 
        return(0);
 }
 
@@ -410,7 +443,7 @@ duped(bno, size)
 makecg()
 {
        int c, blk;
 makecg()
 {
        int c, blk;
-       daddr_t dbase, d, dmin, dmax;
+       daddr_t dbase, d, dlower, dupper, dmax;
        long i, j, s;
        register struct csum *cs;
        register struct dinode *dp;
        long i, j, s;
        register struct csum *cs;
        register struct dinode *dp;
@@ -420,106 +453,120 @@ makecg()
        sblock.fs_cstotal.cs_nifree = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
        sblock.fs_cstotal.cs_nifree = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
-               dbase = cgbase(c, &sblock);
+               dbase = cgbase(&sblock, c);
                dmax = dbase + sblock.fs_fpg;
                dmax = dbase + sblock.fs_fpg;
-               if (dmax > sblock.fs_size)
-                       dmax = sblock.fs_size;
-               dmin = cgdmin(c, &sblock) - dbase;
+               if (dmax > sblock.fs_size) {
+                       for ( ; dmax >= sblock.fs_size; dmax--)
+                               clrbit(cgrp.cg_free, dmax - dbase);
+                       dmax++;
+               }
+               dlower = cgsblock(&sblock, c) - dbase;
+               dupper = cgdmin(&sblock, c) - dbase;
                cs = &sblock.fs_cs(&sblock, c);
                cgrp.cg_time = time(0);
                cgrp.cg_magic = CG_MAGIC;
                cgrp.cg_cgx = c;
                cs = &sblock.fs_cs(&sblock, c);
                cgrp.cg_time = time(0);
                cgrp.cg_magic = CG_MAGIC;
                cgrp.cg_cgx = c;
-               cgrp.cg_ncyl = sblock.fs_cpg;
+               if (c == sblock.fs_ncg - 1)
+                       cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
+               else
+                       cgrp.cg_ncyl = sblock.fs_cpg;
                cgrp.cg_niblk = sblock.fs_ipg;
                cgrp.cg_ndblk = dmax - dbase;
                cgrp.cg_cs.cs_ndir = 0;
                cgrp.cg_cs.cs_nffree = 0;
                cgrp.cg_cs.cs_nbfree = 0;
                cgrp.cg_cs.cs_nifree = 0;
                cgrp.cg_niblk = sblock.fs_ipg;
                cgrp.cg_ndblk = dmax - dbase;
                cgrp.cg_cs.cs_ndir = 0;
                cgrp.cg_cs.cs_nffree = 0;
                cgrp.cg_cs.cs_nbfree = 0;
                cgrp.cg_cs.cs_nifree = 0;
-               cgrp.cg_rotor = dmin;
-               cgrp.cg_frotor = dmin;
+               cgrp.cg_rotor = 0;
+               cgrp.cg_frotor = 0;
                cgrp.cg_irotor = 0;
                for (i = 0; i < sblock.fs_frag; i++)
                        cgrp.cg_frsum[i] = 0;
                cgrp.cg_irotor = 0;
                for (i = 0; i < sblock.fs_frag; i++)
                        cgrp.cg_frsum[i] = 0;
-               bread(fsbtodb(&sblock, cgimin(c, &sblock)), (char *)itab,
+               bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
                      sblock.fs_ipg * sizeof(struct dinode));
                for (i = 0; i < sblock.fs_ipg; i++) {
                      sblock.fs_ipg * sizeof(struct dinode));
                for (i = 0; i < sblock.fs_ipg; i++) {
+                       cgrp.cg_cs.cs_nifree++;
+                       clrbit(cgrp.cg_iused, i);
                        dp = &itab[i];
                        dp = &itab[i];
-                       if (dp == NULL)
-                               continue;
                        if ((dp->di_mode & IFMT) != 0) {
                                if ((dp->di_mode & IFMT) == IFDIR)
                                        cgrp.cg_cs.cs_ndir++;
                        if ((dp->di_mode & IFMT) != 0) {
                                if ((dp->di_mode & IFMT) == IFDIR)
                                        cgrp.cg_cs.cs_ndir++;
+                               cgrp.cg_cs.cs_nifree--;
                                setbit(cgrp.cg_iused, i);
                                continue;
                        }
                                setbit(cgrp.cg_iused, i);
                                continue;
                        }
-                       cgrp.cg_cs.cs_nifree++;
-                       clrbit(cgrp.cg_iused, i);
                }
                while (i < MAXIPG) {
                        clrbit(cgrp.cg_iused, i);
                        i++;
                }
                }
                while (i < MAXIPG) {
                        clrbit(cgrp.cg_iused, i);
                        i++;
                }
-               for (s = 0; s < MAXCPG; s++)
+               if (c == 0)
+                       for (i = 0; i < ROOTINO; i++) {
+                               setbit(cgrp.cg_iused, i);
+                               cgrp.cg_cs.cs_nifree--;
+                       }
+               for (s = 0; s < MAXCPG; s++) {
+                       cgrp.cg_btot[s] = 0;
                        for (i = 0; i < NRPOS; i++)
                                cgrp.cg_b[s][i] = 0;
                        for (i = 0; i < NRPOS; i++)
                                cgrp.cg_b[s][i] = 0;
+               }
                if (c == 0) {
                if (c == 0) {
-                       dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) *
-                           sblock.fs_frag;
+                       dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
                }
                }
-               for (d = 0; d < dmin; d++)
+               for (d = dlower; d < dupper; d++)
                        clrbit(cgrp.cg_free, d);
                        clrbit(cgrp.cg_free, d);
-               for (; (d + sblock.fs_frag) <= dmax - dbase; d += sblock.fs_frag) {
+               for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
+                   d += sblock.fs_frag) {
                        j = 0;
                        for (i = 0; i < sblock.fs_frag; i++) {
                        j = 0;
                        for (i = 0; i < sblock.fs_frag; i++) {
-                               if (!isset(bmap, dbase+d+i)) {
-                                       setbit(cgrp.cg_free, d+i);
+                               if (!isset(bmap, dbase + d + i)) {
+                                       setbit(cgrp.cg_free, d + i);
                                        j++;
                                } else
                                        clrbit(cgrp.cg_free, d+i);
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
                                        j++;
                                } else
                                        clrbit(cgrp.cg_free, d+i);
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
-                               s = d * NSPF(&sblock);
-                               cgrp.cg_b[s/sblock.fs_spc]
-                                 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
+                               cgrp.cg_btot[cbtocylno(&sblock, d)]++;
+                               cgrp.cg_b[cbtocylno(&sblock, d)]
+                                   [cbtorpos(&sblock, d)]++;
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
-                               blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) &
-                                      (0xff >> (NBBY - sblock.fs_frag)));
+                               blk = blkmap(&sblock, cgrp.cg_free, d);
                                fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                        }
                }
                for (j = d; d < dmax - dbase; d++) {
                                fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                        }
                }
                for (j = d; d < dmax - dbase; d++) {
-                       if (!isset(bmap, dbase+d)) {
+                       if (!isset(bmap, dbase + d)) {
                                setbit(cgrp.cg_free, d);
                                cgrp.cg_cs.cs_nffree++;
                        } else
                                clrbit(cgrp.cg_free, d);
                }
                                setbit(cgrp.cg_free, d);
                                cgrp.cg_cs.cs_nffree++;
                        } else
                                clrbit(cgrp.cg_free, d);
                }
+               for (; d % sblock.fs_frag != 0; d++)
+                       clrbit(cgrp.cg_free, d);
                if (j != d) {
                if (j != d) {
-                       blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) &
-                              (0xff >> (NBBY - sblock.fs_frag)));
+                       blk = blkmap(&sblock, cgrp.cg_free, j);
                        fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                }
                        fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                }
-               for (; d < MAXBPG(&sblock); d++)
-                       clrbit(cgrp.cg_free, d);
+               for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
+                       clrblock(&sblock, cgrp.cg_free, d);
                sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
                sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
                sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
                sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
                *cs = cgrp.cg_cs;
                sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
                sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
                sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
                sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
                *cs = cgrp.cg_cs;
-               bwrite(fsbtodb(&sblock, cgtod(c, &sblock)), &cgrp,
+               bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp,
                        sblock.fs_cgsize);
        }
                        sblock.fs_cgsize);
        }
-       for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) {
-               bwrite(fsbtodb(&sblock,
-                   sblock.fs_csaddr + (i * sblock.fs_frag)),
-                   (char *)sblock.fs_csp[i], sblock.fs_bsize);
+       for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
+               bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
+                   (char *)sblock.fs_csp[j],
+                   sblock.fs_cssize - i < sblock.fs_bsize ?
+                   sblock.fs_cssize - i : sblock.fs_bsize);
        }
        sblock.fs_ronly = 0;
        sblock.fs_fmod = 0;
        }
        sblock.fs_ronly = 0;
        sblock.fs_fmod = 0;
-       bwrite(SBLOCK, (char *)&sblock, MAXBSIZE);
+       bwrite(SBLOCK, (char *)&sblock, SBSIZE);
 }
 
 /*
 }
 
 /*
@@ -539,7 +586,7 @@ fragacct(fs, fragmap, fraglist, cnt)
        inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
        fragmap <<= 1;
        for (siz = 1; siz < fs->fs_frag; siz++) {
        inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
        fragmap <<= 1;
        for (siz = 1; siz < fs->fs_frag; siz++) {
-               if (((1 << siz) & inblk) == 0)
+               if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
                        continue;
                field = around[siz];
                subfield = inside[siz];
                        continue;
                field = around[siz];
                subfield = inside[siz];
@@ -560,9 +607,9 @@ getsb(fs, file)
        register struct fs *fs;
        char *file;
 {
        register struct fs *fs;
        char *file;
 {
-       int i;
+       int i, j, size;
 
 
-       if (bread(SBLOCK, fs, MAXBSIZE)) {
+       if (bread(SBLOCK, fs, SBSIZE)) {
                printf("bad super block");
                perror(file);
                nerror |= 04;
                printf("bad super block");
                perror(file);
                nerror |= 04;
@@ -573,10 +620,12 @@ getsb(fs, file)
                nerror |= 04;
                return;
        }
                nerror |= 04;
                return;
        }
-       for (i = 0; i < howmany(fs->fs_cssize, fs->fs_bsize); i++) {
-               fs->fs_csp[i] = (struct csum *)calloc(1, fs->fs_bsize);
-               bread(fsbtodb(fs, fs->fs_csaddr + (i * fs->fs_frag)),
-                     (char *)fs->fs_csp[i], fs->fs_bsize);
+       for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
+               size = sblock.fs_cssize - i < sblock.fs_bsize ?
+                   sblock.fs_cssize - i : sblock.fs_bsize;
+               sblock.fs_csp[j] = (struct csum *)calloc(1, size);
+               bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
+                     (char *)fs->fs_csp[j], size);
        }
 }
 
        }
 }
 
@@ -616,9 +665,8 @@ bread(bno, buf, cnt)
 }
 
 /*
 }
 
 /*
- * block operations
+ * check if a block is available
  */
  */
-
 isblock(fs, cp, h)
        struct fs *fs;
        unsigned char *cp;
 isblock(fs, cp, h)
        struct fs *fs;
        unsigned char *cp;
@@ -639,11 +687,49 @@ isblock(fs, cp, h)
                mask = 0x01 << (h & 0x7);
                return ((cp[h >> 3] & mask) == mask);
        default:
                mask = 0x01 << (h & 0x7);
                return ((cp[h >> 3] & mask) == mask);
        default:
+#ifdef STANDALONE
+               printf("isblock bad fs_frag %d\n", fs->fs_frag);
+#else
                fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
                fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
+#endif
                return;
        }
 }
 
                return;
        }
 }
 
+/*
+ * take a block out of the map
+ */
+clrblock(fs, cp, h)
+       struct fs *fs;
+       unsigned char *cp;
+       int h;
+{
+       switch ((fs)->fs_frag) {
+       case 8:
+               cp[h] = 0;
+               return;
+       case 4:
+               cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
+               return;
+       case 2:
+               cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
+               return;
+       case 1:
+               cp[h >> 3] &= ~(0x01 << (h & 0x7));
+               return;
+       default:
+#ifdef STANDALONE
+               printf("clrblock bad fs_frag %d\n", fs->fs_frag);
+#else
+               fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
+#endif
+               return;
+       }
+}
+
+/*
+ * put a block into the map
+ */
 setblock(fs, cp, h)
        struct fs *fs;
        unsigned char *cp;
 setblock(fs, cp, h)
        struct fs *fs;
        unsigned char *cp;
@@ -663,7 +749,118 @@ setblock(fs, cp, h)
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
+#ifdef STANDALONE
+               printf("setblock bad fs_frag %d\n", fs->fs_frag);
+#else
                fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
                fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
+#endif
                return;
        }
 }
                return;
        }
 }
+
+/*     tables.c        4.1     82/03/25        */
+
+/* merged into kernel: tables.c 2.1 3/25/82 */
+
+/* last monet version: partab.c        4.2     81/03/08        */
+
+/*
+ * bit patterns for identifying fragments in the block map
+ * used as ((map & around) == inside)
+ */
+int around[9] = {
+       0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
+};
+int inside[9] = {
+       0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
+};
+
+/*
+ * given a block map bit pattern, the frag tables tell whether a
+ * particular size fragment is available. 
+ *
+ * used as:
+ * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
+ *     at least one fragment of the indicated size is available
+ * }
+ *
+ * These tables are used by the scanc instruction on the VAX to
+ * quickly find an appropriate fragment.
+ */
+
+unsigned char fragtbl124[256] = {
+       0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
+       0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
+       0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
+       0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
+       0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
+       0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
+       0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
+       0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
+       0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
+       0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
+       0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
+       0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
+};
+
+unsigned char fragtbl8[256] = {
+       0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
+       0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
+       0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
+       0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
+       0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
+       0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
+       0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
+       0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
+       0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
+       0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
+       0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
+       0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
+       0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
+       0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
+       0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
+       0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
+       0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
+       0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
+       0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
+       0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
+};
+
+/*
+ * the actual fragtbl array
+ */
+unsigned char *fragtbl[MAXFRAG + 1] = {
+       0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
+};