File:  [MW Coherent from dump] / coherent / d / etc / fsck.tar
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

fsck/Makefile   644      3      3        1224  5045007365   6404 #
#	for Inetco	: CFLAGS = -O -DHPCOHERENT
#	for PDP-11	: CFLAGS = -O
#	others		: CFLAGS =
#

DESTDIR=/interim/etc/
CFLAGS = -O
#
#	for PDP-11 and IBM PC:	LFLAGS = -i
#	for Z8000	     :	LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
	phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o

fsck:	$(OBJ)
	$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)

#
#	for IBM PC Coherent executable, use:  -DNBLK=1
#	for others, use			   :  -DNBLK=8
#
#	If you are running out of malloc space, try lowering the
#	value of NBLK (no smaller than 1).
#

util.o: util.c
	$(CC) -c $(CFLAGS) $< -DNBLK=8

$(OBJ):	fsck.h
M PC:	LFLAGS = -i
#	for Z8000	     :	LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
	phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o

fsck:	$(OBJ)
	$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)

#
#	for IBM PC Coherent executable, use:  -DNBLK=1
#	for others, use			   :  -DNBLK=8
#
#	If you are rfsck/RCS/   755      3      3           0  5050254740   5304 fsck/RCS/Makefile,v   444      3      3        2644  5045006646   7303 head     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3;
comment  @@;


1.3
date     91.07.29.07.44.07;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.03.15.18.33.07;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.08.13.26.09;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided byinitial version provided by epstein
@


1.3
log
@Updated by epstein for version 321.
@
text
@#
#	for Inetco	: CFLAGS = -O -DHPCOHERENT
#	for PDP-11	: CFLAGS = -O
#	others		: CFLAGS =
#
CFLAGS = -O
#
#	for PDP-11 and IBM PC:	LFLAGS = -i
#	for Z8000	     :	LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
	phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o

fsck:	$(OBJ)
	$(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)

#
#	for IBM PC Coherent executable, use:  -DNBLK=1
#	for others, use			   :  -DNBLK=8
#
#	If you are running out of malloc space, try lowering the
#	value of NBLK (no smaller than 1).
#

util.o: util.c
	$(CC) -c $(CFLAGS) util.c -DNBLK=8

$(OBJ):	fsck.h
@


1.2
log
@bob h added destdir, ownership, permissions...
@
text
@a6 1
DESTDIR = /interim/etc/
d16 2
a17 4
	$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
	su root chown bin $(DESTDIR)$@@
	su root chgrp bin $(DESTDIR)$@@
	su root chmod 511 $(DESTDIR)$@@
@


1.1
log
@Initial revision
@
text
@d7 1
d17 4
a20 2
	$(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)

@
unning out of malloc space, try lowering the
#	value of NBLK (no smaller than 1).
#

util.o:fsck/RCS/READ_ME,v   444      3      3        1565  4754523421   6664 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @@;


1.1
date     91.02.08.13.26.37;  author bin;  state Exp;
branches ;
next	;


desc
@updated version provided by epstein
@



1.1
log
@Initial revision
@
text
@Ideas for improving the performance of fsck:

(1)  Utilize a different mechanism for storing the (struct direct)
     entries throughout phase2.c, to remove implicit memory intensive
     redundancy.

(2)  Encode the number of links per i-node count differently, in order
     to save space taking advantage of the typical usage under Coherent.

(3)  Arrange space for the tables in a total needed way to avoid later
     fragmentation problems affecting the memory requests for successive
     file systems.

(4)  Devise a more clever buffering scheme for the blocks containing
     i-nodes to understand the differences between phase1, phase2, and
     phase4.
@
ove implicit memory intensive
     redundancy.

(2)  Encode the number of links per i-node count differently, in order
     to save space tfsck/RCS/cleanup.c,v   444      3      3        2652  4753557355   7452 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.35.30;  author bin;  state Exp;
branches ;
next	;


desc
@provided by Mark Epstein
@



1.1
log
@Initial revision
@
text
@/*
 *	Cleanup functions for phases of fsck
 */

#include "fsck.h"

cleanup()
{
	int retval = 0;

	if (sbpfix == TRUE) 
		writesuper();
	prtstats();
	if (changeflg == TRUE)
		retval = advise();
	close(fsfd);
	cleanV();
	return(retval);
}

writesuper()
{
	register int i;

	canshort(sbp->s_isize);
	candaddr(sbp->s_fsize);
	canshort(sbp->s_nfree);
	for(i=0; i<NICFREE; i++)
		candaddr(sbp->s_free[i]);
	canshort(sbp->s_ninode);
	for(i=0; i<NICINOD; i++)
		canino(sbp->s_inode[i]);
	cantime(sbp->s_time);
	candaddr(sbp->s_tfree);
	canino(sbp->s_tinode);
	canshort(sbp->s_m);
	canshort(sbp->s_n);
	canlong(sbp->s_unique);

	bwrite((daddr_t)SUPERI, sbp);
}

prtstats()
{
	if (!fflag)
		printf("%u files ", numfiles);
	printf("%U blocks ", fsize - isize - totfree);
	printf("%U free\n", totfree);
	if ( lostsize ) {
		lostsize = (lostsize + BSIZE - 1)/BSIZE;
		printf("Expect roughly %U missing block%s next\n", lostsize,
				(lostsize!=1) ? "s" : "" );
		printf("time fsck is run as a result of inodes ");
		printf("being cleared.\n");
	}
}

advise()
{
	int retval = 0;

	printf(" ***** File System %s was modified *****\n", fsname);
	if ( mounted ) {
		printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
		retval = 1;
	}
	return(retval);
}
@
ocks ", fsize - isize - totfree);
	printf("%U free\n", totfree);
	if ( lostsize ) {
		fsck/RCS/fsck.h,v   444      3      3       14557  4771205357   6775 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.45.54;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.08.13.26.49;  author bin;  state Exp;
branches ;
next	;


desc
@updated version provided by epstein
@


1.2
log
@update provided by epstein
@
text
@/*
 *	Header file for fsck  --  File System Check Program
 *
 */

#include <canon.h>
#include <sys/dir.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

#if HPCOHERENT
typedef long fsize_t;
#endif

/*
 *	Conditional Compilation Flags
 */

#define NOT_ALL_ZERO_INODE	/* Dependent on whether or not an inode */
#ifdef 	ALL_ZERO_INODE		/* is totally zeroed when unallocated   */
#undef	ALL_ZERO_INODE		/* or simply a zero mode and zero link  */
#endif


/*
 *	Definitions and Externs
 */

#define NUL	0		/* true zero ! */
#define NULL	((char *)0)

#define	YES	3		/* default actions */
#define	NO	2
#define ASK	1

#define	NFILSYS	10		/* max number of file systems */
#define	MAXCH	20		/* max length of filesys name */

#define	MAXBADOK	10	/* Max number of bad blocks before excessive */
extern	int numbad;		/* num bad blocks found so far this inode*/

#define MAXDUPOK	10	/* Max number of dup blocks */
				/* in a single inode before excessive */
#define	DUPTBLSIZE	20	/* Max number of dup referenced blocks */
extern	daddr_t	dupblck[];	/* table of duplicate referenced blocks */
extern 	int totdups;		/* number of dup blocks found so far */

#define MAXBADFREE	10	/* max bad in free list before abort */
#define MAXDUPFREE	10	/* max dup in free list before abort */

#define GOOD	1		/* returned by bad() in util.c */
#define	BAD	0

#define	TRUE	1		/* errflag possibilities */
#define	FALSE	0
extern 	int	errflag;	/* errflag indicates not to do phases */

#define OK	1		/* used to indicate excessive bad/dup */
#define STOP	0		/* blocks in an inode in phase1.c     */
#define BAD_DUP	2

#define FIRSTIN	2		/* First real inode number */

#define	ND	10		/* Number of Direct Blocks */
#undef	NI
#define	NI	1
#define	NII	1
#define	NIII	1
#undef	NADDR
#define	NADDR	(ND+NI+NII+NIII)
extern	int	offsets[];	/* table of offsets for level of indirection */
				/* for the blocks in an inode */

extern	char	nextchar();	/* used in util.c */
extern	int	fsfd;		/* file system file descriptor */
extern 	int	mdaction;	/* default action for this invocation */
extern 	int	daction;	/* default action for current file system */
extern  int 	writeflg;	/* system write ok or read-only */
extern  int	qflag;		/* quiet fsck flag */
extern	int	fflag;		/* fast fsck flag */
extern	int	sflag;		/* force free list salvation	*/
extern	daddr_t	fsize;		/* file system size in blocks */
extern	int	isize;		/* first block not in inode list */
				/* isize is NOT unsigned so that comparisons */
				/* with longs will not cast the long to */
				/* unsigned thus producing confusing results */

extern  daddr_t	totfree;	/* running count of total free blocks */
extern 	unsigned	ninodes;/* Number of inodes in the files system */
extern 	char	*fsname;	/* file system name */
extern  fsize_t  pinfo();	/* returns size of file, in phase2.c */
extern	ino_t	lostfound();	/* returns inumber of lost+found dir */
extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
extern 	char databuf[];		/* buffer to read in block, used throughout */
extern	char buf2[];		/* alternate data buffer */
extern 	daddr_t	cdbn;		/* current block number, used by nextblock() */
#define DSIZE	(sizeof(struct direct))
extern 	char *lostname;		/* name of lost+found directory */
extern  char *nameit();		/* nameing function for lost dirs and files */
extern 	int	depth;		/* used during tree traversal in phase2.c */
extern  struct direct *path[]; 	/* used during tree traversal in phase2.c */
extern	char	*typename();	/* return string to type of inode */
extern 	struct filsys *sbp;	/* Super Block */
extern 	int	sbpfix;		/* flag for super block fixes */
extern  struct stat stats;	/* used by statit() in util.c */
extern	dev_t	rootdev;	/* root device number */
extern	dev_t	fsysrdev;	/* file system real device number */
extern	int	mounted;	/* flag indicating mountedness of filesystem */
extern 	int	changeflg;	/* file system modified flag */
extern 	int	fixerup;	/* flag to rebuild free list */
extern	char	*fixit;		/* Prompt message phase[45].c */
extern 	int	numfiles;	/* num files in system */
extern	daddr_t	imap();		/* function for disk block mapping in util.c */
extern	fsize_t	lostsize;	/* Size of files cleared in phase4.c */
extern	char 	*tmpfile;	/* TMP File name for virtual.c */

#define SUCCESS	1		/* used in connect() in phase3.c */
#define FAILURE	0

#define	MODEMASK	0x07
#define ALLOCMASK	0x06
#define UNALLOC		0x00
#define UNKNOWN		0x01
#define	IDIR		0x02
#define	IREG		0x03
#define ICHR		0x04
#define IBLK		0x05
#define IPIPE		0x06
#define IBAD_IDUP	0x08
#define VISITED		0x10
#define UNREFDIR	0x20
#define CHILDDIR	0x40
#define IFREELIST	0x80

/*
 *	Macros for tables
 */

#define	LOGNBPC	3		/* Log2 Number of Bits per Character    */

/* Actions for virtual block system */
enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
	    testDup, markDup, unmarkDup, setDup,
	    Flags, setFlags, orFlags,
	    linkCtr, incLinkctr, setLinkctr };
	      
#define testblock(bn)  findblock((unsigned long)(bn), testBlock)
#define markblock(bn)  findblock((unsigned long)(bn), markBlock)
#define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)

#define testdup(bn) findblock((unsigned long)(bn), testDup)
#define markdup(bn) findblock((unsigned long)(bn), markDup)
#define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)

#define flags(ino) findblock((unsigned long)(ino), Flags)
#define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
#define orflags(ino, data)  findblock((unsigned long)(ino), orFlags, data)

#define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)

#define badblks(ino)	( flags(ino)&IBAD_IDUP )

/*
 *	Miscellany
 */

#define	NBPC	8			/* number of bits per character */
#define	MAXINTN	255			/* used for interleave table	*/
					/* in phase6.c			*/
/*
 *	Stdio Stuff
 */

#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc();

@


1.1
log
@Initial revision
@
text
@d85 1
@
ne inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)

#fsck/RCS/init.c,v   444      3      3       14501  5045006666   6767 head     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.07.29.07.44.33;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.05.16.36.03;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by epstein
@


1.2
log
@Updated by epstein for version 321.
@
text
@/*
 *	Perform initialization for phases of fsck
 */
#include "fsck.h"
#include <mnttab.h>
#include <mtab.h>

int	fsfd;				/* file system file descriptor */
int	writeflg;			/* write ok or read-only flag */
daddr_t	fsize = SUPERI+1;		/* file system size in blocks  */
					/* Allows for read of Super Block */
int	isize;				/* First block not in inode list */
daddr_t	totfree;			/* Running total free block count */
unsigned	ninodes;		/* number of inodes */
int	numfiles;			/* number of files in file system */

char	superb[BSIZE];			/* Super Block */
struct filsys *sbp = superb;
int	sbpfix;				/* flag for super block fixes */

int	offsets[] = 			/* table of offsets for the levels */
		{ ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
		  ND+NI+NII+NIII };     /* inode block list */

daddr_t	dupblck[DUPTBLSIZE];		/* duplicate referenced blocks */
int	totdups;			/* number of dup blocks so far */

init()
{
	int mode;
	struct stat status;
	unsigned short stmode;

	mode = (mdaction == NO) ? 0 : 2;

	if ( (fsfd = open(fsname, mode)) == (-1) ) {
		mode = 0;
		if ( (fsfd = open(fsname, mode)) == (-1) ) {
			nonfatal("Can't open: %s", fsname);
			return;
		}
	}

	if (mode == 0) {
		daction  = NO;
		writeflg = FALSE;
	} else {
		daction  = mdaction;
		writeflg = TRUE;
	}
	
	printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");

	if ( fstat(fsfd, &status) == (-1) ) {
		nonfatal("Can't stat: %s", fsname);
		return;
	}

	stmode = status.st_mode & S_IFMT;
	if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) ) 
		switch(query("file is not a block or character device; OK?")){
		case YES:
			break;
		case NO:
			errflag = TRUE;
			return;
		}

	domount();
	sbpfix = FALSE;
	readsuper();
	checksuper();
	if ( !errflag )
		alloctables();
}

/*
 *	Read in the super block and canonicalize
 */

readsuper()
{
	register int i;

	bread((daddr_t)SUPERI, superb);
	sbp = superb;

	canshort(sbp->s_isize);
	candaddr(sbp->s_fsize);
	canshort(sbp->s_nfree);
	for(i=0; i<NICFREE; i++)
		candaddr(sbp->s_free[i]);
	canshort(sbp->s_ninode);
	for(i=0; i<NICINOD; i++)
		canino(sbp->s_inode[i]);
	cantime(sbp->s_time);
	candaddr(sbp->s_tfree);
	canino(sbp->s_tinode);
	canshort(sbp->s_m);
	canshort(sbp->s_n);
	canlong(sbp->s_unique);

}

/*
 *	Check super block for obvious inconsistencies
 */

checksuper()
{
	fsize = sbp->s_fsize;
	isize = sbp->s_isize;
	totfree = fsize - isize;
	
	if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
 		badsuper("Size check: fsize %U isize %u", fsize, isize);
		errflag = TRUE;
	}

	if ( sbp->s_nfree > NICFREE )
		badsuper("Too large free block count");

	if ( sbp->s_ninode > NICINOD )
		badsuper("Too large free i-node count");
}

/*
 *	Super Block Error Functions
 */

badsuper(x)
{
	printf("%r\n", &x);
	printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
}

/*
 *	Allocate the necessary buffers for tables
 */

alloctables()
{
	unsigned num, numl;

	numl = 0;
	if (!fflag) {
		ninodes = (unsigned) (isize - INODEI) * INOPB;
		numl = (unsigned) ninodes;
	}
	
	num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
	initV(numl, numl, num, num); /* virtual allocation */

	numfiles =		/* number of files in the file system */
	totdups = 0;		/* num dup blocks */
}

/*
 *	domount() checks the files /etc/mnttab and /etc/mtab to find
 * 	out where the file system is mounted (if at all).  It then 
 *	reports where (and when if possible) it was last mounted.
 */
char *mnttab_name = "/etc/mnttab";
char *mtab_name	  = "/etc/mtab";
char *bttime_name = "/etc/boottime";

domount()
{
	int fd;
	struct mnttab mnttab;
	struct mtab mtab;
	register char *name;
	struct stat sbuf;
	time_t boottime;
	int nothing();
	char devname[MNTNSIZ+6] = "/dev/";

	mounted = FALSE;
	name = fsname;				/* strip off all initial */
	while (*name++ != '\0') ;		/* directories in fsname */
	while ( (*--name != '/') && (name>fsname) ) ;
	if (*name == '/') name++;

	if ( stat(bttime_name, &sbuf) == -1 )
		boottime = (time_t)0;
	else
		boottime = sbuf.st_mtime;
				
	if ( (fd=open(mnttab_name, 0)) != (-1) ) {
		while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) ) 
			if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
				strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
				devname[MNTNSIZ+5] = '\0';
				statit(devname, nothing);
				if (stats.st_rdev != fsysrdev)
					continue;
				statit(mnttab.mt_dev, nothing);
				mounted = (stats.st_dev == fsysrdev);
				prmnttab(&mnttab, boottime);
				return;
			}
	}
	if ( (fd=open(mtab_name, 0)) != (-1) ) {
		while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) ) 
			if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
				strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
				devname[MNAMSIZ+5] = '\0';
				statit(devname, nothing);
				if (stats.st_rdev != fsysrdev)
					continue;
				statit(mtab.mt_name, nothing);
				mounted = (stats.st_dev == fsysrdev);
				prmtab(&mtab);
				return;
			}
	}

	if (fsysrdev == rootdev)
		mounted = TRUE;
	else
		mounted = FALSE;

}

prmnttab(ptr, boottime)
struct mnttab *ptr;
time_t boottime;
{
	if (mounted) {
		if (boottime < ptr->mt_time)
			boottime = ptr->mt_time;
		printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ, 
					ptr->mt_dev, ctime(&boottime));
	} else
		printf("%s unmounted.  Last mounted on %.*s -- %s",
						fsname, MNTNSIZ, ptr->mt_dev,
							ctime(&ptr->mt_time));
}


prmtab(ptr)
struct mtab *ptr;
{
	if (mounted)
		printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
	else
		printf("%s unmounted.  Last mounted on %.*s\n", fsname,
							MNAMSIZ, ptr->mt_name);
}

nothing()
{}
@


1.1
log
@Initial revision
@
text
@d176 1
d178 1
d191 11
a201 10
			if (mnttab.mt_dev[0] != '\0') 
				if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
					statit(mnttab.mt_dev, nothing);
					if (stats.st_dev == fsysrdev)
						mounted = TRUE;
					else
						mounted = FALSE;
					prmnttab(&mnttab, boottime);
					return;
				}
d205 11
a215 10
			if (mtab.mt_name[0] != '\0')
				if ( strcmp(name, mtab.mt_special) == 0 ) {
					statit(mtab.mt_name, nothing);
					if (stats.st_dev == fsysrdev)
						mounted = TRUE;
					else
						mounted = FALSE;
					prmtab(&mtab);
					return;
				}
@
mt_dev[0] != '\0') 
				if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
					statit(mnttab.mt_dev, nothing);
					if (stats.st_dev == fsysrdev)
						mounted = TRUE;
					else
						mounted = FAfsck/RCS/is_fs.c,v   444      3      3        4004  4753557413   7112 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.36.22;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein
@



1.1
log
@Initial revision
@
text
@#include <sys/stat.h>
#include <canon.h>
#include <sys/filsys.h>

/*
 * Check if a special file is a well-formed filesystem.
 * This routine is derived from code in "mount.c".
 * Return values:
 *	-1	Not a device, cannot open, read or seek failed
 *	0	No filesystem
 *	1	Legal filesystem
 */
int
is_fs(special) char *special;
{
	static struct filsys f;
	struct stat sbuf;
	register int fd;
	register struct filsys *fp;
	register daddr_t *dp;
	register ino_t *ip, maxinode;

	if (stat(special, &sbuf) < 0)
		return -1;			/* cannot stat device */
	else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
	      && (sbuf.st_mode&S_IFMT) != S_IFCHR)
		return -1;			/* not a special file */
	else if ((fd = open(special, 2)) < 0)
		return -1;			/* cannot open */
	else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
	      || read(fd, &f, sizeof(f)) != sizeof(f)) {
		close(fd);
		return -1;			/* seek or read failed */
	} else
		close(fd);			/* so far so good */

	/* Canonical stuff. */
	fp = &f;
	canshort(fp->s_isize);
	candaddr(fp->s_fsize);
	canshort(fp->s_nfree);
	for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
		candaddr(*dp);
	canshort(fp->s_ninode);
	for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
		canino(*ip);
	candaddr(fp->s_tfree);
	canino(fp->s_tinode);

	/* Test for rationality. */
	maxinode = (fp->s_isize - INODEI) * INOPB + 1;
	if (fp->s_isize >= fp->s_fsize)
		return 0;
	if ((fp->s_tfree < fp->s_nfree)
	||  (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
		return 0;
	if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
		return 0;
	for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
		if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
			return 0;
	for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
		if ((*ip < 1) || (*ip > maxinode))
			return 0;
	return 1;
}
@
 INODEI) * INOPB + 1;
	if (fp->s_isize >= fp->s_fsize)
		return 0;
	if ((fp->s_tfree < fp->s_nfree)
	||  (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
		return 0;
	if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
		return 0;
	for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
		if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
			return 0;
	for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
		if ((*ip < 1) || (*ip > maxinode))
			return 0;
	return 1;
fsck/RCS/link.c,v   444      3      3        3277  4753557430   6756 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.36.34;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein
@



1.1
log
@Initial revision
@
text
@/*
 *	Routines to handle the counting of links for each i-node
 */

#include "fsck.h"

linkincr(inum)
ino_t inum;
{
	if (inclinkctr(inum) == 0 )
		fatal("Too many links in i-node, %d", inum);
}

/*
 *	The following is the beginning of thinking of how to change
 *	the number of bits used in the link count tables from 8-per
 *	i-node to 2-per i-node, with additional tables for those
 *	i-nodes with more than 2 links.  The changes would be to the
 *	definition of i_lnks, the macro linkctr(), the function linkincr(),
 *	and in init.c, the allocation of table space.
 */

#ifdef	NEWLINKSTUFFF

char	*linkmap;	/* table of inodes with one link */

#define testlink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
			  3 << (((unsigned)bn)&(NBPC>>1)) )
#define marklink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
			  1 << (((unsigned)bn)&(NBPC-2)) )
#define unmarklink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
			  1 << (((unsigned)bn)&(NBPC-2)) )

linkcntr(inum)
ino_t inum;
{
	index = ((unsigned) inum) >> (LOGNBPC-1) ;
	distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
	mask = 3 << distance;
	answer = ( linkmap[index] & mask ) >> distance;

	if ( answer < 3 )
		return(answer);

	hash = inum & 0xFF;
	bucket = &linktable[hash];
	bktinum = bucket->inumb;

	if ( bktinum == inum ) {
		answer = bucket->numlink;
		if ( answer == 0xFF )
			return( bigcntr(inum) );
		else
			return( answer + 3 );
	}

	if ( bktinum > inum )
		fatal("internal linktable corruption.");

	
}

linkincr(inum)
ino_t inum;
{
}

