V10/cmd/icheck.c

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

#define	NI	4
#define	NB	500
#define	BITS	8
#define	MAXFN	500

#include <stdio.h>
#include <sys/param.h>
#include <sys/inode.h>
#include <sys/ino.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/stat.h>

#define	BITFSBIT	64	/* should be in param.h */
#define	BIGINOPB	INOPB(BITFSBIT)
#define	BIGBSIZE	BSIZE(BITFSBIT)
#define	BIGNINDIR	NINDIR(BITFSBIT)

struct	filsys	sblock;
struct	stat	status;
#define	dev	status.st_rdev
struct	dinode	itab[BIGINOPB*NI];
daddr_t	iaddr[NADDR];
daddr_t	blist[NB];
char	*bmap;

int	sflg;
int	mflg;
int	dflg;
int	eflg;
int	fi;
long	ino;
int	bigflag;

ino_t	nrfile;
ino_t	ndfile;
ino_t	nbfile;
ino_t	ncfile;
ino_t	nlfile;

daddr_t	ndirect;
daddr_t	nindir;
daddr_t	niindir;
daddr_t	niiindir;
daddr_t	nfree;
daddr_t	ndup;
daddr_t	maxblk;

int	nerror;

long	atol();
daddr_t	alloc();
char	*malloc();
char	*memset();
time_t	time();
long	lseek();
void	sync();

main(argc, argv)
char *argv[];
{
	register i;
	long n;

	setbuf(stdout, (char *)NULL);
	blist[0] = -1;
	while (--argc) {
		argv++;
		if (**argv=='-')
		switch ((*argv)[1]) {
		case 'd':
			dflg++;
			continue;

		case 'e':
			eflg++;
			continue;

		case 'm':
			mflg++;
			continue;

		case 's':
			sflg++;
			continue;

		case 'b':
			for(i=0; i<NB; i++) {
				n = atol(argv[1]);
				if(n == 0)
					break;
				blist[i] = n;
				argv++;
				argc--;
			}
			blist[i] = -1;
			continue;

		case 'B':
			bigflag = BITFSBIT;
			continue;

		default:
			fprintf(stderr, "Bad flag\n");
		}
		check(*argv);
	}
	return(nerror);
}

check(file)
char *file;
{
	register i, j;
	long mino;
	daddr_t d;
	long n;

	fi = open(file, sflg?2:0);
	if (fi < 0) {
		fprintf(stderr, "cannot open %s\n", file);
		nerror |= 04;
		return;
	}
	if (fstat(fi, &status) < 0) {
		fprintf(stderr, "cannot fstat %s\n", file);
		nerror |= 04;
		close(fi);
		return;
	}
	if ((status.st_mode & S_IFMT) == S_IFREG)
		dev = makedev(0, bigflag);
	printf("%s:\n", file);
	nrfile = 0;
	ndfile = 0;
	ncfile = 0;
	nbfile = 0;
	nlfile = 0;

	ndirect = 0;
	nindir = 0;
	niindir = 0;
	niiindir = 0;

	ndup = 0;
	sync();
	bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
	mino = ((int)sblock.s_isize-2) * INOPB(dev);
	ino = 0;
	maxblk = sblock.s_fsize;
	/*
	 * fudge for new bitmapped filesystems
	 * this should be isolated somewhere
	 */
	if (BITFS(dev) && sblock.U.N.S_flag) {
		n = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
		maxblk -= n;
	}
	n = (maxblk - (int)sblock.s_isize + BITS-1) / BITS;
	if (n != (unsigned)n) {
		fprintf(stderr, "Check fsize and isize: %ld, %u\n",
		   maxblk, (int)sblock.s_isize);
	}
	bmap = malloc((unsigned)n);
	if (bmap==NULL) {
		fprintf(stderr, "Not enough core; duplicates unchecked\n");
		dflg++;
		sflg = 0;
	}
	if(!dflg)
	for(i=0; i<(unsigned)n; i++)
		bmap[i] = 0;
	for(i=2;; i+=NI) {
		if(ino >= mino)
			break;
		bread((daddr_t)i, (char *)itab, BSIZE(dev)*NI);
		for(j=0; j<INOPB(dev)*NI; j++) {
			if(ino >= mino)
				break;
			ino++;
			pass1(&itab[j]);
		}
	}
	ino = 0;
	sync();
	bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
	if (sflg) {
		makefree();
		close(fi);
		if (bmap)
			free(bmap);
		return;
	}
	nfree = 0;
	while(n = alloc()) {
		if (chk(0, n, "free"))
			break;
		nfree++;
	}
	close(fi);

	i = nrfile + ndfile + ncfile + nbfile + nlfile;
	printf("files %6u (r=%u,d=%u,b=%u,c=%u,l=%u)\n",
		i, nrfile, ndfile, nbfile, ncfile, nlfile);
	n = ndirect + nindir + niindir + niiindir;
	printf("used %7ld (i=%ld,ii=%ld,iii=%ld,d=%ld)\n",
		n, nindir, niindir, niiindir, ndirect);
	printf("free %7ld\n", nfree);
	if(!dflg) {
		n = 0;
		for(d=(int)sblock.s_isize; d<maxblk; d++)
			if(!duped(d)) {
				if(mflg)
					printf("%ld missing\n", d);
				n++;
			}
		printf("missing%5ld\n", n);
	}
	if (bmap)
		free(bmap);
}

