xref: /original-bsd/sbin/ncheck/ncheck.c (revision 34b2909f)
10322f2d8Sbostic /*-
2*34b2909fSbostic  * Copyright (c) 1988, 1990, 1993
3*34b2909fSbostic  *	The Regents of the University of California.  All rights reserved.
40322f2d8Sbostic  *
50322f2d8Sbostic  * %sccs.include.proprietary.c%
6f1da8928Sdist  */
7f1da8928Sdist 
8383590d1Ssam #ifndef lint
9*34b2909fSbostic static char copyright[] =
10*34b2909fSbostic "@(#) Copyright (c) 1988, 1990, 1993\n\
11*34b2909fSbostic 	The Regents of the University of California.  All rights reserved.\n";
120322f2d8Sbostic #endif /* not lint */
13f1da8928Sdist 
14f1da8928Sdist #ifndef lint
15*34b2909fSbostic static char sccsid[] = "@(#)ncheck.c	8.1 (Berkeley) 06/05/93";
160322f2d8Sbostic #endif /* not lint */
17f1da8928Sdist 
186dc40552Smckusick /*
196dc40552Smckusick  * ncheck -- obtain file names from reading filesystem
206dc40552Smckusick  */
216dc40552Smckusick 
226dc40552Smckusick #define	NB		500
23f33a7a54Smckusic #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
246dc40552Smckusick 
2527f5c0cfShibler #include <unistd.h>
268aae8c5aSmckusick #include <sys/param.h>
27383590d1Ssam #include <sys/dir.h>
285412f437Smckusick #include <sys/time.h>
29a342f826Sbostic #include <ufs/ufs/dinode.h>
30a342f826Sbostic #include <ufs/ffs/fs.h>
31a405466cSmckusic #include <stdio.h>
326dc40552Smckusick 
3381b035e3Sbostic struct	fs	*sblockp;
346fd30569Smckusick struct	dinode	itab[MAXBSIZE/sizeof(struct dinode)];
355ba00738Smckusic struct	dinode	*gip;
368aae8c5aSmckusick struct ilist {
378aae8c5aSmckusick 	ino_t	ino;
388aae8c5aSmckusick 	u_short	mode;
398aae8c5aSmckusick 	short	uid;
408aae8c5aSmckusick 	short	gid;
418aae8c5aSmckusick } ilist[NB];
426dc40552Smckusick struct	htab
436dc40552Smckusick {
446dc40552Smckusick 	ino_t	h_ino;
456dc40552Smckusick 	ino_t	h_pino;
46a405466cSmckusic 	char	*h_name;
4734d43c7fSmckusick } *htab;
4834d43c7fSmckusick char *strngtab;
4934d43c7fSmckusick long hsize;
50a405466cSmckusic int strngloc;
51a405466cSmckusic 
52a405466cSmckusic struct dirstuff {
53a405466cSmckusic 	int loc;
54a405466cSmckusic 	struct dinode *ip;
55a405466cSmckusic 	char dbuf[MAXBSIZE];
56a405466cSmckusic };
576dc40552Smckusick 
586dc40552Smckusick int	aflg;
596dc40552Smckusick int	sflg;
608aae8c5aSmckusick int	iflg; /* number of inodes being searched for */
618aae8c5aSmckusick int	mflg;
626dc40552Smckusick int	fi;
636dc40552Smckusick ino_t	ino;
646dc40552Smckusick int	nhent;
656dc40552Smckusick int	nxfile;
66e31db33dSmckusick int	dev_bsize = 1;
676dc40552Smckusick 
686dc40552Smckusick int	nerror;
696dc40552Smckusick daddr_t	bmap();
706dc40552Smckusick long	atol();
71e31db33dSmckusick char	*malloc(), *strcpy();
726dc40552Smckusick struct htab *lookup();
73e31db33dSmckusick struct direct *nreaddir();
746dc40552Smckusick 
main(argc,argv)756dc40552Smckusick main(argc, argv)
7612031433Smckusic 	int argc;
776dc40552Smckusick 	char *argv[];
786dc40552Smckusick {
796dc40552Smckusick 	long n;
806dc40552Smckusick 
816dc40552Smckusick 	while (--argc) {
826dc40552Smckusick 		argv++;
836dc40552Smckusick 		if (**argv=='-')
846dc40552Smckusick 		switch ((*argv)[1]) {
856dc40552Smckusick 
866dc40552Smckusick 		case 'a':
876dc40552Smckusick 			aflg++;
886dc40552Smckusick 			continue;
896dc40552Smckusick 
906dc40552Smckusick 		case 'i':
9181b035e3Sbostic 			for(iflg=0; iflg<NB && argc >= 2; iflg++) {
926dc40552Smckusick 				n = atol(argv[1]);
936dc40552Smckusick 				if(n == 0)
946dc40552Smckusick 					break;
958aae8c5aSmckusick 				ilist[iflg].ino = n;
968aae8c5aSmckusick 				nxfile = iflg;
976dc40552Smckusick 				argv++;
986dc40552Smckusick 				argc--;
996dc40552Smckusick 			}
1006dc40552Smckusick 			continue;
1016dc40552Smckusick 
1028aae8c5aSmckusick 		case 'm':
1038aae8c5aSmckusick 			mflg++;
1048aae8c5aSmckusick 			continue;
1058aae8c5aSmckusick 
1066dc40552Smckusick 		case 's':
1076dc40552Smckusick 			sflg++;
1086dc40552Smckusick 			continue;
1096dc40552Smckusick 
1106dc40552Smckusick 		default:
111e31db33dSmckusick 			(void) fprintf(stderr, "ncheck: bad flag %c\n",
112e31db33dSmckusick 			    (*argv)[1]);
1136dc40552Smckusick 			nerror++;
1146dc40552Smckusick 		}
1156dc40552Smckusick 		check(*argv);
1166dc40552Smckusick 	}
1176dc40552Smckusick 	return(nerror);
1186dc40552Smckusick }
1196dc40552Smckusick 
check(file)1206dc40552Smckusick check(file)
1216dc40552Smckusick 	char *file;
1226dc40552Smckusick {
12312031433Smckusic 	register int i, j, c;
1246dc40552Smckusick 
1256dc40552Smckusick 	fi = open(file, 0);
1266dc40552Smckusick 	if(fi < 0) {
127e31db33dSmckusick 		(void) fprintf(stderr, "ncheck: cannot open %s\n", file);
1286dc40552Smckusick 		nerror++;
1296dc40552Smckusick 		return;
1306dc40552Smckusick 	}
1316dc40552Smckusick 	nhent = 0;
132e31db33dSmckusick 	(void) printf("%s:\n", file);
1336dc40552Smckusick 	sync();
134dd06bf90Sbostic 	dev_bsize = 1;
13581b035e3Sbostic 	sblockp = (struct fs *)malloc((unsigned)SBSIZE);
13681b035e3Sbostic 	if (sblockp == 0) {
13781b035e3Sbostic 		(void) printf("icheck: couldn't malloc superblock memory\n");
13881b035e3Sbostic 		nerror++;
13981b035e3Sbostic 		return;
14081b035e3Sbostic 	}
14127f5c0cfShibler 	bread((daddr_t)SBOFF, (char *)sblockp, (long)SBSIZE);
14281b035e3Sbostic 	if (sblockp->fs_magic != FS_MAGIC) {
143e31db33dSmckusick 		(void) printf("%s: not a file system\n", file);
14412031433Smckusic 		nerror++;
14512031433Smckusic 		return;
14612031433Smckusic 	}
14781b035e3Sbostic 	dev_bsize = sblockp->fs_fsize / fsbtodb(sblockp, 1);
14881b035e3Sbostic 	hsize = sblockp->fs_ipg * sblockp->fs_ncg -
14981b035e3Sbostic 	    sblockp->fs_cstotal.cs_nifree + 1;
150e31db33dSmckusick 	htab = (struct htab *)malloc((unsigned)hsize * sizeof(struct htab));
151e31db33dSmckusick 	strngtab = malloc((unsigned)(30 * hsize));
15234d43c7fSmckusick 	if (htab == 0 || strngtab == 0) {
153e31db33dSmckusick 		(void) printf("not enough memory to allocate tables\n");
15434d43c7fSmckusick 		nerror++;
15534d43c7fSmckusick 		return;
15634d43c7fSmckusick 	}
1576dc40552Smckusick 	ino = 0;
15881b035e3Sbostic 	for (c = 0; c < sblockp->fs_ncg; c++) {
1596fd30569Smckusick 		for (i = 0;
16081b035e3Sbostic 		     i < sblockp->fs_ipg / INOPF(sblockp);
16181b035e3Sbostic 		     i += sblockp->fs_frag) {
16281b035e3Sbostic 			bread(fsbtodb(sblockp, cgimin(sblockp, c) + i),
16381b035e3Sbostic 			    (char *)itab, sblockp->fs_bsize);
16481b035e3Sbostic 			for (j = 0; j < INOPB(sblockp); j++) {
1658aae8c5aSmckusick 				if (itab[j].di_mode != 0)
1666dc40552Smckusick 					pass1(&itab[j]);
1676dc40552Smckusick 				ino++;
1686dc40552Smckusick 			}
1696dc40552Smckusick 		}
1706fd30569Smckusick 	}
1718aae8c5aSmckusick 	ilist[nxfile+1].ino = 0;
1726dc40552Smckusick 	ino = 0;
17381b035e3Sbostic 	for (c = 0; c < sblockp->fs_ncg; c++) {
1746fd30569Smckusick 		for (i = 0;
17581b035e3Sbostic 		     i < sblockp->fs_ipg / INOPF(sblockp);
17681b035e3Sbostic 		     i += sblockp->fs_frag) {
17781b035e3Sbostic 			bread(fsbtodb(sblockp, cgimin(sblockp, c) + i),
17881b035e3Sbostic 			    (char *)itab, sblockp->fs_bsize);
17981b035e3Sbostic 			for (j = 0; j < INOPB(sblockp); j++) {
1808aae8c5aSmckusick 				if (itab[j].di_mode != 0)
1816dc40552Smckusick 					pass2(&itab[j]);
1826dc40552Smckusick 				ino++;
1836dc40552Smckusick 			}
1846dc40552Smckusick 		}
1856fd30569Smckusick 	}
1866dc40552Smckusick 	ino = 0;
18781b035e3Sbostic 	for (c = 0; c < sblockp->fs_ncg; c++) {
1886fd30569Smckusick 		for (i = 0;
18981b035e3Sbostic 		     i < sblockp->fs_ipg / INOPF(sblockp);
19081b035e3Sbostic 		     i += sblockp->fs_frag) {
19181b035e3Sbostic 			bread(fsbtodb(sblockp, cgimin(sblockp, c) + i),
19281b035e3Sbostic 			    (char *)itab, sblockp->fs_bsize);
19381b035e3Sbostic 			for (j = 0; j < INOPB(sblockp); j++) {
1948aae8c5aSmckusick 				if (itab[j].di_mode != 0)
1956dc40552Smckusick 					pass3(&itab[j]);
1966dc40552Smckusick 				ino++;
1976dc40552Smckusick 			}
1986dc40552Smckusick 		}
1996fd30569Smckusick 	}
200e31db33dSmckusick 	(void) close(fi);
20134d43c7fSmckusick 	for (i = 0; i < hsize; i++)
2028aae8c5aSmckusick 		htab[i].h_ino = 0;
2038aae8c5aSmckusick 	for (i = iflg; i < NB; i++)
2048aae8c5aSmckusick 		ilist[i].ino = 0;
2058aae8c5aSmckusick 	nxfile = iflg;
2066dc40552Smckusick }
2076dc40552Smckusick 
pass1(ip)2086dc40552Smckusick pass1(ip)
2096dc40552Smckusick 	register struct dinode *ip;
2106dc40552Smckusick {
2118aae8c5aSmckusick 	int i;
2128aae8c5aSmckusick 
2138aae8c5aSmckusick 	if (mflg)
2148aae8c5aSmckusick 		for (i = 0; i < iflg; i++)
2158aae8c5aSmckusick 			if (ino == ilist[i].ino) {
2168aae8c5aSmckusick 				ilist[i].mode = ip->di_mode;
2178aae8c5aSmckusick 				ilist[i].uid = ip->di_uid;
2188aae8c5aSmckusick 				ilist[i].gid = ip->di_gid;
2198aae8c5aSmckusick 			}
2206dc40552Smckusick 	if ((ip->di_mode & IFMT) != IFDIR) {
2216dc40552Smckusick 		if (sflg==0 || nxfile>=NB)
2226dc40552Smckusick 			return;
2236dc40552Smckusick 		if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR
2248aae8c5aSmckusick 		  || ip->di_mode&(ISUID|ISGID)) {
2258aae8c5aSmckusick 			ilist[nxfile].ino = ino;
2268aae8c5aSmckusick 			ilist[nxfile].mode = ip->di_mode;
2278aae8c5aSmckusick 			ilist[nxfile].uid = ip->di_uid;
2288aae8c5aSmckusick 			ilist[nxfile++].gid = ip->di_gid;
2296dc40552Smckusick 			return;
2306dc40552Smckusick 		}
2318aae8c5aSmckusick 	}
232e31db33dSmckusick 	(void) lookup(ino, 1);
2336dc40552Smckusick }
2346dc40552Smckusick 
pass2(ip)2356dc40552Smckusick pass2(ip)
2366dc40552Smckusick 	register struct dinode *ip;
2376dc40552Smckusick {
238a405466cSmckusic 	register struct direct *dp;
239a405466cSmckusic 	struct dirstuff dirp;
2406dc40552Smckusick 	struct htab *hp;
2416dc40552Smckusick 
2426dc40552Smckusick 	if((ip->di_mode&IFMT) != IFDIR)
2436dc40552Smckusick 		return;
244a405466cSmckusic 	dirp.loc = 0;
245a405466cSmckusic 	dirp.ip = ip;
2465ba00738Smckusic 	gip = ip;
247e31db33dSmckusick 	for (dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) {
248a405466cSmckusic 		if(dp->d_ino == 0)
2496dc40552Smckusick 			continue;
250a405466cSmckusic 		hp = lookup(dp->d_ino, 0);
2516dc40552Smckusick 		if(hp == 0)
2526dc40552Smckusick 			continue;
2536dc40552Smckusick 		if(dotname(dp))
2546dc40552Smckusick 			continue;
2556dc40552Smckusick 		hp->h_pino = ino;
256a405466cSmckusic 		hp->h_name = &strngtab[strngloc];
257a405466cSmckusic 		strngloc += strlen(dp->d_name) + 1;
258e31db33dSmckusick 		(void) strcpy(hp->h_name, dp->d_name);
2596dc40552Smckusick 	}
2606dc40552Smckusick }
2616dc40552Smckusick 
pass3(ip)2626dc40552Smckusick pass3(ip)
2636dc40552Smckusick 	register struct dinode *ip;
2646dc40552Smckusick {
265a405466cSmckusic 	register struct direct *dp;
266a405466cSmckusic 	struct dirstuff dirp;
2676dc40552Smckusick 	int k;
2686dc40552Smckusick 
2696dc40552Smckusick 	if((ip->di_mode&IFMT) != IFDIR)
2706dc40552Smckusick 		return;
271a405466cSmckusic 	dirp.loc = 0;
272a405466cSmckusic 	dirp.ip = ip;
2735ba00738Smckusic 	gip = ip;
274e31db33dSmckusick 	for(dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) {
2756dc40552Smckusick 		if(aflg==0 && dotname(dp))
2766dc40552Smckusick 			continue;
2778aae8c5aSmckusick 		if(sflg == 0 && iflg == 0)
2786dc40552Smckusick 			goto pr;
2798aae8c5aSmckusick 		for(k = 0; ilist[k].ino != 0; k++)
2808aae8c5aSmckusick 			if(ilist[k].ino == dp->d_ino)
2818aae8c5aSmckusick 				break;
2828aae8c5aSmckusick 		if (ilist[k].ino == 0)
2836dc40552Smckusick 			continue;
2848aae8c5aSmckusick 		if (mflg)
285e31db33dSmckusick 			(void) printf("mode %-6o uid %-5d gid %-5d ino ",
2868aae8c5aSmckusick 			    ilist[k].mode, ilist[k].uid, ilist[k].gid);
2876dc40552Smckusick 	pr:
288e31db33dSmckusick 		(void) printf("%-5lu\t", dp->d_ino);
2896dc40552Smckusick 		pname(ino, 0);
290e31db33dSmckusick 		(void) printf("/%s", dp->d_name);
291a405466cSmckusic 		if (lookup(dp->d_ino, 0))
292e31db33dSmckusick 			(void) printf("/.");
293e31db33dSmckusick 		(void) printf("\n");
2946dc40552Smckusick 	}
2956dc40552Smckusick }
296a405466cSmckusic 
297a405466cSmckusic /*
298a405466cSmckusic  * get next entry in a directory.
299a405466cSmckusic  */
300a405466cSmckusic struct direct *
nreaddir(dirp)301e31db33dSmckusick nreaddir(dirp)
302a405466cSmckusic 	register struct dirstuff *dirp;
303a405466cSmckusic {
304a405466cSmckusic 	register struct direct *dp;
305a405466cSmckusic 	daddr_t lbn, d;
306a405466cSmckusic 
307a405466cSmckusic 	for(;;) {
308a405466cSmckusic 		if (dirp->loc >= dirp->ip->di_size)
309a405466cSmckusic 			return NULL;
31081b035e3Sbostic 		if (blkoff(sblockp, dirp->loc) == 0) {
31181b035e3Sbostic 			lbn = lblkno(sblockp, dirp->loc);
312a405466cSmckusic 			d = bmap(lbn);
313a405466cSmckusic 			if(d == 0)
314a405466cSmckusic 				return NULL;
31581b035e3Sbostic 			bread(fsbtodb(sblockp, d), dirp->dbuf,
31627f5c0cfShibler 			      (long)dblksize(sblockp, dirp->ip, lbn));
317a405466cSmckusic 		}
318a405466cSmckusic 		dp = (struct direct *)
31981b035e3Sbostic 		    (dirp->dbuf + blkoff(sblockp, dirp->loc));
320a405466cSmckusic 		dirp->loc += dp->d_reclen;
321a405466cSmckusic 		if (dp->d_ino == 0)
322a405466cSmckusic 			continue;
323a405466cSmckusic 		return (dp);
324a405466cSmckusic 	}
3256dc40552Smckusick }
3266dc40552Smckusick 
dotname(dp)3276dc40552Smckusick dotname(dp)
3286dc40552Smckusick 	register struct direct *dp;
3296dc40552Smckusick {
3306dc40552Smckusick 
3316dc40552Smckusick 	if (dp->d_name[0]=='.')
332a405466cSmckusic 		if (dp->d_name[1]==0 ||
333a405466cSmckusic 		   (dp->d_name[1]=='.' && dp->d_name[2]==0))
3346dc40552Smckusick 			return(1);
3356dc40552Smckusick 	return(0);
3366dc40552Smckusick }
3376dc40552Smckusick 
pname(i,lev)3386dc40552Smckusick pname(i, lev)
3396dc40552Smckusick 	ino_t i;
34012031433Smckusic 	int lev;
3416dc40552Smckusick {
3426dc40552Smckusick 	register struct htab *hp;
3436dc40552Smckusick 
3446dc40552Smckusick 	if (i==ROOTINO)
3456dc40552Smckusick 		return;
3466dc40552Smckusick 	if ((hp = lookup(i, 0)) == 0) {
347e31db33dSmckusick 		(void) printf("???");
3486dc40552Smckusick 		return;
3496dc40552Smckusick 	}
3506dc40552Smckusick 	if (lev > 10) {
351e31db33dSmckusick 		(void) printf("...");
3526dc40552Smckusick 		return;
3536dc40552Smckusick 	}
3546dc40552Smckusick 	pname(hp->h_pino, ++lev);
355e31db33dSmckusick 	(void) printf("/%s", hp->h_name);
3566dc40552Smckusick }
3576dc40552Smckusick 
3586dc40552Smckusick struct htab *
lookup(i,ef)3596dc40552Smckusick lookup(i, ef)
3606dc40552Smckusick 	ino_t i;
36112031433Smckusic 	int ef;
3626dc40552Smckusick {
3636dc40552Smckusick 	register struct htab *hp;
3646dc40552Smckusick 
36534d43c7fSmckusick 	for (hp = &htab[i%hsize]; hp->h_ino;) {
3666dc40552Smckusick 		if (hp->h_ino==i)
3676dc40552Smckusick 			return(hp);
36834d43c7fSmckusick 		if (++hp >= &htab[hsize])
3696dc40552Smckusick 			hp = htab;
3706dc40552Smckusick 	}
3716dc40552Smckusick 	if (ef==0)
3726dc40552Smckusick 		return(0);
37334d43c7fSmckusick 	if (++nhent >= hsize) {
374e31db33dSmckusick 		(void) fprintf(stderr, "ncheck: hsize of %ld is too small\n",
375e31db33dSmckusick 		    hsize);
3766dc40552Smckusick 		exit(1);
3776dc40552Smckusick 	}
3786dc40552Smckusick 	hp->h_ino = i;
3796dc40552Smckusick 	return(hp);
3806dc40552Smckusick }
3816dc40552Smckusick 
bread(bno,buf,lcount)382e31db33dSmckusick bread(bno, buf, lcount)
3836dc40552Smckusick 	daddr_t bno;
384e31db33dSmckusick 	register char *buf;
385e31db33dSmckusick 	long lcount;
3866dc40552Smckusick {
387e31db33dSmckusick 	register int i, cnt = lcount;
388e31db33dSmckusick 	register off_t off = bno * dev_bsize;
3896dc40552Smckusick 
39006eb82aeSralph 	(void) lseek(fi, off, SEEK_SET);
3916dc40552Smckusick 	if (read(fi, buf, cnt) != cnt) {
392e31db33dSmckusick 		(void) fprintf(stderr, "ncheck: read error %ld\n", bno);
393e31db33dSmckusick 		if (cnt % dev_bsize) {
394e31db33dSmckusick 			/* THIS INDICATES A SERIOUS BUG */
395e31db33dSmckusick 			/* bzero is probably not correct, but will do */
396e31db33dSmckusick 			(void) fprintf(stderr,
397e31db33dSmckusick 			    "ncheck: bread: cnt %d not multiple of %d\n",
398e31db33dSmckusick 			    cnt, dev_bsize);
399e31db33dSmckusick 			bzero(buf, cnt);
400e31db33dSmckusick 			return;
401e31db33dSmckusick 		}
402e31db33dSmckusick 		for (i = 0; i < cnt; i += dev_bsize) {
40306eb82aeSralph 			(void) lseek(fi, off, SEEK_SET);
404e31db33dSmckusick 			if (read(fi, buf, dev_bsize) != dev_bsize) {
405e31db33dSmckusick 				(void) fprintf(stderr,
406e31db33dSmckusick 				    "ncheck: re-read error %ld\n", bno);
407e31db33dSmckusick 				bzero(buf, dev_bsize);
408e31db33dSmckusick 			}
409e31db33dSmckusick 			off += dev_bsize;
410e31db33dSmckusick 			buf += dev_bsize;
411e31db33dSmckusick 			bno++;
412e31db33dSmckusick 		}
4136dc40552Smckusick 	}
4146dc40552Smckusick }
4156dc40552Smckusick 
4168a858b35Sbostic /*
4178a858b35Sbostic  * Swiped from standalone sys.c.
4188a858b35Sbostic  */
4198a858b35Sbostic #define	NBUFS	4
4208a858b35Sbostic char	b[NBUFS][MAXBSIZE];
4218a858b35Sbostic daddr_t	blknos[NBUFS];
4226dc40552Smckusick 
4238a858b35Sbostic daddr_t
bmap(bn)4248a858b35Sbostic bmap(bn)
4258a858b35Sbostic 	register daddr_t bn;
4268a858b35Sbostic {
4278a858b35Sbostic 	register int j;
4288a858b35Sbostic 	int i, sh;
4298a858b35Sbostic 	daddr_t nb, *bap;
4308a858b35Sbostic 
4318a858b35Sbostic 	if (bn < 0) {
432e31db33dSmckusick 		(void) fprintf(stderr, "ncheck: bn %ld negative\n", bn);
4336dc40552Smckusick 		return ((daddr_t)0);
4346dc40552Smckusick 	}
4358a858b35Sbostic 
4368a858b35Sbostic 	/*
4378a858b35Sbostic 	 * blocks 0..NDADDR are direct blocks
4388a858b35Sbostic 	 */
4398a858b35Sbostic 	if(bn < NDADDR)
4408a858b35Sbostic 		return(gip->di_db[bn]);
4418a858b35Sbostic 
4428a858b35Sbostic 	/*
4438a858b35Sbostic 	 * addresses NIADDR have single and double indirect blocks.
4448a858b35Sbostic 	 * the first step is to determine how many levels of indirection.
4458a858b35Sbostic 	 */
4468a858b35Sbostic 	sh = 1;
4478a858b35Sbostic 	bn -= NDADDR;
4488a858b35Sbostic 	for (j = NIADDR; j > 0; j--) {
44981b035e3Sbostic 		sh *= NINDIR(sblockp);
4508a858b35Sbostic 		if (bn < sh)
4518a858b35Sbostic 			break;
4528a858b35Sbostic 		bn -= sh;
4538a858b35Sbostic 	}
4548a858b35Sbostic 	if (j == 0) {
455e31db33dSmckusick 		(void) printf("ncheck: bn %ld ovf, ino %lu\n", bn, ino);
4568a858b35Sbostic 		return ((daddr_t)0);
4578a858b35Sbostic 	}
4588a858b35Sbostic 
4598a858b35Sbostic 	/*
4608a858b35Sbostic 	 * fetch the first indirect block address from the inode
4618a858b35Sbostic 	 */
4628a858b35Sbostic 	nb = gip->di_ib[NIADDR - j];
4638a858b35Sbostic 	if (nb == 0) {
464e31db33dSmckusick 		(void) printf("ncheck: bn %ld void1, ino %lu\n", bn, ino);
4658a858b35Sbostic 		return ((daddr_t)0);
4668a858b35Sbostic 	}
4678a858b35Sbostic 
4688a858b35Sbostic 	/*
4698a858b35Sbostic 	 * fetch through the indirect blocks
4708a858b35Sbostic 	 */
4718a858b35Sbostic 	for (; j <= NIADDR; j++) {
4728a858b35Sbostic 		if (blknos[j] != nb) {
47381b035e3Sbostic 			bread(fsbtodb(sblockp, nb), b[j], sblockp->fs_bsize);
4748a858b35Sbostic 			blknos[j] = nb;
4758a858b35Sbostic 		}
4768a858b35Sbostic 		bap = (daddr_t *)b[j];
47781b035e3Sbostic 		sh /= NINDIR(sblockp);
47881b035e3Sbostic 		i = (bn / sh) % NINDIR(sblockp);
4798a858b35Sbostic 		nb = bap[i];
4808a858b35Sbostic 		if(nb == 0) {
481e31db33dSmckusick 			(void) printf("ncheck: bn %ld void2, ino %lu\n", bn,
482e31db33dSmckusick 			    ino);
4838a858b35Sbostic 			return ((daddr_t)0);
4848a858b35Sbostic 		}
4858a858b35Sbostic 	}
4868a858b35Sbostic 	return (nb);
4876dc40552Smckusick }
488