diff options
Diffstat (limited to 'ufs-fsck/pass1.c')
-rw-r--r-- | ufs-fsck/pass1.c | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/ufs-fsck/pass1.c b/ufs-fsck/pass1.c deleted file mode 100644 index bd41cc62..00000000 --- a/ufs-fsck/pass1.c +++ /dev/null @@ -1,437 +0,0 @@ -/* Pass one of GNU fsck -- count blocks and verify inodes - Copyright (C) 1994,95,96,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - - -#include "fsck.h" - -static struct dinode zino; - -/* Find all the blocks in use by files and filesystem reserved blocks. - Set them in the global block map. For each file, if a block is found - allocated twice, then record the block and inode in DUPLIST. - Initialize INODESTATE, LINKCOUNT, and TYPEMAP. */ -void -pass1 () -{ - ino_t number; - ino_t i; - int cg; - struct dinode dino; - struct dinode *dp = &dino; - mode_t mode, type; - int ndb; - int holdallblocks; - int lbn; - int nblocks; - int blkerror; - int nblkrngerrors; - int nblkduperrors; - - /* This function is called for each block of DP. Check to see - if the block number is valid. If so, set the entry in the - block map. If the block map entry is already set, then keep - track of this block and see if the user wants to clear the - node. Increment NBLOCKS by the number of data blocks held. - Set BLKERROR if this block is invalid. - Return RET_GOOD, RET_BAD, RET_STOP if the block is good, - bad, or if we should entirely stop checking blocks in this - inode. */ - int - checkblock (daddr_t bno, int nfrags, off_t offset) - { -#define MAXBAD 10 - int outofrange; - struct dups *dlp, *new; - int wasbad = 0; - - /* Check to see if this block is in range */ - outofrange = check_range (bno, nfrags); - if (outofrange) - { - blkerror = 1; - wasbad = 1; - if (nblkrngerrors == 0) - warning (0, "I=%Ld HAS BAD BLOCKS", number); - if (nblkrngerrors++ > MAXBAD) - { - problem (0, "EXCESSIVE BAD BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - } - - for (; nfrags > 0; bno++, nfrags--) - { - if (outofrange && check_range (bno, 1)) - warning (0, "BAD BLOCK %lu", bno); - else - { - if (!testbmap (bno)) - setbmap (bno); - else - { - blkerror = 1; - if (nblkduperrors == 0) - warning (0, "I=%Ld HAS DUPLICATE BLOCKS", number); - warning (0, "DUPLICATE BLOCK %ld", bno); - wasbad = 1; - if (nblkduperrors++ > MAXBAD) - { - problem (0, "EXCESSIVE DUP BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - new = malloc (sizeof (struct dups)); - new->dup = bno; - 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 == bno) - break; - if (dlp == muldup && dlp->dup != bno) - muldup = new; - } - } - nblocks += sblock->fs_fsize / DEV_BSIZE; - } - return wasbad ? RET_BAD : RET_GOOD; - } - - - /* Account for blocks used by meta data */ - for (cg = 0; cg < sblock->fs_ncg; cg++) - { - daddr_t firstdata, firstcgblock, bno; - - /* Each cylinder group past the first reserves data - from its cylinder group copy to (but not including) - the first datablock. - - The first, however, reserves from the very front of the - cylinder group (thus including the boot block), and it also - reserves the data blocks holding the csum information. */ - firstdata = cgdmin (sblock, cg); - if (cg == 0) - { - firstcgblock = cgbase (sblock, cg); - firstdata += howmany (sblock->fs_cssize, sblock->fs_fsize); - } - else - firstcgblock = cgsblock (sblock, cg); - - /* Mark the blocks set */ - for (bno = firstcgblock; bno < firstdata; bno++) - setbmap (bno); - } - - /* Loop through each inode, doing initial checks */ - for (number = 0, cg = 0; cg < sblock->fs_ncg; cg++) - for (i = 0; i < sblock->fs_ipg; i++, number++) - { - /* These record whether we've already complained about extra - direct/indirect blocks. */ - int dbwarn = 0, ibwarn = 0; - -/* if (!preen && !(number % 10000)) - printf ("I=%Ld\n", number); */ - - if (number < ROOTINO) - continue; - - getinode (number, dp); - mode = DI_MODE (dp); - type = mode & IFMT; - - /* If the node is not allocated, then make sure it's - properly clear */ - if (type == 0) - { - if (bcmp (dp->di_db, zino.di_db, NDADDR * sizeof (daddr_t)) - || bcmp (dp->di_ib, zino.di_ib, NIADDR * sizeof (daddr_t)) - || dp->di_trans - || DI_MODE (dp) - || dp->di_size) - { - problem (0, "PARTIALLY ALLOCATED INODE I=%Ld", number); - if (preen || reply ("CLEAR")) - { - clear_inode (number, dp); - pfix ("CLEARED"); - } - } - inodestate[number] = UNALLOC; - } - else - { - /* Node is allocated. */ - - /* Check to see if we think the node should be cleared */ - - /* Verify size for basic validity */ - holdallblocks = 0; - - if (dp->di_size + sblock->fs_bsize - 1 < dp->di_size) - { - problem (1, "OVERFLOW IN FILE SIZE I=%Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Decode type and set NDB - also set inodestate correctly. */ - inodestate[number] = REG; - switch (type) - { - case IFBLK: - case IFCHR: - ndb = 1; - break; - - case IFIFO: - case IFSOCK: - ndb = 0; - break; - - case IFLNK: - if (sblock->fs_maxsymlinklen != -1) - { - /* Check to see if this is a fastlink. The - old fast link format has fs_maxsymlinklen - of zero and di_blocks zero; the new format has - fs_maxsymlinklen set and we ignore di_blocks. - So check for either. */ - if ((sblock->fs_maxsymlinklen - && dp->di_size < sblock->fs_maxsymlinklen) - || (!sblock->fs_maxsymlinklen && !dp->di_blocks)) - { - /* Fake NDB value so that we will check - all the block pointers past the symlink */ - ndb = howmany (dp->di_size, sizeof (daddr_t)); - if (ndb > NDADDR) - { - int j = ndb - NDADDR; - for (ndb = 1; j > 1; i--) - ndb *= NINDIR (sblock); - ndb += NDADDR; - } - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - case IFDIR: - inodestate[number] = DIRECTORY; - /* Fall through */ - case IFREG: - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - default: - problem (1, "UNKNOWN FILE TYPE I=%Ld (MODE=%ol)", number, mode); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - holdallblocks = 1; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld " - "AS ALLOCATED", number); - ndb = 0; - } - - if (ndb < 0) - { - problem (1, "BAD FILE SIZE I= %Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Make sure that direct and indirect block pointers - past the file size are zero. If the size is bogus, then - don't bother (they should all be zero, but the user has - requested that they be treated as allocated). */ - if (!holdallblocks) - { - if (dp->di_size - && (type == IFBLK || type == IFCHR - || type == IFSOCK || type == IFIFO)) - { - problem (1, "SPECIAL NODE I=%Ld (MODE=%ol) HAS SIZE %lld", - number, mode, dp->di_size); - if (reply ("TRUNCATE")) - { - dp->di_size = 0; - write_inode (number, dp); - } - } - - /* If we haven't set NDB speciall above, then it is set from - the file size correctly by the size check. */ - - /* Check all the direct and indirect blocks that are past the - amount necessary to be zero. */ - for (lbn = ndb; lbn < NDADDR; lbn++) - { - if (dp->di_db[lbn]) - { - if (!dbwarn) - { - dbwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA DIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_db[lbn] = 0; - dbwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (dbwarn == 2) - dp->di_db[lbn] = 0; - } - if (dbwarn == 2) - write_inode (number, dp); - } - - for (lbn = 0, ndb -= NDADDR; ndb > 0; lbn++) - ndb /= NINDIR (sblock); - for (; lbn < NIADDR; lbn++) - { - if (dp->di_ib[lbn]) - { - if (ibwarn) - { - ibwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA INDIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_ib[lbn] = 0; - ibwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (ibwarn == 2) - dp->di_ib[lbn] = 0; - } - if (ibwarn == 2) - write_inode (number, dp); - } - } - - /* If this node is really allocated (as opposed to something - that we should clear but the user won't) then set LINKCOUNT - and TYPEMAP entries. */ - if (inodestate[number] != UNALLOC) - { - linkcount[number] = dp->di_nlink; - typemap[number] = IFTODT (mode); - } - - /* Iterate over the blocks of the file, - calling CHECKBLOCK for each file. */ - nblocks = 0; - blkerror = 0; - nblkduperrors = 0; - nblkrngerrors = 0; - allblock_iterate (dp, checkblock); - - if (blkerror) - { - if (preen) - warning (1, "DUPLICATE or BAD BLOCKS"); - else - { - problem (0, "I=%Ld has ", number); - if (nblkduperrors) - { - pextend ("%d DUPLICATE BLOCKS", nblkduperrors); - if (nblkrngerrors) - pextend (" and "); - } - if (nblkrngerrors) - pextend ("%d BAD BLOCKS", nblkrngerrors); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - else if (inodestate[number] == DIRECTORY) - inodestate[number] = BADDIR; - } - } - else if (dp->di_blocks != nblocks) - { - problem (0, "INCORRECT BLOCK COUNT I=%Ld (%ld should be %d)", - number, dp->di_blocks, nblocks); - if (preen || reply ("CORRECT")) - { - dp->di_blocks = nblocks; - write_inode (number, dp); - pfix ("CORRECTED"); - } - } - - num_files++; - - if (type == IFDIR) - record_directory (dp, number); - } - } -} |