xref: /csrg-svn/sbin/icheck/icheck.c (revision 9298)
1*9298Smckusick static	char *sccsid = "@(#)icheck.c	2.4 (Berkeley) 11/18/82";
24410Smckusic 
34240Smckusick /*
44240Smckusick  * icheck
54240Smckusick  */
64240Smckusick #define	NB	500
74240Smckusick #define	MAXFN	500
85349Smckusic #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
94240Smckusick 
104240Smckusick #ifndef STANDALONE
114240Smckusick #include <stdio.h>
124240Smckusick #endif
136490Smckusick #ifndef SIMFS
146490Smckusick #include <sys/param.h>
156490Smckusick #include <sys/inode.h>
166490Smckusick #include <sys/fs.h>
176490Smckusick #else
184240Smckusick #include "../h/param.h"
194240Smckusick #include "../h/inode.h"
204240Smckusick #include "../h/fs.h"
216490Smckusick #endif
224240Smckusick 
234240Smckusick union {
244240Smckusick 	struct	fs sb;
255326Smckusic 	char pad[MAXBSIZE];
264240Smckusick } sbun;
274240Smckusick #define	sblock sbun.sb
284240Smckusick 
294240Smckusick union {
304240Smckusick 	struct	cg cg;
315326Smckusic 	char pad[MAXBSIZE];
324240Smckusick } cgun;
334240Smckusick #define	cgrp cgun.cg
344240Smckusick 
354240Smckusick struct	dinode	itab[MAXIPG];
364240Smckusick daddr_t	blist[NB];
37*9298Smckusick daddr_t	fsblist[NB];
384240Smckusick char	*bmap;
394240Smckusick 
404240Smckusick int	mflg;
415098Smckusic int	sflg;
424240Smckusick int	dflg;
434240Smckusick int	fi;
444240Smckusick ino_t	ino;
454240Smckusick int	cginit;
464240Smckusick 
474240Smckusick ino_t	nrfile;
484240Smckusick ino_t	ndfile;
494240Smckusick ino_t	nbfile;
504240Smckusick ino_t	ncfile;
516286Smckusick ino_t	nlfile;
524240Smckusick 
534240Smckusick daddr_t	nblock;
544240Smckusick daddr_t	nfrag;
554240Smckusick daddr_t	nindir;
564240Smckusick daddr_t	niindir;
574240Smckusick 
584240Smckusick daddr_t	nffree;
594240Smckusick daddr_t	nbfree;
604240Smckusick 
614240Smckusick daddr_t	ndup;
624240Smckusick 
634240Smckusick int	nerror;
644240Smckusick 
655098Smckusic extern int inside[], around[];
665326Smckusic extern unsigned char *fragtbl[];
675098Smckusic 
684240Smckusick long	atol();
694240Smckusick #ifndef STANDALONE
704240Smckusick char	*malloc();
715098Smckusic char	*calloc();
724240Smckusick #endif
734240Smckusick 
744240Smckusick main(argc, argv)
755098Smckusic 	int argc;
765098Smckusic 	char *argv[];
774240Smckusick {
784240Smckusick 	register i;
794240Smckusick 	long n;
804240Smckusick 
814240Smckusick 	blist[0] = -1;
824240Smckusick #ifndef STANDALONE
834240Smckusick 	while (--argc) {
844240Smckusick 		argv++;
854240Smckusick 		if (**argv=='-')
864240Smckusick 		switch ((*argv)[1]) {
874240Smckusick 		case 'd':
884240Smckusick 			dflg++;
894240Smckusick 			continue;
904240Smckusick 
914240Smckusick 		case 'm':
924240Smckusick 			mflg++;
934240Smckusick 			continue;
944240Smckusick 
955098Smckusic 		case 's':
965098Smckusic 			sflg++;
975098Smckusic 			continue;
985098Smckusic 
994240Smckusick 		case 'b':
1004240Smckusick 			for(i=0; i<NB; i++) {
1014240Smckusick 				n = atol(argv[1]);
1024240Smckusick 				if(n == 0)
1034240Smckusick 					break;
1044240Smckusick 				blist[i] = n;
1054240Smckusick 				argv++;
1064240Smckusick 				argc--;
1074240Smckusick 			}
1084240Smckusick 			blist[i] = -1;
1094240Smckusick 			continue;
1104240Smckusick 
1114240Smckusick 		default:
1124240Smckusick 			printf("Bad flag\n");
1134240Smckusick 		}
1144240Smckusick 		check(*argv);
1154240Smckusick 	}
1164240Smckusick #else
1174240Smckusick 	{
1184240Smckusick 		static char fname[128];
1194240Smckusick 
1204240Smckusick 		printf("File: ");
1214240Smckusick 		gets(fname);
1224240Smckusick 		check(fname);
1234240Smckusick 	}
1244240Smckusick #endif
1254240Smckusick 	return(nerror);
1264240Smckusick }
1274240Smckusick 
1284240Smckusick check(file)
1295098Smckusic 	char *file;
1304240Smckusick {
1314240Smckusick 	register i, j, c;
1324240Smckusick 	daddr_t d, cgd, cbase, b;
1334240Smckusick 	long n;
134*9298Smckusick 	char buf[BUFSIZ];
1354240Smckusick 
1365098Smckusic 	fi = open(file, sflg ? 2 : 0);
1374240Smckusick 	if (fi < 0) {
1385098Smckusic 		perror(file);
1394240Smckusick 		nerror |= 04;
1404240Smckusick 		return;
1414240Smckusick 	}
1424240Smckusick 	printf("%s:\n", file);
1434240Smckusick 	nrfile = 0;
1444240Smckusick 	ndfile = 0;
1454240Smckusick 	ncfile = 0;
1464240Smckusick 	nbfile = 0;
1476286Smckusick 	nlfile = 0;
1484240Smckusick 
1494240Smckusick 	nblock = 0;
1504240Smckusick 	nfrag = 0;
1514240Smckusick 	nindir = 0;
1524240Smckusick 	niindir = 0;
1534240Smckusick 
1544240Smckusick 	ndup = 0;
1554240Smckusick #ifndef STANDALONE
1564240Smckusick 	sync();
1574240Smckusick #endif
1585326Smckusic 	getsb(&sblock, file);
1595326Smckusic 	if (nerror)
1604240Smckusick 		return;
161*9298Smckusick 	for (n=0; blist[n] != -1; n++)
162*9298Smckusick 		fsblist[n] = dbtofsb(&sblock, blist[n]);
1634240Smckusick 	ino = 0;
1645098Smckusic 	n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
1654240Smckusick #ifdef STANDALONE
1664240Smckusick 	bmap = NULL;
1674240Smckusick #else
1684240Smckusick 	bmap = malloc((unsigned)n);
1694240Smckusick #endif
1704240Smckusick 	if (bmap==NULL) {
1714240Smckusick 		printf("Not enough core; duplicates unchecked\n");
1724240Smckusick 		dflg++;
1735098Smckusic 		if (sflg) {
1745098Smckusic 			printf("No Updates\n");
1755098Smckusic 			sflg = 0;
1765098Smckusic 		}
1774240Smckusick 	}
1784240Smckusick 	ino = 0;
1794240Smckusick 	cginit = 1;
1806534Smckusick 	if (!dflg) {
1816534Smckusick 		for (i = 0; i < (unsigned)n; i++)
1824240Smckusick 			bmap[i] = 0;
1836534Smckusick 		for (c = 0; c < sblock.fs_ncg; c++) {
1845382Smckusic 			cgd = cgtod(&sblock, c);
1856534Smckusick 			if (c == 0)
1866534Smckusick 				d = cgbase(&sblock, c);
1876534Smckusick 			else
1886534Smckusick 				d = cgsblock(&sblock, c);
189*9298Smckusick 			sprintf(buf, "spare super block %d", c);
1906534Smckusick 			for (; d < cgd; d += sblock.fs_frag)
191*9298Smckusick 				chk(d, buf, sblock.fs_bsize);
1925382Smckusic 			d = cgimin(&sblock, c);
193*9298Smckusick 			sprintf(buf, "cylinder group %d", c);
1944240Smckusick 			while (cgd < d) {
195*9298Smckusick 				chk(cgd, buf, sblock.fs_bsize);
1965326Smckusic 				cgd += sblock.fs_frag;
1974240Smckusick 			}
1985382Smckusic 			d = cgdmin(&sblock, c);
199*9298Smckusick 			i = INOPB(&sblock);
200*9298Smckusick 			for (; cgd < d; cgd += sblock.fs_frag) {
201*9298Smckusick 				sprintf(buf, "inodes %d-%d", ino, ino + i);
202*9298Smckusick 				chk(cgd, buf, sblock.fs_bsize);
203*9298Smckusick 				ino += i;
204*9298Smckusick 			}
2054240Smckusick 			if (c == 0) {
2066534Smckusick 				d += howmany(sblock.fs_cssize, sblock.fs_fsize);
2076534Smckusick 				for (; cgd < d; cgd++)
2086534Smckusick 					chk(cgd, "csum", sblock.fs_fsize);
2094240Smckusick 			}
2104240Smckusick 		}
2114240Smckusick 	}
212*9298Smckusick 	ino = 0;
2134240Smckusick 	cginit = 0;
2144240Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
2155382Smckusic 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
2164240Smckusick 		    sblock.fs_ipg * sizeof (struct dinode));
2174240Smckusick 		for (j=0; j < sblock.fs_ipg; j++) {
2184240Smckusick 			pass1(&itab[j]);
2194240Smckusick 			ino++;
2204240Smckusick 		}
2214240Smckusick 	}
2224240Smckusick 	ino = 0;
2234240Smckusick #ifndef STANDALONE
2244240Smckusick 	sync();
2254240Smckusick #endif
2265098Smckusic 	if (sflg) {
2275098Smckusic 		makecg();
2285098Smckusic 		close(fi);
2295098Smckusic #ifndef STANDALONE
2305098Smckusic 		if (bmap)
2315098Smckusic 			free(bmap);
2325098Smckusic #endif
2335098Smckusic 		return;
2345098Smckusic 	}
2354240Smckusick 	nffree = 0;
2364240Smckusick 	nbfree = 0;
2374240Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
2385382Smckusic 		cbase = cgbase(&sblock, c);
2395382Smckusic 		bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp,
2405326Smckusic 			sblock.fs_cgsize);
2416534Smckusick 		if (cgrp.cg_magic != CG_MAGIC)
2426534Smckusick 			printf("cg %d: bad magic number\n", c);
2435326Smckusic 		for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
2445326Smckusic 			if (isblock(&sblock, cgrp.cg_free,
2455326Smckusic 			    b / sblock.fs_frag)) {
2464240Smckusick 				nbfree++;
247*9298Smckusick 				chk(cbase+b, "free block", sblock.fs_bsize);
2484240Smckusick 			} else {
2495326Smckusic 				for (d = 0; d < sblock.fs_frag; d++)
2504240Smckusick 					if (isset(cgrp.cg_free, b+d)) {
251*9298Smckusick 						chk(cbase+b+d, "free frag", sblock.fs_fsize);
2524240Smckusick 						nffree++;
2534240Smckusick 					}
2544240Smckusick 			}
2554240Smckusick 		}
2564240Smckusick 	}
2574240Smckusick 	close(fi);
2584240Smckusick #ifndef STANDALONE
2594240Smckusick 	if (bmap)
2604240Smckusick 		free(bmap);
2614240Smckusick #endif
2624240Smckusick 
2636286Smckusick 	i = nrfile + ndfile + ncfile + nbfile + nlfile;
2644240Smckusick #ifndef STANDALONE
2656286Smckusick 	printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
2666286Smckusick 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
2674240Smckusick #else
2686286Smckusick 	printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
2696286Smckusick 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
2704240Smckusick #endif
2715326Smckusic 	n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
2724240Smckusick #ifdef STANDALONE
2734240Smckusick 	printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
2744240Smckusick 		n, nindir, niindir, nblock, nfrag);
2755326Smckusic 	printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
2764240Smckusick 	    nbfree, nffree);
2774240Smckusick #else
2784240Smckusick 	printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
2794240Smckusick 		n, nindir, niindir, nblock, nfrag);
2805326Smckusic 	printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
2814240Smckusick 	    nbfree, nffree);
2824240Smckusick #endif
2834240Smckusick 	if(!dflg) {
2844240Smckusick 		n = 0;
2854410Smckusic 		for (d = 0; d < sblock.fs_size; d++)
2865326Smckusic 			if(!duped(d, sblock.fs_fsize)) {
2874240Smckusick 				if(mflg)
2884240Smckusick 					printf("%ld missing\n", d);
2894240Smckusick 				n++;
2904240Smckusick 			}
2914240Smckusick 		printf("missing%5ld\n", n);
2924240Smckusick 	}
2934240Smckusick }
2944240Smckusick 
2954240Smckusick pass1(ip)
2964410Smckusic 	register struct dinode *ip;
2974240Smckusick {
2985326Smckusic 	daddr_t ind1[MAXNINDIR];
2995326Smckusic 	daddr_t ind2[MAXNINDIR];
3004429Smckusic 	daddr_t db, ib;
3014429Smckusic 	register int i, j, k, siz;
302*9298Smckusick 	int lbn;
303*9298Smckusick 	char buf[BUFSIZ];
3044240Smckusick 
3054240Smckusick 	i = ip->di_mode & IFMT;
3064790Smckusic 	if(i == 0)
3074240Smckusick 		return;
3084240Smckusick 	switch (i) {
3094240Smckusick 	case IFCHR:
3104240Smckusick 		ncfile++;
3114240Smckusick 		return;
3124240Smckusick 	case IFBLK:
3134240Smckusick 		nbfile++;
3144240Smckusick 		return;
3154240Smckusick 	case IFDIR:
3164240Smckusick 		ndfile++;
3174240Smckusick 		break;
3184240Smckusick 	case IFREG:
3194240Smckusick 		nrfile++;
3204240Smckusick 		break;
3216286Smckusick 	case IFLNK:
3226286Smckusick 		nlfile++;
3236286Smckusick 		break;
3244240Smckusick 	default:
3254240Smckusick 		printf("bad mode %u\n", ino);
3264240Smckusick 		return;
3274240Smckusick 	}
3284410Smckusic 	for (i = 0; i < NDADDR; i++) {
3294410Smckusic 		db = ip->di_db[i];
3304410Smckusic 		if (db == 0)
3314240Smckusick 			continue;
3325326Smckusic 		siz = dblksize(&sblock, ip, i);
333*9298Smckusick 		sprintf(buf, "logical data block %d", i);
334*9298Smckusick 		chk(db, buf, siz);
3355326Smckusic 		if (siz == sblock.fs_bsize)
3364429Smckusic 			nblock++;
3374429Smckusic 		else
3385326Smckusic 			nfrag += howmany(siz, sblock.fs_fsize);
3394240Smckusick 	}
3404410Smckusic 	for(i = 0; i < NIADDR; i++) {
3414410Smckusic 		ib = ip->di_ib[i];
342*9298Smckusick 		if (ib == 0)
3434240Smckusick 			continue;
3445326Smckusic 		if (chk(ib, "1st indirect", sblock.fs_bsize))
3454410Smckusic 			continue;
3465326Smckusic 		bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize);
3474240Smckusick 		nindir++;
3485326Smckusic 		for (j = 0; j < NINDIR(&sblock); j++) {
3494410Smckusic 			ib = ind1[j];
3504410Smckusic 			if (ib == 0)
3514240Smckusick 				continue;
3524410Smckusic 			if (i == 0) {
353*9298Smckusick 				lbn = NDADDR + j;
354*9298Smckusick 				siz = dblksize(&sblock, ip, lbn);
355*9298Smckusick 				sprintf(buf, "logical data block %d", lbn);
356*9298Smckusick 				chk(ib, buf, siz);
3575326Smckusic 				if (siz == sblock.fs_bsize)
3584429Smckusic 					nblock++;
3594429Smckusic 				else
3605326Smckusic 					nfrag += howmany(siz, sblock.fs_fsize);
3614240Smckusick 				continue;
3624240Smckusick 			}
3635326Smckusic 			if (chk(ib, "2nd indirect", sblock.fs_bsize))
3644410Smckusic 				continue;
3655326Smckusic 			bread(fsbtodb(&sblock, ib), (char *)ind2,
3665326Smckusic 				sblock.fs_bsize);
3674240Smckusick 			niindir++;
3685326Smckusic 			for (k = 0; k < NINDIR(&sblock); k++) {
3694410Smckusic 				ib = ind2[k];
3704410Smckusic 				if (ib == 0)
3714240Smckusick 					continue;
372*9298Smckusick 				lbn = NDADDR + NINDIR(&sblock) * (i + j) + k;
373*9298Smckusick 				siz = dblksize(&sblock, ip, lbn);
374*9298Smckusick 				sprintf(buf, "logical data block %d", lbn);
375*9298Smckusick 				chk(ib, buf, siz);
3765326Smckusic 				if (siz == sblock.fs_bsize)
3774429Smckusic 					nblock++;
3784429Smckusic 				else
3795326Smckusic 					nfrag += howmany(siz, sblock.fs_fsize);
3804240Smckusick 			}
3814240Smckusick 		}
3824240Smckusick 	}
3834240Smckusick }
3844240Smckusick 
3854429Smckusic chk(bno, s, size)
3864410Smckusic 	daddr_t bno;
3874410Smckusic 	char *s;
3884429Smckusic 	int size;
3894240Smckusick {
3904240Smckusick 	register n, cg;
3915957Smckusic 	int frags;
3924240Smckusick 
3935382Smckusic 	cg = dtog(&sblock, bno);
3946534Smckusick 	if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) {
3954240Smckusick 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
3964240Smckusick 		return(1);
3974240Smckusick 	}
398*9298Smckusick 	frags = numfrags(&sblock, size);
399*9298Smckusick 	if (frags == sblock.fs_frag) {
4004429Smckusic 		if (duped(bno, size)) {
4014429Smckusic 			printf("%ld dup block; inode=%u, class=%s\n",
4024429Smckusic 			    bno, ino, s);
4035326Smckusic 			ndup += sblock.fs_frag;
4044429Smckusic 		}
4054429Smckusic 	} else {
4065957Smckusic 		for (n = 0; n < frags; n++) {
4075326Smckusic 			if (duped(bno + n, sblock.fs_fsize)) {
4084429Smckusic 				printf("%ld dup frag; inode=%u, class=%s\n",
4094429Smckusic 				    bno, ino, s);
4104429Smckusic 				ndup++;
4114429Smckusic 			}
4124429Smckusic 		}
4134240Smckusick 	}
4144240Smckusick 	for (n=0; blist[n] != -1; n++)
415*9298Smckusick 		if (fsblist[n] >= bno && fsblist[n] < bno + frags)
416*9298Smckusick 			printf("%ld arg; frag %d of %d, inode=%u, class=%s\n",
417*9298Smckusick 				blist[n], fsblist[n] - bno, frags, ino, s);
4184240Smckusick 	return(0);
4194240Smckusick }
4204240Smckusick 
4214429Smckusic duped(bno, size)
4224410Smckusic 	daddr_t bno;
4234429Smckusic 	int size;
4244240Smckusick {
4254240Smckusick 	if(dflg)
4264240Smckusick 		return(0);
4275326Smckusic 	if (size != sblock.fs_fsize && size != sblock.fs_bsize)
4284429Smckusic 		printf("bad size %d to duped\n", size);
4295326Smckusic 	if (size == sblock.fs_fsize) {
4304410Smckusic 		if (isset(bmap, bno))
4314410Smckusic 			return(1);
4324410Smckusic 		setbit(bmap, bno);
4334410Smckusic 		return (0);
4344410Smckusic 	}
4355326Smckusic 	if (bno % sblock.fs_frag != 0)
4364410Smckusic 		printf("bad bno %d to duped\n", bno);
4375326Smckusic 	if (isblock(&sblock, bmap, bno/sblock.fs_frag))
4384410Smckusic 		return (1);
4395326Smckusic 	setblock(&sblock, bmap, bno/sblock.fs_frag);
4404240Smckusick 	return(0);
4414240Smckusick }
4424240Smckusick 
4435098Smckusic makecg()
4445098Smckusic {
4455098Smckusic 	int c, blk;
4466534Smckusick 	daddr_t dbase, d, dlower, dupper, dmax;
4475098Smckusic 	long i, j, s;
4485098Smckusic 	register struct csum *cs;
4495098Smckusic 	register struct dinode *dp;
4505098Smckusic 
4515098Smckusic 	sblock.fs_cstotal.cs_nbfree = 0;
4525098Smckusic 	sblock.fs_cstotal.cs_nffree = 0;
4535098Smckusic 	sblock.fs_cstotal.cs_nifree = 0;
4545098Smckusic 	sblock.fs_cstotal.cs_ndir = 0;
4555098Smckusic 	for (c = 0; c < sblock.fs_ncg; c++) {
4565382Smckusic 		dbase = cgbase(&sblock, c);
4575098Smckusic 		dmax = dbase + sblock.fs_fpg;
4585410Smckusic 		if (dmax > sblock.fs_size) {
4595410Smckusic 			for ( ; dmax >= sblock.fs_size; dmax--)
4605400Smckusic 				clrbit(cgrp.cg_free, dmax - dbase);
4615410Smckusic 			dmax++;
4625410Smckusic 		}
4636534Smckusick 		dlower = cgsblock(&sblock, c) - dbase;
4646534Smckusick 		dupper = cgdmin(&sblock, c) - dbase;
4655326Smckusic 		cs = &sblock.fs_cs(&sblock, c);
4665098Smckusic 		cgrp.cg_time = time(0);
4675098Smckusic 		cgrp.cg_magic = CG_MAGIC;
4685098Smckusic 		cgrp.cg_cgx = c;
4698143Smckusick 		if (c == sblock.fs_ncg - 1)
4708143Smckusick 			cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
4718143Smckusick 		else
4728143Smckusick 			cgrp.cg_ncyl = sblock.fs_cpg;
4735098Smckusic 		cgrp.cg_niblk = sblock.fs_ipg;
4745098Smckusic 		cgrp.cg_ndblk = dmax - dbase;
4755098Smckusic 		cgrp.cg_cs.cs_ndir = 0;
4765098Smckusic 		cgrp.cg_cs.cs_nffree = 0;
4775098Smckusic 		cgrp.cg_cs.cs_nbfree = 0;
4785098Smckusic 		cgrp.cg_cs.cs_nifree = 0;
4796534Smckusick 		cgrp.cg_rotor = 0;
4806534Smckusick 		cgrp.cg_frotor = 0;
4815098Smckusic 		cgrp.cg_irotor = 0;
4825326Smckusic 		for (i = 0; i < sblock.fs_frag; i++)
4835098Smckusic 			cgrp.cg_frsum[i] = 0;
4845382Smckusic 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
4855098Smckusic 		      sblock.fs_ipg * sizeof(struct dinode));
4865098Smckusic 		for (i = 0; i < sblock.fs_ipg; i++) {
4875945Smckusic 			cgrp.cg_cs.cs_nifree++;
4885945Smckusic 			clrbit(cgrp.cg_iused, i);
4895098Smckusic 			dp = &itab[i];
4905098Smckusic 			if ((dp->di_mode & IFMT) != 0) {
4915098Smckusic 				if ((dp->di_mode & IFMT) == IFDIR)
4925098Smckusic 					cgrp.cg_cs.cs_ndir++;
4935945Smckusic 				cgrp.cg_cs.cs_nifree--;
4945098Smckusic 				setbit(cgrp.cg_iused, i);
4955098Smckusic 				continue;
4965098Smckusic 			}
4975098Smckusic 		}
4985098Smckusic 		while (i < MAXIPG) {
4995098Smckusic 			clrbit(cgrp.cg_iused, i);
5005098Smckusic 			i++;
5015098Smckusic 		}
5025338Smckusic 		if (c == 0)
5035338Smckusic 			for (i = 0; i < ROOTINO; i++) {
5045338Smckusic 				setbit(cgrp.cg_iused, i);
5055338Smckusic 				cgrp.cg_cs.cs_nifree--;
5065338Smckusic 			}
5075372Smckusic 		for (s = 0; s < MAXCPG; s++) {
5085372Smckusic 			cgrp.cg_btot[s] = 0;
5095098Smckusic 			for (i = 0; i < NRPOS; i++)
5105098Smckusic 				cgrp.cg_b[s][i] = 0;
5115372Smckusic 		}
5125098Smckusic 		if (c == 0) {
5136534Smckusick 			dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
5145098Smckusic 		}
5156534Smckusick 		for (d = dlower; d < dupper; d++)
5165098Smckusic 			clrbit(cgrp.cg_free, d);
5176534Smckusick 		for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
5186534Smckusick 		    d += sblock.fs_frag) {
5195098Smckusic 			j = 0;
5205326Smckusic 			for (i = 0; i < sblock.fs_frag; i++) {
5216534Smckusick 				if (!isset(bmap, dbase + d + i)) {
5226534Smckusick 					setbit(cgrp.cg_free, d + i);
5235098Smckusic 					j++;
5245098Smckusic 				} else
5255098Smckusic 					clrbit(cgrp.cg_free, d+i);
5265098Smckusic 			}
5275326Smckusic 			if (j == sblock.fs_frag) {
5285098Smckusic 				cgrp.cg_cs.cs_nbfree++;
5295372Smckusic 				cgrp.cg_btot[cbtocylno(&sblock, d)]++;
5305364Smckusic 				cgrp.cg_b[cbtocylno(&sblock, d)]
5315364Smckusic 				    [cbtorpos(&sblock, d)]++;
5325098Smckusic 			} else if (j > 0) {
5335098Smckusic 				cgrp.cg_cs.cs_nffree += j;
5346534Smckusick 				blk = blkmap(&sblock, cgrp.cg_free, d);
5355326Smckusic 				fragacct(&sblock, blk, cgrp.cg_frsum, 1);
5365098Smckusic 			}
5375098Smckusic 		}
5385098Smckusic 		for (j = d; d < dmax - dbase; d++) {
5396534Smckusick 			if (!isset(bmap, dbase + d)) {
5405098Smckusic 				setbit(cgrp.cg_free, d);
5415098Smckusic 				cgrp.cg_cs.cs_nffree++;
5425098Smckusic 			} else
5435098Smckusic 				clrbit(cgrp.cg_free, d);
5445098Smckusic 		}
5458143Smckusick 		for (; d % sblock.fs_frag != 0; d++)
5468143Smckusick 			clrbit(cgrp.cg_free, d);
5475098Smckusic 		if (j != d) {
5486534Smckusick 			blk = blkmap(&sblock, cgrp.cg_free, j);
5495326Smckusic 			fragacct(&sblock, blk, cgrp.cg_frsum, 1);
5505098Smckusic 		}
5518143Smckusick 		for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
5528143Smckusick 			clrblock(&sblock, cgrp.cg_free, d);
5535098Smckusic 		sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
5545098Smckusic 		sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
5555098Smckusic 		sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
5565098Smckusic 		sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
5575098Smckusic 		*cs = cgrp.cg_cs;
5585382Smckusic 		bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp,
5595326Smckusic 			sblock.fs_cgsize);
5605098Smckusic 	}
5616534Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
5626534Smckusick 		bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
5636534Smckusick 		    (char *)sblock.fs_csp[j],
5646534Smckusick 		    sblock.fs_cssize - i < sblock.fs_bsize ?
5656534Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize);
5665098Smckusic 	}
5675098Smckusic 	sblock.fs_ronly = 0;
5685098Smckusic 	sblock.fs_fmod = 0;
5695349Smckusic 	bwrite(SBLOCK, (char *)&sblock, SBSIZE);
5705098Smckusic }
5715098Smckusic 
5725098Smckusic /*
5735098Smckusic  * update the frsum fields to reflect addition or deletion
5745098Smckusic  * of some frags
5755098Smckusic  */
5765326Smckusic fragacct(fs, fragmap, fraglist, cnt)
5775326Smckusic 	struct fs *fs;
5785098Smckusic 	int fragmap;
5795098Smckusic 	long fraglist[];
5805098Smckusic 	int cnt;
5815098Smckusic {
5825098Smckusic 	int inblk;
5835098Smckusic 	register int field, subfield;
5845098Smckusic 	register int siz, pos;
5855098Smckusic 
5865326Smckusic 	inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
5875098Smckusic 	fragmap <<= 1;
5885326Smckusic 	for (siz = 1; siz < fs->fs_frag; siz++) {
5896291Smckusick 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
5905098Smckusic 			continue;
5915098Smckusic 		field = around[siz];
5925098Smckusic 		subfield = inside[siz];
5935326Smckusic 		for (pos = siz; pos <= fs->fs_frag; pos++) {
5945098Smckusic 			if ((fragmap & field) == subfield) {
5955098Smckusic 				fraglist[siz] += cnt;
5965098Smckusic 				pos += siz;
5975098Smckusic 				field <<= siz;
5985098Smckusic 				subfield <<= siz;
5995098Smckusic 			}
6005098Smckusic 			field <<= 1;
6015098Smckusic 			subfield <<= 1;
6025098Smckusic 		}
6035098Smckusic 	}
6045098Smckusic }
6055098Smckusic 
6065326Smckusic getsb(fs, file)
6075326Smckusic 	register struct fs *fs;
6085326Smckusic 	char *file;
6095326Smckusic {
6106534Smckusick 	int i, j, size;
6115326Smckusic 
6125349Smckusic 	if (bread(SBLOCK, fs, SBSIZE)) {
6135326Smckusic 		printf("bad super block");
6145326Smckusic 		perror(file);
6155326Smckusic 		nerror |= 04;
6165326Smckusic 		return;
6175326Smckusic 	}
6185326Smckusic 	if (fs->fs_magic != FS_MAGIC) {
6195326Smckusic 		printf("%s: bad magic number\n", file);
6205326Smckusic 		nerror |= 04;
6215326Smckusic 		return;
6225326Smckusic 	}
6236534Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
6246534Smckusick 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
6256534Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize;
6266534Smckusick 		sblock.fs_csp[j] = (struct csum *)calloc(1, size);
6276534Smckusick 		bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
6286534Smckusick 		      (char *)fs->fs_csp[j], size);
6295326Smckusic 	}
6305326Smckusic }
6315326Smckusic 
6325098Smckusic bwrite(blk, buf, size)
6335098Smckusic 	char *buf;
6345098Smckusic 	daddr_t blk;
6355098Smckusic 	register size;
6365098Smckusic {
6375326Smckusic 	if (lseek(fi, blk * DEV_BSIZE, 0) < 0) {
6385098Smckusic 		perror("FS SEEK");
6395098Smckusic 		return(1);
6405098Smckusic 	}
6415098Smckusic 	if (write(fi, buf, size) != size) {
6425098Smckusic 		perror("FS WRITE");
6435098Smckusic 		return(1);
6445098Smckusic 	}
6455326Smckusic 	return (0);
6465098Smckusic }
6475098Smckusic 
6484240Smckusick bread(bno, buf, cnt)
6494410Smckusic 	daddr_t bno;
6504410Smckusic 	char *buf;
6514240Smckusick {
6524240Smckusick 	register i;
6534240Smckusick 
6545326Smckusic 	lseek(fi, bno * DEV_BSIZE, 0);
6554240Smckusick 	if ((i = read(fi, buf, cnt)) != cnt) {
6565098Smckusic 		if (sflg) {
6575098Smckusic 			printf("No Update\n");
6585098Smckusic 			sflg = 0;
6595098Smckusic 		}
6605326Smckusic 		for(i=0; i<sblock.fs_bsize; i++)
6614240Smckusick 			buf[i] = 0;
6625326Smckusic 		return (1);
6634240Smckusick 	}
6645326Smckusic 	return (0);
6654240Smckusick }
6665326Smckusic 
6675326Smckusic /*
6688143Smckusick  * check if a block is available
6695326Smckusic  */
6705326Smckusic isblock(fs, cp, h)
6715326Smckusic 	struct fs *fs;
6725326Smckusic 	unsigned char *cp;
6735326Smckusic 	int h;
6745326Smckusic {
6755326Smckusic 	unsigned char mask;
6765326Smckusic 
6775326Smckusic 	switch (fs->fs_frag) {
6785326Smckusic 	case 8:
6795326Smckusic 		return (cp[h] == 0xff);
6805326Smckusic 	case 4:
6815326Smckusic 		mask = 0x0f << ((h & 0x1) << 2);
6825326Smckusic 		return ((cp[h >> 1] & mask) == mask);
6835326Smckusic 	case 2:
6845326Smckusic 		mask = 0x03 << ((h & 0x3) << 1);
6855326Smckusic 		return ((cp[h >> 2] & mask) == mask);
6865326Smckusic 	case 1:
6875326Smckusic 		mask = 0x01 << (h & 0x7);
6885326Smckusic 		return ((cp[h >> 3] & mask) == mask);
6895326Smckusic 	default:
6908143Smckusick #ifdef STANDALONE
6918143Smckusick 		printf("isblock bad fs_frag %d\n", fs->fs_frag);
6928143Smckusick #else
6935326Smckusic 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
6948143Smckusick #endif
6955326Smckusic 		return;
6965326Smckusic 	}
6975326Smckusic }
6985326Smckusic 
6998143Smckusick /*
7008143Smckusick  * take a block out of the map
7018143Smckusick  */
7028143Smckusick clrblock(fs, cp, h)
7038143Smckusick 	struct fs *fs;
7048143Smckusick 	unsigned char *cp;
7058143Smckusick 	int h;
7068143Smckusick {
7078143Smckusick 	switch ((fs)->fs_frag) {
7088143Smckusick 	case 8:
7098143Smckusick 		cp[h] = 0;
7108143Smckusick 		return;
7118143Smckusick 	case 4:
7128143Smckusick 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
7138143Smckusick 		return;
7148143Smckusick 	case 2:
7158143Smckusick 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
7168143Smckusick 		return;
7178143Smckusick 	case 1:
7188143Smckusick 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
7198143Smckusick 		return;
7208143Smckusick 	default:
7218143Smckusick #ifdef STANDALONE
7228143Smckusick 		printf("clrblock bad fs_frag %d\n", fs->fs_frag);
7238143Smckusick #else
7248143Smckusick 		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
7258143Smckusick #endif
7268143Smckusick 		return;
7278143Smckusick 	}
7288143Smckusick }
7298143Smckusick 
7308143Smckusick /*
7318143Smckusick  * put a block into the map
7328143Smckusick  */
7335326Smckusic setblock(fs, cp, h)
7345326Smckusic 	struct fs *fs;
7355326Smckusic 	unsigned char *cp;
7365326Smckusic 	int h;
7375326Smckusic {
7385326Smckusic 	switch (fs->fs_frag) {
7395326Smckusic 	case 8:
7405326Smckusic 		cp[h] = 0xff;
7415326Smckusic 		return;
7425326Smckusic 	case 4:
7435326Smckusic 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
7445326Smckusic 		return;
7455326Smckusic 	case 2:
7465326Smckusic 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
7475326Smckusic 		return;
7485326Smckusic 	case 1:
7495326Smckusic 		cp[h >> 3] |= (0x01 << (h & 0x7));
7505326Smckusic 		return;
7515326Smckusic 	default:
7528143Smckusick #ifdef STANDALONE
7538143Smckusick 		printf("setblock bad fs_frag %d\n", fs->fs_frag);
7548143Smckusick #else
7555326Smckusic 		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
7568143Smckusick #endif
7575326Smckusic 		return;
7585326Smckusic 	}
7595326Smckusic }
7606490Smckusick 
7616490Smckusick /*	tables.c	4.1	82/03/25	*/
7626490Smckusick 
7636490Smckusick /* merged into kernel:	tables.c 2.1 3/25/82 */
7646490Smckusick 
7656490Smckusick /* last monet version:	partab.c	4.2	81/03/08	*/
7666490Smckusick 
7676490Smckusick /*
7686490Smckusick  * bit patterns for identifying fragments in the block map
7696490Smckusick  * used as ((map & around) == inside)
7706490Smckusick  */
7716490Smckusick int around[9] = {
7726490Smckusick 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
7736490Smckusick };
7746490Smckusick int inside[9] = {
7756490Smckusick 	0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
7766490Smckusick };
7776490Smckusick 
7786490Smckusick /*
7796490Smckusick  * given a block map bit pattern, the frag tables tell whether a
7806490Smckusick  * particular size fragment is available.
7816490Smckusick  *
7826490Smckusick  * used as:
7836490Smckusick  * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
7846490Smckusick  *	at least one fragment of the indicated size is available
7856490Smckusick  * }
7866490Smckusick  *
7876490Smckusick  * These tables are used by the scanc instruction on the VAX to
7886490Smckusick  * quickly find an appropriate fragment.
7896490Smckusick  */
7906490Smckusick 
7916490Smckusick unsigned char fragtbl124[256] = {
7926490Smckusick 	0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
7936490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
7946490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
7956490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
7966490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
7976490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
7986490Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
7996490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
8006490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8016490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8026490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8036490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8046490Smckusick 	0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
8056490Smckusick 	0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
8066490Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
8076490Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
8086490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8096490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8106490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8116490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8126490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8136490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8146490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
8156490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
8166490Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
8176490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
8186490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
8196490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
8206490Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
8216490Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
8226490Smckusick 	0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
8236490Smckusick 	0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
8246490Smckusick };
8256490Smckusick 
8266490Smckusick unsigned char fragtbl8[256] = {
8276490Smckusick 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
8286490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
8296490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8306490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
8316490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8326490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8336490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8346490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
8356490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8366490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8376490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8386490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
8396490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8406490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
8416490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
8426490Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
8436490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8446490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8456490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8466490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
8476490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8486490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8496490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
8506490Smckusick 	0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
8516490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8526490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
8536490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
8546490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
8556490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
8566490Smckusick 	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
8576490Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
8586490Smckusick 	0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
8596490Smckusick };
8606490Smckusick 
8616490Smckusick /*
8626490Smckusick  * the actual fragtbl array
8636490Smckusick  */
8646490Smckusick unsigned char *fragtbl[MAXFRAG + 1] = {
8656490Smckusick 	0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
8666490Smckusick };
867