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.4 (Berkeley) 1/9/86"; 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[MAXIPG]; 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: 64: int nerror; 65: daddr_t bmap(); 66: long atol(); 67: struct htab *lookup(); 68: 69: main(argc, argv) 70: int argc; 71: char *argv[]; 72: { 73: register i; 74: long n; 75: 76: while (--argc) { 77: argv++; 78: if (**argv=='-') 79: switch ((*argv)[1]) { 80: 81: case 'a': 82: aflg++; 83: continue; 84: 85: case 'i': 86: for(iflg=0; iflg<NB; iflg++) { 87: n = atol(argv[1]); 88: if(n == 0) 89: break; 90: ilist[iflg].ino = n; 91: nxfile = iflg; 92: argv++; 93: argc--; 94: } 95: continue; 96: 97: case 'm': 98: mflg++; 99: continue; 100: 101: case 's': 102: sflg++; 103: continue; 104: 105: default: 106: fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]); 107: nerror++; 108: } 109: check(*argv); 110: } 111: return(nerror); 112: } 113: 114: check(file) 115: char *file; 116: { 117: register int i, j, c; 118: int nfiles; 119: 120: fi = open(file, 0); 121: if(fi < 0) { 122: fprintf(stderr, "ncheck: cannot open %s\n", file); 123: nerror++; 124: return; 125: } 126: nhent = 0; 127: printf("%s:\n", file); 128: sync(); 129: bread(SBLOCK, (char *)&sblock, SBSIZE); 130: if (sblock.fs_magic != FS_MAGIC) { 131: printf("%s: not a file system\n", file); 132: nerror++; 133: return; 134: } 135: hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1; 136: htab = (struct htab *)malloc(hsize * sizeof(struct htab)); 137: strngtab = (char *)malloc(30 * hsize); 138: if (htab == 0 || strngtab == 0) { 139: printf("not enough memory to allocate tables\n"); 140: nerror++; 141: return; 142: } 143: ino = 0; 144: for (c = 0; c < sblock.fs_ncg; c++) { 145: bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 146: sblock.fs_ipg * sizeof (struct dinode)); 147: for(j = 0; j < sblock.fs_ipg; j++) { 148: if (itab[j].di_mode != 0) 149: pass1(&itab[j]); 150: ino++; 151: } 152: } 153: ilist[nxfile+1].ino = 0; 154: ino = 0; 155: for (c = 0; c < sblock.fs_ncg; c++) { 156: bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 157: sblock.fs_ipg * sizeof (struct dinode)); 158: for(j = 0; j < sblock.fs_ipg; j++) { 159: if (itab[j].di_mode != 0) 160: pass2(&itab[j]); 161: ino++; 162: } 163: } 164: ino = 0; 165: for (c = 0; c < sblock.fs_ncg; c++) { 166: bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 167: sblock.fs_ipg * sizeof (struct dinode)); 168: for(j = 0; j < sblock.fs_ipg; j++) { 169: if (itab[j].di_mode != 0) 170: pass3(&itab[j]); 171: ino++; 172: } 173: } 174: close(fi); 175: for (i = 0; i < hsize; i++) 176: htab[i].h_ino = 0; 177: for (i = iflg; i < NB; i++) 178: ilist[i].ino = 0; 179: nxfile = iflg; 180: } 181: 182: pass1(ip) 183: register struct dinode *ip; 184: { 185: int i; 186: 187: if (mflg) 188: for (i = 0; i < iflg; i++) 189: if (ino == ilist[i].ino) { 190: ilist[i].mode = ip->di_mode; 191: ilist[i].uid = ip->di_uid; 192: ilist[i].gid = ip->di_gid; 193: } 194: if ((ip->di_mode & IFMT) != IFDIR) { 195: if (sflg==0 || nxfile>=NB) 196: return; 197: if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR 198: || ip->di_mode&(ISUID|ISGID)) { 199: ilist[nxfile].ino = ino; 200: ilist[nxfile].mode = ip->di_mode; 201: ilist[nxfile].uid = ip->di_uid; 202: ilist[nxfile++].gid = ip->di_gid; 203: return; 204: } 205: } 206: lookup(ino, 1); 207: } 208: 209: pass2(ip) 210: register struct dinode *ip; 211: { 212: register struct direct *dp; 213: struct dirstuff dirp; 214: struct htab *hp; 215: 216: if((ip->di_mode&IFMT) != IFDIR) 217: return; 218: dirp.loc = 0; 219: dirp.ip = ip; 220: gip = ip; 221: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 222: if(dp->d_ino == 0) 223: continue; 224: hp = lookup(dp->d_ino, 0); 225: if(hp == 0) 226: continue; 227: if(dotname(dp)) 228: continue; 229: hp->h_pino = ino; 230: hp->h_name = &strngtab[strngloc]; 231: strngloc += strlen(dp->d_name) + 1; 232: strcpy(hp->h_name, dp->d_name); 233: } 234: } 235: 236: pass3(ip) 237: register struct dinode *ip; 238: { 239: register struct direct *dp; 240: struct dirstuff dirp; 241: int k; 242: 243: if((ip->di_mode&IFMT) != IFDIR) 244: return; 245: dirp.loc = 0; 246: dirp.ip = ip; 247: gip = ip; 248: for(dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 249: if(aflg==0 && dotname(dp)) 250: continue; 251: if(sflg == 0 && iflg == 0) 252: goto pr; 253: for(k = 0; ilist[k].ino != 0; k++) 254: if(ilist[k].ino == dp->d_ino) 255: break; 256: if (ilist[k].ino == 0) 257: continue; 258: if (mflg) 259: printf("mode %-6o uid %-5d gid %-5d ino ", 260: ilist[k].mode, ilist[k].uid, ilist[k].gid); 261: pr: 262: printf("%-5u\t", dp->d_ino); 263: pname(ino, 0); 264: printf("/%s", dp->d_name); 265: if (lookup(dp->d_ino, 0)) 266: printf("/."); 267: printf("\n"); 268: } 269: } 270: 271: /* 272: * get next entry in a directory. 273: */ 274: struct direct * 275: readdir(dirp) 276: register struct dirstuff *dirp; 277: { 278: register struct direct *dp; 279: daddr_t lbn, d; 280: 281: for(;;) { 282: if (dirp->loc >= dirp->ip->di_size) 283: return NULL; 284: if (blkoff(&sblock, dirp->loc) == 0) { 285: lbn = lblkno(&sblock, dirp->loc); 286: d = bmap(lbn); 287: if(d == 0) 288: return NULL; 289: bread(fsbtodb(&sblock, d), dirp->dbuf, 290: dblksize(&sblock, dirp->ip, lbn)); 291: } 292: dp = (struct direct *) 293: (dirp->dbuf + blkoff(&sblock, dirp->loc)); 294: dirp->loc += dp->d_reclen; 295: if (dp->d_ino == 0) 296: continue; 297: return (dp); 298: } 299: } 300: 301: dotname(dp) 302: register struct direct *dp; 303: { 304: 305: if (dp->d_name[0]=='.') 306: if (dp->d_name[1]==0 || 307: (dp->d_name[1]=='.' && dp->d_name[2]==0)) 308: return(1); 309: return(0); 310: } 311: 312: pname(i, lev) 313: ino_t i; 314: int lev; 315: { 316: register struct htab *hp; 317: 318: if (i==ROOTINO) 319: return; 320: if ((hp = lookup(i, 0)) == 0) { 321: printf("???"); 322: return; 323: } 324: if (lev > 10) { 325: printf("..."); 326: return; 327: } 328: pname(hp->h_pino, ++lev); 329: printf("/%s", hp->h_name); 330: } 331: 332: struct htab * 333: lookup(i, ef) 334: ino_t i; 335: int ef; 336: { 337: register struct htab *hp; 338: 339: for (hp = &htab[i%hsize]; hp->h_ino;) { 340: if (hp->h_ino==i) 341: return(hp); 342: if (++hp >= &htab[hsize]) 343: hp = htab; 344: } 345: if (ef==0) 346: return(0); 347: if (++nhent >= hsize) { 348: fprintf(stderr, "ncheck: hsize of %d is too small\n", hsize); 349: exit(1); 350: } 351: hp->h_ino = i; 352: return(hp); 353: } 354: 355: bread(bno, buf, cnt) 356: daddr_t bno; 357: char *buf; 358: int cnt; 359: { 360: register i; 361: 362: lseek(fi, bno * DEV_BSIZE, 0); 363: if (read(fi, buf, cnt) != cnt) { 364: fprintf(stderr, "ncheck: read error %d\n", bno); 365: for(i=0; i < cnt; i++) 366: buf[i] = 0; 367: } 368: } 369: 370: daddr_t 371: bmap(i) 372: int i; 373: { 374: daddr_t ibuf[MAXNINDIR]; 375: 376: if(i < NDADDR) 377: return(gip->di_db[i]); 378: i -= NDADDR; 379: if(i > NINDIR(&sblock)) { 380: fprintf(stderr, "ncheck: %u - huge directory\n", ino); 381: return((daddr_t)0); 382: } 383: bread(fsbtodb(&sblock, gip->di_ib[i]), (char *)ibuf, sizeof(ibuf)); 384: return(ibuf[i]); 385: }