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