add fixes per Jim Reeds, add -m flag to print out file modes
[unix-history] / usr / src / old / dcheck / dcheck.c
CommitLineData
3352e84a 1static char *sccsid = "@(#)dcheck.c 1.8 (Berkeley) %G%";
e19a5dd5
KM
2/*
3 * dcheck - check directory consistency
4 */
5#define NB 10
c312eebd 6#define MAXNINDIR (MAXBSIZE / sizeof (daddr_t))
e19a5dd5 7
e19a5dd5
KM
8#include "../h/param.h"
9#include "../h/inode.h"
e19a5dd5 10#include "../h/fs.h"
5086d197
KM
11#include <ndir.h>
12#include <stdio.h>
e19a5dd5
KM
13
14union {
15 struct fs fs;
b6407c9d 16 char pad[MAXBSIZE];
e19a5dd5
KM
17} fsun;
18#define sblock fsun.fs
19
5086d197
KM
20struct dirstuff {
21 int loc;
22 struct dinode *ip;
23 char dbuf[MAXBSIZE];
24};
25
e19a5dd5 26struct dinode itab[MAXIPG];
56d45dcd 27struct dinode *gip;
e19a5dd5
KM
28ino_t ilist[NB];
29
30int fi;
31ino_t ino;
32ino_t *ecount;
33int headpr;
34int nfiles;
35
36int nerror;
37daddr_t bmap();
38long atol();
39char *malloc();
40
41main(argc, argv)
42char *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
73check(file)
74char *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();
c312eebd 87 bread(SBLOCK, (char *)&sblock, SBSIZE);
e19a5dd5
KM
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++) {
6994bf5d 108 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
e19a5dd5
KM
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++) {
6994bf5d 117 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
e19a5dd5
KM
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
127pass1(ip)
5086d197 128 register struct dinode *ip;
e19a5dd5 129{
5086d197
KM
130 register struct direct *dp;
131 struct dirstuff dirp;
e19a5dd5 132 int k;
e19a5dd5
KM
133
134 if((ip->di_mode&IFMT) != IFDIR)
135 return;
5086d197
KM
136 dirp.loc = 0;
137 dirp.ip = ip;
56d45dcd 138 gip = ip;
5086d197
KM
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);
e19a5dd5 152 nerror++;
e19a5dd5 153 }
5086d197 154 ecount[dp->d_ino]++;
e19a5dd5
KM
155 }
156}
157
158pass2(ip)
159register 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
5086d197
KM
176/*
177 * get next entry in a directory.
178 */
179struct direct *
180readdir(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;
3352e84a 189 if ((lbn = lblkno(&sblock, dirp->loc)) == 0) {
5086d197
KM
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 *)
3352e84a 197 (dirp->dbuf + blkoff(&sblock, dirp->loc));
5086d197
KM
198 dirp->loc += dp->d_reclen;
199 if (dp->d_ino == 0)
200 continue;
201 return (dp);
202 }
203}
204
e19a5dd5
KM
205bread(bno, buf, cnt)
206daddr_t bno;
207char *buf;
208{
209 register i;
210
b6407c9d 211 lseek(fi, bno * DEV_BSIZE, 0);
e19a5dd5
KM
212 if (read(fi, buf, cnt) != cnt) {
213 printf("read error %d\n", bno);
b6407c9d 214 for(i=0; i < cnt; i++)
e19a5dd5
KM
215 buf[i] = 0;
216 }
217}
218
219daddr_t
220bmap(i)
221{
b6407c9d 222 daddr_t ibuf[MAXNINDIR];
e19a5dd5
KM
223
224 if(i < NDADDR)
56d45dcd 225 return(gip->di_db[i]);
e19a5dd5 226 i -= NDADDR;
b6407c9d 227 if(i > NINDIR(&sblock)) {
e19a5dd5
KM
228 printf("%u - huge directory\n", ino);
229 return((daddr_t)0);
230 }
b6407c9d 231 bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf));
e19a5dd5
KM
232 return(ibuf[i]);
233}