AUSAM/source/S/dlscan.c

Compare this file to the similar file:
Show the results in this format:

#
/*
**	dlscan - scan all mounted file-systems for disk usage by users & groups
**
**		update passwd file entries appropriately,
**		note any discrepancies on file "dlnotef"
*/


#include	<local-system>		/* global parameters */
#include	<sys/param.h>		/* system parameters */
#include	<sys/ino.h>		/* disk inode structure */
#include	<sys/inode.h>		/* inode mode definitions */
#include	<sys/filsys.h>		/* super-block structure */
#include	<mtab.h>		/* mounted file table structure */
#include	<passwd.h>		/* "passwd" entry structure */
#include	<stdio.h>		/* standard i/o streams */


#define	TEST		1		/* for testing ! */

#define	NBLOCKS		30		/* read NBLOCKS of inodes at a time */
#define	F_READ		0		/* file read parameter for open sys call */

char	dlnotef[]	= "/usr/adm/dlnotes";
char	gusagef[]	= "/usr/adm/gusages";
char	rawname[]	= "/dev/r";




main( argc, argv )
	int		argc;
	char		*argv[];
{
	extern char	*getfs();
	register char	*fs;

#	ifndef	TEST
	close( 0 );
	close( 1 );
#	endif

	while ( (fs = getfs()) != NULL )
		chkfs( fs );

	updtpasswd();

#	ifndef	TEST
	updtgroups();
#	endif

	return 0;
}




dusage_t	dusages[NUSERS+1];		/* real usage per user */
#ifndef	TEST
long		gdusages[NGROUPS+1];		/* real usage per group */
#endif
struct mtab	mtabent;			/* entry from "mtabf" */
#define	NINODES	(INOPB*NBLOCKS)
struct dinode	inbuf[NINODES];			/* read NBLOCKS of inodes at a time */




/*
**	getfs - returns pointer to next file system name
*/

char *
getfs()
{
	static	 	init, fd;
	register	n;
	static char	s[(sizeof mtabent.m_spec)+(sizeof rawname)];

	if ( !init )
	{
		init++;

		if ( (fd = open( mtabf, F_READ )) == SYSERROR )
		{
			perror( mtabf );
			exit( 1 );
		}
	}

	if ( (n = read( fd, &mtabent, sizeof mtabent )) != sizeof mtabent )
	{
		close( fd );
		return NULL;
	}

	return strcatn( strcpy( s, rawname ), mtabent.m_spec, sizeof mtabent.m_spec );
}




/*
**	chkfs - check file-system "fs" for usage per uid & group
*/

chkfs( fs )
	char		*fs;
{
	int		fd;
	register	ninodes, n;
	struct filsys	super;

#	ifdef	TEST
	printf( "%s\n", fs );
#	endif

	if ( (fd = open( fs, F_READ )) == SYSERROR )
	{
		perror( fs );
		return;
	}

	lseek( fd, SUPERB*BSIZE, 0 );

	if ( read( fd, &super, sizeof super ) != sizeof super )
	{
		perror( fs );
		close( fd );
		return;
	}

	lseek( fd, (SUPERB+1)*BSIZE, 0 );

	for ( ninodes = super.s_isize * INOPB ; ninodes > 0 ; ninodes -= NINODES )
	{
		register		i = sizeof inbuf;

		if ( ninodes < NINODES )
			i = ninodes * (sizeof (struct dinode));

#		ifdef	TEST
		printf( "read %d\n", i );
#		endif

		if ( read( fd, &inbuf, i ) != i )
		{
			perror( fs );
			close( fd );
			return;
		}

		i /= sizeof (struct dinode);

		while ( i-- )
			switch ( inbuf[i].di_mode & IFMT )
			{
				register dusage_t	d = IWEIGHT;
				register		u;
				extern dusage_t		fsize();

			 case 0:	/** Unallocated **/
					break;

			 case IFDIR:
			 case IFREG:
			 case IFLOK:
			 case IFALK:
					d += fsize( &inbuf[i] );
			 default:
					dusages[(u = inbuf[i].di_uid) >= NUSERS ? NUSERS : u] += d;
#					ifndef	TEST
					gdusages[(u = inbuf[i].di_gid) >= NGROUPS ? NGROUPS : u] += d;
#					endif
			}
	}

	close( fd );
}




