xref: /original-bsd/sbin/ncheck/ncheck.c (revision 01e9891b)
1 static	char *sccsid = "@(#)ncheck.c	1.8 (Berkeley) 02/25/82";
2 /*
3  * ncheck -- obtain file names from reading filesystem
4  */
5 
6 #define	NB		500
7 #define	HSIZE		2503
8 #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
9 
10 #include "../h/param.h"
11 #include "../h/inode.h"
12 #include "../h/fs.h"
13 #include <stdio.h>
14 #include <ndir.h>
15 
16 struct	fs	sblock;
17 struct	dinode	itab[MAXIPG];
18 struct 	dinode	*gip;
19 ino_t	ilist[NB];
20 struct	htab
21 {
22 	ino_t	h_ino;
23 	ino_t	h_pino;
24 	char	*h_name;
25 } htab[HSIZE];
26 char strngtab[30 * HSIZE];
27 int strngloc;
28 
29 struct dirstuff {
30 	int loc;
31 	struct dinode *ip;
32 	char dbuf[MAXBSIZE];
33 };
34 
35 int	aflg;
36 int	sflg;
37 int	fi;
38 ino_t	ino;
39 int	nhent;
40 int	nxfile;
41 
42 int	nerror;
43 daddr_t	bmap();
44 long	atol();
45 struct htab *lookup();
46 
47 main(argc, argv)
48 	int argc;
49 	char *argv[];
50 {
51 	register i;
52 	long n;
53 
54 	while (--argc) {
55 		argv++;
56 		if (**argv=='-')
57 		switch ((*argv)[1]) {
58 
59 		case 'a':
60 			aflg++;
61 			continue;
62 
63 		case 'i':
64 			for(i=0; i<NB; i++) {
65 				n = atol(argv[1]);
66 				if(n == 0)
67 					break;
68 				ilist[i] = n;
69 				nxfile = i;
70 				argv++;
71 				argc--;
72 			}
73 			continue;
74 
75 		case 's':
76 			sflg++;
77 			continue;
78 
79 		default:
80 			fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]);
81 			nerror++;
82 		}
83 		check(*argv);
84 	}
85 	return(nerror);
86 }
87 
88 check(file)
89 	char *file;
90 {
91 	register int i, j, c;
92 	int nfiles;
93 
94 	fi = open(file, 0);
95 	if(fi < 0) {
96 		fprintf(stderr, "ncheck: cannot open %s\n", file);
97 		nerror++;
98 		return;
99 	}
100 	nhent = 0;
101 	printf("%s:\n", file);
102 	sync();
103 	bread(SBLOCK, (char *)&sblock, SBSIZE);
104 	if (sblock.fs_magic != FS_MAGIC) {
105 		printf("%s: not a file system\n", file);
106 		nerror++;
107 		return;
108 	}
109 	nfiles = sblock.fs_ipg * sblock.fs_ncg;
110 	if (nfiles > 65535) {
111 		printf("%s: %d is a preposterous number of files\n",
112 		    file, nfiles);
113 		nerror++;
114 		return;
115 	}
116 	ino = 0;
117 	for (c = 0; c < sblock.fs_ncg; c++) {
118 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
119 		    sblock.fs_ipg * sizeof (struct dinode));
120 		for(j=0; j<sblock.fs_ipg; j++) {
121 			pass1(&itab[j]);
122 			ino++;
123 		}
124 	}
125 	ilist[nxfile+1] = 0;
126 	ino = 0;
127 	for (c = 0; c < sblock.fs_ncg; c++) {
128 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
129 		    sblock.fs_ipg * sizeof (struct dinode));
130 		for(j=0; j<sblock.fs_ipg; j++) {
131 			pass2(&itab[j]);
132 			ino++;
133 		}
134 	}
135 	ino = 0;
136 	for (c = 0; c < sblock.fs_ncg; c++) {
137 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
138 		    sblock.fs_ipg * sizeof (struct dinode));
139 		for(j=0; j<sblock.fs_ipg; j++) {
140 			pass3(&itab[j]);
141 			ino++;
142 		}
143 	}
144 }
145 
146 pass1(ip)
147 	register struct dinode *ip;
148 {
149 	if((ip->di_mode & IFMT) != IFDIR) {
150 		if (sflg==0 || nxfile>=NB)
151 			return;
152 		if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR
153 		  || ip->di_mode&(ISUID|ISGID))
154 			ilist[nxfile++] = ino;
155 			return;
156 	}
157 	lookup(ino, 1);
158 }
159 
160 pass2(ip)
161 	register struct dinode *ip;
162 {
163 	register struct direct *dp;
164 	struct dirstuff dirp;
165 	struct htab *hp;
166 
167 	if((ip->di_mode&IFMT) != IFDIR)
168 		return;
169 	dirp.loc = 0;
170 	dirp.ip = ip;
171 	gip = ip;
172 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
173 		if(dp->d_ino == 0)
174 			continue;
175 		hp = lookup(dp->d_ino, 0);
176 		if(hp == 0)
177 			continue;
178 		if(dotname(dp))
179 			continue;
180 		hp->h_pino = ino;
181 		hp->h_name = &strngtab[strngloc];
182 		strngloc += strlen(dp->d_name) + 1;
183 		strcpy(hp->h_name, dp->d_name);
184 	}
185 }
186 
187 pass3(ip)
188 	register struct dinode *ip;
189 {
190 	register struct direct *dp;
191 	struct dirstuff dirp;
192 	int k;
193 
194 	if((ip->di_mode&IFMT) != IFDIR)
195 		return;
196 	dirp.loc = 0;
197 	dirp.ip = ip;
198 	gip = ip;
199 	for(dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
200 		if(dp->d_ino == 0)
201 			continue;
202 		if(aflg==0 && dotname(dp))
203 			continue;
204 		if(ilist[0] == 0)
205 			goto pr;
206 		for(k = 0; ilist[k] != 0; k++)
207 			if(ilist[k] == dp->d_ino)
208 				goto pr;
209 		continue;
210 	pr:
211 		printf("%u	", dp->d_ino);
212 		pname(ino, 0);
213 		printf("/%s", dp->d_name);
214 		if (lookup(dp->d_ino, 0))
215 			printf("/.");
216 		printf("\n");
217 	}
218 }
219 
220 /*
221  * get next entry in a directory.
222  */
223 struct direct *
224 readdir(dirp)
225 	register struct dirstuff *dirp;
226 {
227 	register struct direct *dp;
228 	daddr_t lbn, d;
229 
230 	for(;;) {
231 		if (dirp->loc >= dirp->ip->di_size)
232 			return NULL;
233 		if ((lbn = lblkno(&sblock, dirp->loc)) == 0) {
234 			d = bmap(lbn);
235 			if(d == 0)
236 				return NULL;
237 			bread(fsbtodb(&sblock, d), dirp->dbuf,
238 			    dblksize(&sblock, dirp->ip, lbn));
239 		}
240 		dp = (struct direct *)
241 		    (dirp->dbuf + blkoff(&sblock, dirp->loc));
242 		dirp->loc += dp->d_reclen;
243 		if (dp->d_ino == 0)
244 			continue;
245 		return (dp);
246 	}
247 }
248 
249 dotname(dp)
250 	register struct direct *dp;
251 {
252 
253 	if (dp->d_name[0]=='.')
254 		if (dp->d_name[1]==0 ||
255 		   (dp->d_name[1]=='.' && dp->d_name[2]==0))
256 			return(1);
257 	return(0);
258 }
259 
260 pname(i, lev)
261 	ino_t i;
262 	int lev;
263 {
264 	register struct htab *hp;
265 
266 	if (i==ROOTINO)
267 		return;
268 	if ((hp = lookup(i, 0)) == 0) {
269 		printf("???");
270 		return;
271 	}
272 	if (lev > 10) {
273 		printf("...");
274 		return;
275 	}
276 	pname(hp->h_pino, ++lev);
277 	printf("/%s", hp->h_name);
278 }
279 
280 struct htab *
281 lookup(i, ef)
282 	ino_t i;
283 	int ef;
284 {
285 	register struct htab *hp;
286 
287 	for (hp = &htab[i%HSIZE]; hp->h_ino;) {
288 		if (hp->h_ino==i)
289 			return(hp);
290 		if (++hp >= &htab[HSIZE])
291 			hp = htab;
292 	}
293 	if (ef==0)
294 		return(0);
295 	if (++nhent >= HSIZE) {
296 		fprintf(stderr, "ncheck: out of core-- increase HSIZE\n");
297 		exit(1);
298 	}
299 	hp->h_ino = i;
300 	return(hp);
301 }
302 
303 bread(bno, buf, cnt)
304 	daddr_t bno;
305 	char *buf;
306 	int cnt;
307 {
308 	register i;
309 
310 	lseek(fi, bno * DEV_BSIZE, 0);
311 	if (read(fi, buf, cnt) != cnt) {
312 		fprintf(stderr, "ncheck: read error %d\n", bno);
313 		for(i=0; i < cnt; i++)
314 			buf[i] = 0;
315 	}
316 }
317 
318 daddr_t
319 bmap(i)
320 	int i;
321 {
322 	daddr_t ibuf[MAXNINDIR];
323 
324 	if(i < NDADDR)
325 		return(gip->di_db[i]);
326 	i -= NDADDR;
327 	if(i > NINDIR(&sblock)) {
328 		fprintf(stderr, "ncheck: %u - huge directory\n", ino);
329 		return((daddr_t)0);
330 	}
331 	bread(fsbtodb(&sblock, gip->di_ib[i]), (char *)ibuf, sizeof(ibuf));
332 	return(ibuf[i]);
333 }
334