date and time created 85/06/03 17:31:54 by mckusick
[unix-history] / usr / src / sbin / fsck / utilities.c
index 4163a98..2312eb9 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)utilities.c       3.1 (Berkeley) %G%";
+static char version[] = "@(#)utilities.c       3.7 (Berkeley) %G%";
 #endif
 
 #include <stdio.h>
 #endif
 
 #include <stdio.h>
@@ -7,6 +7,7 @@ static char version[] = "@(#)utilities.c        3.1 (Berkeley) %G%";
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
+#include <sys/dir.h>
 #include "fsck.h"
 
 long   lseek();
 #include "fsck.h"
 
 long   lseek();
@@ -38,7 +39,6 @@ reply(s)
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
-       rplyflag = 1;
        printf("\n%s? ", s);
        if (nflag || dfile.wfdes < 0) {
                printf(" no\n\n");
        printf("\n%s? ", s);
        if (nflag || dfile.wfdes < 0) {
                printf(" no\n\n");
@@ -90,23 +90,33 @@ getblk(bp, blk, size)
        if (bp->b_bno == dblk)
                return (bp);
        flush(fcp, bp);
        if (bp->b_bno == dblk)
                return (bp);
        flush(fcp, bp);
-       if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) {
-               bp->b_bno = dblk;
-               bp->b_size = size;
-               return (bp);
-       }
-       bp->b_bno = (daddr_t)-1;
-       return (NULL);
+       bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size);
+       bp->b_bno = dblk;
+       bp->b_size = size;
+       return (bp);
 }
 
 flush(fcp, bp)
        struct filecntl *fcp;
        register BUFAREA *bp;
 {
 }
 
 flush(fcp, bp)
        struct filecntl *fcp;
        register BUFAREA *bp;
 {
+       register int i, j;
 
 
-       if (bp->b_dirty)
-               (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
+       if (!bp->b_dirty)
+               return;
+       if (bp->b_errs != 0)
+               pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno);
        bp->b_dirty = 0;
        bp->b_dirty = 0;
+       bp->b_errs = 0;
+       bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
+       if (bp != &sblk)
+               return;
+       for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
+               bwrite(&dfile, (char *)sblock.fs_csp[j],
+                   fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
+                   sblock.fs_cssize - i < sblock.fs_bsize ?
+                   sblock.fs_cssize - i : sblock.fs_bsize);
+       }
 }
 
 rwerr(s, blk)
 }
 
 rwerr(s, blk)
@@ -132,6 +142,7 @@ ckfini()
                flush(&dfile, &sblk);
        }
        flush(&dfile, &inoblk);
                flush(&dfile, &sblk);
        }
        flush(&dfile, &inoblk);
+       flush(&dfile, &cgblk);
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }
@@ -142,12 +153,27 @@ bread(fcp, buf, blk, size)
        daddr_t blk;
        long size;
 {
        daddr_t blk;
        long size;
 {
+       char *cp;
+       int i, errs;
+
        if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
        if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
-               return (1);
+               return (0);
        rwerr("READ", blk);
        rwerr("READ", blk);
-       return (0);
+       if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
+               rwerr("SEEK", blk);
+       errs = 0;
+       pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:");
+       for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) {
+               if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) {
+                       printf(" %d,", blk + i / DEV_BSIZE);
+                       bzero(cp, DEV_BSIZE);
+                       errs++;
+               }
+       }
+       printf("\n");
+       return (errs);
 }
 
 bwrite(fcp, buf, blk, size)
 }
 
 bwrite(fcp, buf, blk, size)
@@ -156,19 +182,124 @@ bwrite(fcp, buf, blk, size)
        daddr_t blk;
        long size;
 {
        daddr_t blk;
        long size;
 {
+       int i;
+       char *cp;
 
        if (fcp->wfdes < 0)
 
        if (fcp->wfdes < 0)
-               return (0);
+               return;
        if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
        if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
-               return (1);
+               return;
        }
        rwerr("WRITE", blk);
        }
        rwerr("WRITE", blk);
