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