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