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