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