4.4BSD snapshot (revision 8.1)
[unix-history] / usr / src / sbin / fsck / pass2.c
index 23c5401..5ac8d2c 100644 (file)
@@ -1,20 +1,19 @@
 /*
 /*
- * Copyright (c) 1980, 1986 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1980, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)pass2.c    5.14 (Berkeley) %G%";
+static char sccsid[] = "@(#)pass2.c    8.1 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
-#include <ufs/dinode.h>
-#include <ufs/fs.h>
-#define KERNEL
-#include <ufs/dir.h>
-#undef KERNEL
+#include <sys/time.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
 #include <stdlib.h>
 #include <string.h>
 #include "fsck.h"
 #include <stdlib.h>
 #include <string.h>
 #include "fsck.h"
@@ -88,6 +87,7 @@ pass2()
        bzero((char *)&curino, sizeof(struct inodesc));
        curino.id_type = DATA;
        curino.id_func = pass2check;
        bzero((char *)&curino, sizeof(struct inodesc));
        curino.id_type = DATA;
        curino.id_func = pass2check;
+       dino.di_mode = IFDIR;
        dp = &dino;
        inpend = &inpsort[inplast];
        for (inpp = inpsort; inpp < inpend; inpp++) {
        dp = &dino;
        inpend = &inpsort[inplast];
        for (inpp = inpsort; inpp < inpend; inpp++) {
@@ -96,15 +96,14 @@ pass2()
                        continue;
                if (inp->i_isize < MINDIRSIZE) {
                        direrror(inp->i_number, "DIRECTORY TOO SHORT");
                        continue;
                if (inp->i_isize < MINDIRSIZE) {
                        direrror(inp->i_number, "DIRECTORY TOO SHORT");
-                       inp->i_isize = MINDIRSIZE;
+                       inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);
                        if (reply("FIX") == 1) {
                                dp = ginode(inp->i_number);
                        if (reply("FIX") == 1) {
                                dp = ginode(inp->i_number);
-                               dp->di_size = MINDIRSIZE;
+                               dp->di_size = inp->i_isize;
                                inodirty();
                                dp = &dino;
                        }
                                inodirty();
                                dp = &dino;
                        }
-               }
-               if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
+               } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
                        getpathname(pathbuf, inp->i_number, inp->i_number);
                        pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
                                pathbuf, inp->i_isize, DIRBLKSIZ);
                        getpathname(pathbuf, inp->i_number, inp->i_number);
                        pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
                                pathbuf, inp->i_isize, DIRBLKSIZ);
@@ -149,7 +148,7 @@ pass2()
                        continue;
                }
                fileerror(inp->i_parent, inp->i_number,
                        continue;
                }
                fileerror(inp->i_parent, inp->i_number,
-                       "BAD INODE NUMBER FOR '..'");
+                   "BAD INODE NUMBER FOR '..'");
                if (reply("FIX") == 0)
                        continue;
                lncntp[inp->i_dotdot]++;
                if (reply("FIX") == 0)
                        continue;
                lncntp[inp->i_dotdot]++;
@@ -175,6 +174,13 @@ pass2check(idesc)
        char namebuf[MAXPATHLEN + 1];
        char pathbuf[MAXPATHLEN + 1];
 
        char namebuf[MAXPATHLEN + 1];
        char pathbuf[MAXPATHLEN + 1];
 
+       /*
+        * If converting, set directory entry type.
+        */
+       if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
+               dirp->d_type = typemap[dirp->d_ino];
+               ret |= ALTERED;
+       }
        /* 
         * check for "."
         */
        /* 
         * check for "."
         */
@@ -187,13 +193,23 @@ pass2check(idesc)
                        if (reply("FIX") == 1)
                                ret |= ALTERED;
                }
                        if (reply("FIX") == 1)
                                ret |= ALTERED;
                }
+               if (newinofmt && dirp->d_type != DT_DIR) {
+                       direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
+                       dirp->d_type = DT_DIR;
+                       if (reply("FIX") == 1)
+                               ret |= ALTERED;
+               }
                goto chk1;
        }
        direrror(idesc->id_number, "MISSING '.'");
        proto.d_ino = idesc->id_number;
                goto chk1;
        }
        direrror(idesc->id_number, "MISSING '.'");
        proto.d_ino = idesc->id_number;
