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