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