1*12660Smckusick #ifndef lit
2*12660Smckusick static char sccsid[] = "@(#)quotacheck.c	4.1 (Melbourne) 05/22/83";
3*12660Smckusick #endif
4*12660Smckusick 
5*12660Smckusick /*
6*12660Smckusick  * Fix up / report on disc quotas & usage
7*12660Smckusick  */
8*12660Smckusick #include <stdio.h>
9*12660Smckusick #include <ctype.h>
10*12660Smckusick #include <signal.h>
11*12660Smckusick #include <pwd.h>
12*12660Smckusick #include <sys/param.h>
13*12660Smckusick #include <sys/inode.h>
14*12660Smckusick #include <sys/fs.h>
15*12660Smckusick #define	QUOTA
16*12660Smckusick #include <sys/quota.h>
17*12660Smckusick #include <sys/stat.h>
18*12660Smckusick 
19*12660Smckusick #define	ITABSZ	256
20*12660Smckusick #define	NUID	3500
21*12660Smckusick union {
22*12660Smckusick 	struct	fs	sblk;
23*12660Smckusick 	char	___[MAXBSIZE];
24*12660Smckusick } un;
25*12660Smckusick #define	sblock	un.sblk
26*12660Smckusick struct	dinode	itab[ITABSZ];
27*12660Smckusick struct	dinode	*dp;
28*12660Smckusick struct	dqblk	du[NUID];
29*12660Smckusick char	*dn[NUID];
30*12660Smckusick struct	dqblk	zeroes;
31*12660Smckusick u_short	iuse[NUID];
32*12660Smckusick u_long	buse[NUID];
33*12660Smckusick long	blocks;
34*12660Smckusick dev_t	dev;
35*12660Smckusick 
36*12660Smckusick int	bflg;
37*12660Smckusick int	iflg;
38*12660Smckusick int	rflg;
39*12660Smckusick int	sflg;
40*12660Smckusick 
41*12660Smckusick int	fi;
42*12660Smckusick unsigned	ino;
43*12660Smckusick unsigned	nfiles;
44*12660Smckusick int	highuid;
45*12660Smckusick 
46*12660Smckusick struct	passwd	*getpwent();
47*12660Smckusick struct	dinode	*ginode();
48*12660Smckusick char	*malloc();
49*12660Smckusick char	*copy();
50*12660Smckusick 
51*12660Smckusick main(argc, argv)
52*12660Smckusick 	char **argv;
53*12660Smckusick {
54*12660Smckusick 	register int n;
55*12660Smckusick 	register struct passwd *lp;
56*12660Smckusick 	register char *p;
57*12660Smckusick 	register long unsigned i;
58*12660Smckusick 	register c;
59*12660Smckusick 	register cg;
60*12660Smckusick 	FILE *qf;
61*12660Smckusick 	struct stat statb;
62*12660Smckusick 
63*12660Smckusick 	while (--argc > 0 && *(p = *++argv) == '-')
64*12660Smckusick 		while (c = *++p) switch (c) {
65*12660Smckusick 
66*12660Smckusick 		case 's':
67*12660Smckusick 			sflg++;
68*12660Smckusick 			break;
69*12660Smckusick 
70*12660Smckusick 		case 'b':
71*12660Smckusick 			bflg++;
72*12660Smckusick 			break;
73*12660Smckusick 
74*12660Smckusick 		case 'i':
75*12660Smckusick 			iflg++;
76*12660Smckusick 			break;
77*12660Smckusick 
78*12660Smckusick 		case 'r':
79*12660Smckusick 			rflg++;
80*12660Smckusick 			break;
81*12660Smckusick 		}
82*12660Smckusick 
83*12660Smckusick 	if (argc != 2) {
84*12660Smckusick 		fprintf(stderr, "Usage: fixquota filesys qfile\n");
85*12660Smckusick 		exit(1);
86*12660Smckusick 	}
87*12660Smckusick 
88*12660Smckusick 	fi = open(p, 0);
89*12660Smckusick 	if (fi < 0) {
90*12660Smckusick 		fprintf(stderr, "Can't open %s\n", p);
91*12660Smckusick 		exit(1);
92*12660Smckusick 	}
93*12660Smckusick 
94*12660Smckusick 	if (iflg || bflg || rflg) {
95*12660Smckusick 		while((lp=getpwent()) != 0) {
96*12660Smckusick 			n = lp->pw_uid;
97*12660Smckusick 			if (n>=NUID)
98*12660Smckusick 				continue;
99*12660Smckusick 			if(dn[n])
100*12660Smckusick 				continue;
101*12660Smckusick 			dn[n] = copy(lp->pw_name);
102*12660Smckusick 		}
103*12660Smckusick 	}
104*12660Smckusick 
105*12660Smckusick 	if (!(iflg || bflg))
106*12660Smckusick 		sflg++;
107*12660Smckusick 
108*12660Smckusick 	qf = fopen(*++argv, "r");
109*12660Smckusick 	if (qf != NULL) {
110*12660Smckusick 		fstat(fileno(qf), &statb);
111*12660Smckusick 		dev = statb.st_dev;
112*12660Smckusick 		quota(Q_SYNC, 0, dev, 0);
113*12660Smckusick 		n = fread(du, sizeof(struct dqblk), NUID, qf);
114*12660Smckusick 		if (n == EOF)
115*12660Smckusick 			n = 0;
116*12660Smckusick 		highuid = n-1;
117*12660Smckusick 		fclose(qf);
118*12660Smckusick 	} else {
119*12660Smckusick 		highuid = -1;
120*12660Smckusick 		dev = NODEV;
121*12660Smckusick 	}
122*12660Smckusick /*ZZprintf("highuid = %d\n", highuid);*/
123*12660Smckusick 
124*12660Smckusick 	for (n = 0; n <= highuid; n++) {
125*12660Smckusick 		iuse[n] = du[n].dqb_curinodes;
126*12660Smckusick 		buse[n] = du[n].dqb_curblocks;
127*12660Smckusick 		du[n].dqb_curinodes = du[n].dqb_curblocks = 0;
128*12660Smckusick 	}
129*12660Smckusick 
130*12660Smckusick 	sync();
131*12660Smckusick 	bread(SBLOCK, (char *)&sblock, SBSIZE);
132*12660Smckusick 	ino = 0;
133*12660Smckusick 	for (cg = 0; cg < sblock.fs_ncg; cg++) {
134*12660Smckusick /*ZZprintf("cg %d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", cg);*/
135*12660Smckusick 		dp = NULL;
136*12660Smckusick 		for (i = 0; i < sblock.fs_ipg; i++)
137*12660Smckusick 			acct(ginode());
138*12660Smckusick 	}
139*12660Smckusick 	if (sflg && highuid >= 0) {
140*12660Smckusick 		int sig;
141*12660Smckusick 		int ssig;
142*12660Smckusick 
143*12660Smckusick 		sig = (int) signal(SIGINT, SIG_IGN);
144*12660Smckusick 		ssig = (int) signal(SIGTSTP, SIG_IGN);
145*12660Smckusick 		if ((qf = fopen(*argv, "a")) == NULL) {
146*12660Smckusick 			fprintf(stderr, "Can't create %s\n", *argv);
147*12660Smckusick 			exit(1);
148*12660Smckusick 		}
149*12660Smckusick 
150*12660Smckusick 		rewind(qf);
151*12660Smckusick 		fwrite(du, sizeof(struct dqblk), highuid+1, qf);
152*12660Smckusick 		fclose(qf);
153*12660Smckusick 		signal(SIGTSTP, ssig);
154*12660Smckusick 		sysset();
155*12660Smckusick 		signal(SIGINT, sig);
156*12660Smckusick 	}
157*12660Smckusick 	report();
158*12660Smckusick }
159*12660Smckusick 
160*12660Smckusick acct(ip)
161*12660Smckusick 	register struct dinode *ip;
162*12660Smckusick {
163*12660Smckusick 	register n;
164*12660Smckusick 
165*12660Smckusick 	if (ip == NULL)
166*12660Smckusick 		return;
167*12660Smckusick 	if (ip->di_mode == 0)
168*12660Smckusick /*ZZ{printf(" unallocated\n");*/
169*12660Smckusick 		return;
170*12660Smckusick /*ZZ}*/
171*12660Smckusick 	if (ip->di_uid >= NUID)
172*12660Smckusick /*ZZ{printf(" uid oor\n");*/
173*12660Smckusick 		return;
174*12660Smckusick /*ZZ}*/
175*12660Smckusick 	if (ip->di_uid > highuid) {
176*12660Smckusick 		for (n = highuid+1; n <= ip->di_uid; n++)
177*12660Smckusick 			du[n] = zeroes;
178*12660Smckusick 		highuid = ip->di_uid;
179*12660Smckusick 	}
180*12660Smckusick 	du[ip->di_uid].dqb_curinodes++;
181*12660Smckusick 	if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
182*12660Smckusick /*ZZ{printf(" special\n");*/
183*12660Smckusick 		return;
184*12660Smckusick /*ZZ}*/
185*12660Smckusick 	blocks = 0;
186*12660Smckusick 	for (n = 0; n < NDADDR; n++)
187*12660Smckusick 		if (ip->di_db[n])
188*12660Smckusick 			blocks += dblksize(&sblock, ip, n) / DEV_BSIZE;
189*12660Smckusick 	for (n = 0; n < NIADDR; n++)
190*12660Smckusick 		tloop(ip->di_ib[n], ip, n);
191*12660Smckusick 	du[ip->di_uid].dqb_curblocks += blocks;
192*12660Smckusick 	if (blocks != ip->di_blocks)
193*12660Smckusick 		printf("Ino %d: <calc %d, recorded %d>\n", ino, blocks, ip->di_blocks);
194*12660Smckusick /*ZZprintf(" %d blks\n", blocks);*/
195*12660Smckusick }
196*12660Smckusick 
197*12660Smckusick tloop(bn, ip, f)
198*12660Smckusick 	long bn;
199*12660Smckusick {
200*12660Smckusick 	register i;
201*12660Smckusick 	long	iblk[MAXBSIZE/sizeof(long)];
202*12660Smckusick 
203*12660Smckusick 	if (!bn)
204*12660Smckusick 		return;
205*12660Smckusick 	blocks += sblock.fs_bsize / DEV_BSIZE;
206*12660Smckusick 	bread(fsbtodb(&sblock, bn), iblk, sblock.fs_bsize);
207*12660Smckusick 	if (f) {
208*12660Smckusick 		for (i = 0; i < NINDIR(&sblock); i++)
209*12660Smckusick 			tloop(iblk[i], ip, f-1);
210*12660Smckusick 	} else {
211*12660Smckusick 		for (i = 0; i < NINDIR(&sblock); i++)
212*12660Smckusick 			if (iblk[i])
213*12660Smckusick 				blocks += sblock.fs_bsize / DEV_BSIZE;
214*12660Smckusick 	}
215*12660Smckusick }
216*12660Smckusick 
217*12660Smckusick struct dinode *
218*12660Smckusick ginode()
219*12660Smckusick {
220*12660Smckusick 	register unsigned long iblk;
221*12660Smckusick 
222*12660Smckusick 	if (dp == NULL || ++dp >= &itab[ITABSZ]) {
223*12660Smckusick 		iblk = itod(&sblock, ino);
224*12660Smckusick /*ZZprintf("dp = %x, itab=%x", dp, itab);*/
225*12660Smckusick /*ZZprintf(" Reading inodes from fs blk %d ", iblk);*/
226*12660Smckusick 		bread(fsbtodb(&sblock, iblk), (char *)itab, sizeof itab);
227*12660Smckusick 		dp = &itab[ino % INOPB(&sblock)];
228*12660Smckusick /*ZZprintf("dp = %x\n", dp, itab);*/
229*12660Smckusick 	}
230*12660Smckusick /*ZZprintf("ino %d ", ino);*/
231*12660Smckusick 	if (ino++ < ROOTINO)
232*12660Smckusick 		return(NULL);
233*12660Smckusick 	return(dp);
234*12660Smckusick }
235*12660Smckusick 
236*12660Smckusick bread(bno, buf, cnt)
237*12660Smckusick 	long unsigned bno;
238*12660Smckusick 	char *buf;
239*12660Smckusick {
240*12660Smckusick 
241*12660Smckusick 	lseek(fi, (long)bno*DEV_BSIZE, 0);
242*12660Smckusick 	if (read(fi, buf, cnt) != cnt) {
243*12660Smckusick 		printf("read error %u\n", bno);
244*12660Smckusick 		exit(1);
245*12660Smckusick 	}
246*12660Smckusick }
247*12660Smckusick 
248*12660Smckusick sysset()
249*12660Smckusick {
250*12660Smckusick 	struct dqusage usage;
251*12660Smckusick 	register i;
252*12660Smckusick 
253*12660Smckusick 	for (i = 0; i <= highuid; i++) {
254*12660Smckusick 		if (du[i].dqb_curinodes != iuse[i] || du[i].dqb_curblocks != buse[i]) {
255*12660Smckusick 			if (du[i].dqb_isoftlimit == 0 && du[i].dqb_bsoftlimit == 0)
256*12660Smckusick 				continue;
257*12660Smckusick 			if (rflg) {
258*12660Smckusick 				if (dn[i])
259*12660Smckusick 					printf("%s", dn[i]);
260*12660Smckusick 				else
261*12660Smckusick 					printf("#%d", i);
262*12660Smckusick 				printf(": i %d->%d, b %d->%d\n"
263*12660Smckusick 					, iuse[i]
264*12660Smckusick 					, du[i].dqb_curinodes
265*12660Smckusick 					, buse[i]
266*12660Smckusick 					, du[i].dqb_curblocks
267*12660Smckusick 				);
268*12660Smckusick 			}
269*12660Smckusick 			usage.du_curinodes = du[i].dqb_curinodes;
270*12660Smckusick 			usage.du_curblocks = du[i].dqb_curblocks;
271*12660Smckusick 			quota(Q_SETDUSE, i, dev, &usage);
272*12660Smckusick 		}
273*12660Smckusick 	}
274*12660Smckusick }
275*12660Smckusick 
276*12660Smckusick report()
277*12660Smckusick {
278*12660Smckusick 	register i;
279*12660Smckusick 
280*12660Smckusick 	if (iflg)
281*12660Smckusick 		for (i = 0; i <= highuid; i++)
282*12660Smckusick 			if (du[i].dqb_isoftlimit && du[i].dqb_curinodes >= du[i].dqb_isoftlimit) {
283*12660Smckusick 				if (dn[i])
284*12660Smckusick 					printf("%-10s", dn[i]);
285*12660Smckusick 				else
286*12660Smckusick 					printf("#%-9d", i);
287*12660Smckusick 				printf("%5d (iq = %d)\n", du[i].dqb_curinodes, du[i].dqb_isoftlimit);
288*12660Smckusick 			}
289*12660Smckusick 
290*12660Smckusick 	if (bflg)
291*12660Smckusick 		for (i = 0; i <= highuid; i++)
292*12660Smckusick 			if (du[i].dqb_bsoftlimit && du[i].dqb_curblocks >= du[i].dqb_bsoftlimit) {
293*12660Smckusick 				if (dn[i])
294*12660Smckusick 					printf("%-10s", dn[i]);
295*12660Smckusick 				else
296*12660Smckusick 					printf("#%-9s", i);
297*12660Smckusick 				printf("%5d (quot = %d)\n", du[i].dqb_curblocks, du[i].dqb_bsoftlimit);
298*12660Smckusick 			}
299*12660Smckusick }
300*12660Smckusick 
301*12660Smckusick char *
302*12660Smckusick copy(s)
303*12660Smckusick 	char *s;
304*12660Smckusick {
305*12660Smckusick 	register char *p;
306*12660Smckusick 	register n;
307*12660Smckusick 
308*12660Smckusick 	for(n=0; s[n]; n++)
309*12660Smckusick 		;
310*12660Smckusick 	p = malloc((unsigned)n+1);
311*12660Smckusick 	for(n=0; p[n] = s[n]; n++)
312*12660Smckusick 		;
313*12660Smckusick 	return(p);
314*12660Smckusick }
315