4.4BSD snapshot (revision 8.1)
[unix-history] / usr / src / sbin / fsck / pass2.c
index d44f19b..5ac8d2c 100644 (file)
@@ -1,31 +1,21 @@
 /*
 /*
- * 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.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)pass2.c    5.11 (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 <strings.h>
+#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"
 
 #define MINDIRSIZE     (sizeof (struct dirtemplate))
 #include "fsck.h"
 
 #define MINDIRSIZE     (sizeof (struct dirtemplate))
@@ -90,13 +80,14 @@ pass2()
        /*
         * Sort the directory list into disk block order.
         */
        /*
         * Sort the directory list into disk block order.
         */
-       qsort((char *)inpsort, (int)inplast, sizeof *inpsort, blksort);
+       qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort);
        /*
         * Check the integrity of each directory.
         */
        bzero((char *)&curino, sizeof(struct inodesc));
        curino.id_type = DATA;
        curino.id_func = pass2check;
        /*
         * Check the integrity of each directory.
         */
        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++) {
@@ -105,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);
@@ -129,7 +119,7 @@ pass2()
                }
                dp->di_size = inp->i_isize;
                bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],
                }
                dp->di_size = inp->i_isize;
                bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],
-                       (int)inp->i_numblks);
+                       (size_t)inp->i_numblks);
                curino.id_number = inp->i_number;
                curino.id_parent = inp->i_parent;
                (void)ckinode(dp, &curino);
                curino.id_number = inp->i_number;
                curino.id_parent = inp->i_parent;
                (void)ckinode(dp, &curino);
@@ -153,12 +143,12 @@ pass2()
                        fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
                        if (reply("FIX") == 0)
                                continue;
                        fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
                        if (reply("FIX") == 0)
                                continue;
-                       makeentry(inp->i_number, inp->i_parent, "..");
+                       (void)makeentry(inp->i_number, inp->i_parent, "..");
                        lncntp[inp->i_parent]--;
                        continue;
                }
                fileerror(inp->i_parent, inp->i_number,
                        lncntp[inp->i_parent]--;
                        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]++;
@@ -184,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 "."
         */
@@ -196,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);
@@ -210,17 +217,17 @@ pass2check(idesc)
                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
        } else if (dirp->d_reclen < 2 * entrysize) {
                proto.d_reclen = dirp->d_reclen;
                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
        } else if (dirp->d_reclen < 2 * entrysize) {
                proto.d_reclen = dirp->d_reclen;
-               bcopy((char *)&proto, (char *)dirp, entrysize);
+               bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                if (reply("FIX") == 1)
                        ret |= ALTERED;
        } else {
                n = dirp->d_reclen - entrysize;
                proto.d_reclen = entrysize;
                if (reply("FIX") == 1)
                        ret |= ALTERED;
        } else {
                n = dirp->d_reclen - entrysize;
                proto.d_reclen = entrysize;
-               bcopy((char *)&proto, (char *)dirp, entrysize);
+               bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                idesc->id_entryno++;
                lncntp[dirp->d_ino]--;
                dirp = (struct direct *)((char *)(dirp) + entrysize);
                idesc->id_entryno++;
                lncntp[dirp->d_ino]--;
                dirp = (struct direct *)((char *)(dirp) + entrysize);
-               bzero((char *)dirp, n);
+               bzero((char *)dirp, (size_t)n);
                dirp->d_reclen = n;
                if (reply("FIX") == 1)
                        ret |= ALTERED;
                dirp->d_reclen = n;
                if (reply("FIX") == 1)
                        ret |= ALTERED;
@@ -230,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;
@@ -242,11 +253,17 @@ chk1:
                idesc->id_entryno++;
                lncntp[dirp->d_ino]--;
                dirp = (struct direct *)((char *)(dirp) + n);
                idesc->id_entryno++;
                lncntp[dirp->d_ino]--;
                dirp = (struct direct *)((char *)(dirp) + n);
-               bzero((char *)dirp, (int)proto.d_reclen);
+               bzero((char *)dirp, (size_t)proto.d_reclen);
                dirp->d_reclen = proto.d_reclen;
        }
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
                inp->i_dotdot = dirp->d_ino;
                dirp->d_reclen = proto.d_reclen;
        }
        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) {
@@ -265,7 +282,7 @@ chk1:
                inp->i_dotdot = inp->i_parent;
                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                proto.d_reclen = dirp->d_reclen;
                inp->i_dotdot = inp->i_parent;
                fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
                proto.d_reclen = dirp->d_reclen;
-               bcopy((char *)&proto, (char *)dirp, entrysize);
+               bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);
                if (reply("FIX") == 1)
                        ret |= ALTERED;
        }
                if (reply("FIX") == 1)
                        ret |= ALTERED;
        }
@@ -296,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 {
@@ -313,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;
@@ -350,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;