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