xref: /original-bsd/old/dcheck/dcheck.c (revision d4c43c37)
112d93969Sdist /*
212d93969Sdist  * Copyright (c) 1980 Regents of the University of California.
312d93969Sdist  * All rights reserved.  The Berkeley software License Agreement
412d93969Sdist  * specifies the terms and conditions for redistribution.
512d93969Sdist  */
612d93969Sdist 
704d02f54Ssam #ifndef lint
812d93969Sdist char copyright[] =
912d93969Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1012d93969Sdist  All rights reserved.\n";
1112d93969Sdist #endif not lint
1212d93969Sdist 
1312d93969Sdist #ifndef lint
14*d4c43c37Sbostic static char sccsid[] = "@(#)dcheck.c	5.4 (Berkeley) 07/30/89";
1512d93969Sdist #endif not lint
1612d93969Sdist 
1756c871baSmckusick /*
1856c871baSmckusick  * dcheck - check directory consistency
1956c871baSmckusick  */
2056c871baSmckusick #define	NB	10
219b43ab0cSmckusic #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
2256c871baSmckusick 
23b257f55fSmckusick #include <sys/param.h>
24*d4c43c37Sbostic #include <sys/time.h>
25*d4c43c37Sbostic #include <sys/vnode.h>
26*d4c43c37Sbostic #include <ufs/inode.h>
27*d4c43c37Sbostic #include <ufs/fs.h>
2804d02f54Ssam #include <sys/dir.h>
29a405466cSmckusic #include <stdio.h>
3056c871baSmckusick 
3156c871baSmckusick union {
3256c871baSmckusick 	struct	fs fs;
33c4a51231Smckusick 	char pad[SBSIZE];
3456c871baSmckusick } fsun;
3556c871baSmckusick #define	sblock	fsun.fs
3656c871baSmckusick 
37a405466cSmckusic struct dirstuff {
38a405466cSmckusic 	int loc;
39a405466cSmckusic 	struct dinode *ip;
40a405466cSmckusic 	char dbuf[MAXBSIZE];
41a405466cSmckusic };
42a405466cSmckusic 
43c4a51231Smckusick struct	dinode	itab[MAXBSIZE / sizeof(struct dinode)];
445ba00738Smckusic struct	dinode	*gip;
4556c871baSmckusick ino_t	ilist[NB];
4656c871baSmckusick 
4756c871baSmckusick int	fi;
4856c871baSmckusick ino_t	ino;
4956c871baSmckusick ino_t	*ecount;
5056c871baSmckusick int	headpr;
5156c871baSmckusick int	nfiles;
52397eaf9bSmckusick long	dev_bsize = 1;
5356c871baSmckusick 
5456c871baSmckusick int	nerror;
5556c871baSmckusick daddr_t	bmap();
5656c871baSmckusick long	atol();
5756c871baSmckusick char	*malloc();
5856c871baSmckusick 
main(argc,argv)5956c871baSmckusick main(argc, argv)
6056c871baSmckusick char *argv[];
6156c871baSmckusick {
6256c871baSmckusick 	register i;
6356c871baSmckusick 	long n;
6456c871baSmckusick 
6556c871baSmckusick 	while (--argc) {
6656c871baSmckusick 		argv++;
6756c871baSmckusick 		if (**argv=='-')
6856c871baSmckusick 		switch ((*argv)[1]) {
6956c871baSmckusick 
7056c871baSmckusick 		case 'i':
7156c871baSmckusick 			for(i=0; i<NB; i++) {
7256c871baSmckusick 				n = atol(argv[1]);
7356c871baSmckusick 				if(n == 0)
7456c871baSmckusick 					break;
7556c871baSmckusick 				ilist[i] = n;
7656c871baSmckusick 				argv++;
7756c871baSmckusick 				argc--;
7856c871baSmckusick 			}
7956c871baSmckusick 			ilist[i] = 0;
8056c871baSmckusick 			continue;
8156c871baSmckusick 
8256c871baSmckusick 		default:
8356c871baSmckusick 			printf("Bad flag %c\n", (*argv)[1]);
8456c871baSmckusick 			nerror++;
8556c871baSmckusick 		}
8656c871baSmckusick 		check(*argv);
8756c871baSmckusick 	}
8856c871baSmckusick 	return(nerror);
8956c871baSmckusick }
9056c871baSmckusick 
check(file)9156c871baSmckusick check(file)
9256c871baSmckusick char *file;
9356c871baSmckusick {
9456c871baSmckusick 	register i, j, c;
9556c871baSmckusick 
9656c871baSmckusick 	fi = open(file, 0);
9756c871baSmckusick 	if(fi < 0) {
9856c871baSmckusick 		printf("cannot open %s\n", file);
9956c871baSmckusick 		nerror++;
10056c871baSmckusick 		return;
10156c871baSmckusick 	}
10256c871baSmckusick 	headpr = 0;
10356c871baSmckusick 	printf("%s:\n", file);
10456c871baSmckusick 	sync();
105397eaf9bSmckusick 	bread(SBOFF, (char *)&sblock, SBSIZE);
10656c871baSmckusick 	if (sblock.fs_magic != FS_MAGIC) {
10756c871baSmckusick 		printf("%s: not a file system\n", file);
10856c871baSmckusick 		nerror++;
10956c871baSmckusick 		return;
11056c871baSmckusick 	}
111397eaf9bSmckusick 	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
11256c871baSmckusick 	nfiles = sblock.fs_ipg * sblock.fs_ncg;
11356c871baSmckusick 	ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount));
11456c871baSmckusick 	if (ecount == 0) {
11556c871baSmckusick 		printf("%s: not enough core for %d files\n", file, nfiles);
11656c871baSmckusick 		exit(04);
11756c871baSmckusick 	}
11856c871baSmckusick 	for (i = 0; i<=nfiles; i++)
11956c871baSmckusick 		ecount[i] = 0;
12056c871baSmckusick 	ino = 0;
12156c871baSmckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
122c4a51231Smckusick 		for (i = 0;
123c4a51231Smckusick 		     i < sblock.fs_ipg / INOPF(&sblock);
124c4a51231Smckusick 		     i += sblock.fs_frag) {
125c4a51231Smckusick 			bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
126c4a51231Smckusick 			    (char *)itab, sblock.fs_bsize);
127c4a51231Smckusick 			for (j = 0; j < INOPB(&sblock); j++) {
12856c871baSmckusick 				pass1(&itab[j]);
12956c871baSmckusick 				ino++;
13056c871baSmckusick 			}
13156c871baSmckusick 		}
132c4a51231Smckusick 	}
13356c871baSmckusick 	ino = 0;
13456c871baSmckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
135c4a51231Smckusick 		for (i = 0;
136c4a51231Smckusick 		     i < sblock.fs_ipg / INOPF(&sblock);
137c4a51231Smckusick 		     i += sblock.fs_frag) {
138c4a51231Smckusick 			bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
139c4a51231Smckusick 			    (char *)itab, sblock.fs_bsize);
140c4a51231Smckusick 			for (j = 0; j < INOPB(&sblock); j++) {
14156c871baSmckusick 				pass2(&itab[j]);
14256c871baSmckusick 				ino++;
14356c871baSmckusick 			}
14456c871baSmckusick 		}
145c4a51231Smckusick 	}
14656c871baSmckusick 	free(ecount);
14756c871baSmckusick }
14856c871baSmckusick 
pass1(ip)14956c871baSmckusick pass1(ip)
15056c871baSmckusick 	register struct dinode *ip;
15156c871baSmckusick {
152a405466cSmckusic 	register struct direct *dp;
153a405466cSmckusic 	struct dirstuff dirp;
15456c871baSmckusick 	int k;
15556c871baSmckusick 
15656c871baSmckusick 	if((ip->di_mode&IFMT) != IFDIR)
15756c871baSmckusick 		return;
158a405466cSmckusic 	dirp.loc = 0;
159a405466cSmckusic 	dirp.ip = ip;
1605ba00738Smckusic 	gip = ip;
161a405466cSmckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
162a405466cSmckusic 		if(dp->d_ino == 0)
16356c871baSmckusick 			continue;
164a405466cSmckusic 		if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) {
165a405466cSmckusic 			printf("%d bad; %d/%s\n",
166a405466cSmckusic 			    dp->d_ino, ino, dp->d_name);
16756c871baSmckusick 			nerror++;
16856c871baSmckusick 			continue;
16956c871baSmckusick 		}
17056c871baSmckusick 		for (k = 0; ilist[k] != 0; k++)
171a405466cSmckusic 			if (ilist[k] == dp->d_ino) {
172a405466cSmckusic 				printf("%d arg; %d/%s\n",
173a405466cSmckusic 				     dp->d_ino, ino, dp->d_name);
17456c871baSmckusick 				nerror++;
17556c871baSmckusick 			}
176a405466cSmckusic 		ecount[dp->d_ino]++;
17756c871baSmckusick 	}
17856c871baSmckusick }
17956c871baSmckusick 
pass2(ip)18056c871baSmckusick pass2(ip)
18156c871baSmckusick register struct dinode *ip;
18256c871baSmckusick {
18356c871baSmckusick 	register i;
18456c871baSmckusick 
18556c871baSmckusick 	i = ino;
18656c871baSmckusick 	if ((ip->di_mode&IFMT)==0 && ecount[i]==0)
18756c871baSmckusick 		return;
18856c871baSmckusick 	if (ip->di_nlink==ecount[i] && ip->di_nlink!=0)
18956c871baSmckusick 		return;
19056c871baSmckusick 	if (headpr==0) {
19156c871baSmckusick 		printf("     entries  link cnt\n");
19256c871baSmckusick 		headpr++;
19356c871baSmckusick 	}
19456c871baSmckusick 	printf("%u\t%d\t%d\n", ino,
19556c871baSmckusick 	    ecount[i], ip->di_nlink);
19656c871baSmckusick }
19756c871baSmckusick 
198a405466cSmckusic /*
199a405466cSmckusic  * get next entry in a directory.
200a405466cSmckusic  */
201a405466cSmckusic struct direct *
readdir(dirp)202a405466cSmckusic readdir(dirp)
203a405466cSmckusic 	register struct dirstuff *dirp;
204a405466cSmckusic {
205a405466cSmckusic 	register struct direct *dp;
206a405466cSmckusic 	daddr_t lbn, d;
207a405466cSmckusic 
208a405466cSmckusic 	for(;;) {
209a405466cSmckusic 		if (dirp->loc >= dirp->ip->di_size)
210a405466cSmckusic 			return NULL;
21142e3eb1bSmckusic 		if ((lbn = lblkno(&sblock, dirp->loc)) == 0) {
212a405466cSmckusic 			d = bmap(lbn);
213a405466cSmckusic 			if(d == 0)
214a405466cSmckusic 				return NULL;
215a405466cSmckusic 			bread(fsbtodb(&sblock, d), dirp->dbuf,
216a405466cSmckusic 			    dblksize(&sblock, dirp->ip, lbn));
217a405466cSmckusic 		}
218a405466cSmckusic 		dp = (struct direct *)
21942e3eb1bSmckusic 		    (dirp->dbuf + blkoff(&sblock, dirp->loc));
220a405466cSmckusic 		dirp->loc += dp->d_reclen;
221a405466cSmckusic 		if (dp->d_ino == 0)
222a405466cSmckusic 			continue;
223a405466cSmckusic 		return (dp);
224a405466cSmckusic 	}
225a405466cSmckusic }
226a405466cSmckusic 
bread(bno,buf,cnt)22756c871baSmckusick bread(bno, buf, cnt)
22856c871baSmckusick daddr_t bno;
22956c871baSmckusick char *buf;
23056c871baSmckusick {
23156c871baSmckusick 	register i;
23256c871baSmckusick 
233397eaf9bSmckusick 	lseek(fi, bno * dev_bsize, 0);
23456c871baSmckusick 	if (read(fi, buf, cnt) != cnt) {
23556c871baSmckusick 		printf("read error %d\n", bno);
2369b43ab0cSmckusic 		for(i=0; i < cnt; i++)
23756c871baSmckusick 			buf[i] = 0;
23856c871baSmckusick 	}
23956c871baSmckusick }
24056c871baSmckusick 
24156c871baSmckusick daddr_t
bmap(i)24256c871baSmckusick bmap(i)
24356c871baSmckusick {
2449b43ab0cSmckusic 	daddr_t ibuf[MAXNINDIR];
24556c871baSmckusick 
24656c871baSmckusick 	if(i < NDADDR)
2475ba00738Smckusic 		return(gip->di_db[i]);
24856c871baSmckusick 	i -= NDADDR;
2499b43ab0cSmckusic 	if(i > NINDIR(&sblock)) {
25056c871baSmckusick 		printf("%u - huge directory\n", ino);
25156c871baSmckusick 		return((daddr_t)0);
25256c871baSmckusick 	}
2539b43ab0cSmckusic 	bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf));
25456c871baSmckusick 	return(ibuf[i]);
25556c871baSmckusick }
256