|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)quot.c 4.14 (Berkeley) 88/04/18";
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: extern char *optarg;
60: extern int optind;
61: int ch;
62: time_t time();
63:
64: while ((ch = getopt(argc, argv, "cfhnv")) != EOF)
65: switch((char)ch) {
66: case 'c':
67: cflg++; break;
68: case 'f':
69: fflg++; break;
70: case 'h': /* undocumented */
71: hflg++; break;
72: case 'n':
73: nflg++; break;
74: case 'v': /* undocumented */
75: vflg++; break;
76: case '?':
77: default:
78: fputs("usage: quot [-cfn] [filesystem ...]\n", stderr);
79: exit(1);
80: }
81: argc -= optind;
82: argv += optind;
83:
84: (void)time(&now);
85: if (argc)
86: for (; *argv; ++argv) {
87: if (check(*argv, (char *)NULL) == 0)
88: report();
89: }
90: else
91: quotall();
92: exit(0);
93: }
94:
95: #include <sys/dir.h>
96: #include <fstab.h>
97:
98: quotall()
99: {
100: register struct fstab *fs;
101: register char *cp;
102: char dev[MAXNAMLEN + 10], *rindex();
103:
104: while (fs = getfsent()) {
105: if (strcmp(fs->fs_type, FSTAB_RO) &&
106: strcmp(fs->fs_type, FSTAB_RW) &&
107: strcmp(fs->fs_type, FSTAB_RQ))
108: continue;
109: cp = rindex(fs->fs_spec, '/');
110: if (cp == 0)
111: continue;
112: (void)sprintf(dev, "/dev/r%s", cp + 1);
113: if (check(dev, fs->fs_file) == 0)
114: report();
115: }
116: }
117:
118: check(file, fsdir)
119: char *file;
120: char *fsdir;
121: {
122: register int i, j, nfiles;
123: register struct du **dp;
124: daddr_t iblk;
125: long dev_bsize;
126: int c, fd;
127:
128: /*
129: * Initialize tables between checks;
130: * because of the qsort done in report()
131: * the hash tables must be rebuilt each time.
132: */
133: for (i = 0; i < TSIZE; i++)
134: sizes[i] = 0;
135: overflow = 0;
136: for (dp = duhash; dp < &duhash[DUHASH]; dp++)
137: *dp = 0;
138: ndu = 0;
139: fd = open(file, O_RDONLY);
140: if (fd < 0) {
141: fprintf(stderr, "quot: ");
142: perror(file);
143: return (-1);
144: }
145: printf("%s", file);
146: if (fsdir == NULL) {
147: register struct fstab *fs = getfsspec(file);
148: if (fs != NULL)
149: fsdir = fs->fs_file;
150: }
151: if (fsdir != NULL && *fsdir != '\0')
152: printf(" (%s)", fsdir);
153: printf(":\n");
154: sync();
155: bread(fd, (long)SBOFF, (char *)&sblock, SBSIZE);
156: dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
157: if (nflg) {
158: if (isdigit(c = getchar()))
159: (void)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 * dev_bsize, (char *)itab, (int)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\t", np);
253: else
254: printf("%u\t", 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: long bno;
269: char *buf;
270: {
271: off_t lseek();
272:
273: (void)lseek(fd, bno, L_SET);
274: if (read(fd, buf, cnt) != cnt) {
275: fprintf(stderr, "quot: read error at block %ld\n", bno);
276: exit(1);
277: }
278: }
279:
280: qcmp(p1, p2)
281: register struct du *p1, *p2;
282: {
283: char *s1, *s2;
284:
285: if (p1->blocks > p2->blocks)
286: return (-1);
287: if (p1->blocks < p2->blocks)
288: return (1);
289: s1 = getname(p1->uid);
290: if (s1 == 0)
291: return (0);
292: s2 = getname(p2->uid);
293: if (s2 == 0)
294: return (0);
295: return (strcmp(s1, s2));
296: }
297:
298: report()
299: {
300: register i;
301: register struct du *dp;
302:
303: if (nflg)
304: return;
305: if (cflg) {
306: register long t = 0;
307:
308: for (i = 0; i < TSIZE - 1; i++)
309: if (sizes[i]) {
310: t += i*sizes[i];
311: printf("%d\t%d\t%ld\n", i, sizes[i], t);
312: }
313: printf("%d\t%d\t%ld\n",
314: TSIZE - 1, sizes[TSIZE - 1], overflow + t);
315: return;
316: }
317: qsort(du, ndu, sizeof (du[0]), qcmp);
318: for (dp = du; dp < &du[ndu]; dp++) {
319: register char *cp;
320:
321: if (dp->blocks == 0)
322: return;
323: printf("%5D\t", dp->blocks);
324: if (fflg)
325: printf("%5D\t", dp->nfiles);
326: if (cp = getname(dp->uid))
327: printf("%-8.8s", cp);
328: else
329: printf("#%-8d", dp->uid);
330: if (vflg)
331: printf("\t%5D\t%5D\t%5D",
332: dp->blocks30, dp->blocks60, dp->blocks90);
333: printf("\n");
334: }
335: }
336:
337: /* rest should be done with nameserver or database */
338:
339: #include <pwd.h>
340: #include <grp.h>
341: #include <utmp.h>
342:
343: struct utmp utmp;
344: #define NMAX (sizeof (utmp.ut_name))
345: #define SCPYN(a, b) strncpy(a, b, NMAX)
346:
347: #define NUID 64 /* power of 2 */
348: #define UIDMASK 0x3f
349:
350: struct ncache {
351: int uid;
352: char name[NMAX+1];
353: } nc[NUID];
354:
355: char *
356: getname(uid)
357: {
358: register struct passwd *pw;
359: struct passwd *getpwent();
360: extern int _pw_stayopen;
361: register int cp;
362:
363: _pw_stayopen = 1;
364: cp = uid & UIDMASK;
365: if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
366: return (nc[cp].name);
367: pw = getpwuid(uid);
368: if (!pw)
369: return (0);
370: nc[cp].uid = uid;
371: SCPYN(nc[cp].name, pw->pw_name);
372: return (nc[cp].name);
373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.