update for 4.3BSD version
[unix-history] / usr / src / sbin / fsck / pass2.c
index d5461eb..cab8b72 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[] = "@(#)pass2.c   3.2 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)pass2.c    5.2 (Berkeley) %G%";
+#endif not lint
 
 #include <sys/param.h>
 #include <sys/inode.h>
 
 #include <sys/param.h>
 #include <sys/inode.h>
@@ -24,16 +30,45 @@ pass2()
        switch (statemap[ROOTINO]) {
 
        case USTATE:
        switch (statemap[ROOTINO]) {
 
        case USTATE:
-               errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
+               pfatal("ROOT INODE UNALLOCATED");
+               if (reply("ALLOCATE") == 0)
+                       errexit("");
+               if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
+                       errexit("CANNOT ALLOCATE ROOT INODE\n");
+               descend(&rootdesc, ROOTINO);
+               break;
+
+       case DCLEAR:
+               pfatal("DUPS/BAD IN ROOT INODE");
+               if (reply("REALLOCATE")) {
+                       freeino(ROOTINO);
+                       if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
+                               errexit("CANNOT ALLOCATE ROOT INODE\n");
+                       descend(&rootdesc, ROOTINO);
+                       break;
+               }
+               if (reply("CONTINUE") == 0)
+                       errexit("");
+               statemap[ROOTINO] = DSTATE;
+               descend(&rootdesc, ROOTINO);
+               break;
 
        case FSTATE:
 
        case FSTATE:
+       case FCLEAR:
                pfatal("ROOT INODE NOT DIRECTORY");
                pfatal("ROOT INODE NOT DIRECTORY");
-               if (reply("FIX") == 0 || (dp = ginode(ROOTINO)) == NULL)
+               if (reply("REALLOCATE")) {
+                       freeino(ROOTINO);
+                       if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
+                               errexit("CANNOT ALLOCATE ROOT INODE\n");
+                       descend(&rootdesc, ROOTINO);
+                       break;
+               }
+               if (reply("FIX") == 0)
                        errexit("");
                        errexit("");
+               dp = ginode(ROOTINO);
                dp->di_mode &= ~IFMT;
                dp->di_mode |= IFDIR;
                inodirty();
                dp->di_mode &= ~IFMT;
                dp->di_mode |= IFDIR;
                inodirty();
-               inosumbad++;
                statemap[ROOTINO] = DSTATE;
                /* fall into ... */
 
                statemap[ROOTINO] = DSTATE;
                /* fall into ... */
 
@@ -41,13 +76,8 @@ pass2()
                descend(&rootdesc, ROOTINO);
                break;
 
                descend(&rootdesc, ROOTINO);
                break;
 
-       case CLEAR:
-               pfatal("DUPS/BAD IN ROOT INODE");
-               printf("\n");
-               if (reply("CONTINUE") == 0)
-                       errexit("");
-               statemap[ROOTINO] = DSTATE;
-               descend(&rootdesc, ROOTINO);
+       default:
+               errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
        }
 }
 
        }
 }
 
@@ -59,6 +89,7 @@ pass2check(idesc)
        int n, entrysize, ret = 0;
        DINODE *dp;
        DIRECT proto;
        int n, entrysize, ret = 0;
        DINODE *dp;
        DIRECT proto;
+       char namebuf[BUFSIZ];
 
        /* 
         * check for "."
 
        /* 
         * check for "."
@@ -183,28 +214,47 @@ again:
                        n = reply("REMOVE");
                        break;
 
                        n = reply("REMOVE");
                        break;
 
-               case CLEAR:
+               case DCLEAR:
+               case FCLEAR:
                        direrr(dirp->d_ino, "DUP/BAD");
                        if ((n = reply("REMOVE")) == 1)
                                break;
                        direrr(dirp->d_ino, "DUP/BAD");
                        if ((n = reply("REMOVE")) == 1)
                                break;
-                       if ((dp = ginode(dirp->d_ino)) == NULL)
-                               break;
+                       dp = ginode(dirp->d_ino);
                        statemap[dirp->d_ino] = DIRCT(dp) ? DSTATE : FSTATE;
                        goto again;
 
                        statemap[dirp->d_ino] = DIRCT(dp) ? DSTATE : FSTATE;
                        goto again;
 
+               case DFOUND:
+                       if (idesc->id_entryno > 2) {
+                               getpathname(namebuf, dirp->d_ino, dirp->d_ino);
+                               pwarn("%s %s %s\n", pathname,
+                                   "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
+                                   namebuf);
+                               if (preen)
+                                       printf(" (IGNORED)\n");
+                               else if ((n = reply("REMOVE")) == 1)
+                                       break;
+                       }
+                       /* fall through */
+
                case FSTATE:
                        lncntp[dirp->d_ino]--;
                        break;
 
                case DSTATE:
                        descend(idesc, dirp->d_ino);
                case FSTATE:
                        lncntp[dirp->d_ino]--;
                        break;
 
                case DSTATE:
                        descend(idesc, dirp->d_ino);
-                       if (statemap[dirp->d_ino] != CLEAR) {
+                       if (statemap[dirp->d_ino] == DFOUND) {
                                lncntp[dirp->d_ino]--;
                                lncntp[dirp->d_ino]--;
-                       } else {
+                       } else if (statemap[dirp->d_ino] == DCLEAR) {
                                dirp->d_ino = 0;
                                ret |= ALTERED;
                                dirp->d_ino = 0;
                                ret |= ALTERED;
-                       }
+                       } else
+                               errexit("BAD RETURN STATE %d FROM DESCEND",
+                                   statemap[dirp->d_ino]);
                        break;
                        break;
+
+               default:
+                       errexit("BAD STATE %d FOR INODE I=%d",
+                           statemap[dirp->d_ino], dirp->d_ino);
                }
        }
        pathp = curpathloc;
                }
        }
        pathp = curpathloc;