AUSAM/source/S/dlscan.c
#
/*
** 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