pass1.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include "fsck.h"
/*
* for each large file ( size > MAXOFF_T) this global counter
* gets incremented here.
*/
extern uint_t largefile_count;
int pass1check();
struct dinode *getnextinode();
pass1()
{
uint_t c, i, j;
/*
* Set file system reserved blocks in used block map.
*/
if (c == 0) {
} else
for (; i < cgd; i++)
setbmap(i);
}
/*
* Record log blocks
*/
int i;
int j;
}
}
/*
* Find all allocated blocks.
*/
inumber = 0;
if (inumber < UFSROOTINO)
continue;
/* mode and type of file is not set */
pfatal("PARTIALLY ALLOCATED INODE I=%u",
inumber);
clearinode(dp);
inodirty();
}
}
continue;
}
if (debug)
printf("bad size %llu:",
goto unknown;
}
inodirty();
}
/* number of blocks is a 32 bit value */
if (ndb < 0) {
if (debug)
printf("bad size %llu ndb %d:",
goto unknown;
}
if (debug) {
printf("bad number of sectors %d: ",
}
inodirty();
if (debug) {
printf("new number of sectors "
}
}
for (j = 0; j < NDADDR; j++) {
if (debug) {
printf("special file contains value %d at indirect addr[%d] - should be 0\n",
}
goto unknown;
}
}
} else {
if (debug) {
printf("bad direct addr[%lld]: 0x%x mode:%o\n",
}
goto unknown;
}
}
for (; j < NIADDR; j++)
if (debug) {
printf("bad indirect addr: %d\n",
}
goto unknown;
}
goto unknown;
}
n_files++;
/*
* if errorlocked then open deleted files will
* manifest as di_nlink <= 0 and di_mode != 0
* so skip them; they're ok.
*/
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
errexit("");
} else {
}
}
/*
* Check for holes in a directory inode.
*
* Handle holes in direct blocks here.
* Holes in indirect blocks for large directories
* (>NDADDR blocks) will be checked in ckinode().
*/
idesc.id_hasholes = 0;
for (j = 0; j < ndb; j++) {
pwarn("DIRECTORY I=%d "
"HAS HOLES",
inumber);
if (preen)
printf("(CORRECTED)\n");
else if (reply("CORRECT") == 0)
break;
break;
} else {
}
}
if (idesc.id_hasholes) {
/*
* Move the existing entries in the
* direct block list, down.
*
* Do this only if the hole is
* not in the first block, or else
* the "." & the ".." entries will be
* missing and cannot be fixed.
* Such directories will get cleared.
*/
for (; j > 0 && j < ndb; j++) {
continue;
}
/*
* Clear out rest of the direct block
* entries as they could be non zero
* as a result of the above operation.
*/
j++)
/*
* Clear out indirect blocks, if any.
* We don't move indirect blocks down
* into the direct blocks, as it gets
* complicated.
*
* These blocks have not been accounted
* for yet. All the resulting orphaned
* directory entries will be taken
* care of in this run of pass1() and
* hence we do not need another run of
* fsck(no need for setting dirholes)
*/
for (j = 0; j < NIADDR; j++)
/*
* update the inode size & blocks count
*/
inodirty();
}
}
else
else
} else
if (debug)
printf("largefile: size=%lld,"
}
/*
* Check if we have holes in the directory's indirect
* blocks. Update the size. This requires another
* pass1 run (fsck once again).
*/
/*
* update the size
*/
/*
* Clear out indirect blocks in the
* inode beyond the new size.
*
* All the disk block pointers in the
* the indirect blocks past the hole
* will get cleared out by the pass1()
* run as part of the re-check.
*/
for (; j < NIADDR; j++)
inodirty();
/*
* flag that we need to re-check this
* filesystem to recover the blocks we
* just orphaned.
*/
dirholes = 1;
}
if (preen)
printf(" (CORRECTED)\n");
}
pwarn("INCORRECT BLOCK COUNT I=%u (%d should be %d)",
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
inodirty();
}
/*
* Check that the ACL is on a valid file type
*/
if (shadow != 0) {
pwarn("NON-ZERO ACL REFERENCE, I=%ld",
inumber);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
inodirty();
} else if ((shadow <= UFSROOTINO) ||
(shadow > maxinumber)) {
/*
* The shadow inode # must be realistic -
* either 0 or a real inode number.
*/
pwarn("BAD ACL REFERENCE I=%ld",
inumber);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
inodirty();
} else {
/*
*/
}
}
if (attrinode != 0) {
if ((attrinode <= UFSROOTINO) ||
(attrinode > maxinumber)) {
/*
* The attrdir inode # must be realistic -
* either 0 or a real inode number.
*/
pwarn("BAD ATTRIBUTE REFERENCE I=%ld"
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
dp->di_oeftflag = 0;
inodirty();
} else {
/*
*/
pwarn("BAD ATTRIBUTE DIR I=%ld"
if (preen)
" (CORRECTED)\n");
else if (reply("CORRECT") ==
0)
continue;
dp->di_oeftflag = 0;
inodirty();
} else {
}
}
}
continue;
} else
clearinode(dp);
inodirty();
}
}
}
freeinodebuf();
}
{
int anyout;
int nfrags;
pwarn("EXCESSIVE BAD BLKS I=%u",
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
errexit("");
return (STOP);
}
}
n_blks++;
} else {
pwarn("EXCESSIVE DUP BLKS I=%u",
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
errexit("");
return (STOP);
}
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
errexit("");
return (STOP);
}
if (muldup == 0) {
} else {
}
break;
}
/*
* count the number of blocks found in id_entryno
*/
idesc->id_entryno++;
}
return (res);
}