xref: /csrg-svn/old/dcheck/dcheck.c (revision 22489)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)dcheck.c	5.1 (Berkeley) 06/06/85";
15 #endif not lint
16 
17 /*
18  * dcheck - check directory consistency
19  */
20 #define	NB	10
21 #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
22 
23 #include <sys/param.h>
24 #include <sys/inode.h>
25 #include <sys/fs.h>
26 #include <sys/dir.h>
27 #include <stdio.h>
28 
29 union {
30 	struct	fs fs;
31 	char pad[MAXBSIZE];
32 } fsun;
33 #define	sblock	fsun.fs
34 
35 struct dirstuff {
36 	int loc;
37 	struct dinode *ip;
38 	char dbuf[MAXBSIZE];
39 };
40 
41 struct	dinode	itab[MAXIPG];
42 struct	dinode	*gip;
43 ino_t	ilist[NB];
44 
45 int	fi;
46 ino_t	ino;
47 ino_t	*ecount;
48 int	headpr;
49 int	nfiles;
50 
51 int	nerror;
52 daddr_t	bmap();
53 long	atol();
54 char	*malloc();
55 
56 main(argc, argv)
57 char *argv[];
58 {
59 	register i;
60 	long n;
61 
62 	while (--argc) {
63 		argv++;
64 		if (**argv=='-')
65 		switch ((*argv)[1]) {
66 
67 		case 'i':
68 			for(i=0; i<NB; i++) {
69 				n = atol(argv[1]);
70 				if(n == 0)
71 					break;
72 				ilist[i] = n;
73 				argv++;
74 				argc--;
75 			}
76 			ilist[i] = 0;
77 			continue;
78 
79 		default:
80 			printf("Bad flag %c\n", (*argv)[1]);
81 			nerror++;
82 		}
83 		check(*argv);
84 	}
85 	return(nerror);
86 }
87 
88 check(file)
89 char *file;
90 {
91 	register i, j, c;
92 
93 	fi = open(file, 0);
94 	if(fi < 0) {
95 		printf("cannot open %s\n", file);
96 		nerror++;
97 		return;
98 	}
99 	headpr = 0;
100 	printf("%s:\n", file);
101 	sync();
102 	bread(SBLOCK, (char *)&sblock, SBSIZE);
103 	if (sblock.fs_magic != FS_MAGIC) {
104 		printf("%s: not a file system\n", file);
105 		nerror++;
106 		return;
107 	}
108 	nfiles = sblock.fs_ipg * sblock.fs_ncg;
109 	ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount));
110 	if (ecount == 0) {
111 		printf("%s: not enough core for %d files\n", file, nfiles);
112 		exit(04);
113 	}
114 	for (i = 0; i<=nfiles; i++)
115 		ecount[i] = 0;
116 	ino = 0;
117 	for (c = 0; c < sblock.fs_ncg; c++) {
118 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
119 		    sblock.fs_ipg * sizeof (struct dinode));
120 		for (j = 0; j < sblock.fs_ipg; j++) {
121 			pass1(&itab[j]);
122 			ino++;
123 		}
124 	}
125 	ino = 0;
126 	for (c = 0; c < sblock.fs_ncg; c++) {
127 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
128 		    sblock.fs_ipg * sizeof (struct dinode));
129 		for (j = 0; j < sblock.fs_ipg; j++) {
130 			pass2(&itab[j]);
131 			ino++;
132 		}
133 	}
134 	free(ecount);
135 }
136 
137 pass1(ip)
138 	register struct dinode *ip;
139 {
140 	register struct direct *dp;
141 	struct dirstuff dirp;
142 	int k;
143 
144 	if((ip->di_mode&IFMT) != IFDIR)
145 		return;
146 	dirp.loc = 0;
147 	dirp.ip = ip;
148 	gip = ip;
149 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
150 		if(dp->d_ino == 0)
151 			continue;
152 		if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) {
153 			printf("%d bad; %d/%s\n",
154 			    dp->d_ino, ino, dp->d_name);
155 			nerror++;
156 			continue;
157 		}
158 		for (k = 0; ilist[k] != 0; k++)
159 			if (ilist[k] == dp->d_ino) {
160 				printf("%d arg; %d/%s\n",
161 				     dp->d_ino, ino, dp->d_name);
162 				nerror++;
163 			}
164 		ecount[dp->d_ino]++;
165 	}
166 }
167 
168 pass2(ip)
169 register struct dinode *ip;
170 {
171 	register i;
172 
173 	i = ino;
174 	if ((ip->di_mode&IFMT)==0 && ecount[i]==0)
175 		return;
176 	if (ip->di_nlink==ecount[i] && ip->di_nlink!=0)
177 		return;
178 	if (headpr==0) {
179 		printf("     entries  link cnt\n");
180 		headpr++;
181 	}
182 	printf("%u\t%d\t%d\n", ino,
183 	    ecount[i], ip->di_nlink);
184 }
185 
186 /*
187  * get next entry in a directory.
188  */
189 struct direct *
190 readdir(dirp)
191 	register struct dirstuff *dirp;
192 {
193 	register struct direct *dp;
194 	daddr_t lbn, d;
195 
196 	for(;;) {
197 		if (dirp->loc >= dirp->ip->di_size)
198 			return NULL;
199 		if ((lbn = lblkno(&sblock, dirp->loc)) == 0) {
200 			d = bmap(lbn);
201 			if(d == 0)
202 				return NULL;
203 			bread(fsbtodb(&sblock, d), dirp->dbuf,
204 			    dblksize(&sblock, dirp->ip, lbn));
205 		}
206 		dp = (struct direct *)
207 		    (dirp->dbuf + blkoff(&sblock, dirp->loc));
208 		dirp->loc += dp->d_reclen;
209 		if (dp->d_ino == 0)
210 			continue;
211 		return (dp);
212 	}
213 }
214 
215 bread(bno, buf, cnt)
216 daddr_t bno;
217 char *buf;
218 {
219 	register i;
220 
221 	lseek(fi, bno * DEV_BSIZE, 0);
222 	if (read(fi, buf, cnt) != cnt) {
223 		printf("read error %d\n", bno);
224 		for(i=0; i < cnt; i++)
225 			buf[i] = 0;
226 	}
227 }
228 
229 daddr_t
230 bmap(i)
231 {
232 	daddr_t ibuf[MAXNINDIR];
233 
234 	if(i < NDADDR)
235 		return(gip->di_db[i]);
236 	i -= NDADDR;
237 	if(i > NINDIR(&sblock)) {
238 		printf("%u - huge directory\n", ino);
239 		return((daddr_t)0);
240 	}
241 	bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf));
242 	return(ibuf[i]);
243 }
244