home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / fsck / pass1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  7.2 KB  |  263 lines

  1. /*
  2.  * Copyright (c) 1980, 1986 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)pass1.c    5.16 (Berkeley) 3/19/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <ufs/dinode.h>
  40. #include <ufs/fs.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include "fsck.h"
  44.  
  45. static daddr_t badblk;
  46. static daddr_t dupblk;
  47. int pass1check();
  48. struct dinode *getnextinode();
  49.  
  50. pass1()
  51. {
  52.     register int c, i, j;
  53.     register struct dinode *dp;
  54.     struct zlncnt *zlnp;
  55.     int ndb, cgd;
  56.     struct inodesc idesc;
  57.     ino_t inumber;
  58.  
  59.     /*
  60.      * Set file system reserved blocks in used block map.
  61.      */
  62.     for (c = 0; c < sblock.fs_ncg; c++) {
  63.         cgd = cgdmin(&sblock, c);
  64.         if (c == 0) {
  65.             i = cgbase(&sblock, c);
  66.             cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
  67.         } else
  68.             i = cgsblock(&sblock, c);
  69.         for (; i < cgd; i++)
  70.             setbmap(i);
  71.     }
  72.     /*
  73.      * Find all allocated blocks.
  74.      */
  75.     bzero((char *)&idesc, sizeof(struct inodesc));
  76.     idesc.id_type = ADDR;
  77.     idesc.id_func = pass1check;
  78.     inumber = 0;
  79.     n_files = n_blks = 0;
  80.     resetinodebuf();
  81.     for (c = 0; c < sblock.fs_ncg; c++) {
  82.         for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
  83.             if (inumber < ROOTINO)
  84.                 continue;
  85.             dp = getnextinode(inumber);
  86.             if ((dp->di_mode & IFMT) == 0) {
  87.                 if (bcmp((char *)dp->di_db, (char *)zino.di_db,
  88.                     NDADDR * sizeof(daddr_t)) ||
  89.                     bcmp((char *)dp->di_ib, (char *)zino.di_ib,
  90.                     NIADDR * sizeof(daddr_t)) ||
  91.                     dp->di_mode || dp->di_size) {
  92.                     pfatal("PARTIALLY ALLOCATED INODE I=%lu",
  93.                         inumber);
  94.                     if (reply("CLEAR") == 1) {
  95.                         dp = ginode(inumber);
  96.                         clearinode(dp);
  97.                         inodirty();
  98.                     }
  99.                 }
  100.                 statemap[inumber] = USTATE;
  101.                 continue;
  102.             }
  103.             lastino = inumber;
  104.             if (/* dp->di_size < 0 || */
  105.                 dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
  106.                 if (debug)
  107.                     printf("bad size %lu:", dp->di_size);
  108.                 goto unknown;
  109.             }
  110.             if (!preen && (dp->di_mode & IFMT) == IFMT &&
  111.                 reply("HOLD BAD BLOCK") == 1) {
  112.                 dp = ginode(inumber);
  113.                 dp->di_size = sblock.fs_fsize;
  114.                 dp->di_mode = IFREG|0600;
  115.                 inodirty();
  116.             }
  117.             ndb = howmany(dp->di_size, sblock.fs_bsize);
  118.             if (ndb < 0) {
  119.                 if (debug)
  120.                     printf("bad size %lu ndb %d:",
  121.                         dp->di_size, ndb);
  122.                 goto unknown;
  123.             }
  124.             if ((dp->di_mode & IFMT) == IFBLK ||
  125.                 (dp->di_mode & IFMT) == IFCHR)
  126.                 ndb++;
  127.             for (j = ndb; j < NDADDR; j++)
  128.                 if (dp->di_db[j] != 0) {
  129.                     if (debug)
  130.                         printf("bad direct addr: %ld\n",
  131.                             dp->di_db[j]);
  132.                     goto unknown;
  133.                 }
  134.             for (j = 0, ndb -= NDADDR; ndb > 0; j++)
  135.                 ndb /= NINDIR(&sblock);
  136.             for (; j < NIADDR; j++)
  137.                 if (dp->di_ib[j] != 0) {
  138.                     if (debug)
  139.                         printf("bad indirect addr: %ld\n",
  140.                             dp->di_ib[j]);
  141.                     goto unknown;
  142.                 }
  143.             if (ftypeok(dp) == 0)
  144.                 goto unknown;
  145.             n_files++;
  146.             lncntp[inumber] = dp->di_nlink;
  147.             if (dp->di_nlink <= 0) {
  148.                 zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
  149.                 if (zlnp == NULL) {
  150.                     pfatal("LINK COUNT TABLE OVERFLOW");
  151.                     if (reply("CONTINUE") == 0)
  152.                         errexit("");
  153.                 } else {
  154.                     zlnp->zlncnt = inumber;
  155.                     zlnp->next = zlnhead;
  156.                     zlnhead = zlnp;
  157.                 }
  158.             }
  159.             if ((dp->di_mode & IFMT) == IFDIR) {
  160.                 if (dp->di_size == 0)
  161.                     statemap[inumber] = DCLEAR;
  162.                 else
  163.                     statemap[inumber] = DSTATE;
  164.                 cacheino(dp, inumber);
  165.             } else
  166.                 statemap[inumber] = FSTATE;
  167.             badblk = dupblk = 0;
  168.             idesc.id_number = inumber;
  169.             (void)ckinode(dp, &idesc);
  170.             idesc.id_entryno *= btodb(sblock.fs_fsize);
  171.             if (dp->di_blocks != idesc.id_entryno) {
  172.                 pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
  173.                     inumber, dp->di_blocks, idesc.id_entryno);
  174.                 if (preen)
  175.                     printf(" (CORRECTED)\n");
  176.                 else if (reply("CORRECT") == 0)
  177.                     continue;
  178.                 dp = ginode(inumber);
  179.                 dp->di_blocks = idesc.id_entryno;
  180.                 inodirty();
  181.             }
  182.             continue;
  183.     unknown:
  184.             pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
  185.             statemap[inumber] = FCLEAR;
  186.             if (reply("CLEAR") == 1) {
  187.                 statemap[inumber] = USTATE;
  188.                 dp = ginode(inumber);
  189.                 clearinode(dp);
  190.                 inodirty();
  191.             }
  192.         }
  193.     }
  194.     freeinodebuf();
  195. }
  196.  
  197. pass1check(idesc)
  198.     register struct inodesc *idesc;
  199. {
  200.     int res = KEEPON;
  201.     int anyout, nfrags;
  202.     daddr_t blkno = idesc->id_blkno;
  203.     register struct dups *dlp;
  204.     struct dups *new;
  205.  
  206.     if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
  207.         blkerror(idesc->id_number, "BAD", blkno);
  208.         if (badblk++ >= MAXBAD) {
  209.             pwarn("EXCESSIVE BAD BLKS I=%lu",
  210.                 idesc->id_number);
  211.             if (preen)
  212.                 printf(" (SKIPPING)\n");
  213.             else if (reply("CONTINUE") == 0)
  214.                 errexit("");
  215.             return (STOP);
  216.         }
  217.     }
  218.     for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
  219.         if (anyout && chkrange(blkno, 1)) {
  220.             res = SKIP;
  221.         } else if (!testbmap(blkno)) {
  222.             n_blks++;
  223.             setbmap(blkno);
  224.         } else {
  225.             blkerror(idesc->id_number, "DUP", blkno);
  226.             if (dupblk++ >= MAXDUP) {
  227.                 pwarn("EXCESSIVE DUP BLKS I=%lu",
  228.                     idesc->id_number);
  229.                 if (preen)
  230.                     printf(" (SKIPPING)\n");
  231.                 else if (reply("CONTINUE") == 0)
  232.                     errexit("");
  233.                 return (STOP);
  234.             }
  235.             new = (struct dups *)malloc(sizeof(struct dups));
  236.             if (new == NULL) {
  237.                 pfatal("DUP TABLE OVERFLOW.");
  238.                 if (reply("CONTINUE") == 0)
  239.                     errexit("");
  240.                 return (STOP);
  241.             }
  242.             new->dup = blkno;
  243.             if (muldup == 0) {
  244.                 duplist = muldup = new;
  245.                 new->next = 0;
  246.             } else {
  247.                 new->next = muldup->next;
  248.                 muldup->next = new;
  249.             }
  250.             for (dlp = duplist; dlp != muldup; dlp = dlp->next)
  251.                 if (dlp->dup == blkno)
  252.                     break;
  253.             if (dlp == muldup && dlp->dup != blkno)
  254.                 muldup = new;
  255.         }
  256.         /*
  257.          * count the number of blocks found in id_entryno
  258.          */
  259.         idesc->id_entryno++;
  260.     }
  261.     return (res);
  262. }
  263.