xref: /csrg-svn/sbin/icheck/icheck.c (revision 21133)
1*21133Sdist /*
2*21133Sdist  * Copyright (c) 1980 Regents of the University of California.
3*21133Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21133Sdist  * specifies the terms and conditions for redistribution.
5*21133Sdist  */
64410Smckusic 
7*21133Sdist #ifndef lint
8*21133Sdist static char sccsid[] = "@(#)icheck.c	5.1 (Berkeley) 05/28/85";
9*21133Sdist #endif not lint
10*21133Sdist 
11*21133Sdist 
124240Smckusick /*
134240Smckusick  * icheck
144240Smckusick  */
154240Smckusick #define	NB	500
164240Smckusick #define	MAXFN	500
175349Smckusic #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
184240Smckusick 
194240Smckusick #ifndef STANDALONE
204240Smckusick #include <stdio.h>
214240Smckusick #endif
226490Smckusick #ifndef SIMFS
236490Smckusick #include <sys/param.h>
246490Smckusick #include <sys/inode.h>
256490Smckusick #include <sys/fs.h>
266490Smckusick #else
274240Smckusick #include "../h/param.h"
284240Smckusick #include "../h/inode.h"
294240Smckusick #include "../h/fs.h"
306490Smckusick #endif
314240Smckusick 
324240Smckusick union {
334240Smckusick 	struct	fs sb;
345326Smckusic 	char pad[MAXBSIZE];
354240Smckusick } sbun;
364240Smckusick #define	sblock sbun.sb
374240Smckusick 
384240Smckusick union {
394240Smckusick 	struct	cg cg;
405326Smckusic 	char pad[MAXBSIZE];
414240Smckusick } cgun;
424240Smckusick #define	cgrp cgun.cg
434240Smckusick 
444240Smckusick struct	dinode	itab[MAXIPG];
454240Smckusick daddr_t	blist[NB];
469298Smckusick daddr_t	fsblist[NB];
474240Smckusick char	*bmap;
484240Smckusick 
494240Smckusick int	mflg;
505098Smckusic int	sflg;
514240Smckusick int	dflg;
524240Smckusick int	fi;
534240Smckusick ino_t	ino;
544240Smckusick int	cginit;
554240Smckusick 
564240Smckusick ino_t	nrfile;
574240Smckusick ino_t	ndfile;
584240Smckusick ino_t	nbfile;
594240Smckusick ino_t	ncfile;
606286Smckusick ino_t	nlfile;
614240Smckusick 
624240Smckusick daddr_t	nblock;
634240Smckusick daddr_t	nfrag;
644240Smckusick daddr_t	nindir;
654240Smckusick daddr_t	niindir;
664240Smckusick 
674240Smckusick daddr_t	nffree;
684240Smckusick daddr_t	nbfree;
694240Smckusick 
704240Smckusick daddr_t	ndup;
714240Smckusick 
724240Smckusick int	nerror;
734240Smckusick 
745098Smckusic extern int inside[], around[];
755326Smckusic extern unsigned char *fragtbl[];
765098Smckusic 
774240Smckusick long	atol();
784240Smckusick #ifndef STANDALONE
794240Smckusick char	*malloc();
805098Smckusic char	*calloc();
814240Smckusick #endif
824240Smckusick 
834240Smckusick main(argc, argv)
845098Smckusic 	int argc;
855098Smckusic 	char *argv[];
864240Smckusick {
874240Smckusick 	register i;
884240Smckusick 	long n;
894240Smckusick 
904240Smckusick 	blist[0] = -1;
914240Smckusick #ifndef STANDALONE
924240Smckusick 	while (--argc) {
934240Smckusick 		argv++;
944240Smckusick 		if (**argv=='-')
954240Smckusick 		switch ((*argv)[1]) {
964240Smckusick 		case 'd':
974240Smckusick 			dflg++;
984240Smckusick 			continue;
994240Smckusick 
1004240Smckusick 		case 'm':
1014240Smckusick 			mflg++;
1024240Smckusick 			continue;
1034240Smckusick 
1045098Smckusic 		case 's':
1055098Smckusic 			sflg++;
1065098Smckusic 			continue;
1075098Smckusic 
1084240Smckusick 		case 'b':
1094240Smckusick 			for(i=0; i<NB; i++) {
1104240Smckusick 				n = atol(argv[1]);
1114240Smckusick 				if(n == 0)
1124240Smckusick 					break;
1134240Smckusick 				blist[i] = n;
1144240Smckusick 				argv++;
1154240Smckusick 				argc--;
1164240Smckusick 			}
1174240Smckusick 			blist[i] = -1;
1184240Smckusick 			continue;
1194240Smckusick 
1204240Smckusick 		default:
1214240Smckusick 			printf("Bad flag\n");
1224240Smckusick 		}
1234240Smckusick 		check(*argv);
1244240Smckusick 	}
1254240Smckusick #else
1264240Smckusick 	{
1274240Smckusick 		static char fname[128];
1284240Smckusick 
1294240Smckusick 		printf("File: ");
1304240Smckusick 		gets(fname);
1314240Smckusick 		check(fname);
1324240Smckusick 	}
1334240Smckusick #endif
1344240Smckusick 	return(nerror);
1354240Smckusick }
1364240Smckusick 
1374240Smckusick check(file)
1385098Smckusic 	char *file;
1394240Smckusick {
1404240Smckusick 	register i, j, c;
1414240Smckusick 	daddr_t d, cgd, cbase, b;
1424240Smckusick 	long n;
1439298Smckusick 	char buf[BUFSIZ];
1444240Smckusick 
1455098Smckusic 	fi = open(file, sflg ? 2 : 0);
1464240Smckusick 	if (fi < 0) {
1475098Smckusic 		perror(file);
1484240Smckusick 		nerror |= 04;
1494240Smckusick 		return;
1504240Smckusick 	}
1514240Smckusick 	printf("%s:\n", file);
1524240Smckusick 	nrfile = 0;
1534240Smckusick 	ndfile = 0;
1544240Smckusick 	ncfile = 0;
1554240Smckusick 	nbfile = 0;
1566286Smckusick 	nlfile = 0;
1574240Smckusick 
1584240Smckusick 	nblock = 0;
1594240Smckusick 	nfrag = 0;
1604240Smckusick 	nindir = 0;
1614240Smckusick 	niindir = 0;
1624240Smckusick 
1634240Smckusick 	ndup = 0;
1644240Smckusick #ifndef STANDALONE
1654240Smckusick 	sync();
1664240Smckusick #endif
1675326Smckusic 	getsb(&sblock, file);
1685326Smckusic 	if (nerror)
1694240Smckusick 		return;
1709298Smckusick 	for (n=0; blist[n] != -1; n++)
1719298Smckusick 		fsblist[n] = dbtofsb(&sblock, blist[n]);
1724240Smckusick 	ino = 0;
1735098Smckusic 	n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
1744240Smckusick #ifdef STANDALONE
1754240Smckusick 	bmap = NULL;
1764240Smckusick #else
1774240Smckusick 	bmap = malloc((unsigned)n);
1784240Smckusick #endif
1794240Smckusick 	if (bmap==NULL) {
1804240Smckusick 		printf("Not enough core; duplicates unchecked\n");
1814240Smckusick 		dflg++;
1825098Smckusic 		if (sflg) {
1835098Smckusic 			printf("No Updates\n");
1845098Smckusic 			sflg = 0;
1855098Smckusic 		}
1864240Smckusick 	}
1874240Smckusick 	ino = 0;
1884240Smckusick 	cginit = 1;
1896534Smckusick 	if (!dflg) {
1906534Smckusick 		for (i = 0; i < (unsigned)n; i++)
1914240Smckusick 			bmap[i] = 0;
1926534Smckusick 		for (c = 0; c < sblock.fs_ncg; c++) {
1935382Smckusic 			cgd = cgtod(&sblock, c);
1946534Smckusick 			if (c == 0)
1956534Smckusick 				d = cgbase(&sblock, c);
1966534Smckusick 			else
1976534Smckusick 				d = cgsblock(&sblock, c);
1989298Smckusick 			sprintf(buf, "spare super block %d", c);
1996534Smckusick 			for (; d < cgd; d += sblock.fs_frag)
2009298Smckusick 				chk(d, buf, sblock.fs_bsize);
2015382Smckusic 			d = cgimin(&sblock, c);
2029298Smckusick 			sprintf(buf, "cylinder group %d", c);
2034240Smckusick 			while (cgd < d) {
2049298Smckusick 				chk(cgd, buf, sblock.fs_bsize);
2055326Smckusic 				cgd += sblock.fs_frag;
2064240Smckusick 			}
2075382Smckusic 			d = cgdmin(&sblock, c);
2089298Smckusick 			i = INOPB(&sblock);
2099298Smckusick 			for (; cgd < d; cgd += sblock.fs_frag) {
2109298Smckusick 				sprintf(buf, "inodes %d-%d", ino, ino + i);
2119298Smckusick 				chk(cgd, buf, sblock.fs_bsize);
2129298Smckusick 				ino += i;
2139298Smckusick 			}
2144240Smckusick 			if (c == 0) {
2156534Smckusick 				d += howmany(sblock.fs_cssize, sblock.fs_fsize);
2166534Smckusick 				for (; cgd < d; cgd++)
2176534Smckusick 					chk(cgd, "csum", sblock.fs_fsize);
2184240Smckusick 			}
2194240Smckusick 		}
2204240Smckusick 	}
2219298Smckusick 	ino = 0;
2224240Smckusick 	cginit = 0;
2234240Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
2245382Smckusic 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
2254240Smckusick 		    sblock.fs_ipg * sizeof (struct dinode));
2264240Smckusick 		for (j=0; j < sblock.fs_ipg; j++) {
2274240Smckusick 			pass1(&itab[j]);
2284240Smckusick 			ino++;
2294240Smckusick 		}
2304240Smckusick 	}
2314240Smckusick 	ino = 0;
2324240Smckusick #ifndef STANDALONE
2334240Smckusick 	sync();
2344240Smckusick #endif
2355098Smckusic 	if (sflg) {
2365098Smckusic 		makecg();
2375098Smckusic 		close(fi);
2385098Smckusic #ifndef STANDALONE
2395098Smckusic 		if (bmap)
2405098Smckusic 			free(bmap);
2415098Smckusic #endif
2425098Smckusic 		return;
2435098Smckusic 	}
2444240Smckusick 	nffree = 0;
2454240Smckusick 	nbfree = 0;
2464240Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
2475382Smckusic 		cbase = cgbase(&sblock, c);
2485382Smckusic 		bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp,
2495326Smckusic 			sblock.fs_cgsize);
2506534Smckusick 		if (cgrp.cg_magic != CG_MAGIC)
2516534Smckusick 			printf("cg %d: bad magic number\n", c);
2525326Smckusic 		for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
2535326Smckusic 			if (isblock(&sblock, cgrp.cg_free,
2545326Smckusic 			    b / sblock.fs_frag)) {
2554240Smckusick 				nbfree++;
2569298Smckusick 				chk(cbase+b, "free block", sblock.fs_bsize);
2574240Smckusick 			} else {
2585326Smckusic 				for (d = 0; d < sblock.fs_frag; d++)
2594240Smckusick 					if (isset(cgrp.cg_free, b+d)) {
2609298Smckusick 						chk(cbase+b+d, "free frag", sblock.fs_fsize);
2614240Smckusick 						nffree++;
2624240Smckusick 					}
2634240Smckusick 			}
2644240Smckusick 		}
2654240Smckusick 	}
2664240Smckusick 	close(fi);
2674240Smckusick #ifndef STANDALONE
2684240Smckusick 	if (bmap)
2694240Smckusick 		free(bmap);
2704240Smckusick #endif
2714240Smckusick 
2726286Smckusick 	i = nrfile + ndfile + ncfile + nbfile + nlfile;
2734240Smckusick #ifndef STANDALONE
2746286Smckusick 	printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
2756286Smckusick 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
2764240Smckusick #else
2776286Smckusick 	printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
2786286Smckusick 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
2794240Smckusick #endif
2805326Smckusic 	n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
2814240Smckusick #ifdef STANDALONE
2824240Smckusick 	printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
2834240Smckusick 		n, nindir, niindir, nblock, nfrag);
2845326Smckusic 	printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
2854240Smckusick 	    nbfree, nffree);
2864240Smckusick #else
2874240Smckusick 	printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
2884240Smckusick 		n, nindir, niindir, nblock, nfrag);
2895326Smckusic 	printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
2904240Smckusick 	    nbfree, nffree);
2914240Smckusick #endif
2924240Smckusick 	if(!dflg) {
2934240Smckusick 		n = 0;
2944410Smckusic 		for (d = 0; d < sblock.fs_size; d++)
2955326Smckusic 			if(!duped(d, sblock.fs_fsize)) {
2964240Smckusick 				if(mflg)
2974240Smckusick 					printf("%ld missing\n", d);
2984240Smckusick 				n++;
2994240Smckusick 			}
3004240Smckusick 		printf("missing%5ld\n", n);
3014240Smckusick 	}
3024240Smckusick }
3034240Smckusick 
3044240Smckusick pass1(ip)
3054410Smckusic 	register struct dinode *ip;
3064240Smckusick {
3075326Smckusic 	daddr_t ind1[MAXNINDIR];
3085326Smckusic 	daddr_t ind2[MAXNINDIR];
3094429Smckusic 	daddr_t db, ib;
3104429Smckusic 	register int i, j, k, siz;
3119298Smckusick 	int lbn;
3129298Smckusick 	char buf[BUFSIZ];
3134240Smckusick 
3144240Smckusick 	i = ip->di_mode & IFMT;
3154790Smckusic 	if(i == 0)
3164240Smckusick 		return;
3174240Smckusick 	switch (i) {
3184240Smckusick 	case IFCHR:
3194240Smckusick 		ncfile++;
3204240Smckusick 		return;
3214240Smckusick 	case IFBLK:
3224240Smckusick 		nbfile++;
3234240Smckusick 		return;
3244240Smckusick 	case IFDIR:
3254240Smckusick 		ndfile++;
3264240Smckusick 		break;
3274240Smckusick 	case IFREG:
3284240Smckusick 		nrfile++;
3294240Smckusick 		break;
3306286Smckusick 	case IFLNK:
3316286Smckusick 		nlfile++;
3326286Smckusick 		break;
3334240Smckusick 	default:
3344240Smckusick 		printf("bad mode %u\n", ino);
3354240Smckusick 		return;
3364240Smckusick 	}
3374410Smckusic 	for (i = 0; i < NDADDR; i++) {
3384410Smckusic 		db = ip->di_db[i];
3394410Smckusic 		if (db == 0)
3404240Smckusick 			continue;
3415326Smckusic 		siz = dblksize(&sblock, ip, i);
3429298Smckusick 		sprintf(buf, "logical data block %d", i);
3439298Smckusick 		chk(db, buf, siz);
3445326Smckusic 		if (siz == sblock.fs_bsize)
3454429Smckusic 			nblock++;
3464429Smckusic 		else
3475326Smckusic 			nfrag += howmany(siz, sblock.fs_fsize);
3484240Smckusick 	}
3494410Smckusic 	for(i = 0; i < NIADDR; i++) {
3504410Smckusic 		ib = ip->di_ib[i];
3519298Smckusick 		if (ib == 0)
3524240Smckusick 			continue;
3535326Smckusic 		if (chk(ib, "1st indirect", sblock.fs_bsize))
3544410Smckusic 			continue;
3555326Smckusic 		bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize);
3564240Smckusick 		nindir++;
3575326Smckusic 		for (j = 0; j < NINDIR(&sblock); j++) {
3584410Smckusic 			ib = ind1[j];
3594410Smckusic 			if (ib == 0)
3604240Smckusick 				continue;
3614410Smckusic 			if (i == 0) {
3629298Smckusick 				lbn = NDADDR + j;
3639298Smckusick 				siz = dblksize(&sblock, ip, lbn);
3649298Smckusick 				sprintf(buf, "logical data block %d", lbn);
3659298Smckusick 				chk(ib, buf, siz);
3665326Smckusic 				if (siz == sblock.fs_bsize)
3674429Smckusic 					nblock++;
3684429Smckusic 				else
3695326Smckusic 					nfrag += howmany(siz, sblock.fs_fsize);
3704240Smckusick 				continue;
3714240Smckusick 			}
3725326Smckusic 			if (chk(ib, "2nd indirect", sblock.fs_bsize))
3734410Smckusic 				continue;
3745326Smckusic 			bread(fsbtodb(&sblock, ib), (char *)ind2,
3755326Smckusic 				sblock.fs_bsize);
3764240Smckusick 			niindir++;
3775326Smckusic 			for (k = 0; k < NINDIR(&sblock); k++) {
3784410Smckusic 				ib = ind2[k];
3794410Smckusic 				if (ib == 0)
3804240Smckusick 					continue;
3819298Smckusick 				lbn = NDADDR + NINDIR(&sblock) * (i + j) + k;
3829298Smckusick 				siz = dblksize(&sblock, ip, lbn);
3839298Smckusick 				sprintf(buf, "logical data block %d", lbn);
3849298Smckusick 				chk(ib, buf, siz);
3855326Smckusic 				if (siz == sblock.fs_bsize)
3864429Smckusic 					nblock++;
3874429Smckusic 				else
3885326Smckusic 					nfrag += howmany(siz, sblock.fs_fsize);
3894240Smckusick 			}
3904240Smckusick 		}
3914240Smckusick 	}
3924240Smckusick }
3934240Smckusick 
3944429Smckusic chk(bno, s, size)
3954410Smckusic 	daddr_t bno;
3964410Smckusic 	char *s;
3974429Smckusic 	int size;
3984240Smckusick {
3994240Smckusick 	register n, cg;
4005957Smckusic 	int frags;
4014240Smckusick 
4025382Smckusic 	cg = dtog(&sblock, bno);
4036534Smckusick 	if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) {
4044240Smckusick 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
4054240Smckusick 		return(1);
4064240Smckusick 	}
4079298Smckusick 	frags = numfrags(&sblock, size);
4089298Smckusick 	if (frags == sblock.fs_frag) {
4094429Smckusic 		if (duped(bno, size)) {
4104429Smckusic 			printf("%ld dup block; inode=%u, class=%s\n",
4114429Smckusic 			    bno, ino, s);
4125326Smckusic 			ndup += sblock.fs_frag;
4134429Smckusic 		}
4144429Smckusic 	} else {
4155957Smckusic 		for (n = 0; n < frags; n++) {
4165326Smckusic 			if (duped(bno + n, sblock.fs_fsize)) {
4174429Smckusic 				printf("%ld dup frag; inode=%u, class=%s\n",
4184429Smckusic 				    bno, ino, s);
4194429Smckusic 				ndup++;
4204429Smckusic 			}
4214429Smckusic 		}
4224240Smckusick 	}
4234240Smckusick 	for (n=0; blist[n] != -1; n++)
4249298Smckusick 		if (fsblist[n] >= bno && fsblist[n] < bno + frags)
4259298Smckusick 			printf("%ld arg; frag %d of %d, inode=%u, class=%s\n",
4269298Smckusick 				blist[n], fsblist[n] - bno, frags, ino, s);
4274240Smckusick 	return(0);
4284240Smckusick }
4294240Smckusick 
4304429Smckusic duped(bno, size)
4314410Smckusic 	daddr_t bno;
4324429Smckusic 	int size;
4334240Smckusick {
4344240Smckusick 	if(dflg)
4354240Smckusick 		return(0);
4365326Smckusic 	if (size != sblock.fs_fsize && size != sblock.fs_bsize)
4374429Smckusic 		printf("bad size %d to duped\n", size);
4385326Smckusic 	if (size == sblock.fs_fsize) {
4394410Smckusic 		if (isset(bmap, bno))
4404410Smckusic 			return(1);
4414410Smckusic 		setbit(bmap, bno);
4424410Smckusic 		return (0);
4434410Smckusic 	}
4445326Smckusic 	if (bno % sblock.fs_frag != 0)
4454410Smckusic 		printf("bad bno %d to duped\n", bno);
4465326Smckusic 	if (isblock(&sblock, bmap, bno/sblock.fs_frag))
4474410Smckusic 		return (1);
4485326Smckusic 	setblock(&sblock, bmap, bno/sblock.fs_frag);
4494240Smckusick 	return(0);
4504240Smckusick }
4514240Smckusick 
4525098Smckusic makecg()
4535098Smckusic {
4545098Smckusic 	int c, blk;
4556534Smckusick 	daddr_t dbase, d, dlower, dupper, dmax;
4565098Smckusic 	long i, j, s;
4575098Smckusic 	register struct csum *cs;
4585098Smckusic 	register struct dinode *dp;
4595098Smckusic 
4605098Smckusic 	sblock.fs_cstotal.cs_nbfree = 0;
4615098Smckusic 	sblock.fs_cstotal.cs_nffree = 0;
4625098Smckusic 	sblock.fs_cstotal.cs_nifree = 0;
4635098Smckusic 	sblock.fs_cstotal.cs_ndir = 0;
4645098Smckusic 	for (c = 0; c < sblock.fs_ncg; c++) {
4655382Smckusic 		dbase = cgbase(&sblock, c);
4665098Smckusic 		dmax = dbase + sblock.fs_fpg;
4675410Smckusic 		if (dmax > sblock.fs_size) {
4685410Smckusic 			for ( ; dmax >= sblock.fs_size; dmax--)
4695400Smckusic 				clrbit(cgrp.cg_free, dmax - dbase);
4705410Smckusic 			dmax++;
4715410Smckusic 		}
4726534Smckusick 		dlower = cgsblock(&sblock, c) - dbase;
4736534Smckusick 		dupper = cgdmin(&sblock, c) - dbase;
4745326Smckusic 		cs = &sblock.fs_cs(&sblock, c);
4755098Smckusic 		cgrp.cg_time = time(0);
4765098Smckusic 		cgrp.cg_magic = CG_MAGIC;
4775098Smckusic 		cgrp.cg_cgx = c;
4788143Smckusick 		if (c == sblock.fs_ncg - 1)
4798143Smckusick 			cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
4808143Smckusick 		else
4818143Smckusick 			cgrp.cg_ncyl = sblock.fs_cpg;
4825098Smckusic 		cgrp.cg_niblk = sblock.fs_ipg;
4835098Smckusic 		cgrp.cg_ndblk = dmax - dbase;
4845098Smckusic 		cgrp.cg_cs.cs_ndir = 0;
4855098Smckusic 		cgrp.cg_cs.cs_nffree = 0;
4865098Smckusic 		cgrp.cg_cs.cs_nbfree = 0;
4875098Smckusic 		cgrp.cg_cs.cs_nifree = 0;
4886534Smckusick 		cgrp.cg_rotor = 0;
4896534Smckusick 		cgrp.cg_frotor = 0;
4905098Smckusic 		cgrp.cg_irotor = 0;
4915326Smckusic 		for (i = 0; i < sblock.fs_frag; i++)
4925098Smckusic 			cgrp.cg_frsum[i] = 0;
4935382Smckusic 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
4945098Smckusic 		      sblock.fs_ipg * sizeof(struct dinode));
4955098Smckusic 		for (i = 0; i < sblock.fs_ipg; i++) {
4965945Smckusic 			cgrp.cg_cs.cs_nifree++;
4975945Smckusic 			clrbit(cgrp.cg_iused, i);
4985098Smckusic 			dp = &itab[i];
4995098Smckusic 			if ((dp->di_mode & IFMT) != 0) {
5005098Smckusic 				if ((dp->di_mode & IFMT) == IFDIR)
5015098Smckusic 					cgrp.cg_cs.cs_ndir++;
5025945Smckusic 				cgrp.cg_cs.cs_nifree--;
5035098Smckusic 				setbit(cgrp.cg_iused, i);
5045098Smckusic 				continue;
5055098Smckusic 			}
5065098Smckusic 		}
5075098Smckusic 		while (i < MAXIPG) {
5085098Smckusic 			clrbit(cgrp.cg_iused, i);
5095098Smckusic 			i++;
5105098Smckusic 		}
5115338Smckusic 		if (c == 0)
5125338Smckusic 			for (i = 0; i < ROOTINO; i++) {
5135338Smckusic 				setbit(cgrp.cg_iused, i);
5145338Smckusic 				cgrp.cg_cs.cs_nifree--;
5155338Smckusic 			}
5165372Smckusic 		for (s = 0; s < MAXCPG; s++) {
5175372Smckusic 			cgrp.cg_btot[s] = 0;
5185098Smckusic 			for (i = 0; i < NRPOS; i++)
5195098Smckusic 				cgrp.cg_b[s][i] = 0;
5205372Smckusic 		}
5215098Smckusic 		if (c == 0) {
5226534Smckusick 			dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
5235098Smckusic 		}
5246534Smckusick 		for (d = dlower; d < dupper; d++)
5255098Smckusic 			clrbit(cgrp.cg_free, d);
5266534Smckusick 		for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
5276534Smckusick 		    d += sblock.fs_frag) {
5285098Smckusic 			j = 0;
5295326Smckusic 			for (i = 0; i < sblock.fs_frag; i++) {
5306534Smckusick 				if (!isset(bmap, dbase + d + i)) {
5316534Smckusick 					setbit(cgrp.cg_free, d + i);
5325098Smckusic 					j++;
5335098Smckusic 				} else
5345098Smckusic 					clrbit(cgrp.cg_free, d+i);
5355098Smckusic 			}
5365326Smckusic 			if (j == sblock.fs_frag) {
5375098Smckusic 				cgrp.cg_cs.cs_nbfree++;
5385372Smckusic 				cgrp.cg_btot[cbtocylno(&sblock, d)]++;
5395364Smckusic 				cgrp.cg_b[cbtocylno(&sblock, d)]
5405364Smckusic 				    [cbtorpos(&sblock, d)]++;
5415098Smckusic 			} else if (j > 0) {
5425098Smckusic 				cgrp.cg_cs.cs_nffree += j;
5436534Smckusick 				blk = blkmap(&sblock, cgrp.cg_free, d);
5445326Smckusic 				fragacct(&sblock, blk, cgrp.cg_frsum, 1);
5455098Smckusic 			}
5465098Smckusic 		}
5475098Smckusic 		for (j = d; d < dmax - dbase; d++) {
5486534Smckusick 			if (!isset(bmap, dbase + d)) {
5495098Smckusic 				setbit(cgrp.cg_free, d);
5505098Smckusic 				cgrp.cg_cs.cs_nffree++;
5515098Smckusic 			} else
5525098Smckusic 				clrbit(cgrp.cg_free, d);
5535098Smckusic 		}
5548143Smckusick 		for (; d % sblock.fs_frag != 0; d++)
5558143Smckusick 			clrbit(cgrp.cg_free, d);
5565098Smckusic 		if (j != d) {
5576534Smckusick 			blk = blkmap(&sblock, cgrp.cg_free, j);
5585326Smckusic 			fragacct(&sblock, blk, cgrp.cg_frsum, 1);
5595098Smckusic 		}
5608143Smckusick 		for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
5618143Smckusick 			clrblock(&sblock, cgrp.cg_free, d);
5625098Smckusic 		sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
5635098Smckusic 		sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
5645098Smckusic 		sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
5655098Smckusic 		sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
5665098Smckusic 		*cs = cgrp.cg_cs;
5675382Smckusic 		bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp,
5685326Smckusic 			sblock.fs_cgsize);
5695098Smckusic 	}
5706534Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
5716534Smckusick 		bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
5726534Smckusick 		    (char *)sblock.fs_csp[j],
5736534Smckusick 		    sblock.fs_cssize - i < sblock.fs_bsize ?
5746534Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize);
5755098Smckusic 	}
5765098Smckusic 	sblock.fs_ronly = 0;
5775098Smckusic 	sblock.fs_fmod = 0;
5785349Smckusic 	bwrite(SBLOCK, (char *)&sblock, SBSIZE);
5795098Smckusic }
5805098Smckusic 
5815098Smckusic /*
5825098Smckusic  * update the frsum fields to reflect addition or deletion
5835098Smckusic  * of some frags
5845098Smckusic  */
5855326Smckusic fragacct(fs, fragmap, fraglist, cnt)
5865326Smckusic 	struct fs *fs;
5875098Smckusic 	int fragmap;
5885098Smckusic 	long fraglist[];
5895098Smckusic 	int cnt;
5905098Smckusic {
5915098Smckusic 	int inblk;
5925098Smckusic 	register int field, subfield;
5935098Smckusic 	register int siz, pos;
5945098Smckusic 
5955326Smckusic 	inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
5965098Smckusic 	fragmap <<= 1;
5975326Smckusic 	for (siz = 1; siz < fs->fs_frag; siz++) {
5986291Smckusick 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
5995098Smckusic 			continue;
6005098Smckusic 		field = around[siz];
6015098Smckusic 		subfield = inside[siz];
6025326Smckusic 		for (pos = siz; pos <= fs->fs_frag; pos++) {
6035098Smckusic 			if ((fragmap & field) == subfield) {
6045098Smckusic 				fraglist[siz] += cnt;
6055098Smckusic 				pos += siz;
6065098Smckusic 				field <<= siz;
6075098Smckusic 				subfield <<= siz;
6085098Smckusic 			}
6095098Smckusic 			field <<= 1;
6105098Smckusic 			subfield <<= 1;
6115098Smckusic 		}
6125098Smckusic 	}
6135098Smckusic }
6145098Smckusic 
6155326Smckusic getsb(fs, file)
6165326Smckusic 	register struct fs *fs;
6175326Smckusic 	char *file;
6185326Smckusic {
6196534Smckusick 	int i, j, size;
6205326Smckusic 
6215349Smckusic 	if (bread(SBLOCK, fs, SBSIZE)) {
6225326Smckusic 		printf("bad super block");
6235326Smckusic 		perror(file);
6245326Smckusic 		nerror |= 04;
6255326Smckusic 		return;
6265326Smckusic 	}
6275326Smckusic 	if (fs->fs_magic != FS_MAGIC) {
6285326Smckusic 		printf("%s: bad magic number\n", file);
6295326Smckusic 		nerror |= 04;
6305326Smckusic 		return;
6315326Smckusic 	}
6326534Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
6336534Smckusick 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
6346534Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize;
6356534Smckusick 		sblock.fs_csp[j] = (struct csum *)calloc(1, size);
6366534Smckusick 		bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
6376534Smckusick 		      (char *)fs->fs_csp[j], size);
6385326Smckusic 	}
6395326Smckusic }
6405326Smckusic 
6415098Smckusic bwrite(blk, buf, size)
6425098Smckusic 	char *buf;
6435098Smckusic 	daddr_t blk;
6445098Smckusic 	register size;
6455098Smckusic {
6465326Smckusic 	if (lseek(fi, blk * DEV_BSIZE, 0) < 0) {
6475098Smckusic 		perror("FS SEEK");
6485098Smckusic 		return(1);
6495098Smckusic 	}
6505098Smckusic 	if (write(fi, buf, size) != size) {
6515098Smckusic 		perror("FS WRITE");
6525098Smckusic 		return(1);
6535098Smckusic 	}
6545326Smckusic 	return (0);
6555098Smckusic }
6565098Smckusic 
6574240Smckusick bread(bno, buf, cnt)
6584410Smckusic 	daddr_t bno;
6594410Smckusic 	char *buf;
6604240Smckusick {
6614240Smckusick 	register i;
6624240Smckusick 
6635326Smckusic 	lseek(fi, bno * DEV_BSIZE, 0);
6644240Smckusick 	if ((i = read(fi, buf, cnt)) != cnt) {
6655098Smckusic 		if (sflg) {
6665098Smckusic 			printf("No Update\n");
6675098Smckusic 			sflg = 0;
6685098Smckusic 		}
6695326Smckusic 		for(i=0; i<sblock.fs_bsize; i++)
6704240Smckusick 			buf[i] = 0;
6715326Smckusic 		return (1);
6724240Smckusick 	}
6735326Smckusic 	return (0);
6744240Smckusick }
6755326Smckusic 
6765326Smckusic /*
6778143Smckusick  * check if a block is available
6785326Smckusic  */
6795326Smckusic isblock(fs, cp, h)
6805326Smckusic 	struct fs *fs;
6815326Smckusic 	unsigned char *cp;
6825326Smckusic 	int h;
6835326Smckusic {
6845326Smckusic 	unsigned char mask;
6855326Smckusic 
6865326Smckusic 	switch (fs->fs_frag) {
6875326Smckusic 	case 8:
6885326Smckusic 		return (cp[h] == 0xff);
6895326Smckusic 	case 4:
6905326Smckusic 		mask = 0x0f << ((h & 0x1) << 2);
6915326Smckusic 		return ((cp[h >> 1] & mask) == mask);
6925326Smckusic 	case 2:
6935326Smckusic 		mask = 0x03 << ((h & 0x3) << 1);
6945326Smckusic 		return ((cp[h >> 2] & mask) == mask);
6955326Smckusic 	case 1:
6965326Smckusic 		mask = 0x01 << (h & 0x7);
6975326Smckusic 		return ((cp[h >> 3] & mask) == mask);
6985326Smckusic 	default:
6998143Smckusick #ifdef STANDALONE
7008143Smckusick 		printf("isblock bad fs_frag %d\n", fs->fs_frag);
7018143Smckusick #else
7025326Smckusic 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
7038143Smckusick #endif
7045326Smckusic 		return;
7055326Smckusic 	}
7065326Smckusic }
7075326Smckusic 
7088143Smckusick /*
7098143Smckusick  * take a block out of the map
7108143Smckusick  */
7118143Smckusick clrblock(fs, cp, h)
7128143Smckusick 	struct fs *fs;
7138143Smckusick 	unsigned char *cp;
7148143Smckusick 	int h;
7158143Smckusick {
7168143Smckusick 	switch ((fs)->fs_frag) {
7178143Smckusick 	case 8:
7188143Smckusick 		cp[h] = 0;
7198143Smckusick 		return;
7208143Smckusick 	case 4:
7218143Smckusick 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
7228143Smckusick 		return;
7238143Smckusick 	case 2:
7248143Smckusick 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
7258143Smckusick 		return;
7268143Smckusick 	case 1:
7278143Smckusick 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
7288143Smckusick 		return;
7298143Smckusick 	default:
7308143Smckusick #ifdef STANDALONE
7318143Smckusick 		printf("clrblock bad fs_frag %d\n", fs->fs_frag);
7328143Smckusick #else
7338143Smckusick 		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
7348143Smckusick #endif
7358143Smckusick 		return;
7368143Smckusick 	}
7378143Smckusick }
7388143Smckusick 
7398143Smckusick /*
7408143Smckusick  * put a block into the map
7418143Smckusick  */
7425326Smckusic setblock(fs, cp, h)
7435326Smckusic 	struct fs *fs;
7445326Smckusic 	unsigned char *cp;
7455326Smckusic 	int h;
7465326Smckusic {
7475326Smckusic 	switch (fs->fs_frag) {
7485326Smckusic 	case 8:
7495326Smckusic 		cp[h] = 0xff;
7505326Smckusic 		return;
7515326Smckusic 	case 4:
7525326Smckusic 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
7535326Smckusic 		return;
7545326Smckusic 	case 2:
7555326Smckusic 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
7565326Smckusic 		return;
7575326Smckusic 	case 1:
7585326Smckusic 		cp[h >> 3] |= (0x01 << (h & 0x7));
7595326Smckusic 		return;
7605326Smckusic 	default:
7618143Smckusick #ifdef STANDALONE
7628143Smckusick 		printf("setblock bad fs_frag %d\n", fs->fs_frag);
7638143Smckusick #else
7645326Smckusic 		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
7658143Smckusick #endif
7665326Smckusic 		return;
7675326Smckusic 	}
7685326Smckusic }
7696490Smckusick 
7706490Smckusick /*	tables.c	4.1	82/03/25	*/
7716490Smckusick 
7726490Smckusick /* merged into kernel:	tables.c 2.1 3/25/82 */
7736490Smckusick 
7746490Smckusick /* last monet version:	partab.c	4.2	81/03/08	*/
7756490Smckusick 
7766490Smckusick /*
7776490Smckusick  * bit patterns for identifying fragments in the block map
7786490Smckusick  * used as ((map & around) == inside)
7796490Smckusick  */
7806490Smckusick int around[9] = {
7816490Smckusick 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
7826490Smckusick };
7836490Smckusick int inside[9] = {
7846490Smckusick 	0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
7856490Smckusick };
7866490Smckusick 
7876490Smckusick /*
7886490Smckusick  * given a block map bit pattern, the frag tables tell whether a
7896490Smckusick  * particular size fragment is available.
7906490Smckusick  *
7916490Smckusick  * used as:
7926490Smckusick  * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
7936490Smckusick  *	at least one fragment of the indicated size is available
7946490Smckusick  * }
7956490Smckusick  *
7966490Smckusick  * These tables are used by the scanc instruction on the VAX to
7976490Smckusick  * quickly find an appropriate fragment.
7986490Smckusick  */
7996490Smckusick 
8006490Smckusick unsigned char fragtbl124[256] = {
8016490Smckusick 	0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
8026490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
8036490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8046490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8056490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8066490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8076490Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
8086490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
8096490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8106490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8116490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8126490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8136490Smckusick 	0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
8146490Smckusick 	0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
8156490Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
8166490Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
8176490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8186490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8196490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8206490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8216490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
8226490Smckusick 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
8236490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
8246490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
8256490Smckusick 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
8266490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
8276490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
8286490Smckusick 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
8296490Smckusick 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
8306490Smckusick 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
8316490Smckusick 	0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
8326490Smckusick 	0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
8336490Smckusick };
8346490Smckusick 
8356490Smckusick unsigned char fragtbl8[256] = {
8366490Smckusick 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
8376490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
8386490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8396490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
8406490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8416490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8426490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8436490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
8446490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8456490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8466490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8476490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
8486490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8496490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
8506490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
8516490Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
8526490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8536490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8546490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8556490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
8566490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
8576490Smckusick 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
8586490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
8596490Smckusick 	0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
8606490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
8616490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
8626490Smckusick 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
8636490Smckusick 	0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
8646490Smckusick 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
8656490Smckusick 	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
8666490Smckusick 	0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
8676490Smckusick 	0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
8686490Smckusick };
8696490Smckusick 
8706490Smckusick /*
8716490Smckusick  * the actual fragtbl array
8726490Smckusick  */
8736490Smckusick unsigned char *fragtbl[MAXFRAG + 1] = {
8746490Smckusick 	0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
8756490Smckusick };
876