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.10 (Berkeley) 02/20/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 <sys/time.h> 26 #include <sys/vnode.h> 27 #include <ufs/inode.h> 28 #include <ufs/fs.h> 29 #include <sys/dir.h> 30 #include <stdio.h> 31 32 struct fs sblock; 33 struct dinode itab[MAXBSIZE/sizeof(struct dinode)]; 34 struct dinode *gip; 35 struct ilist { 36 ino_t ino; 37 u_short mode; 38 short uid; 39 short gid; 40 } ilist[NB]; 41 struct htab 42 { 43 ino_t h_ino; 44 ino_t h_pino; 45 char *h_name; 46 } *htab; 47 char *strngtab; 48 long hsize; 49 int strngloc; 50 51 struct dirstuff { 52 int loc; 53 struct dinode *ip; 54 char dbuf[MAXBSIZE]; 55 }; 56 57 int aflg; 58 int sflg; 59 int iflg; /* number of inodes being searched for */ 60 int mflg; 61 int fi; 62 ino_t ino; 63 int nhent; 64 int nxfile; 65 int dev_bsize = 1; 66 67 int nerror; 68 daddr_t bmap(); 69 long atol(); 70 off_t lseek(); 71 char *malloc(), *strcpy(); 72 struct htab *lookup(); 73 struct direct *nreaddir(); 74 75 main(argc, argv) 76 int argc; 77 char *argv[]; 78 { 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': 91 for(iflg=0; iflg<NB; iflg++) { 92 n = atol(argv[1]); 93 if(n == 0) 94 break; 95 ilist[iflg].ino = n; 96 nxfile = iflg; 97 argv++; 98 argc--; 99 } 100 continue; 101 102 case 'm': 103 mflg++; 104 continue; 105 106 case 's': 107 sflg++; 108 continue; 109 110 default: 111 (void) fprintf(stderr, "ncheck: bad flag %c\n", 112 (*argv)[1]); 113 nerror++; 114 } 115 check(*argv); 116 } 117 return(nerror); 118 } 119 120 check(file) 121 char *file; 122 { 123 register int i, j, c; 124 125 fi = open(file, 0); 126 if(fi < 0) { 127 (void) fprintf(stderr, "ncheck: cannot open %s\n", file); 128 nerror++; 129 return; 130 } 131 nhent = 0; 132 (void) printf("%s:\n", file); 133 sync(); 134 bread(SBOFF, (char *)&sblock, (long)SBSIZE); 135 if (sblock.fs_magic != FS_MAGIC) { 136 (void) printf("%s: not a file system\n", file); 137 nerror++; 138 return; 139 } 140 dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 141 hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1; 142 htab = (struct htab *)malloc((unsigned)hsize * sizeof(struct htab)); 143 strngtab = malloc((unsigned)(30 * hsize)); 144 if (htab == 0 || strngtab == 0) { 145 (void) printf("not enough memory to allocate tables\n"); 146 nerror++; 147 return; 148 } 149 ino = 0; 150 for (c = 0; c < sblock.fs_ncg; c++) { 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 } 161 } 162 } 163 ilist[nxfile+1].ino = 0; 164 ino = 0; 165 for (c = 0; c < sblock.fs_ncg; c++) { 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 } 176 } 177 } 178 ino = 0; 179 for (c = 0; c < sblock.fs_ncg; c++) { 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 } 190 } 191 } 192 (void) close(fi); 193 for (i = 0; i < hsize; i++) 194 htab[i].h_ino = 0; 195 for (i = iflg; i < NB; i++) 196 ilist[i].ino = 0; 197 nxfile = iflg; 198 } 199 200 pass1(ip) 201 register struct dinode *ip; 202 { 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) { 213 if (sflg==0 || nxfile>=NB) 214 return; 215 if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR 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; 221 return; 222 } 223 } 224 (void) lookup(ino, 1); 225 } 226 227 pass2(ip) 228 register struct dinode *ip; 229 { 230 register struct direct *dp; 231 struct dirstuff dirp; 232 struct htab *hp; 233 234 if((ip->di_mode&IFMT) != IFDIR) 235 return; 236 dirp.loc = 0; 237 dirp.ip = ip; 238 gip = ip; 239 for (dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) { 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; 250 (void) strcpy(hp->h_name, dp->d_name); 251 } 252 } 253 254 pass3(ip) 255 register struct dinode *ip; 256 { 257 register struct direct *dp; 258 struct dirstuff dirp; 259 int k; 260 261 if((ip->di_mode&IFMT) != IFDIR) 262 return; 263 dirp.loc = 0; 264 dirp.ip = ip; 265 gip = ip; 266 for(dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) { 267 if(aflg==0 && dotname(dp)) 268 continue; 269 if(sflg == 0 && iflg == 0) 270 goto pr; 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) 277 (void) printf("mode %-6o uid %-5d gid %-5d ino ", 278 ilist[k].mode, ilist[k].uid, ilist[k].gid); 279 pr: 280 (void) printf("%-5lu\t", dp->d_ino); 281 pname(ino, 0); 282 (void) printf("/%s", dp->d_name); 283 if (lookup(dp->d_ino, 0)) 284 (void) printf("/."); 285 (void) printf("\n"); 286 } 287 } 288 289 /* 290 * get next entry in a directory. 291 */ 292 struct direct * 293 nreaddir(dirp) 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; 302 if (blkoff(&sblock, dirp->loc) == 0) { 303 lbn = lblkno(&sblock, dirp->loc); 304 d = bmap(lbn); 305 if(d == 0) 306 return NULL; 307 bread(fsbtodb(&sblock, d), dirp->dbuf, 308 dblksize(&sblock, dirp->ip, lbn)); 309 } 310 dp = (struct direct *) 311 (dirp->dbuf + blkoff(&sblock, dirp->loc)); 312 dirp->loc += dp->d_reclen; 313 if (dp->d_ino == 0) 314 continue; 315 return (dp); 316 } 317 } 318 319 dotname(dp) 320 register struct direct *dp; 321 { 322 323 if (dp->d_name[0]=='.') 324 if (dp->d_name[1]==0 || 325 (dp->d_name[1]=='.' && dp->d_name[2]==0)) 326 return(1); 327 return(0); 328 } 329 330 pname(i, lev) 331 ino_t i; 332 int lev; 333 { 334 register struct htab *hp; 335 336 if (i==ROOTINO) 337 return; 338 if ((hp = lookup(i, 0)) == 0) { 339 (void) printf("???"); 340 return; 341 } 342 if (lev > 10) { 343 (void) printf("..."); 344 return; 345 } 346 pname(hp->h_pino, ++lev); 347 (void) printf("/%s", hp->h_name); 348 } 349 350 struct htab * 351 lookup(i, ef) 352 ino_t i; 353 int ef; 354 { 355 register struct htab *hp; 356 357 for (hp = &htab[i%hsize]; hp->h_ino;) { 358 if (hp->h_ino==i) 359 return(hp); 360 if (++hp >= &htab[hsize]) 361 hp = htab; 362 } 363 if (ef==0) 364 return(0); 365 if (++nhent >= hsize) { 366 (void) fprintf(stderr, "ncheck: hsize of %ld is too small\n", 367 hsize); 368 exit(1); 369 } 370 hp->h_ino = i; 371 return(hp); 372 } 373 374 bread(bno, buf, lcount) 375 daddr_t bno; 376 register char *buf; 377 long lcount; 378 { 379 register int i, cnt = lcount; 380 register off_t off = bno * dev_bsize; 381 382 (void) lseek(fi, off, 0); 383 if (read(fi, buf, cnt) != cnt) { 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 } 405 } 406 } 407 408 /* 409 * Swiped from standalone sys.c. 410 */ 411 #define NBUFS 4 412 char b[NBUFS][MAXBSIZE]; 413 daddr_t blknos[NBUFS]; 414 415 daddr_t 416 bmap(bn) 417 register daddr_t bn; 418 { 419 register int j; 420 int i, sh; 421 daddr_t nb, *bap; 422 423 if (bn < 0) { 424 (void) fprintf(stderr, "ncheck: bn %ld negative\n", bn); 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) { 447 (void) printf("ncheck: bn %ld ovf, ino %lu\n", bn, ino); 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) { 456 (void) printf("ncheck: bn %ld void1, ino %lu\n", bn, ino); 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) { 473 (void) printf("ncheck: bn %ld void2, ino %lu\n", bn, 474 ino); 475 return ((daddr_t)0); 476 } 477 } 478 return (nb); 479 } 480