convert SBLOCK to SBOFF; generalize use of dev_bsize
[unix-history] / usr / src / sbin / ncheck / ncheck.c
CommitLineData
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
8char 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 14static 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
30struct fs sblock;
31struct dinode itab[MAXIPG];
56d45dcd 32struct dinode *gip;
61b11ef4
KM
33struct ilist {
34 ino_t ino;
35 u_short mode;
36 short uid;
37 short gid;
38} ilist[NB];
d9c5783d
KM
39struct htab
40{
41 ino_t h_ino;
42 ino_t h_pino;
5086d197 43 char *h_name;
9570c66d
KM
44} *htab;
45char *strngtab;
46long hsize;
5086d197
KM
47int strngloc;
48
49struct dirstuff {
50 int loc;
51 struct dinode *ip;
52 char dbuf[MAXBSIZE];
53};
d9c5783d
KM
54
55int aflg;
56int sflg;
61b11ef4
KM
57int iflg; /* number of inodes being searched for */
58int mflg;
d9c5783d
KM
59int fi;
60ino_t ino;
61int nhent;
62int nxfile;
a66ab591 63long dev_bsize = 1;
d9c5783d
KM
64
65int nerror;
66daddr_t bmap();
67long atol();
68struct htab *lookup();
69
70main(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
115check(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
184pass1(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
211pass2(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
238pass3(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 */
276struct direct *
277readdir(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
303dotname(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
314pname(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
334struct htab *
335lookup(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
357bread(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
376char b[NBUFS][MAXBSIZE];
377daddr_t blknos[NBUFS];
378
d9c5783d 379daddr_t
6a5c181e
KB
380bmap(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}