make readdir more robust; allow printing of dir entries not on tape
[unix-history] / usr / src / sbin / fsck / main.c
index 75b38b8..5aec981 100644 (file)
@@ -1,4 +1,4 @@
-static char sccsid[] = "@(#)main.c     2.16    (Berkeley)      %G%";
+char version[] = "@(#)main.c   2.22    (Berkeley)      %G%";
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -34,6 +34,8 @@ typedef struct direct DIRECT;
 #define        BLK     ((dp->di_mode & IFMT) == IFBLK)
 #define        CHR     ((dp->di_mode & IFMT) == IFCHR)
 #define        LNK     ((dp->di_mode & IFMT) == IFLNK)
 #define        BLK     ((dp->di_mode & IFMT) == IFBLK)
 #define        CHR     ((dp->di_mode & IFMT) == IFCHR)
 #define        LNK     ((dp->di_mode & IFMT) == IFLNK)
+#define        SOCK    ((dp->di_mode & IFMT) == IFSOCK)
+#define        BADBLK  ((dp->di_mode & IFMT) == IFMT)
 #define        SPECIAL (BLK || CHR)
 
 ino_t  startinum;              /* blk num of first in raw area */
 #define        SPECIAL (BLK || CHR)
 
 ino_t  startinum;              /* blk num of first in raw area */
@@ -81,7 +83,7 @@ daddr_t       duplist[DUPTBLSIZE];    /* dup block table */
 daddr_t        *enddup;                /* next entry in dup table */
 daddr_t        *muldup;                /* multiple dups part of table */
 
 daddr_t        *enddup;                /* next entry in dup table */
 daddr_t        *muldup;                /* multiple dups part of table */
 
-#define        MAXLNCNT        50      /* num zero link cnts to remember */
+#define        MAXLNCNT        500     /* num zero link cnts to remember */
 ino_t  badlncnt[MAXLNCNT];     /* table of inos with zero link cnts */
 ino_t  *badlnp;                /* next entry in table */
 
 ino_t  badlncnt[MAXLNCNT];     /* table of inos with zero link cnts */
 ino_t  *badlnp;                /* next entry in table */
 
@@ -104,6 +106,7 @@ char        *pathp;                 /* pointer to pathname position */
 char   *thisname;              /* ptr to current pathname component */
 char   *srchname;              /* name being searched for in dir */
 char   pathname[BUFSIZ];
 char   *thisname;              /* ptr to current pathname component */
 char   *srchname;              /* name being searched for in dir */
 char   pathname[BUFSIZ];
+char   *endpathname = &pathname[BUFSIZ - 2];
 
 char   *lfname = "lost+found";
 
 
 char   *lfname = "lost+found";
 
@@ -289,7 +292,7 @@ retry:
                if (stchar.st_mode & S_IFCHR) {
                        if (stslash.st_dev == stblock.st_rdev) {
                                hotroot++;
                if (stchar.st_mode & S_IFCHR) {
                        if (stslash.st_dev == stblock.st_rdev) {
                                hotroot++;
-                               raw = unrawname(name);
+                               raw = rawname(name);
                        }
                        checkfilesys(raw);
                        return (1);
                        }
                        checkfilesys(raw);
                        return (1);
@@ -583,21 +586,38 @@ pass1()
                                }
                                n--;
                                lastino = inum;
                                }
                                n--;
                                lastino = inum;
-                               if (ftypeok(dp) == 0)
+                               if (!preen && BADBLK &&
+                                   reply("HOLD BAD BLOCK") == 1) {
+                                       dp->di_size = sblock.fs_fsize;
+                                       dp->di_mode = IFREG|0600;
+                                       inodirty();
+                               } else if (ftypeok(dp) == 0)
                                        goto unknown;
                                        goto unknown;
