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