#endif
@
m) >> (LOGNBPC-1) ;
	distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
	mask = 3 << distance;
	answer = ( linkmap[index] & mask ) >> distance;

	if ( answer < 3 )
		return(answer);

	hash = inum & 0xFF;
	bucket = &linktable[hash];
	bktinum = bucket->inumb;

	if ( bktinum == inum ) {
		answer = bucket->numlink;
		if ( ansfsck/RCS/main.c,v   444      3      3       15241  5045006700   6737 head     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3;
comment  @ * @;


1.3
date     91.07.29.07.44.44;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.03.18.18.43.33;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.05.16.36.45;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by epstein
@


1.3
log
@Updated by epstein for version 321.
@
text
@/*					
 * fsck  --  File System Check Program
 * an interactive file system check and repair program.
 *
 * Usage:
 *	/etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
 *	audit and interactively repair inconsistent conditions for
 *  	file systems.  Options -y and -n indicate an assumed response
 *	to all questions asked by fsck.  Default is to prompt operator
 *	for yes/no response.  Option -q is to quiet fsck from printing
 *	certain messages, i.e. no size check messages, unreferenced
 *	pipes will be silently removed, and counts in the superblock
 *	will be automatically fixed and free list salvaged, if necessary.
 *	Option -f is for a 'fast' check of the file system, i.e. only
 *	check blocks, sizes, superblock counts, and the free list.
 *	(-f) does not check pathnames, connectivity, or reference
 *	counts.  Option -s forces the reconstruction (or salvaging) of
 *	both the free inode list and the free block list, even if there
 *	are no file system problems.  This will reorder the free block
 *	list in the best order to limit additional fragmentation (respecting
 *	interleaving as well).  Note: Option -s will be ignored on mounted
 *	file systems.  The option -S acts in the same manner as -s except
 *	that it will not be ignored on mounted file systems.  Beware: -S
 *	on mounted file systems should only be used if you intend to reboot
 *	NO SYNC immediately afterwards.  Option -t sets the temporary file
 *	to use for disk caching of necessary tables on filesystems which are
 *	too big to do in core. The temporary file defaults to "/dev/rram1",
 *	which must be there.
 */

#include "fsck.h"

int	errflag;

int	mdaction;			/* default action for invocation */
int	daction;			/* default action for file system */
int	gSflag=FALSE;			/* force salvage flag ignored mounted */
int	gsflag=FALSE;			/* force salvage flag ignored mounted */
int	sflag=FALSE;			/* force salvage flag	*/
int	qflag=FALSE;			/* fsck quiet flag	*/
int	fflag=FALSE;			/* fsck fast flag	*/

char *tmpfile = NULL;			/* TMP file for virtual.c */
char *checklistfile = "/etc/checklist";	/* default file for list of file */
					/* systems to fsck. */
char *filelist[NFILSYS];		/* list of filesystems */
char word[MAXCH];			/* hold single words */
char *fsname;				/* file system name */

dev_t	rootdev;			/* root device number */
dev_t	fsysrdev;			/* file system real device number */
int	mounted;			/* flag for mounted file system */

int	changeflg;			/* file system modified flag */

main(argc, argv)
char *argv[];
{
	int yflag=0, nflag=0;
	int retval;

	while (argc>1 && *argv[1]=='-') {
		switch (argv[1][1]) {
		case 'q':
			qflag = TRUE;
			break;
		case 'y':
			yflag = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'f':
			fflag = TRUE;
			break;
		case 'S':
			gSflag = TRUE;
			break;
		case 's':
			gsflag = TRUE;
			break;
		case 't':
			tmpfile = argv[2];
			argc--;
			argv++;
			break;
		default:
			usage();
			break;
		}
	
		argc--;
		argv++;
	}
	
	if ( yflag+nflag > 1 )
		usage();

	mdaction = ( yflag ? YES :
		    nflag ? NO : ASK );

	if ( argc > 1 )
		retval = allfsck(argv+1);
	else {
		getlist();
		retval = allfsck(filelist);
	}
	exit(retval);
}


/*
 *	perform fsck on each of the individual filesystem in list
 */

allfsck(fsl)
register char **fsl;
{
	int fatal();
	int retval = 0;

	sync();
	statit("/", fatal);
	rootdev = stats.st_dev;
	while (*fsl != NULL)
		retval |= fsck(*fsl++);
	return(retval);
}

/* 
 *  	get the names of the filesystems from the default file
 *	checklistfile  (e.g. /etc/checklist)
 */

getlist()
{
	int fd;
	int index, size;

	if ( (fd = open(checklistfile, 0)) == (-1) )
		fatal("Can't open checklist file: %s", checklistfile);

	index = 0;
	while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
                filelist[index] = malloc( size );
		strcpy(filelist[index++], word);
	}

	if (size != 0) 
		fatal("Too many file systems in checklist file: %s",
							checklistfile);

	filelist[index] = NULL;

	close(fd);
}

/*
 *	read in the next "word" from file with descriptor fd
 *  	return the length of the word.
 */

getword(fd)
int fd;
{
	int n = 0, num;
	char *cp = word;
	char ch;

	while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
		( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );

	if (num != 1)
		return(0);

	do {
		*cp++ = ch;
	} while (  (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
		(ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
	
	*cp = '\0';

	return(n+1);
}
	
/*
 *	perform fsck on the given filesystem
 */
fsck(name)
char *name;
{
	int retval = 1;
	int nonfatal();

	fsname = name;		/* file system name */
	errflag = FALSE;
	statit(fsname, nonfatal);
	fsysrdev = stats.st_rdev;
	if ( errflag )
		return(retval);
	changeflg = FALSE;
	init();
	if ( sflag = ((gsflag && !mounted) || gSflag) )
		printf("Switch \"-s\" selected to automatically rebuild free lists\n");
	if (!sflag && gsflag)
		printf("Ignoring \"-s\" on mounted file system\n");
	if ( !errflag ) {
		phase1();	/* check blocks and sizes */
		if ( !fflag ) {
			phase2();	/* check pathnames        */
			phase3();	/* check connectivity     */
			phase4();	/* check reference counts */
		}
		phase5();	/* check free list	  */
		phase6();	/* salvage free list	  */
		retval = cleanup();
	}
	return(retval);
}

usage()
{
	printf("\
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
	_exit(1);
}
@


1.2
log
@update provided by epstein
@
text
@d6 1
a6 1
 *	/etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]
d21 7
a27 3
 *	interleaving as well). Option -t sets the temporary file to use
 *	for disk caching of necessary tables on filesystems which are too
 *	big to do in core. The temporary file defaults to "/dev/rram1",
d37 2
d76 3
d80 1
a80 1
			sflag = TRUE;
d203 4
d224 1
a224 1
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]\n");
@


1.1
log
@Initial revision
@
text
@d6 1
a6 1
 *	/etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
d17 8
a24 4
 *	counts. Option -t sets the temporary file to use for disk caching
 *	of necessary tables on filesystems which are too big to do in core.
 *	The temporary file defaults to "/dev/rram1", which must be there.
 *
d33 3
a35 2
int	qflag=FALSE;			/* fsck quiet flag */
int	fflag=FALSE;			/* fsck fast flag */
d70 3
d211 1
a211 1
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]\n");
@
g
@Initial revision
@
text
@d6 1
a6 1
 *	/etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
d17 8
a24 4
 *	counts. Option -t sets the temporary file to use for disk caching
 *	of necessary tables on filesystems which are too big to do in core.
 *	The temporary file defaults to "/dev/rram1", which must be there.
 *
d33 3
a35 2
int	qflag=FALSfsck/RCS/phase1.c,v   444      3      3       16554  4771205175   7220 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.43.50;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.05.16.36.59;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein
@


1.2
log
@update provided by epstein
@
text
@/*
 *	phase 1 of fsck - Check Blocks and Sizes
 */

#include "fsck.h"

char	databuf[BSIZE];		/* buffer for blocks */

int	clrflg;			/* indicates when to clear an inode */
int	dupflag;		/* indicates whether there are any dups */

int	numbad;			/* number of bad blocks in the inode   */
int	numdup;			/* number of duplicate blocks in inode */
long	numblks;		/* number of data blks for size check */
long	sparsecnt;		/* count for sparse blocks for size check */

/*  The following is a table of the number of direct blocks pointed at by the
 *  four types of blocks direct, ..., triple-indirect, to help count sparse
 *  blocks.
 */

daddr_t	blockcnt[] = {1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN};

phase1()
{
	if (!qflag)
		printf("Phase 1 : Check Blocks and Sizes\n");
	dupflag = FALSE;
	inodescan();
	if (dupflag)
		phase1b();	
}

inodescan()
{
	register daddr_t bn;
	register struct dinode *dip;
	register ino_t	ino;
	int i;

	ino = 1;

	for (bn=INODEI; bn<isize; bn++) {
		if (testblock(bn)) {		/* block is bad via inode 1 */
			ino += INOPB;
			continue;
		}
		bread(bn, databuf);
		clrflg = FALSE;
		dip = (struct dinode *) databuf;
		for (i=0; i<INOPB; i++) {
			candino(dip);
			if (inuse(dip) == TRUE) {
				if (!fflag) 
					checkmode(dip, ino);
				if ( checkblks(dip, ino) != STOP ) 
					if ( qflag == FALSE )
						checksize(dip, ino);
			}
			candino(dip);
			ino++;
			dip++;
		}
		if (clrflg)
			bwrite(bn, databuf);
	}
}

/*
 *  	Determine if the given inode is in use.
 */

inuse(dip)
register struct dinode *dip;
{
#ifdef NOT_ALL_ZERO_INODE

	if ( (dip->di_mode != 0) || (dip->di_nlink != 0) )
		return(TRUE);
	else
		return(FALSE);
#endif
#ifdef ALL_ZERO_INODE

	register char *ptr;
	register struct dinode *next;

	ptr = (char *) dip;
	next = dip + 1;
	while (ptr < next)
		if (*ptr++ != 0)
			return(TRUE);

	return(FALSE);
#endif
}

/*
 *	Check the mode of the given inode
 */

checkmode(dip, ino)
register struct dinode *dip;
register ino_t	ino;
{
	register unsigned short	mode;

	mode = dip->di_mode & IFMT;

	switch (mode) {
	case IFREG:
		setflags(ino, IREG);
		return;
	case IFDIR:
		setflags(ino, IDIR);
		return;
	case IFCHR:
		setflags(ino, ICHR);
		return;
	case IFBLK:
		setflags(ino, IBLK);
		return;
	case IFPIPE:
		setflags(ino, IPIPE);
		return;
	default:
		setflags(ino, UNKNOWN);
		break;
	}

	switch ( query("Unknown File Type i-number = %u (Clear)", ino) ){
	case NO:
		return;
	case YES:
		zeroinode(dip);
		setflags(ino, UNALLOC);
		clrflg = TRUE;
		break;
	}
}

/*
 *	Zero the given inode
 */

zeroinode(dip)
struct dinode *dip;
{
	register char *ptr;
	register struct dinode *next;

	lostsize += dip->di_size;
	next = dip+1;
	ptr = (char *) dip;

	while (ptr < next)
		*ptr++ = 0;

}

/*
 *	Check the blocks associated with the given inode to determine
 *	if any are bad or duplicate
 */

checkblks(dip, ino)
struct dinode *dip;
ino_t	ino;
{
	daddr_t	addrs[NADDR];
	register daddr_t bn;
	register int i, lev;
	register int mode;

	mode = dip->di_mode & IFMT;

	if ( (mode != IFREG) && (mode != IFDIR) )
		return(STOP);

	l3tol(addrs, dip->di_addr, NADDR);

	numbad = 			/* number of bad blocks so far */
	numdup = 			/* num dup blocks so far THIS INODE */
	numblks =			/* num used data blocks for size chk */
	sparsecnt = 0;			/* count of missed data blocks	*/

	for(i=0; i<NADDR; i++)
		for (lev=0; lev<4; lev++) 
			if (i < offsets[lev]) {
				if ( (bn=addrs[i]) != 0 ) {
					if (doblocks(bn, ino, lev) != OK)
						return(STOP);
				} else
					sparsecnt += blockcnt[lev];
				break;
			}
	return(OK);
}

/*
 *	Checks recursively the blocks pointed at via
 *	the inode list of blocks.  'bn' is the block number,
 *	'ino' is the inode referencing it, and 'lev' is the
 *	level 0 == direct ... 3 = triple-indirect
 */

doblocks(bn, ino, lev)
register daddr_t bn;
ino_t	ino;
int	lev;
{
	char buf[BSIZE];
	register daddr_t *bnptr;
	register char *end;
	register int flag;

	if (lev-- == 0)	{		/* we have a direct block */
		numblks += sparsecnt + 1;
		sparsecnt = 0;
		return(dodirect(bn, ino));
	} else {
		end = &buf[BSIZE];
		if ( (flag=dodirect(bn, ino)) == OK ) {
			bread(bn, buf);
			bnptr = (long *) buf;
			while ( bnptr < end ) {
				bn = *bnptr++;
				candaddr(bn);
				if ( bn == 0 ) {
					sparsecnt += blockcnt[lev];
					continue;
				}
				if ( doblocks(bn, ino, lev) == STOP )
					return(STOP);
			}
			return(OK);
		} else 
			return(flag);
	}
}
			
/*
 *	Check the given block to determine if it is bad
 * 	or if it is a duplicate.  'ino' is the inode referencing it
 */

dodirect(bn, ino)
register daddr_t bn;
register ino_t ino;
{
	register int flag;
	
	if ( (flag=checkbad(bn, ino)) == OK ) 
		return( checkdup(bn, ino) );
	else
		return(flag);
}

/*
 *	Check the given block number for being bad.
 */

checkbad(bn, ino)
register daddr_t bn;
ino_t	ino;
{
	if ( (bn>=isize) && (bn<fsize) )
		return(OK);

	else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
							/* bad block is in  */
		totfree++;				/* the inode blocks */
		return(OK);
	}
		
	if (!fflag)
		orflags(ino, IBAD_IDUP);

	printf("Bad block %U, i-number = %u\n", bn, ino);

	if (numbad++ < MAXBADOK)
		return(BAD_DUP);

	switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
	case NO:
		abort();
	case YES:
		return(STOP);
	}
}


/*
 *	Check the given block number for duplicate reference.
 */

checkdup(bn, ino)
register daddr_t bn;
ino_t	ino;
{
	if ( !testblock(bn) ) {
		markblock(bn);
		totfree--;
		return(OK);
	}

	dupflag = TRUE;
	if (!fflag)
		orflags(ino, IBAD_IDUP);
	printf("Dup Block %U, i-number = %u\n", bn, ino);

	if (totdups < DUPTBLSIZE) 
		dupblck[totdups++] = bn;
	else {
		switch ( query("DUP Table Overflow (Continue)") ) {
		case NO:
			abort();
		case YES:
			return(BAD_DUP);
		}
	}

	if (numdup++ < MAXDUPOK)
		return(BAD_DUP);

	switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
	case NO:
		abort();
	case YES:
		return(STOP);
	}
}

/*
 *	Check For Possible File Size Error 
 */

checksize(dip, ino)
register struct dinode *dip;
ino_t	ino;
{
	register int mode;
	register fsize_t size;

	mode = dip->di_mode & IFMT;
	size = dip->di_size;
	
	if ( mode == IFREG )
		filesize(ino, size);
	else	/* mode == IFDIR */
		dirsize(dip, ino, size);
}

dirsize(dip, ino, size)
struct dinode *dip;
ino_t ino;
register fsize_t size;
{
	if ( size <= 0 ) {
		switch ( query("\
Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
		case NO:
			break;
		case YES:
			zeroinode(dip);
			setflags(ino, UNALLOC);
			clrflg = TRUE;
			return;
		}
	}

	if ( size < (2*DSIZE) )
		printf("Directory Size too small i-number = %u\n", ino);

	if ( size % sizeof(struct direct) != 0 )
		printf("Directory Misaligned i-number = %u\n", ino);

	if (sizerr(size))
		printf("Possible Directory Size Error i-number = %u\n", ino);
}

filesize(ino, size)
ino_t ino;
register fsize_t size;
{
	if (sizerr(size))
		printf("Possible File Size Error i-number = %u\n", ino);
}

sizerr(size)
register fsize_t size;
{
	register fsize_t calc;

	calc = (unsigned long)numblks*BSIZE;
	if ( (size > calc) || ( calc >= (size+BSIZE) ) ) 
		return(TRUE);
	else
		return(FALSE);
}
@


1.1
log
@Initial revision
@
text
@d152 1
d252 1
a252 1

@
saligned i-number = %u\n", ino);

	if (sizerr(size))
		printf("Possible Directory Size Error i-number = %u\n", ino);
}

filesize(ino, size)
ino_t infsck/RCS/phase1b.c,v   444      3      3        4676  4753557476   7362 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.37.12;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein
@



1.1
log
@Initial revision
@
text
@/*
 *	Phase 1b of fsck - Rescan for more Dups
 */

#include "fsck.h"

extern int	numdup;		/* declared in phase1.c */

phase1b()
{
	if (!qflag)
		printf("Phase 1b: Rescan for more Dups\n");
	buildtable();
	iscanb();
}

buildtable()
{
	unsigned cntr=0, numdiff=0;
	daddr_t bn;

	while (cntr<totdups) {
		bn = dupblck[cntr++];
		if (!testdup(bn)) {
			markdup(bn);
			numdiff++;
		}
	}
	totdups = numdiff;
}

iscanb()
{
	register daddr_t bn;
	register struct dinode *dip;
	register ino_t	ino;
	int i;

	ino = 1;

	for (bn=INODEI; bn<isize; bn++) {
		if (testblock(bn)) {		/* block is bad via inode 1 */
			ino += INOPB;
			continue;
		}
		bread(bn, databuf);
		dip = (struct dinode *) databuf;
		for (i=0; i<INOPB; i++) {
			candino(dip);
			if (inuse(dip) == TRUE) 
				ckblksb(dip, ino);
			if (totdups == 0)
				return;			
			ino++;
			dip++;
		}
	}
}

/*
 *	Check the blocks associated with the given inode to find the
 *	remaining duplicate blocks
 */

ckblksb(dip, ino)
register struct dinode *dip;
register ino_t	ino;
{
	daddr_t	addrs[NADDR];
	int i, lev;
	int mode;

	mode = dip->di_mode & IFMT;

	if ( (mode != IFREG) && (mode != IFDIR) )
		return;

	l3tol(addrs, dip->di_addr, NADDR);

	numdup = 0;			/* num dup blocks so far THIS INODE */

	for(i=0; i<NADDR; i++)
		for (lev=0; lev<4; lev++) 
			if (i < offsets[lev]) {
				dblocksb(addrs[i], ino, lev);
				break;
			}
}

/*
 *	Checks recursively the blocks pointed at via
 *	the inode list of blocks.  'bn' is the block number,
 *	'ino' is the inode referencing it, and 'lev' is the
 *	level 0 == direct ... 3 = triple-indirect
 */

dblocksb(bn, ino, lev)
daddr_t	bn;
ino_t	ino;
int	lev;
{
	char buf[BSIZE];
	int  i;
	daddr_t	*bnptr;

	if (bn == 0)
		return(OK);
		
	switch ( cdupb(bn, ino) ) {
	case OK:
		if (lev--==0)
			return(OK);
		bread(bn, buf);
		bnptr = (long *) buf;
		for (i=0; i<NBN; i++) {
			bn = bnptr[i];
			candaddr(bn);
			if ( dblocksb(bn, ino, lev) == STOP )
				return(STOP);
		}
		return(OK);
	case STOP:
		return(STOP);
	}
}

/*
 *	Check the given block number for duplicate reference.
 */

cdupb(bn, ino)
daddr_t	bn;
ino_t	ino;
{
	if ( !testdup(bn) ) 
		return(OK);

	totdups--;
	unmarkdup(bn);
	if (!fflag)
		orflags(ino, IBAD_IDUP);
	printf("Dup Block %U, i-number = %u\n", bn, ino);

	return(STOP);
}
@
)
			return(OK);
		bread(bn, buf);
		bnptr = (long *) buf;
		for (fsck/RCS/phase2.c,v   444      3      3       17750  4771205232   7212 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.44.18;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.05.16.37.24;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein
@


1.2
log
@update provided by epstein
@
text
@/*
 *	phase 2 of fsck - Check Pathnames
 */

#include "fsck.h"
#include <pwd.h>

#define MAXDEPTH 50
struct	direct *path[MAXDEPTH];
int 	depth;
int 	fixflag;			/* flags when must rewrite databuf  */
daddr_t blocknum;			/* Current block num read in        */

typedef struct list {
	struct direct d_entry;
	struct list *next;
} list;

char	buf2[BSIZE];			/* buffer for blocks		*/
daddr_t	cdbn;				/* current logical block number */

/*	Format errors, args to blkerr() */

#define	NULLNAME	5
#define	NULLPAD		6
#define SLASHES		7
#define DOT		8
#define DOTDOT		9

phase2()
{
	if (!qflag)
		printf("Phase 2 : Check Pathnames\n");
	checkroot();
	depth = 0;
	checkpath(ROOTIN);
}


checkroot()
{
	if ( (flags(ROOTIN)&MODEMASK) == UNALLOC )
		fatal("Root i-node is unallocated.  Terminating");

	if ( (flags(ROOTIN)&MODEMASK) != IDIR ) {
		switch ( query("Root i-node is not a directory (FIX)") ){
		case YES:
			fixroot();
			break;
		case NO:
			abort();
		}
	}
	
	if ( badblks(ROOTIN) ){
		switch ( query("Dup/Bad blocks in root i-node (Continue)") ) {
		case YES:
			break;
		case NO:
			abort();
		}
	}
	linkincr(ROOTIN);		/* (?) Feature (?) of mkfs is  */
					/* that root inode of a file   */
					/* system has a link count one */
					/* too large.		       */
}

fixroot()
{
	register struct dinode *dip;

	if (!writeflg) 
		fatal("File System Read-Only (NO WRITE)\n");

	setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR);

	/* Save change to disk */
	
	dip = ptrino(ROOTIN, databuf);
	dip->di_mode &= (~IFMT);
	dip->di_mode |= IFDIR;
	writeino(ROOTIN, databuf);
}

#define	myinum	( (depth>0) ? path[depth-1]->d_ino : ROOTIN )
#define popinum	( (depth>1) ? path[depth-2]->d_ino : ROOTIN )

char *memory = "Can't malloc memory, phase 2";

list *
procfiles(addrs, length)
daddr_t *addrs;
fsize_t length;
{
	register struct direct *elemnt;
	register list *first, *ptr;

	if ((first=ptr=(list *)malloc(sizeof(list)))==NULL)
		fatal(memory);
	first->d_entry.d_ino = 0;
	first->next = NULL;
	if ( length < DSIZE )
		return( first );
	cdbn = 0;
	nextblock(addrs);
	fixflag = FALSE;
	elemnt = (struct direct *) databuf;
	cdots(elemnt++, ".", myinum, DOT);
	++numfiles;
	if ( (length-=DSIZE) < DSIZE )
		return( first );
	cdots(elemnt++, "..", popinum, DOTDOT);
	++numfiles;
	length -= DSIZE;

	while ( length >= DSIZE ) {
		while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if (chck(elemnt)==IDIR) {
				copy(elemnt, &ptr->d_entry, 
						sizeof(struct direct));
				if ((ptr->next=(list *)malloc(sizeof(list))) ==
					NULL)
					fatal(memory);
				ptr = ptr->next;
				ptr->d_entry.d_ino = 0;
				ptr->next = NULL;
			}
			elemnt++;
			length -= DSIZE;
		}
		if (fixflag && (fixblock(addrs) == NUL) )
			fixblkerr();
		nextblock(addrs);
		fixflag = FALSE;
		elemnt = (struct direct *) databuf;
	}
	return(first);	 
}

candblock(dptr)
register struct direct *dptr;
{
	register int num, i;

	num = BSIZE/sizeof(struct direct);
	for (i=0; i<num; i++)
		canino(dptr[i].d_ino);
}

nextblock(addrs)
register daddr_t *addrs;
{
	register daddr_t bn;

	if ( (bn=imap(addrs, cdbn++)) == 0 ) {
		bclear(databuf, BSIZE);
		return;
	}
	bread(bn, databuf);
	candblock(databuf);
	blocknum = bn;
}

fixblock(addrs)
daddr_t *addrs;
{
	daddr_t bn;

	if ( (bn=imap(addrs, cdbn-1)) == 0 ) 
		return(NUL);
	candblock(databuf);
	bwrite(bn, databuf);
	return(TRUE);
}

fixblkerr()
{
	fatal("Fixblock error.");
}

copy(from, to, size)
register char *from, *to;
register int size;
{
	while (size--)
		*to++=*from++;
}

cdots(elemnt, dots, ino, type)
register struct direct *elemnt;
char *dots;
ino_t ino;	/* what the inode number should be */
int type;
{
	register char *name = elemnt->d_name;
	register ino_t inum;

	inum = elemnt->d_ino;
	if ( (strcmp(name, dots) != 0) || (inum != ino) ||
		(format(name) != GOOD) ) {
		blkerr(type);
		return;
	}
	linkincr(inum);
}

format(name)
register char *name;
{
	register char *ptr=name;
	register char *end=&name[DIRSIZ];

	while ( (ptr<end) && (*ptr++ != '\0') ) ;

	if ( (ptr-1) == name )
		return(NULLNAME);
	
	if (ptr<end) {
		while ( (ptr<end) && (*ptr++ == '\0') ) ;
		if (ptr!=end)
			return(NULLPAD);
	}

	ptr = name;
	while (ptr < end) 
		if (*ptr++ == '/')
			return(SLASHES);

	return(GOOD);
}

	
blkerr(type)
int type;
{	
	char *errname;

	switch(type) {
	case NULLNAME:
		errname = "Null name";
		break;
	case NULLPAD:
		errname = "Non null padded";
		break;
	case SLASHES:
		errname = "Embedded slashes in";
		break;
	case DOT:
		errname = "Inconsistent .";
		break;
	case DOTDOT:
		errname = "Inconsistent ..";
		break;
	default:
		errname = "Bad";
		break;
	}

	printf("%s entry in block %U in directory\n", errname, blocknum);
	pinfo(myinum);
	pname(path[--depth]->d_name);
	depth++;
}

chck(elemnt)
register struct direct *elemnt;
{
	register ino_t inum;
	register char *name;
	int type;

	inum = elemnt->d_ino;
	if ( inum == 0 )
		return(UNALLOC);

	name = elemnt->d_name;
	if ( (type=format(name)) != GOOD )
		blkerr(type);

	if (inum>ninodes) {
		if ( irange(inum, name) ) 
			zeroent(elemnt);
		return(UNALLOC);
	}

	if ( (flags(inum)&ALLOCMASK)==UNALLOC ) {
		if ( unalloc(inum, name) )
			zeroent(elemnt);
		return(UNALLOC);
	}

	if ( badblks(inum) ) {
		if ( baddup(inum, name) ) {
			zeroent(elemnt);
			return(UNALLOC);
		}
		if ( (flags(inum)&MODEMASK)==IDIR )
			return(UNALLOC);
	}

	linkincr(inum);
	numfiles++;
	return( flags(inum)&MODEMASK );
}

zeroent(elemnt)
struct direct *elemnt;
{
	elemnt->d_ino = 0;
	fixflag = TRUE;
}

pname(name)
char *name;
{
	int i=0;

	while (i<depth) 
		prdirsize(path[i++]->d_name);
	prdirsize(name);
	putchar('\n');
}

prdirsize(name)
char *name;
{
	if (name[DIRSIZ-1] == '\0')
		printf("/%s", name);
	else
		printf("/%*s", DIRSIZ, name);
}

fsize_t
pinfo(inum)
ino_t inum;
{
	register struct dinode *dip;
	register struct passwd *pwd;

	if ( (dip=ptrino(inum, buf2)) == NULL ) {
		printf("i-number = %u is in a bad inode block.\n", inum);
		return(0);
	}

	printf("i-number = %u, ", inum);
	if ( (pwd=getpwuid(dip->di_uid)) != NULL )
		printf("Owner=%s, ", pwd->pw_name);
	else
		printf("Owner=%u, ", dip->di_uid);
	printf(" Mode=0%o\n", dip->di_mode);
	printf("Size=%U, Mtime=%s", dip->di_size, ctime(&dip->di_mtime));
	return(dip->di_size);
}

char *remove = "(Remove)";

irange(inum, name)
ino_t inum;
char *name;
{
	printf("I-number is out of range  I=%u\n", inum);
	pname(name);
	return(action(remove));
}

unalloc(inum, name)
ino_t inum;
char *name;
{	
	fsize_t size;

	printf("Unallocated\n");
	size = pinfo(inum);
	pname(name);
	if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) {
		printf("%s [Forced - Yes]\n", remove);
		return(YES);
	}
	return(action(remove));
}

baddup(inum, name)
ino_t inum;
char *name;
{
	register int mode = flags(inum)&MODEMASK;

	printf("Bad or Dup blocks in %s\n",(mode==IDIR) ? "Directory" : "File");
	pinfo(inum);
	pname(name);
	return(action(remove));
}

checkpath(ino)
register ino_t ino;
{
	static daddr_t	addrs[NADDR];
	static struct dinode *dip;
	static list *temp;
	register list *ptr;

	if ( (flags(ino)&VISITED)==VISITED ) {
		circle(ino);
		return;
	} else
		orflags(ino, VISITED);

	dip = ptrino(ino, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	
	if ( (dip->di_mode&IFMT) != IFDIR )
		fatal("Tried to checkpath i-node %u which is not dir.\n", ino);

	ptr = procfiles(addrs, dip->di_size);

	while (ptr->d_entry.d_ino) {
		if (depth >= MAXDEPTH)
			toolong();
		path[depth++] = &ptr->d_entry;
		checkpath(ptr->d_entry.d_ino);
		depth--;
		temp = ptr;
		ptr = ptr->next;
		free(temp);
	}
	free(ptr);
}

circle(ino)
ino_t ino;
{
	printf("I-node %u is a multiply referenced directory i-node.\n", ino);
}

toolong()
{
	printf("Name too long.\n");
	pname("\0");
	abort();
}

	
@


1.1
log
@Initial revision
@
text
@d102 3
d110 3
d114 2
a115 2
	numfiles += 2;
	length -= 2*DSIZE;		/* for the . & .. entries */
d127 1
@
r->d_entry.d_ino) {
		iffsck/RCS/phase3.c,v   444      3      3       12752  5050254731   7207 head     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.08.08.09.48.33;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.05.16.37.54;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by epstein (post 310)
@


1.2
log
@updated by epstein to properly handle directory allocations.
@
text
@/*
 *	phase 3 of fsck - Check Connectivity
 */

#include "fsck.h"

char *lostname = "lost+found";

phase3()
{
	ino_t i;

	if (!qflag)
		printf("Phase 3 : Check Connectivity\n");
	for (i=FIRSTIN; i<=ninodes; i++) 
		if ( ((flags(i)&MODEMASK) == IDIR) &&
		     (linkctr(i) == 0) ) {
			orflags(i, UNREFDIR);
			markchildren(i);
		}

	for (i=FIRSTIN; i<ninodes; i++)
		if ( (flags(i)&(UNREFDIR|CHILDDIR)) == UNREFDIR )
			unrefdir(i);
}

markchildren(ino)
ino_t ino;
{
	struct dinode *dip;
	struct direct *element;
	daddr_t	addrs[NADDR];
	ino_t inumber;
	fsize_t length;

	if ( badblks(ino) )
		return;
	dip = ptrino(ino, databuf);
	if ( (length=dip->di_size) <= 0 )
		return;
	l3tol(addrs, dip->di_addr, NADDR);
	cdbn = 0;
	nextblock(addrs);
	element = (struct direct *) databuf;
	element += 2;		/* skip over . and .. entries */
	if ( (length-=2*DSIZE) <= 0 )
		return;

	while ( length >= DSIZE ) {
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( ((inumber=element->d_ino) != 0) &&
			     ((flags(inumber)&MODEMASK)==IDIR) &&
			     (inumber!=ino) )
				orflags(inumber, CHILDDIR);
			element++;
			length -= DSIZE;
		}
		nextblock(addrs);
		element = (struct direct *) databuf;
	}
}

char *reconnect = "(Reconnect)";

unrefdir(ino)
ino_t ino;
{
	printf("Unref Dir\n");
	if( (pinfo(ino) == 0) || (daction == NO) || (mounted == TRUE) ) {
		if ( action(reconnect) == FALSE )
			return;
	} else 
		printf("%s FORCED\n", reconnect);

	connect(ino, IDIR);
}

#define CONNECT		1
#define NOCONNECT	0

connect(ino, type)
ino_t ino;
int type;
{
	ino_t lostino;
	struct dinode *dip;
	daddr_t addrs[NADDR];
	fsize_t length;
	struct direct *element;
	int chgino = FALSE;

	if ( ((lostino=lostfound()) == NUL) ||
		 ((flags(lostino)&MODEMASK) != IDIR) ||
			( badblks(lostino) ) ) {
		nolost();
		if (type==IDIR)
			traverse(NOCONNECT, ino, lostino);
		return(FAILURE);
	}

	dip = ptrino(lostino, buf2);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length>=DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( element<&databuf[BSIZE] ) {
			length -= DSIZE;
			if ( element->d_ino == 0 ) {
				element->d_ino = ino;
				strncpy(element->d_name, nameit(ino), DIRSIZ);
				if ( fixblock(addrs) == NUL )
					fixblkerr();
				linkincr(ino);
				numfiles++;
				if ( length<0 ) {
					dip->di_size -= length;
					chgino = TRUE;
				}
				if ( (type == IDIR) &&
				     (connected(ino, lostino)==YES) ) {
					dip->di_nlink++;
					writeino(lostino, buf2);
					traverse(CONNECT, ino, lostino);
				} else if (chgino) {
					writeino(lostino, buf2);
				}
				return(SUCCESS);
			}
			element++;
		}
	}
	
	noroom();
	if (type == IDIR)
		traverse(NOCONNECT, ino, lostino);
	return(FAILURE);
}

traverse(flag, ino, lostino)
int flag;
ino_t ino, lostino;
{
	struct direct dirlost, nothing, newtree;

	dirinit(&dirlost, lostino, lostname);
	dirinit(&nothing, 0, "??");
	dirinit(&newtree, ino, nameit(ino));
	depth = 0;
	if (flag == CONNECT) 
		path[depth++] = &dirlost;
	else
		path[depth++] = &nothing;

	path[depth++] = &newtree;
	checkpath(ino);
}

dirinit(element, ino, name)
struct direct *element;
ino_t ino;
char *name;
{
	element->d_ino = ino;
	strncpy(element->d_name, name, DIRSIZ);
}

connected(ino, lostino)
ino_t ino;		/* inumber just reconnected	  */
ino_t lostino;		/* inumber of lostfound directory */
{
	struct dinode *dip;
	daddr_t addrs[NADDR];
	fsize_t length;
	struct direct *element;

	if ( badblks(ino) ) {
		badconnect(ino);
		return(NO);
	}
	dip = ptrino(ino, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length >= DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( strcmp(element->d_name, "..") == 0 ) {
				printf("Dir i-number = %u connected.  ", ino);
				printf("Parent was i-number = %u.\n",
							element->d_ino);
				element->d_ino = lostino;
				if ( fixblock(addrs) == NUL )
					fixblkerr();
				return(YES);
			}
			length -= DSIZE;
			element++;
		}
	}
	noparent(ino);
	return(NO);
}

badconnect(ino)
ino_t ino;
{
	printf("Dir i-number = %u connected.  It has bad/dup blocks.\n", ino);
}

