quot(1)

John F. Haugh II jfh at rpp386.Dallas.TX.US
Fri Nov 4 01:42:29 AEST 1988


This has been posted to pubnet.sources before.  pubnet does not receive
a wide distribution, so I am reposting it here.  This is liable to need
much twiddling, so please hack first and write me second.  Better still,
hack several times before writing ;-)

- John.
--
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/filsys.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>

#undef	MAXUID
#define	MAXUID	400
#ifndef	DEF_FS
#define	DEF_FS	"/dev/root"
#endif
#define	DIR_BLKS	10
#define	FILSYS	(sizeof (struct filsys))

static	char	sccsid[] = "@(#)quot.c	1.0";

struct	passwd	*getpwuid ();
struct	group	*getgrgid ();

struct	ublks	{
	int	u_uid;			/* uid of person/group */
	long	int	u_blks;		/* total blocks used */
}	ublks[MAXUID];

int	tflg,				/* print totals only */
	gflg;				/* print groups, not users */

struct	dinode	*iget (fd, ino)
register int	fd,
		ino;
{
	static	long	int	lastblk = -1;
	static	struct	dinode	iblk[4*INOPB];

	if ((lastblk >> 2) != (itod (ino) >> 2)) {
		lastblk = itod (ino);
		lastblk &= ~03;
		if (lseek (fd, lastblk << BSHIFT, 0) < 0)
			return (0);

		if (read (fd, iblk, BSIZE*4) != BSIZE*4)
			return (0);
	}
	return (&iblk[((itod (ino) & 03) * INOPB) + itoo (ino)]);
}

int	fsopen (fs, superb)
char	*fs;
register struct	filsys	*superb;
{
register int	file;

	if (((file = open (fs, O_RDONLY)) < 0) ||
	     (lseek (file, (long) (SUPERB << BSHIFT), 0) < 0) ||
	     (read (file, superb, BSIZE) != BSIZE))
		return (-1);
	else
		return (file);
}

int	blkcmp (a, b)
struct	ublks	*a, *b;
{
	return (b->u_blks - a->u_blks);
}

usage ()
{
	write (2, "usage: quot [ -tug ] [ filesystem ]\n", 36);
	exit (1);
}

printtotals (device)
char	*device;
{
	int	user;
	struct	passwd	*pwent;
	struct	group	*grent;

	printf ("%s:\n", device);
	qsort (ublks, MAXUID, sizeof (struct ublks), blkcmp);
	for (user = 0;user < MAXUID;user++)
		if (ublks[user].u_blks) {
			if (! gflg)
				if (pwent = getpwuid (ublks[user].u_uid))
					printf ("%8.8s %d\n", pwent->pw_name, ublks[user].u_blks * 2);
				else
					printf ("%8.8d %d\n", ublks[user].u_uid, ublks[user].u_blks * 2);
			else
				if (grent = getgrgid (ublks[user].u_uid))
					printf ("%8.8s %d\n", grent->gr_name, ublks[user].u_blks * 2);
				else
					printf ("%8.8d %d\n", ublks[user].u_uid, ublks[user].u_blks * 2);
		}
}

blocks (fsize)
long	int	fsize;
{
	long	int	extra = fsize;		/* indirect blocks */

	if (fsize <= NINDIR)			/* single indirect */
		return (fsize + 1);

	fsize -= NINDIR;
	extra++;

	if (fsize <= NINDIR*NINDIR)
		return (extra + ((fsize + NINDIR - 1) / NINDIR + 1));

	extra += NINDIR + 1;
	fsize -= NINDIR*NINDIR;

	extra += (fsize + NINDIR - 1) / NINDIR;	/* indirect blocks to point to direct blocks */
	fsize = (fsize + NINDIR - 1) / NINDIR;	/* fsize is now just the indirect block count */

	extra += (fsize + NINDIR - 1) / NINDIR;	/* double indirects to point to single indirects */
	fsize = (fsize + NINDIR - 1) / NINDIR;	/* fsize is now just the double indirect count */

	extra += (fsize + NINDIR - 1) / NINDIR;	/* triple indirect(s) to point to double indirects */
	fsize = (fsize + NINDIR - 1) / NINDIR;	/* had better just be 1 ... */

	return (extra);
}

main (argc, argv)
int	argc;
char	**argv;
{
	struct	dinode	*dino;
	char	buf[BSIZE];
	struct	filsys	*superb = (struct filsys *) buf;
	register int	fd,
			ino,
			user;
	long	fsize;
long foobar;
	int	arg,
		c,
		maxino;
	char	*uid;
	struct	passwd	*pwent;

	for (user = 0;user < MAXUID;user++) {
		ublks[user].u_blks = 0;
		ublks[user].u_uid = user;
	}
	for (arg = 1;arg < argc;arg++) {
		if (argv[arg][0] != '-')
			break;
		for (c = 1;argv[arg][c];c++)
			switch (argv[arg][c]) {
				case 't':
					tflg++;
					break;
				case 'g':
					gflg++;
					break;
				case 'u':
					gflg = 0;
					break;
				default:
					usage ();
			}
	}
	if (argc == arg) {
		argv[arg] = DEF_FS;
		argc = arg + 1;
	}
	for (;arg < argc;arg++) {
		if ((fd = fsopen (argv[arg], superb)) < 0) {
			perror (argv[arg]);
			continue;
		}
		if (! tflg)
			for (user = 0;user < MAXUID;user++) {
				ublks[user].u_blks = 0;
				ublks[user].u_uid = user;
			}
		maxino = (superb->s_isize) * INOPB;

		for (ino = 2;ino < maxino;ino++) {
			if (! (dino = iget (fd, ino)))
				continue;

			if (! dino->di_mode || ! dino->di_nlink)
				continue;

			if ((dino->di_mode & IFMT) != IFDIR &&
					(dino->di_mode & IFMT) != IFREG)
				continue;

			if (dino->di_size == 0)
				continue;

			if (gflg)
				dino->di_uid = dino->di_gid;

			if (dino->di_uid < 0 || dino->di_uid >= MAXUID)
				continue;

			fsize = (dino->di_size + BSIZE - 1) >> (BSHIFT);
			if (fsize <= DIR_BLKS) {
				ublks[dino->di_uid].u_blks += fsize;
			} else {
				ublks[dino->di_uid].u_blks += blocks (fsize - DIR_BLKS) + DIR_BLKS;
			}
		}
		close (fd);
		if (! tflg)
			printtotals (argv[arg]);
	}
	if (tflg)
		printtotals ("totals");
}
-- 
John F. Haugh II                        +----Make believe quote of the week----
VoiceNet: (214) 250-3311   Data: -6272  | Nancy Reagan on Richard Stallman:
InterNet: jfh at rpp386.Dallas.TX.US       |          "Just say `Gno'"
UucpNet : <backbone>!killer!rpp386!jfh  +--------------------------------------



More information about the Alt.sources mailing list