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