xref: /csrg-svn/sbin/fsck/main.c (revision 6547)
1*6547Smckusick static	char *sccsid = "@(#)main.c	2.4 (Berkeley) 04/15/82";
24428Smckusic 
34236Smckusick #include <stdio.h>
44236Smckusick #include <ctype.h>
56489Smckusick #ifndef SIMFS
66489Smckusick #include <sys/param.h>
76489Smckusick #include <sys/fs.h>
86489Smckusick #include <sys/inode.h>
96489Smckusick #include <ndir.h>
106489Smckusick #else
114236Smckusick #include "../h/param.h"
124236Smckusick #include "../h/fs.h"
134236Smckusick #include "../h/inode.h"
146489Smckusick #include "../h/ndir.h"
156489Smckusick #endif
166489Smckusick #include <sys/stat.h>
174236Smckusick #include <fstab.h>
184236Smckusick 
194236Smckusick typedef	int	(*SIG_TYP)();
204236Smckusick 
215347Smckusic #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
225347Smckusic #define	MAXINOPB	(MAXBSIZE / sizeof (struct dinode))
235325Smckusic #define	SPERB		(MAXBSIZE / sizeof(short))
244236Smckusick 
254236Smckusick #define	MAXDUP	10		/* limit on dup blks (per inode) */
264236Smckusick #define	MAXBAD	10		/* limit on bad blks (per inode) */
274236Smckusick 
284236Smckusick #define	USTATE	0		/* inode not allocated */
294236Smckusick #define	FSTATE	01		/* inode is file */
304236Smckusick #define	DSTATE	02		/* inode is directory */
314236Smckusick #define	CLEAR	03		/* inode is to be cleared */
324236Smckusick 
334236Smckusick typedef struct dinode	DINODE;
344236Smckusick typedef struct direct	DIRECT;
354236Smckusick 
364236Smckusick #define	ALLOC	((dp->di_mode & IFMT) != 0)
375877Smckusic #define	DIRCT	((dp->di_mode & IFMT) == IFDIR)
384236Smckusick #define	REG	((dp->di_mode & IFMT) == IFREG)
394236Smckusick #define	BLK	((dp->di_mode & IFMT) == IFBLK)
404236Smckusick #define	CHR	((dp->di_mode & IFMT) == IFCHR)
416285Smckusick #define	SPECIAL	(BLK || CHR)
424236Smckusick 
434465Smckusic ino_t	startinum;		/* blk num of first in raw area */
444236Smckusick 
454236Smckusick struct bufarea {
464236Smckusick 	struct bufarea	*b_next;		/* must be first */
474236Smckusick 	daddr_t	b_bno;
484236Smckusick 	int	b_size;
494236Smckusick 	union {
505325Smckusic 		char	b_buf[MAXBSIZE];	/* buffer space */
514236Smckusick 		short	b_lnks[SPERB];		/* link counts */
525325Smckusic 		daddr_t	b_indir[MAXNINDIR];	/* indirect block */
534236Smckusick 		struct	fs b_fs;		/* super block */
544236Smckusick 		struct	cg b_cg;		/* cylinder group */
555325Smckusic 		struct dinode b_dinode[MAXINOPB]; /* inode block */
564236Smckusick 	} b_un;
574236Smckusick 	char	b_dirty;
584236Smckusick };
594236Smckusick 
604236Smckusick typedef struct bufarea BUFAREA;
614236Smckusick 
624236Smckusick BUFAREA	inoblk;			/* inode blocks */
634236Smckusick BUFAREA	fileblk;		/* other blks in filesys */
644236Smckusick BUFAREA	sblk;			/* file system superblock */
654236Smckusick BUFAREA	cgblk;
664236Smckusick 
674236Smckusick #define	initbarea(x)	(x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
684236Smckusick #define	dirty(x)	(x)->b_dirty = 1
694236Smckusick #define	inodirty()	inoblk.b_dirty = 1
704236Smckusick #define	sbdirty()	sblk.b_dirty = 1
714236Smckusick #define	cgdirty()	cgblk.b_dirty = 1
724236Smckusick 
734236Smckusick #define	dirblk		fileblk.b_un
744236Smckusick #define	sblock		sblk.b_un.b_fs
754236Smckusick #define	cgrp		cgblk.b_un.b_cg
764236Smckusick 
774236Smckusick struct filecntl {
784236Smckusick 	int	rfdes;
794236Smckusick 	int	wfdes;
804236Smckusick 	int	mod;
814236Smckusick } dfile;			/* file descriptors for filesys */
824236Smckusick 
834236Smckusick #define	DUPTBLSIZE	100	/* num of dup blocks to remember */
844236Smckusick daddr_t	duplist[DUPTBLSIZE];	/* dup block table */
854236Smckusick daddr_t	*enddup;		/* next entry in dup table */
864236Smckusick daddr_t	*muldup;		/* multiple dups part of table */
874236Smckusick 
884236Smckusick #define	MAXLNCNT	20	/* num zero link cnts to remember */
894236Smckusick ino_t	badlncnt[MAXLNCNT];	/* table of inos with zero link cnts */
904236Smckusick ino_t	*badlnp;		/* next entry in table */
914236Smckusick 
924236Smckusick char	rawflg;
934236Smckusick char	nflag;			/* assume a no response */
944236Smckusick char	yflag;			/* assume a yes response */
954236Smckusick int	bflag;			/* location of alternate super block */
965381Smckusic int	debug;			/* output debugging info */
974236Smckusick char	preen;			/* just fix normal inconsistencies */
984236Smckusick char	rplyflag;		/* any questions asked? */
994236Smckusick char	hotroot;		/* checking root device */
1004236Smckusick char	fixcg;			/* corrupted free list bit maps */
1014236Smckusick 
1026314Smckusick char	*blockmap;		/* ptr to primary blk allocation map */
1034236Smckusick char	*freemap;		/* ptr to secondary blk allocation map */
1044236Smckusick char	*statemap;		/* ptr to inode state table */
1054236Smckusick short	*lncntp;		/* ptr to link count table */
1064236Smckusick 
1074236Smckusick char	*pathp;			/* pointer to pathname position */
1084236Smckusick char	*thisname;		/* ptr to current pathname component */
1094236Smckusick char	*srchname;		/* name being searched for in dir */
1105877Smckusic char	pathname[BUFSIZ];
1114236Smckusick 
1124236Smckusick char	*lfname = "lost+found";
1134236Smckusick 
1144236Smckusick ino_t	inum;			/* inode we are currently working on */
1154236Smckusick ino_t	imax;			/* number of inodes */
1164236Smckusick ino_t	parentdir;		/* i number of parent directory */
1174236Smckusick ino_t	lastino;		/* hiwater mark of inodes */
1184236Smckusick ino_t	lfdir;			/* lost & found directory */
1194236Smckusick ino_t	orphan;			/* orphaned inode */
1204236Smckusick 
1214236Smckusick off_t	filsize;		/* num blks seen in file */
1224236Smckusick off_t	maxblk;			/* largest logical blk in file */
1236314Smckusick off_t	bmapsz;			/* num chars in blockmap */
1244236Smckusick 
1254236Smckusick daddr_t	n_ffree;		/* number of small free blocks */
1264236Smckusick daddr_t	n_bfree;		/* number of large free blocks */
1274236Smckusick daddr_t	n_blks;			/* number of blocks used */
1284236Smckusick daddr_t	n_files;		/* number of files seen */
1294236Smckusick daddr_t	n_index;
1304236Smckusick daddr_t	n_bad;
1314236Smckusick daddr_t	fmax;			/* number of blocks in the volume */
1324236Smckusick 
1334236Smckusick daddr_t	badblk;
1344236Smckusick daddr_t	dupblk;
1354236Smckusick 
1364236Smckusick int	inosumbad;
1374236Smckusick int	offsumbad;
1384465Smckusic int	frsumbad;
1396491Smckusick int	sbsumbad;
1404236Smckusick 
1414236Smckusick #define	zapino(x)	(*(x) = zino)
1424236Smckusick struct	dinode zino;
1434236Smckusick 
1444236Smckusick #define	setlncnt(x)	(lncntp[inum] = x)
1454236Smckusick #define	getlncnt()	(lncntp[inum])
1464236Smckusick #define	declncnt()	(--lncntp[inum])
1474236Smckusick 
1486314Smckusick #define	setbmap(x)	setbit(blockmap, x)
1496314Smckusick #define	getbmap(x)	isset(blockmap, x)
1506314Smckusick #define	clrbmap(x)	clrbit(blockmap, x)
1514236Smckusick 
1524236Smckusick #define	setfmap(x)	setbit(freemap, x)
1534236Smckusick #define	getfmap(x)	isset(freemap, x)
1544236Smckusick #define	clrfmap(x)	clrbit(freemap, x)
1554236Smckusick 
1564236Smckusick #define	setstate(x)	(statemap[inum] = x)
1574236Smckusick #define	getstate()	statemap[inum]
1584236Smckusick 
1594236Smckusick #define	DATA	1
1604236Smckusick #define	ADDR	0
1614236Smckusick 
1624236Smckusick #define	ALTERD	010
1634236Smckusick #define	KEEPON	04
1644236Smckusick #define	SKIP	02
1654236Smckusick #define	STOP	01
1664236Smckusick 
1674236Smckusick int	(*signal())();
1684236Smckusick long	lseek();
1694236Smckusick time_t	time();
1704236Smckusick DINODE	*ginode();
1714236Smckusick BUFAREA	*getblk();
1724236Smckusick int	dirscan();
1734236Smckusick int	findino();
1744236Smckusick int	catch();
1754236Smckusick int	mkentry();
1764236Smckusick int	chgdd();
1774236Smckusick int	pass1(), pass1b(), pass2(), pass4(), pass5();
1784236Smckusick int	(*pfunc)();
1794236Smckusick char	*rawname(), *rindex(), *unrawname();
1804606Smckusic extern int inside[], around[];
1815325Smckusic extern unsigned char *fragtbl[];
1824236Smckusick 
1834236Smckusick char	*devname;
1844236Smckusick 
1854236Smckusick main(argc, argv)
1864715Smckusic 	int	argc;
1874715Smckusic 	char	*argv[];
1884236Smckusick {
1894236Smckusick 	struct fstab *fsp;
1904236Smckusick 	int pid, passno, anygtr, sumstatus;
1914236Smckusick 
1924236Smckusick 	sync();
1934236Smckusick 	while (--argc > 0 && **++argv == '-') {
1944236Smckusick 		switch (*++*argv) {
1954236Smckusick 
1964236Smckusick 		case 'p':
1974236Smckusick 			preen++;
1984236Smckusick 			break;
1994236Smckusick 
2004236Smckusick 		case 'b':
2014236Smckusick 			bflag = atoi(argv[0]+1);
2024236Smckusick 			printf("Alternate super block location: %d\n", bflag);
2034236Smckusick 			break;
2044236Smckusick 
2055381Smckusic 		case 'd':
2065381Smckusic 			debug++;
2075381Smckusic 			break;
2085381Smckusic 
2094236Smckusick 		case 'n':	/* default no answer flag */
2104236Smckusick 		case 'N':
2114236Smckusick 			nflag++;
2124236Smckusick 			yflag = 0;
2134236Smckusick 			break;
2144236Smckusick 
2154236Smckusick 		case 'y':	/* default yes answer flag */
2164236Smckusick 		case 'Y':
2174236Smckusick 			yflag++;
2184236Smckusick 			nflag = 0;
2194236Smckusick 			break;
2204236Smckusick 
2214236Smckusick 		default:
2224236Smckusick 			errexit("%c option?\n", **argv);
2234236Smckusick 		}
2244236Smckusick 	}
2254236Smckusick 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
2264236Smckusick 		signal(SIGINT, catch);
2274236Smckusick 	if (argc) {
2284236Smckusick 		while (argc-- > 0) {
2294236Smckusick 			hotroot = 0;
2304236Smckusick 			check(*argv++);
2314236Smckusick 		}
2324236Smckusick 		exit(0);
2334236Smckusick 	}
2344236Smckusick 	sumstatus = 0;
2354236Smckusick 	passno = 1;
2364236Smckusick 	do {
2374236Smckusick 		anygtr = 0;
2384236Smckusick 		if (setfsent() == 0)
2394236Smckusick 			errexit("Can't open checklist file: %s\n", FSTAB);
2404236Smckusick 		while ((fsp = getfsent()) != 0) {
2414236Smckusick 			if (strcmp(fsp->fs_type, FSTAB_RW) &&
2424236Smckusick 			    strcmp(fsp->fs_type, FSTAB_RO))
2434236Smckusick 				continue;
2444236Smckusick 			if (preen == 0 ||
2454236Smckusick 			    passno == 1 && fsp->fs_passno == passno) {
2464236Smckusick 				if (blockcheck(fsp->fs_spec) == 0 && preen)
2474236Smckusick 					exit(8);
2484236Smckusick 			} else if (fsp->fs_passno > passno)
2494236Smckusick 				anygtr = 1;
2504236Smckusick 			else if (fsp->fs_passno == passno) {
2514236Smckusick 				pid = fork();
2524236Smckusick 				if (pid < 0) {
2534236Smckusick 					perror("fork");
2544236Smckusick 					exit(8);
2554236Smckusick 				}
2564236Smckusick 				if (pid == 0)
2574236Smckusick 					if (blockcheck(fsp->fs_spec)==0)
2584236Smckusick 						exit(8);
2594236Smckusick 					else
2604236Smckusick 						exit(0);
2614236Smckusick 			}
2624236Smckusick 		}
2634236Smckusick 		if (preen) {
2644236Smckusick 			int status;
2654236Smckusick 			while (wait(&status) != -1)
2664236Smckusick 				sumstatus |= status;
2674236Smckusick 		}
2684236Smckusick 		passno++;
2694236Smckusick 	} while (anygtr);
2704236Smckusick 	if (sumstatus)
2714236Smckusick 		exit(8);
2724236Smckusick 	endfsent();
2734236Smckusick 	exit(0);
2744236Smckusick }
2754236Smckusick 
2764236Smckusick blockcheck(name)
2774236Smckusick 	char *name;
2784236Smckusick {
2796489Smckusick 	struct stat stslash, stblock, stchar;
2804236Smckusick 	char *raw;
2814236Smckusick 	int looped = 0;
2824236Smckusick 
2834236Smckusick 	hotroot = 0;
2844236Smckusick 	if (stat("/", &stslash) < 0){
2854236Smckusick 		error("Can't stat root\n");
2864236Smckusick 		return (0);
2874236Smckusick 	}
2884236Smckusick retry:
2894236Smckusick 	if (stat(name, &stblock) < 0){
2904236Smckusick 		error("Can't stat %s\n", name);
2914236Smckusick 		return (0);
2924236Smckusick 	}
2934236Smckusick 	if (stblock.st_mode & S_IFBLK) {
2944236Smckusick 		raw = rawname(name);
2954236Smckusick 		if (stat(raw, &stchar) < 0){
2964236Smckusick 			error("Can't stat %s\n", raw);
2974236Smckusick 			return (0);
2984236Smckusick 		}
2994236Smckusick 		if (stchar.st_mode & S_IFCHR) {
3004236Smckusick 			if (stslash.st_dev == stblock.st_rdev) {
3014236Smckusick 				hotroot++;
3024236Smckusick 				raw = unrawname(name);
3034236Smckusick 			}
3044236Smckusick 			check(raw);
3054236Smckusick 			return (1);
3064236Smckusick 		} else {
3074236Smckusick 			error("%s is not a character device\n", raw);
3084236Smckusick 			return (0);
3094236Smckusick 		}
3104236Smckusick 	} else if (stblock.st_mode & S_IFCHR) {
3114236Smckusick 		if (looped) {
3124236Smckusick 			error("Can't make sense out of name %s\n", name);
3134236Smckusick 			return (0);
3144236Smckusick 		}
3154236Smckusick 		name = unrawname(name);
3164236Smckusick 		looped++;
3174236Smckusick 		goto retry;
3184236Smckusick 	}
3194236Smckusick 	error("Can't make sense out of name %s\n", name);
3204236Smckusick 	return (0);
3214236Smckusick }
3224236Smckusick 
3234236Smckusick char *
3244236Smckusick unrawname(cp)
3254236Smckusick 	char *cp;
3264236Smckusick {
3274236Smckusick 	char *dp = rindex(cp, '/');
3286489Smckusick 	struct stat stb;
3294236Smckusick 
3304236Smckusick 	if (dp == 0)
3314236Smckusick 		return (cp);
3324236Smckusick 	if (stat(cp, &stb) < 0)
3334236Smckusick 		return (cp);
3344236Smckusick 	if ((stb.st_mode&S_IFMT) != S_IFCHR)
3354236Smckusick 		return (cp);
3364236Smckusick 	if (*(dp+1) != 'r')
3374236Smckusick 		return (cp);
3384236Smckusick 	strcpy(dp+1, dp+2);
3394236Smckusick 	return (cp);
3404236Smckusick }
3414236Smckusick 
3424236Smckusick char *
3434236Smckusick rawname(cp)
3444236Smckusick 	char *cp;
3454236Smckusick {
3464236Smckusick 	static char rawbuf[32];
3474236Smckusick 	char *dp = rindex(cp, '/');
3484236Smckusick 
3494236Smckusick 	if (dp == 0)
3504236Smckusick 		return (0);
3514236Smckusick 	*dp = 0;
3524236Smckusick 	strcpy(rawbuf, cp);
3534236Smckusick 	*dp = '/';
3544236Smckusick 	strcat(rawbuf, "/r");
3554236Smckusick 	strcat(rawbuf, dp+1);
3564236Smckusick 	return (rawbuf);
3574236Smckusick }
3584236Smckusick 
3594236Smckusick check(dev)
3604236Smckusick 	char *dev;
3614236Smckusick {
3624236Smckusick 	register DINODE *dp;
3634236Smckusick 	register ino_t *blp;
3644236Smckusick 	register int i, n;
3654236Smckusick 	ino_t savino;
3664236Smckusick 	int b, c;
3674236Smckusick 	daddr_t d, s;
3684236Smckusick 
3694236Smckusick 	devname = dev;
3704236Smckusick 	if (setup(dev) == 0) {
3714236Smckusick 		if (preen)
3724236Smckusick 			pfatal("CAN'T CHECK DEVICE.");
3734236Smckusick 		return;
3744236Smckusick 	}
3754236Smckusick /* 1 */
3764236Smckusick 	if (preen==0) {
3774236Smckusick 		if (hotroot)
3784236Smckusick 			printf("** Root file system\n");
3794236Smckusick 		printf("** Phase 1 - Check Blocks and Sizes\n");
3804236Smckusick 	}
3814236Smckusick 	pfunc = pass1;
3824236Smckusick 	inum = 0;
3836533Smckusick 	n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
3844236Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
3855381Smckusic 		if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
3864236Smckusick 			continue;
3876533Smckusick 		if (debug && cgrp.cg_magic != CG_MAGIC)
3886533Smckusick 			printf("cg %d: bad magic number\n", c);
3894236Smckusick 		n = 0;
3904465Smckusic 		for (i = 0; i < sblock.fs_ipg; i++, inum++) {
3914465Smckusic 			dp = ginode();
3924465Smckusic 			if (dp == NULL)
3934465Smckusic 				continue;
3945944Smckusic 			n++;
3954236Smckusick 			if (ALLOC) {
3964236Smckusick 				if (!isset(cgrp.cg_iused, i)) {
3975381Smckusic 					if (debug)
3985381Smckusic 						printf("%d bad, not used\n",
3995381Smckusic 						    inum);
4004236Smckusick 					inosumbad++;
4014236Smckusick 				}
4025944Smckusic 				n--;
4034236Smckusick 				lastino = inum;
4044236Smckusick 				if (ftypeok(dp) == 0) {
4054236Smckusick 					pfatal("UNKNOWN FILE TYPE I=%u", inum);
4064236Smckusick 					if (reply("CLEAR") == 1) {
4074236Smckusick 						zapino(dp);
4084236Smckusick 						inodirty();
4094236Smckusick 						inosumbad++;
4104236Smckusick 					}
4114236Smckusick 					continue;
4124236Smckusick 				}
4134236Smckusick 				n_files++;
4144236Smckusick 				if (setlncnt(dp->di_nlink) <= 0) {
4154236Smckusick 					if (badlnp < &badlncnt[MAXLNCNT])
4164236Smckusick 						*badlnp++ = inum;
4174236Smckusick 					else {
4184236Smckusick 						pfatal("LINK COUNT TABLE OVERFLOW");
4194236Smckusick 						if (reply("CONTINUE") == 0)
4204236Smckusick 							errexit("");
4214236Smckusick 					}
4224236Smckusick 				}
4235877Smckusic 				setstate(DIRCT ? DSTATE : FSTATE);
4244236Smckusick 				badblk = dupblk = 0; filsize = 0; maxblk = 0;
4254236Smckusick 				ckinode(dp, ADDR);
4264236Smckusick 			} else {
4274236Smckusick 				if (isset(cgrp.cg_iused, i)) {
4285381Smckusic 					if (debug)
4295381Smckusic 						printf("%d bad, marked used\n",
4305381Smckusic 						    inum);
4314236Smckusick 					inosumbad++;
4324465Smckusic 					n--;
4334236Smckusick 				}
4344236Smckusick 				if (dp->di_mode != 0) {
4354236Smckusick 					pfatal("PARTIALLY ALLOCATED INODE I=%u", inum);
4364236Smckusick 					if (reply("CLEAR") == 1) {
4374236Smckusick 						zapino(dp);
4384236Smckusick 						inodirty();
4394236Smckusick 						inosumbad++;
4404236Smckusick 					}
4414236Smckusick 				}
4424236Smckusick 			}
4434236Smckusick 		}
4444789Smckusic 		if (n != cgrp.cg_cs.cs_nifree) {
4455381Smckusic 			if (debug)
4465944Smckusic 				printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
4475381Smckusic 				    c, cgrp.cg_cs.cs_nifree, n);
4484236Smckusick 			inosumbad++;
4494236Smckusick 		}
4506491Smckusick 		if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
4516491Smckusick 		  || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
4526491Smckusick 		  || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
4536491Smckusick 		  || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
4546491Smckusick 			sbsumbad++;
4554236Smckusick 	}
4564236Smckusick /* 1b */
4574236Smckusick 	if (enddup != &duplist[0]) {
4584236Smckusick 		if (preen)
4594236Smckusick 			pfatal("INTERNAL ERROR: dups with -p");
4604236Smckusick 		printf("** Phase 1b - Rescan For More DUPS\n");
4614236Smckusick 		pfunc = pass1b;
4624236Smckusick 		inum = 0;
4634236Smckusick 		for (c = 0; c < sblock.fs_ncg; c++) {
4644465Smckusic 			for (i = 0; i < sblock.fs_ipg; i++, inum++) {
4654465Smckusic 				dp = ginode();
4664465Smckusic 				if (dp == NULL)
4674465Smckusic 					continue;
4684236Smckusick 				if (getstate() != USTATE &&
4694236Smckusick 				    (ckinode(dp, ADDR) & STOP))
4704236Smckusick 					goto out1b;
4714465Smckusic 			}
4724236Smckusick 		}
4734236Smckusick 	}
4744236Smckusick out1b:
4754465Smckusic 	flush(&dfile, &inoblk);
4764236Smckusick /* 2 */
4774236Smckusick 	if (preen == 0)
4784236Smckusick 		printf("** Phase 2 - Check Pathnames\n");
4794236Smckusick 	inum = ROOTINO;
4804236Smckusick 	thisname = pathp = pathname;
4814236Smckusick 	pfunc = pass2;
4824236Smckusick 	switch (getstate()) {
4834236Smckusick 
4844236Smckusick 	case USTATE:
4854236Smckusick 		errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
4864236Smckusick 
4874236Smckusick 	case FSTATE:
4884236Smckusick 		pfatal("ROOT INODE NOT DIRECTORY");
4894236Smckusick 		if (reply("FIX") == 0 || (dp = ginode()) == NULL)
4904236Smckusick 			errexit("");
4914236Smckusick 		dp->di_mode &= ~IFMT;
4924236Smckusick 		dp->di_mode |= IFDIR;
4934236Smckusick 		inodirty();
4944236Smckusick 		inosumbad++;
4954236Smckusick 		setstate(DSTATE);
4964236Smckusick 		/* fall into ... */
4974236Smckusick 
4984236Smckusick 	case DSTATE:
4994236Smckusick 		descend();
5004236Smckusick 		break;
5014236Smckusick 
5024236Smckusick 	case CLEAR:
5034236Smckusick 		pfatal("DUPS/BAD IN ROOT INODE");
5044236Smckusick 		printf("\n");
5054236Smckusick 		if (reply("CONTINUE") == 0)
5064236Smckusick 			errexit("");
5074236Smckusick 		setstate(DSTATE);
5084236Smckusick 		descend();
5094236Smckusick 	}
5104236Smckusick /* 3 */
5114236Smckusick 	if (preen == 0)
5124236Smckusick 		printf("** Phase 3 - Check Connectivity\n");
5134236Smckusick 	for (inum = ROOTINO; inum <= lastino; inum++) {
5144236Smckusick 		if (getstate() == DSTATE) {
5154236Smckusick 			pfunc = findino;
5164236Smckusick 			srchname = "..";
5174236Smckusick 			savino = inum;
5184236Smckusick 			do {
5194236Smckusick 				orphan = inum;
5204236Smckusick 				if ((dp = ginode()) == NULL)
5214236Smckusick 					break;
5224236Smckusick 				filsize = dp->di_size;
5234236Smckusick 				parentdir = 0;
5244236Smckusick 				ckinode(dp, DATA);
5254236Smckusick 				if ((inum = parentdir) == 0)
5264236Smckusick 					break;
5274236Smckusick 			} while (getstate() == DSTATE);
5284236Smckusick 			inum = orphan;
5294236Smckusick 			if (linkup() == 1) {
5304236Smckusick 				thisname = pathp = pathname;
5314236Smckusick 				*pathp++ = '?';
5324236Smckusick 				pfunc = pass2;
5334236Smckusick 				descend();
5344236Smckusick 			}
5354236Smckusick 			inum = savino;
5364236Smckusick 		}
5374236Smckusick 	}
5384236Smckusick /* 4 */
5394236Smckusick 	if (preen == 0)
5404236Smckusick 		printf("** Phase 4 - Check Reference Counts\n");
5414236Smckusick 	pfunc = pass4;
5424236Smckusick 	for (inum = ROOTINO; inum <= lastino; inum++) {
5434236Smckusick 		switch (getstate()) {
5444236Smckusick 
5454236Smckusick 		case FSTATE:
5464236Smckusick 			if (n = getlncnt())
5474236Smckusick 				adjust((short)n);
5484236Smckusick 			else {
5494236Smckusick 				for (blp = badlncnt;blp < badlnp; blp++)
5504236Smckusick 					if (*blp == inum) {
5514236Smckusick 						clri("UNREF", 1);
5524236Smckusick 						break;
5534236Smckusick 					}
5544236Smckusick 			}
5554236Smckusick 			break;
5564236Smckusick 
5574236Smckusick 		case DSTATE:
5584236Smckusick 			clri("UNREF", 1);
5594236Smckusick 			break;
5604236Smckusick 
5614236Smckusick 		case CLEAR:
5624236Smckusick 			clri("BAD/DUP", 1);
5634236Smckusick 			break;
5644236Smckusick 		}
5654236Smckusick 	}
5665337Smckusic 	if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) {
5674236Smckusick 		pwarn("FREE INODE COUNT WRONG IN SUPERBLK");
5684236Smckusick 		if (preen)
5694236Smckusick 			printf(" (FIXED)\n");
5704236Smckusick 		if (preen || reply("FIX") == 1) {
5715944Smckusic 			sblock.fs_cstotal.cs_nifree = imax - ROOTINO - n_files;
5724236Smckusick 			sbdirty();
5734236Smckusick 		}
5744236Smckusick 	}
5754236Smckusick 	flush(&dfile, &fileblk);
5764236Smckusick 
5774236Smckusick /* 5 */
5784236Smckusick 	if (preen == 0)
5794236Smckusick 		printf("** Phase 5 - Check Cyl groups\n");
5806314Smckusick 	copy(blockmap, freemap, (unsigned)bmapsz);
5814236Smckusick 	dupblk = 0;
5825381Smckusic 	n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
5834236Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
5845381Smckusic 		daddr_t cbase = cgbase(&sblock, c);
5854236Smckusick 		short bo[MAXCPG][NRPOS];
5865371Smckusic 		long botot[MAXCPG];
5875325Smckusic 		long frsum[MAXFRAG];
5884465Smckusic 		int blk;
5894465Smckusic 
5905371Smckusic 		for (n = 0; n < sblock.fs_cpg; n++) {
5915371Smckusic 			botot[n] = 0;
5924236Smckusick 			for (i = 0; i < NRPOS; i++)
5934236Smckusick 				bo[n][i] = 0;
5945371Smckusic 		}
5955325Smckusic 		for (i = 0; i < sblock.fs_frag; i++) {
5964465Smckusic 			frsum[i] = 0;
5974465Smckusic 		}
5984465Smckusic 		/*
5996533Smckusick 		 * need to account for the super blocks
6004465Smckusic 		 * which appear (inaccurately) bad
6014465Smckusic 		 */
6026533Smckusick 		n_bad += cgtod(&sblock, c) - cgsblock(&sblock, c);
6035381Smckusic 		if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
6044236Smckusick 			continue;
6056533Smckusick 		if (debug && cgrp.cg_magic != CG_MAGIC)
6066533Smckusick 			printf("cg %d: bad magic number\n", c);
6075325Smckusic 		for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
6085325Smckusic 			if (isblock(&sblock, cgrp.cg_free, b/sblock.fs_frag)) {
6095325Smckusic 				if (pass5(cbase+b, sblock.fs_frag) == STOP)
6104236Smckusick 					goto out5;
6114236Smckusick 				/* this is clumsy ... */
6125325Smckusic 				n_ffree -= sblock.fs_frag;
6134236Smckusick 				n_bfree++;
6145371Smckusic 				botot[cbtocylno(&sblock, b)]++;
6155363Smckusic 				bo[cbtocylno(&sblock, b)]
6165363Smckusic 				    [cbtorpos(&sblock, b)]++;
6174465Smckusic 			} else {
6185325Smckusic 				for (d = 0; d < sblock.fs_frag; d++)
6194236Smckusick 					if (isset(cgrp.cg_free, b+d))
6204236Smckusick 						if (pass5(cbase+b+d,1) == STOP)
6214236Smckusick 							goto out5;
6224465Smckusic 				blk = ((cgrp.cg_free[b / NBBY] >> (b % NBBY)) &
6235325Smckusic 				       (0xff >> (NBBY - sblock.fs_frag)));
6244465Smckusic 				if (blk != 0)
6255325Smckusic 					fragacct(&sblock, blk, frsum, 1);
6264465Smckusic 			}
6274236Smckusick 		}
6285325Smckusic 		for (i = 0; i < sblock.fs_frag; i++) {
6294465Smckusic 			if (cgrp.cg_frsum[i] != frsum[i]) {
6305381Smckusic 				if (debug)
6315381Smckusic 					printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
6325381Smckusic 					    c, i, cgrp.cg_frsum[i], frsum[i]);
6334465Smckusic 				frsumbad++;
6344465Smckusic 			}
6354465Smckusic 		}
6365371Smckusic 		for (n = 0; n < sblock.fs_cpg; n++) {
6375371Smckusic 			if (botot[n] != cgrp.cg_btot[n]) {
6385381Smckusic 				if (debug)
6395381Smckusic 					printf("cg[%d].cg_btot[%d] have %d calc %d\n",
6405381Smckusic 					    c, n, cgrp.cg_btot[n], botot[n]);
6415371Smckusic 				offsumbad++;
6425371Smckusic 			}
6434236Smckusick 			for (i = 0; i < NRPOS; i++)
6444236Smckusick 				if (bo[n][i] != cgrp.cg_b[n][i]) {
6455381Smckusic 					if (debug)
6465381Smckusic 						printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
6475381Smckusic 						    c, n, i, cgrp.cg_b[n][i],
6485381Smckusic 						    bo[n][i]);
6494236Smckusick 					offsumbad++;
6504236Smckusick 				}
6515371Smckusic 		}
6524236Smckusick 	}
6534236Smckusick out5:
6544236Smckusick 	if (dupblk)
6554236Smckusick 		pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk);
6564236Smckusick 	if (fixcg == 0) {
6575325Smckusic 		if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) {
6584236Smckusick 			pwarn("%ld BLK(S) MISSING\n", fmax - b);
6594236Smckusick 			fixcg = 1;
6606491Smckusick 		} else if (inosumbad + offsumbad + frsumbad + sbsumbad) {
6616491Smckusick 			pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n",
6624236Smckusick 			    inosumbad ? "(INODE FREE) " : "",
6634465Smckusic 			    offsumbad ? "(BLOCK OFFSETS) " : "",
6646491Smckusick 			    frsumbad ? "(FRAG SUMMARIES) " : "",
6656491Smckusick 			    sbsumbad ? "(SUPER BLOCK SUMMARIES) " : "");
6664236Smckusick 			fixcg = 1;
6674789Smckusic 		} else if (n_ffree != sblock.fs_cstotal.cs_nffree ||
6684789Smckusic 		    n_bfree != sblock.fs_cstotal.cs_nbfree) {
6694236Smckusick 			pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
6704236Smckusick 			if (preen)
6714236Smckusick 				printf(" (FIXED)\n");
6724236Smckusick 			if (preen || reply("FIX") == 1) {
6734789Smckusic 				sblock.fs_cstotal.cs_nffree = n_ffree;
6744789Smckusic 				sblock.fs_cstotal.cs_nbfree = n_bfree;
6754236Smckusick 				sbdirty();
6764236Smckusick 			}
6774236Smckusick 		}
6784236Smckusick 	}
6794236Smckusick 	if (fixcg) {
6804236Smckusick 		pwarn("BAD CYLINDER GROUPS");
6814236Smckusick 		if (preen)
6824236Smckusick 			printf(" (SALVAGED)\n");
6834236Smckusick 		else if (reply("SALVAGE") == 0)
6844236Smckusick 			fixcg = 0;
6854236Smckusick 	}
6864236Smckusick 
6874236Smckusick 	if (fixcg) {
6884236Smckusick 		if (preen == 0)
6894236Smckusick 			printf("** Phase 6 - Salvage Cylinder Groups\n");
6904236Smckusick 		makecg();
6914789Smckusic 		n_ffree = sblock.fs_cstotal.cs_nffree;
6924789Smckusic 		n_bfree = sblock.fs_cstotal.cs_nbfree;
6934236Smckusick 	}
6944236Smckusick 
6954236Smckusick 	pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n",
6966533Smckusick 	    n_files, n_blks - howmany(sblock.fs_cssize, sblock.fs_fsize),
6975325Smckusic 	    n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree);
6984236Smckusick 	if (dfile.mod) {
6994236Smckusick 		time(&sblock.fs_time);
7004236Smckusick 		sbdirty();
7014236Smckusick 	}
7024236Smckusick 	ckfini();
7034236Smckusick 	sync();
7044236Smckusick 	if (dfile.mod && hotroot) {
7054236Smckusick 		printf("\n***** BOOT UNIX (NO SYNC!) *****\n");
7064236Smckusick 		exit(4);
7074236Smckusick 	}
7084236Smckusick 	if (dfile.mod && preen == 0)
7094236Smckusick 		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
7106314Smckusick 	free(blockmap);
7114236Smckusick 	free(freemap);
7124236Smckusick 	free(statemap);
7134236Smckusick 	free(lncntp);
7144236Smckusick }
7154236Smckusick 
7164236Smckusick /* VARARGS1 */
7174236Smckusick error(s1, s2, s3, s4)
7184715Smckusic 	char *s1;
7194236Smckusick {
7204236Smckusick 
7214236Smckusick 	printf(s1, s2, s3, s4);
7224236Smckusick }
7234236Smckusick 
7244236Smckusick /* VARARGS1 */
7254236Smckusick errexit(s1, s2, s3, s4)
7264715Smckusic 	char *s1;
7274236Smckusick {
7284236Smckusick 	error(s1, s2, s3, s4);
7294236Smckusick 	exit(8);
7304236Smckusick }
7314236Smckusick 
7324236Smckusick /*
7334236Smckusick  * An inconsistency occured which shouldn't during normal operations.
7344236Smckusick  * Die if preening, otw just printf.
7354236Smckusick  */
7364236Smckusick /* VARARGS1 */
7374236Smckusick pfatal(s, a1, a2, a3)
7384236Smckusick 	char *s;
7394236Smckusick {
7404236Smckusick 
7414236Smckusick 	if (preen) {
7424236Smckusick 		printf("%s: ", devname);
7434236Smckusick 		printf(s, a1, a2, a3);
7444236Smckusick 		printf("\n");
7454236Smckusick 		preendie();
7464236Smckusick 	}
7474236Smckusick 	printf(s, a1, a2, a3);
7484236Smckusick }
7494236Smckusick 
7504236Smckusick preendie()
7514236Smckusick {
7524236Smckusick 
7534236Smckusick 	printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
7544236Smckusick 	exit(8);
7554236Smckusick }
7564236Smckusick 
7574236Smckusick /*
7584236Smckusick  * Pwarn is like printf when not preening,
7594236Smckusick  * or a warning (preceded by filename) when preening.
7604236Smckusick  */
7614236Smckusick /* VARARGS1 */
7624236Smckusick pwarn(s, a1, a2, a3, a4, a5)
7634236Smckusick 	char *s;
7644236Smckusick {
7654236Smckusick 
7664236Smckusick 	if (preen)
7674236Smckusick 		printf("%s: ", devname);
7684236Smckusick 	printf(s, a1, a2, a3, a4, a5);
7694236Smckusick }
7704236Smckusick 
7714236Smckusick ckinode(dp, flg)
7724236Smckusick 	DINODE *dp;
7734236Smckusick 	register flg;
7744236Smckusick {
7754236Smckusick 	register daddr_t *ap;
7764236Smckusick 	register ret;
7775956Smckusic 	int (*func)(), n, ndb, size, offset;
7784236Smckusick 
7794236Smckusick 	if (SPECIAL)
7804236Smckusick 		return (KEEPON);
7814236Smckusick 	func = (flg == ADDR) ? pfunc : dirscan;
7825325Smckusic 	ndb = howmany(dp->di_size, sblock.fs_bsize);
7834428Smckusic 	for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) {
7845956Smckusic 		if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0)
7855956Smckusic 			size = numfrags(&sblock, fragroundup(&sblock, offset));
7864236Smckusick 		else
7875325Smckusic 			size = sblock.fs_frag;
7884236Smckusick 		if (*ap && (ret = (*func)(*ap, size)) & STOP)
7894236Smckusick 			return (ret);
7904236Smckusick 	}
7914428Smckusic 	for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) {
7925325Smckusic 		if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - sblock.fs_bsize * NDADDR)) & STOP)
7934236Smckusick 			return (ret);
7944236Smckusick 	}
7954236Smckusick 	return (KEEPON);
7964236Smckusick }
7974236Smckusick 
7984236Smckusick iblock(blk, ilevel, flg, isize)
7994236Smckusick 	daddr_t blk;
8004236Smckusick 	register ilevel;
8014236Smckusick 	int isize;
8024236Smckusick {
8034236Smckusick 	register daddr_t *ap;
8044236Smckusick 	register daddr_t *aplim;
8054428Smckusic 	register int i, n;
8064236Smckusick 	int (*func)(), nif;
8074236Smckusick 	BUFAREA ib;
8084236Smckusick 
8094236Smckusick 	if (flg == ADDR) {
8104236Smckusick 		func = pfunc;
8115325Smckusic 		if (((n = (*func)(blk, sblock.fs_frag)) & KEEPON) == 0)
8124236Smckusick 			return (n);
8134236Smckusick 	} else
8144236Smckusick 		func = dirscan;
8154236Smckusick 	if (outrange(blk))		/* protect thyself */
8164236Smckusick 		return (SKIP);
8174236Smckusick 	initbarea(&ib);
8185325Smckusic 	if (getblk(&ib, blk, sblock.fs_bsize) == NULL)
8194236Smckusick 		return (SKIP);
8204236Smckusick 	ilevel--;
8214428Smckusic 	if (ilevel == 0) {
8225956Smckusic 		nif = lblkno(&sblock, isize) + 1;
8234428Smckusic 	} else /* ilevel == 1 */ {
8245325Smckusic 		nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1;
8254428Smckusic 	}
8265325Smckusic 	if (nif > NINDIR(&sblock))
8275325Smckusic 		nif = NINDIR(&sblock);
8284428Smckusic 	aplim = & ib.b_un.b_indir[nif];
8294428Smckusic 	for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
8304236Smckusick 		if (*ap) {
8314236Smckusick 			if (ilevel > 0)
8325325Smckusic 				n = iblock(*ap, ilevel, flg, isize - i * NINDIR(&sblock) * sblock.fs_bsize);
8334236Smckusick 			else
8345325Smckusic 				n = (*func)(*ap, sblock.fs_frag);
8354236Smckusick 			if (n & STOP)
8364236Smckusick 				return (n);
8374236Smckusick 		}
8384236Smckusick 	return (KEEPON);
8394236Smckusick }
8404236Smckusick 
8414236Smckusick pass1(blk, size)
8424236Smckusick 	daddr_t blk;
8434236Smckusick 	int size;
8444236Smckusick {
8454236Smckusick 	register daddr_t *dlp;
8464236Smckusick 	int res = KEEPON;
8474236Smckusick 
8484236Smckusick 	for (; size > 0; blk++, size--) {
8494236Smckusick 		if (outrange(blk)) {
8504236Smckusick 			blkerr("BAD", blk);
8514236Smckusick 			if (++badblk >= MAXBAD) {
8524236Smckusick 				printf("EXCESSIVE BAD BLKS I=%u", inum);
8534236Smckusick 				if (reply("CONTINUE") == 0)
8544236Smckusick 					errexit("");
8554236Smckusick 				return (STOP);
8564236Smckusick 			}
8574236Smckusick 			res = SKIP;
8584236Smckusick 		} else if (getbmap(blk)) {
8594236Smckusick 			blkerr("DUP", blk);
8604236Smckusick 			if (++dupblk >= MAXDUP) {
8614236Smckusick 				printf("EXCESSIVE DUP BLKS I=%u", inum);
8624236Smckusick 				if (reply("CONTINUE") == 0)
8634236Smckusick 					errexit("");
8644236Smckusick 				return (STOP);
8654236Smckusick 			}
8664236Smckusick 			if (enddup >= &duplist[DUPTBLSIZE]) {
8674236Smckusick 				printf("DUP TABLE OVERFLOW.");
8684236Smckusick 				if (reply("CONTINUE") == 0)
8694236Smckusick 					errexit("");
8704236Smckusick 				return (STOP);
8714236Smckusick 			}
8724236Smckusick 			for (dlp = duplist; dlp < muldup; dlp++)
8734236Smckusick 				if (*dlp == blk) {
8744236Smckusick 					*enddup++ = blk;
8754236Smckusick 					break;
8764236Smckusick 				}
8774236Smckusick 			if (dlp >= muldup) {
8784236Smckusick 				*enddup++ = *muldup;
8794236Smckusick 				*muldup++ = blk;
8804236Smckusick 			}
8814236Smckusick 		} else {
8824236Smckusick 			n_blks++;
8834236Smckusick 			setbmap(blk);
8844236Smckusick 		}
8854236Smckusick 		filsize++;
8864236Smckusick 	}
8874236Smckusick 	return (res);
8884236Smckusick }
8894236Smckusick 
8904236Smckusick pass1b(blk, size)
8914236Smckusick 	daddr_t blk;
8924236Smckusick 	int size;
8934236Smckusick {
8944236Smckusick 	register daddr_t *dlp;
8954236Smckusick 	int res = KEEPON;
8964236Smckusick 
8974236Smckusick 	for (; size > 0; blk++, size--) {
8984236Smckusick 		if (outrange(blk))
8994236Smckusick 			res = SKIP;
9004236Smckusick 		for (dlp = duplist; dlp < muldup; dlp++)
9014236Smckusick 			if (*dlp == blk) {
9024236Smckusick 				blkerr("DUP", blk);
9034236Smckusick 				*dlp = *--muldup;
9044236Smckusick 				*muldup = blk;
9054236Smckusick 				if (muldup == duplist)
9064236Smckusick 					return (STOP);
9074236Smckusick 			}
9084236Smckusick 	}
9094236Smckusick 	return (res);
9104236Smckusick }
9114236Smckusick 
9124236Smckusick pass2(dirp)
9134236Smckusick 	register DIRECT *dirp;
9144236Smckusick {
9154236Smckusick 	register char *p;
9164236Smckusick 	register n;
9174236Smckusick 	DINODE *dp;
9184236Smckusick 
9194236Smckusick 	if ((inum = dirp->d_ino) == 0)
9204236Smckusick 		return (KEEPON);
9214236Smckusick 	thisname = pathp;
9225877Smckusic 	for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; )
9234236Smckusick 		if ((*pathp++ = *p++) == 0) {
9244236Smckusick 			--pathp;
9254236Smckusick 			break;
9264236Smckusick 		}
9274236Smckusick 	*pathp = 0;
9284236Smckusick 	n = 0;
9294715Smckusic 	if (inum > imax || inum <= 0)
9304236Smckusick 		n = direrr("I OUT OF RANGE");
9314236Smckusick 	else {
9324236Smckusick again:
9334236Smckusick 		switch (getstate()) {
9344236Smckusick 		case USTATE:
9354236Smckusick 			n = direrr("UNALLOCATED");
9364236Smckusick 			break;
9374236Smckusick 
9384236Smckusick 		case CLEAR:
9394236Smckusick 			if ((n = direrr("DUP/BAD")) == 1)
9404236Smckusick 				break;
9414236Smckusick 			if ((dp = ginode()) == NULL)
9424236Smckusick 				break;
9435877Smckusic 			setstate(DIRCT ? DSTATE : FSTATE);
9444236Smckusick 			goto again;
9454236Smckusick 
9464236Smckusick 		case FSTATE:
9474236Smckusick 			declncnt();
9484236Smckusick 			break;
9494236Smckusick 
9504236Smckusick 		case DSTATE:
9514236Smckusick 			declncnt();
9524236Smckusick 			descend();
9534236Smckusick 			break;
9544236Smckusick 		}
9554236Smckusick 	}
9564236Smckusick 	pathp = thisname;
9574236Smckusick 	if (n == 0)
9584236Smckusick 		return (KEEPON);
9594236Smckusick 	dirp->d_ino = 0;
9604236Smckusick 	return (KEEPON|ALTERD);
9614236Smckusick }
9624236Smckusick 
9634236Smckusick pass4(blk, size)
9644715Smckusic 	daddr_t blk;
9654236Smckusick {
9664236Smckusick 	register daddr_t *dlp;
9674236Smckusick 	int res = KEEPON;
9684236Smckusick 
9694236Smckusick 	for (; size > 0; blk++, size--) {
9704236Smckusick 		if (outrange(blk))
9714236Smckusick 			res = SKIP;
9724236Smckusick 		else if (getbmap(blk)) {
9734236Smckusick 			for (dlp = duplist; dlp < enddup; dlp++)
9744236Smckusick 				if (*dlp == blk) {
9754236Smckusick 					*dlp = *--enddup;
9764236Smckusick 					return (KEEPON);
9774236Smckusick 				}
9784236Smckusick 			clrbmap(blk);
9794236Smckusick 			n_blks--;
9804236Smckusick 		}
9814236Smckusick 	}
9824236Smckusick 	return (res);
9834236Smckusick }
9844236Smckusick 
9854236Smckusick pass5(blk, size)
9864236Smckusick 	daddr_t blk;
9874236Smckusick 	int size;
9884236Smckusick {
9894236Smckusick 	int res = KEEPON;
9904236Smckusick 
9914236Smckusick 	for (; size > 0; blk++, size--) {
9924236Smckusick 		if (outrange(blk)) {
9934236Smckusick 			fixcg = 1;
9944236Smckusick 			if (preen)
9954236Smckusick 				pfatal("BAD BLOCKS IN BIT MAPS.");
9964236Smckusick 			if (++badblk >= MAXBAD) {
9974236Smckusick 				printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
9984236Smckusick 				if (reply("CONTINUE") == 0)
9994236Smckusick 					errexit("");
10004236Smckusick 				return (STOP);
10014236Smckusick 			}
10024236Smckusick 		} else if (getfmap(blk)) {
10034236Smckusick 			fixcg = 1;
10044236Smckusick 			if (++dupblk >= DUPTBLSIZE) {
10054236Smckusick 				printf("EXCESSIVE DUP BLKS IN BIT MAPS.");
10064236Smckusick 				if (reply("CONTINUE") == 0)
10074236Smckusick 					errexit("");
10084236Smckusick 				return (STOP);
10094236Smckusick 			}
10104236Smckusick 		} else {
10114236Smckusick 			n_ffree++;
10124236Smckusick 			setfmap(blk);
10134236Smckusick 		}
10144236Smckusick 	}
10154236Smckusick 	return (res);
10164236Smckusick }
10174236Smckusick 
10184236Smckusick outrange(blk)
10194236Smckusick 	daddr_t blk;
10204236Smckusick {
10214236Smckusick 	register int c;
10224236Smckusick 
10235381Smckusic 	c = dtog(&sblock, blk);
10246533Smckusick 	if ((unsigned)blk >= fmax) {
10254236Smckusick 		return (1);
10264428Smckusic 	}
10274236Smckusick 	return (0);
10284236Smckusick }
10294236Smckusick 
10304236Smckusick blkerr(s, blk)
10314236Smckusick 	daddr_t blk;
10324236Smckusick 	char *s;
10334236Smckusick {
10344236Smckusick 	pfatal("%ld %s I=%u", blk, s, inum);
10354236Smckusick 	printf("\n");
10364236Smckusick 	setstate(CLEAR);	/* mark for possible clearing */
10374236Smckusick }
10384236Smckusick 
10394236Smckusick descend()
10404236Smckusick {
10414236Smckusick 	register DINODE *dp;
10424236Smckusick 	register char *savname;
10434236Smckusick 	off_t savsize;
10444236Smckusick 
10454236Smckusick 	setstate(FSTATE);
10464236Smckusick 	if ((dp = ginode()) == NULL)
10474236Smckusick 		return;
10484236Smckusick 	savname = thisname;
10494236Smckusick 	*pathp++ = '/';
10504236Smckusick 	savsize = filsize;
10514236Smckusick 	filsize = dp->di_size;
10524236Smckusick 	ckinode(dp, DATA);
10534236Smckusick 	thisname = savname;
10544236Smckusick 	*--pathp = 0;
10554236Smckusick 	filsize = savsize;
10564236Smckusick }
10574236Smckusick 
10585877Smckusic struct dirstuff {
10595877Smckusic 	int loc;
10605877Smckusic 	int blkno;
10615877Smckusic 	int blksiz;
10625877Smckusic };
10635877Smckusic 
10644236Smckusick dirscan(blk, nf)
10654715Smckusic 	daddr_t blk;
10664715Smckusic 	int nf;
10674236Smckusick {
10685877Smckusic 	register DIRECT *dp;
10695877Smckusic 	struct dirstuff dirp;
10706251Smckusick 	int blksiz, dsize, n;
10716251Smckusick 	char dbuf[DIRBLKSIZ];
10724236Smckusick 
10734236Smckusick 	if (outrange(blk)) {
10745325Smckusic 		filsize -= sblock.fs_bsize;
10754236Smckusick 		return (SKIP);
10764236Smckusick 	}
10775877Smckusic 	blksiz = nf * sblock.fs_fsize;
10785877Smckusic 	dirp.loc = 0;
10795877Smckusic 	dirp.blkno = blk;
10805877Smckusic 	dirp.blksiz = blksiz;
10815877Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
10826251Smckusick 		dsize = dp->d_reclen;
10836251Smckusick 		copy(dp, dbuf, dsize);
10846251Smckusick 		if ((n = (*pfunc)(dbuf)) & ALTERD) {
10855877Smckusic 			if (getblk(&fileblk, blk, blksiz) != NULL) {
10866251Smckusick 				copy(dbuf, dp, dsize);
10874715Smckusic 				dirty(&fileblk);
10884236Smckusick 				sbdirty();
10894236Smckusick 			} else
10904236Smckusick 				n &= ~ALTERD;
10914236Smckusick 		}
10925877Smckusic 		if (n & STOP)
10934236Smckusick 			return (n);
10944236Smckusick 	}
10954236Smckusick 	return (filsize > 0 ? KEEPON : STOP);
10964236Smckusick }
10974236Smckusick 
10985877Smckusic /*
10995877Smckusic  * get next entry in a directory.
11005877Smckusic  */
11015877Smckusic DIRECT *
11025877Smckusic readdir(dirp)
11035877Smckusic 	register struct dirstuff *dirp;
11045877Smckusic {
11056251Smckusick 	register DIRECT *dp, *ndp;
11065877Smckusic 
11075877Smckusic 	if (getblk(&fileblk, dirp->blkno, dirp->blksiz) == NULL) {
11085877Smckusic 		filsize -= dirp->blksiz - dirp->loc;
11095877Smckusic 		return NULL;
11105877Smckusic 	}
11115877Smckusic 	for (;;) {
11125877Smckusic 		if (filsize <= 0 || dirp->loc >= dirp->blksiz)
11135877Smckusic 			return NULL;
11145935Smckusic 		dp = (DIRECT *)(dirblk.b_buf + dirp->loc);
11155935Smckusic 		dirp->loc += dp->d_reclen;
11165935Smckusic 		filsize -= dp->d_reclen;
11176251Smckusick 		ndp = (DIRECT *)(dirblk.b_buf + dirp->loc);
11186372Smckusick 		if (dirp->loc < dirp->blksiz && filsize > 0 &&
11196251Smckusick 		    (ndp->d_ino > imax || ndp->d_namlen > MAXNAMLEN ||
11206251Smckusick 		    ndp->d_reclen <= 0 ||
11216251Smckusick 		    ndp->d_reclen > DIRBLKSIZ - (dirp->loc % DIRBLKSIZ))) {
11226251Smckusick 			pwarn("DIRECTORY CORRUPTED");
11236251Smckusick 			if (preen)
11246251Smckusick 				printf(" (SALVAGED)\n");
11256251Smckusick 			else if (reply("SALVAGE") == 0) {
11266251Smckusick 				dirp->loc +=
11276251Smckusick 				    DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
11286251Smckusick 				filsize -= DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
11296251Smckusick 				return(dp);
11306251Smckusick 			}
11316251Smckusick 			dirp->loc -= dp->d_reclen;
11326251Smckusick 			filsize += dp->d_reclen;
11336251Smckusick 			dp->d_reclen = DIRBLKSIZ - (dirp->loc % DIRBLKSIZ);
11346251Smckusick 			dirty(&fileblk);
11355877Smckusic 			continue;
11366251Smckusick 		}
11375935Smckusic 		return (dp);
11385877Smckusic 	}
11395877Smckusic }
11405877Smckusic 
11414236Smckusick direrr(s)
11424715Smckusic 	char *s;
11434236Smckusick {
11444236Smckusick 	register DINODE *dp;
11454236Smckusick 
11464236Smckusick 	pwarn("%s ", s);
11474236Smckusick 	pinode();
11484236Smckusick 	printf("\n");
11494236Smckusick 	if ((dp = ginode()) != NULL && ftypeok(dp))
11505877Smckusic 		pfatal("%s=%s", DIRCT?"DIR":"FILE", pathname);
11514236Smckusick 	else
11524236Smckusick 		pfatal("NAME=%s", pathname);
11534236Smckusick 	return (reply("REMOVE"));
11544236Smckusick }
11554236Smckusick 
11564236Smckusick adjust(lcnt)
11574465Smckusic 	register short lcnt;
11584236Smckusick {
11594236Smckusick 	register DINODE *dp;
11604236Smckusick 
11614236Smckusick 	if ((dp = ginode()) == NULL)
11624236Smckusick 		return;
11634236Smckusick 	if (dp->di_nlink == lcnt) {
11644236Smckusick 		if (linkup() == 0)
11654236Smckusick 			clri("UNREF", 0);
11664236Smckusick 	}
11674236Smckusick 	else {
11684236Smckusick 		pwarn("LINK COUNT %s",
11695877Smckusic 			(lfdir==inum)?lfname:(DIRCT?"DIR":"FILE"));
11704236Smckusick 		pinode();
11714236Smckusick 		printf(" COUNT %d SHOULD BE %d",
11724236Smckusick 			dp->di_nlink, dp->di_nlink-lcnt);
11734236Smckusick 		if (preen) {
11744236Smckusick 			if (lcnt < 0) {
11754236Smckusick 				printf("\n");
11764236Smckusick 				preendie();
11774236Smckusick 			}
11784236Smckusick 			printf(" (ADJUSTED)\n");
11794236Smckusick 		}
11804236Smckusick 		if (preen || reply("ADJUST") == 1) {
11814236Smckusick 			dp->di_nlink -= lcnt;
11824236Smckusick 			inodirty();
11834236Smckusick 		}
11844236Smckusick 	}
11854236Smckusick }
11864236Smckusick 
11874236Smckusick clri(s, flg)
11884715Smckusic 	char *s;
11894236Smckusick {
11904236Smckusick 	register DINODE *dp;
11914236Smckusick 
11924236Smckusick 	if ((dp = ginode()) == NULL)
11934236Smckusick 		return;
11944236Smckusick 	if (flg == 1) {
11955877Smckusic 		pwarn("%s %s", s, DIRCT?"DIR":"FILE");
11964236Smckusick 		pinode();
11974236Smckusick 	}
11984236Smckusick 	if (preen || reply("CLEAR") == 1) {
11994236Smckusick 		if (preen)
12004236Smckusick 			printf(" (CLEARED)\n");
12014236Smckusick 		n_files--;
12024236Smckusick 		pfunc = pass4;
12034236Smckusick 		ckinode(dp, ADDR);
12044236Smckusick 		zapino(dp);
12054465Smckusic 		setstate(USTATE);
12064236Smckusick 		inodirty();
12074236Smckusick 		inosumbad++;
12084236Smckusick 	}
12094236Smckusick }
12104236Smckusick 
12114236Smckusick setup(dev)
12124715Smckusic 	char *dev;
12134236Smckusick {
12144236Smckusick 	dev_t rootdev;
12156489Smckusick 	struct stat statb;
12164236Smckusick 	int super = bflag ? bflag : SBLOCK;
12176533Smckusick 	int i, j, size;
12186533Smckusick 	int c, d, cgd;
12194236Smckusick 
12204236Smckusick 	bflag = 0;
12214236Smckusick 	if (stat("/", &statb) < 0)
12224236Smckusick 		errexit("Can't stat root\n");
12234236Smckusick 	rootdev = statb.st_dev;
12244236Smckusick 	if (stat(dev, &statb) < 0) {
12254236Smckusick 		error("Can't stat %s\n", dev);
12264236Smckusick 		return (0);
12274236Smckusick 	}
12284236Smckusick 	rawflg = 0;
12294236Smckusick 	if ((statb.st_mode & S_IFMT) == S_IFBLK)
12304236Smckusick 		;
12314236Smckusick 	else if ((statb.st_mode & S_IFMT) == S_IFCHR)
12324236Smckusick 		rawflg++;
12334236Smckusick 	else {
12344236Smckusick 		if (reply("file is not a block or character device; OK") == 0)
12354236Smckusick 			return (0);
12364236Smckusick 	}
12374236Smckusick 	if (rootdev == statb.st_rdev)
12384236Smckusick 		hotroot++;
12394236Smckusick 	if ((dfile.rfdes = open(dev, 0)) < 0) {
12404236Smckusick 		error("Can't open %s\n", dev);
12414236Smckusick 		return (0);
12424236Smckusick 	}
12434236Smckusick 	if (preen == 0)
12444236Smckusick 		printf("** %s", dev);
12454236Smckusick 	if (nflag || (dfile.wfdes = open(dev, 1)) < 0) {
12464236Smckusick 		dfile.wfdes = -1;
12474236Smckusick 		if (preen)
12484236Smckusick 			pfatal("NO WRITE ACCESS");
12494236Smckusick 		printf(" (NO WRITE)");
12504236Smckusick 	}
12514236Smckusick 	if (preen == 0)
12524236Smckusick 		printf("\n");
12536491Smckusick 	fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; sbsumbad = 0;
12544236Smckusick 	dfile.mod = 0;
12554236Smckusick 	n_files = n_blks = n_ffree = n_bfree = 0;
12564236Smckusick 	muldup = enddup = &duplist[0];
12574236Smckusick 	badlnp = &badlncnt[0];
12584236Smckusick 	lfdir = 0;
12594236Smckusick 	rplyflag = 0;
12604236Smckusick 	initbarea(&sblk);
12614236Smckusick 	initbarea(&fileblk);
12624236Smckusick 	initbarea(&inoblk);
12634236Smckusick 	initbarea(&cgblk);
12646491Smckusick 	/*
12656491Smckusick 	 * Read in the super block and its summary info.
12666491Smckusick 	 */
12675347Smckusic 	if (bread(&dfile, &sblock, super, SBSIZE) == 0)
12684236Smckusick 		return (0);
12694465Smckusic 	sblk.b_bno = super;
12705347Smckusic 	sblk.b_size = SBSIZE;
12715363Smckusic 	/*
12725363Smckusic 	 * run a few consistency checks of the super block
12735363Smckusic 	 */
12744236Smckusick 	if (sblock.fs_magic != FS_MAGIC)
12754236Smckusick 		{ badsb("MAGIC NUMBER WRONG"); return (0); }
12764236Smckusick 	if (sblock.fs_ncg < 1)
12774236Smckusick 		{ badsb("NCG OUT OF RANGE"); return (0); }
12784236Smckusick 	if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG)
12794236Smckusick 		{ badsb("CPG OUT OF RANGE"); return (0); }
12804236Smckusick 	if (sblock.fs_nsect < 1)
12814236Smckusick 		{ badsb("NSECT < 1"); return (0); }
12824236Smckusick 	if (sblock.fs_ntrak < 1)
12834236Smckusick 		{ badsb("NTRAK < 1"); return (0); }
12845363Smckusic 	if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak)
12855363Smckusic 		{ badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); }
12865363Smckusic 	if (sblock.fs_ipg % INOPB(&sblock))
12875363Smckusic 		{ badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); }
12885381Smckusic 	if (cgdmin(&sblock, 0) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
12894236Smckusick 		{ badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); }
12905363Smckusic 	if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
12915363Smckusic 	    (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
12924236Smckusick 		{ badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
12935325Smckusic 	if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
12944236Smckusick 		{ badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); }
12955363Smckusic 	if (sblock.fs_size * NSPF(&sblock) <=
12965363Smckusic 	    (sblock.fs_ncyl - 1) * sblock.fs_spc)
12974236Smckusick 		{ badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); }
12985363Smckusic 	if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc)
12994236Smckusick 		{ badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
13004236Smckusick 	/* rest we COULD repair... */
13015956Smckusic 	if (sblock.fs_cgsize != fragroundup(&sblock,
13025956Smckusic 	    sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY)))
13034236Smckusick 		{ badsb("CGSIZE INCORRECT"); return (0); }
13046533Smckusick 	if (sblock.fs_cssize !=
13056533Smckusick 	    fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)))
13064236Smckusick 		{ badsb("CSSIZE INCORRECT"); return (0); }
13074236Smckusick 	fmax = sblock.fs_size;
13084236Smckusick 	imax = sblock.fs_ncg * sblock.fs_ipg;
13096533Smckusick 	n_bad = cgsblock(&sblock, 0); /* boot block plus dedicated sblock */
13105363Smckusic 	/*
13116533Smckusick 	 * read in the summary info.
13125363Smckusic 	 */
13136533Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
13146533Smckusick 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
13156533Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize;
13166533Smckusick 		sblock.fs_csp[j] = (struct csum *)calloc(1, size);
13176533Smckusick 		bread(&dfile, (char *)sblock.fs_csp[j],
13186533Smckusick 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
13196533Smckusick 		    size);
13206533Smckusick 	}
13216533Smckusick 	/*
13226533Smckusick 	 * allocate and initialize the necessary maps
13236533Smckusick 	 */
13244236Smckusick 	bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
13256314Smckusick 	blockmap = (char *)calloc(bmapsz, sizeof (char));
1326*6547Smckusick 	if (blockmap == NULL) {
1327*6547Smckusick 		printf("cannot alloc %d bytes for blockmap\n", bmapsz);
1328*6547Smckusick 		exit(1);
1329*6547Smckusick 	}
13304236Smckusick 	freemap = (char *)calloc(bmapsz, sizeof (char));
1331*6547Smckusick 	if (freemap == NULL) {
1332*6547Smckusick 		printf("cannot alloc %d bytes for freemap\n", bmapsz);
1333*6547Smckusick 		exit(1);
1334*6547Smckusick 	}
13354236Smckusick 	statemap = (char *)calloc(imax+1, sizeof(char));
1336*6547Smckusick 	if (statemap == NULL) {
1337*6547Smckusick 		printf("cannot alloc %d bytes for statemap\n", imax + 1);
1338*6547Smckusick 		exit(1);
1339*6547Smckusick 	}
13404236Smckusick 	lncntp = (short *)calloc(imax+1, sizeof(short));
1341*6547Smckusick 	if (lncntp == NULL) {
1342*6547Smckusick 		printf("cannot alloc %d bytes for lncntp\n",
1343*6547Smckusick 		    (imax + 1) * sizeof(short));
1344*6547Smckusick 		exit(1);
1345*6547Smckusick 	}
13466533Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
13476533Smckusick 		cgd = cgdmin(&sblock, c);
13486533Smckusick 		if (c == 0) {
13496533Smckusick 			d = cgbase(&sblock, c);
13506533Smckusick 			cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
13516533Smckusick 		} else
13526533Smckusick 			d = cgsblock(&sblock, c);
13536533Smckusick 		for (; d < cgd; d++)
13546533Smckusick 			setbmap(d);
13556533Smckusick 	}
13564236Smckusick 
13574465Smckusic 	startinum = imax + 1;
13584236Smckusick 	return (1);
13594236Smckusick 
13604236Smckusick badsb:
13614236Smckusick 	ckfini();
13624236Smckusick 	return (0);
13634236Smckusick }
13644236Smckusick 
13654236Smckusick badsb(s)
13664236Smckusick 	char *s;
13674236Smckusick {
13684236Smckusick 
13694236Smckusick 	if (preen)
13704236Smckusick 		printf("%s: ", devname);
13714236Smckusick 	printf("BAD SUPER BLOCK: %s\n", s);
13724236Smckusick 	pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n");
13734236Smckusick 	pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n");
13744236Smckusick }
13754236Smckusick 
13764236Smckusick DINODE *
13774236Smckusick ginode()
13784236Smckusick {
13794236Smckusick 	daddr_t iblk;
13804236Smckusick 
1381*6547Smckusick 	if (inum < ROOTINO || inum > imax) {
1382*6547Smckusick 		if (debug && (inum < 0 || inum > imax))
1383*6547Smckusick 			printf("inum out of range (%d)\n", inum);
13844236Smckusick 		return (NULL);
1385*6547Smckusick 	}
13865325Smckusic 	if (inum < startinum || inum >= startinum + INOPB(&sblock)) {
13875381Smckusic 		iblk = itod(&sblock, inum);
13885325Smckusic 		if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) {
13894236Smckusick 			return (NULL);
13904236Smckusick 		}
13915325Smckusic 		startinum = (inum / INOPB(&sblock)) * INOPB(&sblock);
13924236Smckusick 	}
13935325Smckusic 	return (&inoblk.b_un.b_dinode[inum % INOPB(&sblock)]);
13944236Smckusick }
13954236Smckusick 
13964236Smckusick ftypeok(dp)
13974236Smckusick 	DINODE *dp;
13984236Smckusick {
13994236Smckusick 	switch (dp->di_mode & IFMT) {
14004236Smckusick 
14014236Smckusick 	case IFDIR:
14024236Smckusick 	case IFREG:
14034236Smckusick 	case IFBLK:
14044236Smckusick 	case IFCHR:
14056285Smckusick 	case IFLNK:
14064236Smckusick 		return (1);
14074236Smckusick 
14084236Smckusick 	default:
14094236Smckusick 		return (0);
14104236Smckusick 	}
14114236Smckusick }
14124236Smckusick 
14134236Smckusick reply(s)
14144236Smckusick 	char *s;
14154236Smckusick {
14164236Smckusick 	char line[80];
14174236Smckusick 
14184236Smckusick 	if (preen)
14194236Smckusick 		pfatal("INTERNAL ERROR: GOT TO reply()");
14204236Smckusick 	rplyflag = 1;
14214236Smckusick 	printf("\n%s? ", s);
14224236Smckusick 	if (nflag || dfile.wfdes < 0) {
14234236Smckusick 		printf(" no\n\n");
14244236Smckusick 		return (0);
14254236Smckusick 	}
14264236Smckusick 	if (yflag) {
14274236Smckusick 		printf(" yes\n\n");
14284236Smckusick 		return (1);
14294236Smckusick 	}
14304236Smckusick 	if (getline(stdin, line, sizeof(line)) == EOF)
14314236Smckusick 		errexit("\n");
14324236Smckusick 	printf("\n");
14334236Smckusick 	if (line[0] == 'y' || line[0] == 'Y')
14344236Smckusick 		return (1);
14354236Smckusick 	else
14364236Smckusick 		return (0);
14374236Smckusick }
14384236Smckusick 
14394236Smckusick getline(fp, loc, maxlen)
14404236Smckusick 	FILE *fp;
14414236Smckusick 	char *loc;
14424236Smckusick {
14434236Smckusick 	register n;
14444236Smckusick 	register char *p, *lastloc;
14454236Smckusick 
14464236Smckusick 	p = loc;
14474236Smckusick 	lastloc = &p[maxlen-1];
14484236Smckusick 	while ((n = getc(fp)) != '\n') {
14494236Smckusick 		if (n == EOF)
14504236Smckusick 			return (EOF);
14514236Smckusick 		if (!isspace(n) && p < lastloc)
14524236Smckusick 			*p++ = n;
14534236Smckusick 	}
14544236Smckusick 	*p = 0;
14554236Smckusick 	return (p - loc);
14564236Smckusick }
14574236Smckusick 
14584236Smckusick BUFAREA *
14594236Smckusick getblk(bp, blk, size)
14604236Smckusick 	daddr_t blk;
14614236Smckusick 	register BUFAREA *bp;
14624236Smckusick 	int size;
14634236Smckusick {
14644236Smckusick 	register struct filecntl *fcp;
14655325Smckusic 	daddr_t dblk;
14664236Smckusick 
14674236Smckusick 	fcp = &dfile;
14685325Smckusic 	dblk = fsbtodb(&sblock, blk);
14695325Smckusic 	if (bp->b_bno == dblk)
14704236Smckusick 		return (bp);
14714236Smckusick 	flush(fcp, bp);
14725325Smckusic 	if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) {
14735325Smckusic 		bp->b_bno = dblk;
14744236Smckusick 		bp->b_size = size;
14754236Smckusick 		return (bp);
14764236Smckusick 	}
14774236Smckusick 	bp->b_bno = (daddr_t)-1;
14784236Smckusick 	return (NULL);
14794236Smckusick }
14804236Smckusick 
14814236Smckusick flush(fcp, bp)
14824236Smckusick 	struct filecntl *fcp;
14834236Smckusick 	register BUFAREA *bp;
14844236Smckusick {
14854236Smckusick 
14864236Smckusick 	if (bp->b_dirty)
14874236Smckusick 		bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size);
14884236Smckusick 	bp->b_dirty = 0;
14894236Smckusick }
14904236Smckusick 
14914236Smckusick rwerr(s, blk)
14924236Smckusick 	char *s;
14934236Smckusick 	daddr_t blk;
14944236Smckusick {
14954236Smckusick 
14964236Smckusick 	if (preen == 0)
14974236Smckusick 		printf("\n");
14984236Smckusick 	pfatal("CANNOT %s: BLK %ld", s, blk);
14994236Smckusick 	if (reply("CONTINUE") == 0)
15004236Smckusick 		errexit("Program terminated\n");
15014236Smckusick }
15024236Smckusick 
15034236Smckusick ckfini()
15044236Smckusick {
15054236Smckusick 
15064236Smckusick 	flush(&dfile, &fileblk);
15074236Smckusick 	flush(&dfile, &sblk);
15084465Smckusic 	if (sblk.b_bno != SBLOCK) {
15094465Smckusic 		sblk.b_bno = SBLOCK;
15104465Smckusic 		sbdirty();
15114465Smckusic 		flush(&dfile, &sblk);
15124465Smckusic 	}
15134236Smckusick 	flush(&dfile, &inoblk);
15144236Smckusick 	close(dfile.rfdes);
15154236Smckusick 	close(dfile.wfdes);
15164236Smckusick }
15174236Smckusick 
15184236Smckusick pinode()
15194236Smckusick {
15204236Smckusick 	register DINODE *dp;
15214236Smckusick 	register char *p;
15225877Smckusic 	char uidbuf[BUFSIZ];
15234236Smckusick 	char *ctime();
15244236Smckusick 
15254236Smckusick 	printf(" I=%u ", inum);
15264236Smckusick 	if ((dp = ginode()) == NULL)
15274236Smckusick 		return;
15284236Smckusick 	printf(" OWNER=");
15294236Smckusick 	if (getpw((int)dp->di_uid, uidbuf) == 0) {
15304236Smckusick 		for (p = uidbuf; *p != ':'; p++);
15314236Smckusick 		*p = 0;
15324236Smckusick 		printf("%s ", uidbuf);
15334236Smckusick 	}
15344236Smckusick 	else {
15354236Smckusick 		printf("%d ", dp->di_uid);
15364236Smckusick 	}
15374236Smckusick 	printf("MODE=%o\n", dp->di_mode);
15384236Smckusick 	if (preen)
15394236Smckusick 		printf("%s: ", devname);
15404236Smckusick 	printf("SIZE=%ld ", dp->di_size);
15414236Smckusick 	p = ctime(&dp->di_mtime);
15424236Smckusick 	printf("MTIME=%12.12s %4.4s ", p+4, p+20);
15434236Smckusick }
15444236Smckusick 
15454236Smckusick copy(fp, tp, size)
15464236Smckusick 	register char *tp, *fp;
15474236Smckusick 	unsigned size;
15484236Smckusick {
15494236Smckusick 
15504236Smckusick 	while (size--)
15514236Smckusick 		*tp++ = *fp++;
15524236Smckusick }
15534236Smckusick 
15544236Smckusick makecg()
15554236Smckusick {
15564465Smckusic 	int c, blk;
15576533Smckusick 	daddr_t dbase, d, dlower, dupper, dmax;
15584236Smckusick 	long i, j, s;
15594236Smckusick 	register struct csum *cs;
15604465Smckusic 	register DINODE *dp;
15614236Smckusick 
15624789Smckusic 	sblock.fs_cstotal.cs_nbfree = 0;
15634789Smckusic 	sblock.fs_cstotal.cs_nffree = 0;
15644789Smckusic 	sblock.fs_cstotal.cs_nifree = 0;
15654789Smckusic 	sblock.fs_cstotal.cs_ndir = 0;
15664236Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
15675381Smckusic 		dbase = cgbase(&sblock, c);
15684236Smckusick 		dmax = dbase + sblock.fs_fpg;
15695409Smckusic 		if (dmax > sblock.fs_size) {
15705944Smckusic 			for ( ; dmax >= sblock.fs_size; dmax--)
15715401Smckusic 				clrbit(cgrp.cg_free, dmax - dbase);
15725409Smckusic 			dmax++;
15735409Smckusic 		}
15746533Smckusick 		dlower = cgsblock(&sblock, c) - dbase;
15756533Smckusick 		dupper = cgdmin(&sblock, c) - dbase;
15765325Smckusic 		cs = &sblock.fs_cs(&sblock, c);
15774236Smckusick 		cgrp.cg_time = time(0);
15784236Smckusick 		cgrp.cg_magic = CG_MAGIC;
15794236Smckusick 		cgrp.cg_cgx = c;
15804236Smckusick 		cgrp.cg_ncyl = sblock.fs_cpg;
15814236Smckusick 		cgrp.cg_niblk = sblock.fs_ipg;
15824236Smckusick 		cgrp.cg_ndblk = dmax - dbase;
15834789Smckusic 		cgrp.cg_cs.cs_ndir = 0;
15844789Smckusic 		cgrp.cg_cs.cs_nffree = 0;
15854789Smckusic 		cgrp.cg_cs.cs_nbfree = 0;
15864789Smckusic 		cgrp.cg_cs.cs_nifree = 0;
15876533Smckusick 		cgrp.cg_rotor = 0;
15886533Smckusick 		cgrp.cg_frotor = 0;
15894258Smckusic 		cgrp.cg_irotor = 0;
15905325Smckusic 		for (i = 0; i < sblock.fs_frag; i++)
15914465Smckusic 			cgrp.cg_frsum[i] = 0;
15924236Smckusick 		inum = sblock.fs_ipg * c;
15934465Smckusic 		for (i = 0; i < sblock.fs_ipg; inum++, i++) {
15945944Smckusic 			cgrp.cg_cs.cs_nifree++;
15955944Smckusic 			clrbit(cgrp.cg_iused, i);
15964465Smckusic 			dp = ginode();
15974465Smckusic 			if (dp == NULL)
15984465Smckusic 				continue;
15994465Smckusic 			if (ALLOC) {
16005877Smckusic 				if (DIRCT)
16014789Smckusic 					cgrp.cg_cs.cs_ndir++;
16025944Smckusic 				cgrp.cg_cs.cs_nifree--;
16034465Smckusic 				setbit(cgrp.cg_iused, i);
16044465Smckusic 				continue;
16054465Smckusic 			}
16064236Smckusick 		}
16074236Smckusick 		while (i < MAXIPG) {
16084236Smckusick 			clrbit(cgrp.cg_iused, i);
16094236Smckusick 			i++;
16104236Smckusick 		}
16115944Smckusic 		if (c == 0)
16125944Smckusic 			for (i = 0; i < ROOTINO; i++) {
16135944Smckusic 				setbit(cgrp.cg_iused, i);
16145944Smckusic 				cgrp.cg_cs.cs_nifree--;
16155944Smckusic 			}
16165371Smckusic 		for (s = 0; s < MAXCPG; s++) {
16175371Smckusic 			cgrp.cg_btot[s] = 0;
16184236Smckusick 			for (i = 0; i < NRPOS; i++)
16194236Smckusick 				cgrp.cg_b[s][i] = 0;
16205371Smckusic 		}
16214236Smckusick 		if (c == 0) {
16226533Smckusick 			dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
16234236Smckusick 		}
16246533Smckusick 		for (d = dlower; d < dupper; d++)
16254236Smckusick 			clrbit(cgrp.cg_free, d);
16266533Smckusick 		for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
16276533Smckusick 		    d += sblock.fs_frag) {
16284236Smckusick 			j = 0;
16295325Smckusic 			for (i = 0; i < sblock.fs_frag; i++) {
16306533Smckusick 				if (!getbmap(dbase + d + i)) {
16316533Smckusick 					setbit(cgrp.cg_free, d + i);
16324236Smckusick 					j++;
16334236Smckusick 				} else
16344236Smckusick 					clrbit(cgrp.cg_free, d+i);
16354236Smckusick 			}
16365325Smckusic 			if (j == sblock.fs_frag) {
16374789Smckusic 				cgrp.cg_cs.cs_nbfree++;
16385371Smckusic 				cgrp.cg_btot[cbtocylno(&sblock, d)]++;
16395363Smckusic 				cgrp.cg_b[cbtocylno(&sblock, d)]
16405363Smckusic 				    [cbtorpos(&sblock, d)]++;
16414465Smckusic 			} else if (j > 0) {
16424789Smckusic 				cgrp.cg_cs.cs_nffree += j;
16436533Smckusick 				blk = blkmap(&sblock, cgrp.cg_free, d);
16445325Smckusic 				fragacct(&sblock, blk, cgrp.cg_frsum, 1);
16454465Smckusic 			}
16464236Smckusick 		}
16474465Smckusic 		for (j = d; d < dmax - dbase; d++) {
16486533Smckusick 			if (!getbmap(dbase + d)) {
16494236Smckusick 				setbit(cgrp.cg_free, d);
16504789Smckusic 				cgrp.cg_cs.cs_nffree++;
16514236Smckusick 			} else
16524236Smckusick 				clrbit(cgrp.cg_free, d);
16534236Smckusick 		}
16544465Smckusic 		if (j != d) {
16556533Smckusick 			blk = blkmap(&sblock, cgrp.cg_free, j);
16565325Smckusic 			fragacct(&sblock, blk, cgrp.cg_frsum, 1);
16574465Smckusic 		}
16585325Smckusic 		for (; d < MAXBPG(&sblock); d++)
16594236Smckusick 			clrbit(cgrp.cg_free, d);
16604789Smckusic 		sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
16614789Smckusic 		sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
16624789Smckusic 		sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
16634789Smckusic 		sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
16644789Smckusic 		*cs = cgrp.cg_cs;
16655381Smckusic 		bwrite(&dfile, &cgrp, fsbtodb(&sblock, cgtod(&sblock, c)),
16665956Smckusic 		    sblock.fs_cgsize);
16674236Smckusick 	}
16686533Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
16696533Smckusick 		bwrite(&dfile, (char *)sblock.fs_csp[j],
16706533Smckusick 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
16716533Smckusick 		    sblock.fs_cssize - i < sblock.fs_bsize ?
16726533Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize);
16735097Smckusic 	}
16744236Smckusick 	sblock.fs_ronly = 0;
16754236Smckusick 	sblock.fs_fmod = 0;
16764236Smckusick 	sbdirty();
16774236Smckusick }
16784236Smckusick 
16794465Smckusic /*
16804465Smckusic  * update the frsum fields to reflect addition or deletion
16814465Smckusic  * of some frags
16824465Smckusic  */
16835325Smckusic fragacct(fs, fragmap, fraglist, cnt)
16845325Smckusic 	struct fs *fs;
16854470Smckusic 	int fragmap;
16864789Smckusic 	long fraglist[];
16874465Smckusic 	int cnt;
16884465Smckusic {
16894465Smckusic 	int inblk;
16904465Smckusic 	register int field, subfield;
16914465Smckusic 	register int siz, pos;
16924465Smckusic 
16935325Smckusic 	inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
16944465Smckusic 	fragmap <<= 1;
16955325Smckusic 	for (siz = 1; siz < fs->fs_frag; siz++) {
16966290Smckusick 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
16974465Smckusic 			continue;
16984465Smckusic 		field = around[siz];
16994465Smckusic 		subfield = inside[siz];
17005325Smckusic 		for (pos = siz; pos <= fs->fs_frag; pos++) {
17014465Smckusic 			if ((fragmap & field) == subfield) {
17024465Smckusic 				fraglist[siz] += cnt;
17034465Smckusic 				pos += siz;
17044465Smckusic 				field <<= siz;
17054465Smckusic 				subfield <<= siz;
17064465Smckusic 			}
17074465Smckusic 			field <<= 1;
17084465Smckusic 			subfield <<= 1;
17094465Smckusic 		}
17104465Smckusic 	}
17114465Smckusic }
17124465Smckusic 
17134236Smckusick findino(dirp)
17144236Smckusick 	register DIRECT *dirp;
17154236Smckusick {
17164236Smckusick 	if (dirp->d_ino == 0)
17174236Smckusick 		return (KEEPON);
17185877Smckusic 	if (!strcmp(dirp->d_name, srchname)) {
17195877Smckusic 		if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax)
17205877Smckusic 			parentdir = dirp->d_ino;
17215877Smckusic 		return (STOP);
17224236Smckusick 	}
17234236Smckusick 	return (KEEPON);
17244236Smckusick }
17254236Smckusick 
17264236Smckusick mkentry(dirp)
17274236Smckusick 	register DIRECT *dirp;
17284236Smckusick {
17294236Smckusick 	register ino_t in;
17304236Smckusick 	register char *p;
17316251Smckusick 	DIRECT newent;
17326251Smckusick 	int newlen, oldlen;
17334236Smckusick 
17346251Smckusick 	newent.d_namlen = 11;
17356251Smckusick 	newlen = DIRSIZ(&newent);
17366251Smckusick 	if (dirp->d_ino != 0)
17376251Smckusick 		oldlen = DIRSIZ(dirp);
17386251Smckusick 	else
17396251Smckusick 		oldlen = 0;
17406251Smckusick 	if (dirp->d_reclen - oldlen < newlen)
17414236Smckusick 		return (KEEPON);
17426251Smckusick 	newent.d_reclen = dirp->d_reclen - oldlen;
17436251Smckusick 	dirp->d_reclen = oldlen;
17446251Smckusick 	dirp = (struct direct *)(((char *)dirp) + oldlen);
17454236Smckusick 	dirp->d_ino = orphan;
17466251Smckusick 	dirp->d_reclen = newent.d_reclen;
17476251Smckusick 	p = &dirp->d_name[2];
17486251Smckusick 	for (in = imax; in > 0; in /= 10)
17496251Smckusick 		p++;
17506251Smckusick 	*--p = 0;
17516251Smckusick 	dirp->d_namlen = p - dirp->d_name;
17524236Smckusick 	in = orphan;
17534236Smckusick 	while (p > dirp->d_name) {
17544236Smckusick 		*--p = (in % 10) + '0';
17554236Smckusick 		in /= 10;
17564236Smckusick 	}
17574236Smckusick 	*p = '#';
17584236Smckusick 	return (ALTERD|STOP);
17594236Smckusick }
17604236Smckusick 
17614236Smckusick chgdd(dirp)
17624236Smckusick 	register DIRECT *dirp;
17634236Smckusick {
17644236Smckusick 	if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' &&
17654236Smckusick 	dirp->d_name[2] == 0) {
17664236Smckusick 		dirp->d_ino = lfdir;
17674236Smckusick 		return (ALTERD|STOP);
17684236Smckusick 	}
17694236Smckusick 	return (KEEPON);
17704236Smckusick }
17714236Smckusick 
17724236Smckusick linkup()
17734236Smckusick {
17744236Smckusick 	register DINODE *dp;
17754236Smckusick 	register lostdir;
17764236Smckusick 	register ino_t pdir;
17774236Smckusick 
17784236Smckusick 	if ((dp = ginode()) == NULL)
17794236Smckusick 		return (0);
17805877Smckusic 	lostdir = DIRCT;
17814236Smckusick 	pdir = parentdir;
17824236Smckusick 	pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
17834236Smckusick 	pinode();
17844236Smckusick 	if (preen && dp->di_size == 0)
17854236Smckusick 		return (0);
17864236Smckusick 	if (preen)
17874236Smckusick 		printf(" (RECONNECTED)\n");
17884236Smckusick 	else
17894236Smckusick 		if (reply("RECONNECT") == 0)
17904236Smckusick 			return (0);
17914236Smckusick 	orphan = inum;
17924236Smckusick 	if (lfdir == 0) {
17934236Smckusick 		inum = ROOTINO;
17944236Smckusick 		if ((dp = ginode()) == NULL) {
17954236Smckusick 			inum = orphan;
17964236Smckusick 			return (0);
17974236Smckusick 		}
17984236Smckusick 		pfunc = findino;
17994236Smckusick 		srchname = lfname;
18004236Smckusick 		filsize = dp->di_size;
18014236Smckusick 		parentdir = 0;
18024236Smckusick 		ckinode(dp, DATA);
18034236Smckusick 		inum = orphan;
18044236Smckusick 		if ((lfdir = parentdir) == 0) {
18054236Smckusick 			pfatal("SORRY. NO lost+found DIRECTORY");
18064236Smckusick 			printf("\n\n");
18074236Smckusick 			return (0);
18084236Smckusick 		}
18094236Smckusick 	}
18104236Smckusick 	inum = lfdir;
18115877Smckusic 	if ((dp = ginode()) == NULL || !DIRCT || getstate() != FSTATE) {
18124236Smckusick 		inum = orphan;
18134236Smckusick 		pfatal("SORRY. NO lost+found DIRECTORY");
18144236Smckusick 		printf("\n\n");
18154236Smckusick 		return (0);
18164236Smckusick 	}
18175956Smckusic 	if (fragoff(&sblock, dp->di_size)) {
18185956Smckusic 		dp->di_size = fragroundup(&sblock, dp->di_size);
18194236Smckusick 		inodirty();
18204236Smckusick 	}
18214236Smckusick 	filsize = dp->di_size;
18224236Smckusick 	inum = orphan;
18234236Smckusick 	pfunc = mkentry;
18244236Smckusick 	if ((ckinode(dp, DATA) & ALTERD) == 0) {
18254236Smckusick 		pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
18264236Smckusick 		printf("\n\n");
18274236Smckusick 		return (0);
18284236Smckusick 	}
18294236Smckusick 	declncnt();
18304236Smckusick 	if (lostdir) {
18314236Smckusick 		pfunc = chgdd;
18324236Smckusick 		dp = ginode();
18334236Smckusick 		filsize = dp->di_size;
18344236Smckusick 		ckinode(dp, DATA);
18354236Smckusick 		inum = lfdir;
18364236Smckusick 		if ((dp = ginode()) != NULL) {
18374236Smckusick 			dp->di_nlink++;
18384236Smckusick 			inodirty();
18394236Smckusick 			setlncnt(getlncnt()+1);
18404236Smckusick 		}
18414236Smckusick 		inum = orphan;
18424236Smckusick 		pwarn("DIR I=%u CONNECTED. ", orphan);
18434236Smckusick 		printf("PARENT WAS I=%u\n", pdir);
18444236Smckusick 		if (preen == 0)
18454236Smckusick 			printf("\n");
18464236Smckusick 	}
18474236Smckusick 	return (1);
18484236Smckusick }
18494236Smckusick 
18504236Smckusick bread(fcp, buf, blk, size)
18514236Smckusick 	daddr_t blk;
18524236Smckusick 	register struct filecntl *fcp;
18534236Smckusick 	register size;
18544236Smckusick 	char *buf;
18554236Smckusick {
18565325Smckusic 	if (lseek(fcp->rfdes, blk * DEV_BSIZE, 0) < 0)
18574236Smckusick 		rwerr("SEEK", blk);
18584236Smckusick 	else if (read(fcp->rfdes, buf, size) == size)
18594236Smckusick 		return (1);
18604236Smckusick 	rwerr("READ", blk);
18614236Smckusick 	return (0);
18624236Smckusick }
18634236Smckusick 
18644236Smckusick bwrite(fcp, buf, blk, size)
18654236Smckusick 	daddr_t blk;
18664236Smckusick 	register struct filecntl *fcp;
18674236Smckusick 	register size;
18684236Smckusick 	char *buf;
18694236Smckusick {
18704236Smckusick 
18714236Smckusick 	if (fcp->wfdes < 0)
18724236Smckusick 		return (0);
18735325Smckusic 	if (lseek(fcp->wfdes, blk * DEV_BSIZE, 0) < 0)
18744236Smckusick 		rwerr("SEEK", blk);
18754236Smckusick 	else if (write(fcp->wfdes, buf, size) == size) {
18764236Smckusick 		fcp->mod = 1;
18774236Smckusick 		return (1);
18784236Smckusick 	}
18794236Smckusick 	rwerr("WRITE", blk);
18804236Smckusick 	return (0);
18814236Smckusick }
18824236Smckusick 
18834236Smckusick catch()
18844236Smckusick {
18854236Smckusick 
18864236Smckusick 	ckfini();
18874236Smckusick 	exit(12);
18884236Smckusick }
18895325Smckusic 
18905325Smckusic /*
18915325Smckusic  * block operations
18925325Smckusic  */
18935325Smckusic 
18945325Smckusic isblock(fs, cp, h)
18955325Smckusic 	struct fs *fs;
18965325Smckusic 	unsigned char *cp;
18975325Smckusic 	int h;
18985325Smckusic {
18995325Smckusic 	unsigned char mask;
19005325Smckusic 
19015325Smckusic 	switch (fs->fs_frag) {
19025325Smckusic 	case 8:
19035325Smckusic 		return (cp[h] == 0xff);
19045325Smckusic 	case 4:
19055325Smckusic 		mask = 0x0f << ((h & 0x1) << 2);
19065325Smckusic 		return ((cp[h >> 1] & mask) == mask);
19075325Smckusic 	case 2:
19085325Smckusic 		mask = 0x03 << ((h & 0x3) << 1);
19095325Smckusic 		return ((cp[h >> 2] & mask) == mask);
19105325Smckusic 	case 1:
19115325Smckusic 		mask = 0x01 << (h & 0x7);
19125325Smckusic 		return ((cp[h >> 3] & mask) == mask);
19135325Smckusic 	default:
19145381Smckusic 		error("isblock bad fs_frag %d\n", fs->fs_frag);
19155381Smckusic 		return (0);
19165325Smckusic 	}
19175325Smckusic }
19186489Smckusick 
19196489Smckusick /*	tables.c	4.1	82/03/25	*/
19206489Smckusick 
19216489Smckusick /* merged into kernel:	tables.c 2.1 3/25/82 */
19226489Smckusick 
19236489Smckusick /* last monet version:	partab.c	4.2	81/03/08	*/
19246489Smckusick 
19256489Smckusick /*
19266489Smckusick  * bit patterns for identifying fragments in the block map
19276489Smckusick  * used as ((map & around) == inside)
19286489Smckusick  */
19296489Smckusick int around[9] = {
19306489Smckusick 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
19316489Smckusick };
19326489Smckusick int inside[9] = {
19336489Smckusick 	0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
19346489Smckusick };
19356489Smckusick 
19366489Smckusick /*
19376489Smckusick  * given a block map bit pattern, the frag tables tell whether a
19386489Smckusick  * particular size fragment is available.
19396489Smckusick  *
19406489Smckusick  * used as:
19416489Smckusick  * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
19426489Smckusick  *	at least one fragment of the indicated size is available
19436489Smckusick  * }
19446489Smckusick  *
19456489Smckusick  * These tables are used by the scanc instruction on the VAX to
19466489Smckusick  * quickly find an appropriate fragment.
19476489Smckusick  */
19486489Smckusick 
19496489Smckusick unsigned char fragtbl124[256] = {
19506489Smckusick 	0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
19516489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
19526489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19536489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19546489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19556489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19566489Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
19576489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
19586489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19596489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19606489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19616489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19626489Smckusick 	0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
19636489Smckusick 	0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
19646489Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
19656489Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
19666489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19676489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19686489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19696489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19706489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
19716489Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
19726489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
19736489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
19746489Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
19756489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
19766489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
19776489Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
19786489Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
19796489Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
19806489Smckusick 	0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
19816489Smckusick 	0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
19826489Smckusick };
19836489Smckusick 
19846489Smckusick unsigned char fragtbl8[256] = {
19856489Smckusick 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
19866489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
19876489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
19886489Smckusick 	0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
19896489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
19906489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
19916489Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
19926489Smckusick 	0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
19936489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
19946489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
19956489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
19966489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
19976489Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
19986489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
19996489Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
20006489Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
20016489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
20026489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
20036489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
20046489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
20056489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
20066489Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
20076489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
20086489Smckusick 	0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
20096489Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
20106489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
20116489Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
20126489Smckusick 	0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
20136489Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
20146489Smckusick 	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
20156489Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
20166489Smckusick 	0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
20176489Smckusick };
20186489Smckusick 
20196489Smckusick /*
20206489Smckusick  * the actual fragtbl array
20216489Smckusick  */
20226489Smckusick unsigned char *fragtbl[MAXFRAG + 1] = {
20236489Smckusick 	0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
20246489Smckusick };
2025