pass1(ip)
register struct dinode *ip;
{
	daddr_t ind1[BIGNINDIR];
	daddr_t ind2[BIGNINDIR];
	daddr_t ind3[BIGNINDIR];
	register i, j;
	int k, l;
	int squawked = 0;

	i = ip->di_mode & IFMT;
	if(i == 0) {
		sblock.s_tinode++;
		return;
	}
	if(i == IFCHR) {
		ncfile++;
		return;
	}
	if(i == IFBLK) {
		nbfile++;
		return;
	}
	if(i == IFDIR)
		ndfile++;
	else if(i == IFREG)
		nrfile++;
	else if(i == IFLNK)
		nlfile++;
	else {
		printf("bad mode %u\n", ino);
		return;
	}
	l3tol(iaddr, ip->di_addr, NADDR);
	for(i=0; i<NADDR; i++) {
		if(iaddr[i] == 0)
			continue;
		if(i < NADDR-3) {
			ndirect++;
			chk(squawked++, iaddr[i], "data (small)");
			continue;
		}
		nindir++;
		if (chk(squawked++, iaddr[i], "1st indirect"))
				continue;
		bread(iaddr[i], (char *)ind1, BSIZE(dev));
		for(j=0; j<NINDIR(dev); j++) {
			if(ind1[j] == 0)
				continue;
			if(i == NADDR-3) {
				ndirect++;
				chk(squawked++, ind1[j], "data (large)");
				continue;
			}
			niindir++;
			if(chk(squawked++, ind1[j], "2nd indirect"))
				continue;
			bread(ind1[j], (char *)ind2, BSIZE(dev));
			for(k=0; k<NINDIR(dev); k++) {
				if(ind2[k] == 0)
					continue;
				if(i == NADDR-2) {
					ndirect++;
					chk(squawked++, ind2[k], "data (huge)");
					continue;
				}
				niiindir++;
				if(chk(squawked++, ind2[k], "3rd indirect"))
					continue;
				bread(ind2[k], (char *)ind3, BSIZE(dev));
				for(l=0; l<NINDIR(dev); l++)
					if(ind3[l]) {
						ndirect++;
						chk(squawked++, ind3[l], "data (garg)");
					}
			}
		}
	}
}

chk(loud, bno, s)
daddr_t bno;
char *s;
{
	register n;

	for (n=0; blist[n] != -1; n++)
		if (bno == blist[n])
			printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
	if (bno<(int)sblock.s_isize || bno>=maxblk) {
		if (loud == 0 || eflg == 0)
			printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
		return(1);
	}
	if(duped(bno)) {
		if (loud == 0)
			printf("%ld dup; inode=%u, class=%s\n", bno, ino, s);
		ndup++;
	}
	return(0);
}

