- ckfini();
- sync();
- if (dfile.mod && hotroot) {
- printf("\n***** BOOT UNIX (NO SYNC!) *****\n");
- exit(4);
- }
- if (dfile.mod && preen == 0)
- printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
- free(blkmap);
- free(freemap);
- free(statemap);
- free(lncntp);
-}
-
-/* VARARGS1 */
-error(s1, s2, s3, s4)
- char *s1;
-{
-
- printf(s1, s2, s3, s4);
-}
-
-/* VARARGS1 */
-errexit(s1, s2, s3, s4)
- char *s1;
-{
- error(s1, s2, s3, s4);
- exit(8);
-}
-
-/*
- * An inconsistency occured which shouldn't during normal operations.
- * Die if preening, otw just printf.
- */
-/* VARARGS1 */
-pfatal(s, a1, a2, a3)
- char *s;
-{
-
- if (preen) {
- printf("%s: ", devname);
- printf(s, a1, a2, a3);
- printf("\n");
- preendie();
- }
- printf(s, a1, a2, a3);
-}
-
-preendie()
-{
-
- printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
- exit(8);
-}
-
-/*
- * Pwarn is like printf when not preening,
- * or a warning (preceded by filename) when preening.
- */
-/* VARARGS1 */
-pwarn(s, a1, a2, a3, a4, a5)
- char *s;
-{
-
- if (preen)
- printf("%s: ", devname);
- printf(s, a1, a2, a3, a4, a5);
-}
-
-ckinode(dp, flg)
- DINODE *dp;
- register flg;
-{
- register daddr_t *ap;
- register ret;
- int (*func)(), n, ndb, size, offset;
-
- if (SPECIAL)
- return (KEEPON);
- func = (flg == ADDR) ? pfunc : dirscan;
- ndb = howmany(dp->di_size, sblock.fs_bsize);
- for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) {
- if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0)
- size = numfrags(&sblock, fragroundup(&sblock, offset));
- else
- size = sblock.fs_frag;
- if (*ap && (ret = (*func)(*ap, size)) & STOP)
- return (ret);
- }
- for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) {
- if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - sblock.fs_bsize * NDADDR)) & 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)) /* 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);
-}
-
-pass1(blk, size)
- daddr_t blk;
- int size;
-{
- register daddr_t *dlp;
- int res = KEEPON;
-
- for (; size > 0; blk++, size--) {
- if (outrange(blk)) {
- blkerr("BAD", blk);
- if (++badblk >= MAXBAD) {
- printf("EXCESSIVE BAD BLKS I=%u", inum);
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- res = SKIP;
- } else if (getbmap(blk)) {
- blkerr("DUP", blk);
- if (++dupblk >= MAXDUP) {
- printf("EXCESSIVE DUP BLKS I=%u", inum);
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- if (enddup >= &duplist[DUPTBLSIZE]) {
- printf("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(blk, size)
- daddr_t blk;
- int size;
-{
- register daddr_t *dlp;
- int res = KEEPON;
-
- for (; size > 0; blk++, size--) {
- if (outrange(blk))
- 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(dirp)
- register DIRECT *dirp;
-{
- register char *p;
- register n;
- DINODE *dp;
-
- if ((inum = dirp->d_ino) == 0)
- return (KEEPON);
- thisname = pathp;
- 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 (getstate()) {
- case USTATE:
- n = direrr("UNALLOCATED");
- break;
-
- case CLEAR:
- if ((n = direrr("DUP/BAD")) == 1)
- break;
- if ((dp = ginode()) == NULL)
- break;
- setstate(DIRCT ? DSTATE : FSTATE);
- goto again;
-
- case FSTATE:
- declncnt();
- break;
-
- case DSTATE:
- declncnt();
- descend();
- break;
- }
- }
- pathp = thisname;
- if (n == 0)
- return (KEEPON);
- dirp->d_ino = 0;
- return (KEEPON|ALTERD);
-}
-
-pass4(blk, size)
- daddr_t blk;
-{
- register daddr_t *dlp;
- int res = KEEPON;
-
- for (; size > 0; blk++, size--) {
- if (outrange(blk))
- res = SKIP;
- else if (getbmap(blk)) {
- for (dlp = duplist; dlp < enddup; dlp++)
- if (*dlp == blk) {
- *dlp = *--enddup;
- return (KEEPON);
- }
- clrbmap(blk);
- n_blks--;
- }
- }
- return (res);
-}
-
-pass5(blk, size)
- daddr_t blk;
- int size;
-{
- int res = KEEPON;
-
- for (; size > 0; blk++, size--) {
- if (outrange(blk)) {
- 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);
- }
- } else if (getfmap(blk)) {
- fixcg = 1;
- if (++dupblk >= DUPTBLSIZE) {
- printf("EXCESSIVE DUP BLKS IN BIT MAPS.");
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- } else {
- n_ffree++;
- setfmap(blk);
- }
- }
- return (res);
-}
-
-outrange(blk)
- daddr_t blk;
-{
- register int c;
-
- c = dtog(&sblock, blk);
- if (blk >= fmax || blk < cgdmin(&sblock, c)) {
- return (1);
- }
- return (0);
-}
-
-blkerr(s, blk)
- daddr_t blk;
- char *s;
-{
- pfatal("%ld %s I=%u", blk, s, inum);
- printf("\n");
- setstate(CLEAR); /* mark for possible clearing */
-}
-
-descend()
-{
- register DINODE *dp;
- register char *savname;
- off_t savsize;
-
- setstate(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;
-};
-
-dirscan(blk, nf)
- daddr_t blk;
- int nf;
-{
- register DIRECT *dp;
- struct dirstuff dirp;
- int blksiz, dsize, n;
- char dbuf[DIRBLKSIZ];
-
- if (outrange(blk)) {
- filsize -= sblock.fs_bsize;
- return (SKIP);
- }
- blksiz = nf * sblock.fs_fsize;
- dirp.loc = 0;
- dirp.blkno = blk;
- dirp.blksiz = blksiz;
- for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
- dsize = dp->d_reclen;
- copy(dp, dbuf, dsize);
- if ((n = (*pfunc)(dbuf)) & ALTERD) {
- if (getblk(&fileblk, blk, blksiz) != NULL) {
- copy(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;
-
- if (getblk(&fileblk, dirp->blkno, dirp->blksiz) == NULL) {
- filsize -= dirp->blksiz - dirp->loc;
- return NULL;
- }
- for (;;) {
- 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 (dirp->loc < dirp->blksiz &&
- (ndp->d_ino > imax || ndp->d_namlen > MAXNAMLEN ||
- ndp->d_reclen <= 0 ||
- ndp->d_reclen > DIRBLKSIZ - (dirp->loc % DIRBLKSIZ))) {
- pwarn("DIRECTORY CORRUPTED");
- if (preen)
- printf(" (SALVAGED)\n");
- else if (reply("SALVAGE") == 0) {
- dirp->loc +=
- DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
- filsize -= DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
- return(dp);
- }
- dirp->loc -= dp->d_reclen;
- filsize += dp->d_reclen;
- dp->d_reclen = DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
- dirty(&fileblk);
- continue;
- }
- 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 = pass4;
- ckinode(dp, ADDR);
- zapino(dp);
- setstate(USTATE);
- inodirty();
- inosumbad++;
- }
-}
-
-setup(dev)
- char *dev;
-{
- dev_t rootdev;
- struct ostat statb;
- int super = bflag ? bflag : SBLOCK;
-
- bflag = 0;
- if (stat("/", &statb) < 0)
- errexit("Can't stat root\n");
- rootdev = statb.st_dev;
- if (stat(dev, &statb) < 0) {
- error("Can't stat %s\n", dev);
- return (0);
- }
- rawflg = 0;
- if ((statb.st_mode & S_IFMT) == S_IFBLK)
- ;
- else if ((statb.st_mode & S_IFMT) == S_IFCHR)
- rawflg++;
- else {
- if (reply("file is not a block or character device; OK") == 0)
- return (0);
- }
- if (rootdev == statb.st_rdev)
- hotroot++;
- if ((dfile.rfdes = open(dev, 0)) < 0) {
- error("Can't open %s\n", dev);
- return (0);
- }
- if (preen == 0)
- printf("** %s", dev);
- if (nflag || (dfile.wfdes = open(dev, 1)) < 0) {
- dfile.wfdes = -1;
- if (preen)
- pfatal("NO WRITE ACCESS");
- printf(" (NO WRITE)");