/*
**	fsize - return block usage of file described by ip
*/

dusage_t
fsize( ip )
	struct dinode		*ip;
{
	register unsigned	b, ib, ib2;

	b = (ip->di_size + BMASK) >> BSHIFT;

	if ( b > 10 )
		if ( (ib = (b-10+NMASK)>>NSHIFT) > 1 )
			if ( (ib2 = (ib+NMASK)>>NSHIFT) > 1 )
				return (dusage_t)(1+ib2+ib+b);
			else
				return (dusage_t)(1+ib+b);
		else
			return (dusage_t)(1+b);
	else
		return (dusage_t)b;
}




/*
**	updtpasswd - updates passwd file entries with disk usage
**		and checks consistency
*/

updtpasswd()
{
	register	i;
	char		buf[SSIZ];
	register FILE	*nfd;
	extern FILE	*fopen();

	if ( (nfd = fopen( dlnotef, 'a' )) == NULL )
		perror( dlnotef );

	for ( i = 0 ; i < NUSERS ; i++ )
	{
		register dusage_t	u, d;

		if ( u = dusages[i] )
		{
			struct pwent	pwe;

			pwe.pw_limits.l_uid = i;

			if ( getpwlog( &pwe, buf, SSIZ ) == PWERROR )
			{
				if ( nfd != NULL )
					fprintf( nfd, "uid %u has %u disk units and DOES NOT EXIST\n", i, u );
			}
			else
			{
				if ( pwe.pw_limits.l_duse != u )
				{
					register	f;
					struct lnode	user;

					user.l_uid = i;

					if ( ((f = limits( &user, L_OTHLIM )) == SYSERROR )
						|| ((pwe.pw_limits.l_duse = user.l_duse) != u )
					   )
					{
						if ( nfd != NULL )
							fprintf( nfd, "uid %u passwd usage %u != real usage %u%s\n",
								i
								,pwe.pw_limits.l_duse
								,u
								,f == SYSERROR ? "" : " (logged on)"
								);
						pwe.pw_limits.l_duse = u;
					}
				}

				if ( u > (d = pwe.pw_limits.l_dlimit + pwe.pw_limits.l_doverflw) )
				{
					chmod( pwe.pw_strings[DIRPATH], 0 );
					pwe.pw_limits.l_flags |= NOLOGIN;
					if ( nfd != NULL )
						fprintf( nfd, "uid %u exceeds disk limit of %u units by %u -- NOLOGIN\n",
							i, d, u-d );
				}

				updtpwent( &pwe );
			}
		}
	}

	if ( nfd != NULL )
	{
		if ( dusages[NUSERS] )
			fprintf( nfd, "ILLEGAL uids possess %u units!\n", dusages[NUSERS] );

		fclose( nfd );
	}

	pwclose();
}
#ifndef	TEST




/*
**	updtgroups - updates group disk usage file
*/

updtgroups()
{
	register	i;
	register FILE	*gufd;
	extern FILE	*fopen();

	if ( (gufd = fopen( gusagef, 'w' )) == NULL )
	{
		perror( gusagef );
		return;
	}

	for ( i = 0 ; i <= NGROUPS ; i++ )
	{
		if ( gdusages[i] )
		{
			fprintf( gufd, "gid %u: disk usage = %U units\n", i, gdusages[i] );
		}
	}

	fclose( gufd );
}
#else	TEST




/*
**	SAFE TEST
*/




updtpwent( pe )
	struct pwent	*pe;
{
	printf( "updtpwent on uid %d\n", pe.pw_limits.l_uid );
}




chmod( s, m )
	char	*s;
	int	m;
{
	printf( "chmod on %s to %o\n", s, m );
}
#endif	TEST