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