noparent(ino)
ino_t ino;
{
	printf("Dir i-number = %u connected.  It has no .. entry.\n", ino);
}

ino_t
lostfound()
{
	static daddr_t addrs[NADDR];
	struct dinode *dip;
	struct direct *element;
	fsize_t length;

	dip = ptrino(ROOTIN, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length>=DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( strcmp(element->d_name, lostname) == 0 ) 
				return(element->d_ino);
			length -= DSIZE;
			element++;
		}
	}

	return(NUL);
}

nolost()
{
	printf("Sorry.  No %s directory.\n", lostname);

}

noroom()
{
	printf("Sorry.  No space in %s directory.\n", lostname);
}

char namebuf[DIRSIZ];

char *
nameit(ino)
register ino_t ino;
{
	register int i = DIRSIZ-1;

	namebuf[i] = '\0';
	while ( (ino != 0) && (i>0) ) {
		namebuf[--i] = '0' + ino%10;
		ino = ino/10;
	}
	return(&namebuf[i]);
}
@


1.1
log
@Initial revision
@
text
@d109 1
a130 1
			length -= DSIZE;
@
eturn(element->d_ino);fsck/RCS/phase4.c,v   444      3      3       12033  4771205260   7202 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.44.48;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.05.16.38.17;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein (post 310)
@


1.2
log
@update provided by epstein
@
text
@/*
 *	phase 4 of fsck - Check Reference Counts
 */

#include "fsck.h"

extern char *reconnect;
fsize_t	lostsize;

phase4()
{
	ino_t i;
	short actlink;

	if (!qflag)
		printf("Phase 4 : Check Reference Counts\n");
	for (i=FIRSTIN; i<=ninodes; i++) {
		if ( badblks(i) )
			if ( bddp(i) == YES )
				continue;	/* inode zeroed */

		if ( (linkctr(i) == 0) &&
		     ((flags(i)&MODEMASK) != IDIR) &&
		     ((flags(i)&ALLOCMASK) != UNALLOC) )
			if ( unreflink(i) == YES )
				continue;	/* inode zeroed */

		if ( (linkctr(i) == 0) &&
		     ((flags(i)&ALLOCMASK) != UNALLOC)  )
			if ( unrefclr(i) == YES )
				continue;	/* inode zeroed */

		if ( (actlink=getlink(i)) == (-1) ) {
			i += INOPB-1;
			continue;		/* bad inode block */
		}

		if ( actlink != linkctr(i) )
			linkprob(i, actlink);	/* fix link count */
	}

	freeilist();
}

short
getlink(inum)
register ino_t inum;
{
	register unsigned offset;
	static ibuf[BSIZE];
	register struct dinode *dip;
	register daddr_t bn;

	offset = iblocko(inum);
	if ( (offset==0) || (inum==FIRSTIN) ) {
		bn = iblockn(inum);
		if ( (testblock(bn)) && (inum!=FIRSTIN) ) 
			return(-1);
		bread(bn, ibuf);
	}
	dip = ((struct dinode *) ibuf) + offset;
	candino(dip);
	return(dip->di_nlink);
}

char *clearit = "(Clear i-node)";

unreflink(ino)
ino_t ino;
{
	fsize_t size;

	if ( (qflag == TRUE) && ((flags(ino)&MODEMASK) == IPIPE) ) {
		doclear(ino);
		return(YES);
	}

	printf("Unref %s\n", typename(ino));
	size = pinfo(ino);
	if ( (daction != NO) && (size == 0) && (mounted == FALSE) 
		&& ((flags(ino)&MODEMASK) == IREG) ) {
		printf("%s [Forced - Yes]\n", clearit);
		doclear(ino);
		return(YES);
	}
	if ( action(reconnect) == TRUE )
		if( connect(ino, IREG) == FAILURE )  /* connect back in the */
			return(askclear(ino));	     /* non dir inode	    */
			
	return(NO);
}

askclear(ino)
ino_t ino;
{
	if ( action(clearit) == TRUE ) {
		doclear(ino);
		return(YES);
	}
	return(NO);
}

doclear(ino)
ino_t ino;
{
	struct dinode *dip;

	dip = ptrino(ino, databuf);
	zeroinode(dip);
	writeino(ino, databuf);
	setflags(ino, UNALLOC);
	setlinkctr(ino, 0);
}

char *adjust = "(Adjust)";

linkprob(ino, actlink)
ino_t ino;
short actlink;
{
	printf("Link Count discrepancy in %s\n", typename(ino));
	pinfo(ino);
	printf("Count = %u, should be %u ", actlink, linkctr(ino));
	if ( action(adjust) == TRUE )
		chglink(ino);
}

chglink(ino)
ino_t ino;
{
	struct dinode *dip;

	dip = ptrino(ino, databuf);
	dip->di_nlink = linkctr(ino);
	writeino(ino, databuf);
}
	
unrefclr(ino)
ino_t ino;
{
	printf("Unref %s\n", typename(ino));
	pinfo(ino);
	return(askclear(ino));
}

bddp(ino)
ino_t ino;
{
	printf("Bad/Dup blocks in %s\n", typename(ino));
	pinfo(ino);
	return(askclear(ino));
}

char *fixit = "(FIX)";

freeilist()
{
	ino_t i, count=0;
	daddr_t bn;

	for (i=FIRSTIN; i<=ninodes; i++)
		if ( (flags(i)&ALLOCMASK) == UNALLOC )
			count++;

	for (bn=INODEI+1; bn<isize; bn++)	/* block # INODEI can't */
		if ( testblock(bn) )		/* be bad since ROOTIN  */
			count -= INOPB;		/* is in it, otherwise  */
						/* big time bad news.	*/
	if ( sbp->s_tinode != count ) 
		if ( (qflag==FALSE) && (daction!=NO) ) {
			printf("Free i-node count wrong in superblock.  ");
			if ( action(fixit) == TRUE ) {
				sbp->s_tinode = count;
				sbpfix = TRUE;
			}
		} else {
			sbp->s_tinode = count;
			sbpfix = TRUE;
		}

	if ( (daction!=NO) &&
	     ( (sflag==TRUE) || (sbpfix==TRUE) || (badilist()==BAD) ) )
	 	rebuild();

}

badilist()
{
	ino_t i, inum;
	unsigned numfree;
	daddr_t bn;

	if ( (numfree=(unsigned) sbp->s_ninode) > NICINOD )
		return(BAD);
	for (i=0; i<numfree; i++) {
		inum = sbp->s_inode[i];
		bn = iblockn(inum);
		if ( (testblock(bn)) && (bn!=INODEI) )
			return(BAD);
		if ( (inum < FIRSTIN) || (inum > ninodes) )
			return(BAD);
		if ( (flags(inum)&ALLOCMASK) != UNALLOC ) 
			return(BAD);
		if ( flags(inum)&IFREELIST )
			return(BAD);		/* dup in ifree list */
		orflags(inum, IFREELIST);
	}
	return(GOOD);
}

rebuild()
{
	daddr_t bn;
	ino_t i;
	int index;

	sbpfix = TRUE;
	for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) {
		if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
			bn = iblockn(i);
			if ( (!testblock(bn)) || (bn==INODEI) )
				index++;
		}
	}
	sbp->s_ninode = index;
	for (i=FIRSTIN; (i<=ninodes) && (index>0); i++) {
		if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
			bn = iblockn(i);
			if ( (!testblock(bn)) || (bn==INODEI) )
				sbp->s_inode[--index] = i;
		}
	}
	printf("Free i-node list in superblock rebuilt.\n");
}
@


1.1
log
@Initial revision
@
text
@a16 1
	lostsize = 0;
a108 1
	lostsize += dip->di_size;
d181 2
a182 1
	if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) ) 
d214 2
a215 2
	ino_t i = FIRSTIN;
	int index = 0;
d218 1
a218 1
	while ( (i<=ninodes) && (index<NICINOD) ) {
d222 1
a222 1
				sbp->s_inode[index++] = i;
a223 1
		i++;
a224 1

d226 7
@
		bn = iblockn(i);
			if ( (!testblock(bn)) || (bn==INODEI) )
				sbp->s_inode[--index] = i;
		}
	}
	printf("Free i-node list in superblock rebuilt.\n");
}
@


1.1
log
@Initial revision
@
text
@a16 1
	lostsize = 0;
a108 1
	lostsize += dip->di_size;
d181 2
a182 1
	if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) ) 
d214 2
a215 2
	ino_t i = FIRSTIN;
	int index = 0;
d218 1
a218 1
	while ( (i<=ninodes) && (index<NICINOD) ) {
d222 1
a222 1
				sbp->s_inode[index++] = i;
a223fsck/RCS/phase5.c,v   444      3      3        7463  4771205275   7204 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.45.05;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.05.16.38.33;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein (phase5.c)
@


1.2
log
@update provided by epstein
@
text
@/*
 *	phase 5 of fsck - Check Free List
 */

#include "fsck.h"

daddr_t	badcnt;			/* Number of bad blocks in free list */
daddr_t dupcnt;			/* Number of dup blocks in free list */
int	badflag;		/* Bad free list flag */
int 	fixerup;		/* Flag to salvage free list */

phase5()
{
	struct fblk *fbp;
	unsigned size;
	
	if (!qflag)
		printf("Phase 5 : Check Free List\n");
	fbp = (struct fblk *) &sbp->s_nfree;
	size = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
	copyV(size);
	badcnt = dupcnt = 0;
	badflag = FALSE;
	freetrav(fbp);
	fixerup = FALSE;
	if (badflag || sflag) 
		asksalvage();
}


#define	IGNORE	3		/* Return Possibilities from chk() */
#define	ABORT	4		/* as well as perhaps GOOD and BAD */

freetrav(fbp)
struct fblk *fbp;
{
	daddr_t total=0;
	int i, flag;

	while ( fbp->df_nfree != 0 ) {
		if ( (unsigned) fbp->df_nfree > NICFREE ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
		for (i=1; i<fbp->df_nfree; i++) {
			if ( (flag=chk(fbp->df_free[i])) == GOOD ) {
				total++;
				continue;
			}
			if (flag == BAD)
				continue;
			break;		/* break for IGNORE or ABORT	*/
		}
		if ( (flag == IGNORE) || (flag == ABORT) )
			break;
		if ( chk(fbp->df_free[0]) != GOOD )
			break;
		total++;
		bread(fbp->df_free[0], databuf);
		fbp = (struct fblk *) databuf;
		if ( !canfblk(fbp) ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
	}

#if 0
	printf("Total traversed free blocks     = %U\n", total);	 
	printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);	 
	printf("Running total free blocks       = %U\n", totfree);	 
#endif

	if ( flag == ABORT ) { 		/* To Terminate fsck on this 	*/
		badflag = FALSE;	/* File System, because of	*/
		return;			/* excessive dup or bad blocks	*/
	}

	if ( sbp->s_tfree != totfree )
		if ( (qflag==FALSE) && (daction!=NO) ) {
			printf("Free Block count wrong in superblock.  ");
			if ( action(fixit) == TRUE ) {
				sbp->s_tfree = totfree;
				sbpfix = TRUE;
			}
		} else {
			sbp->s_tfree = totfree;
			sbpfix = TRUE;
		}

	report("%U Bad Block%s in Free List\n", badcnt);
	report("%U Dup Block%s in Free List\n", dupcnt);
	report("%U Block%s missing\n", totfree - total);

}

report(message, num)
char *message;
daddr_t num;
{
	if ( num != 0 ) {
		printf(message, num, ( (num>1) ? "s" : "" ) );
		badflag = TRUE;
	}
}

chk(bn)
register daddr_t bn;
{
	if ( (bn<isize) || (bn>=fsize) ) {
		badflag = TRUE;
		if (++badcnt > MAXBADFREE) 
			return( stopit("bad") );
		return(BAD);
	}

	if ( testdup(bn) ) {
		badflag = TRUE;
		if (++dupcnt > MAXDUPFREE)
			return( stopit("dup") );
		return(BAD);
	} else {
		markdup(bn);
		return(GOOD);
	}
}
			
stopit(type)
char *type;
{
	printf("Excessive %s blocks in free list ", type);
	if ( query("(Continue)") == YES )
		return(IGNORE);
	else
		return(ABORT);
}
		
		
canfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	canshort(fbp->df_nfree);
	if ( (unsigned) fbp->df_nfree > NICFREE )
		return(FALSE);

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	return(TRUE);
}

asksalvage()
{
	if ( (daction!=NO) && (qflag || sflag) ) {
		fixerup = TRUE;
		return;
	}
	if ( action("Bad Free List (SALVAGE)") )
		fixerup = TRUE;
}
@


1.1
log
@Initial revision
@
text
@d26 1
a26 1
	if (badflag) 
d62 5
a66 1
		canfblk(fbp);
d69 5
a73 3
/*	printf("Total traversed free blocks     = %U\n", total);	 */
/*	printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);	 */
/*	printf("Running total free blocks       = %U\n", totfree);	 */
d146 3
d151 2
a153 2
}

d156 1
a156 1
	if ( qflag && (daction!=NO) ) {
@
( (daction!=NO) && (qflag || sflag) ) {
		fixerup = TRUE;
		return;
	}
	if ( action("Bad Free List (SALVAGE)") )
		fixerup = TRUE;
}
@


1.1
log
@Initial revision
@
text
@d26 1
a26 1
	if (badflag) 
d62 5
afsck/RCS/phase6.c,v   444      3      3        5736  4771205312   7176 head     1.2;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.03.18.18.45.18;  author bin;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.05.16.38.52;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein (post 310)
@


1.2
log
@update provided by epstein.
@
text
@/*
 *	phase 6 of fsck - Salvage Free List
 */

#include "fsck.h"

static	unsigned char *maptab;	/* table of interleave offsets	*/
static	daddr_t	mapbot;		/* minimum block number to interleave map */
static	daddr_t	maptop;		/* maximum block number to interleave map */
static	short	m,n;		/* interleave factors	*/
#define	DEF_N	1		/* default values 	*/
#define	DEF_M	1		
daddr_t	freeblks;		/* number free blocks left to write out */
daddr_t	blknm;			/* current block number we are working with */
struct	fblk *fblkp;		/* pointer to free block list */
daddr_t	*dp;			/* pointer to block entry in free list block */

phase6()
{
	if (!fixerup) {
		return;
	}

	if (!qflag)
		printf("Phase 6 : Salvage Free List\n");
	if ( maketable() == BAD )
		return;
	writefree();
	free(maptab);
}

maketable()
{
	register int i;
	register int ratio;

	m = sbp->s_m;
	n = sbp->s_n;

	if ( (n > MAXINTN) || (m > n) || (n%m != 0) ) {
		printf("Invalid interleave factors in superblock.\n");
		printf("Default free-block list spacing assumed.\n");
		sbp->s_n = n = DEF_N;
		sbp->s_m = m = DEF_M;
	}

	if ( (maptab = malloc(n)) == NULL ) {
		printf("Can't malloc space for interleave table.\n");
		printf("Free-block list is not rebuilt.\n");
		return(BAD);
	}

	mapbot = (isize + n - 1)/n*n;
	maptop = fsize/n*n;
	ratio = n/m;
	for (i=0; i<n; i++)
		maptab[i] = (i/ratio) + (i%ratio)*m;

	return(GOOD);
}

writefree()
{
	register daddr_t bn;
	daddr_t blk, bmap();
	short num;

	sbpfix = TRUE;
	freeblks = totfree;
	blknm = SUPERI;
	fblkp = (struct fblk *) &sbp->s_nfree;
	fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
	freeblks -= num;
	dp = &fblkp->df_free[num];
	for (bn=isize; bn<fsize; bn++) {
		blk = bmap(bn);
		if ( !testblock(blk) ) 
			if ( addfree(blk) == STOP )
				break;
	}
}

addfree(bn)
daddr_t bn;
{
	short num;

	*--dp = bn;
	if (dp > &fblkp->df_free[0])
		return(OK);

	if ( blknm != SUPERI ) {
		canwfblk(fblkp);
		bwrite(blknm, databuf);
	}

	bclear(databuf, BSIZE);
	if (freeblks == 0) {
		bwrite(bn, databuf);
		return(STOP);
	}
	blknm = bn;
	fblkp = (struct fblk *) databuf;
	fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
	freeblks -= num;
	dp = &fblkp->df_free[num];
	return(OK);
}

daddr_t
bmap(blk)
register daddr_t blk;
{
	short i;

	if ( (blk>=mapbot) && (blk<maptop) ) {
		i = blk%n;
		blk -= i;
		blk += maptab[i];
	}
	return(blk);
}

canwfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	canshort(fbp->df_nfree);
}
@


1.1
log
@Initial revision
@
text
@d7 1
a7 1
static	char	*maptab;	/* table of interleave offsets	*/
d114 1
a114 1
	int i;
d117 3
a119 2
		i = ((unsigned)blk)%n;
		blk += maptab[i] - i;
@
rn(OK);
}

daddr_t
bmap(blk)
regisfsck/RCS/printf.c,v   444      3      3        7620  4753557667   7333 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.39.10;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein (post310)
@



1.1
log
@Initial revision
@
text
@/*
 * Standard output printf using putchar.
 * Non-portable things:
 * 1) alignment of arguments is assumed to be completely contiguous.
 * 2) the smallest number is assumed to negate to itself.
 * 3) All of long, int, char*, and double are assumed to
 *    be held in an exact number of ints.
 */

#define NULL ((char *)0)
#define putchar(c) { char b = c; write(1, &b, 1); }
#include <sys/mdata.h>

union	alltypes {
	char	c;
	int	i;
	unsigned u;
	long	l;
	double	d;
	char	*s;
};

#define	bump(p,s)	(p+=sizeof(s)/sizeof(int))

char	*printi();
char	*printl();

static	char	null[] = "{NULL}";

printf(args)
union alltypes args;
{
	xprintf(&args);
}
xprintf(argp)
union alltypes *argp;
{
	register char *cbp;
	int *iap;
	register c;
	char *s;
	char *cbs;
	char adj, pad;
	int prec;
	int fwidth;
	int pwidth;
	register char *fmt;
	union alltypes elem;
	char cbuf[64];

	iap = (int *)argp;
	fmt = *(char **)iap;
	bump(iap, char*);
	for (;;) {
		while((c = *fmt++) != '%') {
			if(c == '\0') {
				return;
			}
			putchar(c);
		}
		pad = ' ';
		fwidth = -1;
		prec = -1;
		c = *fmt++;
		if (c == '-') {
			adj = 1;
			c = *fmt++;
		} else
			adj = 0;
		if (c == '0') {
			pad = '0';
			c = *fmt++;
		}
		if (c == '*') {
			fwidth = *iap++;
			c = *fmt++;
		} else
			for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
				fwidth = fwidth*10 + c-'0';
		if (c == '.') {
			c = *fmt++;
			if (c == '*') {
				prec = *iap++;
				c = *fmt++;
			} else
				for (prec=0; c>='0' && c<='9'; c=*fmt++)
					prec = prec*10 + c-'0';
		}
		if (c == 'l') {
			c = *fmt++;
			if (c=='d' || c=='o' || c=='u' || c=='x')
				c += 'A' - 'a';
		}
		cbp = cbs = cbuf;
		switch (c) {

		case 'd':
			elem.i = *iap++;
			if (elem.i < 0) {
				elem.i = -elem.i;
				*cbp++ = '-';
			}
			cbp = printi(cbp, elem.i, 10);
			break;

		case 'u':
			cbp = printi(cbp, *iap++, 10);
			break;
	
		case 'o':
			cbp = printi(cbp, *iap++, 8);
			break;

		case 'x':
			cbp = printi(cbp, *iap++, 16);
			break;

		case 'D':
			elem.l = *(long *)iap;
			bump(iap, long);
			if (elem.l < 0) {
				elem.l = -elem.l;
				*cbp++ = '-';
			}
			cbp = printl(cbp, elem.l, 10);
			break;

		case 'U':
			cbp = printl(cbp, *(long *)iap, 10);
			bump(iap, long);
			break;

		case 'O':
			cbp = printl(cbp, *(long *)iap, 8);
			bump(iap, long);
			break;

		case 'X':
			cbp = printl(cbp, *(long *)iap, 16);
			bump(iap, long);
			break;


		case 's':
			if ((s = *(char **)iap) == NULL)
				s = null;
			bump(iap, char*);
			/*
			 * Do %s specially so it can be longer.
			 */
			cbp = cbs = s;
			while (*cbp++ != '\0')
				if (prec>=0 && cbp-s>prec)
					break;
			cbp--;
			break;
	
		case 'c':
			elem.c = *iap++;
			*cbp++ = elem.c;
			break;
	
		case 'r':
			xprintf(*(char ***)iap);
			bump(iap, char**);
			break;
	
		default:
			putchar(c);
			continue;
		}
		if ((pwidth = fwidth + cbs-cbp) < 0)
			pwidth = 0;
		if (!adj)
			while (pwidth-- != 0)
				putchar(pad);
		while (cbs < cbp)
			putchar(*cbs++);
		if (adj)
			while (pwidth-- != 0)
				putchar(pad);
	}
}

static	char	digits[] = {
	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'A', 'B', 'C', 'D', 'E', 'F'
};

/*
 * Print an unsigned integer in base b.
 */
static
char *
printi(cp, n, b)
char *cp;
register unsigned n;
{
	register a;
	register char *ep;
	char pbuf[10];

	ep = &pbuf[10];
	*--ep = 0;
	for ( ; a = n/b; n=a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}

/*
 * Print an unsigned long in base b.
 */
static
char *
printl(cp, n, b)
register char *cp;
unsigned long n;
register b;
{
	char pbuf[13];
	unsigned long a;
	register char *ep;

	ep = &pbuf[13];
	*--ep = '\0';
	for ( ; (a = n/b) != 0; n = a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}
@
egister char *ep;
	char pbuf[10];

	ep = &pbuf[10];
	*--ep = 0;
	for ( ; a = n/b; n=a)
		*--ep = digits[n%b];
	*fsck/RCS/util.c,v   444      3      3       16442  5045006750   7001 head     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.07.29.07.45.21;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.05.16.39.25;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by epstein (post 310)
@


1.2
log
@Updated by epstein for version 321.
@
text
@/*
 *	general utility functions for phases of fsck
 */

#include "fsck.h"

struct stat stats;			/* Used by statit() */

statit(name, probfun)
char *name;
int (*probfun)();
{
	
	if ( stat(name, &stats) == -1 ) {
		bclear(&stats, sizeof(struct stat));
		(*probfun)("Can not stat %s", name);
	}
}


query(x)
{
	while(1) {
		printf("%r [yes/no]: ", &x);
	
		switch (daction) {
		case YES:
			printf("[default - YES]\n");
			return(YES);
			break;
		case NO:
			printf("[default - NO]\n");
			return(NO);
			break;
		case ASK:
			switch( nextchar() ) {
			case 'Y':
				return(YES);
			case 'N':
				return(NO);
			}
		}
	}
}

action(msg)
char *msg;
{
	switch( query(msg) ) {
	case YES:
		return(TRUE);
	case NO:
		return(FALSE);
	}
}

char
nextchar()
{
	char buff[8];
	int i, n, ch;

	if ( ((n=read(0,buff,8)) <= 0) || (n == 8) )
		fatal("Invalid Response");

	for(i=0; i<n; i++)
		if ( ((ch=buff[i])!=' ') && (ch!='\t') )
			break;

	if ( (ch>='a') && (ch<='z') )
		ch += 'A' - 'a';

	return(ch);
}

char	*nfile	= "FILE";
char	*ndir	= "DIR";
char	*nchr	= "Character Special";
char	*nblk	= "Block Special";
char	*npipe	= "PIPE";
char	*nunkwn = "Unknown I-node type";

char *
typename(ino)
ino_t ino;
{
	switch( flags(ino)&MODEMASK ) {
	case IREG:
		return(nfile);
	case IDIR:
		return(ndir);
	case ICHR:
		return(nchr);
	case IBLK:
		return(nblk);
	case IPIPE:
		return(npipe);
	default:
		return(nunkwn);
	}
}

abort()
{
	fatal("abort.");
}

fatal(x)
{
	printf("fsck: %r\n", &x);
	_exit(1);
}

nonfatal(x)
{
	printf("fsck: %r\n", &x);
	errflag = TRUE;
}

/*
 *	Inode Manipulation Routines
 *	ptrino:	returns a pointer to the wanted inode using the given
 *		buffer to read in the block performing canonicalization.
 *	writeino: writes the block containing the given inode to the
 *		disk performing the necessary canonicalization
 *	candino: canonicalize an inode
 *
 */

struct dinode *
ptrino(ino, buf)
register ino_t ino;
register char *buf;
{
	register daddr_t bn;
	register struct dinode *dip;

	bn = iblockn(ino);
	if ( (testblock(bn)) && (bn!=INODEI) )		/* bad inode block */
		return(NULL);
	bread(bn, buf);
	dip = ((struct dinode *) buf) + iblocko(ino);
	candino(dip);
	return(dip);
}

writeino(ino, buf)
ino_t ino;
char *buf;
{
	struct dinode *dip;

	dip = ((struct dinode *) buf) + iblocko(ino);
	candino(dip);
	bwrite((daddr_t) iblockn(ino), buf);
}

candino(dip)
register struct dinode *dip;
{
	canshort(dip->di_mode);
	canshort(dip->di_nlink);
	canshort(dip->di_uid);
	canshort(dip->di_gid);
	cansize(dip->di_size);
	cantime(dip->di_atime);
	cantime(dip->di_mtime);
	cantime(dip->di_ctime);
}

/*
 *	Transfer a logical block number for an inode to a
 *	physical block number, chasing indirects as necessary.
 *	The inefficiency of this method is put up with since
 *	this is only used for directory inodes, and they tend
 *	not to use indirects.  Pass in 'addrs' which is a pointer
 *	to the 13 daddr_s in the inode, and the logical block
 *	number you would like.  (Stolen from dcheck.c)
 */

static	daddr_t	ranges[] = {
	ND,
	ND + (daddr_t)NI*NBN,
	ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
	ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN
};

static	char	index[] = {
	0,
	ND,
	ND+NI,
	ND+NI+NII
};

static	daddr_t	coeff[] = {
	1,	(daddr_t)NBN,	(daddr_t)NBN*NBN,	(daddr_t)NBN*NBN*NBN
};

daddr_t
imap(addrs, block)
daddr_t *addrs;
register daddr_t block;
{
	int i;
	register daddr_t bpos;
	register daddr_t *bp;
	register daddr_t bn;

	for (i=0; i<4; i++)
		if (block < ranges[i]) {
			if (i != 0)
				block -= ranges[i-1];
			bpos = block/coeff[i];
			block %= coeff[i];
			bp = &addrs[(int)bpos + index[i]];
			if ( (bn=*bp) != 0 ) {
				/*
				 * Map through indirects here
				 */
				while (i-- > 0) {
					bread(bn, databuf);
					bpos = block/coeff[i];
					block %= coeff[i];
					bp = (daddr_t *)databuf + bpos;
					if ( (bn=*bp) == 0 )
						break;
					bn = *bp;
					candaddr(bn);
				}
			}
			return(bn);
		}
	return(0);
}

/*
 *	Read the specified block number into the given buffer
 */

char *rgblkerr = "Out of Range Block number: %U  (CONTINUE)";
char *skblkerr = "Can not Seek: Blk num: %U  (CONTINUE)";
char *rdblkerr = "Can not Read: Blk num: %U  (CONTINUE)";
char *wtblkerr = "Can not Write: Blk num: %U  (CONTINUE)";

bread(bn, buf)
register daddr_t bn;
register char *buf;
{
#ifdef	DEBUG
	printf("Reading block number: %ld\n", bn);
#endif
	if (bn<0 || bn >= fsize ) 
		switch( query(rgblkerr, bn) ) {  
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}

	if ( (bn<isize) && getcache(bn, buf) ) {
#if DEBUG
		bdump(buf);
#endif
		return;
	}
	
	if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) )
		switch( query(skblkerr, bn) ) {
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}

	if ( read(fsfd, buf, BSIZE) != BSIZE ) 
		switch( query(rdblkerr, bn) ) {
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}
#if DEBUG
	bdump(buf);
#endif
}

/*
 *	Write block number bn with data in buf
 */

bwrite(bn, buf)
daddr_t bn;
char *buf;
{
#ifdef	DEBUG
	printf("Writing block number: %ld\n", bn);
#endif
	if (!writeflg)
		return;

	if (bn<0 || bn>=fsize) 
		switch( query(rgblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}
	
	if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) )
		switch( query(skblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}

	if ( write(fsfd, buf, BSIZE) != BSIZE ) 
		switch( query(wtblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}

	if ( bn <= isize )
		chgcache(bn, buf);
	changeflg = TRUE;
}

/*
 *	i-node block area caching routines
 */

static char	cache[NBLK * BSIZE];
static int	low = 0; high = -1;

getcache(bn, buf)
register daddr_t bn;
register char *buf;
{
	int totsize;

	if ( bn > isize )
		return(0);

	if ( (bn>=low) && (bn<=high) ) {
		blkmove(buf, &cache[BSIZE * (bn-low)]);
		return(1);
	}

	low = bn;
	if ( (high=bn+NBLK-1) > isize )
		high = isize;
	totsize = BSIZE * (high-low+1);

	if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) ||
	     (read(fsfd, cache, totsize) != totsize) ) {
		low = 0; high = -1;
		return(0);
	}

	return( getcache(bn, buf) );
}

chgcache(bn, buf)
register daddr_t bn;
register char *buf;
{
	if ( (bn>=low) && (bn<=high) )
		blkmove(&cache[BSIZE * (bn-low)], buf);
}

