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