1: #ifndef lint 2: static char *sccsid = "@(#)quot.c 4.11 (Berkeley) 85/09/09"; 3: #endif 4: 5: /* 6: * quot 7: */ 8: 9: #include <stdio.h> 10: #include <ctype.h> 11: #include <sys/param.h> 12: #include <sys/inode.h> 13: #include <sys/fs.h> 14: #include <sys/file.h> 15: 16: #define ISIZ (MAXBSIZE/sizeof(struct dinode)) 17: union { 18: struct fs u_sblock; 19: char dummy[SBSIZE]; 20: } sb_un; 21: #define sblock sb_un.u_sblock 22: struct dinode itab[MAXBSIZE/sizeof(struct dinode)]; 23: 24: struct du { 25: struct du *next; 26: long blocks; 27: long blocks30; 28: long blocks60; 29: long blocks90; 30: long nfiles; 31: int uid; 32: #define NDU 2048 33: } du[NDU]; 34: int ndu; 35: #define DUHASH 8209 /* smallest prime >= 4 * NDU */ 36: #define HASH(u) ((u) % DUHASH) 37: struct du *duhash[DUHASH]; 38: 39: #define TSIZE 500 40: int sizes[TSIZE]; 41: long overflow; 42: 43: int nflg; 44: int fflg; 45: int cflg; 46: int vflg; 47: int hflg; 48: long now; 49: 50: unsigned ino; 51: 52: char *malloc(); 53: char *getname(); 54: 55: main(argc, argv) 56: int argc; 57: char *argv[]; 58: { 59: register int n; 60: 61: now = time(0); 62: argc--, argv++; 63: while (argc > 0 && argv[0][0] == '-') { 64: register char *cp; 65: 66: for (cp = &argv[0][1]; *cp; cp++) 67: switch (*cp) { 68: case 'n': 69: nflg++; break; 70: case 'f': 71: fflg++; break; 72: case 'c': 73: cflg++; break; 74: case 'v': 75: vflg++; break; 76: case 'h': 77: hflg++; break; 78: default: 79: fprintf(stderr, 80: "usage: quot [ -nfcvh ] [ device ... ]\n"); 81: exit(1); 82: } 83: argc--, argv++; 84: } 85: if (argc == 0) 86: quotall(); 87: while (argc-- > 0) 88: if (check(*argv++, (char *)NULL) == 0) 89: report(); 90: exit (0); 91: } 92: 93: #include <fstab.h> 94: 95: quotall() 96: { 97: register struct fstab *fs; 98: register char *cp; 99: char dev[80], *rindex(); 100: 101: if (setfsent() == 0) { 102: fprintf(stderr, "quot: no %s file\n", FSTAB); 103: exit(1); 104: } 105: while (fs = getfsent()) { 106: if (strcmp(fs->fs_type, FSTAB_RO) && 107: strcmp(fs->fs_type, FSTAB_RW) && 108: strcmp(fs->fs_type, FSTAB_RQ)) 109: continue; 110: cp = rindex(fs->fs_spec, '/'); 111: if (cp == 0) 112: continue; 113: sprintf(dev, "/dev/r%s", cp + 1); 114: if (check(dev, fs->fs_file) == 0) 115: report(); 116: } 117: endfsent(); 118: } 119: 120: check(file, fsdir) 121: char *file; 122: char *fsdir; 123: { 124: register int i, j, nfiles; 125: register struct du **dp; 126: daddr_t iblk; 127: int c, fd; 128: 129: /* 130: * Initialize tables between checks; 131: * because of the qsort done in report() 132: * the hash tables must be rebuilt each time. 133: */ 134: for (i = 0; i < TSIZE; i++) 135: sizes[i] = 0; 136: overflow = 0; 137: for (dp = duhash; dp < &duhash[DUHASH]; dp++) 138: *dp = 0; 139: ndu = 0; 140: fd = open(file, O_RDONLY); 141: if (fd < 0) { 142: fprintf(stderr, "quot: "); 143: perror(file); 144: return (-1); 145: } 146: printf("%s", file); 147: if (fsdir == NULL) { 148: register struct fstab *fs = getfsspec(file); 149: if (fs != NULL) 150: fsdir = fs->fs_file; 151: } 152: if (fsdir != NULL && *fsdir != '\0') 153: printf(" (%s)", fsdir); 154: printf(":\n"); 155: sync(); 156: bread(fd, SBLOCK, (char *)&sblock, SBSIZE); 157: if (nflg) { 158: if (isdigit(c = getchar())) 159: ungetc(c, stdin); 160: else while (c != '\n' && c != EOF) 161: c = getchar(); 162: } 163: nfiles = sblock.fs_ipg * sblock.fs_ncg; 164: for (ino = 0; ino < nfiles; ) { 165: iblk = fsbtodb(&sblock, itod(&sblock, ino)); 166: bread(fd, iblk, (char *)itab, sblock.fs_bsize); 167: for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) { 168: if (ino < ROOTINO) 169: continue; 170: acct(&itab[j]); 171: } 172: } 173: close(fd); 174: return (0); 175: } 176: 177: acct(ip) 178: register struct dinode *ip; 179: { 180: register struct du *dp; 181: struct du **hp; 182: long blks, frags, size; 183: int n; 184: static fino; 185: 186: if ((ip->di_mode & IFMT) == 0) 187: return; 188: /* 189: * By default, take block count in inode. Otherwise (-h), 190: * take the size field and estimate the blocks allocated. 191: * The latter does not account for holes in files. 192: */ 193: if (!hflg) 194: size = ip->di_blocks / 2; 195: else { 196: blks = lblkno(&sblock, ip->di_size); 197: frags = blks * sblock.fs_frag + 198: numfrags(&sblock, dblksize(&sblock, ip, blks)); 199: size = frags * sblock.fs_fsize / 1024; 200: } 201: if (cflg) { 202: if ((ip->di_mode&IFMT) != IFDIR && (ip->di_mode&IFMT) != IFREG) 203: return; 204: if (size >= TSIZE) { 205: overflow += size; 206: size = TSIZE-1; 207: } 208: sizes[size]++; 209: return; 210: } 211: hp = &duhash[HASH(ip->di_uid)]; 212: for (dp = *hp; dp; dp = dp->next) 213: if (dp->uid == ip->di_uid) 214: break; 215: if (dp == 0) { 216: if (ndu >= NDU) 217: return; 218: dp = &du[ndu++]; 219: dp->next = *hp; 220: *hp = dp; 221: dp->uid = ip->di_uid; 222: dp->nfiles = 0; 223: dp->blocks = 0; 224: dp->blocks30 = 0; 225: dp->blocks60 = 0; 226: dp->blocks90 = 0; 227: } 228: dp->blocks += size; 229: #define DAY (60 * 60 * 24) /* seconds per day */ 230: if (now - ip->di_atime > 30 * DAY) 231: dp->blocks30 += size; 232: if (now - ip->di_atime > 60 * DAY) 233: dp->blocks60 += size; 234: if (now - ip->di_atime > 90 * DAY) 235: dp->blocks90 += size; 236: dp->nfiles++; 237: while (nflg) { 238: register char *np; 239: 240: if (fino == 0) 241: if (scanf("%d", &fino) <= 0) 242: return; 243: if (fino > ino) 244: return; 245: if (fino < ino) { 246: while ((n = getchar()) != '\n' && n != EOF) 247: ; 248: fino = 0; 249: continue; 250: } 251: if (np = getname(dp->uid)) 252: printf("%.7s ", np); 253: else 254: printf("%d ", ip->di_uid); 255: while ((n = getchar()) == ' ' || n == '\t') 256: ; 257: putchar(n); 258: while (n != EOF && n != '\n') { 259: n = getchar(); 260: putchar(n); 261: } 262: fino = 0; 263: break; 264: } 265: } 266: 267: bread(fd, bno, buf, cnt) 268: unsigned bno; 269: char *buf; 270: { 271: 272: lseek(fd, (long)bno * DEV_BSIZE, L_SET); 273: if (read(fd, buf, cnt) != cnt) { 274: fprintf(stderr, "quot: read error at block %u\n", bno); 275: exit(1); 276: } 277: } 278: 279: qcmp(p1, p2) 280: register struct du *p1, *p2; 281: { 282: char *s1, *s2; 283: 284: if (p1->blocks > p2->blocks) 285: return (-1); 286: if (p1->blocks < p2->blocks) 287: return (1); 288: s1 = getname(p1->uid); 289: if (s1 == 0) 290: return (0); 291: s2 = getname(p2->uid); 292: if (s2 == 0) 293: return (0); 294: return (strcmp(s1, s2)); 295: } 296: 297: report() 298: { 299: register i; 300: register struct du *dp; 301: 302: if (nflg) 303: return; 304: if (cflg) { 305: register long t = 0; 306: 307: for (i = 0; i < TSIZE - 1; i++) 308: if (sizes[i]) { 309: t += i*sizes[i]; 310: printf("%d %d %D\n", i, sizes[i], t); 311: } 312: printf("%d %d %D\n", 313: TSIZE - 1, sizes[TSIZE - 1], overflow + t); 314: return; 315: } 316: qsort(du, ndu, sizeof (du[0]), qcmp); 317: for (dp = du; dp < &du[ndu]; dp++) { 318: register char *cp; 319: 320: if (dp->blocks == 0) 321: return; 322: printf("%5D\t", dp->blocks); 323: if (fflg) 324: printf("%5D\t", dp->nfiles); 325: if (cp = getname(dp->uid)) 326: printf("%-8.8s", cp); 327: else 328: printf("#%-8d", dp->uid); 329: if (vflg) 330: printf("\t%5D\t%5D\t%5D", 331: dp->blocks30, dp->blocks60, dp->blocks90); 332: printf("\n"); 333: } 334: } 335: 336: /* rest should be done with nameserver or database */ 337: 338: #include <pwd.h> 339: #include <grp.h> 340: #include <utmp.h> 341: 342: struct utmp utmp; 343: #define NMAX (sizeof (utmp.ut_name)) 344: #define SCPYN(a, b) strncpy(a, b, NMAX) 345: 346: #define NUID 64 /* power of 2 */ 347: #define UIDMASK 0x3f 348: 349: struct ncache { 350: int uid; 351: char name[NMAX+1]; 352: } nc[NUID]; 353: char outrangename[NMAX+1]; 354: int outrangeuid = -1; 355: 356: char * 357: getname(uid) 358: { 359: register struct passwd *pw; 360: struct passwd *getpwent(); 361: extern int _pw_stayopen; 362: register int cp; 363: 364: _pw_stayopen = 1; 365: cp = uid & UIDMASK; 366: if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0]) 367: return (nc[cp].name); 368: pw = getpwuid(uid); 369: if (!pw) 370: return (0); 371: nc[cp].uid = uid; 372: SCPYN(nc[cp].name, pw->pw_name); 373: return (nc[cp].name); 374: }