quot.c revision 30262
1290931Srodrigc/*
2290931Srodrigc * Copyright (C) 1991, 1994 Wolfgang Solfrank.
3290931Srodrigc * Copyright (C) 1991, 1994 TooLs GmbH.
4290931Srodrigc * All rights reserved.
5290931Srodrigc *
6290931Srodrigc * Redistribution and use in source and binary forms, with or without
7290931Srodrigc * modification, are permitted provided that the following conditions
8290931Srodrigc * are met:
9290931Srodrigc * 1. Redistributions of source code must retain the above copyright
10290931Srodrigc *    notice, this list of conditions and the following disclaimer.
11290931Srodrigc * 2. Redistributions in binary form must reproduce the above copyright
12290931Srodrigc *    notice, this list of conditions and the following disclaimer in the
13290931Srodrigc *    documentation and/or other materials provided with the distribution.
14290931Srodrigc * 3. All advertising materials mentioning features or use of this software
15290931Srodrigc *    must display the following acknowledgement:
16290931Srodrigc *	This product includes software developed by TooLs GmbH.
17290931Srodrigc * 4. The name of TooLs GmbH may not be used to endorse or promote products
18290931Srodrigc *    derived from this software without specific prior written permission.
19290931Srodrigc *
20290937Srodrigc * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21290931Srodrigc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22290931Srodrigc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23290931Srodrigc * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24290931Srodrigc * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25290931Srodrigc * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26290931Srodrigc * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27290931Srodrigc * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28290931Srodrigc * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29290931Srodrigc * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30290931Srodrigc */
31290931Srodrigc
32290931Srodrigc#ifndef lint
33290931Srodrigcstatic const char rcsid[] =
34290931Srodrigc	"$Id: quot.c,v 1.6 1997/08/13 12:09:48 jkh Exp $";
35290931Srodrigc#endif /* not lint */
36290931Srodrigc
37290931Srodrigc#include <sys/param.h>
38290931Srodrigc#include <sys/mount.h>
39290931Srodrigc#include <sys/time.h>
40290931Srodrigc#include <ufs/ffs/fs.h>
41290931Srodrigc#include <ufs/ufs/quota.h>
42290931Srodrigc#include <ufs/ufs/inode.h>
43290931Srodrigc
44290931Srodrigc#include <err.h>
45290931Srodrigc#include <fcntl.h>
46290931Srodrigc#include <errno.h>
47290931Srodrigc#include <pwd.h>
48290931Srodrigc#include <stdio.h>
49290931Srodrigc#include <stdlib.h>
50290931Srodrigc#include <string.h>
51290931Srodrigc#include <unistd.h>
52290931Srodrigc
53290931Srodrigc/* some flags of what to do: */
54290931Srodrigcstatic char estimate;
55290931Srodrigcstatic char count;
56290931Srodrigcstatic char unused;
57290931Srodrigcstatic void (*func)();
58290931Srodrigcstatic long blocksize;
59290931Srodrigcstatic char *header;
60290931Srodrigcstatic int headerlen;
61290931Srodrigc
62290931Srodrigc/*
63290931Srodrigc * Original BSD quot doesn't round to number of frags/blocks,
64290931Srodrigc * doesn't account for indirection blocks and gets it totally
65290931Srodrigc * wrong if the	size is a multiple of the blocksize.
66290931Srodrigc * The new code always counts the number of 512 byte blocks
67290931Srodrigc * instead of the number of kilobytes and converts them	to
68290931Srodrigc * kByte when done (on request).
69290931Srodrigc */
70290931Srodrigc#ifdef	COMPAT
71290931Srodrigc#define	SIZE(n)	(n)
72290931Srodrigc#else
73290931Srodrigc#define	SIZE(n)	(((n) * 512 + blocksize - 1)/blocksize)
74290931Srodrigc#endif
75290931Srodrigc
76290931Srodrigc#define	INOCNT(fs)	((fs)->fs_ipg)
77290931Srodrigc#define	INOSZ(fs)	(sizeof(struct dinode) * INOCNT(fs))
78290931Srodrigc
79290931Srodrigcstatic struct dinode *
80290931Srodrigcget_inode(fd,super,ino)
81290931Srodrigc	struct fs *super;
82290931Srodrigc	ino_t ino;
83290931Srodrigc{
84290931Srodrigc	static struct dinode *ip;
85290931Srodrigc	static ino_t last;
86290931Srodrigc
87290931Srodrigc	if (fd < 0) {		/* flush cache */
88290931Srodrigc		if (ip) {
89290931Srodrigc			free(ip);
90290931Srodrigc			ip = 0;
91290931Srodrigc		}
92290931Srodrigc		return 0;
93290931Srodrigc	}
94290931Srodrigc
95290931Srodrigc	if (!ip || ino < last || ino >= last + INOCNT(super)) {
96290931Srodrigc		if (!ip
97290931Srodrigc		    && !(ip = (struct dinode *)malloc(INOSZ(super))))
98290931Srodrigc			errx(1, "allocate inodes");
99290931Srodrigc		last = (ino / INOCNT(super)) * INOCNT(super);
100290931Srodrigc		if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
101290931Srodrigc		    || read(fd,ip,INOSZ(super)) != INOSZ(super))
102290931Srodrigc			err(1, "read inodes");
103290931Srodrigc	}
104290931Srodrigc
105290931Srodrigc	return ip + ino % INOCNT(super);
106290931Srodrigc}
107290931Srodrigc
108290931Srodrigc#ifdef	COMPAT
109290931Srodrigc#define	actualblocks(super,ip)	((ip)->di_blocks/2)
110290931Srodrigc#else
111290931Srodrigc#define	actualblocks(super,ip)	((ip)->di_blocks)
112290931Srodrigc#endif
113290931Srodrigc
114290931Srodrigcstatic int virtualblocks(super,ip)
115290931Srodrigc	struct fs *super;
116290931Srodrigc	struct dinode *ip;
117290931Srodrigc{
118290931Srodrigc	register off_t nblk, sz;
119290931Srodrigc
120290931Srodrigc	sz = ip->di_size;
121290931Srodrigc#ifdef	COMPAT
122290931Srodrigc	if (lblkno(super,sz) >= NDADDR) {
123290931Srodrigc		nblk = blkroundup(super,sz);
124290931Srodrigc		if (sz == nblk)
125290931Srodrigc			nblk += super->fs_bsize;
126290931Srodrigc	}
127290931Srodrigc
128290931Srodrigc	return sz / 1024;
129290931Srodrigc
130290931Srodrigc#else	/* COMPAT */
131290931Srodrigc
132290931Srodrigc	if (lblkno(super,sz) >= NDADDR) {
133290931Srodrigc		nblk = blkroundup(super,sz);
134290931Srodrigc		sz = lblkno(super,nblk);
135290931Srodrigc		sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super);
136290931Srodrigc		while (sz > 0) {
137290931Srodrigc			nblk += sz * super->fs_bsize;
138290931Srodrigc			/* sz - 1 rounded up */
139290931Srodrigc			sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
140290931Srodrigc		}
141290931Srodrigc	} else
142290931Srodrigc		nblk = fragroundup(super,sz);
143290931Srodrigc
144290931Srodrigc	return nblk / 512;
145290931Srodrigc#endif	/* COMPAT */
146290931Srodrigc}
147290931Srodrigc
148290931Srodrigcstatic int
149290931Srodrigcisfree(ip)
150290931Srodrigc	struct dinode *ip;
151290931Srodrigc{
152290931Srodrigc#ifdef	COMPAT
153290931Srodrigc	return (ip->di_mode&IFMT) == 0;
154290931Srodrigc#else	/* COMPAT */
155290931Srodrigc
156290931Srodrigc	switch (ip->di_mode&IFMT) {
157290931Srodrigc	case IFIFO:
158290931Srodrigc	case IFLNK:		/* should check FASTSYMLINK? */
159290931Srodrigc	case IFDIR:
160290931Srodrigc	case IFREG:
161290931Srodrigc		return 0;
162290931Srodrigc	default:
163290931Srodrigc		return 1;
164290931Srodrigc	}
165290931Srodrigc#endif
166290931Srodrigc}
167290931Srodrigc
168290931Srodrigcstatic struct user {
169290931Srodrigc	uid_t uid;
170290931Srodrigc	char *name;
171290931Srodrigc	daddr_t space;
172290931Srodrigc	long count;
173290931Srodrigc	daddr_t spc30;
174290931Srodrigc	daddr_t spc60;
175290931Srodrigc	daddr_t spc90;
176290931Srodrigc} *users;
177290931Srodrigcstatic int nusers;
178290931Srodrigc
179290931Srodrigcstatic void
180290931Srodrigcinituser()
181290931Srodrigc{
182290931Srodrigc	register i;
183290931Srodrigc	register struct user *usr;
184290931Srodrigc
185290931Srodrigc	if (!nusers) {
186290931Srodrigc		nusers = 8;
187290931Srodrigc		if (!(users =
188290931Srodrigc		    (struct user *)calloc(nusers,sizeof(struct user))))
189290931Srodrigc			errx(1, "allocate users");
190290931Srodrigc	} else {
191290931Srodrigc		for (usr = users, i = nusers; --i >= 0; usr++) {
192290931Srodrigc			usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0;
193290931Srodrigc			usr->count = 0;
194290931Srodrigc		}
195290931Srodrigc	}
196290931Srodrigc}
197290931Srodrigc
198290931Srodrigcstatic void
199290931Srodrigcusrrehash()
200290931Srodrigc{
201290931Srodrigc	register i;
202290931Srodrigc	register struct user *usr, *usrn;
203290931Srodrigc	struct user *svusr;
204290931Srodrigc
205290931Srodrigc	svusr = users;
206290931Srodrigc	nusers <<= 1;
207290931Srodrigc	if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
208290931Srodrigc		errx(1, "allocate users");
209290931Srodrigc	for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
210290931Srodrigc		for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
211290931Srodrigc		    usrn--) {
212290931Srodrigc			if (usrn <= users)
213290931Srodrigc				usrn = users + nusers;
214290931Srodrigc		}
215290931Srodrigc		*usrn = *usr;
216290931Srodrigc	}
217290931Srodrigc}
218290931Srodrigc
219290931Srodrigcstatic struct user *
220290931Srodrigcuser(uid)
221290931Srodrigc	uid_t uid;
222290931Srodrigc{
223290931Srodrigc	register struct user *usr;
224290931Srodrigc	register i;
225290931Srodrigc	struct passwd *pwd;
226290931Srodrigc
227290931Srodrigc	while (1) {
228290931Srodrigc		for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
229290931Srodrigc		    usr--) {
230290931Srodrigc			if (!usr->name) {
231290931Srodrigc				usr->uid = uid;
232290931Srodrigc
233290931Srodrigc				if (!(pwd = getpwuid(uid))) {
234290931Srodrigc					if ((usr->name = (char *)malloc(7)))
235290931Srodrigc						sprintf(usr->name,"#%d",uid);
236290931Srodrigc				} else {
237290931Srodrigc					if ((usr->name = (char *)
238290931Srodrigc					    malloc(strlen(pwd->pw_name) + 1)))
239290931Srodrigc						strcpy(usr->name,pwd->pw_name);
240290931Srodrigc				}
241290931Srodrigc				if (!usr->name)
242290931Srodrigc					errx(1, "allocate users");
243290931Srodrigc
244290931Srodrigc				return usr;
245290931Srodrigc
246290931Srodrigc			} else if (usr->uid == uid)
247290931Srodrigc				return usr;
248290931Srodrigc
249290931Srodrigc			if (usr <= users)
250290931Srodrigc				usr = users + nusers;
251290931Srodrigc		}
252290931Srodrigc		usrrehash();
253290931Srodrigc	}
254290931Srodrigc}
255290931Srodrigc
256290931Srodrigcstatic int
257290931Srodrigccmpusers(u1,u2)
258290931Srodrigc	struct user *u1, *u2;
259290931Srodrigc{
260290931Srodrigc	return u2->space - u1->space;
261290931Srodrigc}
262290931Srodrigc
263290931Srodrigc#define	sortusers(users)	(qsort((users),nusers,sizeof(struct user), \
264290931Srodrigc				    cmpusers))
265290931Srodrigc
266290931Srodrigcstatic void
267290931Srodrigcuses(uid,blks,act)
268290931Srodrigc	uid_t uid;
269290931Srodrigc	daddr_t blks;
270290931Srodrigc	time_t act;
271290931Srodrigc{
272290931Srodrigc	static time_t today;
273290931Srodrigc	register struct user *usr;
274290931Srodrigc
275290931Srodrigc	if (!today)
276290931Srodrigc		time(&today);
277290931Srodrigc
278290931Srodrigc	usr = user(uid);
279290931Srodrigc	usr->count++;
280290931Srodrigc	usr->space += blks;
281290931Srodrigc
282290931Srodrigc	if (today - act > 90L * 24L * 60L * 60L)
283290931Srodrigc		usr->spc90 += blks;
284290931Srodrigc	if (today - act > 60L * 24L * 60L * 60L)
285290931Srodrigc		usr->spc60 += blks;
286290931Srodrigc	if (today - act > 30L * 24L * 60L * 60L)
287290931Srodrigc		usr->spc30 += blks;
288290931Srodrigc}
289290931Srodrigc
290290931Srodrigc#ifdef	COMPAT
291290931Srodrigc#define	FSZCNT	500
292290931Srodrigc#else
293290931Srodrigc#define	FSZCNT	512
294290931Srodrigc#endif
295290931Srodrigcstruct fsizes {
296290931Srodrigc	struct fsizes *fsz_next;
297290931Srodrigc	daddr_t fsz_first, fsz_last;
298290931Srodrigc	ino_t fsz_count[FSZCNT];
299290931Srodrigc	daddr_t fsz_sz[FSZCNT];
300290931Srodrigc} *fsizes;
301290931Srodrigc
302290931Srodrigcstatic void
303290931Srodrigcinitfsizes()
304290931Srodrigc{
305290931Srodrigc	register struct fsizes *fp;
306290931Srodrigc	register i;
307290931Srodrigc
308290931Srodrigc	for (fp = fsizes; fp; fp = fp->fsz_next) {
309290931Srodrigc		for (i = FSZCNT; --i >= 0;) {
310290931Srodrigc			fp->fsz_count[i] = 0;
311290931Srodrigc			fp->fsz_sz[i] = 0;
312290931Srodrigc		}
313290931Srodrigc	}
314290931Srodrigc}
315290931Srodrigc
316290931Srodrigcstatic void
317290931Srodrigcdofsizes(fd,super,name)
318290931Srodrigc	struct fs *super;
319290931Srodrigc	char *name;
320290931Srodrigc{
321290931Srodrigc	ino_t inode, maxino;
322290931Srodrigc	struct dinode *ip;
323290931Srodrigc	daddr_t sz, ksz;
324290931Srodrigc	struct fsizes *fp, **fsp;
325290931Srodrigc	register i;
326290931Srodrigc
327290931Srodrigc	maxino = super->fs_ncg * super->fs_ipg - 1;
328290931Srodrigc#ifdef	COMPAT
329290931Srodrigc	if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes))))
330290931Srodrigc		errx(1, "alloc fsize structure");
331290931Srodrigc#endif	/* COMPAT */
332290931Srodrigc	for (inode = 0; inode < maxino; inode++) {
333290931Srodrigc		errno = 0;
334290931Srodrigc		if ((ip = get_inode(fd,super,inode))
335290931Srodrigc#ifdef	COMPAT
336290931Srodrigc		    && ((ip->di_mode&IFMT) == IFREG
337290931Srodrigc			|| (ip->di_mode&IFMT) == IFDIR)
338290931Srodrigc#else	/* COMPAT */
339290931Srodrigc		    && !isfree(ip)
340290931Srodrigc#endif	/* COMPAT */
341290931Srodrigc		    ) {
342290931Srodrigc			sz = estimate ? virtualblocks(super,ip) :
343290931Srodrigc			    actualblocks(super,ip);
344290931Srodrigc#ifdef	COMPAT
345290931Srodrigc			if (sz >= FSZCNT) {
346290931Srodrigc				fsizes->fsz_count[FSZCNT-1]++;
347290931Srodrigc				fsizes->fsz_sz[FSZCNT-1] += sz;
348290931Srodrigc			} else {
349290931Srodrigc				fsizes->fsz_count[sz]++;
350290931Srodrigc				fsizes->fsz_sz[sz] += sz;
351290931Srodrigc			}
352290931Srodrigc#else	/* COMPAT */
353290931Srodrigc			ksz = SIZE(sz);
354290931Srodrigc			for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) {
355290931Srodrigc				if (ksz < fp->fsz_last)
356290931Srodrigc					break;
357290931Srodrigc			}
358290931Srodrigc			if (!fp || ksz < fp->fsz_first) {
359290931Srodrigc				if (!(fp = (struct fsizes *)
360290931Srodrigc				    malloc(sizeof(struct fsizes))))
361290931Srodrigc					errx(1, "alloc fsize structure");
362290931Srodrigc				fp->fsz_next = *fsp;
363290931Srodrigc				*fsp = fp;
364290931Srodrigc				fp->fsz_first = (ksz / FSZCNT) * FSZCNT;
365290931Srodrigc				fp->fsz_last = fp->fsz_first + FSZCNT;
366290931Srodrigc				for (i = FSZCNT; --i >= 0;) {
367290931Srodrigc					fp->fsz_count[i] = 0;
368290931Srodrigc					fp->fsz_sz[i] = 0;
369290931Srodrigc				}
370290931Srodrigc			}
371290931Srodrigc			fp->fsz_count[ksz % FSZCNT]++;
372290931Srodrigc			fp->fsz_sz[ksz % FSZCNT] += sz;
373290931Srodrigc#endif	/* COMPAT */
374290931Srodrigc		} else if (errno) {
375290931Srodrigc			err(1, "%s", name);
376290931Srodrigc		}
377290931Srodrigc	}
378290931Srodrigc	sz = 0;
379290931Srodrigc	for (fp = fsizes; fp; fp = fp->fsz_next) {
380290931Srodrigc		for (i = 0; i < FSZCNT; i++) {
381290931Srodrigc			if (fp->fsz_count[i])
382290931Srodrigc				printf("%d\t%d\t%d\n",fp->fsz_first + i,
383290931Srodrigc				    fp->fsz_count[i],
384290931Srodrigc				    SIZE(sz += fp->fsz_sz[i]));
385290931Srodrigc		}
386290931Srodrigc	}
387290931Srodrigc}
388290931Srodrigc
389290931Srodrigcstatic void
390290931Srodrigcdouser(fd,super,name)
391290931Srodrigc	struct fs *super;
392290931Srodrigc	char *name;
393290931Srodrigc{
394290931Srodrigc	ino_t inode, maxino;
395290931Srodrigc	struct user *usr, *usrs;
396290931Srodrigc	struct dinode *ip;
397290931Srodrigc	register n;
398290931Srodrigc
399290931Srodrigc	maxino = super->fs_ncg * super->fs_ipg - 1;
400290931Srodrigc	for (inode = 0; inode < maxino; inode++) {
401290931Srodrigc		errno = 0;
402290931Srodrigc		if ((ip = get_inode(fd,super,inode))
403290931Srodrigc		    && !isfree(ip))
404290931Srodrigc			uses(ip->di_uid,
405290931Srodrigc			    estimate ? virtualblocks(super,ip) :
406290931Srodrigc				actualblocks(super,ip),
407290931Srodrigc			    ip->di_atime);
408290931Srodrigc		else if (errno) {
409290931Srodrigc			err(1, "%s", name);
410290931Srodrigc		}
411290931Srodrigc	}
412290931Srodrigc	if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
413290931Srodrigc		errx(1, "allocate users");
414290931Srodrigc	bcopy(users,usrs,nusers * sizeof(struct user));
415290931Srodrigc	sortusers(usrs);
416290931Srodrigc	for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
417290931Srodrigc		printf("%5d",SIZE(usr->space));
418290931Srodrigc		if (count)
419290931Srodrigc			printf("\t%5d",usr->count);
420290931Srodrigc		printf("\t%-8s",usr->name);
421290931Srodrigc		if (unused)
422290931Srodrigc			printf("\t%5d\t%5d\t%5d",
423290931Srodrigc			       SIZE(usr->spc30),
424290931Srodrigc			       SIZE(usr->spc60),
425290931Srodrigc			       SIZE(usr->spc90));
426290931Srodrigc		printf("\n");
427290931Srodrigc	}
428290931Srodrigc	free(usrs);
429290931Srodrigc}
430290931Srodrigc
431290931Srodrigcstatic void
432290931Srodrigcdonames(fd,super,name)
433290931Srodrigc	struct fs *super;
434290931Srodrigc	char *name;
435290931Srodrigc{
436290931Srodrigc	int c;
437290931Srodrigc	ino_t inode, inode1;
438290931Srodrigc	ino_t maxino;
439290931Srodrigc	struct dinode *ip;
440290931Srodrigc
441290931Srodrigc	maxino = super->fs_ncg * super->fs_ipg - 1;
442290931Srodrigc	/* first skip the name of the filesystem */
443290931Srodrigc	while ((c = getchar()) != EOF && (c < '0' || c > '9'))
444290931Srodrigc		while ((c = getchar()) != EOF && c != '\n');
445290931Srodrigc	ungetc(c,stdin);
446290931Srodrigc	inode1 = -1;
447290931Srodrigc	while (scanf("%d",&inode) == 1) {
448290931Srodrigc		if (inode < 0 || inode > maxino) {
449290931Srodrigc			warnx("illegal inode %d",inode);
450290931Srodrigc			return;
451290931Srodrigc		}
452290931Srodrigc		errno = 0;
453290931Srodrigc		if ((ip = get_inode(fd,super,inode))
454290931Srodrigc		    && !isfree(ip)) {
455290931Srodrigc			printf("%s\t",user(ip->di_uid)->name);
456290931Srodrigc			/* now skip whitespace */
457290931Srodrigc			while ((c = getchar()) == ' ' || c == '\t');
458290931Srodrigc			/* and print out the remainder of the input line */
459290931Srodrigc			while (c != EOF && c != '\n') {
460290931Srodrigc				putchar(c);
461290931Srodrigc				c = getchar();
462290931Srodrigc			}
463290931Srodrigc			putchar('\n');
464290931Srodrigc			inode1 = inode;
465290931Srodrigc		} else {
466290931Srodrigc			if (errno) {
467290931Srodrigc				err(1, "%s", name);
468290931Srodrigc			}
469290931Srodrigc			/* skip this line */
470290931Srodrigc			while ((c = getchar()) != EOF && c != '\n');
471290931Srodrigc		}
472290931Srodrigc		if (c == EOF)
473290931Srodrigc			break;
474290931Srodrigc	}
475290931Srodrigc}
476290931Srodrigc
477290931Srodrigcstatic void
478290931Srodrigcusage()
479290931Srodrigc{
480290931Srodrigc#ifdef	COMPAT
481290931Srodrigc	fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n");
482290931Srodrigc#else	/* COMPAT */
483290931Srodrigc	fprintf(stderr,"usage: quot [-acfhknv] [ filesystem ... ]\n");
484290931Srodrigc#endif	/* COMPAT */
485290931Srodrigc	exit(1);
486290931Srodrigc}
487290931Srodrigc
488290931Srodrigcstatic char superblock[SBSIZE];
489290931Srodrigc
490290931Srodrigcvoid
491290931Srodrigcquot(name,mp)
492290931Srodrigc	char *name, *mp;
493290931Srodrigc{
494290931Srodrigc	int fd;
495290931Srodrigc
496290931Srodrigc	get_inode(-1);		/* flush cache */
497290931Srodrigc	inituser();
498290931Srodrigc	initfsizes();
499290931Srodrigc	if ((fd = open(name,0)) < 0
500290931Srodrigc	    || lseek(fd,SBOFF,0) != SBOFF
501290931Srodrigc	    || read(fd,superblock,SBSIZE) != SBSIZE) {
502290931Srodrigc		warn("%s", name);
503290931Srodrigc		close(fd);
504290931Srodrigc		return;
505290931Srodrigc	}
506290931Srodrigc	if (((struct fs *)superblock)->fs_magic != FS_MAGIC) {
507290931Srodrigc		warnx("%s: not a BSD filesystem",name);
508290931Srodrigc		close(fd);
509290931Srodrigc		return;
510290931Srodrigc	}
511290931Srodrigc	printf("%s:",name);
512290931Srodrigc	if (mp)
513290931Srodrigc		printf(" (%s)",mp);
514290931Srodrigc	putchar('\n');
515290931Srodrigc	(*func)(fd,superblock,name);
516290931Srodrigc	close(fd);
517290931Srodrigc}
518290931Srodrigc
519290931Srodrigcint
520290931Srodrigcmain(argc,argv)
521290931Srodrigc	char **argv;
522290931Srodrigc{
523290931Srodrigc	char all = 0;
524290931Srodrigc	struct statfs *mp;
525290931Srodrigc	struct vfsconf *vfsp;
526290931Srodrigc	char dev[MNAMELEN + 1];
527290931Srodrigc	char *nm;
528290931Srodrigc	int cnt;
529290931Srodrigc
530290931Srodrigc	func = douser;
531290931Srodrigc#ifndef	COMPAT
532290931Srodrigc	header = getbsize(&headerlen,&blocksize);
533290931Srodrigc#endif
534290931Srodrigc	while (--argc > 0 && **++argv == '-') {
535290931Srodrigc		while (*++*argv) {
536290931Srodrigc			switch (**argv) {
537290931Srodrigc			case 'n':
538290931Srodrigc				func = donames;
539290931Srodrigc				break;
540290931Srodrigc			case 'c':
541290931Srodrigc				func = dofsizes;
542290931Srodrigc				break;
543290931Srodrigc			case 'a':
544290931Srodrigc				all = 1;
545290931Srodrigc				break;
546290931Srodrigc			case 'f':
547290931Srodrigc				count = 1;
548290931Srodrigc				break;
549290931Srodrigc			case 'h':
550290931Srodrigc				estimate = 1;
551290931Srodrigc				break;
552290931Srodrigc#ifndef	COMPAT
553290931Srodrigc			case 'k':
554290931Srodrigc				blocksize = 1024;
555290931Srodrigc				break;
556290931Srodrigc#endif	/* COMPAT */
557290931Srodrigc			case 'v':
558290931Srodrigc				unused = 1;
559290931Srodrigc				break;
560290931Srodrigc			default:
561290931Srodrigc				usage();
562290931Srodrigc			}
563290931Srodrigc		}
564290931Srodrigc	}
565290931Srodrigc	if (all) {
566290931Srodrigc		cnt = getmntinfo(&mp,MNT_NOWAIT);
567290931Srodrigc		vfsp = getvfsbyname("ufs");
568290931Srodrigc		if (vfsp == NULL)
569290931Srodrigc			errx(1, "cannot find ufs/ffs filesystem type!");
570290931Srodrigc		for (; --cnt >= 0; mp++) {
571290931Srodrigc			if (mp->f_type == vfsp->vfc_index) {
572290931Srodrigc				if ((nm = strrchr(mp->f_mntfromname,'/'))) {
573290931Srodrigc					sprintf(dev,"/dev/r%s",nm + 1);
574290931Srodrigc					nm = dev;
575290931Srodrigc				} else
576290931Srodrigc					nm = mp->f_mntfromname;
577290931Srodrigc				quot(nm,mp->f_mntonname);
578290931Srodrigc			}
579290931Srodrigc		}
580290931Srodrigc	}
581290931Srodrigc	while (--argc >= 0)
582290931Srodrigc		quot(*argv++,0);
583290931Srodrigc	return 0;
584290931Srodrigc}
585290931Srodrigc