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