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