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