blkmove(to, from)
register char *to, *from;
{
	register int num=BSIZE;

	while ( num-- )
		*to++= *from++;
}

/*
 *	Clear the given block of memory
 */

bclear(bp, nb)
register char *bp;
register unsigned nb;
{
	if (nb)
		do {
			*bp++ = 0;
		} while (--nb);
}


/*
 *	Determine if the given block is bad
 */

bad(bn)
daddr_t bn;
{
	if ( (bn >= isize) && (bn < fsize) )
	 	return(GOOD);
	else
		return(BAD);
}


#if DEBUG

/*
 *	Debug dump a block of data.
 */

#define NUMPLIN	16

bdump(buf)
register unsigned char *buf;
{
	register int i;

	for (i=0; i<BSIZE; i++) {
		if ( (i % NUMPLIN) == 0 )
			printf("\n0x%04x:  ", i);
		printf(" %02x", *buf++);
	}
	printf("\n\n");
}

#endif
@


1.1
log
@Initial revision
@
text
@d261 4
a264 1
	if ( (bn<isize) && getcache(bn, buf) )
d266 1
d285 3
d412 24
@
iven block is bad
 */

bad(bn)
daddr_t bn;
{
	if ( (bn >= isize) && (bn < fsize) )
	 	return(GOOD);
	else
		return(BAD);
}


#if DEBUG

/*
 *	Debug dump a block of data.
 */

#define NUMPLIN	16

bdump(buf)
register unsignefsck/RCS/virtual.c,v   444      3      3       16557  4753557734   7543 head     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.05.16.39.42;  author bin;  state Exp;
branches ;
next	;


desc
@prov by epstein (post 310)
@



1.1
log
@Initial revision
@
text
@/*
 * Virtual memory for fsck. Uses hash algorithm
 * rather than LRU to get it up fast.
 */
#include <assert.h>
#include <sys/stat.h>
#include "fsck.h"

#define VBLKB 9			/* bytes in virtual block as power of 2 */
#define VBLK (1 << VBLKB)	/* bytes in a virtual block */
#define MBKSB 6			/* number of virtual blocks as power of 2 */
#define MBKS (1 << MBKSB)	/* number of virtual blocks */

#define DVTMP "/dev/rram1"	/* Default Virtual Temp Filename */
#define DVTMPCLS "/dev/rram1close" /* Default Virtual Temp File Close */
#define	MAJORRAM 8		/* Major Device Number for the Ram Disk	*/

struct mapper {
	unsigned dirty:1;
	unsigned what_in:15;	/* which block is in memory */
};

static unsigned long flagdsp, blkdsp, dupdsp, duplim;
static struct mapper map[MBKS];
static unsigned char data[MBKS][VBLK];
static int tmp;

static char *dvtmp = DVTMP;
static char *dvtmpcls = DVTMPCLS;

/*
 * Init file system for virtual arrays.
 * Data is ordered links, flags, blocks then dups.
 */
initV(links, flags, blocks, dups)
unsigned links, flags, blocks, dups;
{
	register long bp;
	struct stat st;
	unsigned datasiz;

	flagdsp = links;
	blkdsp = flagdsp + flags;
	dupdsp = blkdsp + blocks;
	duplim = dupdsp + dups;

	memset(map, 0, sizeof(map));	/* zero ram arrays */
	memset(data, 0, sizeof(data));

	tmp = -1;

	datasiz = sizeof(data);
	if ( duplim < datasiz )
		return;

	if ( tmpfile == NULL ) {
		switch ( is_fs(dvtmp) ) {
		case -1:
			fatal(
"Can't access ram disk \"%s\", use the -t option", dvtmp);
		case 0:
			break;
		case 1:
			fatal(
"Possible file system on ram disk \"%s\", use the -t option", dvtmp);
		}
		if ( (-1 == stat(dvtmp, &st)) || !(st.st_mode&S_IFCHR) ||
			(major(st.st_rdev) != MAJORRAM) )
				fatal("Ram disk \"%s\" not mknod'ed properly",
								dvtmp);
		if ( -1 == (tmp = open(dvtmp, 2)) )
			fatal("Cannot open read/write Ram Disk \"%s\"", dvtmp);

		/* Ram disk driver may not promise zeroed start.
		 * This code may go later. Extra write not important. */
		for(bp = 0; bp < duplim; bp += VBLK) /* zero disk stuff */
			if ( VBLK != write(tmp, data[0], VBLK) )
				fatal("Error writing to tmp file");
	} else {
		if ( -1 == (tmp = open(tmpfile, 2)) ) {
			if ( -1 == (tmp = creat(tmpfile, 0600)) )
				fatal("Cannot create temp file \"%s\"", 
								tmpfile);
			close(tmp);
			tmp = open(tmpfile, 2);
			unlink(tmpfile);
		}
		if ( -1 == fstat(tmp, &st) )
			fatal("Can't stat temp file \"%s\"", tmpfile);
		if ( st.st_dev == fsysrdev )
			fatal("Temp File must not be on file system to fsck");
	}
}

/*
 * cleanup virtual system
 */
cleanV()
{
	struct stat st;

	if ( tmp == -1 )		/* No Virtual Temp File Opened	*/
		return;

	close(tmp);
	if ( tmpfile != NULL )		/* Virtual File not Default RAMDisk */
		return;
					/* Virtual File is Default RAMDisk */
	if ( (-1 == stat(dvtmpcls, &st)) || !(st.st_mode&S_IFCHR) ||
		(major(st.st_rdev) != MAJORRAM) ||
		((minor(st.st_rdev)&0x7F) != 0) )
		fatal("Ram disk close \"%s\" not mknod'ed properly", dvtmpcls);
	if ( -1 == (tmp = open(dvtmpcls, 2)) )
		fatal("Cannot open Ram Disk Close \"%s\"", dvtmpcls);
	if ( close(tmp) < 0 )
		fatal("Cannot close Ram Disk Close \"%s\"", dvtmpcls);
}

/*
 * All actions for virtual array
 */
findblock(bp, action, odata)
long bp;		/* data address */
enum vact action;	/* what to do */
unsigned odata;		/* optional data */
{
	unsigned which, what_in, byte_no, bit;
	unsigned long diskad;
	unsigned char *byte;
	extern long lseek();

	switch(action) {	/* use displacment to correct part of file */
	case testBlock:
	case markBlock:
	case unmarkBlock:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case grabBlock:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += blkdsp;
		assert(bp < dupdsp);
		break;
	case testDup:
	case markDup:
	case unmarkDup:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case setDup:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += dupdsp;
		assert(bp < duplim);
		break;
	case Flags:
	case setFlags:
	case orFlags:
		assert(bp > 0);
		bp += flagdsp - 1;
		assert(bp < blkdsp);
		break;
	case linkCtr:
	case incLinkctr:
	case setLinkctr:
		assert(bp > 0);
		bp--;
		assert(bp < flagdsp);
	}

	byte_no = bp & (VBLK - 1);
	bp >>= VBLKB;
	which = bp & (MBKS - 1);
	bp >>= MBKSB;
	what_in = bp & 0x7fff;

	if((diskad = map[which].what_in) != what_in)	{
		if(map[which].dirty) {
			diskad <<= VBLKB + MBKSB;
			diskad += which << VBLKB;
			if(-1 == lseek(tmp, diskad, 0))
				fatal("Error seeking tmp file");
			if(VBLK != write(tmp, data[which], VBLK))
				fatal("Error writing tmp file");
		}
		diskad = what_in;
		diskad <<= VBLKB + MBKSB;
		diskad += which << VBLKB;
		if(-1 == lseek(tmp, diskad, 0))
			fatal("Error seeking tmp file");
		if(VBLK != read(tmp, data[which], VBLK))
			memset(data[which], 0, VBLK);
		map[which].what_in = what_in;
		map[which].dirty = 0; /* clean */
	}
	byte = &data[which][byte_no];

	switch(action) {
	case testBlock:
	case testDup:
		return(*byte & bit);
	case markBlock:
	case markDup:
		map[which].dirty = 1;
		return(*byte |= bit);
	case unmarkBlock:
	case unmarkDup:
		map[which].dirty = 1;
		return(*byte ^= bit);
	case linkCtr:
	case Flags:
	case grabBlock:
		return(*byte);
	case setLinkctr:
	case setFlags:
	case setDup:
		map[which].dirty = 1;
		return(*byte = odata);
	case orFlags:
		map[which].dirty = 1;
		return(*byte |= odata);
	case incLinkctr:
		map[which].dirty = 1;
		return(++*byte);
	default:
		fatal("Bad action in virtual system");
	}
}

/*
 * copy virtual memory blockmap to dupmap
 * read and write groups to avoid possable thrashing.
 */
void
copyV(size)
unsigned size;
{
	char buf[128];
	register int i;
	long bp, bs;

	for(bs = bp = 0; bp < size; ) {
		for(i = 0; (i < 128) && (bp < size); i++, bp++)
			buf[i] = findblock(bp, grabBlock);

		for(i = 0; (i < 128) && (bs < size); i++, bs++)
			findblock(bs, setDup, buf[i]);
	}
}

#ifdef TEST
fatal(s)
char *s;
{
	fprintf(stderr, "%s\n", s);
	exit(1);
}

static	char buf[80];
gbuf()
{
	if(NULL == gets(buf)) {
		unlink("vtmp");
		exit(0);
	}
	return(buf[0]);
}

main()
{
	unsigned long b;
	char data;

	initV(10000, 10000, 20000);
	for(;;) {
		printf("b = block, d = dup, f = flags, l = linkctr\n");
		switch(gbuf()) {
		case 'l':
			printf("s = set, d = display, i = increment: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 's':
				setlinkctr(b, 0); /* no data */
			case 'd':
				printf("%d\n", linkctr(b));
				break;
			case 'i':
				printf("%d\n", inclinkctr(b));
			}
			break;
		case 'f':
			printf("d = display, s = set, o = or: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld %c", &b, &data);
			switch(buf[0]) {
			case 's':
				setflags(b, data);
			case 'd':
				break;
			case 'o':
				orflags(b, data);
			}
			printf("%c\n", flags(b));
			break;
		case 'b':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markblock(b);
			case 't':
				break;
			case 'u':
				unmarkblock(b);
			}
			printf("%c\n", testblock(b) ? '1' : '0');
			break;
		case 'd':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markdup(b);
			case 't':
				break;
			case 'u':
				unmarkdup(b);
			}
			printf("%c\n", testdup(b) ? '1' : '0');
			break;
		}
	}
}
#endif

@
 loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markblock(b);
			case 't':
				break;
			case 'u':
				ufsck/READ_ME   644      3      3        1227  4664524112   5766 Ideas for improving the performance of fsck:

(1)  Utilize a different mechanism for storing the (struct direct)
     entries throughout phase2.c, to remove implicit memory intensive
     redundancy.

(2)  Encode the number of links per i-node count differently, in order
     to save space taking advantage of the typical usage under Coherent.

(3)  Arrange space for the tables in a total needed way to avoid later
     fragmentation problems affecting the memory requests for successive
     file systems.

(4)  Devise a more clever buffering scheme for the blocks containing
     i-nodes to understand the differences between phase1, phase2, and
     phase4.
emove implicit memory intensive
     redundancy.

(2)  Encode the number of links per i-node count differently, in order
     to save space taking advantage of the typical usage under Coherent.

(3)  Arrange space for the tables in a total needed way to avoid later
     fragmentation problems affecting the memory requests for successive
     file systems.

(4fsck/cleanup.c   644      3      3        2324  4664524112   6541 /*
 *	Cleanup functions for phases of fsck
 */

#include "fsck.h"

cleanup()
{
	int retval = 0;

	if (sbpfix == TRUE) 
		writesuper();
	prtstats();
	if (changeflg == TRUE)
		retval = advise();
	close(fsfd);
	cleanV();
	return(retval);
}

writesuper()
{
	register int i;

	canshort(sbp->s_isize);
	candaddr(sbp->s_fsize);
	canshort(sbp->s_nfree);
	for(i=0; i<NICFREE; i++)
		candaddr(sbp->s_free[i]);
	canshort(sbp->s_ninode);
	for(i=0; i<NICINOD; i++)
		canino(sbp->s_inode[i]);
	cantime(sbp->s_time);
	candaddr(sbp->s_tfree);
	canino(sbp->s_tinode);
	canshort(sbp->s_m);
	canshort(sbp->s_n);
	canlong(sbp->s_unique);

	bwrite((daddr_t)SUPERI, sbp);
}

prtstats()
{
	if (!fflag)
		printf("%u files ", numfiles);
	printf("%U blocks ", fsize - isize - totfree);
	printf("%U free\n", totfree);
	if ( lostsize ) {
		lostsize = (lostsize + BSIZE - 1)/BSIZE;
		printf("Expect roughly %U missing block%s next\n", lostsize,
				(lostsize!=1) ? "s" : "" );
		printf("time fsck is run as a result of inodes ");
		printf("being cleared.\n");
	}
}

advise()
{
	int retval = 0;

	printf(" ***** File System %s was modified *****\n", fsname);
	if ( mounted ) {
		printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
		retval = 1;
	}
	return(retval);
}
blocks ", fsize - isize - totfree);
	printf("%U free\n", totfree);
	if ( lostsize ) {
		lostsize = (lostsize + BSIZE - 1)/BSIZE;
		printf("Expect roughly %U missing block%s next\n", lostsize,
				(lostsize!=1) ? "s" : "" );
		printf("time fsck is run as a result of inodes ");
		printf("being clearedfsck/fsck.h   644      3      3       14003  5033723044   6056 /*
 *	Header file for fsck  --  File System Check Program
 *
 */

#include <canon.h>
#include <sys/dir.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

#if HPCOHERENT
typedef long fsize_t;
#endif

/*
 *	Conditional Compilation Flags
 */

#define NOT_ALL_ZERO_INODE	/* Dependent on whether or not an inode */
#ifdef 	ALL_ZERO_INODE		/* is totally zeroed when unallocated   */
#undef	ALL_ZERO_INODE		/* or simply a zero mode and zero link  */
#endif


/*
 *	Definitions and Externs
 */

#define NUL	0		/* true zero ! */
#define NULL	((char *)0)

#define	YES	3		/* default actions */
#define	NO	2
#define ASK	1

#define	NFILSYS	10		/* max number of file systems */
#define	MAXCH	20		/* max length of filesys name */

#define	MAXBADOK	10	/* Max number of bad blocks before excessive */
extern	int numbad;		/* num bad blocks found so far this inode*/

#define MAXDUPOK	10	/* Max number of dup blocks */
				/* in a single inode before excessive */
#define	DUPTBLSIZE	20	/* Max number of dup referenced blocks */
extern	daddr_t	dupblck[];	/* table of duplicate referenced blocks */
extern 	int totdups;		/* number of dup blocks found so far */

#define MAXBADFREE	10	/* max bad in free list before abort */
#define MAXDUPFREE	10	/* max dup in free list before abort */

#define GOOD	1		/* returned by bad() in util.c */
#define	BAD	0

#define	TRUE	1		/* errflag possibilities */
#define	FALSE	0
extern 	int	errflag;	/* errflag indicates not to do phases */

#define OK	1		/* used to indicate excessive bad/dup */
#define STOP	0		/* blocks in an inode in phase1.c     */
#define BAD_DUP	2

#define FIRSTIN	2		/* First real inode number */

#define	ND	10		/* Number of Direct Blocks */
#undef	NI
#define	NI	1
#define	NII	1
#define	NIII	1
#undef	NADDR
#define	NADDR	(ND+NI+NII+NIII)
extern	int	offsets[];	/* table of offsets for level of indirection */
				/* for the blocks in an inode */

extern	char	nextchar();	/* used in util.c */
extern	int	fsfd;		/* file system file descriptor */
extern 	int	mdaction;	/* default action for this invocation */
extern 	int	daction;	/* default action for current file system */
extern  int 	writeflg;	/* system write ok or read-only */
extern  int	qflag;		/* quiet fsck flag */
extern	int	fflag;		/* fast fsck flag */
extern	int	sflag;		/* force free list salvation	*/
extern	daddr_t	fsize;		/* file system size in blocks */
extern	int	isize;		/* first block not in inode list */
				/* isize is NOT unsigned so that comparisons */
				/* with longs will not cast the long to */
				/* unsigned thus producing confusing results */

extern  daddr_t	totfree;	/* running count of total free blocks */
extern 	unsigned	ninodes;/* Number of inodes in the files system */
extern 	char	*fsname;	/* file system name */
extern  fsize_t  pinfo();	/* returns size of file, in phase2.c */
extern	ino_t	lostfound();	/* returns inumber of lost+found dir */
extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
extern 	char databuf[];		/* buffer to read in block, used throughout */
extern	char buf2[];		/* alternate data buffer */
extern 	daddr_t	cdbn;		/* current block number, used by nextblock() */
#define DSIZE	(sizeof(struct direct))
extern 	char *lostname;		/* name of lost+found directory */
extern  char *nameit();		/* nameing function for lost dirs and files */
extern 	int	depth;		/* used during tree traversal in phase2.c */
extern  struct direct *path[]; 	/* used during tree traversal in phase2.c */
extern	char	*typename();	/* return string to type of inode */
extern 	struct filsys *sbp;	/* Super Block */
extern 	int	sbpfix;		/* flag for super block fixes */
extern  struct stat stats;	/* used by statit() in util.c */
extern	dev_t	rootdev;	/* root device number */
extern	dev_t	fsysrdev;	/* file system real device number */
extern	int	mounted;	/* flag indicating mountedness of filesystem */
extern 	int	changeflg;	/* file system modified flag */
extern 	int	fixerup;	/* flag to rebuild free list */
extern	char	*fixit;		/* Prompt message phase[45].c */
extern 	int	numfiles;	/* num files in system */
extern	daddr_t	imap();		/* function for disk block mapping in util.c */
extern	fsize_t	lostsize;	/* Size of files cleared in phase4.c */
extern	char 	*tmpfile;	/* TMP File name for virtual.c */

#define SUCCESS	1		/* used in connect() in phase3.c */
#define FAILURE	0

#define	MODEMASK	0x07
#define ALLOCMASK	0x06
#define UNALLOC		0x00
#define UNKNOWN		0x01
#define	IDIR		0x02
#define	IREG		0x03
#define ICHR		0x04
#define IBLK		0x05
#define IPIPE		0x06
#define IBAD_IDUP	0x08
#define VISITED		0x10
#define UNREFDIR	0x20
#define CHILDDIR	0x40
#define IFREELIST	0x80

/*
 *	Macros for tables
 */

#define	LOGNBPC	3		/* Log2 Number of Bits per Character    */

/* Actions for virtual block system */
enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
	    testDup, markDup, unmarkDup, setDup,
	    Flags, setFlags, orFlags,
	    linkCtr, incLinkctr, setLinkctr };
	      
#define testblock(bn)  findblock((unsigned long)(bn), testBlock)
#define markblock(bn)  findblock((unsigned long)(bn), markBlock)
#define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)

#define testdup(bn) findblock((unsigned long)(bn), testDup)
#define markdup(bn) findblock((unsigned long)(bn), markDup)
#define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)

#define flags(ino) findblock((unsigned long)(ino), Flags)
#define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
#define orflags(ino, data)  findblock((unsigned long)(ino), orFlags, data)

#define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)

#define badblks(ino)	( flags(ino)&IBAD_IDUP )

/*
 *	Miscellany
 */

#define	NBPC	8			/* number of bits per character */
#define	MAXINTN	255			/* used for interleave table	*/
					/* in phase6.c			*/
/*
 *	Stdio Stuff
 */

#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc();

findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)

#define badblks(ino)	( flags(ino)&IBAD_IDUP )

/*
 *	Miscellany
 */

#define	NBPC	8			/* number of bits per character */
#define	MAXINTN	255			/* used for interleave table	*/
					/* in phase6.c			*/
/*
 *	Stdio Stuff
 */

#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc()fsck/init.c   644      3      3       12651  5041132573   6075 /*
 *	Perform initialization for phases of fsck
 */
#include "fsck.h"
#include <mnttab.h>
#include <mtab.h>

int	fsfd;				/* file system file descriptor */
int	writeflg;			/* write ok or read-only flag */
daddr_t	fsize = SUPERI+1;		/* file system size in blocks  */
					/* Allows for read of Super Block */
int	isize;				/* First block not in inode list */
daddr_t	totfree;			/* Running total free block count */
unsigned	ninodes;		/* number of inodes */
int	numfiles;			/* number of files in file system */

char	superb[BSIZE];			/* Super Block */
struct filsys *sbp = superb;
int	sbpfix;				/* flag for super block fixes */

int	offsets[] = 			/* table of offsets for the levels */
		{ ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
		  ND+NI+NII+NIII };     /* inode block list */

daddr_t	dupblck[DUPTBLSIZE];		/* duplicate referenced blocks */
int	totdups;			/* number of dup blocks so far */

init()
{
	int mode;
	struct stat status;
	unsigned short stmode;

	mode = (mdaction == NO) ? 0 : 2;

	if ( (fsfd = open(fsname, mode)) == (-1) ) {
		mode = 0;
		if ( (fsfd = open(fsname, mode)) == (-1) ) {
			nonfatal("Can't open: %s", fsname);
			return;
		}
	}

	if (mode == 0) {
		daction  = NO;
		writeflg = FALSE;
	} else {
		daction  = mdaction;
		writeflg = TRUE;
	}
	
	printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");

	if ( fstat(fsfd, &status) == (-1) ) {
		nonfatal("Can't stat: %s", fsname);
		return;
	}

	stmode = status.st_mode & S_IFMT;
	if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) ) 
		switch(query("file is not a block or character device; OK?")){
		case YES:
			break;
		case NO:
			errflag = TRUE;
			return;
		}

	domount();
	sbpfix = FALSE;
	readsuper();
	checksuper();
	if ( !errflag )
		alloctables();
}

/*
 *	Read in the super block and canonicalize
 */

readsuper()
{
	register int i;

	bread((daddr_t)SUPERI, superb);
	sbp = superb;

	canshort(sbp->s_isize);
	candaddr(sbp->s_fsize);
	canshort(sbp->s_nfree);
	for(i=0; i<NICFREE; i++)
		candaddr(sbp->s_free[i]);
	canshort(sbp->s_ninode);
	for(i=0; i<NICINOD; i++)
		canino(sbp->s_inode[i]);
	cantime(sbp->s_time);
	candaddr(sbp->s_tfree);
	canino(sbp->s_tinode);
	canshort(sbp->s_m);
	canshort(sbp->s_n);
	canlong(sbp->s_unique);

}

/*
 *	Check super block for obvious inconsistencies
 */

checksuper()
{
	fsize = sbp->s_fsize;
	isize = sbp->s_isize;
	totfree = fsize - isize;
	
	if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
 		badsuper("Size check: fsize %U isize %u", fsize, isize);
		errflag = TRUE;
	}

	if ( sbp->s_nfree > NICFREE )
		badsuper("Too large free block count");

	if ( sbp->s_ninode > NICINOD )
		badsuper("Too large free i-node count");
}

/*
 *	Super Block Error Functions
 */

badsuper(x)
{
	printf("%r\n", &x);
	printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
}

/*
 *	Allocate the necessary buffers for tables
 */

alloctables()
{
	unsigned num, numl;

	numl = 0;
	if (!fflag) {
		ninodes = (unsigned) (isize - INODEI) * INOPB;
		numl = (unsigned) ninodes;
	}
	
	num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
	initV(numl, numl, num, num); /* virtual allocation */

	numfiles =		/* number of files in the file system */
	totdups = 0;		/* num dup blocks */
}

/*
 *	domount() checks the files /etc/mnttab and /etc/mtab to find
 * 	out where the file system is mounted (if at all).  It then 
 *	reports where (and when if possible) it was last mounted.
 */
char *mnttab_name = "/etc/mnttab";
char *mtab_name	  = "/etc/mtab";
char *bttime_name = "/etc/boottime";

domount()
{
	int fd;
	struct mnttab mnttab;
	struct mtab mtab;
	register char *name;
	struct stat sbuf;
	time_t boottime;
	int nothing();
	char devname[MNTNSIZ+6] = "/dev/";

	mounted = FALSE;
	name = fsname;				/* strip off all initial */
	while (*name++ != '\0') ;		/* directories in fsname */
	while ( (*--name != '/') && (name>fsname) ) ;
	if (*name == '/') name++;

	if ( stat(bttime_name, &sbuf) == -1 )
		boottime = (time_t)0;
	else
		boottime = sbuf.st_mtime;
				
	if ( (fd=open(mnttab_name, 0)) != (-1) ) {
		while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) ) 
			if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
				strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
				devname[MNTNSIZ+5] = '\0';
				statit(devname, nothing);
				if (stats.st_rdev != fsysrdev)
					continue;
				statit(mnttab.mt_dev, nothing);
				mounted = (stats.st_dev == fsysrdev);
				prmnttab(&mnttab, boottime);
				return;
			}
	}
	if ( (fd=open(mtab_name, 0)) != (-1) ) {
		while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) ) 
			if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
				strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
				devname[MNAMSIZ+5] = '\0';
				statit(devname, nothing);
				if (stats.st_rdev != fsysrdev)
					continue;
				statit(mtab.mt_name, nothing);
				mounted = (stats.st_dev == fsysrdev);
				prmtab(&mtab);
				return;
			}
	}

	if (fsysrdev == rootdev)
		mounted = TRUE;
	else
		mounted = FALSE;

}

prmnttab(ptr, boottime)
struct mnttab *ptr;
time_t boottime;
{
	if (mounted) {
		if (boottime < ptr->mt_time)
			boottime = ptr->mt_time;
		printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ, 
					ptr->mt_dev, ctime(&boottime));
	} else
		printf("%s unmounted.  Last mounted on %.*s -- %s",
						fsname, MNTNSIZ, ptr->mt_dev,
							ctime(&ptr->mt_time));
}


prmtab(ptr)
struct mtab *ptr;
{
	if (mounted)
		printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
	else
		printf("%s unmounted.  Last mounted on %.*s\n", fsname,
							MNAMSIZ, ptr->mt_name);
}

