|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)quot.c 4.9 (Berkeley) 83/09/22";
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++) == 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) == 0)
115: report();
116: }
117: endfsent();
118: }
119:
120: check(file)
121: char *file;
122: {
123: register int i, j, nfiles;
124: register struct du **dp;
125: daddr_t iblk;
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:\n", file);
146: sync();
147: bread(fd, SBLOCK, (char *)&sblock, SBSIZE);
148: if (nflg) {
149: if (isdigit(c = getchar()))
150: ungetc(c, stdin);
151: else while (c != '\n' && c != EOF)
152: c = getchar();
153: }
154: nfiles = sblock.fs_ipg * sblock.fs_ncg;
155: for (ino = 0; ino < nfiles; ) {
156: iblk = fsbtodb(&sblock, itod(&sblock, ino));
157: bread(fd, iblk, (char *)itab, sblock.fs_bsize);
158: for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) {
159: if (ino < ROOTINO)
160: continue;
161: acct(&itab[j]);
162: }
163: }
164: close(fd);
165: }
166:
167: acct(ip)
168: register struct dinode *ip;
169: {
170: register struct du *dp;
171: struct du **hp;
172: long blks, frags, size;
173: char n;
174: static fino;
175:
176: if ((ip->di_mode & IFMT) == 0)
177: return;
178: /*
179: * By default, take block count in inode. Otherwise (-h),
180: * take the size field and estimate the blocks allocated.
181: * The latter does not account for holes in files.
182: */
183: if (!hflg)
184: size = ip->di_blocks / 2;
185: else {
186: blks = lblkno(&sblock, ip->di_size);
187: frags = blks * sblock.fs_frag +
188: numfrags(&sblock, dblksize(&sblock, ip, blks));
189: size = frags * sblock.fs_fsize / 1024;
190: }
191: if (cflg) {
192: if ((ip->di_mode&IFMT) != IFDIR && (ip->di_mode&IFMT) != IFREG)
193: return;
194: if (size >= TSIZE) {
195: overflow += size;
196: size = TSIZE-1;
197: }
198: sizes[size]++;
199: return;
200: }
201: hp = &duhash[HASH(ip->di_uid)];
202: for (dp = *hp; dp; dp = dp->next)
203: if (dp->uid == ip->di_uid)
204: break;
205: if (dp == 0) {
206: if (ndu >= NDU)
207: return;
208: dp = &du[ndu++];
209: dp->next = *hp;
210: *hp = dp;
211: dp->uid = ip->di_uid;
212: dp->nfiles = 0;
213: dp->blocks = 0;
214: dp->blocks30 = 0;
215: dp->blocks60 = 0;
216: dp->blocks90 = 0;
217: }
218: dp->blocks += size;
219: #define DAY (60 * 60 * 24) /* seconds per day */
220: if (now - ip->di_atime > 30 * DAY)
221: dp->blocks30 += size;
222: if (now - ip->di_atime > 60 * DAY)
223: dp->blocks60 += size;
224: if (now - ip->di_atime > 90 * DAY)
225: dp->blocks90 += size;
226: dp->nfiles++;
227: while (nflg) {
228: register char *np;
229:
230: if (fino == 0)
231: if (scanf("%d", &fino) <= 0)
232: return;
233: if (fino > ino)
234: return;
235: if (fino < ino) {
236: while ((n = getchar()) != '\n' && n != EOF)
237: ;
238: fino = 0;
239: continue;
240: }
241: if (np = getname(dp->uid))
242: printf("%.7s ", np);
243: else
244: printf("%d ", ip->di_uid);
245: while ((n = getchar()) == ' ' || n == '\t')
246: ;
247: putchar(n);
248: while (n != EOF && n != '\n') {
249: n = getchar();
250: putchar(n);
251: }
252: fino = 0;
253: break;
254: }
255: }
256:
257: bread(fd, bno, buf, cnt)
258: unsigned bno;
259: char *buf;
260: {
261:
262: lseek(fd, (long)bno * DEV_BSIZE, L_SET);
263: if (read(fd, buf, cnt) != cnt) {
264: fprintf(stderr, "quot: read error at block %u\n", bno);
265: exit(1);
266: }
267: }
268:
269: qcmp(p1, p2)
270: register struct du *p1, *p2;
271: {
272: char *s1, *s2;
273:
274: if (p1->blocks > p2->blocks)
275: return (-1);
276: if (p1->blocks < p2->blocks)
277: return (1);
278: s1 = getname(p1->uid);
279: if (s1 == 0)
280: return (0);
281: s2 = getname(p2->uid);
282: if (s2 == 0)
283: return (0);
284: return (strcmp(s1, s2));
285: }
286:
287: report()
288: {
289: register i;
290: register struct du *dp;
291:
292: if (nflg)
293: return;
294: if (cflg) {
295: register long t = 0;
296:
297: for (i = 0; i < TSIZE - 1; i++)
298: if (sizes[i]) {
299: t += i*sizes[i];
300: printf("%d %d %D\n", i, sizes[i], t);
301: }
302: printf("%d %d %D\n",
303: TSIZE - 1, sizes[TSIZE - 1], overflow + t);
304: return;
305: }
306: qsort(du, ndu, sizeof (du[0]), qcmp);
307: for (dp = du; dp < &du[ndu]; dp++) {
308: register char *cp;
309:
310: if (dp->blocks == 0)
311: return;
312: printf("%5D\t", dp->blocks);
313: if (fflg)
314: printf("%5D\t", dp->nfiles);
315: if (cp = getname(dp->uid))
316: printf("%-8.8s", cp);
317: else
318: printf("#%-8d", dp->uid);
319: if (vflg)
320: printf("\t%5D\t%5D\t%5D",
321: dp->blocks30, dp->blocks60, dp->blocks90);
322: printf("\n");
323: }
324: }
325:
326: #include <pwd.h>
327: #include <utmp.h>
328:
329: struct utmp utmp;
330:
331: #define NUID 2048
332: #define NMAX (sizeof (utmp.ut_name))
333:
334: char names[NUID][NMAX+1];
335: char outrangename[NMAX+1];
336: int outrangeuid = -1;
337:
338: char *
339: getname(uid)
340: int uid;
341: {
342: register struct passwd *pw;
343: static init;
344: struct passwd *getpwent();
345:
346: if (uid >= 0 && uid < NUID && names[uid][0])
347: return (&names[uid][0]);
348: if (uid >= 0 && uid == outrangeuid)
349: return (outrangename);
350: rescan:
351: if (init == 2) {
352: if (uid < NUID)
353: return (0);
354: setpwent();
355: while (pw = getpwent()) {
356: if (pw->pw_uid != uid)
357: continue;
358: outrangeuid = pw->pw_uid;
359: strncpy(outrangename, pw->pw_name, NMAX);
360: endpwent();
361: return (outrangename);
362: }
363: endpwent();
364: return (0);
365: }
366: if (init == 0)
367: setpwent(), init = 1;
368: while (pw = getpwent()) {
369: if (pw->pw_uid < 0 || pw->pw_uid >= NUID) {
370: if (pw->pw_uid == uid) {
371: outrangeuid = pw->pw_uid;
372: strncpy(outrangename, pw->pw_name, NMAX);
373: return (outrangename);
374: }
375: continue;
376: }
377: if (names[pw->pw_uid][0])
378: continue;
379: strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
380: if (pw->pw_uid == uid)
381: return (&names[uid][0]);
382: }
383: init = 2;
384: goto rescan;
385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.