+       if (newinofmt)
+               proto.d_type = DT_DIR;
+       else
+               proto.d_type = 0;
        proto.d_namlen = 1;
        (void)strcpy(proto.d_name, ".");
        proto.d_namlen = 1;
        (void)strcpy(proto.d_name, ".");
-       entrysize = DIRSIZ(&proto);
+       entrysize = DIRSIZ(0, &proto);
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
                        dirp->d_name);
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
                        dirp->d_name);
@@ -221,11 +237,15 @@ chk1:
                goto chk2;
        inp = getinoinfo(idesc->id_number);
        proto.d_ino = inp->i_parent;
                goto chk2;
        inp = getinoinfo(idesc->id_number);
        proto.d_ino = inp->i_parent;
+       if (newinofmt)
+               proto.d_type = DT_DIR;
+       else
+               proto.d_type = 0;
        proto.d_namlen = 2;
        (void)strcpy(proto.d_name, "..");
        proto.d_namlen = 2;
        (void)strcpy(proto.d_name, "..");
-       entrysize = DIRSIZ(&proto);
+       entrysize = DIRSIZ(0, &proto);
        if (idesc->id_entryno == 0) {
        if (idesc->id_entryno == 0) {
-               n = DIRSIZ(dirp);
+               n = DIRSIZ(0, dirp);
                if (dirp->d_reclen < n + entrysize)
                        goto chk2;
                proto.d_reclen = dirp->d_reclen - n;
                if (dirp->d_reclen < n + entrysize)
                        goto chk2;
                proto.d_reclen = dirp->d_reclen - n;
@@ -238,6 +258,12 @@ chk1:
        }
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
                inp->i_dotdot = dirp->d_ino;
        }
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
                inp->i_dotdot = dirp->d_ino;
+               if (newinofmt && dirp->d_type != DT_DIR) {
+                       direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
+                       dirp->d_type = DT_DIR;
+                       if (reply("FIX") == 1)
+                               ret |= ALTERED;
+               }
                goto chk2;
        }
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
                goto chk2;
        }
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
@@ -287,7 +313,7 @@ chk2:
        }
        idesc->id_entryno++;
        n = 0;
        }
        idesc->id_entryno++;
        n = 0;
-       if (dirp->d_ino > maxino || dirp->d_ino <= 0) {
+       if (dirp->d_ino > maxino) {
                fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
                n = reply("REMOVE");
        } else {
                fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
                n = reply("REMOVE");
        } else {
@@ -304,10 +330,14 @@ again:
                case FCLEAR:
                        if (idesc->id_entryno <= 2)
                                break;
                case FCLEAR:
                        if (idesc->id_entryno <= 2)
                                break;
-                       if (statemap[dirp->d_ino] == DCLEAR)
-                               errmsg = "ZERO LENGTH DIRECTORY";
-                       else
+                       if (statemap[dirp->d_ino] == FCLEAR)
                                errmsg = "DUP/BAD";
                                errmsg = "DUP/BAD";
+                       else if (!preen)
+                               errmsg = "ZERO LENGTH DIRECTORY";
+                       else {
+                               n = 1;
+                               break;
+                       }
                        fileerror(idesc->id_number, dirp->d_ino, errmsg);
                        if ((n = reply("REMOVE")) == 1)
                                break;
                        fileerror(idesc->id_number, dirp->d_ino, errmsg);
                        if ((n = reply("REMOVE")) == 1)
                                break;
@@ -341,6 +371,13 @@ again:
                        /* fall through */
 
                case FSTATE:
                        /* fall through */
 
                case FSTATE:
+                       if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
+                               fileerror(idesc->id_number, dirp->d_ino,
+                                   "BAD TYPE VALUE");
+                               dirp->d_type = typemap[dirp->d_ino];
+                               if (reply("FIX") == 1)
+                                       ret |= ALTERED;
+                       }
                        lncntp[dirp->d_ino]--;
                        break;
 
                        lncntp[dirp->d_ino]--;
                        break;