add xref to fsdb(8)
[unix-history] / usr / src / sbin / fsck / utilities.c
index 2312eb9..a2140c3 100644 (file)
@@ -1,6 +1,12 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)utilities.c       3.7 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)utilities.c        5.10 (Berkeley) %G%";
+#endif not lint
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -36,15 +42,16 @@ reply(s)
        char *s;
 {
        char line[80];
        char *s;
 {
        char line[80];
+       int cont = (strcmp(s, "CONTINUE") == 0);
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
        printf("\n%s? ", s);
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
        printf("\n%s? ", s);
-       if (nflag || dfile.wfdes < 0) {
+       if (!cont && (nflag || dfile.wfdes < 0)) {
                printf(" no\n\n");
                return (0);
        }
                printf(" no\n\n");
                return (0);
        }
-       if (yflag) {
+       if (yflag || (cont && nflag)) {
                printf(" yes\n\n");
                return (1);
        }
                printf(" yes\n\n");
                return (1);
        }
@@ -105,7 +112,9 @@ flush(fcp, bp)
        if (!bp->b_dirty)
                return;
        if (bp->b_errs != 0)
        if (!bp->b_dirty)
                return;
        if (bp->b_errs != 0)
-               pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno);
+               pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
+                   (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
+                   bp->b_bno);
        bp->b_dirty = 0;
        bp->b_errs = 0;
        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
        bp->b_dirty = 0;
        bp->b_errs = 0;
        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
@@ -136,8 +145,9 @@ ckfini()
 
        flush(&dfile, &fileblk);
        flush(&dfile, &sblk);
 
        flush(&dfile, &fileblk);
        flush(&dfile, &sblk);
-       if (sblk.b_bno != SBLOCK) {
-               sblk.b_bno = SBLOCK;
+       if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
+           !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
+               sblk.b_bno = SBOFF / dev_bsize;
                sbdirty();
                flush(&dfile, &sblk);
        }
                sbdirty();
                flush(&dfile, &sblk);
        }
@@ -156,19 +166,25 @@ bread(fcp, buf, blk, size)
        char *cp;
        int i, errs;
 
        char *cp;
        int i, errs;
 
-       if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
                return (0);
        rwerr("READ", blk);
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
                return (0);
        rwerr("READ", blk);
-       if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        errs = 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);
+       bzero(buf, size);
+       printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
+       for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
+               if (read(fcp->rfdes, cp, secsize) < 0) {
+                       lseek(fcp->rfdes, blk * dev_bsize + i + secsize, 0);
+                       if (secsize != dev_bsize && dev_bsize != 1)
+                               printf(" %d (%d),",
+                                   (blk * dev_bsize + i) / secsize,
+                                   blk + i / dev_bsize);
+                       else
+                               printf(" %d,", blk + i / dev_bsize);
                        errs++;
                }
        }
                        errs++;
                }
        }
@@ -187,19 +203,21 @@ bwrite(fcp, buf, blk, size)
 
        if (fcp->wfdes < 0)
                return;
 
        if (fcp->wfdes < 0)
                return;
-       if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
                return;
        }
        rwerr("WRITE", blk);
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
                return;
        }
        rwerr("WRITE", blk);
-       if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
                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("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) {
+                       lseek(fcp->rfdes, blk * dev_bsize + i + dev_bsize, 0);
+                       printf(" %d,", blk + i / dev_bsize);
+               }
        printf("\n");
        return;
 }
        printf("\n");
        return;
 }
@@ -267,7 +285,7 @@ getpathname(namebuf, curdir, ino)
        bzero(&idesc, sizeof(struct inodesc));
        idesc.id_type = DATA;
        cp = &namebuf[BUFSIZ - 1];
        bzero(&idesc, sizeof(struct inodesc));
        idesc.id_type = DATA;
        cp = &namebuf[BUFSIZ - 1];
-       *cp-- = '\0';
+       *cp = '\0';
        if (curdir != ino) {
                idesc.id_parent = curdir;
                goto namelookup;
        if (curdir != ino) {
                idesc.id_parent = curdir;
                goto namelookup;
@@ -276,14 +294,14 @@ getpathname(namebuf, curdir, ino)
                idesc.id_number = ino;
                idesc.id_func = findino;
                idesc.id_name = "..";
                idesc.id_number = ino;
                idesc.id_func = findino;
                idesc.id_name = "..";
-               if ((ckinode(ginode(ino), &idesc) & STOP) == 0)
+               if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
                        break;
        namelookup:
                idesc.id_number = idesc.id_parent;
                idesc.id_parent = ino;
                idesc.id_func = findname;
                idesc.id_name = namebuf;
                        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)
+               if ((ckinode(ginode(idesc.id_number), &idesc) & FOUND) == 0)
                        break;
                len = strlen(namebuf);
                cp -= len;
                        break;
                len = strlen(namebuf);
                cp -= len;
@@ -307,6 +325,32 @@ catch()
        exit(12);
 }
 
        exit(12);
 }
 
+/*
+ * When preening, allow a single quit to signal
+ * a special exit after filesystem checks complete
+ * so that reboot sequence may be interrupted.
+ */
+catchquit()
+{
+       extern returntosingle;
+
+       printf("returning to single-user after filesystem check\n");
+       returntosingle = 1;
+       (void)signal(SIGQUIT, SIG_DFL);
+}
+
+/*
+ * Ignore a single quit signal; wait and flush just in case.
+ * Used by child processes in preen.
+ */
+voidquit()
+{
+
+       sleep(1);
+       (void)signal(SIGQUIT, SIG_IGN);
+       (void)signal(SIGQUIT, SIG_DFL);
+}
+
 /*
  * determine whether an inode should be fixed.
  */
 /*
  * determine whether an inode should be fixed.
  */