-                               if (dp->di_size < 0)
+                               if (dp->di_size < 0) {
+                                       if (debug)
+                                               printf("bad size %d:",
+                                                       dp->di_size);
                                        goto unknown;
                                        goto unknown;
+                               }
                                ndb = howmany(dp->di_size, sblock.fs_bsize);
                                if (SPECIAL)
                                        ndb++;
                                for (j = ndb; j < NDADDR; j++)
                                ndb = howmany(dp->di_size, sblock.fs_bsize);
                                if (SPECIAL)
                                        ndb++;
                                for (j = ndb; j < NDADDR; j++)
-                                       if (dp->di_db[j] != 0)
+                                       if (dp->di_db[j] != 0) {
+                                               if (debug)
+                                                       printf("bad direct addr: %d\n",
+                                                               dp->di_db[j]);
                                                goto unknown;
                                                goto unknown;
+                                       }
                                for (j = 0, ndb -= NDADDR; ndb > 0; j++)
                                        ndb /= NINDIR(&sblock);
                                for (; j < NIADDR; j++)
                                for (j = 0, ndb -= NDADDR; ndb > 0; j++)
                                        ndb /= NINDIR(&sblock);
                                for (; j < NIADDR; j++)
-                                       if (dp->di_ib[j] != 0)
+                                       if (dp->di_ib[j] != 0) {
+                                               if (debug)
+                                                       printf("bad indirect addr: %d\n",
+                                                               dp->di_ib[j]);
                                                goto unknown;
                                                goto unknown;
+                                       }
                                n_files++;
                                lncntp[inum] = dp->di_nlink;
                                if (dp->di_nlink <= 0) {
                                n_files++;
                                lncntp[inum] = dp->di_nlink;
                                if (dp->di_nlink <= 0) {
@@ -614,8 +634,9 @@ pass1()
                                ckinode(dp, ADDR);
                                continue;
                unknown:
                                ckinode(dp, ADDR);
                                continue;
                unknown:
-                               pfatal("UNKNOWN FILE TYPE I=%u", inum);
-                               if (reply("CLEAR") == 1) {
+                               if (!SOCK)
+                                       pfatal("UNKNOWN FILE TYPE I=%u", inum);
+                               if ((preen && SOCK) || reply("CLEAR") == 1) {
                                        zapino(dp);
                                        inodirty();
                                        inosumbad++;
                                        zapino(dp);
                                        inodirty();
                                        inosumbad++;
@@ -805,6 +826,10 @@ pass2check(dirp)
        if ((inum = dirp->d_ino) == 0)
                return (KEEPON);
        thisname = pathp;
        if ((inum = dirp->d_ino) == 0)
                return (KEEPON);
        thisname = pathp;
+       if (pathp + dirp->d_namlen >= endpathname) {
+               *pathp = '\0';
+               errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
+       }
        for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; )
                if ((*pathp++ = *p++) == 0) {
                        --pathp;
        for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; )
                if ((*pathp++ = *p++) == 0) {
                        --pathp;
@@ -953,7 +978,7 @@ pass5()
        daddr_t cbase;
        int blockbits = (1<<sblock.fs_frag)-1;
 
        daddr_t cbase;
        int blockbits = (1<<sblock.fs_frag)-1;
 
-       blkcpy((unsigned)bmapsz, blockmap, freemap);
+       bcopy(blockmap, freemap, (unsigned)bmapsz);
        dupblk = 0;
        n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
        for (c = 0; c < sblock.fs_ncg; c++) {
        dupblk = 0;
        n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
        for (c = 0; c < sblock.fs_ncg; c++) {
@@ -1292,12 +1317,9 @@ readdir(dirp)
                dirp->loc += DIRBLKSIZ;
                filsize -= DIRBLKSIZ;
                if (dirp->fix == DONTKNOW) {
                dirp->loc += DIRBLKSIZ;
                filsize -= DIRBLKSIZ;
                if (dirp->fix == DONTKNOW) {
-                       pwarn("DIRECTORY %D CORRUPTED", dirp->number);
+                       pfatal("DIRECTORY %D CORRUPTED", dirp->number);
                        dirp->fix = NOFIX;
                        dirp->fix = NOFIX;
-                       if (preen) {
-                               printf(" (SALVAGED)\n");
-                               dirp->fix = FIX;
-                       } else if (reply("SALVAGE") != 0)
+                       if (reply("SALVAGE") != 0)
                                dirp->fix = FIX;
                }
                if (dirp->fix != FIX)
                                dirp->fix = FIX;
                }
                if (dirp->fix != FIX)
@@ -1323,12 +1345,9 @@ readdir(dirp)
                dirp->loc += size;
                filsize -= size;
                if (dirp->fix == DONTKNOW) {
                dirp->loc += size;
                filsize -= size;
                if (dirp->fix == DONTKNOW) {
-                       pwarn("DIRECTORY %D CORRUPTED", dirp->number);
+                       pfatal("DIRECTORY %D CORRUPTED", dirp->number);
                        dirp->fix = NOFIX;
                        dirp->fix = NOFIX;
-                       if (preen) {
-                               printf(" (SALVAGED)\n");
-                               dirp->fix = FIX;
-                       } else if (reply("SALVAGE") != 0)
+                       if (reply("SALVAGE") != 0)
                                dirp->fix = FIX;
                }
                if (dirp->fix == FIX) {
                                dirp->fix = FIX;
                }
                if (dirp->fix == FIX) {
@@ -1453,6 +1472,8 @@ ftypeok(dp)
                return (1);
 
        default:
                return (1);
 
        default:
+               if (debug)
+                       printf("bad file type 0%o\n", dp->di_mode);
                return (0);
        }
 }
                return (0);
        }
 }
@@ -1615,7 +1636,10 @@ makecg()
                cgrp.cg_time = time(0);
                cgrp.cg_magic = CG_MAGIC;
                cgrp.cg_cgx = c;
                cgrp.cg_time = time(0);
                cgrp.cg_magic = CG_MAGIC;
                cgrp.cg_cgx = c;
-               cgrp.cg_ncyl = sblock.fs_cpg;
+               if (c == sblock.fs_ncg - 1)
+                       cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
+               else
+                       cgrp.cg_ncyl = sblock.fs_cpg;
                cgrp.cg_niblk = sblock.fs_ipg;
                cgrp.cg_ndblk = dmax - dbase;
                cgrp.cg_cs.cs_ndir = 0;
                cgrp.cg_niblk = sblock.fs_ipg;
                cgrp.cg_ndblk = dmax - dbase;
                cgrp.cg_cs.cs_ndir = 0;
@@ -1689,12 +1713,14 @@ makecg()
                        } else
                                clrbit(cgrp.cg_free, d);
                }
                        } else
                                clrbit(cgrp.cg_free, d);
                }
+               for (; d % sblock.fs_frag != 0; d++)
+                       clrbit(cgrp.cg_free, d);
                if (j != d) {
                        blk = blkmap(&sblock, cgrp.cg_free, j);
                        fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                }
                if (j != d) {
                        blk = blkmap(&sblock, cgrp.cg_free, j);
                        fragacct(&sblock, blk, cgrp.cg_frsum, 1);
                }
-               for (; d < MAXBPG(&sblock); d++)
-                       clrbit(cgrp.cg_free, d);
+               for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
+                       clrblock(&sblock, cgrp.cg_free, d);
                sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
                sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
                sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
                sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
                sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
                sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
@@ -1945,7 +1971,7 @@ errexit(s1, s2, s3, s4)
 
 /*
  * An inconsistency occured which shouldn't during normal operations.
 
 /*
  * An inconsistency occured which shouldn't during normal operations.
- * Die if preening, otw just printf.
+ * Die if preening, otherwise just printf.
  */
 /* VARARGS1 */
 pfatal(s, a1, a2, a3)
  */
 /* VARARGS1 */
 pfatal(s, a1, a2, a3)