nothing()
{}
) {
		if (boottime < ptr->mt_time)
			boottime = ptr->mt_time;
		printf("%s mounted on fsck/is_fs.c   644      3      3        3467  4705135657   6236 #include <sys/stat.h>
#include <canon.h>
#include <sys/filsys.h>

/*
 * Check if a special file is a well-formed filesystem.
 * This routine is derived from code in "mount.c".
 * Return values:
 *	-1	Not a device, cannot open, read or seek failed
 *	0	No filesystem
 *	1	Legal filesystem
 */
int
is_fs(special) char *special;
{
	static struct filsys f;
	struct stat sbuf;
	register int fd;
	register struct filsys *fp;
	register daddr_t *dp;
	register ino_t *ip, maxinode;

	if (stat(special, &sbuf) < 0)
		return -1;			/* cannot stat device */
	else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
	      && (sbuf.st_mode&S_IFMT) != S_IFCHR)
		return -1;			/* not a special file */
	else if ((fd = open(special, 2)) < 0)
		return -1;			/* cannot open */
	else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
	      || read(fd, &f, sizeof(f)) != sizeof(f)) {
		close(fd);
		return -1;			/* seek or read failed */
	} else
		close(fd);			/* so far so good */

	/* Canonical stuff. */
	fp = &f;
	canshort(fp->s_isize);
	candaddr(fp->s_fsize);
	canshort(fp->s_nfree);
	for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
		candaddr(*dp);
	canshort(fp->s_ninode);
	for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
		canino(*ip);
	candaddr(fp->s_tfree);
	canino(fp->s_tinode);

	/* Test for rationality. */
	maxinode = (fp->s_isize - INODEI) * INOPB + 1;
	if (fp->s_isize >= fp->s_fsize)
		return 0;
	if ((fp->s_tfree < fp->s_nfree)
	||  (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
		return 0;
	if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
		return 0;
	for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
		if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
			return 0;
	for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
		if ((*ip < 1) || (*ip > maxinode))
			return 0;
	return 1;
}
 - INODEI) * INOPB + 1;
	if (fp->s_isize >= fp->s_fsize)
		return 0;
	if ((fp->s_tfree < fp->s_nfree)
	||  (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
		return 0;
	if ((fp->s_tinode < fp->s_ninode)fsck/link.c   644      3      3        2762  4664524116   6061 /*
 *	Routines to handle the counting of links for each i-node
 */

#include "fsck.h"

linkincr(inum)
ino_t inum;
{
	if (inclinkctr(inum) == 0 )
		fatal("Too many links in i-node, %d", inum);
}

/*
 *	The following is the beginning of thinking of how to change
 *	the number of bits used in the link count tables from 8-per
 *	i-node to 2-per i-node, with additional tables for those
 *	i-nodes with more than 2 links.  The changes would be to the
 *	definition of i_lnks, the macro linkctr(), the function linkincr(),
 *	and in init.c, the allocation of table space.
 */

#ifdef	NEWLINKSTUFFF

char	*linkmap;	/* table of inodes with one link */

#define testlink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
			  3 << (((unsigned)bn)&(NBPC>>1)) )
#define marklink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
			  1 << (((unsigned)bn)&(NBPC-2)) )
#define unmarklink(in)	( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
			  1 << (((unsigned)bn)&(NBPC-2)) )

linkcntr(inum)
ino_t inum;
{
	index = ((unsigned) inum) >> (LOGNBPC-1) ;
	distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
	mask = 3 << distance;
	answer = ( linkmap[index] & mask ) >> distance;

	if ( answer < 3 )
		return(answer);

	hash = inum & 0xFF;
	bucket = &linktable[hash];
	bktinum = bucket->inumb;

	if ( bktinum == inum ) {
		answer = bucket->numlink;
		if ( answer == 0xFF )
			return( bigcntr(inum) );
		else
			return( answer + 3 );
	}

	if ( bktinum > inum )
		fatal("internal linktable corruption.");

	
}

linkincr(inum)
ino_t inum;
{
}

#endif
num) >> (LOGNBfsck/main.c   644      3      3       12436  5041134504   6053 /*					
 * fsck  --  File System Check Program
 * an interactive file system check and repair program.
 *
 * Usage:
 *	/etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
 *	audit and interactively repair inconsistent conditions for
 *  	file systems.  Options -y and -n indicate an assumed response
 *	to all questions asked by fsck.  Default is to prompt operator
 *	for yes/no response.  Option -q is to quiet fsck from printing
 *	certain messages, i.e. no size check messages, unreferenced
 *	pipes will be silently removed, and counts in the superblock
 *	will be automatically fixed and free list salvaged, if necessary.
 *	Option -f is for a 'fast' check of the file system, i.e. only
 *	check blocks, sizes, superblock counts, and the free list.
 *	(-f) does not check pathnames, connectivity, or reference
 *	counts.  Option -s forces the reconstruction (or salvaging) of
 *	both the free inode list and the free block list, even if there
 *	are no file system problems.  This will reorder the free block
 *	list in the best order to limit additional fragmentation (respecting
 *	interleaving as well).  Note: Option -s will be ignored on mounted
 *	file systems.  The option -S acts in the same manner as -s except
 *	that it will not be ignored on mounted file systems.  Beware: -S
 *	on mounted file systems should only be used if you intend to reboot
 *	NO SYNC immediately afterwards.  Option -t sets the temporary file
 *	to use for disk caching of necessary tables on filesystems which are
 *	too big to do in core. The temporary file defaults to "/dev/rram1",
 *	which must be there.
 */

#include "fsck.h"

int	errflag;

int	mdaction;			/* default action for invocation */
int	daction;			/* default action for file system */
int	gSflag=FALSE;			/* force salvage flag ignored mounted */
int	gsflag=FALSE;			/* force salvage flag ignored mounted */
int	sflag=FALSE;			/* force salvage flag	*/
int	qflag=FALSE;			/* fsck quiet flag	*/
int	fflag=FALSE;			/* fsck fast flag	*/

char *tmpfile = NULL;			/* TMP file for virtual.c */
char *checklistfile = "/etc/checklist";	/* default file for list of file */
					/* systems to fsck. */
char *filelist[NFILSYS];		/* list of filesystems */
char word[MAXCH];			/* hold single words */
char *fsname;				/* file system name */

dev_t	rootdev;			/* root device number */
dev_t	fsysrdev;			/* file system real device number */
int	mounted;			/* flag for mounted file system */

int	changeflg;			/* file system modified flag */

main(argc, argv)
char *argv[];
{
	int yflag=0, nflag=0;
	int retval;

	while (argc>1 && *argv[1]=='-') {
		switch (argv[1][1]) {
		case 'q':
			qflag = TRUE;
			break;
		case 'y':
			yflag = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'f':
			fflag = TRUE;
			break;
		case 'S':
			gSflag = TRUE;
			break;
		case 's':
			gsflag = TRUE;
			break;
		case 't':
			tmpfile = argv[2];
			argc--;
			argv++;
			break;
		default:
			usage();
			break;
		}
	
		argc--;
		argv++;
	}
	
	if ( yflag+nflag > 1 )
		usage();

	mdaction = ( yflag ? YES :
		    nflag ? NO : ASK );

	if ( argc > 1 )
		retval = allfsck(argv+1);
	else {
		getlist();
		retval = allfsck(filelist);
	}
	exit(retval);
}


/*
 *	perform fsck on each of the individual filesystem in list
 */

allfsck(fsl)
register char **fsl;
{
	int fatal();
	int retval = 0;

	sync();
	statit("/", fatal);
	rootdev = stats.st_dev;
	while (*fsl != NULL)
		retval |= fsck(*fsl++);
	return(retval);
}

/* 
 *  	get the names of the filesystems from the default file
 *	checklistfile  (e.g. /etc/checklist)
 */

getlist()
{
	int fd;
	int index, size;

	if ( (fd = open(checklistfile, 0)) == (-1) )
		fatal("Can't open checklist file: %s", checklistfile);

	index = 0;
	while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
                filelist[index] = malloc( size );
		strcpy(filelist[index++], word);
	}

	if (size != 0) 
		fatal("Too many file systems in checklist file: %s",
							checklistfile);

	filelist[index] = NULL;

	close(fd);
}

/*
 *	read in the next "word" from file with descriptor fd
 *  	return the length of the word.
 */

