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