xref: /freebsd/usr.sbin/quot/quot.c (revision 9983067e)
116c2ba93SPeter Wemm /*
216c2ba93SPeter Wemm  * Copyright (C) 1991, 1994 Wolfgang Solfrank.
316c2ba93SPeter Wemm  * Copyright (C) 1991, 1994 TooLs GmbH.
416c2ba93SPeter Wemm  * All rights reserved.
516c2ba93SPeter Wemm  *
616c2ba93SPeter Wemm  * Redistribution and use in source and binary forms, with or without
716c2ba93SPeter Wemm  * modification, are permitted provided that the following conditions
816c2ba93SPeter Wemm  * are met:
916c2ba93SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
1016c2ba93SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
1116c2ba93SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
1216c2ba93SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
1316c2ba93SPeter Wemm  *    documentation and/or other materials provided with the distribution.
1416c2ba93SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
1516c2ba93SPeter Wemm  *    must display the following acknowledgement:
1616c2ba93SPeter Wemm  *	This product includes software developed by TooLs GmbH.
1716c2ba93SPeter Wemm  * 4. The name of TooLs GmbH may not be used to endorse or promote products
1816c2ba93SPeter Wemm  *    derived from this software without specific prior written permission.
1916c2ba93SPeter Wemm  *
2016c2ba93SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2116c2ba93SPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2216c2ba93SPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2316c2ba93SPeter Wemm  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2416c2ba93SPeter Wemm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2516c2ba93SPeter Wemm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2616c2ba93SPeter Wemm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2716c2ba93SPeter Wemm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2816c2ba93SPeter Wemm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2916c2ba93SPeter Wemm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3016c2ba93SPeter Wemm  */
3116c2ba93SPeter Wemm 
3216c2ba93SPeter Wemm #ifndef lint
336980f0ebSPhilippe Charnier static const char rcsid[] =
349983067eSMatthew Dillon 	"$Id: quot.c,v 1.8 1998/01/17 16:45:03 bde Exp $";
3516c2ba93SPeter Wemm #endif /* not lint */
3616c2ba93SPeter Wemm 
3716c2ba93SPeter Wemm #include <sys/param.h>
3816c2ba93SPeter Wemm #include <sys/mount.h>
3916c2ba93SPeter Wemm #include <sys/time.h>
4016c2ba93SPeter Wemm #include <ufs/ffs/fs.h>
4116c2ba93SPeter Wemm #include <ufs/ufs/quota.h>
4216c2ba93SPeter Wemm #include <ufs/ufs/inode.h>
4316c2ba93SPeter Wemm 
446980f0ebSPhilippe Charnier #include <err.h>
456980f0ebSPhilippe Charnier #include <fcntl.h>
466980f0ebSPhilippe Charnier #include <errno.h>
476980f0ebSPhilippe Charnier #include <pwd.h>
4816c2ba93SPeter Wemm #include <stdio.h>
4916c2ba93SPeter Wemm #include <stdlib.h>
5016c2ba93SPeter Wemm #include <string.h>
516980f0ebSPhilippe Charnier #include <unistd.h>
5216c2ba93SPeter Wemm 
5316c2ba93SPeter Wemm /* some flags of what to do: */
5416c2ba93SPeter Wemm static char estimate;
5516c2ba93SPeter Wemm static char count;
5616c2ba93SPeter Wemm static char unused;
576980f0ebSPhilippe Charnier static void (*func)();
5816c2ba93SPeter Wemm static long blocksize;
5916c2ba93SPeter Wemm static char *header;
6016c2ba93SPeter Wemm static int headerlen;
6116c2ba93SPeter Wemm 
6216c2ba93SPeter Wemm /*
6316c2ba93SPeter Wemm  * Original BSD quot doesn't round to number of frags/blocks,
6416c2ba93SPeter Wemm  * doesn't account for indirection blocks and gets it totally
6516c2ba93SPeter Wemm  * wrong if the	size is a multiple of the blocksize.
6616c2ba93SPeter Wemm  * The new code always counts the number of 512 byte blocks
6716c2ba93SPeter Wemm  * instead of the number of kilobytes and converts them	to
6816c2ba93SPeter Wemm  * kByte when done (on request).
699983067eSMatthew Dillon  *
709983067eSMatthew Dillon  * Due to the size of modern disks, we must cast intermediate
719983067eSMatthew Dillon  * values to 64 bits to prevent potential overflows.
7216c2ba93SPeter Wemm  */
7316c2ba93SPeter Wemm #ifdef	COMPAT
7416c2ba93SPeter Wemm #define	SIZE(n)	(n)
7516c2ba93SPeter Wemm #else
769983067eSMatthew Dillon #define	SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize))
7716c2ba93SPeter Wemm #endif
7816c2ba93SPeter Wemm 
7916c2ba93SPeter Wemm #define	INOCNT(fs)	((fs)->fs_ipg)
8016c2ba93SPeter Wemm #define	INOSZ(fs)	(sizeof(struct dinode) * INOCNT(fs))
8116c2ba93SPeter Wemm 
826980f0ebSPhilippe Charnier static struct dinode *
836980f0ebSPhilippe Charnier get_inode(fd,super,ino)
8416c2ba93SPeter Wemm 	struct fs *super;
8516c2ba93SPeter Wemm 	ino_t ino;
8616c2ba93SPeter Wemm {
8716c2ba93SPeter Wemm 	static struct dinode *ip;
8816c2ba93SPeter Wemm 	static ino_t last;
8916c2ba93SPeter Wemm 
9016c2ba93SPeter Wemm 	if (fd < 0) {		/* flush cache */
9116c2ba93SPeter Wemm 		if (ip) {
9216c2ba93SPeter Wemm 			free(ip);
9316c2ba93SPeter Wemm 			ip = 0;
9416c2ba93SPeter Wemm 		}
9516c2ba93SPeter Wemm 		return 0;
9616c2ba93SPeter Wemm 	}
9716c2ba93SPeter Wemm 
9816c2ba93SPeter Wemm 	if (!ip || ino < last || ino >= last + INOCNT(super)) {
9916c2ba93SPeter Wemm 		if (!ip
1006980f0ebSPhilippe Charnier 		    && !(ip = (struct dinode *)malloc(INOSZ(super))))
1016980f0ebSPhilippe Charnier 			errx(1, "allocate inodes");
10216c2ba93SPeter Wemm 		last = (ino / INOCNT(super)) * INOCNT(super);
103c9d12677SJordan K. Hubbard 		if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
1046980f0ebSPhilippe Charnier 		    || read(fd,ip,INOSZ(super)) != INOSZ(super))
1056980f0ebSPhilippe Charnier 			err(1, "read inodes");
10616c2ba93SPeter Wemm 	}
10716c2ba93SPeter Wemm 
10816c2ba93SPeter Wemm 	return ip + ino % INOCNT(super);
10916c2ba93SPeter Wemm }
11016c2ba93SPeter Wemm 
11116c2ba93SPeter Wemm #ifdef	COMPAT
11216c2ba93SPeter Wemm #define	actualblocks(super,ip)	((ip)->di_blocks/2)
11316c2ba93SPeter Wemm #else
11416c2ba93SPeter Wemm #define	actualblocks(super,ip)	((ip)->di_blocks)
11516c2ba93SPeter Wemm #endif
11616c2ba93SPeter Wemm 
1176980f0ebSPhilippe Charnier static int virtualblocks(super,ip)
11816c2ba93SPeter Wemm 	struct fs *super;
11916c2ba93SPeter Wemm 	struct dinode *ip;
12016c2ba93SPeter Wemm {
12116c2ba93SPeter Wemm 	register off_t nblk, sz;
12216c2ba93SPeter Wemm 
12316c2ba93SPeter Wemm 	sz = ip->di_size;
12416c2ba93SPeter Wemm #ifdef	COMPAT
12516c2ba93SPeter Wemm 	if (lblkno(super,sz) >= NDADDR) {
12616c2ba93SPeter Wemm 		nblk = blkroundup(super,sz);
12716c2ba93SPeter Wemm 		if (sz == nblk)
12816c2ba93SPeter Wemm 			nblk += super->fs_bsize;
12916c2ba93SPeter Wemm 	}
13016c2ba93SPeter Wemm 
13116c2ba93SPeter Wemm 	return sz / 1024;
13216c2ba93SPeter Wemm 
13316c2ba93SPeter Wemm #else	/* COMPAT */
13416c2ba93SPeter Wemm 
13516c2ba93SPeter Wemm 	if (lblkno(super,sz) >= NDADDR) {
13616c2ba93SPeter Wemm 		nblk = blkroundup(super,sz);
13716c2ba93SPeter Wemm 		sz = lblkno(super,nblk);
13816c2ba93SPeter Wemm 		sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super);
13916c2ba93SPeter Wemm 		while (sz > 0) {
14016c2ba93SPeter Wemm 			nblk += sz * super->fs_bsize;
14116c2ba93SPeter Wemm 			/* sz - 1 rounded up */
14216c2ba93SPeter Wemm 			sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
14316c2ba93SPeter Wemm 		}
14416c2ba93SPeter Wemm 	} else
14516c2ba93SPeter Wemm 		nblk = fragroundup(super,sz);
14616c2ba93SPeter Wemm 
14716c2ba93SPeter Wemm 	return nblk / 512;
14816c2ba93SPeter Wemm #endif	/* COMPAT */
14916c2ba93SPeter Wemm }
15016c2ba93SPeter Wemm 
1516980f0ebSPhilippe Charnier static int
1526980f0ebSPhilippe Charnier isfree(ip)
15316c2ba93SPeter Wemm 	struct dinode *ip;
15416c2ba93SPeter Wemm {
15516c2ba93SPeter Wemm #ifdef	COMPAT
15616c2ba93SPeter Wemm 	return (ip->di_mode&IFMT) == 0;
15716c2ba93SPeter Wemm #else	/* COMPAT */
15816c2ba93SPeter Wemm 
15916c2ba93SPeter Wemm 	switch (ip->di_mode&IFMT) {
16016c2ba93SPeter Wemm 	case IFIFO:
16116c2ba93SPeter Wemm 	case IFLNK:		/* should check FASTSYMLINK? */
16216c2ba93SPeter Wemm 	case IFDIR:
16316c2ba93SPeter Wemm 	case IFREG:
16416c2ba93SPeter Wemm 		return 0;
16516c2ba93SPeter Wemm 	default:
16616c2ba93SPeter Wemm 		return 1;
16716c2ba93SPeter Wemm 	}
16816c2ba93SPeter Wemm #endif
16916c2ba93SPeter Wemm }
17016c2ba93SPeter Wemm 
17116c2ba93SPeter Wemm static struct user {
17216c2ba93SPeter Wemm 	uid_t uid;
17316c2ba93SPeter Wemm 	char *name;
17416c2ba93SPeter Wemm 	daddr_t space;
17516c2ba93SPeter Wemm 	long count;
17616c2ba93SPeter Wemm 	daddr_t spc30;
17716c2ba93SPeter Wemm 	daddr_t spc60;
17816c2ba93SPeter Wemm 	daddr_t spc90;
17916c2ba93SPeter Wemm } *users;
18016c2ba93SPeter Wemm static int nusers;
18116c2ba93SPeter Wemm 
1826980f0ebSPhilippe Charnier static void
1836980f0ebSPhilippe Charnier inituser()
18416c2ba93SPeter Wemm {
18516c2ba93SPeter Wemm 	register i;
18616c2ba93SPeter Wemm 	register struct user *usr;
18716c2ba93SPeter Wemm 
18816c2ba93SPeter Wemm 	if (!nusers) {
18916c2ba93SPeter Wemm 		nusers = 8;
19016c2ba93SPeter Wemm 		if (!(users =
1916980f0ebSPhilippe Charnier 		    (struct user *)calloc(nusers,sizeof(struct user))))
1926980f0ebSPhilippe Charnier 			errx(1, "allocate users");
19316c2ba93SPeter Wemm 	} else {
19416c2ba93SPeter Wemm 		for (usr = users, i = nusers; --i >= 0; usr++) {
19516c2ba93SPeter Wemm 			usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0;
19616c2ba93SPeter Wemm 			usr->count = 0;
19716c2ba93SPeter Wemm 		}
19816c2ba93SPeter Wemm 	}
19916c2ba93SPeter Wemm }
20016c2ba93SPeter Wemm 
2016980f0ebSPhilippe Charnier static void
2026980f0ebSPhilippe Charnier usrrehash()
20316c2ba93SPeter Wemm {
20416c2ba93SPeter Wemm 	register i;
20516c2ba93SPeter Wemm 	register struct user *usr, *usrn;
20616c2ba93SPeter Wemm 	struct user *svusr;
20716c2ba93SPeter Wemm 
20816c2ba93SPeter Wemm 	svusr = users;
20916c2ba93SPeter Wemm 	nusers <<= 1;
2106980f0ebSPhilippe Charnier 	if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
2116980f0ebSPhilippe Charnier 		errx(1, "allocate users");
21216c2ba93SPeter Wemm 	for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
21316c2ba93SPeter Wemm 		for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
21416c2ba93SPeter Wemm 		    usrn--) {
21516c2ba93SPeter Wemm 			if (usrn <= users)
21616c2ba93SPeter Wemm 				usrn = users + nusers;
21716c2ba93SPeter Wemm 		}
21816c2ba93SPeter Wemm 		*usrn = *usr;
21916c2ba93SPeter Wemm 	}
22016c2ba93SPeter Wemm }
22116c2ba93SPeter Wemm 
2226980f0ebSPhilippe Charnier static struct user *
2236980f0ebSPhilippe Charnier user(uid)
22416c2ba93SPeter Wemm 	uid_t uid;
22516c2ba93SPeter Wemm {
22616c2ba93SPeter Wemm 	register struct user *usr;
22716c2ba93SPeter Wemm 	register i;
22816c2ba93SPeter Wemm 	struct passwd *pwd;
22916c2ba93SPeter Wemm 
23016c2ba93SPeter Wemm 	while (1) {
23116c2ba93SPeter Wemm 		for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
23216c2ba93SPeter Wemm 		    usr--) {
23316c2ba93SPeter Wemm 			if (!usr->name) {
23416c2ba93SPeter Wemm 				usr->uid = uid;
23516c2ba93SPeter Wemm 
23616c2ba93SPeter Wemm 				if (!(pwd = getpwuid(uid))) {
2376980f0ebSPhilippe Charnier 					if ((usr->name = (char *)malloc(7)))
23816c2ba93SPeter Wemm 						sprintf(usr->name,"#%d",uid);
23916c2ba93SPeter Wemm 				} else {
2406980f0ebSPhilippe Charnier 					if ((usr->name = (char *)
2416980f0ebSPhilippe Charnier 					    malloc(strlen(pwd->pw_name) + 1)))
24216c2ba93SPeter Wemm 						strcpy(usr->name,pwd->pw_name);
24316c2ba93SPeter Wemm 				}
2446980f0ebSPhilippe Charnier 				if (!usr->name)
2456980f0ebSPhilippe Charnier 					errx(1, "allocate users");
24616c2ba93SPeter Wemm 
24716c2ba93SPeter Wemm 				return usr;
24816c2ba93SPeter Wemm 
24916c2ba93SPeter Wemm 			} else if (usr->uid == uid)
25016c2ba93SPeter Wemm 				return usr;
25116c2ba93SPeter Wemm 
25216c2ba93SPeter Wemm 			if (usr <= users)
25316c2ba93SPeter Wemm 				usr = users + nusers;
25416c2ba93SPeter Wemm 		}
25516c2ba93SPeter Wemm 		usrrehash();
25616c2ba93SPeter Wemm 	}
25716c2ba93SPeter Wemm }
25816c2ba93SPeter Wemm 
2596980f0ebSPhilippe Charnier static int
2606980f0ebSPhilippe Charnier cmpusers(u1,u2)
26116c2ba93SPeter Wemm 	struct user *u1, *u2;
26216c2ba93SPeter Wemm {
26316c2ba93SPeter Wemm 	return u2->space - u1->space;
26416c2ba93SPeter Wemm }
26516c2ba93SPeter Wemm 
26616c2ba93SPeter Wemm #define	sortusers(users)	(qsort((users),nusers,sizeof(struct user), \
26716c2ba93SPeter Wemm 				    cmpusers))
26816c2ba93SPeter Wemm 
2696980f0ebSPhilippe Charnier static void
2706980f0ebSPhilippe Charnier uses(uid,blks,act)
27116c2ba93SPeter Wemm 	uid_t uid;
27216c2ba93SPeter Wemm 	daddr_t blks;
27316c2ba93SPeter Wemm 	time_t act;
27416c2ba93SPeter Wemm {
27516c2ba93SPeter Wemm 	static time_t today;
27616c2ba93SPeter Wemm 	register struct user *usr;
27716c2ba93SPeter Wemm 
27816c2ba93SPeter Wemm 	if (!today)
27916c2ba93SPeter Wemm 		time(&today);
28016c2ba93SPeter Wemm 
28116c2ba93SPeter Wemm 	usr = user(uid);
28216c2ba93SPeter Wemm 	usr->count++;
28316c2ba93SPeter Wemm 	usr->space += blks;
28416c2ba93SPeter Wemm 
28516c2ba93SPeter Wemm 	if (today - act > 90L * 24L * 60L * 60L)
28616c2ba93SPeter Wemm 		usr->spc90 += blks;
28716c2ba93SPeter Wemm 	if (today - act > 60L * 24L * 60L * 60L)
28816c2ba93SPeter Wemm 		usr->spc60 += blks;
28916c2ba93SPeter Wemm 	if (today - act > 30L * 24L * 60L * 60L)
29016c2ba93SPeter Wemm 		usr->spc30 += blks;
29116c2ba93SPeter Wemm }
29216c2ba93SPeter Wemm 
29316c2ba93SPeter Wemm #ifdef	COMPAT
29416c2ba93SPeter Wemm #define	FSZCNT	500
29516c2ba93SPeter Wemm #else
29616c2ba93SPeter Wemm #define	FSZCNT	512
29716c2ba93SPeter Wemm #endif
29816c2ba93SPeter Wemm struct fsizes {
29916c2ba93SPeter Wemm 	struct fsizes *fsz_next;
30016c2ba93SPeter Wemm 	daddr_t fsz_first, fsz_last;
30116c2ba93SPeter Wemm 	ino_t fsz_count[FSZCNT];
30216c2ba93SPeter Wemm 	daddr_t fsz_sz[FSZCNT];
30316c2ba93SPeter Wemm } *fsizes;
30416c2ba93SPeter Wemm 
3056980f0ebSPhilippe Charnier static void
3066980f0ebSPhilippe Charnier initfsizes()
30716c2ba93SPeter Wemm {
30816c2ba93SPeter Wemm 	register struct fsizes *fp;
30916c2ba93SPeter Wemm 	register i;
31016c2ba93SPeter Wemm 
31116c2ba93SPeter Wemm 	for (fp = fsizes; fp; fp = fp->fsz_next) {
31216c2ba93SPeter Wemm 		for (i = FSZCNT; --i >= 0;) {
31316c2ba93SPeter Wemm 			fp->fsz_count[i] = 0;
31416c2ba93SPeter Wemm 			fp->fsz_sz[i] = 0;
31516c2ba93SPeter Wemm 		}
31616c2ba93SPeter Wemm 	}
31716c2ba93SPeter Wemm }
31816c2ba93SPeter Wemm 
3196980f0ebSPhilippe Charnier static void
3206980f0ebSPhilippe Charnier dofsizes(fd,super,name)
32116c2ba93SPeter Wemm 	struct fs *super;
32216c2ba93SPeter Wemm 	char *name;
32316c2ba93SPeter Wemm {
32416c2ba93SPeter Wemm 	ino_t inode, maxino;
32516c2ba93SPeter Wemm 	struct dinode *ip;
32616c2ba93SPeter Wemm 	daddr_t sz, ksz;
32716c2ba93SPeter Wemm 	struct fsizes *fp, **fsp;
32816c2ba93SPeter Wemm 	register i;
32916c2ba93SPeter Wemm 
33016c2ba93SPeter Wemm 	maxino = super->fs_ncg * super->fs_ipg - 1;
33116c2ba93SPeter Wemm #ifdef	COMPAT
3326980f0ebSPhilippe Charnier 	if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes))))
3336980f0ebSPhilippe Charnier 		errx(1, "alloc fsize structure");
33416c2ba93SPeter Wemm #endif	/* COMPAT */
33516c2ba93SPeter Wemm 	for (inode = 0; inode < maxino; inode++) {
33616c2ba93SPeter Wemm 		errno = 0;
33716c2ba93SPeter Wemm 		if ((ip = get_inode(fd,super,inode))
33816c2ba93SPeter Wemm #ifdef	COMPAT
33916c2ba93SPeter Wemm 		    && ((ip->di_mode&IFMT) == IFREG
34016c2ba93SPeter Wemm 			|| (ip->di_mode&IFMT) == IFDIR)
34116c2ba93SPeter Wemm #else	/* COMPAT */
34216c2ba93SPeter Wemm 		    && !isfree(ip)
34316c2ba93SPeter Wemm #endif	/* COMPAT */
34416c2ba93SPeter Wemm 		    ) {
34516c2ba93SPeter Wemm 			sz = estimate ? virtualblocks(super,ip) :
34616c2ba93SPeter Wemm 			    actualblocks(super,ip);
34716c2ba93SPeter Wemm #ifdef	COMPAT
34816c2ba93SPeter Wemm 			if (sz >= FSZCNT) {
34916c2ba93SPeter Wemm 				fsizes->fsz_count[FSZCNT-1]++;
35016c2ba93SPeter Wemm 				fsizes->fsz_sz[FSZCNT-1] += sz;
35116c2ba93SPeter Wemm 			} else {
35216c2ba93SPeter Wemm 				fsizes->fsz_count[sz]++;
35316c2ba93SPeter Wemm 				fsizes->fsz_sz[sz] += sz;
35416c2ba93SPeter Wemm 			}
35516c2ba93SPeter Wemm #else	/* COMPAT */
35616c2ba93SPeter Wemm 			ksz = SIZE(sz);
3576980f0ebSPhilippe Charnier 			for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) {
35816c2ba93SPeter Wemm 				if (ksz < fp->fsz_last)
35916c2ba93SPeter Wemm 					break;
36016c2ba93SPeter Wemm 			}
36116c2ba93SPeter Wemm 			if (!fp || ksz < fp->fsz_first) {
36216c2ba93SPeter Wemm 				if (!(fp = (struct fsizes *)
3636980f0ebSPhilippe Charnier 				    malloc(sizeof(struct fsizes))))
3646980f0ebSPhilippe Charnier 					errx(1, "alloc fsize structure");
36516c2ba93SPeter Wemm 				fp->fsz_next = *fsp;
36616c2ba93SPeter Wemm 				*fsp = fp;
36716c2ba93SPeter Wemm 				fp->fsz_first = (ksz / FSZCNT) * FSZCNT;
36816c2ba93SPeter Wemm 				fp->fsz_last = fp->fsz_first + FSZCNT;
36916c2ba93SPeter Wemm 				for (i = FSZCNT; --i >= 0;) {
37016c2ba93SPeter Wemm 					fp->fsz_count[i] = 0;
37116c2ba93SPeter Wemm 					fp->fsz_sz[i] = 0;
37216c2ba93SPeter Wemm 				}
37316c2ba93SPeter Wemm 			}
37416c2ba93SPeter Wemm 			fp->fsz_count[ksz % FSZCNT]++;
37516c2ba93SPeter Wemm 			fp->fsz_sz[ksz % FSZCNT] += sz;
37616c2ba93SPeter Wemm #endif	/* COMPAT */
37716c2ba93SPeter Wemm 		} else if (errno) {
3786980f0ebSPhilippe Charnier 			err(1, "%s", name);
37916c2ba93SPeter Wemm 		}
38016c2ba93SPeter Wemm 	}
38116c2ba93SPeter Wemm 	sz = 0;
38216c2ba93SPeter Wemm 	for (fp = fsizes; fp; fp = fp->fsz_next) {
38316c2ba93SPeter Wemm 		for (i = 0; i < FSZCNT; i++) {
38416c2ba93SPeter Wemm 			if (fp->fsz_count[i])
38516c2ba93SPeter Wemm 				printf("%d\t%d\t%d\n",fp->fsz_first + i,
38616c2ba93SPeter Wemm 				    fp->fsz_count[i],
38716c2ba93SPeter Wemm 				    SIZE(sz += fp->fsz_sz[i]));
38816c2ba93SPeter Wemm 		}
38916c2ba93SPeter Wemm 	}
39016c2ba93SPeter Wemm }
39116c2ba93SPeter Wemm 
3926980f0ebSPhilippe Charnier static void
3936980f0ebSPhilippe Charnier douser(fd,super,name)
39416c2ba93SPeter Wemm 	struct fs *super;
39516c2ba93SPeter Wemm 	char *name;
39616c2ba93SPeter Wemm {
39716c2ba93SPeter Wemm 	ino_t inode, maxino;
39816c2ba93SPeter Wemm 	struct user *usr, *usrs;
39916c2ba93SPeter Wemm 	struct dinode *ip;
40016c2ba93SPeter Wemm 	register n;
40116c2ba93SPeter Wemm 
40216c2ba93SPeter Wemm 	maxino = super->fs_ncg * super->fs_ipg - 1;
40316c2ba93SPeter Wemm 	for (inode = 0; inode < maxino; inode++) {
40416c2ba93SPeter Wemm 		errno = 0;
40516c2ba93SPeter Wemm 		if ((ip = get_inode(fd,super,inode))
40616c2ba93SPeter Wemm 		    && !isfree(ip))
40716c2ba93SPeter Wemm 			uses(ip->di_uid,
40816c2ba93SPeter Wemm 			    estimate ? virtualblocks(super,ip) :
40916c2ba93SPeter Wemm 				actualblocks(super,ip),
41016c2ba93SPeter Wemm 			    ip->di_atime);
41116c2ba93SPeter Wemm 		else if (errno) {
4126980f0ebSPhilippe Charnier 			err(1, "%s", name);
41316c2ba93SPeter Wemm 		}
41416c2ba93SPeter Wemm 	}
4156980f0ebSPhilippe Charnier 	if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
4166980f0ebSPhilippe Charnier 		errx(1, "allocate users");
41716c2ba93SPeter Wemm 	bcopy(users,usrs,nusers * sizeof(struct user));
41816c2ba93SPeter Wemm 	sortusers(usrs);
41916c2ba93SPeter Wemm 	for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
42016c2ba93SPeter Wemm 		printf("%5d",SIZE(usr->space));
42116c2ba93SPeter Wemm 		if (count)
42216c2ba93SPeter Wemm 			printf("\t%5d",usr->count);
42316c2ba93SPeter Wemm 		printf("\t%-8s",usr->name);
42416c2ba93SPeter Wemm 		if (unused)
42516c2ba93SPeter Wemm 			printf("\t%5d\t%5d\t%5d",
42616c2ba93SPeter Wemm 			       SIZE(usr->spc30),
42716c2ba93SPeter Wemm 			       SIZE(usr->spc60),
42816c2ba93SPeter Wemm 			       SIZE(usr->spc90));
42916c2ba93SPeter Wemm 		printf("\n");
43016c2ba93SPeter Wemm 	}
43116c2ba93SPeter Wemm 	free(usrs);
43216c2ba93SPeter Wemm }
43316c2ba93SPeter Wemm 
4346980f0ebSPhilippe Charnier static void
4356980f0ebSPhilippe Charnier donames(fd,super,name)
43616c2ba93SPeter Wemm 	struct fs *super;
43716c2ba93SPeter Wemm 	char *name;
43816c2ba93SPeter Wemm {
43916c2ba93SPeter Wemm 	int c;
44016c2ba93SPeter Wemm 	ino_t inode, inode1;
44116c2ba93SPeter Wemm 	ino_t maxino;
44216c2ba93SPeter Wemm 	struct dinode *ip;
44316c2ba93SPeter Wemm 
44416c2ba93SPeter Wemm 	maxino = super->fs_ncg * super->fs_ipg - 1;
44516c2ba93SPeter Wemm 	/* first skip the name of the filesystem */
44616c2ba93SPeter Wemm 	while ((c = getchar()) != EOF && (c < '0' || c > '9'))
44716c2ba93SPeter Wemm 		while ((c = getchar()) != EOF && c != '\n');
44816c2ba93SPeter Wemm 	ungetc(c,stdin);
44916c2ba93SPeter Wemm 	inode1 = -1;
45016c2ba93SPeter Wemm 	while (scanf("%d",&inode) == 1) {
45116c2ba93SPeter Wemm 		if (inode < 0 || inode > maxino) {
4526980f0ebSPhilippe Charnier 			warnx("illegal inode %d",inode);
45316c2ba93SPeter Wemm 			return;
45416c2ba93SPeter Wemm 		}
45516c2ba93SPeter Wemm 		errno = 0;
45616c2ba93SPeter Wemm 		if ((ip = get_inode(fd,super,inode))
45716c2ba93SPeter Wemm 		    && !isfree(ip)) {
45816c2ba93SPeter Wemm 			printf("%s\t",user(ip->di_uid)->name);
45916c2ba93SPeter Wemm 			/* now skip whitespace */
46016c2ba93SPeter Wemm 			while ((c = getchar()) == ' ' || c == '\t');
46116c2ba93SPeter Wemm 			/* and print out the remainder of the input line */
46216c2ba93SPeter Wemm 			while (c != EOF && c != '\n') {
46316c2ba93SPeter Wemm 				putchar(c);
46416c2ba93SPeter Wemm 				c = getchar();
46516c2ba93SPeter Wemm 			}
46616c2ba93SPeter Wemm 			putchar('\n');
46716c2ba93SPeter Wemm 			inode1 = inode;
46816c2ba93SPeter Wemm 		} else {
46916c2ba93SPeter Wemm 			if (errno) {
4706980f0ebSPhilippe Charnier 				err(1, "%s", name);
47116c2ba93SPeter Wemm 			}
47216c2ba93SPeter Wemm 			/* skip this line */
47316c2ba93SPeter Wemm 			while ((c = getchar()) != EOF && c != '\n');
47416c2ba93SPeter Wemm 		}
47516c2ba93SPeter Wemm 		if (c == EOF)
47616c2ba93SPeter Wemm 			break;
47716c2ba93SPeter Wemm 	}
47816c2ba93SPeter Wemm }
47916c2ba93SPeter Wemm 
4806980f0ebSPhilippe Charnier static void
4816980f0ebSPhilippe Charnier usage()
48216c2ba93SPeter Wemm {
48316c2ba93SPeter Wemm #ifdef	COMPAT
4846980f0ebSPhilippe Charnier 	fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n");
48516c2ba93SPeter Wemm #else	/* COMPAT */
4866980f0ebSPhilippe Charnier 	fprintf(stderr,"usage: quot [-acfhknv] [ filesystem ... ]\n");
48716c2ba93SPeter Wemm #endif	/* COMPAT */
48816c2ba93SPeter Wemm 	exit(1);
48916c2ba93SPeter Wemm }
49016c2ba93SPeter Wemm 
49116c2ba93SPeter Wemm static char superblock[SBSIZE];
49216c2ba93SPeter Wemm 
4936980f0ebSPhilippe Charnier void
49416c2ba93SPeter Wemm quot(name,mp)
49516c2ba93SPeter Wemm 	char *name, *mp;
49616c2ba93SPeter Wemm {
49716c2ba93SPeter Wemm 	int fd;
49816c2ba93SPeter Wemm 
49916c2ba93SPeter Wemm 	get_inode(-1);		/* flush cache */
50016c2ba93SPeter Wemm 	inituser();
50116c2ba93SPeter Wemm 	initfsizes();
50216c2ba93SPeter Wemm 	if ((fd = open(name,0)) < 0
50316c2ba93SPeter Wemm 	    || lseek(fd,SBOFF,0) != SBOFF
50416c2ba93SPeter Wemm 	    || read(fd,superblock,SBSIZE) != SBSIZE) {
5056980f0ebSPhilippe Charnier 		warn("%s", name);
50616c2ba93SPeter Wemm 		close(fd);
50716c2ba93SPeter Wemm 		return;
50816c2ba93SPeter Wemm 	}
50916c2ba93SPeter Wemm 	if (((struct fs *)superblock)->fs_magic != FS_MAGIC) {
5106980f0ebSPhilippe Charnier 		warnx("%s: not a BSD filesystem",name);
51116c2ba93SPeter Wemm 		close(fd);
51216c2ba93SPeter Wemm 		return;
51316c2ba93SPeter Wemm 	}
51416c2ba93SPeter Wemm 	printf("%s:",name);
51516c2ba93SPeter Wemm 	if (mp)
51616c2ba93SPeter Wemm 		printf(" (%s)",mp);
51716c2ba93SPeter Wemm 	putchar('\n');
51816c2ba93SPeter Wemm 	(*func)(fd,superblock,name);
51916c2ba93SPeter Wemm 	close(fd);
52016c2ba93SPeter Wemm }
52116c2ba93SPeter Wemm 
5226980f0ebSPhilippe Charnier int
5236980f0ebSPhilippe Charnier main(argc,argv)
52416c2ba93SPeter Wemm 	char **argv;
52516c2ba93SPeter Wemm {
52616c2ba93SPeter Wemm 	char all = 0;
52716c2ba93SPeter Wemm 	struct statfs *mp;
52816c2ba93SPeter Wemm 	char dev[MNAMELEN + 1];
52916c2ba93SPeter Wemm 	char *nm;
53016c2ba93SPeter Wemm 	int cnt;
53116c2ba93SPeter Wemm 
53216c2ba93SPeter Wemm 	func = douser;
53316c2ba93SPeter Wemm #ifndef	COMPAT
53416c2ba93SPeter Wemm 	header = getbsize(&headerlen,&blocksize);
53516c2ba93SPeter Wemm #endif
53616c2ba93SPeter Wemm 	while (--argc > 0 && **++argv == '-') {
53716c2ba93SPeter Wemm 		while (*++*argv) {
53816c2ba93SPeter Wemm 			switch (**argv) {
53916c2ba93SPeter Wemm 			case 'n':
54016c2ba93SPeter Wemm 				func = donames;
54116c2ba93SPeter Wemm 				break;
54216c2ba93SPeter Wemm 			case 'c':
54316c2ba93SPeter Wemm 				func = dofsizes;
54416c2ba93SPeter Wemm 				break;
54516c2ba93SPeter Wemm 			case 'a':
54616c2ba93SPeter Wemm 				all = 1;
54716c2ba93SPeter Wemm 				break;
54816c2ba93SPeter Wemm 			case 'f':
54916c2ba93SPeter Wemm 				count = 1;
55016c2ba93SPeter Wemm 				break;
55116c2ba93SPeter Wemm 			case 'h':
55216c2ba93SPeter Wemm 				estimate = 1;
55316c2ba93SPeter Wemm 				break;
55416c2ba93SPeter Wemm #ifndef	COMPAT
55516c2ba93SPeter Wemm 			case 'k':
55616c2ba93SPeter Wemm 				blocksize = 1024;
55716c2ba93SPeter Wemm 				break;
55816c2ba93SPeter Wemm #endif	/* COMPAT */
55916c2ba93SPeter Wemm 			case 'v':
56016c2ba93SPeter Wemm 				unused = 1;
56116c2ba93SPeter Wemm 				break;
56216c2ba93SPeter Wemm 			default:
56316c2ba93SPeter Wemm 				usage();
56416c2ba93SPeter Wemm 			}
56516c2ba93SPeter Wemm 		}
56616c2ba93SPeter Wemm 	}
56716c2ba93SPeter Wemm 	if (all) {
56816c2ba93SPeter Wemm 		cnt = getmntinfo(&mp,MNT_NOWAIT);
56916c2ba93SPeter Wemm 		for (; --cnt >= 0; mp++) {
570b49d184bSBruce Evans 			if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) {
5716980f0ebSPhilippe Charnier 				if ((nm = strrchr(mp->f_mntfromname,'/'))) {
57216c2ba93SPeter Wemm 					sprintf(dev,"/dev/r%s",nm + 1);
57316c2ba93SPeter Wemm 					nm = dev;
57416c2ba93SPeter Wemm 				} else
57516c2ba93SPeter Wemm 					nm = mp->f_mntfromname;
57616c2ba93SPeter Wemm 				quot(nm,mp->f_mntonname);
57716c2ba93SPeter Wemm 			}
57816c2ba93SPeter Wemm 		}
57916c2ba93SPeter Wemm 	}
58016c2ba93SPeter Wemm 	while (--argc >= 0)
58116c2ba93SPeter Wemm 		quot(*argv++,0);
58216c2ba93SPeter Wemm 	return 0;
58316c2ba93SPeter Wemm }
584