missing fsbtodb!
[unix-history] / usr / src / sbin / fsck / pass1.c
index 8434668..3ecc82a 100644 (file)
@@ -1,18 +1,27 @@
+/*
+ * 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[] = "@(#)pass1.c   3.2 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)pass1.c    5.4 (Berkeley) %G%";
+#endif not lint
 
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include "fsck.h"
 
 
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include "fsck.h"
 
-int    pass1check();
+static daddr_t badblk;
+static daddr_t dupblk;
+int pass1check();
 
 pass1()
 {
 
 pass1()
 {
-       register int c, i, n, j;
+       register int c, i, j;
        register DINODE *dp;
        register DINODE *dp;
+       struct zlncnt *zlnp;
        int ndb, partial, cgd;
        struct inodesc idesc;
        ino_t inumber;
        int ndb, partial, cgd;
        struct inodesc idesc;
        ino_t inumber;
@@ -37,145 +46,112 @@ pass1()
        idesc.id_type = ADDR;
        idesc.id_func = pass1check;
        inumber = 0;
        idesc.id_type = ADDR;
        idesc.id_func = pass1check;
        inumber = 0;
-       n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
+       n_files = n_blks = 0;
        for (c = 0; c < sblock.fs_ncg; c++) {
        for (c = 0; c < sblock.fs_ncg; c++) {
-               if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
-                       continue;
-               if (cgrp.cg_magic != CG_MAGIC) {
-                       pfatal("CG %d: BAD MAGIC NUMBER\n", c);
-                       bzero((char *)&cgrp, (int)sblock.fs_cgsize);
-               }
-               n = 0;
                for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
                for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
-                       dp = ginode(inumber);
-                       if (dp == NULL)
+                       if (inumber < ROOTINO)
                                continue;
                                continue;
-                       n++;
-                       if (ALLOC(dp)) {
-                               if (!isset(cgrp.cg_iused, i)) {
-                                       if (debug)
-                                               printf("%d bad, not used\n",
-                                                   inumber);
-                                       inosumbad++;
-                               }
-                               n--;
-                               lastino = inumber;
-                               if (!preen && (dp->di_mode & IFMT) == IFMT &&
-                                   reply("HOLD BAD BLOCK") == 1) {
-                                       dp->di_size = sblock.fs_fsize;
-                                       dp->di_mode = IFREG|0600;
-                                       inodirty();
-                               } else if (ftypeok(dp) == 0)
-                                       goto unknown;
-                               if (dp->di_size < 0) {
-                                       if (debug)
-                                               printf("bad size %d:",
-                                                       dp->di_size);
-                                       goto unknown;
-                               }
-                               ndb = howmany(dp->di_size, sblock.fs_bsize);
-                               if (SPECIAL(dp))
-                                       ndb++;
-                               for (j = ndb; j < NDADDR; j++)
-                                       if (dp->di_db[j] != 0) {
-                                               if (debug)
-                                                       printf("bad direct addr: %d\n",
-                                                               dp->di_db[j]);
-                                               goto unknown;
-                                       }
-                               for (j = 0, ndb -= NDADDR; ndb > 0; j++)
-                                       ndb /= NINDIR(&sblock);
-                               for (; j < NIADDR; j++)
-                                       if (dp->di_ib[j] != 0) {
-                                               if (debug)
-                                                       printf("bad indirect addr: %d\n",
-                                                               dp->di_ib[j]);
-                                               goto unknown;
-                                       }
-                               n_files++;
-                               lncntp[inumber] = dp->di_nlink;
-                               if (dp->di_nlink <= 0) {
-                                       if (badlnp < &badlncnt[MAXLNCNT])
-                                               *badlnp++ = inumber;
-                                       else {
-                                               pfatal("LINK COUNT TABLE OVERFLOW");
-                                               if (reply("CONTINUE") == 0)
-                                                       errexit("");
-                                       }
-                               }
-                               statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE;
-                               badblk = dupblk = 0; maxblk = 0;
-                               idesc.id_number = inumber;
-                               idesc.id_filesize = 0;
-                               (void)ckinode(dp, &idesc);
-                               idesc.id_filesize *= btodb(sblock.fs_fsize);
-                               if (dp->di_blocks != idesc.id_filesize) {
-                                       pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
-                                           inumber, dp->di_blocks,
-                                           idesc.id_filesize);
-                                       if (preen)
-                                               printf(" (CORRECTED)\n");
-                                       else if (reply("CORRECT") == 0)
-                                               continue;
-                                       dp->di_blocks = idesc.id_filesize;
-                                       inodirty();
-                               }
-                               continue;
-               unknown:
-                               pfatal("UNKNOWN FILE TYPE I=%u", inumber);
-                               if (reply("CLEAR") == 1) {
-                                       zapino(dp);
-                                       inodirty();
-                                       inosumbad++;
-                               }
-                       } else {
-                               if (isset(cgrp.cg_iused, i)) {
-                                       if (debug)
-                                               printf("%d bad, marked used\n",
-                                                   inumber);
-                                       inosumbad++;
-                                       n--;
-                               }
-                               partial = 0;
-                               for (j = 0; j < NDADDR; j++)
-                                       if (dp->di_db[j] != 0)
-                                               partial++;
-                               for (j = 0; j < NIADDR; j++)
-                                       if (dp->di_ib[j] != 0)
-                                               partial++;
-                               if (partial || dp->di_mode != 0 ||
-                                   dp->di_size != 0) {
+                       dp = ginode(inumber);
+                       if (!ALLOC(dp)) {
+                               if (bcmp((char *)dp->di_db, (char *)zino.di_db,
+                                       NDADDR * sizeof(daddr_t)) ||
+                                   bcmp((char *)dp->di_ib, (char *)zino.di_ib,
+                                       NIADDR * sizeof(daddr_t)) ||
+                                   dp->di_mode || dp->di_size) {
                                        pfatal("PARTIALLY ALLOCATED INODE I=%u",
                                                inumber);
                                        if (reply("CLEAR") == 1) {
                                                zapino(dp);
                                                inodirty();
                                        pfatal("PARTIALLY ALLOCATED INODE I=%u",
                                                inumber);
                                        if (reply("CLEAR") == 1) {
                                                zapino(dp);
                                                inodirty();
-                                               inosumbad++;
                                        }
                                }
                                        }
                                }
+                               statemap[inumber] = USTATE;
+                               continue;
+                       }
+                       lastino = inumber;
+                       if (dp->di_size < 0 ||
+                           dp->di_size + sblock.fs_bsize - 1 < 0) {
+                               if (debug)
+                                       printf("bad size %d:", dp->di_size);
+                               goto unknown;
+                       }
+                       if (!preen && (dp->di_mode & IFMT) == IFMT &&
+                           reply("HOLD BAD BLOCK") == 1) {
+                               dp->di_size = sblock.fs_fsize;
+                               dp->di_mode = IFREG|0600;
+                               inodirty();
+                       }
+                       ndb = howmany(dp->di_size, sblock.fs_bsize);
+                       if (SPECIAL(dp))
+                               ndb++;
+                       for (j = ndb; j < NDADDR; j++)
+                               if (dp->di_db[j] != 0) {
+                                       if (debug)
+                                               printf("bad direct addr: %d\n",
+                                                       dp->di_db[j]);
+                                       goto unknown;
+                               }
+                       for (j = 0, ndb -= NDADDR; ndb > 0; j++)
+                               ndb /= NINDIR(&sblock);
+                       for (; j < NIADDR; j++)
+                               if (dp->di_ib[j] != 0) {
+                                       if (debug)
+                                               printf("bad indirect addr: %d\n",
+                                                       dp->di_ib[j]);
+                                       goto unknown;
+                               }
+                       if (ftypeok(dp) == 0)
+                               goto unknown;
+                       n_files++;
+                       lncntp[inumber] = dp->di_nlink;
+                       if (dp->di_nlink <= 0) {
+                               zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
+                               if (zlnp == NULL) {
+                                       pfatal("LINK COUNT TABLE OVERFLOW");
+                                       if (reply("CONTINUE") == 0)
+                                               errexit("");
+                               } else {
+                                       zlnp->zlncnt = inumber;
+                                       zlnp->next = zlnhead;
+                                       zlnhead = zlnp;
+                               }
+                       }
+                       statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE;
+                       badblk = dupblk = 0; maxblk = 0;
+                       idesc.id_number = inumber;
+                       (void)ckinode(dp, &idesc);
+                       idesc.id_entryno *= btodb(sblock.fs_fsize);
+                       if (dp->di_blocks != idesc.id_entryno) {
+                               pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
+                                   inumber, dp->di_blocks, idesc.id_entryno);
+                               if (preen)
+                                       printf(" (CORRECTED)\n");
+                               else if (reply("CORRECT") == 0)
+                                       continue;
+                               dp->di_blocks = idesc.id_entryno;
+                               inodirty();
+                       }
+                       continue;
+       unknown:
+                       pfatal("UNKNOWN FILE TYPE I=%u", inumber);
+                       statemap[inumber] = FCLEAR;
+                       if (reply("CLEAR") == 1) {
+                               statemap[inumber] = USTATE;
+                               zapino(dp);
+                               inodirty();
                        }
                }
                        }
                }
-               if (n != cgrp.cg_cs.cs_nifree) {
-                       if (debug)
-                               printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
-                                   c, cgrp.cg_cs.cs_nifree, n);
-                       inosumbad++;
-               }
-               if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
-                 || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
-                 || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
-                 || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
-                       sbsumbad++;
        }
 }
 
 pass1check(idesc)
        register struct inodesc *idesc;
 {
        }
 }
 
 pass1check(idesc)
        register struct inodesc *idesc;
 {
-       register daddr_t *dlp;
        int res = KEEPON;
        int anyout, nfrags;
        daddr_t blkno = idesc->id_blkno;
        int res = KEEPON;
        int anyout, nfrags;
        daddr_t blkno = idesc->id_blkno;
+       register struct dups *dlp;
+       struct dups *new;
 
        if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) {
                blkerr(idesc->id_number, "BAD", blkno);
 
        if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) {
                blkerr(idesc->id_number, "BAD", blkno);
@@ -206,23 +182,31 @@ pass1check(idesc)
                                        errexit("");
                                return (STOP);
                        }
                                        errexit("");
                                return (STOP);
                        }
-                       if (enddup >= &duplist[DUPTBLSIZE]) {
+                       new = (struct dups *)malloc(sizeof(struct dups));
+                       if (new == NULL) {
                                pfatal("DUP TABLE OVERFLOW.");
                                if (reply("CONTINUE") == 0)
                                        errexit("");
                                return (STOP);
                        }
                                pfatal("DUP TABLE OVERFLOW.");
                                if (reply("CONTINUE") == 0)
                                        errexit("");
                                return (STOP);
                        }
-                       for (dlp = duplist; dlp < muldup; dlp++)
-                               if (*dlp == blkno) {
-                                       *enddup++ = blkno;
-                                       break;
-                               }
-                       if (dlp >= muldup) {
-                               *enddup++ = *muldup;
-                               *muldup++ = blkno;
+                       new->dup = blkno;
+                       if (muldup == 0) {
+                               duplist = muldup = new;
+                               new->next = 0;
+                       } else {
+                               new->next = muldup->next;
+                               muldup->next = new;
                        }
                        }
+                       for (dlp = duplist; dlp != muldup; dlp = dlp->next)
+                               if (dlp->dup == blkno)
+                                       break;
+                       if (dlp == muldup && dlp->dup != blkno)
+                               muldup = new;
                }
                }
-               idesc->id_filesize++;
+               /*
+                * count the number of blocks found in id_entryno
+                */
+               idesc->id_entryno++;
        }
        return (res);
 }
        }
        return (res);
 }