getword(fd)
int fd;
{
	int n = 0, num;
	char *cp = word;
	char ch;

	while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
		( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );

	if (num != 1)
		return(0);

	do {
		*cp++ = ch;
	} while (  (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
		(ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
	
	*cp = '\0';

	return(n+1);
}
	
/*
 *	perform fsck on the given filesystem
 */
fsck(name)
char *name;
{
	int retval = 1;
	int nonfatal();

	fsname = name;		/* file system name */
	errflag = FALSE;
	statit(fsname, nonfatal);
	fsysrdev = stats.st_rdev;
	if ( errflag )
		return(retval);
	changeflg = FALSE;
	init();
	if ( sflag = ((gsflag && !mounted) || gSflag) )
		printf("Switch \"-s\" selected to automatically rebuild free lists\n");
	if (!sflag && gsflag)
		printf("Ignoring \"-s\" on mounted file system\n");
	if ( !errflag ) {
		phase1();	/* check blocks and sizes */
		if ( !fflag ) {
			phase2();	/* check pathnames        */
			phase3();	/* check connectivity     */
			phase4();	/* check reference counts */
		}
		phase5();	/* check free list	  */
		phase6();	/* salvage free list	  */
		retval = cleanup();
	}
	return(retval);
}

usage()
{
	printf("\
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
	_exit(1);
}
sflag && gsflag)
		printf("Ignoring \"-s\" on mounted file system\n");
	if ( !errflag ) {
		phase1();	/* check blocks and sizes */
		if ( !fflag ) {
			phase2();	/* check pathnames        */
			phase3();	/* check connectivity fsck/objects/   755      3      3           0  5045007474   6312 fsck/objects/main.o   644      3      3        4453  5045007122   7477 0pIVW��F��F��~��v
�|�=-t��~
�}�E��B�CC.;��u`.�gSfnqsty~vo`��h�6�;�F��4�F��-�8�%�0��2��~
�E�:�N�F
��r�N�F
�c��F�F�=~�Z�~�t���~�t�����~~�F
@@P��Xh����F�P�����_^�VW��v�F����hhM��������<t�����5�=��	F���F��_^�VW�j�6<�����F�=��u
�6<hO�����F��v��b���F��t-�~�
}'�~���P�u�����h�~��F������\����Ã~�t
�6<hm�G����~���Dž�v��3����_^�VW��F��F�j�F�P�v�����F�=u�~� t�~�	t݀~�
t׀~�
tу~�t+��M�~��F��F����F��F�=},j�F�P�v�����=u�~� t�~�	t�~�
t�~�
u��~���F�@�_^�VW��F��F��hP�t������>ur��[��>2t�>t�>0t��+��4�t	h��2����>4u�>2t	h������>u���>8u	�����������������F��F��_^�VWU��h������j������_^�>/etc/checklist/Can't open checklist file: %sToo many file systems in checklist file: %sSwitch "-s" selected to automatically rebuild free lists
Ignoring "-s" on mounted file system
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
daction_errflag_strcpy_main_fsck_ncleanup_stats_tmpfile_:open_init_gsflag_2fsysrdev_malloc_exit_fsname_getword_�getlist_@mounted_word_sync_fflag_8phase1_phase2_rootdev_phase3_phase4_phase5_phase6_fatal_qflag_6sflag_4mdaction_printf_nonfatal_gSflag_0usage_close__exit_statit_checklistfile_<read_filelist_changeflg_allfsck_�$<00% 2 R T V X Z \ ^$b$x$�$�$�0�0�0�'�0�'�)0�7�
7'$7&'' 0/$J7M$\$_7b0p7�'�)'�'�)7�$�$�7�'�)7�$'�7�(7>('}'�'�!7�&'�'�'�'�*7�	$�'�$�$�$�7� $�$�$�7� '�7�$�7�7�7777	$7 7&%0usage_close__exit_statit_checklistfile_<read_filelist_changeflg_allfsck_�$<00% 2 R T V X Z \fsck/objects/init.o   644      3      3        6460  5045007137   7524 L��jVW�"�>u+����F�P�6������=��u*�F��v��6������=��u�6h`������~�u�������~�uhw�h��6ho�t����F�P�6�f���=��u	�6h�렋F�%��Fށ~�`t�~� th��8���=t=������>u����_^�VW�hjj������P�>P�u�u������>P�E�U+���@}-����P�F�����>P�u
�u�����~��E�U
F��+���d}F���>P�����������>P�������������n����>P�������������T����>P�������_^�VWU��>P�E�U�L�N����؋ʡL�N+�ѣ��>~"��;N|;Ls�>N|	"�>Lw�6�6N�6Lh��8����>P�E=@~	h�����>P��=d~	h�����_^�VWU��FPh����j�6h�~����_^�VW��F��>u�HH����F�jj�L�N��-��RP�;����F�PP�v��v��*���+����_^�VW��Ɔ.�/Ɔ/�dƆ0�eƆ1�vƆ2�/Ɔ3���6��F�=u�N���=/t;6w�</uF��X�P�6^�����=��udžT�džV����n���p���T���V�j�6Z�����F�=��u�jF�F�P�v��|���=Fun�~�t�~�t�j �F�P��3�P�Z���ƆS�hC��.�P�G����;u�hC�F�P�1����;u��+����V���T��F�P����j�6\������F�=��t}jB��v�P�v������=Buh��v�t�~�t�j �F�P��3�P�����ƆS�hC��.�P�����;u�hC��v�P�����;u��+����v�P�����;u����_^�VWU��>t=�~�F
�V;UD|;EBs�~�EB�UD�F
�V�F
P�#���P�vj �6h[��FBP����P�vj �6hw�����
�_^�VWU��>t�vj �6h���vj �6h�������_^�VWU���_^�

7CMCan't open: %s%s: %s
(NO WRITE)Can't stat: %sfile is not a block or character device; OK?Size check: fsize %U isize %uToo large free block countToo large free i-node count%r
fsck: %s: Bad Super Block: %u
/etc/mnttab/etc/mtab/etc/boottime%s mounted on %.*s as of %s%s unmounted.  Last mounted on %.*s -- %s%s mounted on %.*s
%s unmounted.  Last mounted on %.*s
fsize_Lfstat_daction_errflag_numfiles_fsfd_mtab_name_\isize_writeflg_dupblck_Pprmnttab_�checksuper_�stats_ninodes_open_init_fsysrdev_query_nothing_Ctotfree_fsname_offsets_Rstat_mounted__canl_bread_fflag_lrdivrootdev_bttime_name_^sbp_Pprmtab_mnttab_name_Zalloctables_�domount_�initV_readsuper_�sbpfix_mdaction_superb_ctime_strncpy_printf_nonfatal_totdups_badsuper_dstatit_read_'P''&'7'#'477'='F$I7L+0R'\'b'i&'l'p${$�'�$�7�*'�7�'�$�$�7�0�'�%0�0�'�0�'�'�'7$
''$7$#$9$E7N$k7v$}7�$�7�$�$�$�$�'�$�$�'�'�'�'�$�$$$'$ $$$'0*'1$7$B0E$L$X0[$n7q*'z$}7�*'�'�'�
$�$�7�7�#'�,'�$Z$\$^'''%$679$e7h0v7�/7�) �7�.'�'� �7�.'�'�'�0�0�$�77/7<) G7O.'U'Y ^7f.'l'p'|0�'�'�'�'�'�7�('�$�7�('$7
*''&$)'4$77:*�'�$�$�7�0�'�%0�0�'�0�'�'�'7$
''$7$#$9$E7N$k7v$}7�$�7�$�$�$�$�'�$�$�'�'�'�'�$�$$$'$ $$$'0*'1$7$B0E$L$X0[$nfsck/objects/phase1.o   644      3      3        7042  5045007155   7737 ��4>VWU��>u	h���������>t����_^�VW���F��F���;V�
}�;F�w�j�v��v������t
���F��V���h�v��v��������F��~�}MV�e���V�b��=u*�>uWV�l��WV�7���t�>uWV�p��V�(���G��@�F�뭃>u�|�h�v��v������j��_^�VWU��v�<u�|t��+��_^�VW��v�~
�%��F��G�CC.;��u:.�g
 @`�{sow]jj	��+�RP�����Qj��j��j��j��jj	��+�RP�t���Wh��j���=t"=uV���jj	��+�RP�I�����_^�VWU��^�G�W
�F@���v;�v��F����_^�VW�:�^�%��FƁ~��t�~�@t+��j
�FP�F�P�����+�������+���
}Z+���}P����;�}C����݋G̋WΉFȉV��tW�v
R�v��.��=t댋����������G�F롸�_^�VW��F�N�u3�������v�v
�v�������v�v
�v�������=ur���P�v
�v��������;�vT�ރ���W�F�V
RP������F�V
�u�^�����������v�v�v
�v�A����u�+��	�������_^�VWU��vV�v
�v�����=uV�v
�v��������_^�VWU���;V
|r;Fwm�F�V
;|_;sY���>ujj
�F+�RP�����v�v
�vh��������=
}��N�vh�����=t8=t6�6��;V
|�;Fv��~
|��~r��~u����v���+��_^�VWU��j�v
�v�����uj�v
�v�n����.�����>ujj
�F+�RP�@����v�v
�vh=�.����>}B�>����F�V
������=
}��7�vhx�����=t!=t�hZ�����=t=t�����������+��_^�VW��v�%����D�T
�F��V����u
RP�v
�����v��v��v
V����_^�VWU��~xu"�~u�v
�v�vh��Z���=t=tK�~rw�~ s�v
h��6����Ft�v
h
�#����v�v�^���t.�v
h.����� �v�����jj	�F
+�RP�������_^�VWU���v�v
����t�vh[������_^�VW����	�������F��V��F�V
;V�|;F�w�F�V
��;V�|
;F�w��+��_^��@ Phase 1 : Check Blocks and Sizes
Unknown File Type i-number = %u (Clear)Bad block %U, i-number = %u
Excessive Bad Blocks i-number = %u (Continue)Dup Block %U, i-number = %u
DUP Table Overflow (Continue)Excessive Dup Blocks i-number = %u (Continue)Bad Directory Size, size = %D, i-number = %u (Clear i-node)Directory Size too small i-number = %u
Directory Misaligned i-number = %u
Possible Directory Size Error i-number = %u
Possible File Size Error i-number = %u
fsize_checkmode_"dupflag_inuse_isize_phase1b_dupblck_checkbad_�checkblks_�findblock_l3tol_inodescan_,query_numbad_totfree_checksize_Adirsize_�offsets_clrflg_numblks__canl_lostsize_bread_fflag_phase1_checkdup_pqflag_bwrite_dodirect_�zeroinode_�blockcnt_�doblocks_�totdups_printf_sparsecnt_databuf_abort_numdup_filesize_"candino_sizerr_G'$
7!'0' 7&'@0K0S7^	'u#7~'�'�#7�'0�'�0�0�'�0�7�''�0�'�#7�0� 7 S U W Y [7h	7�	$�7�0�7�	'�'�'�07'
'1"'5"'8'<'?%'B
'X0|$�$�'�"'�"'�"'�"'�'�'�"'�"0�0�0�775$L$P'T"'X"0i0�0�'�'�'�0�'�7�	$7!'
'
$"7%'7'\'a0e7h$7~	7�	'�'�0�'�'�7�	$�7�!'� '� '� '�'�'�%'�%$
7
$7"74$79$0i0{$�7�$�7�!$�7�!0�$�7�!07	'0.$;7>!'N'R'�#7�'0�'�0�0�'�0�7�''�0�'�#7�0� 7 S U W Y [7h	7�	$�7�0�7�	'�'�'�07'
'1"'5"'8'<'?%'B
'X0|$�$�'�"'�"'�"'�"'�'�'�"'�"0�0�0�775$L$P'T"'X"0i0�0�'�'�'�0�'�7�	$7!'
'
$"7%'7'\'a0e7h$7~	7�	'�'�0�'�'�7�	$�7�!'� '� '� '�'�'�%'�%$
7
$7"74$79$0i0{$�7�$�7�!$�7�!0�$�7�!fsck/objects/phase1b.o   644      3      3        2472  5045007170  10100 �>��VWU��>u	h��������_�_^�VW��F��F��F�;s8�~��F��������F��V�jRP�����u�j�v��v������F�뿋F���_^�VW���F��F���;V�|l;F�vgj�v��v��X����t
���F��V���h�v��v��8�����F��~�}�V�#���V����=uWV����>t	G��@�F����_^�VW�:�v�~
�%��FƁ~��t�~�@u^j
�DP�F�P�������F��~�
}=�F��~�}-�^���F�;�}�v�W�^�����w��w������F����F���_^�VW��FF
u���v�v
�v����tr=uo�F�N�t؍��P�v
�v�0����������dž�������}������������U�F�V
RP������F�V
�v�vRP�t����t�����+��_^�VWU��j�v
�v������u��>�j�v
�v�����>ujj
�F+�RP�����v�v
�vh�����+��_^�Phase 1b: Rescan for more Dups
Dup Block %U, i-number = %u
inuse_isize_phase1b_dupblck_findblock_l3tol_iscanb_zoffsets__canl_bread_fflag_dblocksb_�qflag_cdupb_+totdups_printf_databuf_buildtable_numdup_ckblksb_candino_'$
700'4'C'G7T7f't'�7�'�7�	'�7�7�0�'�75'<'`0w0�0�7�	7079'I7T'[
7l${7~findblock_l3tol_iscanb_zoffsets__canl_bread_fflag_dblocksb_�qflag_cdupb_fsck/objects/phase2.o   644      3      3       11604  5045007207   7755 ��8�|VWU��>u	h��������j�}���_^�VWU��jjj���������u	h�����jjj����%=th�����=t
=u�=���jjj�|�������th	�k���=t=t��Y�j�T����_^�VWU��>u	h.	�;���jjj�/���%��
Pj	jj����hj�������$��@hj������_^�VW�j������F����u
�6��������E�~s�Zw	�~
s�O���v�b����j�>~�K�㋟�7�jhm	�ƃ�P�����n
�^�F
�V�؋ʃ�s��w��s��j	�>~�KK�㋟�7�jho	�ƃ�P������n
�^�~ws��~
s���sd�~wr\�~
rVV����=u=j�v�V�S��j������^��G�u
�6������^��G�F��^���G���n
�^떃>t�v����u���v�4�����V����_^�VW��v� �F�;~�~�F����_^�VW��v����RPV�#����F��V��uhh�
����%h�v��v������h�����F��V����_^�VW���-��RP�v������F��V��u+��h�K���h�v��v�������_^�VWU��hr	�����_^�VW��v�~
�F�N�t��G�F���F���^�����_^�VW��v�|��F��v
W�=����u�F�;FuW���=t�v�p��v������_^�VW��v���D�F�;~�s��G�?u��I;�u��3;~�s;~�s��G�?t�;~�t����;~�s
��G�?/u����_^�VW��F-=w6����.��nx����F��	�!�F��	��F��	��F��	��F��	��F��	�6�6�v�h�	�O����>~�>O�狽�5�j�w����>�狅@@P������_^�VW��v�<�u+���D�F�P������F�=tP�6���;>v�v�W����t�V�����j��+�RP��������u	�v�W���j��+�RP��������t'�v�W�����u�j��+�RP�t���%=u�f�W�b����j��+�RP�P���%�_^�VWU��~���_^�VW��F��F�;}�~��F��狅@@P�$�����v����F�
j�F�Pj������_^�VWU��~�}
uWh�	�������vjh�	������_^�VWU��h�v�������u�vh�	����+����Y�vh'
�����t�������t�5h7
��thB
�f����4hM
�[����D8P�Q���P�t
�thX
�A����D�T
�_^�VWU���vhs
�&����v
������6������_^�VW�h�
�����v�=����F��V��v
�����>t!�F�F�u�>u�6�h�
�������
�6������_^�VWU��j�F+�RP����%����uh�
�h�
h�
�����v������v
�A����6��g����_^�VWU��vj��+�RP�M���%=uV��jj
��+�RP�.���hV�$�����j
PhT�������%�=@t
Vh�
��������w
�whT��������=t7�>2|�M���㉿�5�`�����>��}�6�������W�����_^�VWU���vh�����_^�VWU��hA�{���hQ�B����l��_^�P	j
Phase 2 : Check Pathnames
Root i-node is unallocated.  TerminatingRoot i-node is not a directory (FIX)Dup/Bad blocks in root i-node (Continue)File System Read-Only (NO WRITE)
Can't malloc memory, phase 2...Fixblock error.Null nameNon null paddedEmbedded slashes inInconsistent .Inconsistent ..Bad%s entry in block %U in directory
/%s/%*si-number = %u is in a bad inode block.
i-number = %u, Owner=%s, Owner=%u,  Mode=0%o
Size=%U, Mtime=%s(Remove)I-number is out of range  I=%u
Unallocated
%s [Forced - Yes]
Bad or Dup blocks in %s
DirectoryFileTried to checkpath i-node %u which is not dir.
I-node %u is a multiply referenced directory i-node.
Name too long.
candblock_�fixflag_free_daction_numfiles_writeflg_imap_getpwuid_bclear_write_checkpath_�findblock_path_dl3tol_unalloc_�buf2_baddup_Qninodes_writeino_circle_eirange_�query_malloc_copy_~mounted_action_bread_toolong_zblkerr_Tcheckroot_*phase2_zeroent_�procfiles_fatal_format_�fixblkerr_lnextblock_�fixroot_�qflag_bwrite_remove_�pname_�ctime_fixblock_!printf_depth_databuf_cdbn_abort_strcmp_chck_�memory_�linkincr_blocknum_prdirsize_pinfo_Fptrino_cdots_�'&$
7,0'-0!76$D7G!7S$a7d0t7y07�$�7�7�07�4'�$�7�!7�7�'�.7�8'�.7$�7$$7'!0<0G'K/'Q/0Y'`'e.'k-'r-'y$�0�'�0�0�'�-'�-'�$�0�'�0�0'.00)71$B7E!'n0w0�0�'�'�.0�'�/'�/'�/'�/7�'�.7�'�.7'.0'5'5'(/',/7:'N.0Q'W.7`'$r7u!7�10�0�7�4 l n p r t v${$�$�$�$�$�'�5'�5$�7�,'�-'�-'�0�'�-'�-'�0�'�-00
0'#0,077G0Y7f0x7�0�7�4'�7�'�'�-'�0�0�7	$*7-,$:7=,'L7R8$a7d,$s7v,7$�$�7�,$�7�,7�*$�7�,$�$�7�,0�$�7�$�7�,00'',$3$679,$E7H7`$p$u$x7{,0�0�$�7�7�0�0�7�'�.7�8%�%�7�
%�$7!%%0'%-0+'/-'3-'90>'E-%I%P7S7\$n7q,$�7�,$�0�7�0$r7u!7�10�0�7�4 l n p r t v${$�$�$�$�$�'�5'�5$�7�,'�-'�-'�0�'�-'�-'�0�'�-00
fsck/objects/phase3.o   644      3      3        6464  5050255263   7751 l64 FVW��>u	h{������F��F�;wFj+�RP�����%=u-j�F�+�RP�����uj j
�F�+�RP�����v��<���F���F��F�;s"j+�RP����%`= u	�v�� ���F����_^�VW�>j�F+�RP�P�������t��h�v�9����F��~��E�U
�F‰V��y��u�u��j
�F�P�F�P�������F�P������F��F� �n� �^��F‹V��x~u�tx�~�wrp�~�rj�~�sR�~�wrJ�~�rD�~���F��t*j+�RP����%=u�F�;Ftj@j
+�RP�t����F��n��^�맍F�P�\����F���_^�VWU��h��C����v�:����t�>t�>u�6n�����u��6nh�����j�v����_^�VW�@�F��I�F��t+j+�RP�����%=uj�F�+�RP���������t��&h�v������F�j
P�F�P�����~��E�U
�FĉV����~�ws���~�s���F�P�^����F��~�sփn��^��~ƒ=t��F�j�v�W��P�F�@@P�"����F�P�����u���v������~�y�FċVƋ~�)EU
�F��~
u3�v��v���=u"�~��Eh�v�������v��vj�@����~�th�v������� �F��:���~
u�v��vj�	��+��_^�VW�0�6l�v�F�P�s��h�j�F�P�d���v
�o��P�v
�F�P�M����~u�>���F��
�>���F����>���FЉ��v
������_^�VWU��F
�~�j�v�F@@P������_^�VW�<j�F+�RP��������t	�v����h�v�����F�j
P�F�P�����~��E�U
�FƉV����~�ws��~�r}�F�P�R����F��~�sك~�wrу~�r�h��F�@@P�)����u8�vh������~��5h������F
�~ĉ�F�P������u������n��^��F���v�����_^�VWU���vh������_^�VWU���vh1�����_^�VW�hj�����F�j
Ph������~��E�U
�F��V����~�wrR�~�rLh��P����F��~�s݃~�wrՃ~�r��6l�F�@@P�&����u�~����n��^��F���+��_^�VWU���6lhd������_^�VWU���6lh~������_^�VWU��v�
ƅ�t&�~"O�ߋ�+�.�6j��0����+�.�6j���֍��_^�
p�lost+foundPhase 3 : Check Connectivity
(Reconnect)Unref Dir
%s FORCED
??..Dir i-number = %u connected.  Parent was i-number = %u.
Dir i-number = %u connected.  It has bad/dup blocks.
Dir i-number = %u connected.  It has no .. entry.
Sorry.  No %s directory.
Sorry.  No space in %s directory.
daction_numfiles_lostname_lnoparent_Iconnect_checkpath_traverse_�findblock_path_l3tol_buf2_ninodes_writeino_dirinit_connected_6markchildren_�mounted_nameit_(action_reconnect_nphase3_fixblkerr_nextblock_qflag_badconnect_4fixblock_strncpy_printf_depth_cdbn_databuf_strcmp_noroom_linkincr_pinfo_ptrino_namebuf_lostfound_^nolost_�unrefdir_�$l'$7' 7+7B7W0`'t70�7�0�'�7�#0�0�7�	''7''G7l7�7�'�$n$�7�7�"'�'�$�7�$�$�7�0�07#7:0H0K'N
7T#7g	'}'�0�0�7�'�'�0�0�7�7�7�7�!'�0&'7
7=0K'Y
7_0n0q0�$�0�$�0�0�0�'�'�'�'�'�'�'�'�'77-7F0W0Z']7c#7v	'�'�0�7�'�'�$�7�$�7�$�7�770($=7@$R7U'e7j#%y7|	'�'�%�7�'�'�$�7�$$7	$$7'5$ J'S$ \'d$0�0�7�	''7''G7l7�7�'�$n$�7�7�"'�'�$�7�$�$�7�0�07#7:0H0K'N
7T#7g	'}'�0�0�7�'�'�0�0�7�7�7�7�!'�0&'fsck/objects/phase4.o   644      3      3        6171  5045007242   7741 H�VW��>u	hN������F��F�;v��j+�RP���������t�v��F��=u�F���j�F�+�RP�����u<j�F�+�RP����%=t%j�F�+�RP�|�������t�v�����=t�j�F�+�RP�W����u(j�F�+�RP�D�������t�v����=u�q��v��?���F�=��u�F��Y�j�F�+�RP����;F�u�B��v��v�����3���_^�VW��v����%���t��u=��������AA��+҉F��V�jRP�����t
��t����'hV�v��v���������V�F�P�{����^��G�_^�VW��>u&j�F+�RP�U���%=u�v������v�5���Ph�+����v�"����F��V��>t1�u-�>u&j�F+�RP�����%=u�6Hh��������6�����=uj�v������u�v������_^�VWU���6H����=u�v�������_^�VW�h�v�y����F�P�o���h�v�c���jj	�F+�RP�R���jj
�F+�RP�A����_^�VWU���v�/���Ph��%����v����j�F+�RP�
���P�v
h������6J�����=u	�v����_^�VW�h�v������F�j�F+�RP������~��Eh�v�����_^�VWU���v����Ph������v�����v������_^�VWU���v�n���Ph��d����v�[����v�����_^�VW��F��F��F�;wj+�RP�)�������u�F��F����F��F���;V�|%;F�v j�v��v�������t�n��F��V��Ћ>���;F�t7�>u�>th�����6L����=u�F��>�����>t�>t�>t��u���_^�VW�
�>���F�=dv+���F��F�;F�r��~���>��
�F��~������GG��+҉F��V�jRP�����t�~�u��~�u��~�r��F�;w�j+�RP���������u�j�F�+�RP��������ǀt�o�h�j
�F�+�RP�����F��a���_^�VW���F��F��F�;wQ�~�d}Kj+�RP��������u2�~������GG��+҉F��V�jRP�Z����t�~�u	�~�u�F��F�릋F��>���F��F�;wa�~�~[j+�RP��������uB�~������GG��+҉F��V�jRP������t�~�u�~�u�N��~���>�F���
�F��h,�����_^�p��Phase 4 : Check Reference Counts
(Clear i-node)Unref %s
%s [Forced - Yes]
(Adjust)Link Count discrepancy in %s
Count = %u, should be %u Unref %s
Bad/Dup blocks in %s
(FIX)Free i-node count wrong in superblock.  Free i-node list in superblock rebuilt.
linkprob_�unrefclr_Ydaction_typename_isize_fixit_Lclearit_Hrebuild_Qconnect_findblock_getlink_ninodes_writeino_mounted_lostsize_action_bread_reconnect_sbp_phase4_askclear_Ofreeilist_�adjust_Jqflag_badilist_�sbpfix_sflag_unreflink_�zeroinode_printf_databuf_doclear_xbddp_�ptrino_pinfo_candino_chglink_'$7' 0%7.	0?7X	7k	7�	0�7�	7�	0�0�0�0�7�	00007T	%h7q%|7�#$H'�7�	0�0�7�$�7�7�"'�'�
7	$$7'!7$740A$V7Y0g'7�!7�'�7�7�	7�	$J7�$�7�7�"7�	$�7�$70'&7,!7>	'J7P7b$i7l7u"0~7�$�7�7�"0�$L'�7�	'�7
	'&'3':$@7C$J7M'\'d'j'q'x0~0�'�0�0�'�7�	'7	7"	007?	0H'Y'l7}	7�	'�'�7�	7	'-$<7?%7.	0?7X	7k	7�	0�7�	7�	0�0�0�0�7�	00007T	%h7q%|7�#$H'�7�	0�0�7�$�7�7�"'�'�
7	$$7'!7$740A$V7Y0g'7�!7�'�7�7�	7�	$J7�$�7�7�"7�	$�7�$70'&7,!7>	'J7P7b$i7l7u"0~7�$�7�7�"0�$L'�7�	'�7
	'&'3':$@7C$J7M'\'dfsck/objects/phase5.o   644      3      3        4231  5045007255   7741 �D�VW��>u	h��������F�jj����-��RP������F�P����+�������v������>u�>t���_^�VW��F��F��~�=u��=@v�h��N�����F��~�F�;}0�~���~�u�u�Y���F�=u
�F��V��F��̃~�t��~�tU�~�tO�~�u�u�#��=u;�F��V�h�~�u�u������F�v�����t�N��h��]��~�u	���>������;u;t?�>u�>th��s����6�i���=u���>��������6�6h��0���6�6h�����+F�V�RPh+����_^�VWU��F
Ft+�~|�~
vh?�hA�v�v
�v�������_^�VWU���;V
|;Fw�F�V
;|9;r3�������|��
vhB�Y���P+��Lj�v
�v�g����t)�������|˃�
v�hF�j�v
�v�,�����_^�VWU���vhJ����hl����=u����_^�VW��v�<@v+��2+�;<})����ƉF�������w�w������^��G�WG�Ӹ�_^�VWU��>t�>u�>u
hw�����t��_^�Phase 5 : Check Free List
Bad freeblock count.
Bad freeblock count.
Free Block count wrong in superblock.  %U Bad Block%s in Free List
%U Dup Block%s in Free List
%U Block%s missing
sbaddupExcessive %s blocks in free list (Continue)Bad Free List (SALVAGE)fsize_daction_asksalvage_Qstopit_�isize_fixit_findblock_badcnt_query_chk_2totfree__canl_action_bread_badflag_lrdivfixerup_sbp_phase5_qflag_sbpfix_sflag_dupcnt_canfblk_	copyV_printf_databuf_report_�freetrav_�'$7''$'(797C'M'Q'T'X'\0d'k'q'x0~0�'�$�7�0�0�0
' 7,
'40:0D'H$M0P'Z0_'c'o
'u
'{'�$�7�'�7�'�
'�
'�'�'�'�$�0�'�'�$�0�'�
'�
$�0�$$7#'*'8'O'W']'c'h'm'q$�0�7�'�'�'�'�'�$�7�$�7�$�7�79'X'_'f$l7o'z	copyV_printf_databuf_report_�freetrav_�'$7''$'(797C'M'Q'T'X'\0d'k'q'x0~0�'�$�7�0�0�0
' 7,
'40:0D'H$M0P'Z0_'c'o
'u
'{'�$�7�'�7�'�
'�
'�'�'�'�$�0�'�'�$�0�'�
'�
$�fsck/objects/phase6.o   644      3      3        4104  5045007271   7737 b�0�VWU��>t$�>u	hb�������t
��6 ������_^�VWU������*����,�>,��*;,�,��>*�t*h����h�������,������*����6,�g���� �uh��W���h��N���+��w�,H��>,�.,�ȋ���"�$�,�RP�RP�6�6����RP�����&�(�,��>*��+�;6,}�� �ƙ�����.*�ȋƙ����F�۸�_^�VW�
����������>|	�>@s���@�F��>��F��)���@@����F��V��F��V�;|@;s:�v��v������F��V�jRP�/����u�v��v�����t
�F��V���_^�VW��.�>�F�V
��U�@@;s��>u�>t�6����h�6�6����hh�����uh�v
�v����+��M�F�V
����>|	�>@s���@�F��>��F��)���@@���_^�VW��F�V
;$|G;"rA�F�V
;(|3;&s-�,�RP�v
�v�����F��)FV
�> ��*�FV
�F�V
�_^�VW��v+�;<})����ƉF�������w�w�����^��G�WG���_^�Phase 6 : Salvage Free List
Invalid interleave factors in superblock.
Default free-block list spacing assumed.
Can't malloc space for interleave table.
Free-block list is not rebuilt.
fsize_free_isize_maketable_4bclear_findblock_malloc_totfree__canl_lrdivlrremfixerup_sbp_phase6_canwfblk_%addfree_�qflag_sbpfix_bwrite_lrmulwritefree_4freeblks_fblkp_printf_dp_blknm_databuf_bmap_�''$700$%(7+';%B%I%M%T%X%]%b$i7l$r7u%~'�%�%�7�%�$�7�$�7�'�%�%�%�%�%�%�'�'�7�	7�%�%�%�%%
%%'<'A'E'H'L'P'V'['a'e'n't'�'�'�'�'�'�'�0�7�0�'�'''0' '''.01'7';'?7B'K7N'T'X']7f'v'z'~'�'�'�'�'�'�'�'�%�%�%�%�%�7�
%7Lm_databuf_bmap_�''$700$%(7+';%B%I%M%T%X%]%b$i7l$r7u%~'�%�%�7�%�$�7�$�7�'�%�%�%�%�%�%�'�'�7�	7�%�%�%�%%
%%'<'A'E'H'L'P'V'['a'e'n't'�'�'�'�'�'�'�0�7�0�'�'''0' '''.01'7';'?7B'K7N'T'X']7f'v'z'~fsck/objects/cleanup.o   644      3      3        2674  5045007303  10206 ���VW��F��>u�$���>u��F��6���������F��_^�VW��>�u�u�����>�E�U+���@}-�����F�����>�u
�u�����~��E�U
F��+���d}F���>�������Z����>�������������@����>�������������&����>������Wjj�����_^�VWU��>u
�6h���������؋ʡ�+��+RPh�������6�6h������t`jh����-��RP�������>u�>th0�h2�6�6h�d���h3�[���h[�R����_^�VW��F��6hk�6����>th��&����F��F��_^�%u files %U blocks %U free
Expect roughly %U missing block%s next
stime fsck is run as a result of inodes being cleared.
 ***** File System %s was modified *****
 ***** BOOT Coherent (NO SYNC!) *****
fsize_numfiles_fsfd_isize_cleanup_totfree_fsname_mounted_advise_�lostsize__canl_fflag_lrdivsbp_prtstats_�sbpfix_bwrite_printf_close_cleanV_writesuper_9changeflg_'
00'0 ''7*70'A
7J
'Q
'g
's
7|
'�
7�
'�
7�
'�
7�
'�
7�'�'$	7''''&'*$/72'9'=$@7C'I	'M	'W	'[	7l'r	'v	'z	'�	$�$�'�	'�	$�7�$�7�$�7�'�$�7�'�$�7�fflag_lrdivsbp_fsck/objects/util.o   644      3      3        7635  5045007407   7543 ���IVWU��h�v�����=��ujh�_���vh
�V
���_^�VWU��FPh������H=w�����.��Uti[h(������h9������6=Nt=Yt�본�_^�VWU���v����=t
=u��+��_^�VW�j�F�Pj�B����F��~�~�u	hI����F��F�;F�}����E���F�= t�~�	u�F��݃~�a|
�~�z�n� �F��_^�VWU��j�F+�RP�����%-=w,����.��>MHRW\���������
���������_^�VWU��h�����_^�VWU��FPh��w���j�o����_^�VWU��FPh��Y�����_^�VW��v�~
��������AA��+҉F��V�jRP�#����t�~�u�~�t+��'W�v��v��
������%��ljF�P�G���F��_^�VW��F��%��F
�F�P�!���v
�~�����GG��+�RP����_^�VWU��v�t
�t�����D�T
�t6�t4�����D4�T6�t:�t8�o����D8�T:�t>�t<�]����D<�T>�_^�VW�
�F��~�|�<�~����F
�V;��|~�;��r��~�t�~�O��������)F
V�F����P�v�v
������F��V��~����������v�v
������F
�V�^��������F����F����T�F��V��u��F��N���h�v��v�����F����P�v�v
�m����F��V��~����������v�v
�M����F
�V�F�������T�F��V��t��T�F��V�RP�����F��V��r��F��V��
�F���+����_^�VWU��v�~
x�F�V
;|0;r*�v
�v�6������=t=uhV�2�������;V
|;FvV�v
�v����t�j�F�V
�	������RP�6�n������Ǚ�؋ʃ��u$���u�v
�v�6�|���=t=t����hV�6�.���=t �v
�v�6�J���=t=u�M��n��_^�VWU��>u���~
x�F�V
;|(;r"�v
�v�6������=t
=u����j�F�V
�	������RP�6�������Ǚ�؋ʃ��u$���u�v
�v�6����=t=t^����h�v�6�[���=t�v
�v�6�w���=t=t*�����;V
|;Fr�v�v
�v�����_^�VW��v��;V
|
;Fs+�����;V
|A;Fw<��;V
|1;Fr,���؋ʋF�V
+�ѹ	������T	PV�������F��F�V
��-���;~���+@��	�F�j�F�V
�	������RP�6�R������Ǚ�؋ʃ��u���t�v�hT	�6�/���;F�t�����&�V�v
�v�����_^�VWU��v��;V
|;;Fw6��;V
|+;Fr&V���؋ʋF�V
+�ѹ	������T	P����_^�VW��v�~
�F��F��N��t��F�F���G���^�����_^�VWU��v�~
�t	��F�Ou��_^�VWU���;V
|;Fw�F�V
;|;s��+��_^�Z_cu��
��@�@ 
�@ ��	-	��Can not stat %s%r [yes/no]: [default - YES]
[default - NO]
Invalid ResponseFILEDIRCharacter SpecialBlock SpecialPIPEUnknown I-node typeabort.fsck: %r
fsck: %r
Out of Range Block number: %U  (CONTINUE)Can not Seek: Blk num: %U  (CONTINUE)Can not Read: Blk num: %U  (CONTINUE)Can not Write: Blk num: %U  (CONTINUE)fsize_nunkwn_�daction_fsfd_errflag_typename_writeflg_isize_chgcache_�bad_�imap_�nblk_�bclear_}write_nchr_�findblock_wtblkerr_ndir_�stats_blkmove_Kwriteino_getcache_�query_1lldivstat__canl_bread_action_�lrremfatal_zbwrite_�nfile_�nonfatal_�printf_lseek_databuf_rdblkerr_abort_h_exit_statit_rgblkerr_�candino_\ptrino_�npipe_�read_nextchar_�changeflg_high_skblkerr_'7'0$%$;7>!'D S U W Y$\7_!$j7m!0u0�7�,$�0�$�$�$�$�$�$�7% < > @ B D F$I$N$S$X$]$b$n0q$�7�!7�&$�7�!'�7�0�0090S7k7}7�7�0�$�0�$�0�$�$�$7$#$'70$@0b0o'r#0{$�7�$�$�7�'�#7�0�0�$�$$$''&$2050I0O0R'U0l0v'�7�"$�0�0�'�7�,$�0�0�0�'0''#$/020B0G'^7a"$�0�0�'�7�
$�0�0�'�0�'�.'�0$$$$4%O0T0]$c$x'|'�$�$�$�'�7�"%�'�7�,$�$�0�0�$$$#%>0B'�'�'�$�0�$�$�$�$�$�$�7% < > @ B D F$I$N$S$X$]$b$n0q$�7�!7�&$�7�!'�7�fsck/objects/fsck.o   644      3      3          54  5045007416   7440    644      3      3          54  5045007416   7440 fsck/objects/printf.o   644      3      3        2543  5045007431  10056 LdoVWU��FP����_^�VW�Y�F�F��^���F��F��^��F�����=%t�u���LjF�j�F�Pj�������F� �F����F����^��F�������-u�F��^��F�������F���0u�F�0�^��F�������*u�^��F���F�^��F������,�F���0|"��9kF�
�ȋ��-0�F�^��F������ك�.uU�^��F�������*u�^��F���F��^��F������,�F���0|"��9kF�
�ȋ��-0�F��^��F������ك�lu"�^��F�������dt��ot
��ut��xu�� �F��F����ǻ��CC.;��t��.�gDOUXcdorsux�M4Q����U���^��F���F�~�}�؉F��F�-j
�v�V�b������j
�^��F��7��j��j��^���W�F�V�F��~�y���؃��F�V��F�-j
�v��v�V����j
�^��w�7V�p�����F��fj��j��^���F��u�F�L�F��F��F�����F�?t�~�|��+F�;F�~�N�&�^��F���F��F�F蘈��^��7�g����F��F�F�+ƉF��}�F��~�u �F��N��t�F��F�j�F�Pj������;v�v�^��F���F�j�F�Pj��������~�u���F��N��u���F��F�j�F�Pj��������_^�VW��v
�F��F��N��^����+��v���t �N��F��F��+��v�ڊ�T��^������N��^���T���^��?t�F�F�F��F����^���F�_^�VW��v�~�n��N�^���ǙRP�v�v
�(����F�V��t4�N�F�F�ǙRP�v�v
�����؊�T��^��F�V�F
�V��N�F�F�F
�؊�T��^��^�?t
��F�F��F�����_^�{NULL}0123456789ABCDEFwrite_xprintf_vrdivvrremprintf_0
0@7P t0� � � � � � � � � � � �0�0�0-0@$d0�7�700!72$v$�7�7�$$)���_^�VW��v
�F��F��N��^����+��v���t �N��F��F��+��v�ڊ�T��^������N��^���T���^��?t�F�F�F��F����^���F�_^�VW��v�~�n��N�^���ǙRP�v�vfsck/objects/link.o   644      3      3         273  5045007443   7472 (<
VWU��j�F+�RP������u�vh(������_^�Too many links in i-node, %dfindblock_fatal_linkincr_7$7fsck/objects/virtual.o   644      3      3       10046  5045007462  10263 �r���$VW�$�F+ңF�H�F
+�FH�J�L�F+�JL�N�P�F+�NP�R�Th�jhV����h�jh������֋���F���F�+�;Tv�xr	;Rv�m�>t���6��a���@=w%����.�������6�h���6�h!�6����F�P�6��(���=��t�F� t�F���%�=t
�6�hZ����j�6�������֋=��u
�6�h~������F��F��F��V�;Trv�;Rr�hh��6֋����=t	h������F��V��j�6�����֋=��uEh��6�r����֋=��u
�6h��]����6֋�S���j�6�G����֋�6�:����F�P�6֋�,���=��u
�6h������F�;u	h������_^�VW��>֋�u��6֋������>ux�F�P�6������=��t�F� t�F���%�=u�F�t
�6�h!	����j�6������֋=��u
�6�hK	�����6֋�|����}
�6�hk	�k����_^�VW��F=
v������.������ZZZ����???�F�V
%+ҋ������������F���F�V
�������F�V
�~
yh�	h�h�	h�	�����j������J�LFV
�F�V
;Pws�[;Ns�Rh�	h�h�	h�	�5�F�V
%+ҋ������������F���F�V
�������F�V
�~
yh
h�h�	h�	�_���j�W����N�PFV
�F�V
;Tws��;Rs��h6
h�h)
h
��~
xu �~uha
h�hT
h8
����j������F�H-��FV
�F�V
;Lwrr;Jrlh�
h�h
hc
�P�~
xu �~uh�
h�h�
h�
����j�����n�^
�F�V
;Hwr ;Frh�
h�h�
h�
�n���j�f����F�V
%�+҉F��	�F�V
�������F�V
%?+҉F���F�V
�������F�V
%�+҉F��F�V��v��拼V������+҉F�V�;V�u;F�u�*�~�����Vtr��F�V��������F�V��~���	��+�F�V�R�v��v��6֋�����؋ʃ��u���u	h�
����h�F���	�P�6֋����=t	h�
�s����F�+҉F�V���������F�V��~���	��+�F�V�R�v��v��6֋�8����؋ʃ��u���u	h�!���h�F���	�P�6֋�
���=thj�F���	�P������~���F���%����V	�V�~��灥V����V�F���	F���F�F=
v�����.��^z���z����������~�*�#F���~��灥V����V�F��~��*��r�~��灥V����V�F��~�0�ߋ~��ڋ~��灥V����V�F�~����~��灥V����V�F뤋~��灥V����V�~���h)������_^�VWȈ+��Љ�|���~���x���z��F+�;�~�ws�;�|�w�+����}7�F+�;�~�wr*;�|�v$���j��~���|��!����E�F��|���~���+����}��F+�;�z�wr�;�x�v�����E��Pj��z���x������F��x���z����_^���/dev/rram1/dev/rram1closeCan't access ram disk "%s", use the -t optionPossible file system on ram disk "%s", use the -t optionRam disk "%s" not mknod'ed properlyCannot open read/write Ram Disk "%s"Error writing to tmp fileCannot create temp file "%s"Can't stat temp file "%s"Temp File must not be on file system to fsckRam disk close "%s" not mknod'ed properlyCannot open Ram Disk Close "%s"Cannot close Ram Disk Close "%s"%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cp%s: %d: assert(%s) failed.
../virtual.cpError seeking tmp fileError writing tmp fileError seeking tmp fileBad action in virtual systemfstat_write_findblock_�tmpfile_open_fsysrdev_exit_stat_fatal_initV_memset_creat_copyV_unlink_printf_lseek_is_fs_close_cleanV_�read_$�$�%%%%% %$%-%1%4%8%A%E%H%L%T7W
%b7e
%l%|0�%�0�'�0�$�7� � � � �$�$�$�$�7�$�7�$�$�7�$7	%$$7%50<%@0E%K%O7R$]7`'t7w%}'�7�%�'�$�7�%�7�'�7�%�'�7�
%�7�'�$�7�'�$�7�%0
%7'$&7)$Q$T7W$`7c%i$r$u7x%7�$�$�7�0� � � � � � � � � � � � � � � �$$$77%%%)%90@%D0I$L$R$U0X$�$�$�7�7�%�%�%�0�%�0�$�$�$�0�$�$�$�7�7%%%%%-$2$8$;$N$T$W7Z7b%w%$�$�$�7�7�%�0%%L7O$c7f%u%z7}$�7�%�7�$�7�%�%�7�%
7
%"%(%1%7%E0S \ ^ ` b d f h j l n p r t v x0�%�%�%�%�%�%�%�%�%�%$70D0M0y0�$�7�%0
%7'$&7)$Q$T7W$`7c%i$r$u7x%7�$�$�7�0� � � � � � � � � � � � � � � �$$$77%%%)%90@%D0I$L$R$U0X$�$�$�7�7�%�%�%�0�%�0�$�$�$�0�$�$�$�7�7%%%%%-$2$8$;$N$T$W7Z7b%w%$�$�$�7�7�%�0%%L7O$c7f%u%z7}$�7�%�7�$�7�%�%�7�%
7
%"%(%1%7%E0S \ ^ ` b d f h j l n p r t v x0�%�%�%�%�fsck/objects/is_fs.o   644      3      3        1347  5045007474   7667 ���EVW�$�F�P�v������}������F�%�=`t�F�%�= u�j�v��������|�jjhV�����Ћ™�؋ʃ��u���th�h�V����=�t	V�����V�|������u�u�m����E�U�E�F��ρ��F�;�s�^��w�7�F����^���W�F��׍�
�Fދρ���F�;�s�F������������������������@�F܋+�;Uwr
;Er+����E�;��|�;��w�+ҋ؋ʋE�U+���;��r�w;��vċ��;�r��F���;��v��E�F��E���;F�v2�^��+�;Wrw�;w��^���W;U~�v�|;Er�l��F�뾍�
�Fދ����
;F�v�^ދ=s�B�;F�v�:��F��ո�_^�open_stat__canl_lseek_is_fs_close_read_70797M%i7m7y7�%�7�7�7�00�0�0�0���^���W�F��׍�
�Fދρ���F�;�s�F������������������������@�F܋+�;Uwr
;Er+����E�;��|�;��w�+ҋ؋ʋE�U+���;��r�w;��vċ��;�r��F���;��v��E�F��E���;F�v2�^��+�;Wrw�;w��^���W;U~�v�|;Er�l��F�뾍�
�Fދ����
;F�v�^ދ=s�Bfsck/phase1.c   644      3      3       16004  4767515610   6322 /*
 *	phase 1 of fsck - Check Blocks and Sizes
 */

#include "fsck.h"

char	databuf[BSIZE];		/* buffer for blocks */

int	clrflg;			/* indicates when to clear an inode */
int	dupflag;		/* indicates whether there are any dups */

int	numbad;			/* number of bad blocks in the inode   */
int	numdup;			/* number of duplicate blocks in inode */
long	numblks;		/* number of data blks for size check */
long	sparsecnt;		/* count for sparse blocks for size check */

/*  The following is a table of the number of direct blocks pointed at by the
 *  four types of blocks direct, ..., triple-indirect, to help count sparse
 *  blocks.
 */

daddr_t	blockcnt[] = {1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN};

phase1()
{
	if (!qflag)
		printf("Phase 1 : Check Blocks and Sizes\n");
	dupflag = FALSE;
	inodescan();
	if (dupflag)
		phase1b();	
}

inodescan()
{
	register daddr_t bn;
	register struct dinode *dip;
	register ino_t	ino;
	int i;

	ino = 1;

	for (bn=INODEI; bn<isize; bn++) {
		if (testblock(bn)) {		/* block is bad via inode 1 */
			ino += INOPB;
			continue;
		}
		bread(bn, databuf);
		clrflg = FALSE;
		dip = (struct dinode *) databuf;
		for (i=0; i<INOPB; i++) {
			candino(dip);
			if (inuse(dip) == TRUE) {
				if (!fflag) 
					checkmode(dip, ino);
				if ( checkblks(dip, ino) != STOP ) 
					if ( qflag == FALSE )
						checksize(dip, ino);
			}
			candino(dip);
			ino++;
			dip++;
		}
		if (clrflg)
			bwrite(bn, databuf);
	}
}

/*
 *  	Determine if the given inode is in use.
 */

inuse(dip)
register struct dinode *dip;
{
#ifdef NOT_ALL_ZERO_INODE

	if ( (dip->di_mode != 0) || (dip->di_nlink != 0) )
		return(TRUE);
	else
		return(FALSE);
#endif
#ifdef ALL_ZERO_INODE

	register char *ptr;
	register struct dinode *next;

	ptr = (char *) dip;
	next = dip + 1;
	while (ptr < next)
		if (*ptr++ != 0)
			return(TRUE);

	return(FALSE);
#endif
}

/*
 *	Check the mode of the given inode
 */

checkmode(dip, ino)
register struct dinode *dip;
register ino_t	ino;
{
	register unsigned short	mode;

	mode = dip->di_mode & IFMT;

	switch (mode) {
	case IFREG:
		setflags(ino, IREG);
		return;
	case IFDIR:
		setflags(ino, IDIR);
		return;
	case IFCHR:
		setflags(ino, ICHR);
		return;
	case IFBLK:
		setflags(ino, IBLK);
		return;
	case IFPIPE:
		setflags(ino, IPIPE);
		return;
	default:
		setflags(ino, UNKNOWN);
		break;
	}

	switch ( query("Unknown File Type i-number = %u (Clear)", ino) ){
	case NO:
		return;
	case YES:
		zeroinode(dip);
		setflags(ino, UNALLOC);
		clrflg = TRUE;
		break;
	}
}

/*
 *	Zero the given inode
 */

zeroinode(dip)
struct dinode *dip;
{
	register char *ptr;
	register struct dinode *next;

	lostsize += dip->di_size;
	next = dip+1;
	ptr = (char *) dip;

	while (ptr < next)
		*ptr++ = 0;

}

/*
 *	Check the blocks associated with the given inode to determine
 *	if any are bad or duplicate
 */

checkblks(dip, ino)
struct dinode *dip;
ino_t	ino;
{
	daddr_t	addrs[NADDR];
	register daddr_t bn;
	register int i, lev;
	register int mode;

	mode = dip->di_mode & IFMT;

	if ( (mode != IFREG) && (mode != IFDIR) )
		return(STOP);

	l3tol(addrs, dip->di_addr, NADDR);

	numbad = 			/* number of bad blocks so far */
	numdup = 			/* num dup blocks so far THIS INODE */
	numblks =			/* num used data blocks for size chk */
	sparsecnt = 0;			/* count of missed data blocks	*/

	for(i=0; i<NADDR; i++)
		for (lev=0; lev<4; lev++) 
			if (i < offsets[lev]) {
				if ( (bn=addrs[i]) != 0 ) {
					if (doblocks(bn, ino, lev) != OK)
						return(STOP);
				} else
					sparsecnt += blockcnt[lev];
				break;
			}
	return(OK);
}

/*
 *	Checks recursively the blocks pointed at via
 *	the inode list of blocks.  'bn' is the block number,
 *	'ino' is the inode referencing it, and 'lev' is the
 *	level 0 == direct ... 3 = triple-indirect
 */

doblocks(bn, ino, lev)
register daddr_t bn;
ino_t	ino;
int	lev;
{
	char buf[BSIZE];
	register daddr_t *bnptr;
	register char *end;
	register int flag;

	if (lev-- == 0)	{		/* we have a direct block */
		numblks += sparsecnt + 1;
		sparsecnt = 0;
		return(dodirect(bn, ino));
	} else {
		end = &buf[BSIZE];
		if ( (flag=dodirect(bn, ino)) == OK ) {
			bread(bn, buf);
			bnptr = (long *) buf;
			while ( bnptr < end ) {
				bn = *bnptr++;
				candaddr(bn);
				if ( bn == 0 ) {
					sparsecnt += blockcnt[lev];
					continue;
				}
				if ( doblocks(bn, ino, lev) == STOP )
					return(STOP);
			}
			return(OK);
		} else 
			return(flag);
	}
}
			
/*
 *	Check the given block to determine if it is bad
 * 	or if it is a duplicate.  'ino' is the inode referencing it
 */

dodirect(bn, ino)
register daddr_t bn;
register ino_t ino;
{
	register int flag;
	
	if ( (flag=checkbad(bn, ino)) == OK ) 
		return( checkdup(bn, ino) );
	else
		return(flag);
}

/*
 *	Check the given block number for being bad.
 */

checkbad(bn, ino)
register daddr_t bn;
ino_t	ino;
{
	if ( (bn>=isize) && (bn<fsize) )
		return(OK);

	else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
							/* bad block is in  */
		totfree++;				/* the inode blocks */
		return(OK);
	}
		
	if (!fflag)
		orflags(ino, IBAD_IDUP);

	printf("Bad block %U, i-number = %u\n", bn, ino);

	if (numbad++ < MAXBADOK)
		return(BAD_DUP);

	switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
	case NO:
		abort();
	case YES:
		return(STOP);
	}
}


/*
 *	Check the given block number for duplicate reference.
 */

checkdup(bn, ino)
register daddr_t bn;
ino_t	ino;
{
	if ( !testblock(bn) ) {
		markblock(bn);
		totfree--;
		return(OK);
	}

	dupflag = TRUE;
	if (!fflag)
		orflags(ino, IBAD_IDUP);
	printf("Dup Block %U, i-number = %u\n", bn, ino);

	if (totdups < DUPTBLSIZE) 
		dupblck[totdups++] = bn;
	else {
		switch ( query("DUP Table Overflow (Continue)") ) {
		case NO:
			abort();
		case YES:
			return(BAD_DUP);
		}
	}

	if (numdup++ < MAXDUPOK)
		return(BAD_DUP);

	switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
	case NO:
		abort();
	case YES:
		return(STOP);
	}
}

/*
 *	Check For Possible File Size Error 
 */

checksize(dip, ino)
register struct dinode *dip;
ino_t	ino;
{
	register int mode;
	register fsize_t size;

	mode = dip->di_mode & IFMT;
	size = dip->di_size;
	
	if ( mode == IFREG )
		filesize(ino, size);
	else	/* mode == IFDIR */
		dirsize(dip, ino, size);
}

dirsize(dip, ino, size)
struct dinode *dip;
ino_t ino;
register fsize_t size;
{
	if ( size <= 0 ) {
		switch ( query("\
Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
		case NO:
			break;
		case YES:
			zeroinode(dip);
			setflags(ino, UNALLOC);
			clrflg = TRUE;
			return;
		}
	}

	if ( size < (2*DSIZE) )
		printf("Directory Size too small i-number = %u\n", ino);

	if ( size % sizeof(struct direct) != 0 )
		printf("Directory Misaligned i-number = %u\n", ino);

	if (sizerr(size))
		printf("Possible Directory Size Error i-number = %u\n", ino);
}

filesize(ino, size)
ino_t ino;
register fsize_t size;
{
	if (sizerr(size))
		printf("Possible File Size Error i-number = %u\n", ino);
}

sizerr(size)
register fsize_t size;
{
	register fsize_t calc;

	calc = (unsigned long)numblks*BSIZE;
	if ( (size > calc) || ( calc >= (size+BSIZE) ) ) 
		return(TRUE);
	else
		return(FALSE);
}
f ( size % sizeof(struct direct) != 0 )
		printf("Directory Misaligned i-number = %u\n", ino);

	if (sizerr(size))
		printf("Possible Directory Size Error i-number = %u\n", ino);
}

filesize(ino, size)
ino_t ino;
register fsize_t size;
{
	if (sizerr(size))
		printf("Possible File Size Error i-number = %u\n", ino);
}

sizerr(size)
register fsize_t size;
{
	register fsize_t calc;

	calc = (unsigned long)numblks*BSIZE;
	if ( (size > calc) || ( calc >= (size+BSIZE) ) ) 
		return(TRUE);
	else
		return(FALSE)fsck/phase1b.c   644      3      3        4361  4664524116   6444 /*
 *	Phase 1b of fsck - Rescan for more Dups
 */

#include "fsck.h"

extern int	numdup;		/* declared in phase1.c */

phase1b()
{
	if (!qflag)
		printf("Phase 1b: Rescan for more Dups\n");
	buildtable();
	iscanb();
}

buildtable()
{
	unsigned cntr=0, numdiff=0;
	daddr_t bn;

	while (cntr<totdups) {
		bn = dupblck[cntr++];
		if (!testdup(bn)) {
			markdup(bn);
			numdiff++;
		}
	}
	totdups = numdiff;
}

iscanb()
{
	register daddr_t bn;
	register struct dinode *dip;
	register ino_t	ino;
	int i;

	ino = 1;

	for (bn=INODEI; bn<isize; bn++) {
		if (testblock(bn)) {		/* block is bad via inode 1 */
			ino += INOPB;
			continue;
		}
		bread(bn, databuf);
		dip = (struct dinode *) databuf;
		for (i=0; i<INOPB; i++) {
			candino(dip);
			if (inuse(dip) == TRUE) 
				ckblksb(dip, ino);
			if (totdups == 0)
				return;			
			ino++;
			dip++;
		}
	}
}

/*
 *	Check the blocks associated with the given inode to find the
 *	remaining duplicate blocks
 */

ckblksb(dip, ino)
register struct dinode *dip;
register ino_t	ino;
{
	daddr_t	addrs[NADDR];
	int i, lev;
	int mode;

	mode = dip->di_mode & IFMT;

	if ( (mode != IFREG) && (mode != IFDIR) )
		return;

	l3tol(addrs, dip->di_addr, NADDR);

	numdup = 0;			/* num dup blocks so far THIS INODE */

	for(i=0; i<NADDR; i++)
		for (lev=0; lev<4; lev++) 
			if (i < offsets[lev]) {
				dblocksb(addrs[i], ino, lev);
				break;
			}
}

/*
 *	Checks recursively the blocks pointed at via
 *	the inode list of blocks.  'bn' is the block number,
 *	'ino' is the inode referencing it, and 'lev' is the
 *	level 0 == direct ... 3 = triple-indirect
 */

dblocksb(bn, ino, lev)
daddr_t	bn;
ino_t	ino;
int	lev;
{
	char buf[BSIZE];
	int  i;
	daddr_t	*bnptr;

	if (bn == 0)
		return(OK);
		
	switch ( cdupb(bn, ino) ) {
	case OK:
		if (lev--==0)
			return(OK);
		bread(bn, buf);
		bnptr = (long *) buf;
		for (i=0; i<NBN; i++) {
			bn = bnptr[i];
			candaddr(bn);
			if ( dblocksb(bn, ino, lev) == STOP )
				return(STOP);
		}
		return(OK);
	case STOP:
		return(STOP);
	}
}

/*
 *	Check the given block number for duplicate reference.
 */

cdupb(bn, ino)
daddr_t	bn;
ino_t	ino;
{
	if ( !testdup(bn) ) 
		return(OK);

	totdups--;
	unmarkdup(bn);
	if (!fflag)
		orflags(ino, IBAD_IDUP);
	printf("Dup Block %U, i-number = %u\n", bn, ino);

	return(STOP);
}
=0)
			return(OK);
		bread(bn, buf);
		bnptr = (long *) buf;
		for (i=0; i<NBN; i++) {
			bn = bnptr[i];
			candaddr(bn);
			if ( dblocksb(bn, ino, lev) == STOP )
				return(STOP);
		}
		return(OK);
	case STOP:
		return(STOP);
	}
}

