2.11BSD/src/sbin/fsck/pass1.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#if	!defined(lint) && defined(DOSCCS)
/* static char sccsid[] = "@(#)pass1.c	5.3 (Berkeley) 5/13/86"; */
static char sccsid[] = "@(#)pass1.c	1.0 (2.11BSD) 9/13/90";
#endif not lint

#include <sys/param.h>
#include <sys/inode.h>
#include <sys/fs.h>
#include "fsck.h"

int pass1check();

pass1()
{
	register int j;
	register DINODE *dp;
	daddr_t ndb, lj;
	struct inodesc idesc;
	register ino_t inumber;

	/*
	 * Set file system reserved blocks in used block map.
	 */
	for (j = 0; j < fmin; j++)
		setbmap((daddr_t)j);
	/*
	 * Find all allocated blocks.
	 */
	bzero((char *)&idesc, sizeof(struct inodesc));
	idesc.id_type = ADDR;
	idesc.id_func = pass1check;
	n_files = n_blks = n_free = 0;
	for (inumber = ROOTINO; inumber < imax; inumber++) {
		dp = ginode(inumber);
		if (!ALLOC(dp)) {
			if (bcmp((char *)dp->di_addr, (char *)zino.di_addr,
				NADDR * sizeof(daddr_t)) ||
			    dp->di_mode || dp->di_size) {
				pfatal("PARTIALLY ALLOCATED INODE I=%u",
					inumber);
				if (reply("CLEAR") == 1) {
					zapino(dp);
					inodirty();
				}
			}
			setstate(inumber, USTATE);
			continue;
		}
		lastino = inumber;
		if (dp->di_size < 0) {
			printf("bad size %ld:", 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, DEV_BSIZE);
		if (SPECIAL(dp))
			ndb++;
/*
 * This check is not in 4.3BSD and is due to the fact that pipes in 2.11BSD
 * are still implemented using the filesystem.  Zero length files with blocks
 * (typically only the first direct block) allocated are the symptom.  It is
 * safe to clear the inode as the blocks will end up missing and be reclaimed
 * in pass5.
*/
		else if (dp->di_size == 0 && bcmp(dp->di_addr,
				zino.di_addr,NADDR* sizeof (daddr_t))) {
			pwarn("SIZE=0 FILE HAS ALLOCATED BLOCKS. I=%u",inumber);
			if (preen)
				printf(" (CLEARED)\n");
			if (preen || reply("CLEAR") == 1) {
				setstate(inumber, USTATE);
				zapino(dp);
				inodirty();
				continue;
			}
		}
		for (lj = ndb; lj < NDADDR; lj++) {
			j = lj;
			if (dp->di_addr[j] != 0) {
				if (debug)
					printf("bad direct di_addr[%d]: %ld\n",
						j, dp->di_addr[j]);
				goto unknown;
			}
		}
		for (j = 0, ndb -= NDADDR; ndb > 0; j++)
			ndb /= NINDIR;
		for (; j < NIADDR; j++)
			if (dp->di_addr[NDADDR + j] != 0) {
				if (debug)
					printf("bad indirect addr: %ld\n",
						dp->di_addr[NDADDR + j]);
				goto unknown;
			}
		if (ftypeok(dp) == 0)
			goto unknown;
		n_files++;
		setlncnt(inumber, dp->di_nlink);
		if (dp->di_nlink <= 0) {
			if (zlnp >= &zlnlist[MAXLNCNT]) {
				pfatal("LINK COUNT TABLE OVERFLOW");
				if (reply("CONTINUE") == 0)
					errexit("");
			} else
				*zlnp++ = inumber;
		}
		setstate(inumber, DIRCT(dp) ? DSTATE : FSTATE);
		badblk = dupblk = 0;
		idesc.id_number = inumber;
		(void)ckinode(dp, &idesc);
		continue;
unknown:
		pfatal("UNKNOWN FILE TYPE I=%u mode: %o", inumber, dp->di_mode);
		setstate(inumber, FCLEAR);
		if (reply("CLEAR") == 1) {
			setstate(inumber, USTATE);
			zapino(dp);
			inodirty();
		}
	}
}

pass1check(idesc)
	register struct inodesc *idesc;
{
	int res = KEEPON;
	daddr_t blkno = idesc->id_blkno;
	register daddr_t *dlp;

	if (outrange(blkno)) {
		blkerr(idesc->id_number, "BAD", blkno);
		if (++badblk >= MAXBAD) {
			pwarn("EXCESSIVE BAD BLKS I=%u", idesc->id_number);
			if (preen)
				printf(" (SKIPPING)\n");
			else if (reply("CONTINUE") == 0)
				errexit("");
			return (STOP);
		}
	return (SKIP);
	}
	if (!getbmap(blkno)) {
			n_blks++;
			setbmap(blkno);
	} else {
		blkerr(idesc->id_number, "DUP", blkno);
		if (++dupblk >= MAXDUP) {
			pwarn("EXCESSIVE DUP BLKS I=%u",
				idesc->id_number);
			if (preen)
				printf(" (SKIPPING)\n");
			else if (reply("CONTINUE") == 0)
				errexit("");
			return (STOP);
		}
		if (enddup >= &duplist[DUPTBLSIZE]) {
			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;
		}
	}
		/*
		 * count the number of blocks found in id_entryno
		 */
	idesc->id_entryno++;
	return (res);
}