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