duped(bno)
daddr_t bno;
{
	daddr_t d;
	register m, n;

	if(dflg)
		return(0);
	d = bno - (int)sblock.s_isize;
	m = 1 << (d%BITS);
	n = (d/BITS);
	if(bmap[n] & m)
		return(1);
	bmap[n] |= m;
	return(0);
}

daddr_t bitfsalloc(), bigfsalloc();

daddr_t
alloc()
{
	daddr_t bno;
	union {
		char	data[BIGBSIZE];
		struct	fblk fb;
	} buf;
	register int i;

	sblock.s_tfree--;
	if (BITFS(dev)) {
		if (sblock.U.N.S_flag)
			return (bigfsalloc());
		return (bitfsalloc());
	}
	if (sblock.s_nfree<=0)
		return(0);
	if (sblock.s_nfree>NICFREE) {
		fprintf(stderr, "Bad free list, s.b. count = %d\n", sblock.s_nfree);
		return(0);
	}
	bno = sblock.s_free[--sblock.s_nfree];
	sblock.s_free[sblock.s_nfree] = (daddr_t)0;
	if(bno == 0)
		return(bno);
	if(sblock.s_nfree <= 0) {
		bread(bno, buf.data, BSIZE(dev));
		sblock.s_nfree = buf.fb.df_nfree;
		if (sblock.s_nfree<0 || sblock.s_nfree>NICFREE) {
			fprintf(stderr, "Bad free list, entry count of block %ld = %d\n",
				bno, sblock.s_nfree);
			sblock.s_nfree = 0;
			return(0);
		}
		for(i=0; i<NICFREE; i++)
			sblock.s_free[i] = buf.fb.df_free[i];
	}
	return(bno);
}

daddr_t
bitfsalloc()
{
	daddr_t bno;
	register long *p;
	register int i, j;

	p = sblock.s_bfree;
	for(i = 0; i < BITMAP && *p == 0; i++, p++)
		;
	if(i >= BITMAP)
		return (0);
	bno = sblock.s_isize + BITCELL * i;
	for(j = 0; j < BITCELL; j++)
		if(*p & (1 << j))
			break;
	if(j >= BITCELL)
		return (0);
	bno += j;
	if(bno >= sblock.s_fsize)
		return (0);
	*p &= ~(1 << j);
	return (bno);
}

daddr_t
bigfsalloc()
{
	register long *p;
	register int i;
	int nblk;
	static long *flist, *fend;
	daddr_t bno;

	if (flist == NULL) {
		if (sblock.U.N.S_bsize == 0)	/* unlikely */
			sblock.U.N.S_bsize = BIGBSIZE*NBBY;
		nblk = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
		if ((flist = (long *)malloc(nblk*BIGBSIZE)) == NULL) {
			fprintf(stderr, "no mem for free bitmap\n");
			return (0);
		}
		bno = sblock.s_fsize - nblk;
		fend = flist;
		for (i = 0; i < nblk; i++, bno++, fend += BIGBSIZE/sizeof(long))
			bread(bno, (char *)fend, BIGBSIZE);
	}
	for (p = flist; p < fend && *p == 0; p++)
		;
	if (p >= fend)
		return (0);
	for (i = 0; i < BITCELL; i++)
		if (*p & (1<<i))
			break;
	if (i >= BITCELL)
		return (0);	/* shouldn't happen */
	bno = i + (p - flist)*BITCELL;
	if (bno >= maxblk)
		return (0);
	*p &=~ (1<<i);
	return (bno);
}


bread(bno, buf, cnt)
daddr_t bno;
char *buf;
{
	register i;

	lseek(fi, bno*BSIZE(dev), 0);
	if (read(fi, buf, cnt) != cnt) {
		fprintf(stderr, "read error %ld\n", bno);
		if (sflg) {
			fprintf(stderr, "No update\n");
			sflg = 0;
		}
		for(i=0; i<BSIZE(dev); i++)
			buf[i] = 0;
	}
}

