Commit | Line | Data |
---|---|---|
c018628f DF |
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 | ||
80ee6eb3 | 7 | #ifndef lint |
c018628f DF |
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 | |
a66ab591 | 14 | static char sccsid[] = "@(#)ncheck.c 5.6 (Berkeley) %G%"; |
c018628f DF |
15 | #endif not lint |
16 | ||
d9c5783d KM |
17 | /* |
18 | * ncheck -- obtain file names from reading filesystem | |
19 | */ | |
20 | ||
b6407c9d | 21 | #define NB 500 |
c312eebd | 22 | #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) |
d9c5783d | 23 | |
61b11ef4 KM |
24 | #include <sys/param.h> |
25 | #include <sys/inode.h> | |
26 | #include <sys/fs.h> | |
80ee6eb3 | 27 | #include <sys/dir.h> |
5086d197 | 28 | #include <stdio.h> |
d9c5783d KM |
29 | |
30 | struct fs sblock; | |
31 | struct dinode itab[MAXIPG]; | |
56d45dcd | 32 | struct dinode *gip; |
61b11ef4 KM |
33 | struct ilist { |
34 | ino_t ino; | |
35 | u_short mode; | |
36 | short uid; | |
37 | short gid; | |
38 | } ilist[NB]; | |
d9c5783d KM |
39 | struct htab |
40 | { | |
41 | ino_t h_ino; | |
42 | ino_t h_pino; | |
5086d197 | 43 | char *h_name; |
9570c66d KM |
44 | } *htab; |
45 | char *strngtab; | |
46 | long hsize; | |
5086d197 KM |
47 | int strngloc; |
48 | ||
49 | struct dirstuff { | |
50 | int loc; | |
51 | struct dinode *ip; | |
52 | char dbuf[MAXBSIZE]; | |
53 | }; | |
d9c5783d KM |
54 | |
55 | int aflg; | |
56 | int sflg; | |
61b11ef4 KM |
57 | int iflg; /* number of inodes being searched for */ |
58 | int mflg; | |
d9c5783d KM |
59 | int fi; |
60 | ino_t ino; | |
61 | int nhent; | |
62 | int nxfile; | |
a66ab591 | 63 | long dev_bsize = 1; |
d9c5783d KM |
64 | |
65 | int nerror; | |
66 | daddr_t bmap(); | |
67 | long atol(); | |
68 | struct htab *lookup(); | |
69 | ||
70 | main(argc, argv) | |
20380c05 KM |
71 | int argc; |
72 | char *argv[]; | |
d9c5783d KM |
73 | { |
74 | register i; | |
75 | long n; | |
76 | ||
77 | while (--argc) { | |
78 | argv++; | |
79 | if (**argv=='-') | |
80 | switch ((*argv)[1]) { | |
81 | ||
82 | case 'a': | |
83 | aflg++; | |
84 | continue; | |
85 | ||
86 | case 'i': | |
61b11ef4 | 87 | for(iflg=0; iflg<NB; iflg++) { |
d9c5783d KM |
88 | n = atol(argv[1]); |
89 | if(n == 0) | |
90 | break; | |
61b11ef4 KM |
91 | ilist[iflg].ino = n; |
92 | nxfile = iflg; | |
d9c5783d KM |
93 | argv++; |
94 | argc--; | |
95 | } | |
96 | continue; | |
97 | ||
61b11ef4 KM |
98 | case 'm': |
99 | mflg++; | |
100 | continue; | |
101 | ||
d9c5783d KM |
102 | case 's': |
103 | sflg++; | |
104 | continue; | |
105 | ||
106 | default: | |
107 | fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]); | |
108 | nerror++; | |
109 | } | |
110 | check(*argv); | |
111 | } | |
112 | return(nerror); | |
113 | } | |
114 | ||
115 | check(file) | |
20380c05 | 116 | char *file; |
d9c5783d | 117 | { |
20380c05 KM |
118 | register int i, j, c; |
119 | int nfiles; | |
d9c5783d KM |
120 | |
121 | fi = open(file, 0); | |
122 | if(fi < 0) { | |
123 | fprintf(stderr, "ncheck: cannot open %s\n", file); | |
124 | nerror++; | |
125 | return; | |
126 | } | |
127 | nhent = 0; | |
128 | printf("%s:\n", file); | |
129 | sync(); | |
a66ab591 | 130 | bread(SBOFF, (char *)&sblock, SBSIZE); |
20380c05 KM |
131 | if (sblock.fs_magic != FS_MAGIC) { |
132 | printf("%s: not a file system\n", file); | |
133 | nerror++; | |
134 | return; | |
135 | } | |
a66ab591 | 136 | dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); |
9570c66d KM |
137 | hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1; |
138 | htab = (struct htab *)malloc(hsize * sizeof(struct htab)); | |
139 | strngtab = (char *)malloc(30 * hsize); | |
140 | if (htab == 0 || strngtab == 0) { | |
141 | printf("not enough memory to allocate tables\n"); | |
142 | nerror++; | |
143 | return; | |
144 | } | |
d9c5783d KM |
145 | ino = 0; |
146 | for (c = 0; c < sblock.fs_ncg; c++) { | |
6994bf5d | 147 | bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, |
d9c5783d | 148 | sblock.fs_ipg * sizeof (struct dinode)); |
61b11ef4 KM |
149 | for(j = 0; j < sblock.fs_ipg; j++) { |
150 | if (itab[j].di_mode != 0) | |
151 | pass1(&itab[j]); | |
d9c5783d KM |
152 | ino++; |
153 | } | |
154 | } | |
61b11ef4 | 155 | ilist[nxfile+1].ino = 0; |
d9c5783d KM |
156 | ino = 0; |
157 | for (c = 0; c < sblock.fs_ncg; c++) { | |
6994bf5d | 158 | bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, |
d9c5783d | 159 | sblock.fs_ipg * sizeof (struct dinode)); |
61b11ef4 KM |
160 | for(j = 0; j < sblock.fs_ipg; j++) { |
161 | if (itab[j].di_mode != 0) | |
162 | pass2(&itab[j]); | |
d9c5783d KM |
163 | ino++; |
164 | } | |
165 | } | |
166 | ino = 0; | |
167 | for (c = 0; c < sblock.fs_ncg; c++) { | |
6994bf5d | 168 | bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, |
d9c5783d | 169 | sblock.fs_ipg * sizeof (struct dinode)); |
61b11ef4 KM |
170 | for(j = 0; j < sblock.fs_ipg; j++) { |
171 | if (itab[j].di_mode != 0) | |
172 | pass3(&itab[j]); | |
d9c5783d KM |
173 | ino++; |
174 | } | |
175 | } | |
61b11ef4 | 176 | close(fi); |
9570c66d | 177 | for (i = 0; i < hsize; i++) |
61b11ef4 KM |
178 | htab[i].h_ino = 0; |
179 | for (i = iflg; i < NB; i++) | |
180 | ilist[i].ino = 0; | |
181 | nxfile = iflg; | |
d9c5783d KM |
182 | } |
183 | ||
184 | pass1(ip) | |
20380c05 | 185 | register struct dinode *ip; |
d9c5783d | 186 | { |
61b11ef4 KM |
187 | int i; |
188 | ||
189 | if (mflg) | |
190 | for (i = 0; i < iflg; i++) | |
191 | if (ino == ilist[i].ino) { | |
192 | ilist[i].mode = ip->di_mode; | |
193 | ilist[i].uid = ip->di_uid; | |
194 | ilist[i].gid = ip->di_gid; | |
195 | } | |
196 | if ((ip->di_mode & IFMT) != IFDIR) { | |
d9c5783d KM |
197 | if (sflg==0 || nxfile>=NB) |
198 | return; | |
199 | if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR | |
61b11ef4 KM |
200 | || ip->di_mode&(ISUID|ISGID)) { |
201 | ilist[nxfile].ino = ino; | |
202 | ilist[nxfile].mode = ip->di_mode; | |
203 | ilist[nxfile].uid = ip->di_uid; | |
204 | ilist[nxfile++].gid = ip->di_gid; | |
d9c5783d | 205 | return; |
61b11ef4 | 206 | } |
d9c5783d KM |
207 | } |
208 | lookup(ino, 1); | |
209 | } | |
210 | ||
211 | pass2(ip) | |
20380c05 | 212 | register struct dinode *ip; |
d9c5783d | 213 | { |
5086d197 KM |
214 | register struct direct *dp; |
215 | struct dirstuff dirp; | |
d9c5783d | 216 | struct htab *hp; |
d9c5783d KM |
217 | |
218 | if((ip->di_mode&IFMT) != IFDIR) | |
219 | return; | |
5086d197 KM |
220 | dirp.loc = 0; |
221 | dirp.ip = ip; | |
56d45dcd | 222 | gip = ip; |
5086d197 KM |
223 | for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { |
224 | if(dp->d_ino == 0) | |
225 | continue; | |
226 | hp = lookup(dp->d_ino, 0); | |
227 | if(hp == 0) | |
228 | continue; | |
229 | if(dotname(dp)) | |
230 | continue; | |
231 | hp->h_pino = ino; | |
232 | hp->h_name = &strngtab[strngloc]; | |
233 | strngloc += strlen(dp->d_name) + 1; | |
234 | strcpy(hp->h_name, dp->d_name); | |
d9c5783d KM |
235 | } |
236 | } | |
237 | ||
238 | pass3(ip) | |
20380c05 | 239 | register struct dinode *ip; |
d9c5783d | 240 | { |
5086d197 KM |
241 | register struct direct *dp; |
242 | struct dirstuff dirp; | |
d9c5783d | 243 | int k; |
d9c5783d KM |
244 | |
245 | if((ip->di_mode&IFMT) != IFDIR) | |
246 | return; | |
5086d197 KM |
247 | dirp.loc = 0; |
248 | dirp.ip = ip; | |
56d45dcd | 249 | gip = ip; |
5086d197 | 250 | for(dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { |
5086d197 KM |
251 | if(aflg==0 && dotname(dp)) |
252 | continue; | |
61b11ef4 | 253 | if(sflg == 0 && iflg == 0) |
5086d197 | 254 | goto pr; |
61b11ef4 KM |
255 | for(k = 0; ilist[k].ino != 0; k++) |
256 | if(ilist[k].ino == dp->d_ino) | |
257 | break; | |
258 | if (ilist[k].ino == 0) | |
259 | continue; | |
260 | if (mflg) | |
261 | printf("mode %-6o uid %-5d gid %-5d ino ", | |
262 | ilist[k].mode, ilist[k].uid, ilist[k].gid); | |
5086d197 | 263 | pr: |
61b11ef4 | 264 | printf("%-5u\t", dp->d_ino); |
5086d197 KM |
265 | pname(ino, 0); |
266 | printf("/%s", dp->d_name); | |
267 | if (lookup(dp->d_ino, 0)) | |
268 | printf("/."); | |
269 | printf("\n"); | |
270 | } | |
271 | } | |
272 | ||
273 | /* | |
274 | * get next entry in a directory. | |
275 | */ | |
276 | struct direct * | |
277 | readdir(dirp) | |
278 | register struct dirstuff *dirp; | |
279 | { | |
280 | register struct direct *dp; | |
281 | daddr_t lbn, d; | |
282 | ||
283 | for(;;) { | |
284 | if (dirp->loc >= dirp->ip->di_size) | |
285 | return NULL; | |
43cc0ec7 KM |
286 | if (blkoff(&sblock, dirp->loc) == 0) { |
287 | lbn = lblkno(&sblock, dirp->loc); | |
5086d197 KM |
288 | d = bmap(lbn); |
289 | if(d == 0) | |
290 | return NULL; | |
291 | bread(fsbtodb(&sblock, d), dirp->dbuf, | |
292 | dblksize(&sblock, dirp->ip, lbn)); | |
d9c5783d | 293 | } |
5086d197 | 294 | dp = (struct direct *) |
3352e84a | 295 | (dirp->dbuf + blkoff(&sblock, dirp->loc)); |
5086d197 KM |
296 | dirp->loc += dp->d_reclen; |
297 | if (dp->d_ino == 0) | |
298 | continue; | |
299 | return (dp); | |
d9c5783d KM |
300 | } |
301 | } | |
302 | ||
303 | dotname(dp) | |
20380c05 | 304 | register struct direct *dp; |
d9c5783d KM |
305 | { |
306 | ||
307 | if (dp->d_name[0]=='.') | |
5086d197 KM |
308 | if (dp->d_name[1]==0 || |
309 | (dp->d_name[1]=='.' && dp->d_name[2]==0)) | |
d9c5783d KM |
310 | return(1); |
311 | return(0); | |
312 | } | |
313 | ||
314 | pname(i, lev) | |
20380c05 KM |
315 | ino_t i; |
316 | int lev; | |
d9c5783d KM |
317 | { |
318 | register struct htab *hp; | |
319 | ||
320 | if (i==ROOTINO) | |
321 | return; | |
322 | if ((hp = lookup(i, 0)) == 0) { | |
323 | printf("???"); | |
324 | return; | |
325 | } | |
326 | if (lev > 10) { | |
327 | printf("..."); | |
328 | return; | |
329 | } | |
330 | pname(hp->h_pino, ++lev); | |
5086d197 | 331 | printf("/%s", hp->h_name); |
d9c5783d KM |
332 | } |
333 | ||
334 | struct htab * | |
335 | lookup(i, ef) | |
20380c05 KM |
336 | ino_t i; |
337 | int ef; | |
d9c5783d KM |
338 | { |
339 | register struct htab *hp; | |
340 | ||
9570c66d | 341 | for (hp = &htab[i%hsize]; hp->h_ino;) { |
d9c5783d KM |
342 | if (hp->h_ino==i) |
343 | return(hp); | |
9570c66d | 344 | if (++hp >= &htab[hsize]) |
d9c5783d KM |
345 | hp = htab; |
346 | } | |
347 | if (ef==0) | |
348 | return(0); | |
9570c66d KM |
349 | if (++nhent >= hsize) { |
350 | fprintf(stderr, "ncheck: hsize of %d is too small\n", hsize); | |
d9c5783d KM |
351 | exit(1); |
352 | } | |
353 | hp->h_ino = i; | |
354 | return(hp); | |
355 | } | |
356 | ||
357 | bread(bno, buf, cnt) | |
20380c05 KM |
358 | daddr_t bno; |
359 | char *buf; | |
360 | int cnt; | |
d9c5783d KM |
361 | { |
362 | register i; | |
363 | ||
a66ab591 | 364 | lseek(fi, bno * dev_bsize, 0); |
d9c5783d KM |
365 | if (read(fi, buf, cnt) != cnt) { |
366 | fprintf(stderr, "ncheck: read error %d\n", bno); | |
b6407c9d | 367 | for(i=0; i < cnt; i++) |
d9c5783d KM |
368 | buf[i] = 0; |
369 | } | |
370 | } | |
371 | ||
6a5c181e KB |
372 | /* |
373 | * Swiped from standalone sys.c. | |
374 | */ | |
375 | #define NBUFS 4 | |
376 | char b[NBUFS][MAXBSIZE]; | |
377 | daddr_t blknos[NBUFS]; | |
378 | ||
d9c5783d | 379 | daddr_t |
6a5c181e KB |
380 | bmap(bn) |
381 | register daddr_t bn; | |
d9c5783d | 382 | { |
6a5c181e KB |
383 | register int j; |
384 | int i, sh; | |
385 | daddr_t nb, *bap; | |
386 | ||
387 | if (bn < 0) { | |
388 | fprintf(stderr, "ncheck: bn %d negative\n", bn); | |
389 | return ((daddr_t)0); | |
390 | } | |
391 | ||
392 | /* | |
393 | * blocks 0..NDADDR are direct blocks | |
394 | */ | |
395 | if(bn < NDADDR) | |
396 | return(gip->di_db[bn]); | |
397 | ||
398 | /* | |
399 | * addresses NIADDR have single and double indirect blocks. | |
400 | * the first step is to determine how many levels of indirection. | |
401 | */ | |
402 | sh = 1; | |
403 | bn -= NDADDR; | |
404 | for (j = NIADDR; j > 0; j--) { | |
405 | sh *= NINDIR(&sblock); | |
406 | if (bn < sh) | |
407 | break; | |
408 | bn -= sh; | |
409 | } | |
410 | if (j == 0) { | |
411 | printf("ncheck: bn %ld ovf, ino %u\n", bn, ino); | |
412 | return ((daddr_t)0); | |
413 | } | |
414 | ||
415 | /* | |
416 | * fetch the first indirect block address from the inode | |
417 | */ | |
418 | nb = gip->di_ib[NIADDR - j]; | |
419 | if (nb == 0) { | |
420 | printf("ncheck: bn %ld void1, ino %u\n", bn, ino); | |
421 | return ((daddr_t)0); | |
422 | } | |
423 | ||
424 | /* | |
425 | * fetch through the indirect blocks | |
426 | */ | |
427 | for (; j <= NIADDR; j++) { | |
428 | if (blknos[j] != nb) { | |
429 | bread(fsbtodb(&sblock, nb), b[j], sblock.fs_bsize); | |
430 | blknos[j] = nb; | |
431 | } | |
432 | bap = (daddr_t *)b[j]; | |
433 | sh /= NINDIR(&sblock); | |
434 | i = (bn / sh) % NINDIR(&sblock); | |
435 | nb = bap[i]; | |
436 | if(nb == 0) { | |
437 | printf("ncheck: bn %ld void2, ino %u\n", bn, ino); | |
438 | return ((daddr_t)0); | |
439 | } | |
d9c5783d | 440 | } |
6a5c181e | 441 | return (nb); |
d9c5783d | 442 | } |