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