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