xref: /original-bsd/usr.sbin/quot/quot.c (revision 5998a314)
1 static char *sccsid = "@(#)quot.c	4.2 (Berkeley) 82/03/29";
2 
3 /*
4  * quot
5  */
6 
7 #include <stdio.h>
8 #include <ctype.h>
9 #include <pwd.h>
10 #include <sys/param.h>
11 #include <sys/ino.h>
12 #include <sys/inode.h>
13 #include <sys/filsys.h>
14 
15 #define	ITABSZ	256
16 #define	ISIZ	(BSIZE/sizeof(struct dinode))
17 #define	NUID	1000
18 struct	filsys	sblock;
19 struct	dinode	itab[ITABSZ];
20 struct du
21 {
22 	long	blocks;
23 	long	blocks30,blocks60,blocks90;
24 	long	nfiles;
25 	int	uid;
26 	char	*name;
27 } du[NUID];
28 #define	TSIZE	500
29 int	sizes[TSIZE];
30 long	overflow;
31 
32 int	nflg;
33 int	fflg;
34 int	cflg;
35 int	vflg;
36 long	now;
37 
38 int	fi;
39 unsigned	ino;
40 unsigned	nfiles;
41 
42 struct	passwd	*getpwent();
43 char	*malloc();
44 char	*copy();
45 
46 main(argc, argv)
47 char **argv;
48 {
49 	register int n;
50 	register struct passwd *lp;
51 	register char **p;
52 
53 	now = time(0);
54 	for(n=0; n<NUID; n++)
55 		du[n].uid = n;
56 	while((lp=getpwent()) != 0) {
57 		n = lp->pw_uid;
58 		if (n>NUID)
59 			continue;
60 		if(du[n].name)
61 			continue;
62 		du[n].name = copy(lp->pw_name);
63 	}
64 	if (argc == 1) {
65 		fprintf(stderr, "usage: df device ...\n");
66 		exit(1);
67 	}
68 	while (--argc) {
69 		argv++;
70 		if (argv[0][0]=='-') {
71 			if (argv[0][1]=='n')
72 				nflg++;
73 			else if (argv[0][1]=='f')
74 				fflg++;
75 			else if (argv[0][1]=='c')
76 				cflg++;
77 			else if (argv[0][1]=='v')
78 				vflg++;
79 		} else {
80 			check(*argv);
81 			report();
82 		}
83 	}
84 	return(0);
85 }
86 
87 check(file)
88 char *file;
89 {
90 	register unsigned i, j;
91 	register c;
92 
93 	fi = open(file, 0);
94 	if (fi < 0) {
95 		printf("cannot open %s\n", file);
96 		return;
97 	}
98 	printf("%s:\n", file);
99 	sync();
100 	bread(1, (char *)&sblock, sizeof sblock);
101 	nfiles = (sblock.s_isize-2)*(BSIZE/sizeof(struct dinode));
102 	ino = 0;
103 	if (nflg) {
104 		if (isdigit(c = getchar()))
105 			ungetc(c, stdin);
106 		else while (c!='\n' && c != EOF)
107 			c = getchar();
108 	}
109 	for(i=2; ino<nfiles; i += ITABSZ/ISIZ) {
110 		bread(i, (char *)itab, sizeof itab);
111 		for (j=0; j<ITABSZ && ino<nfiles; j++) {
112 			ino++;
113 			acct(&itab[j]);
114 		}
115 	}
116 }
117 
118 acct(ip)
119 register struct dinode *ip;
120 {
121 	register n;
122 	register char *np;
123 	static fino;
124 
125 	if ((ip->di_mode&IFMT) == 0)
126 		return;
127 	if (cflg) {
128 		if ((ip->di_mode&IFMT)!=IFDIR && (ip->di_mode&IFMT)!=IFREG)
129 			return;
130 		n = (ip->di_size+BSIZE-1)/BSIZE;
131 		if (n >= TSIZE) {
132 			overflow += n;
133 			n = TSIZE-1;
134 		}
135 		sizes[n]++;
136 		return;
137 	}
138 	if (ip->di_uid >= NUID)
139 		return;
140 	du[ip->di_uid].blocks += (ip->di_size+BSIZE-1)/BSIZE;
141 #define	DAY (60 * 60 * 24)	/* seconds per day */
142 	if (now - ip->di_atime > 30 * DAY)
143 		du[ip->di_uid].blocks30 += (ip->di_size+BSIZE-1)/BSIZE;
144 	if (now - ip->di_atime > 60 * DAY)
145 		du[ip->di_uid].blocks60 += (ip->di_size+BSIZE-1)/BSIZE;
146 	if (now - ip->di_atime > 90 * DAY)
147 		du[ip->di_uid].blocks90 += (ip->di_size+BSIZE-1)/BSIZE;
148 	du[ip->di_uid].nfiles++;
149 	if (nflg) {
150 	tryagain:
151 		if (fino==0)
152 			if (scanf("%d", &fino)<=0)
153 				return;
154 		if (fino > ino)
155 			return;
156 		if (fino<ino) {
157 			while ((n=getchar())!='\n' && n!=EOF)
158 				;
159 			fino = 0;
160 			goto tryagain;
161 		}
162 		if (np = du[ip->di_uid].name)
163 			printf("%.7s	", np);
164 		else
165 			printf("%d	", ip->di_uid);
166 		while ((n = getchar())==' ' || n=='\t')
167 			;
168 		putchar(n);
169 		while (n!=EOF && n!='\n') {
170 			n = getchar();
171 			putchar(n);
172 		}
173 		fino = 0;
174 	}
175 }
176 
177 bread(bno, buf, cnt)
178 unsigned bno;
179 char *buf;
180 {
181 
182 	lseek(fi, (long)bno*BSIZE, 0);
183 	if (read(fi, buf, cnt) != cnt) {
184 		printf("read error %u\n", bno);
185 		exit(1);
186 	}
187 }
188 
189 qcmp(p1, p2)
190 register struct du *p1, *p2;
191 {
192 	if (p1->blocks > p2->blocks)
193 		return(-1);
194 	if (p1->blocks < p2->blocks)
195 		return(1);
196 	return(strcmp(p1->name, p2->name));
197 }
198 
199 report()
200 {
201 	register i;
202 
203 	if (nflg)
204 		return;
205 	if (cflg) {
206 		long t = 0;
207 		for (i=0; i<TSIZE-1; i++)
208 			if (sizes[i]) {
209 				t += i*sizes[i];
210 				printf("%d	%d	%D\n", i, sizes[i], t);
211 			}
212 		printf("%d	%d	%D\n", TSIZE-1, sizes[TSIZE-1], overflow+t);
213 		return;
214 	}
215 	qsort(du, NUID, sizeof(du[0]), qcmp);
216 	for (i=0; i<NUID; i++) {
217 		if (du[i].blocks==0)
218 			return;
219 		printf("%5D\t", du[i].blocks);
220 		if (fflg)
221 			printf("%5D\t", du[i].nfiles);
222 		if (du[i].name)
223 			printf("%-8.8s", du[i].name);
224 		else
225 			printf("#%-8d", du[i].uid);
226 		if (vflg)
227 			printf("\t%5D\t%5D\t%5D",
228 			    du[i].blocks30, du[i].blocks60, du[i].blocks90);
229 		printf("\n");
230 	}
231 }
232 
233 char *
234 copy(s)
235 char *s;
236 {
237 	register char *p;
238 	register n;
239 
240 	for(n=0; s[n]; n++)
241 		;
242 	p = malloc((unsigned)n+1);
243 	for(n=0; p[n] = s[n]; n++)
244 		;
245 	return(p);
246 }
247