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