+       if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
+               rwerr("SEEK", blk);
+       pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
+       for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE)
+               if (write(fcp->wfdes, cp, DEV_BSIZE) < 0)
+                       printf(" %d,", blk + i / DEV_BSIZE);
+       printf("\n");
+       return;
+}
+
+/*
+ * allocate a data block with the specified number of fragments
+ */
+allocblk(frags)
+       int frags;
+{
+       register int i, j, k;
+
+       if (frags <= 0 || frags > sblock.fs_frag)
+               return (0);
+       for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
+               for (j = 0; j <= sblock.fs_frag - frags; j++) {
+                       if (getbmap(i + j))
+                               continue;
+                       for (k = 1; k < frags; k++)
+                               if (getbmap(i + j + k))
+                                       break;
+                       if (k < frags) {
+                               j += k;
+                               continue;
+                       }
+                       for (k = 0; k < frags; k++)
+                               setbmap(i + j + k);
+                       n_blks += frags;
+                       return (i + j);
+               }
+       }
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Free a previously allocated block
+ */
+freeblk(blkno, frags)
+       daddr_t blkno;
+       int frags;
+{
+       struct inodesc idesc;
+
+       idesc.id_blkno = blkno;
+       idesc.id_numfrags = frags;
+       pass4check(&idesc);
+}
+
+/*
+ * Find a pathname
+ */
+getpathname(namebuf, curdir, ino)
+       char *namebuf;
+       ino_t curdir, ino;
+{
+       int len;
+       register char *cp;
+       struct inodesc idesc;
+       extern int findname();
+
+       if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) {
+               strcpy(namebuf, "?");
+               return;
+       }
+       bzero(&idesc, sizeof(struct inodesc));
+       idesc.id_type = DATA;
+       cp = &namebuf[BUFSIZ - 1];
+       *cp-- = '\0';
+       if (curdir != ino) {
+               idesc.id_parent = curdir;
+               goto namelookup;
+       }
+       while (ino != ROOTINO) {
+               idesc.id_number = ino;
+               idesc.id_func = findino;
+               idesc.id_name = "..";
+               if ((ckinode(ginode(ino), &idesc) & STOP) == 0)
+                       break;
+       namelookup:
+               idesc.id_number = idesc.id_parent;
+               idesc.id_parent = ino;
+               idesc.id_func = findname;
+               idesc.id_name = namebuf;
+               if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0)
+                       break;
+               len = strlen(namebuf);
+               cp -= len;
+               if (cp < &namebuf[MAXNAMLEN])
+                       break;
+               bcopy(namebuf, cp, len);
+               *--cp = '/';
+               ino = idesc.id_number;
+       }
+       if (ino != ROOTINO) {
+               strcpy(namebuf, "?");
+               return;
+       }
+       bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp);
+}
+
 catch()
 {
 
 catch()
 {
 
@@ -179,14 +310,23 @@ catch()
 /*
  * determine whether an inode should be fixed.
  */
 /*
  * determine whether an inode should be fixed.
  */
-dofix(idesc)
+dofix(idesc, msg)
        register struct inodesc *idesc;
        register struct inodesc *idesc;
+       char *msg;
 {
 
        switch (idesc->id_fix) {
 
        case DONTKNOW:
 {
 
        switch (idesc->id_fix) {
 
        case DONTKNOW:
-               direrr(idesc->id_number, "DIRECTORY CORRUPTED");
+               if (idesc->id_type == DATA)
+                       direrr(idesc->id_number, msg);
+               else
+                       pwarn(msg);
+               if (preen) {
+                       printf(" (SALVAGED)\n");
+                       idesc->id_fix = FIX;
+                       return (ALTERED);
+               }
                if (reply("SALVAGE") == 0) {
                        idesc->id_fix = NOFIX;
                        return (0);
                if (reply("SALVAGE") == 0) {
                        idesc->id_fix = NOFIX;
                        return (0);
@@ -206,19 +346,11 @@ dofix(idesc)
        /* NOTREACHED */
 }
 
        /* NOTREACHED */
 }
 
-/* VARARGS1 */
-error(s1, s2, s3, s4)
-       char *s1;
-{
-
-       printf(s1, s2, s3, s4);
-}
-
 /* VARARGS1 */
 errexit(s1, s2, s3, s4)
        char *s1;
 {
 /* VARARGS1 */
 errexit(s1, s2, s3, s4)
        char *s1;
 {
-       error(s1, s2, s3, s4);
+       printf(s1, s2, s3, s4);
        exit(8);
 }
 
        exit(8);
 }
 
@@ -235,18 +367,13 @@ pfatal(s, a1, a2, a3)
                printf("%s: ", devname);
                printf(s, a1, a2, a3);
                printf("\n");
                printf("%s: ", devname);
                printf(s, a1, a2, a3);
                printf("\n");
-               preendie();
+               printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
+                       devname);
+               exit(8);
        }
        printf(s, a1, a2, a3);
 }
 
        }
        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.
 /*
  * Pwarn is like printf when not preening,
  * or a warning (preceded by filename) when preening.
@@ -269,7 +396,7 @@ panic(s)
        char *s;
 {
 
        char *s;
 {
 
-       pfatal("INTERNAL INCONSISTENCY: %s\n", s);
-       exit(12);
+       pfatal("INTERNAL INCONSISTENCY:");
+       errexit(s);
 }
 #endif
 }
 #endif