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