bwrite(bno, buf)
daddr_t bno;
char	*buf;
{

	lseek(fi, bno*BSIZE(dev), 0);
	if (write(fi, buf, BSIZE(dev)) != BSIZE(dev))
		fprintf(stderr, "write error %ld\n", bno);
}

makefree()
{

	if (!BITFS(dev))
		makeoldfree();
	else if (sblock.U.N.S_flag == 0)
		makesbitfree();
	else
		makebbitfree();
}

makeoldfree()
{
	char flg[MAXFN];
	int adr[MAXFN];
	register i, j;
	daddr_t f, d;
	int m, n;

	n = sblock.s_n;
	if(n <= 0 || n > MAXFN)
		n = MAXFN;
	sblock.s_n = n;
	m = sblock.s_m;
	if(m <= 0 || m > sblock.s_n)
		m = 3;
	sblock.s_m = m;

	for(i=0; i<n; i++)
		flg[i] = 0;
	i = 0;
	for(j=0; j<n; j++) {
		while(flg[i])
			i = (i+1)%n;
		adr[j] = i+1;
		flg[i]++;
		i = (i+m)%n;
	}

	sblock.s_nfree = 0;
	sblock.s_ninode = 0;
	sblock.s_flock = 0;
	sblock.s_ilock = 0;
	sblock.s_fmod = 0;
	sblock.s_ronly = 0;
	time(&sblock.s_time);

	bfree((daddr_t)0);
	sblock.s_tfree = 0;
	sblock.s_tinode = 0;
	d = maxblk-1;
	while(d%sblock.s_n)
		d++;
	for(; d > 0; d -= sblock.s_n)
	for(i=0; i<sblock.s_n; i++) {
		f = d - adr[i];
		if(f < maxblk && f >= (int)sblock.s_isize)
			if(!duped(f))
				bfree(f);
	}
	bwrite((daddr_t)1, (char *)&sblock);
	sync();
}

bfree(bno)
daddr_t bno;
{
	union {
		char	data[BIGBSIZE];
		struct	fblk fb;
	} buf;
	int i;

	sblock.s_tfree++;
	if(sblock.s_nfree >= NICFREE) {
		for(i=0; i<BSIZE(dev); i++)
			buf.data[i] = 0;
		buf.fb.df_nfree = sblock.s_nfree;
		for(i=0; i<NICFREE; i++)
			buf.fb.df_free[i] = sblock.s_free[i];
		bwrite(bno, buf.data);
		sblock.s_nfree = 0;
	}
	sblock.s_free[sblock.s_nfree] = bno;
	sblock.s_nfree++;
}

makesbitfree()
{
	register daddr_t bno;

	memset((char *)sblock.s_bfree, 0, BITMAP);
	sblock.s_tfree = 0;
	for (bno = sblock.s_isize; bno < maxblk; bno++)
		if (!duped(bno)) {
			BITFREE(sblock.s_bfree, bno-sblock.s_isize);
			sblock.s_tfree++;
		}
	sblock.s_valid = 1;
	bwrite((daddr_t)1, (char *)&sblock);
}

makebbitfree()
{
	register daddr_t bno;
	register long *flist;
	register int nblk, i;

	nblk = (sblock.s_fsize+sblock.U.N.S_bsize-1)/sblock.U.N.S_bsize;
	if ((flist = (long *)malloc(nblk*BIGBSIZE)) == NULL) {
		fprintf(stderr, "no mem for free bitmap\n");
		exit(1);	/* eh? */
	}
	memset((char *)flist, 0, nblk*BIGBSIZE);
	sblock.s_tfree = 0;
	for (bno = sblock.s_isize; bno < maxblk; bno++)
		if (!duped(bno)) {
			BITFREE(flist, bno);
			sblock.s_tfree++;
		}
	for (i = 0; i < nblk; i++)
		bwrite(sblock.s_fsize - nblk + i, ((char *)flist)+(i*BIGBSIZE));
	free((char *)flist);
	sblock.s_valid = 1;
	bwrite((daddr_t)1, (char *)&sblock);
}