/*
 *	Check the given block number forfsck/phase2.c   644      3      3       17061  4767515401   6325 /*
 *	phase 2 of fsck - Check Pathnames
 */

#include "fsck.h"
#include <pwd.h>

#define MAXDEPTH 50
struct	direct *path[MAXDEPTH];
int 	depth;
int 	fixflag;			/* flags when must rewrite databuf  */
daddr_t blocknum;			/* Current block num read in        */

typedef struct list {
	struct direct d_entry;
	struct list *next;
} list;

char	buf2[BSIZE];			/* buffer for blocks		*/
daddr_t	cdbn;				/* current logical block number */

/*	Format errors, args to blkerr() */

#define	NULLNAME	5
#define	NULLPAD		6
#define SLASHES		7
#define DOT		8
#define DOTDOT		9

phase2()
{
	if (!qflag)
		printf("Phase 2 : Check Pathnames\n");
	checkroot();
	depth = 0;
	checkpath(ROOTIN);
}


checkroot()
{
	if ( (flags(ROOTIN)&MODEMASK) == UNALLOC )
		fatal("Root i-node is unallocated.  Terminating");

	if ( (flags(ROOTIN)&MODEMASK) != IDIR ) {
		switch ( query("Root i-node is not a directory (FIX)") ){
		case YES:
			fixroot();
			break;
		case NO:
			abort();
		}
	}
	
	if ( badblks(ROOTIN) ){
		switch ( query("Dup/Bad blocks in root i-node (Continue)") ) {
		case YES:
			break;
		case NO:
			abort();
		}
	}
	linkincr(ROOTIN);		/* (?) Feature (?) of mkfs is  */
					/* that root inode of a file   */
					/* system has a link count one */
					/* too large.		       */
}

fixroot()
{
	register struct dinode *dip;

	if (!writeflg) 
		fatal("File System Read-Only (NO WRITE)\n");

	setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR);

	/* Save change to disk */
	
	dip = ptrino(ROOTIN, databuf);
	dip->di_mode &= (~IFMT);
	dip->di_mode |= IFDIR;
	writeino(ROOTIN, databuf);
}

#define	myinum	( (depth>0) ? path[depth-1]->d_ino : ROOTIN )
#define popinum	( (depth>1) ? path[depth-2]->d_ino : ROOTIN )

char *memory = "Can't malloc memory, phase 2";

list *
procfiles(addrs, length)
daddr_t *addrs;
fsize_t length;
{
	register struct direct *elemnt;
	register list *first, *ptr;

	if ((first=ptr=(list *)malloc(sizeof(list)))==NULL)
		fatal(memory);
	first->d_entry.d_ino = 0;
	first->next = NULL;
	if ( length < DSIZE )
		return( first );
	cdbn = 0;
	nextblock(addrs);
	fixflag = FALSE;
	elemnt = (struct direct *) databuf;
	cdots(elemnt++, ".", myinum, DOT);
	++numfiles;
	if ( (length-=DSIZE) < DSIZE )
		return( first );
	cdots(elemnt++, "..", popinum, DOTDOT);
	++numfiles;
	length -= DSIZE;

	while ( length >= DSIZE ) {
		while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if (chck(elemnt)==IDIR) {
				copy(elemnt, &ptr->d_entry, 
						sizeof(struct direct));
				if ((ptr->next=(list *)malloc(sizeof(list))) ==
					NULL)
					fatal(memory);
				ptr = ptr->next;
				ptr->d_entry.d_ino = 0;
				ptr->next = NULL;
			}
			elemnt++;
			length -= DSIZE;
		}
		if (fixflag && (fixblock(addrs) == NUL) )
			fixblkerr();
		nextblock(addrs);
		fixflag = FALSE;
		elemnt = (struct direct *) databuf;
	}
	return(first);	 
}

candblock(dptr)
register struct direct *dptr;
{
	register int num, i;

	num = BSIZE/sizeof(struct direct);
	for (i=0; i<num; i++)
		canino(dptr[i].d_ino);
}

nextblock(addrs)
register daddr_t *addrs;
{
	register daddr_t bn;

	if ( (bn=imap(addrs, cdbn++)) == 0 ) {
		bclear(databuf, BSIZE);
		return;
	}
	bread(bn, databuf);
	candblock(databuf);
	blocknum = bn;
}

fixblock(addrs)
daddr_t *addrs;
{
	daddr_t bn;

	if ( (bn=imap(addrs, cdbn-1)) == 0 ) 
		return(NUL);
	candblock(databuf);
	bwrite(bn, databuf);
	return(TRUE);
}

fixblkerr()
{
	fatal("Fixblock error.");
}

copy(from, to, size)
register char *from, *to;
register int size;
{
	while (size--)
		*to++=*from++;
}

cdots(elemnt, dots, ino, type)
register struct direct *elemnt;
char *dots;
ino_t ino;	/* what the inode number should be */
int type;
{
	register char *name = elemnt->d_name;
	register ino_t inum;

	inum = elemnt->d_ino;
	if ( (strcmp(name, dots) != 0) || (inum != ino) ||
		(format(name) != GOOD) ) {
		blkerr(type);
		return;
	}
	linkincr(inum);
}

format(name)
register char *name;
{
	register char *ptr=name;
	register char *end=&name[DIRSIZ];

	while ( (ptr<end) && (*ptr++ != '\0') ) ;

	if ( (ptr-1) == name )
		return(NULLNAME);
	
	if (ptr<end) {
		while ( (ptr<end) && (*ptr++ == '\0') ) ;
		if (ptr!=end)
			return(NULLPAD);
	}

	ptr = name;
	while (ptr < end) 
		if (*ptr++ == '/')
			return(SLASHES);

	return(GOOD);
}

	
blkerr(type)
int type;
{	
	char *errname;

	switch(type) {
	case NULLNAME:
		errname = "Null name";
		break;
	case NULLPAD:
		errname = "Non null padded";
		break;
	case SLASHES:
		errname = "Embedded slashes in";
		break;
	case DOT:
		errname = "Inconsistent .";
		break;
	case DOTDOT:
		errname = "Inconsistent ..";
		break;
	default:
		errname = "Bad";
		break;
	}

	printf("%s entry in block %U in directory\n", errname, blocknum);
	pinfo(myinum);
	pname(path[--depth]->d_name);
	depth++;
}

chck(elemnt)
register struct direct *elemnt;
{
	register ino_t inum;
	register char *name;
	int type;

	inum = elemnt->d_ino;
	if ( inum == 0 )
		return(UNALLOC);

	name = elemnt->d_name;
	if ( (type=format(name)) != GOOD )
		blkerr(type);

	if (inum>ninodes) {
		if ( irange(inum, name) ) 
			zeroent(elemnt);
		return(UNALLOC);
	}

	if ( (flags(inum)&ALLOCMASK)==UNALLOC ) {
		if ( unalloc(inum, name) )
			zeroent(elemnt);
		return(UNALLOC);
	}

	if ( badblks(inum) ) {
		if ( baddup(inum, name) ) {
			zeroent(elemnt);
			return(UNALLOC);
		}
		if ( (flags(inum)&MODEMASK)==IDIR )
			return(UNALLOC);
	}

	linkincr(inum);
	numfiles++;
	return( flags(inum)&MODEMASK );
}

zeroent(elemnt)
struct direct *elemnt;
{
	elemnt->d_ino = 0;
	fixflag = TRUE;
}

pname(name)
char *name;
{
	int i=0;

	while (i<depth) 
		prdirsize(path[i++]->d_name);
	prdirsize(name);
	putchar('\n');
}

prdirsize(name)
char *name;
{
	if (name[DIRSIZ-1] == '\0')
		printf("/%s", name);
	else
		printf("/%*s", DIRSIZ, name);
}

fsize_t
pinfo(inum)
ino_t inum;
{
	register struct dinode *dip;
	register struct passwd *pwd;

	if ( (dip=ptrino(inum, buf2)) == NULL ) {
		printf("i-number = %u is in a bad inode block.\n", inum);
		return(0);
	}

	printf("i-number = %u, ", inum);
	if ( (pwd=getpwuid(dip->di_uid)) != NULL )
		printf("Owner=%s, ", pwd->pw_name);
	else
		printf("Owner=%u, ", dip->di_uid);
	printf(" Mode=0%o\n", dip->di_mode);
	printf("Size=%U, Mtime=%s", dip->di_size, ctime(&dip->di_mtime));
	return(dip->di_size);
}

char *remove = "(Remove)";

irange(inum, name)
ino_t inum;
char *name;
{
	printf("I-number is out of range  I=%u\n", inum);
	pname(name);
	return(action(remove));
}

unalloc(inum, name)
ino_t inum;
char *name;
{	
	fsize_t size;

	printf("Unallocated\n");
	size = pinfo(inum);
	pname(name);
	if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) {
		printf("%s [Forced - Yes]\n", remove);
		return(YES);
	}
	return(action(remove));
}

baddup(inum, name)
ino_t inum;
char *name;
{
	register int mode = flags(inum)&MODEMASK;

	printf("Bad or Dup blocks in %s\n",(mode==IDIR) ? "Directory" : "File");
	pinfo(inum);
	pname(name);
	return(action(remove));
}

checkpath(ino)
register ino_t ino;
{
	static daddr_t	addrs[NADDR];
	static struct dinode *dip;
	static list *temp;
	register list *ptr;

	if ( (flags(ino)&VISITED)==VISITED ) {
		circle(ino);
		return;
	} else
		orflags(ino, VISITED);

	dip = ptrino(ino, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	
	if ( (dip->di_mode&IFMT) != IFDIR )
		fatal("Tried to checkpath i-node %u which is not dir.\n", ino);

	ptr = procfiles(addrs, dip->di_size);

	while (ptr->d_entry.d_ino) {
		if (depth >= MAXDEPTH)
			toolong();
		path[depth++] = &ptr->d_entry;
		checkpath(ptr->d_entry.d_ino);
		depth--;
		temp = ptr;
		ptr = ptr->next;
		free(temp);
	}
	free(ptr);
}

circle(ino)
ino_t ino;
{
	printf("I-node %u is a multiply referenced directory i-node.\n", ino);
}

toolong()
{
	printf("Name too long.\n");
	pname("\0");
	abort();
}

	
i_mode&IFMT) != IFDIR )
		fatal("Tried to checkpath i-node %u which is not dir.\n", ino);

	ptr = procfiles(addrs, dip->di_size);

	while (ptr->d_entry.d_ino) {
		if (depth >= MAXDEPTH)
			toolong();
		path[depth++] = &ptr->d_entry;
		checkpath(ptr->d_entry.d_ino);
		depth--;
		temp = ptr;
		ptr = ptr->next;
		free(temp);
	}
	free(ptr);
}

circle(ino)
ino_t ino;
{
	printf("I-node %u is a multiply referenced directory i-node.\n", ino);
}

toolong()
{
	printf("fsck/phase3.c   644      3      3       12066  5050254732   6317 /*
 *	phase 3 of fsck - Check Connectivity
 */

#include "fsck.h"

char *lostname = "lost+found";

phase3()
{
	ino_t i;

	if (!qflag)
		printf("Phase 3 : Check Connectivity\n");
	for (i=FIRSTIN; i<=ninodes; i++) 
		if ( ((flags(i)&MODEMASK) == IDIR) &&
		     (linkctr(i) == 0) ) {
			orflags(i, UNREFDIR);
			markchildren(i);
		}

	for (i=FIRSTIN; i<ninodes; i++)
		if ( (flags(i)&(UNREFDIR|CHILDDIR)) == UNREFDIR )
			unrefdir(i);
}

markchildren(ino)
ino_t ino;
{
	struct dinode *dip;
	struct direct *element;
	daddr_t	addrs[NADDR];
	ino_t inumber;
	fsize_t length;

	if ( badblks(ino) )
		return;
	dip = ptrino(ino, databuf);
	if ( (length=dip->di_size) <= 0 )
		return;
	l3tol(addrs, dip->di_addr, NADDR);
	cdbn = 0;
	nextblock(addrs);
	element = (struct direct *) databuf;
	element += 2;		/* skip over . and .. entries */
	if ( (length-=2*DSIZE) <= 0 )
		return;

	while ( length >= DSIZE ) {
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( ((inumber=element->d_ino) != 0) &&
			     ((flags(inumber)&MODEMASK)==IDIR) &&
			     (inumber!=ino) )
				orflags(inumber, CHILDDIR);
			element++;
			length -= DSIZE;
		}
		nextblock(addrs);
		element = (struct direct *) databuf;
	}
}

char *reconnect = "(Reconnect)";

unrefdir(ino)
ino_t ino;
{
	printf("Unref Dir\n");
	if( (pinfo(ino) == 0) || (daction == NO) || (mounted == TRUE) ) {
		if ( action(reconnect) == FALSE )
			return;
	} else 
		printf("%s FORCED\n", reconnect);

	connect(ino, IDIR);
}

#define CONNECT		1
#define NOCONNECT	0

connect(ino, type)
ino_t ino;
int type;
{
	ino_t lostino;
	struct dinode *dip;
	daddr_t addrs[NADDR];
	fsize_t length;
	struct direct *element;
	int chgino = FALSE;

	if ( ((lostino=lostfound()) == NUL) ||
		 ((flags(lostino)&MODEMASK) != IDIR) ||
			( badblks(lostino) ) ) {
		nolost();
		if (type==IDIR)
			traverse(NOCONNECT, ino, lostino);
		return(FAILURE);
	}

	dip = ptrino(lostino, buf2);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length>=DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( element<&databuf[BSIZE] ) {
			length -= DSIZE;
			if ( element->d_ino == 0 ) {
				element->d_ino = ino;
				strncpy(element->d_name, nameit(ino), DIRSIZ);
				if ( fixblock(addrs) == NUL )
					fixblkerr();
				linkincr(ino);
				numfiles++;
				if ( length<0 ) {
					dip->di_size -= length;
					chgino = TRUE;
				}
				if ( (type == IDIR) &&
				     (connected(ino, lostino)==YES) ) {
					dip->di_nlink++;
					writeino(lostino, buf2);
					traverse(CONNECT, ino, lostino);
				} else if (chgino) {
					writeino(lostino, buf2);
				}
				return(SUCCESS);
			}
			element++;
		}
	}
	
	noroom();
	if (type == IDIR)
		traverse(NOCONNECT, ino, lostino);
	return(FAILURE);
}

traverse(flag, ino, lostino)
int flag;
ino_t ino, lostino;
{
	struct direct dirlost, nothing, newtree;

	dirinit(&dirlost, lostino, lostname);
	dirinit(&nothing, 0, "??");
	dirinit(&newtree, ino, nameit(ino));
	depth = 0;
	if (flag == CONNECT) 
		path[depth++] = &dirlost;
	else
		path[depth++] = &nothing;

	path[depth++] = &newtree;
	checkpath(ino);
}

dirinit(element, ino, name)
struct direct *element;
ino_t ino;
char *name;
{
	element->d_ino = ino;
	strncpy(element->d_name, name, DIRSIZ);
}

connected(ino, lostino)
ino_t ino;		/* inumber just reconnected	  */
ino_t lostino;		/* inumber of lostfound directory */
{
	struct dinode *dip;
	daddr_t addrs[NADDR];
	fsize_t length;
	struct direct *element;

	if ( badblks(ino) ) {
		badconnect(ino);
		return(NO);
	}
	dip = ptrino(ino, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length >= DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( strcmp(element->d_name, "..") == 0 ) {
				printf("Dir i-number = %u connected.  ", ino);
				printf("Parent was i-number = %u.\n",
							element->d_ino);
				element->d_ino = lostino;
				if ( fixblock(addrs) == NUL )
					fixblkerr();
				return(YES);
			}
			length -= DSIZE;
			element++;
		}
	}
	noparent(ino);
	return(NO);
}

badconnect(ino)
ino_t ino;
{
	printf("Dir i-number = %u connected.  It has bad/dup blocks.\n", ino);
}

noparent(ino)
ino_t ino;
{
	printf("Dir i-number = %u connected.  It has no .. entry.\n", ino);
}

ino_t
lostfound()
{
	static daddr_t addrs[NADDR];
	struct dinode *dip;
	struct direct *element;
	fsize_t length;

	dip = ptrino(ROOTIN, databuf);
	l3tol(addrs, dip->di_addr, NADDR);
	length = dip->di_size;
	cdbn = 0;
	while ( length>=DSIZE ) {
		nextblock(addrs);
		element = (struct direct *) databuf;
		while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
			if ( strcmp(element->d_name, lostname) == 0 ) 
				return(element->d_ino);
			length -= DSIZE;
			element++;
		}
	}

	return(NUL);
}

nolost()
{
	printf("Sorry.  No %s directory.\n", lostname);

}

noroom()
{
	printf("Sorry.  No space in %s directory.\n", lostname);
}

char namebuf[DIRSIZ];

char *
nameit(ino)
register ino_t ino;
{
	register int i = DIRSIZ-1;

	namebuf[i] = '\0';
	while ( (ino != 0) && (i>0) ) {
		namebuf[--i] = '0' + ino%10;
		ino = ino/10;
	}
	return(&namebuf[i]);
}
length>=DSIZE) ) {
			if ( strcmp(element->d_name, lostname) == 0 ) 
				return(element->d_ino);
			length -= DSIZE;
			element++;
		}
	}

	return(NUL);
}

nolost()
{
	printf("Sorry.  No %s directory.\n", lostname);

}

noroom()
{
	printf("Sorry.  No space in %s directory.\n", lostname);
}

char namebuf[DIRSIZ];

