- n_bad += cgtod(&sblock, c) - cgsblock(&sblock, 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);
- }
- for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
- blk = blkmap(&sblock, cgrp.cg_free, b);
- if (blk == 0)
- continue;
- if (blk == blockbits) {
- if (pass5check(cbase+b, sblock.fs_frag) == STOP)
- goto out5;
- /* this is clumsy ... */
- n_ffree -= sblock.fs_frag;
- n_bfree++;
- botot[cbtocylno(&sblock, b)]++;
- bo[cbtocylno(&sblock, b)]
- [cbtorpos(&sblock, b)]++;
- continue;
- }
- for (d = 0; d < sblock.fs_frag; d++)
- if ((blk & (1<<d)) &&
- pass5check(cbase+b+d,1) == STOP)
- goto out5;
- fragacct(&sblock, blk, frsum, 1);
- }
- if (bcmp(cgrp.cg_frsum, frsum, sizeof (frsum))) {
- if (debug)
- for (i = 0; i < sblock.fs_frag; i++)
- if (cgrp.cg_frsum[i] != frsum[i])
- printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
- c, i, cgrp.cg_frsum[i], frsum[i]);
- frsumbad++;
- }
- if (bcmp(cgrp.cg_btot, botot, sizeof (botot))) {
- if (debug)
- for (n = 0; n < sblock.fs_cpg; n++)
- if (botot[n] != cgrp.cg_btot[n])
- printf("cg[%d].cg_btot[%d] have %d calc %d\n",
- c, n, cgrp.cg_btot[n], botot[n]);
- offsumbad++;
- }
- if (bcmp(cgrp.cg_b, bo, sizeof (bo))) {
- if (debug)
- for (i = 0; i < NRPOS; i++)
- if (bo[n][i] != cgrp.cg_b[n][i])
- printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
- c, n, i, cgrp.cg_b[n][i], bo[n][i]);
- offsumbad++;
- }
- }
-out5:
- if (dupblk)
- pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk);
- if (fixcg == 0) {
- if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) {
- pwarn("%ld BLK(S) MISSING\n", fmax - b);
- fixcg = 1;
- } else if (inosumbad + offsumbad + frsumbad + sbsumbad) {
- pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n",
- inosumbad ? "(INODE FREE) " : "",
- offsumbad ? "(BLOCK OFFSETS) " : "",
- frsumbad ? "(FRAG SUMMARIES) " : "",
- sbsumbad ? "(SUPER BLOCK SUMMARIES) " : "");
- fixcg = 1;
- } else if (n_ffree != sblock.fs_cstotal.cs_nffree ||
- n_bfree != sblock.fs_cstotal.cs_nbfree) {
- pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- sblock.fs_cstotal.cs_nffree = n_ffree;
- sblock.fs_cstotal.cs_nbfree = n_bfree;
- sbdirty();
- }
- }
- }
- if (fixcg) {
- pwarn("BAD CYLINDER GROUPS");
- if (preen)
- printf(" (SALVAGED)\n");
- else if (reply("SALVAGE") == 0)
- fixcg = 0;
- }
-}
-
-pass5check(blk, size)
- daddr_t blk;
- int size;
-{
-
- if (outrange(blk, size)) {
- fixcg = 1;
- if (preen)
- pfatal("BAD BLOCKS IN BIT MAPS.");
- if (++badblk >= MAXBAD) {
- printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- }
- for (; size > 0; blk++, size--)
- if (getfmap(blk)) {
- fixcg = 1;
- ++dupblk;
- } else {
- n_ffree++;
- setfmap(blk);
- }
- return (KEEPON);
-}
-
-ckinode(dp, flg)
- DINODE *dp;
- register flg;
-{
- register daddr_t *ap;
- register ret;
- int (*func)(), n, ndb, size, offset;
- ino_t number = inum;
- DINODE dino;
-
- if (SPECIAL)
- return (KEEPON);
- dino = *dp;
- func = (flg == ADDR) ? pfunc : dirscan;
- ndb = howmany(dino.di_size, sblock.fs_bsize);
- for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
- if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
- size = numfrags(&sblock, fragroundup(&sblock, offset));
- else
- size = sblock.fs_frag;
- dnum = number;
- if (*ap && (ret = (*func)(*ap, size)) & STOP)
- return (ret);
- }
- for (ap = &dino.di_ib[0], n = 1; n <= 2; ap++, n++) {
- dnum = number;
- if (*ap) {
- ret = iblock(*ap, n, flg,
- dino.di_size - sblock.fs_bsize * NDADDR);
- if (ret & STOP)
- return (ret);
- }
- }
- return (KEEPON);
-}
-
-iblock(blk, ilevel, flg, isize)
- daddr_t blk;
- register ilevel;
- int isize;
-{
- register daddr_t *ap;
- register daddr_t *aplim;
- register int i, n;
- int (*func)(), nif;
- BUFAREA ib;
-
- if (flg == ADDR) {
- func = pfunc;
- if (((n = (*func)(blk, sblock.fs_frag)) & KEEPON) == 0)
- return (n);
- } else
- func = dirscan;
- if (outrange(blk, sblock.fs_frag)) /* protect thyself */
- return (SKIP);
- initbarea(&ib);
- if (getblk(&ib, blk, sblock.fs_bsize) == NULL)
- return (SKIP);
- ilevel--;
- if (ilevel == 0) {
- nif = lblkno(&sblock, isize) + 1;
- } else /* ilevel == 1 */ {
- nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1;
- }
- if (nif > NINDIR(&sblock))
- nif = NINDIR(&sblock);
- aplim = &ib.b_un.b_indir[nif];
- for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
- if (*ap) {
- if (ilevel > 0)
- n = iblock(*ap, ilevel, flg,
- isize - i*NINDIR(&sblock)*sblock.fs_bsize);
- else
- n = (*func)(*ap, sblock.fs_frag);
- if (n & STOP)
- return (n);
- }
- return (KEEPON);
-}
-
-outrange(blk, cnt)
- daddr_t blk;
- int cnt;
-{
- register int c;
-
- if ((unsigned)(blk+cnt) > fmax)
- return (1);
- c = dtog(&sblock, blk);
- if (blk < cgdmin(&sblock, c)) {
- if ((blk+cnt) > cgsblock(&sblock, c)) {
- if (debug) {
- printf("blk %d < cgdmin %d;",
- blk, cgdmin(&sblock, c));
- printf(" blk+cnt %d > cgsbase %d\n",
- blk+cnt, cgsblock(&sblock, c));
- }
- return (1);
- }
- } else {
- if ((blk+cnt) > cgbase(&sblock, c+1)) {
- if (debug) {
- printf("blk %d >= cgdmin %d;",
- blk, cgdmin(&sblock, c));
- printf(" blk+cnt %d > sblock.fs_fpg %d\n",
- blk+cnt, sblock.fs_fpg);
- }
- return (1);
- }
- }
- return (0);
-}
-
-blkerr(s, blk)
- daddr_t blk;
- char *s;
-{
-
- pfatal("%ld %s I=%u", blk, s, inum);
- printf("\n");
- statemap[inum] = CLEAR;
-}
-
-descend()
-{
- register DINODE *dp;
- register char *savname;
- off_t savsize;
-
- statemap[inum] = FSTATE;
- if ((dp = ginode()) == NULL)
- return;
- savname = thisname;
- *pathp++ = '/';
- savsize = filsize;
- filsize = dp->di_size;
- ckinode(dp, DATA);
- thisname = savname;
- *--pathp = 0;
- filsize = savsize;
-}
-
-struct dirstuff {
- int loc;
- int blkno;
- int blksiz;
- ino_t number;
- enum {DONTKNOW, NOFIX, FIX} fix;
-};
-
-dirscan(blk, nf)
- daddr_t blk;
- int nf;
-{
- register DIRECT *dp;
- struct dirstuff dirp;
- int blksiz, dsize, n;
- char dbuf[DIRBLKSIZ];
-
- if (outrange(blk, 1)) {
- filsize -= sblock.fs_bsize;
- return (SKIP);
- }
- blksiz = nf * sblock.fs_fsize;
- dirp.loc = 0;
- dirp.blkno = blk;
- dirp.blksiz = blksiz;
- if (dirp.number != dnum) {
- dirp.number = dnum;
- dirp.fix = DONTKNOW;
- }
- for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
- dsize = dp->d_reclen;
- bcopy(dp, dbuf, dsize);
- if ((n = (*pfunc)(dbuf)) & ALTERD) {
- if (getblk(&fileblk, blk, blksiz) != NULL) {
- bcopy(dbuf, dp, dsize);
- dirty(&fileblk);
- sbdirty();
- } else
- n &= ~ALTERD;
- }
- if (n & STOP)
- return (n);
- }
- return (filsize > 0 ? KEEPON : STOP);
-}
-
-/*
- * get next entry in a directory.
- */
-DIRECT *
-readdir(dirp)
- register struct dirstuff *dirp;
-{
- register DIRECT *dp, *ndp;
- long size;
-
- if (getblk(&fileblk, dirp->blkno, dirp->blksiz) == NULL) {
- filsize -= dirp->blksiz - dirp->loc;
- return NULL;
- }
- while (dirp->loc % DIRBLKSIZ == 0 && filsize > 0 &&
- dirp->loc < dirp->blksiz) {
- dp = (DIRECT *)(dirblk.b_buf + dirp->loc);
- if (dp->d_ino < imax &&
- dp->d_namlen <= MAXNAMLEN && dp->d_namlen >= 0 &&
- dp->d_reclen > 0 && dp->d_reclen <= DIRBLKSIZ)
- break;
- dirp->loc += DIRBLKSIZ;
- filsize -= DIRBLKSIZ;
- if (dirp->fix == DONTKNOW) {
- pfatal("DIRECTORY %D CORRUPTED", dirp->number);
- dirp->fix = NOFIX;
- if (reply("SALVAGE") != 0)
- dirp->fix = FIX;
- }
- if (dirp->fix != FIX)
- continue;
- dp->d_reclen = DIRBLKSIZ;
- dp->d_ino = 0;
- dp->d_namlen = 0;
- dirty(&fileblk);
- }
- if (filsize <= 0 || dirp->loc >= dirp->blksiz)
- return NULL;
- dp = (DIRECT *)(dirblk.b_buf + dirp->loc);
- dirp->loc += dp->d_reclen;
- filsize -= dp->d_reclen;
- ndp = (DIRECT *)(dirblk.b_buf + dirp->loc);
- if ((filsize <= 0 && dirp->loc % DIRBLKSIZ != 0) ||
- (dirp->loc < dirp->blksiz && filsize > 0 &&
- (ndp->d_ino >= imax ||
- ndp->d_namlen > MAXNAMLEN || ndp->d_namlen < 0 ||
- ndp->d_reclen <= 0 ||
- ndp->d_reclen > DIRBLKSIZ - (dirp->loc % DIRBLKSIZ)))) {
- size = DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
- dirp->loc += size;
- filsize -= size;
- if (dirp->fix == DONTKNOW) {
- pfatal("DIRECTORY %D CORRUPTED", dirp->number);
- dirp->fix = NOFIX;
- if (reply("SALVAGE") != 0)
- dirp->fix = FIX;
- }
- if (dirp->fix == FIX) {
- dp->d_reclen += size;
- dirty(&fileblk);
- }
- }
- return (dp);
-}
-
-direrr(s)
- char *s;
-{
- register DINODE *dp;
-
- pwarn("%s ", s);
- pinode();
- printf("\n");
- if ((dp = ginode()) != NULL && ftypeok(dp))
- pfatal("%s=%s", DIRCT?"DIR":"FILE", pathname);
- else
- pfatal("NAME=%s", pathname);
- return (reply("REMOVE"));
-}
-
-adjust(lcnt)
- register short lcnt;
-{
- register DINODE *dp;
-
- if ((dp = ginode()) == NULL)
- return;
- if (dp->di_nlink == lcnt) {
- if (linkup() == 0)
- clri("UNREF", 0);
- }
- else {
- pwarn("LINK COUNT %s",
- (lfdir==inum)?lfname:(DIRCT?"DIR":"FILE"));
- pinode();
- printf(" COUNT %d SHOULD BE %d",
- dp->di_nlink, dp->di_nlink-lcnt);
- if (preen) {
- if (lcnt < 0) {
- printf("\n");
- preendie();
- }
- printf(" (ADJUSTED)\n");
- }
- if (preen || reply("ADJUST") == 1) {
- dp->di_nlink -= lcnt;
- inodirty();
- }
- }
-}
-
-clri(s, flg)
- char *s;
-{
- register DINODE *dp;
-
- if ((dp = ginode()) == NULL)
- return;
- if (flg == 1) {
- pwarn("%s %s", s, DIRCT?"DIR":"FILE");
- pinode();
- }
- if (preen || reply("CLEAR") == 1) {
- if (preen)
- printf(" (CLEARED)\n");
- n_files--;
- pfunc = pass4check;
- ckinode(dp, ADDR);
- zapino(dp);
- statemap[inum] = USTATE;
- inodirty();
- inosumbad++;
- }
-}
-
-badsb(s)
- char *s;
-{
-
- if (preen)
- printf("%s: ", devname);
- printf("BAD SUPER BLOCK: %s\n", s);
- pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n");
- pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n");
-}
-
-DINODE *
-ginode()
-{
- daddr_t iblk;
-
- if (inum < ROOTINO || inum > imax) {
- if (debug && (inum < 0 || inum > imax))
- printf("inum out of range (%d)\n", inum);
- return (NULL);
- }
- if (inum < startinum || inum >= startinum + INOPB(&sblock)) {
- iblk = itod(&sblock, inum);
- if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) {
- return (NULL);
- }
- startinum = (inum / INOPB(&sblock)) * INOPB(&sblock);