char *
nameit(ino)
register ino_t ino;
{
	register int i = DIRSIZ-1;

	namebuf[i] = '\0';
	while ( (ino != 0) && (i>0) ) {
		namebuf[--i] = '0'fsck/phase4.c   644      3      3       10602  4767744166   6335 /*
 *	phase 4 of fsck - Check Reference Counts
 */

#include "fsck.h"

extern char *reconnect;
fsize_t	lostsize;

phase4()
{
	ino_t i;
	short actlink;

	if (!qflag)
		printf("Phase 4 : Check Reference Counts\n");
	for (i=FIRSTIN; i<=ninodes; i++) {
		if ( badblks(i) )
			if ( bddp(i) == YES )
				continue;	/* inode zeroed */

		if ( (linkctr(i) == 0) &&
		     ((flags(i)&MODEMASK) != IDIR) &&
		     ((flags(i)&ALLOCMASK) != UNALLOC) )
			if ( unreflink(i) == YES )
				continue;	/* inode zeroed */

		if ( (linkctr(i) == 0) &&
		     ((flags(i)&ALLOCMASK) != UNALLOC)  )
			if ( unrefclr(i) == YES )
				continue;	/* inode zeroed */

		if ( (actlink=getlink(i)) == (-1) ) {
			i += INOPB-1;
			continue;		/* bad inode block */
		}

		if ( actlink != linkctr(i) )
			linkprob(i, actlink);	/* fix link count */
	}

	freeilist();
}

short
getlink(inum)
register ino_t inum;
{
	register unsigned offset;
	static ibuf[BSIZE];
	register struct dinode *dip;
	register daddr_t bn;

	offset = iblocko(inum);
	if ( (offset==0) || (inum==FIRSTIN) ) {
		bn = iblockn(inum);
		if ( (testblock(bn)) && (inum!=FIRSTIN) ) 
			return(-1);
		bread(bn, ibuf);
	}
	dip = ((struct dinode *) ibuf) + offset;
	candino(dip);
	return(dip->di_nlink);
}

char *clearit = "(Clear i-node)";

unreflink(ino)
ino_t ino;
{
	fsize_t size;

	if ( (qflag == TRUE) && ((flags(ino)&MODEMASK) == IPIPE) ) {
		doclear(ino);
		return(YES);
	}

	printf("Unref %s\n", typename(ino));
	size = pinfo(ino);
	if ( (daction != NO) && (size == 0) && (mounted == FALSE) 
		&& ((flags(ino)&MODEMASK) == IREG) ) {
		printf("%s [Forced - Yes]\n", clearit);
		doclear(ino);
		return(YES);
	}
	if ( action(reconnect) == TRUE )
		if( connect(ino, IREG) == FAILURE )  /* connect back in the */
			return(askclear(ino));	     /* non dir inode	    */
			
	return(NO);
}

askclear(ino)
ino_t ino;
{
	if ( action(clearit) == TRUE ) {
		doclear(ino);
		return(YES);
	}
	return(NO);
}

doclear(ino)
ino_t ino;
{
	struct dinode *dip;

	dip = ptrino(ino, databuf);
	zeroinode(dip);
	writeino(ino, databuf);
	setflags(ino, UNALLOC);
	setlinkctr(ino, 0);
}

char *adjust = "(Adjust)";

linkprob(ino, actlink)
ino_t ino;
short actlink;
{
	printf("Link Count discrepancy in %s\n", typename(ino));
	pinfo(ino);
	printf("Count = %u, should be %u ", actlink, linkctr(ino));
	if ( action(adjust) == TRUE )
		chglink(ino);
}

chglink(ino)
ino_t ino;
{
	struct dinode *dip;

	dip = ptrino(ino, databuf);
	dip->di_nlink = linkctr(ino);
	writeino(ino, databuf);
}
	
unrefclr(ino)
ino_t ino;
{
	printf("Unref %s\n", typename(ino));
	pinfo(ino);
	return(askclear(ino));
}

bddp(ino)
ino_t ino;
{
	printf("Bad/Dup blocks in %s\n", typename(ino));
	pinfo(ino);
	return(askclear(ino));
}

char *fixit = "(FIX)";

freeilist()
{
	ino_t i, count=0;
	daddr_t bn;

	for (i=FIRSTIN; i<=ninodes; i++)
		if ( (flags(i)&ALLOCMASK) == UNALLOC )
			count++;

	for (bn=INODEI+1; bn<isize; bn++)	/* block # INODEI can't */
		if ( testblock(bn) )		/* be bad since ROOTIN  */
			count -= INOPB;		/* is in it, otherwise  */
						/* big time bad news.	*/
	if ( sbp->s_tinode != count ) 
		if ( (qflag==FALSE) && (daction!=NO) ) {
			printf("Free i-node count wrong in superblock.  ");
			if ( action(fixit) == TRUE ) {
				sbp->s_tinode = count;
				sbpfix = TRUE;
			}
		} else {
			sbp->s_tinode = count;
			sbpfix = TRUE;
		}

	if ( (daction!=NO) &&
	     ( (sflag==TRUE) || (sbpfix==TRUE) || (badilist()==BAD) ) )
	 	rebuild();

}

badilist()
{
	ino_t i, inum;
	unsigned numfree;
	daddr_t bn;

	if ( (numfree=(unsigned) sbp->s_ninode) > NICINOD )
		return(BAD);
	for (i=0; i<numfree; i++) {
		inum = sbp->s_inode[i];
		bn = iblockn(inum);
		if ( (testblock(bn)) && (bn!=INODEI) )
			return(BAD);
		if ( (inum < FIRSTIN) || (inum > ninodes) )
			return(BAD);
		if ( (flags(inum)&ALLOCMASK) != UNALLOC ) 
			return(BAD);
		if ( flags(inum)&IFREELIST )
			return(BAD);		/* dup in ifree list */
		orflags(inum, IFREELIST);
	}
	return(GOOD);
}

rebuild()
{
	daddr_t bn;
	ino_t i;
	int index;

	sbpfix = TRUE;
	for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) {
		if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
			bn = iblockn(i);
			if ( (!testblock(bn)) || (bn==INODEI) )
				index++;
		}
	}
	sbp->s_ninode = index;
	for (i=FIRSTIN; (i<=ninodes) && (index>0); i++) {
		if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
			bn = iblockn(i);
			if ( (!testblock(bn)) || (bn==INODEI) )
				sbp->s_inode[--index] = i;
		}
	}
	printf("Free i-node list in superblock rebuilt.\n");
}
t bn;
	ino_t i;
	int index;

	sbpfix = TRUE;
	for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) {
		if ( (flags(ifsck/phase5.c   644      3      3        6203  4767744635   6321 /*
 *	phase 5 of fsck - Check Free List
 */

#include "fsck.h"

daddr_t	badcnt;			/* Number of bad blocks in free list */
daddr_t dupcnt;			/* Number of dup blocks in free list */
int	badflag;		/* Bad free list flag */
int 	fixerup;		/* Flag to salvage free list */

phase5()
{
	struct fblk *fbp;
	unsigned size;
	
	if (!qflag)
		printf("Phase 5 : Check Free List\n");
	fbp = (struct fblk *) &sbp->s_nfree;
	size = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
	copyV(size);
	badcnt = dupcnt = 0;
	badflag = FALSE;
	freetrav(fbp);
	fixerup = FALSE;
	if (badflag || sflag) 
		asksalvage();
}


#define	IGNORE	3		/* Return Possibilities from chk() */
#define	ABORT	4		/* as well as perhaps GOOD and BAD */

freetrav(fbp)
struct fblk *fbp;
{
	daddr_t total=0;
	int i, flag;

	while ( fbp->df_nfree != 0 ) {
		if ( (unsigned) fbp->df_nfree > NICFREE ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
		for (i=1; i<fbp->df_nfree; i++) {
			if ( (flag=chk(fbp->df_free[i])) == GOOD ) {
				total++;
				continue;
			}
			if (flag == BAD)
				continue;
			break;		/* break for IGNORE or ABORT	*/
		}
		if ( (flag == IGNORE) || (flag == ABORT) )
			break;
		if ( chk(fbp->df_free[0]) != GOOD )
			break;
		total++;
		bread(fbp->df_free[0], databuf);
		fbp = (struct fblk *) databuf;
		if ( !canfblk(fbp) ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
	}

#if 0
	printf("Total traversed free blocks     = %U\n", total);	 
	printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);	 
	printf("Running total free blocks       = %U\n", totfree);	 
#endif

	if ( flag == ABORT ) { 		/* To Terminate fsck on this 	*/
		badflag = FALSE;	/* File System, because of	*/
		return;			/* excessive dup or bad blocks	*/
	}

	if ( sbp->s_tfree != totfree )
		if ( (qflag==FALSE) && (daction!=NO) ) {
			printf("Free Block count wrong in superblock.  ");
			if ( action(fixit) == TRUE ) {
				sbp->s_tfree = totfree;
				sbpfix = TRUE;
			}
		} else {
			sbp->s_tfree = totfree;
			sbpfix = TRUE;
		}

	report("%U Bad Block%s in Free List\n", badcnt);
	report("%U Dup Block%s in Free List\n", dupcnt);
	report("%U Block%s missing\n", totfree - total);

}

report(message, num)
char *message;
daddr_t num;
{
	if ( num != 0 ) {
		printf(message, num, ( (num>1) ? "s" : "" ) );
		badflag = TRUE;
	}
}

chk(bn)
register daddr_t bn;
{
	if ( (bn<isize) || (bn>=fsize) ) {
		badflag = TRUE;
		if (++badcnt > MAXBADFREE) 
			return( stopit("bad") );
		return(BAD);
	}

	if ( testdup(bn) ) {
		badflag = TRUE;
		if (++dupcnt > MAXDUPFREE)
			return( stopit("dup") );
		return(BAD);
	} else {
		markdup(bn);
		return(GOOD);
	}
}
			
stopit(type)
char *type;
{
	printf("Excessive %s blocks in free list ", type);
	if ( query("(Continue)") == YES )
		return(IGNORE);
	else
		return(ABORT);
}
		
		
canfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	canshort(fbp->df_nfree);
	if ( (unsigned) fbp->df_nfree > NICFREE )
		return(FALSE);

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	return(TRUE);
}

asksalvage()
{
	if ( (daction!=NO) && (qflag || sflag) ) {
		fixerup = TRUE;
		return;
	}
	if ( action("Bad Free List (SALVAGE)") )
		fixerup = TRUE;
}
tf("Excessive %s blocks in free list ", type);
	if ( query("(Continue)") == YES )
		return(IGNORE);
	else
		return(ABORT);
}
		
		
canfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	canshort(fbp->df_nfree);
	if ( (unsigned) fbp->df_nfree > NICFREE )
		return(FALSE);

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	return(TRUE);
}

asksalvage()
{
	if ( fsck/phase6.c   644      3      3        4752  4767014240   6307 /*
 *	phase 6 of fsck - Salvage Free List
 */

#include "fsck.h"

static	unsigned char *maptab;	/* table of interleave offsets	*/
static	daddr_t	mapbot;		/* minimum block number to interleave map */
static	daddr_t	maptop;		/* maximum block number to interleave map */
static	short	m,n;		/* interleave factors	*/
#define	DEF_N	1		/* default values 	*/
#define	DEF_M	1		
daddr_t	freeblks;		/* number free blocks left to write out */
daddr_t	blknm;			/* current block number we are working with */
struct	fblk *fblkp;		/* pointer to free block list */
daddr_t	*dp;			/* pointer to block entry in free list block */

phase6()
{
	if (!fixerup) {
		return;
	}

	if (!qflag)
		printf("Phase 6 : Salvage Free List\n");
	if ( maketable() == BAD )
		return;
	writefree();
	free(maptab);
}

maketable()
{
	register int i;
	register int ratio;

	m = sbp->s_m;
	n = sbp->s_n;

	if ( (n > MAXINTN) || (m > n) || (n%m != 0) ) {
		printf("Invalid interleave factors in superblock.\n");
		printf("Default free-block list spacing assumed.\n");
		sbp->s_n = n = DEF_N;
		sbp->s_m = m = DEF_M;
	}

	if ( (maptab = malloc(n)) == NULL ) {
		printf("Can't malloc space for interleave table.\n");
		printf("Free-block list is not rebuilt.\n");
		return(BAD);
	}

	mapbot = (isize + n - 1)/n*n;
	maptop = fsize/n*n;
	ratio = n/m;
	for (i=0; i<n; i++)
		maptab[i] = (i/ratio) + (i%ratio)*m;

	return(GOOD);
}

writefree()
{
	register daddr_t bn;
	daddr_t blk, bmap();
	short num;

	sbpfix = TRUE;
	freeblks = totfree;
	blknm = SUPERI;
	fblkp = (struct fblk *) &sbp->s_nfree;
	fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
	freeblks -= num;
	dp = &fblkp->df_free[num];
	for (bn=isize; bn<fsize; bn++) {
		blk = bmap(bn);
		if ( !testblock(blk) ) 
			if ( addfree(blk) == STOP )
				break;
	}
}

addfree(bn)
daddr_t bn;
{
	short num;

	*--dp = bn;
	if (dp > &fblkp->df_free[0])
		return(OK);

	if ( blknm != SUPERI ) {
		canwfblk(fblkp);
		bwrite(blknm, databuf);
	}

	bclear(databuf, BSIZE);
	if (freeblks == 0) {
		bwrite(bn, databuf);
		return(STOP);
	}
	blknm = bn;
	fblkp = (struct fblk *) databuf;
	fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
	freeblks -= num;
	dp = &fblkp->df_free[num];
	return(OK);
}

daddr_t
bmap(blk)
register daddr_t blk;
{
	short i;

	if ( (blk>=mapbot) && (blk<maptop) ) {
		i = blk%n;
		blk -= i;
		blk += maptab[i];
	}
	return(blk);
}

canwfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	canshort(fbp->df_nfree);
}
uf);
		return(STOP);
	fsck/printf.c   644      3      3        7271  4664524124   6425 /*
 * Standard output printf using putchar.
 * Non-portable things:
 * 1) alignment of arguments is assumed to be completely contiguous.
 * 2) the smallest number is assumed to negate to itself.
 * 3) All of long, int, char*, and double are assumed to
 *    be held in an exact number of ints.
 */

#define NULL ((char *)0)
#define putchar(c) { char b = c; write(1, &b, 1); }
#include <sys/mdata.h>

union	alltypes {
	char	c;
	int	i;
	unsigned u;
	long	l;
	double	d;
	char	*s;
};

#define	bump(p,s)	(p+=sizeof(s)/sizeof(int))

char	*printi();
char	*printl();

static	char	null[] = "{NULL}";

printf(args)
union alltypes args;
{
	xprintf(&args);
}
xprintf(argp)
union alltypes *argp;
{
	register char *cbp;
	int *iap;
	register c;
	char *s;
	char *cbs;
	char adj, pad;
	int prec;
	int fwidth;
	int pwidth;
	register char *fmt;
	union alltypes elem;
	char cbuf[64];

	iap = (int *)argp;
	fmt = *(char **)iap;
	bump(iap, char*);
	for (;;) {
		while((c = *fmt++) != '%') {
			if(c == '\0') {
				return;
			}
			putchar(c);
		}
		pad = ' ';
		fwidth = -1;
		prec = -1;
		c = *fmt++;
		if (c == '-') {
			adj = 1;
			c = *fmt++;
		} else
			adj = 0;
		if (c == '0') {
			pad = '0';
			c = *fmt++;
		}
		if (c == '*') {
			fwidth = *iap++;
			c = *fmt++;
		} else
			for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
				fwidth = fwidth*10 + c-'0';
		if (c == '.') {
			c = *fmt++;
			if (c == '*') {
				prec = *iap++;
				c = *fmt++;
			} else
				for (prec=0; c>='0' && c<='9'; c=*fmt++)
					prec = prec*10 + c-'0';
		}
		if (c == 'l') {
			c = *fmt++;
			if (c=='d' || c=='o' || c=='u' || c=='x')
				c += 'A' - 'a';
		}
		cbp = cbs = cbuf;
		switch (c) {

		case 'd':
			elem.i = *iap++;
			if (elem.i < 0) {
				elem.i = -elem.i;
				*cbp++ = '-';
			}
			cbp = printi(cbp, elem.i, 10);
			break;

		case 'u':
			cbp = printi(cbp, *iap++, 10);
			break;
	
		case 'o':
			cbp = printi(cbp, *iap++, 8);
			break;

		case 'x':
			cbp = printi(cbp, *iap++, 16);
			break;

		case 'D':
			elem.l = *(long *)iap;
			bump(iap, long);
			if (elem.l < 0) {
				elem.l = -elem.l;
				*cbp++ = '-';
			}
			cbp = printl(cbp, elem.l, 10);
			break;

		case 'U':
			cbp = printl(cbp, *(long *)iap, 10);
			bump(iap, long);
			break;

		case 'O':
			cbp = printl(cbp, *(long *)iap, 8);
			bump(iap, long);
			break;

		case 'X':
			cbp = printl(cbp, *(long *)iap, 16);
			bump(iap, long);
			break;


		case 's':
			if ((s = *(char **)iap) == NULL)
				s = null;
			bump(iap, char*);
			/*
			 * Do %s specially so it can be longer.
			 */
			cbp = cbs = s;
			while (*cbp++ != '\0')
				if (prec>=0 && cbp-s>prec)
					break;
			cbp--;
			break;
	
		case 'c':
			elem.c = *iap++;
			*cbp++ = elem.c;
			break;
	
		case 'r':
			xprintf(*(char ***)iap);
			bump(iap, char**);
			break;
	
		default:
			putchar(c);
			continue;
		}
		if ((pwidth = fwidth + cbs-cbp) < 0)
			pwidth = 0;
		if (!adj)
			while (pwidth-- != 0)
				putchar(pad);
		while (cbs < cbp)
			putchar(*cbs++);
		if (adj)
			while (pwidth-- != 0)
				putchar(pad);
	}
}

static	char	digits[] = {
	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'A', 'B', 'C', 'D', 'E', 'F'
};

/*
 * Print an unsigned integer in base b.
 */
static
char *
printi(cp, n, b)
char *cp;
register unsigned n;
{
	register a;
	register char *ep;
	char pbuf[10];

	ep = &pbuf[10];
	*--ep = 0;
	for ( ; a = n/b; n=a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}

/*
 * Print an unsigned long in base b.
 */
static
char *
printl(cp, n, b)
register char *cp;
unsigned long n;
register b;
{
	char pbuf[13];
	unsigned long a;
	register char *ep;

	ep = &pbuf[13];
	*--ep = '\0';
	for ( ; (a = n/b) != 0; n = a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}
	register char *ep;
	char pbuf[10];

	ep = &pbuf[10];
	*--ep = 0;
	for ( ; a = n/b; n=a)
		*--ep = digits[n%b];
	*--ep = digits[n];
	while (*ep)
		*cp++ = *ep++;
	return (cp);
}

/*
 * Print an unsigned long in base b.
 */
static
char *
printl(cp, n, b)
register char *cp;
unsigned long n;
register b;
{
	char pbuf[13];
	unsignfsck/util.c   644      3      3       15535  5033710270   6110 /*
 *	general utility functions for phases of fsck
 */

#include "fsck.h"

struct stat stats;			/* Used by statit() */

statit(name, probfun)
char *name;
int (*probfun)();
{
	
	if ( stat(name, &stats) == -1 ) {
		bclear(&stats, sizeof(struct stat));
		(*probfun)("Can not stat %s", name);
	}
}


query(x)
{
	while(1) {
		printf("%r [yes/no]: ", &x);
	
		switch (daction) {
		case YES:
			printf("[default - YES]\n");
			return(YES);
			break;
		case NO:
			printf("[default - NO]\n");
			return(NO);
			break;
		case ASK:
			switch( nextchar() ) {
			case 'Y':
				return(YES);
			case 'N':
				return(NO);
			}
		}
	}
}

action(msg)
char *msg;
{
	switch( query(msg) ) {
	case YES:
		return(TRUE);
	case NO:
		return(FALSE);
	}
}

char
nextchar()
{
	char buff[8];
	int i, n, ch;

	if ( ((n=read(0,buff,8)) <= 0) || (n == 8) )
		fatal("Invalid Response");

	for(i=0; i<n; i++)
		if ( ((ch=buff[i])!=' ') && (ch!='\t') )
			break;

	if ( (ch>='a') && (ch<='z') )
		ch += 'A' - 'a';

	return(ch);
}

char	*nfile	= "FILE";
char	*ndir	= "DIR";
char	*nchr	= "Character Special";
char	*nblk	= "Block Special";
char	*npipe	= "PIPE";
char	*nunkwn = "Unknown I-node type";

char *
typename(ino)
ino_t ino;
{
	switch( flags(ino)&MODEMASK ) {
	case IREG:
		return(nfile);
	case IDIR:
		return(ndir);
	case ICHR:
		return(nchr);
	case IBLK:
		return(nblk);
	case IPIPE:
		return(npipe);
	default:
		return(nunkwn);
	}
}

abort()
{
	fatal("abort.");
}

fatal(x)
{
	printf("fsck: %r\n", &x);
	_exit(1);
}

nonfatal(x)
{
	printf("fsck: %r\n", &x);
	errflag = TRUE;
}

/*
 *	Inode Manipulation Routines
 *	ptrino:	returns a pointer to the wanted inode using the given
 *		buffer to read in the block performing canonicalization.
 *	writeino: writes the block containing the given inode to the
 *		disk performing the necessary canonicalization
 *	candino: canonicalize an inode
 *
 */

struct dinode *
ptrino(ino, buf)
register ino_t ino;
register char *buf;
{
	register daddr_t bn;
	register struct dinode *dip;

	bn = iblockn(ino);
	if ( (testblock(bn)) && (bn!=INODEI) )		/* bad inode block */
		return(NULL);
	bread(bn, buf);
	dip = ((struct dinode *) buf) + iblocko(ino);
	candino(dip);
	return(dip);
}

writeino(ino, buf)
ino_t ino;
char *buf;
{
	struct dinode *dip;

	dip = ((struct dinode *) buf) + iblocko(ino);
	candino(dip);
	bwrite((daddr_t) iblockn(ino), buf);
}

candino(dip)
register struct dinode *dip;
{
	canshort(dip->di_mode);
	canshort(dip->di_nlink);
	canshort(dip->di_uid);
	canshort(dip->di_gid);
	cansize(dip->di_size);
	cantime(dip->di_atime);
	cantime(dip->di_mtime);
	cantime(dip->di_ctime);
}

/*
 *	Transfer a logical block number for an inode to a
 *	physical block number, chasing indirects as necessary.
 *	The inefficiency of this method is put up with since
 *	this is only used for directory inodes, and they tend
 *	not to use indirects.  Pass in 'addrs' which is a pointer
 *	to the 13 daddr_s in the inode, and the logical block
 *	number you would like.  (Stolen from dcheck.c)
 */

static	daddr_t	ranges[] = {
	ND,
	ND + (daddr_t)NI*NBN,
	ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
	ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN
};

static	char	index[] = {
	0,
	ND,
	ND+NI,
	ND+NI+NII
};

static	daddr_t	coeff[] = {
	1,	(daddr_t)NBN,	(daddr_t)NBN*NBN,	(daddr_t)NBN*NBN*NBN
};

daddr_t
imap(addrs, block)
daddr_t *addrs;
register daddr_t block;
{
	int i;
	register daddr_t bpos;
	register daddr_t *bp;
	register daddr_t bn;

	for (i=0; i<4; i++)
		if (block < ranges[i]) {
			if (i != 0)
				block -= ranges[i-1];
			bpos = block/coeff[i];
			block %= coeff[i];
			bp = &addrs[(int)bpos + index[i]];
			if ( (bn=*bp) != 0 ) {
				/*
				 * Map through indirects here
				 */
				while (i-- > 0) {
					bread(bn, databuf);
					bpos = block/coeff[i];
					block %= coeff[i];
					bp = (daddr_t *)databuf + bpos;
					if ( (bn=*bp) == 0 )
						break;
					bn = *bp;
					candaddr(bn);
				}
			}
			return(bn);
		}
	return(0);
}

/*
 *	Read the specified block number into the given buffer
 */

char *rgblkerr = "Out of Range Block number: %U  (CONTINUE)";
char *skblkerr = "Can not Seek: Blk num: %U  (CONTINUE)";
char *rdblkerr = "Can not Read: Blk num: %U  (CONTINUE)";
char *wtblkerr = "Can not Write: Blk num: %U  (CONTINUE)";

bread(bn, buf)
register daddr_t bn;
register char *buf;
{
#ifdef	DEBUG
	printf("Reading block number: %ld\n", bn);
#endif
	if (bn<0 || bn >= fsize ) 
		switch( query(rgblkerr, bn) ) {  
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}

	if ( (bn<isize) && getcache(bn, buf) ) {
#if DEBUG
		bdump(buf);
#endif
		return;
	}
	
	if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) )
		switch( query(skblkerr, bn) ) {
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}

	if ( read(fsfd, buf, BSIZE) != BSIZE ) 
		switch( query(rdblkerr, bn) ) {
		case YES:
			bclear(buf, BSIZE);
			return;
		case NO:
			abort();
		}
#if DEBUG
	bdump(buf);
#endif
}

/*
 *	Write block number bn with data in buf
 */

bwrite(bn, buf)
daddr_t bn;
char *buf;
{
#ifdef	DEBUG
	printf("Writing block number: %ld\n", bn);
#endif
	if (!writeflg)
		return;

	if (bn<0 || bn>=fsize) 
		switch( query(rgblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}
	
	if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) )
		switch( query(skblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}

	if ( write(fsfd, buf, BSIZE) != BSIZE ) 
		switch( query(wtblkerr, bn) ) {
		case YES:
			return;
		case NO:
			abort();
		}

	if ( bn <= isize )
		chgcache(bn, buf);
	changeflg = TRUE;
}

/*
 *	i-node block area caching routines
 */

static char	cache[NBLK * BSIZE];
static int	low = 0; high = -1;

getcache(bn, buf)
register daddr_t bn;
register char *buf;
{
	int totsize;

	if ( bn > isize )
		return(0);

	if ( (bn>=low) && (bn<=high) ) {
		blkmove(buf, &cache[BSIZE * (bn-low)]);
		return(1);
	}

	low = bn;
	if ( (high=bn+NBLK-1) > isize )
		high = isize;
	totsize = BSIZE * (high-low+1);

	if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) ||
	     (read(fsfd, cache, totsize) != totsize) ) {
		low = 0; high = -1;
		return(0);
	}

	return( getcache(bn, buf) );
}

chgcache(bn, buf)
register daddr_t bn;
register char *buf;
{
	if ( (bn>=low) && (bn<=high) )
		blkmove(&cache[BSIZE * (bn-low)], buf);
}

blkmove(to, from)
register char *to, *from;
{
	register int num=BSIZE;

	while ( num-- )
		*to++= *from++;
}

/*
 *	Clear the given block of memory
 */

bclear(bp, nb)
register char *bp;
register unsigned nb;
{
	if (nb)
		do {
			*bp++ = 0;
		} while (--nb);
}


/*
 *	Determine if the given block is bad
 */

bad(bn)
daddr_t bn;
{
	if ( (bn >= isize) && (bn < fsize) )
	 	return(GOOD);
	else
		return(BAD);
}


#if DEBUG

/*
 *	Debug dump a block of data.
 */

#define NUMPLIN	16

bdump(buf)
register unsigned char *buf;
{
	register int i;

	for (i=0; i<BSIZE; i++) {
		if ( (i % NUMPLIN) == 0 )
			printf("\n0x%04x:  ", i);
		printf(" %02x", *buf++);
	}
	printf("\n\n");
}

#endif
ister char *bp;
register unsigned nb;
{
	if (nb)
		do {
			*bp++ = 0;
		} while (--nb);
}


/*
 *	Determine if the given block is bad
 */

bad(bn)
daddr_t bn;
{
	ifsck/virtual.c   644      3      3       16227  4767016247   6640 /*
 * Virtual memory for fsck. Uses hash algorithm
 * rather than LRU to get it up fast.
 */
#include <assert.h>
#include <sys/stat.h>
#include "fsck.h"

#define VBLKB 9			/* bytes in virtual block as power of 2 */
#define VBLK (1 << VBLKB)	/* bytes in a virtual block */
#define MBKSB 6			/* number of virtual blocks as power of 2 */
#define MBKS (1 << MBKSB)	/* number of virtual blocks */

#define DVTMP "/dev/rram1"	/* Default Virtual Temp Filename */
#define DVTMPCLS "/dev/rram1close" /* Default Virtual Temp File Close */
#define	MAJORRAM 8		/* Major Device Number for the Ram Disk	*/

struct mapper {
	unsigned dirty:1;
	unsigned what_in:15;	/* which block is in memory */
};

static unsigned long flagdsp, blkdsp, dupdsp, duplim;
static struct mapper map[MBKS];
static unsigned char data[MBKS][VBLK];
static int tmp;

static char *dvtmp = DVTMP;
static char *dvtmpcls = DVTMPCLS;

/*
 * Init file system for virtual arrays.
 * Data is ordered links, flags, blocks then dups.
 */
initV(links, flags, blocks, dups)
unsigned links, flags, blocks, dups;
{
	register long bp;
	struct stat st;
	unsigned datasiz;

	flagdsp = links;
	blkdsp = flagdsp + flags;
	dupdsp = blkdsp + blocks;
	duplim = dupdsp + dups;

	memset(map, 0, sizeof(map));	/* zero ram arrays */
	memset(data, 0, sizeof(data));

	tmp = -1;

	datasiz = sizeof(data);
	if ( duplim < datasiz )
		return;

	if ( tmpfile == NULL ) {
		switch ( is_fs(dvtmp) ) {
		case -1:
			fatal(
"Can't access ram disk \"%s\", use the -t option", dvtmp);
		case 0:
			break;
		case 1:
			fatal(
"Possible file system on ram disk \"%s\", use the -t option", dvtmp);
		}
		if ( (-1 == stat(dvtmp, &st)) || !(st.st_mode&S_IFCHR) ||
			(major(st.st_rdev) != MAJORRAM) )
				fatal("Ram disk \"%s\" not mknod'ed properly",
								dvtmp);
		if ( -1 == (tmp = open(dvtmp, 2)) )
			fatal("Cannot open read/write Ram Disk \"%s\"", dvtmp);

		/* Ram disk driver may not promise zeroed start.
		 * This code may go later. Extra write not important. */
		for(bp = 0; bp < duplim; bp += VBLK) /* zero disk stuff */
			if ( VBLK != write(tmp, data[0], VBLK) )
				fatal("Error writing to tmp file");
	} else {
		if ( -1 == (tmp = open(tmpfile, 2)) ) {
			if ( -1 == (tmp = creat(tmpfile, 0600)) )
				fatal("Cannot create temp file \"%s\"", 
								tmpfile);
			close(tmp);
			tmp = open(tmpfile, 2);
			unlink(tmpfile);
		}
		if ( -1 == fstat(tmp, &st) )
			fatal("Can't stat temp file \"%s\"", tmpfile);
		if ( st.st_dev == fsysrdev )
			fatal("Temp File must not be on file system to fsck");
	}
}

/*
 * cleanup virtual system
 */
cleanV()
{
	struct stat st;

	if ( tmp == -1 )		/* No Virtual Temp File Opened	*/
		return;

	close(tmp);
	if ( tmpfile != NULL )		/* Virtual File not Default RAMDisk */
		return;
					/* Virtual File is Default RAMDisk */
	if ( (-1 == stat(dvtmpcls, &st)) || !(st.st_mode&S_IFCHR) ||
		(major(st.st_rdev) != MAJORRAM) ||
		((minor(st.st_rdev)&0x7F) != 0) )
		fatal("Ram disk close \"%s\" not mknod'ed properly", dvtmpcls);
	if ( -1 == (tmp = open(dvtmpcls, 2)) )
		fatal("Cannot open Ram Disk Close \"%s\"", dvtmpcls);
	if ( close(tmp) < 0 )
		fatal("Cannot close Ram Disk Close \"%s\"", dvtmpcls);
}

/*
 * All actions for virtual array
 */
findblock(bp, action, odata)
long bp;		/* data address */
enum vact action;	/* what to do */
unsigned odata;		/* optional data */
{
	unsigned which, what_in, byte_no, bit;
	unsigned long diskad;
	unsigned char *byte;
	extern long lseek();

	switch(action) {	/* use displacment to correct part of file */
	case testBlock:
	case markBlock:
	case unmarkBlock:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case grabBlock:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += blkdsp;
		assert(bp < dupdsp);
		break;
	case testDup:
	case markDup:
	case unmarkDup:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case setDup:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += dupdsp;
		assert(bp < duplim);
		break;
	case Flags:
	case setFlags:
	case orFlags:
		assert(bp > 0);
		bp += flagdsp - 1;
		assert(bp < blkdsp);
		break;
	case linkCtr:
	case incLinkctr:
	case setLinkctr:
		assert(bp > 0);
		bp--;
		assert(bp < flagdsp);
	}

	byte_no = bp & (VBLK - 1);
	bp >>= VBLKB;
	which = bp & (MBKS - 1);
	bp >>= MBKSB;
	what_in = bp & 0x7fff;

	if((diskad = map[which].what_in) != what_in)	{
		if(map[which].dirty) {
			diskad <<= VBLKB + MBKSB;
			diskad += which << VBLKB;
			if(-1 == lseek(tmp, diskad, 0))
				fatal("Error seeking tmp file");
			if(VBLK != write(tmp, data[which], VBLK))
				fatal("Error writing tmp file");
		}
		diskad = what_in;
		diskad <<= VBLKB + MBKSB;
		diskad += which << VBLKB;
		if(-1 == lseek(tmp, diskad, 0))
			fatal("Error seeking tmp file");
		if(VBLK != read(tmp, data[which], VBLK))
			memset(data[which], 0, VBLK);
		map[which].what_in = what_in;
		map[which].dirty = 0; /* clean */
	}
	byte = &data[which][byte_no];

	switch(action) {
	case testBlock:
	case testDup:
		return(*byte & bit);
	case markBlock:
	case markDup:
		map[which].dirty = 1;
		return(*byte |= bit);
	case unmarkBlock:
	case unmarkDup:
		map[which].dirty = 1;
		return(*byte ^= bit);
	case linkCtr:
	case Flags:
	case grabBlock:
		return(*byte);
	case setLinkctr:
	case setFlags:
	case setDup:
		map[which].dirty = 1;
		return(*byte = odata);
	case orFlags:
		map[which].dirty = 1;
		return(*byte |= odata);
	case incLinkctr:
		map[which].dirty = 1;
		return(++*byte);
	default:
		fatal("Bad action in virtual system");
	}
}

/*
 * copy virtual memory blockmap to dupmap
 * read and write groups to avoid possable thrashing.
 */
void
copyV(size)
unsigned size;
{
	char buf[128];
	register int i;
	long bp, bs;

	for(bs = bp = 0; bp < size; ) {
		for(i = 0; (i < 128) && (bp < size); i++, bp++)
			buf[i] = findblock(bp, grabBlock);

		for(i = 0; (i < 128) && (bs < size); i++, bs++)
			findblock(bs, setDup, buf[i]);
	}
}

#ifdef TEST
fatal(s)
char *s;
{
	fprintf(stderr, "%s\n", s);
	exit(1);
}

static	char buf[80];
gbuf()
{
	if(NULL == gets(buf)) {
		unlink("vtmp");
		exit(0);
	}
	return(buf[0]);
}

main()
{
	unsigned long b;
	char data;

	initV(10000, 10000, 20000);
	for(;;) {
		printf("b = block, d = dup, f = flags, l = linkctr\n");
		switch(gbuf()) {
		case 'l':
			printf("s = set, d = display, i = increment: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 's':
				setlinkctr(b, 0); /* no data */
			case 'd':
				printf("%d\n", linkctr(b));
				break;
			case 'i':
				printf("%d\n", inclinkctr(b));
			}
			break;
		case 'f':
			printf("d = display, s = set, o = or: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld %c", &b, &data);
			switch(buf[0]) {
			case 's':
				setflags(b, data);
			case 'd':
				break;
			case 'o':
				orflags(b, data);
			}
			printf("%c\n", flags(b));
			break;
		case 'b':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markblock(b);
			case 't':
				break;
			case 'u':
				unmarkblock(b);
			}
			printf("%c\n", testblock(b) ? '1' : '0');
			break;
		case 'd':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markdup(b);
			case 't':
				break;
			case 'u':
				unmarkdup(b);
			}
			printf("%c\n", testdup(b) ? '1' : '0');
			break;
		}
	}
}
#endif

en loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markblock(b);
			case 't':
				break;
			case 'u':
				unmarkblock(b);
			}
			printf("%c\n", testblock(b) ? '1' : '0');
			break;
		case 'd':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.