fmc@cnam.cnam.fr (Frederic Chauveau) (02/20/91)
Submitted-by: Frederic Chauveau <fmc@cnam.cnam.fr> Posting-number: Volume 17, Issue 7 Archive-name: space/part01 space is a tool which create and update data-bases to watch how much and by whom disk space is used. It maintains a record of the used space on a per day / per users / per file-system basis. Frederic Chauveau <fmc@cnam.cnam.fr> ---- Cut Here and unpack ---- #!/bin/sh # This is space, a shell archive (shar 3.32) # made 02/13/1991 11:50 UTC by fmc@cnam.cnam.fr # Source directory /users/labinf/fmc/tools/Space # # existing files will NOT be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 9367 -rw-r--r-- space.c # 4960 -rw-r--r-- sysdep.c # 1649 -rw-r--r-- defs.h # 3102 -rw-r--r-- Makefile # 1534 -r--r--r-- space.8 # 4037 -rw-r--r-- INSTALL # if touch 2>&1 | fgrep 'amc' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= space.c ============== if test X"$1" != X"-c" -a -f 'space.c'; then echo "File already exists: skipping 'space.c'" else echo "x - extracting space.c (Text)" sed 's/^X//' << 'SHAR_EOF' > space.c && X/* X * space A tool to look out for greedy users X * $Header: /users/labinf/fmc/tools/Space/RCS/space.c,v 2.4 91/01/24 15:14:18 fmc Exp $ X * $Source: /users/labinf/fmc/tools/Space/RCS/space.c,v $ X * $Locker: $ X * $State: Exp $ X * $Log: space.c,v $ X * Revision 2.4 91/01/24 15:14:18 fmc X * Split System dependencies. X * Fixed a bug in -tx options. X * X * Revision 2.3 90/10/13 15:20:38 fmc X * Fixed a bug with the -D option (sort by Delta-percentage) X * Added a Startday compilation option. X * Some mode (final?) cleanup. X * X * Revision 2.2 90/09/01 11:06:13 fmc X * added -d and -D option to sort user by delta or percentage X * Some more (final) clean-up. X * X * Revision 2.1 90/08/30 19:00:36 fmc X * Do not log users occupying no space. Added -t option X * to look through all file Systems. X * X * Revision 2.0 90/08/28 18:57:26 fmc X * Split the sums by file-systems. Some Clean Up X * X * Revision 1.3 90/08/27 18:48:16 fmc X * Various Bug Fix X * X * Revision 1.2 90/08/10 16:35:22 fmc X * Added -Ln option to have a sorted list with the last n days disk occupation. X * X * Revision 1.1 90/08/02 13:47:16 fmc X * Initial revision X * X * X */ X X#include "defs.h" X Xstatic char SortFlag = 0; Xstatic char DataFile[128]; Xstatic RecP *Sorted; Xstatic short StartDay = STARTDAY; X Xint SortAllRecs(r1, r2) XSuprecP *r1, *r2; { X long v1, v2; X X switch (SortFlag) X { X case TMAX: v1 = (*r1)->Fmax; v2 = (*r2)->Fmax; break; X case TMIN: v1 = (*r1)->Fmin; v2 = (*r2)->Fmin; break; X case CUR: v1 = (*r1)->Fcur; v2 = (*r2)->Fcur; break; X } X if (v1 == v2) X return 0; X return (v2 > v1) ? 1 : -1; X} X Xint SortUsers(r1, r2) XRecP *r1, *r2; { X long v1, v2; X v1 = (*r1)->blocks[CurrentDay]; X v2 = (*r2)->blocks[CurrentDay]; X X if (v1 == v2) X return 0; X return (v2 > v1) ? 1 : -1; X} X Xvoid GetRecords(fn) Xchar *fn; { X unsigned int fd, i, j; X Record tmp; X X sprintf(DataFile,"%s/space-%s.dat",DATADIR,fn); X fd = open(DataFile,0); X if (fd < 0) { X perror(DataFile); X if (log_file && (log_file != stderr)) X fclose(log_file); X exit(1); X } X X for (i = 0; i != MAXUSERS; i++) X if (WhatDidTheyDo[i]) { X free(WhatDidTheyDo[i]); X WhatDidTheyDo[i] = NULL; X } X while (read(fd, &tmp, sizeof(Record)) == sizeof(Record)) { X register unsigned long max = 0L, min = 500000L; X if (WhatDidTheyDo[tmp.uid]) X fprintf(log_file,"Duplicate Record Entry for Uid %d\n",tmp.uid); X for (i = 0; i <= CurrentDay; i++) { X if (tmp.blocks[i] && (tmp.blocks[i] < min)) X min = tmp.blocks[i]; X if (tmp.blocks[i] > max) { X max = tmp.blocks[i]; X } X } X tmp.dmax = max; X tmp.dmin = min; X WhatDidTheyDo[tmp.uid] = (RecP) malloc(sizeof(Record)); X *(WhatDidTheyDo[tmp.uid]) = tmp; X MaxUsers++; X } X close(fd); X} X Xvoid SaveRecords(fn) Xchar *fn; { X unsigned int fd, i; X X sprintf(DataFile,"%s/space-%s.dat",DATADIR,fn); X close(creat(DataFile,0777)); X fd = open(DataFile,1); X if (fd < 0) { X perror(DataFile); X if (log_file && (log_file != stderr)) X fclose(log_file); X exit(1); X } X X for (i = 0; i != MAXUSERS; i++) X if (WhatDidTheyDo[i] && WhatDidTheyDo[i]->dmax) X write(fd, WhatDidTheyDo[i], sizeof(Record)); X close(fd); X} X Xvoid DispAllFs() { X register int i, j; X X printf(" User "); X for (i = 0; i!= MaxFs; i++) X printf("%7s",all_fs[i].dev); X puts(" Total"); X for (i = 0; i != MaxAllUsers; i++) { X printf("%9s",AllRecs[i]->name); X for (j = 0; j != MaxFs; j++) { X unsigned long v; X v = (SortFlag == CUR) ? AllRecs[i]->current[j] : X (SortFlag == TMIN) ? AllRecs[i]->min[j] : AllRecs[i]->max[j]; X printf("%7lu",v); X } X printf("%7lu\n",(SortFlag == CUR) ? AllRecs[i]->Fcur : X (SortFlag == TMIN) ? AllRecs[i]->Fmin : AllRecs[i]->Fmax); X } X} X X Xvoid LookRoom(fs) X{ X char dev[80]; X register int i; X X sprintf(dev, "/dev/r%s", fs); X fprintf(log_file,"Checking %s\n",dev); X check(dev); X for (i = 0; i != MAXUSERS; i++) { X unsigned long j; X X if (!WhatDidTheyDo[i]) X continue; X j = WhatDidTheyDo[i]->blocks[CurrentDay]; X WhatDidTheyDo[i]->current = j; X if (WhatDidTheyDo[i]->dmin > j) X WhatDidTheyDo[i]->dmin = j; X else if (WhatDidTheyDo[i]->dmax < j) X WhatDidTheyDo[i]->dmax = j; X } X} X Xint SortDelta(r1, r2) XRecP *r1, *r2; { X long v1, v2; X v1 = (*r1)->ddel; X v2 = (*r2)->ddel; X X if (v1 == v2) X return 0; X return (v2 > v1) ? 1 : -1; X} X Xint SortPerc(r1, r2) XRecP *r1, *r2; { X double v1, v2; X v1 = (*r1)->dper; X v2 = (*r2)->dper; X X if (v1 == v2) X return 0; X return (v2 > v1) ? 1 : -1; X} X Xvoid LookDelta(min,mode) { X register int i, j; X X if (min > CurrentDay) { X fprintf(log_file,"Cannot look more than %d days in the past\n",CurrentDay); X min=CurrentDay; X } X Sorted = (RecP *) malloc(MaxUsers * sizeof(RecP)); X for (i = 0, j = 0; i != MAXUSERS; i++) X if (WhatDidTheyDo[i]) { X double f; X Sorted[j] = WhatDidTheyDo[i]; X Sorted[j]->ddel = Sorted[j]->current - Sorted[j]->blocks[CurrentDay-min]; X f = (double) Sorted[j]->blocks[CurrentDay-min]; X if (f) X Sorted[j]->dper = (double) Sorted[j]->current / f; X else X Sorted[j]->dper = HUGE; X j++; X } X qsort(Sorted, MaxUsers, sizeof(RecP), (mode) ? SortDelta : SortPerc); X for (i = 0; i != MaxUsers; i++) { X if (!Sorted[i]->ddel) X continue; X printf("%8s\t%10lu\t%10lu",Sorted[i]->name,Sorted[i]->current, X Sorted[i]->blocks[CurrentDay-min]); X if (mode) X printf("\t%10ld\n",Sorted[i]->ddel); X else if (Sorted[i]->dper != HUGE) X printf("\t%10.6f%%\n",(Sorted[i]->dper - 1)*100); X else X printf("\t+ Infini \n"); X } X} X XInitWDTD() { X register short i; X FILE *pwd = fopen("/etc/passwd","r"); X char buf[BUFSIZ], *p, *strchr(); X int uid; X X while (fgets(buf,BUFSIZ,pwd)) { X if (!*buf || (*buf == '#')) X continue; X p = strchr(buf,':'); X if (!p || !*p) X continue; X *p = '\0'; X p = strchr(p+1,':'); X uid = atoi(p+1); X if (uid < 0) X fprintf(log_file,"Skipping negative uid %d (%s)\n",uid,buf); X else if (WhatDidTheyDo[uid]) X fprintf(log_file,"Duplicate entry uid %d (%s %s)\n",uid,buf, X WhatDidTheyDo[uid]->name); X else { X WhatDidTheyDo[uid] = (RecP) malloc(sizeof(Record)); X strncpy(WhatDidTheyDo[uid]->name,buf,8); X WhatDidTheyDo[uid]->uid = uid; X for (i = 0; i != TOKEEP; i++) { X WhatDidTheyDo[uid]->blocks[i] = 0L; X } X MaxUsers++; X } X } X fclose(pwd); X} X Xvoid ShowUser(username) Xchar *username; { X long first = 0L, min = 0L, max = 0L; X register int uid, i, j, k; X Record *r; X X uid = usertouid(username); X r = WhatDidTheyDo[uid]; X if (!r) { X fprintf(stderr, "No user %s [%d] on the device\n",username,uid); X return; X } X for (i = 0; i <= CurrentDay; i++) { X if (!r->blocks[i]) X continue; X if (!first) { X first = r->blocks[i]; X break; X } X } X printf("User %s (%d) is between %lu and %lu blocks (beginning at %lu)\n", X r->name, r->uid, r->dmin, r->dmax, first); X if (CurrentDay > 32) X k = 32; X else X k = CurrentDay; X printf("Here are the last %d days :",k); X for (j = 0, i = CurrentDay - k; i != CurrentDay; i++, j++) X if (j & 07) X printf("%8lu ",r->blocks[i+1]); X else X printf("\n%8lu ",r->blocks[i+1]); X puts(""); X} X Xint CurDay() { X time_t t; X struct tm *tt; X X t = time((time_t *) 0); X tt = localtime(&t); X return (tt->tm_yday - StartDay); X} X XShowList(n) { X register int i, j; X X Sorted = (RecP *) malloc(MaxUsers * sizeof(RecP)); X for (i = 0, j = 0; i != MAXUSERS; i++) X if (WhatDidTheyDo[i]) X Sorted[j++] = WhatDidTheyDo[i]; X qsort(Sorted, MaxUsers, sizeof(RecP), SortUsers); X if (n > CurrentDay) X n = CurrentDay; X for (i = 0; i != MaxUsers; i++) { X printf("%8s",Sorted[i]->name); X for (j = 0; j <= n; j++) X printf("%8lu",Sorted[i]->blocks[CurrentDay-j]); X puts(""); X } X} X Xvoid Usage() { X fprintf(stderr,"Usage: space -iul device\n"); X fprintf(stderr," or space -Ldays device\n"); X fprintf(stderr," or space -s device user1 user2 ...\n"); X fprintf(stderr," or space -t[cm-M]\n"); X fprintf(stderr," or space -[dD]days device\n"); X if (log_file && log_file != stderr) { X fclose(log_file); X } X exit(1); X} X Xmain(argc,argv) Xchar **argv; { X char *fs; X ++argv; --argc; X log_file = fopen(LOGFILE,"a"); X if (!log_file) { X perror(LOGFILE); X log_file = stderr; X fprintf(stderr,"Loggin informations on stderr\n"); X } X if (argc && (**argv == '-')) { X CurrentDay = CurDay(); X switch(argv[0][1]) { X case 'i': X InitWDTD(); X LookRoom(argv[1]); X SaveRecords(argv[1]); X exit(); X case 'u': X GetRecords(argv[1]); X LookRoom(argv[1]); X SaveRecords(argv[1]); X break; X case 's': X GetRecords(argv[1]); X ++argv; --argc; X while (++argv, --argc) X ShowUser(*argv); X break; X case 'l': X GetRecords(argv[1]); X ShowList(0); X break; X case 'L': X GetRecords(argv[1]); X ShowList(atoi(*argv+2)); X break; X case 'd': X case 'D': X GetRecords(argv[1]); X LookDelta(atoi(*argv + 2),argv[0][1] == 'd'); X break; X case 't': X if (!argv[0][2] || argv[0][2] == 'c') X SortFlag = CUR; X else if (argv[0][2] == 'm' || argv[0][2] == '-') X SortFlag = TMIN; X else X SortFlag = TMAX; X AllFileSystems(CurrentDay); X break; X default: X Usage(); X } X } X else X Usage(); X if (log_file && log_file != stderr) X fclose(log_file); X} SHAR_EOF $TOUCH -am 0124154791 space.c && chmod 0644 space.c || echo "restore of space.c failed" set `wc -c space.c`;Wc_c=$1 if test "$Wc_c" != "9367"; then echo original size 9367, current size $Wc_c fi fi # ============= sysdep.c ============== if test X"$1" != X"-c" -a -f 'sysdep.c'; then echo "File already exists: skipping 'sysdep.c'" else echo "x - extracting sysdep.c (Text)" sed 's/^X//' << 'SHAR_EOF' > sysdep.c && X/* X * space A tool to look out for greedy users X * $Header: /users/labinf/fmc/tools/Space/RCS/sysdep.c,v 1.2 91/01/24 15:30:13 fmc Exp $ X * $Source: /users/labinf/fmc/tools/Space/RCS/sysdep.c,v $ X * $Locker: $ X * $State: Exp $ X * $Log: sysdep.c,v $ X * Revision 1.2 91/01/24 15:30:13 fmc X * Added FSNAME define to check for non-local file-systems. X * X * Revision 1.1 91/01/24 15:17:50 fmc X * Initial revision X * X */ X X#include "defs.h" X XRecP WhatDidTheyDo[MAXUSERS]; XSuprecP TempRecs[MAXUSERS]; XSuprecP *AllRecs; Xint MaxUsers = 0, MaxAllUsers = 0; XFsName all_fs[MAXFS]; Xint MaxFs = 0; X XFILE *log_file; Xshort CurrentDay; X X/* X * User name to UID. X */ X Xint usertouid(user) Xchar *user; X{ X register struct passwd *pw; X struct passwd *getpwent(); X X setpwent(); X while (pw = getpwent()) X { X if (!strcmp(user,pw->pw_name)) { X endpwent(); X return (pw->pw_uid); X } X } X endpwent(); X return -1; X} X X/* X * UID to user name X */ X Xchar *uidtouser(uid) Xshort uid; X{ X register struct passwd *pw; X struct passwd *getpwent(); X X setpwent(); X while (pw = getpwent()) X { X if (uid == pw->pw_uid) { X endpwent(); X return (pw->pw_name); X } X } X endpwent(); X return NULL; X} X X/* X * Take inode ino/ip into account. ino (the current inode number) is used only X * to log inodes which belongs to no known users. X */ X Xvoid acct(ip,ino) Xregister struct dinode *ip; Xint ino; X{ X int uid = ip->di_uid; X X if ((ip->di_mode & IFMT) == 0) X return; X if ((uid >= 0) && (uid < MAXUSERS)) { X if (!WhatDidTheyDo[uid]) { X register int i; X char *n; X WhatDidTheyDo[uid] = (RecP) malloc(sizeof(Record)); X WhatDidTheyDo[uid]->uid = uid; X n = uidtouser(uid); X if (n) X strcpy(WhatDidTheyDo[uid]->name,n); X else X sprintf(WhatDidTheyDo[uid]->name,"#%d",uid); X for (i = 0; i != CurrentDay; i++) X WhatDidTheyDo[uid]->blocks[i] = 0L; X MaxUsers++; X } X WhatDidTheyDo[uid]->blocks[CurrentDay] += ip->di_blocks / 2; X if (WhatDidTheyDo[uid]->name[0] == '#') X fprintf(log_file,"inode %d of %d blocks owned by unknown uid %d\n", X ino,ip->di_blocks,uid); X } X} X X/* X * Block Read. Read block bno of size cnt from file fd into buf. X */ X Xvoid bread(fd, bno, buf, cnt) Xunsigned bno; Xchar *buf; X{ X X lseek(fd, (long)bno * DEV_BSIZE, L_SET); X if (read(fd, buf, cnt) != cnt) { X fprintf(log_file, "\tread error at block %u\n", bno); X if (log_file && log_file != stderr) X fclose(log_file); X exit(1); X } X} X Xunion { X struct fs u_sblock; X char dummy[SBSIZE]; X} sb_un; X#define sblock sb_un.u_sblock X Xstruct dinode itab[MAXBSIZE/sizeof(struct dinode)]; Xunsigned ino; X X/* X * Browse the file file_system. file should be the name of a block device X * corresponding to a disk partition. X */ X Xvoid check(file) Xchar *file; X{ X register int i, j, nfiles; X daddr_t iblk; X int c, fd; X X fd = open(file, O_RDONLY); X if (fd < 0) { X fprintf(log_file, "\tCan't access %s\n",file); X return; X } X sync(); X bread(fd, SBLOCK, (char *)&sblock, SBSIZE); X nfiles = sblock.fs_ipg * sblock.fs_ncg; X for (ino = 0; ino < nfiles; ) { X iblk = fsbtodb(&sblock, itod(&sblock, ino)); X bread(fd, iblk, (char *)itab, sblock.fs_bsize); X for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) { X if (ino < ROOTINO) X continue; X acct(&itab[j],ino); X } X } X close(fd); X} X X/* X * Browse though all file-systems (using getfsent()) and check all X * valid file system (file system of type ufs_name). X */ X Xvoid AllFileSystems(day) Xshort day; X{ X register struct fstab *fs; X register char *cp; X char dev[80], *rindex(); X FsName *fsp; X register int i, j; X X if (setfsent() == 0) { X fprintf(log_file, "space: no %s file\n", FSTAB); X exit(1); X } X while (fs = getfsent()) { X X /* X * Make sure we can read the file system. X */ X X#ifdef FSNAME X if (!strcmp(fs->fs_name,FSNAME)) X continue; X#endif X if (strcmp(fs->fs_type, FSTAB_RO) && X strcmp(fs->fs_type, FSTAB_RW) && X strcmp(fs->fs_type, FSTAB_RQ)) X continue; X cp = rindex(fs->fs_spec, '/'); X if (cp == 0) X continue; X fsp = all_fs + MaxFs; X strcpy(fsp->dev,++cp); X fsp->mount_point = (char *) malloc(strlen(fs->fs_file)+1); X strcpy(fsp->mount_point,fs->fs_file); X GetRecords(cp); X for (i = 0; i != MAXUSERS; i++) { X RecP rp = WhatDidTheyDo[i]; X SuprecP sp = TempRecs[i]; X X if (!rp) X continue; X if (!sp) { X sp = TempRecs[i] = (SuprecP) malloc(sizeof(Suprec)); X sp->uid = rp->uid; X strcpy(sp->name,rp->name); X MaxAllUsers++; X } X sp->Fcur += sp->current[MaxFs] = rp->current; X sp->Fmin += sp->min[MaxFs] = rp->dmin; X sp->Fmax += sp->max[MaxFs] = rp->dmax; X } X MaxFs++; X } X endfsent(); X AllRecs = (SuprecP *) malloc(MaxAllUsers * sizeof(SuprecP)); X for (i = 0, j = 0; i != MAXUSERS; i++) X if (TempRecs[i]) X AllRecs[j++] = TempRecs[i]; X qsort(AllRecs,MaxAllUsers,sizeof(SuprecP),SortAllRecs); X DispAllFs(); X} X SHAR_EOF $TOUCH -am 0124154791 sysdep.c && chmod 0644 sysdep.c || echo "restore of sysdep.c failed" set `wc -c sysdep.c`;Wc_c=$1 if test "$Wc_c" != "4960"; then echo original size 4960, current size $Wc_c fi fi # ============= defs.h ============== if test X"$1" != X"-c" -a -f 'defs.h'; then echo "File already exists: skipping 'defs.h'" else echo "x - extracting defs.h (Text)" sed 's/^X//' << 'SHAR_EOF' > defs.h && X/* X * defs.h X * $Header: X * $Source: X * $Locker: $ X * $State: Exp $ X * $Log: X * X */ X X#include <stdio.h> X#include <sys/types.h> X#include <signal.h> X#include <ctype.h> X#include <pwd.h> X#include <fstab.h> X#include <math.h> X#include <sys/time.h> X#include <sys/stat.h> X#include <sys/param.h> X#include <sys/file.h> X#include <ufs/fs.h> X#ifdef ULTRIX X#include <sys/inode.h> X#else X#include <sys/vnode.h> X#include <ufs/inode.h> X#endif X X#ifndef TOKEEP X#define TOKEEP 365 X#endif X X#define MAXUSERS 9999 X#define MAXFS 10 X X#define CUR 0 X#define TMIN 1 X#define TMAX 2 X#define FCUR 3 X#define FMIN 4 X#define FMAX 5 X Xtypedef unsigned long Blocks[TOKEEP]; X Xtypedef struct { X char dev[5]; X char *mount_point; X} FsName; X Xtypedef struct { X short uid; X char name[9]; X unsigned long current[MAXFS], min[MAXFS], max[MAXFS]; X unsigned long Fcur, Fmin, Fmax; X} Suprec, *SuprecP; X Xtypedef struct { X short uid; X char name[9]; X unsigned long current; X union { X unsigned long min; X long delta; X } delt; X#define dmin delt.min X#define ddel delt.delta X union { X unsigned long max; X double perc; X } perc; X#define dmax perc.max X#define dper perc.perc X Blocks blocks; X} Record, *RecP; X X X#ifndef DATADIR X#define DATADIR "/usr/tmp" X#endif X X#ifndef LOGFILE X#define LOGFILE "/usr/tmp/space.log" X#endif X X#ifndef STARTDAY X#define STARTDAY 0 X#endif X Xextern FILE *log_file; Xextern short CurrentDay; Xextern short StartDay; Xextern char SortFlag; Xextern RecP WhatDidTheyDo[MAXUSERS]; Xextern RecP *Sorted; Xextern SuprecP TempRecs[MAXUSERS]; Xextern SuprecP *AllRecs; Xextern int MaxUsers, MaxAllUsers; Xextern FsName all_fs[MAXFS]; Xextern int MaxFs; X Xint SortAllRecs(); X SHAR_EOF $TOUCH -am 0124154791 defs.h && chmod 0644 defs.h || echo "restore of defs.h failed" set `wc -c defs.h`;Wc_c=$1 if test "$Wc_c" != "1649"; then echo original size 1649, current size $Wc_c fi fi # ============= Makefile ============== if test X"$1" != X"-c" -a -f 'Makefile'; then echo "File already exists: skipping 'Makefile'" else echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# $Header: X# $Source: X# $Locker: $ X# $State: Exp $ X# $Log: Makefile,v $ X# Revision 1.9 91/01/24 15:48:42 fmc X# More fixes. X# X# Revision 1.7 91/01/24 15:28:46 fmc X# Added check for make depend. X# X# Revision 1.6 91/01/24 15:16:42 fmc X# moved the system dependent stuff in sysdep.c X# X# Revision 1.5 90/09/01 11:05:52 fmc X# Added install and clean target. X# X# Revision 1.4 90/08/31 16:26:24 fmc X# Added makedepend X# X# Revision 1.3 90/08/31 16:19:10 fmc X# More clean up X# X# Revision 1.2 90/08/30 19:01:25 fmc X# Some cleanup X# X# Revision 1.1 90/08/08 17:53:12 fmc X# Initial revision X# X XDESTDIR=/users/labinf/fmc/bin XCC=gcc XDEBUGFLAGS= -g XOPTFLAGS= -O -fwritable-strings -finline-functions XCPPFLAGS= X# X# For some system you have to define FSNAME as a string X# with the type of local file-system. X# On Ultrix it should be : X# SYSFLAGS= -DFSNAME=\"ufs\" -DULTRIX XSYSFLAGS= -DFSNAME=\"ufs\" -DULTRIX -DDATADIR=\"/usr/src\" XCFLAGS= $(DEBUGFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(SYSFLAGS) XLDFLAGS= $(DEBUGFLAGS) XMISC= Makefile space.8 INSTALL XSRCS= space.c sysdep.c defs.h XOBJS= space.o sysdep.o XMAKEDEPEND= makedepend X Xall: space X Xspace: $(OBJS) X $(CC) $(CFLAGS) $(LDFLAGS) -o space $(OBJS) -lm X Xinstall: all X install space $(DESTDIR) X Xclean: X rm -f *~ #* *.o core space .depend X Xdepend: $(SRCS) X $(MAKEDEPEND) -- $(CPPFLAGS) $(SYSFLAGS) -- $(SRCS) X Xshar: $(SRCS) $(MISC) X shar -n space -a -x -c -o space.shar $(SRCS) $(MISC) X X X# DO NOT DELETE THIS LINE -- make depend depends on it. X Xspace.o: defs.h /usr/include/stdio.h /usr/include/sys/types.h Xspace.o: /usr/include/signal.h /usr/include/ctype.h /usr/include/pwd.h Xspace.o: /usr/include/fstab.h /usr/local/lib/gcc-include/math.h Xspace.o: /usr/include/sys/time.h /usr/include/sys/stat.h Xspace.o: /usr/include/sys/param.h /usr/include/machine/param.h Xspace.o: /usr/include/sys/smp_lock.h /usr/include/sys/file.h Xspace.o: /usr/include/ufs/fs.h /usr/include/sys/inode.h Xspace.o: /usr/include/sys/gnode_common.h /usr/include/ufs/ufs_inode.h Xspace.o: /usr/include/sys/gnode.h Xsysdep.o: defs.h /usr/include/stdio.h /usr/include/sys/types.h Xsysdep.o: /usr/include/signal.h /usr/include/ctype.h /usr/include/pwd.h Xsysdep.o: /usr/include/fstab.h /usr/local/lib/gcc-include/math.h Xsysdep.o: /usr/include/sys/time.h /usr/include/sys/stat.h Xsysdep.o: /usr/include/sys/param.h /usr/include/machine/param.h Xsysdep.o: /usr/include/sys/smp_lock.h /usr/include/sys/file.h Xsysdep.o: /usr/include/ufs/fs.h /usr/include/sys/inode.h Xsysdep.o: /usr/include/sys/gnode_common.h /usr/include/ufs/ufs_inode.h Xsysdep.o: /usr/include/sys/gnode.h Xdefs.o: /usr/include/stdio.h /usr/include/sys/types.h /usr/include/signal.h Xdefs.o: /usr/include/ctype.h /usr/include/pwd.h /usr/include/fstab.h Xdefs.o: /usr/local/lib/gcc-include/math.h /usr/include/sys/time.h Xdefs.o: /usr/include/sys/stat.h /usr/include/sys/param.h Xdefs.o: /usr/include/machine/param.h /usr/include/sys/smp_lock.h Xdefs.o: /usr/include/sys/file.h /usr/include/ufs/fs.h Xdefs.o: /usr/include/sys/inode.h /usr/include/sys/gnode_common.h Xdefs.o: /usr/include/ufs/ufs_inode.h /usr/include/sys/gnode.h SHAR_EOF $TOUCH -am 0213114991 Makefile && chmod 0644 Makefile || echo "restore of Makefile failed" set `wc -c Makefile`;Wc_c=$1 if test "$Wc_c" != "3102"; then echo original size 3102, current size $Wc_c fi fi # ============= space.8 ============== if test X"$1" != X"-c" -a -f 'space.8'; then echo "File already exists: skipping 'space.8'" else echo "x - extracting space.8 (Text)" sed 's/^X//' << 'SHAR_EOF' > space.8 && X.\" RCSID: @(#)space.8 2.3 11/10/90 X.TH space 8 X.SH Name Xspace \- summarize file system usage X.SH Syntax X.B /usr/local/bin/space X[ option ] ... X[ filesystem ] X.SH Description X.NXR "space command" X.NXR "file system" "disk usage per user" XThe X.PN space Xcommand maintains the disk usage for a file system on a user basis. X.SH Options X.TP X.B \-i filesystem XInitialize the data-base associated with the given file system. Only the super user can give this command. X.TP X.B \-u filesystem XUpdate the database for the given file system. Onlu the super user can give this command. X.TP X.B \-s filesystem user1 user2 ... usern XList the disk usage on the given filesystem for each users in arguments. X.TP X.B \-l filesystem XList the current disk usage for the given file system, sorted by most greedy users. X.TP X.B \-Ln filesystem XSame as option \-l but X.I n Xdays in the past. X.TP X.B \-dn filesystem XList the difference in blocks between current usage and usage X.I n Xdays in the past. X.TP X.B \-Dn filesystem XList the difference in percentage between current usage and usage X.I n Xdays in the past. X.TP X.B \-tx XSummarize the disk usage on the whole system, depending on the X.I x Xletter. X.I c Xgives the current usage. X.I m Xgives the minimum usage. X.I M Xgives the maximum usage. X.SH Files XFile system names varies with system. X.br X/etc/passwd to get user names X.br X/usr/src/space-xxx.data for accumulated data for filesystem xxx X.SH See Also Xdu(1), ls(1), quot(8) X.SH Bugs XCertainly a lot. If you find one, send a mail to fmc@cnam.cnam.fr X SHAR_EOF $TOUCH -am 0213114791 space.8 && chmod 0444 space.8 || echo "restore of space.8 failed" set `wc -c space.8`;Wc_c=$1 if test "$Wc_c" != "1534"; then echo original size 1534, current size $Wc_c fi fi # ============= INSTALL ============== if test X"$1" != X"-c" -a -f 'INSTALL'; then echo "File already exists: skipping 'INSTALL'" else echo "x - extracting INSTALL (Text)" sed 's/^X//' << 'SHAR_EOF' > INSTALL && Xspace Version 1.9 Bugs, Gripes, etc... to fmc@cnam.cnam.fr X Last Modification: 12 Feb 91 X Xspace is a maintenance tool used to watch disk-space usage on a per Xuser per day basis. Be warned that you need : X X1/ root privilege to update the data-base (not to read it). X X2/ 1488 bytes per user per file-system, for each user UID possessing a X file on a file-system. Here we have around 300 users, 6 X file-systems are checked, giving us 496 user/fs entries or X 738048 bytes. X X3/ Right now, this usage is ... on a year by year basis. It means that X 1/ Each year, you have to re-initialize the DB X 2/ The starting point of the record keeping is hard-wired in the X code. X In fact, the rationale behind STARTDAY definition is not quite X clear. It will be used in the futur, but right now, it's only X use is to save some space (If you begin checking on the 1st Feb, X #define STARTDAY 31 and #define TOKEEP 334). X In a (hopefully) near future, space will read a configuration file X to determine such parameters. X X4/ Finally, space haws only be tested on : X X 1/ A Vax running Ultrix (3.1 and now 4.0) using gcc X 2/ A Sony MIPS running sony-os (3.3 and now 4.0) with mips-cc. X X I think the code in sysdep.c is rather BSD-dependent, but I've no X SysV box to test it. X XHow to Compile. X XIn the best case do a make depend, followed by a make all and a make install. X XI think everything system dependent resides in sysdep.c and it's there Xyou should check for trouble. X XCOMPILATION options. X XThe following #defines resides in defs.h change them if the default Xvalue doesn't correspond to your needs/environment : X Xname default value meaning XTOKEEP 365 How many days are stored. XMAXUSERS 9999 Maximum number of users (should be enough:-) XMAXFS 10 Maximum number of fs checked. XDATADIR "/usr/tmp" Where to keep the DBs XLOGFILE "/usr/tmp/space.log" The log file name. XSTARTDAY 0 First Day in the record (from 1st Jan.) XFSNAME not defined To check the fs type for local fs only. XDESTDIR /usr/local/bin In the Makefile for make install. X XHow to Install. X Xmake install (hopefully). You then must : X 1/ Initialize the DBs for each fs checked by : X for fs in fs1 fs2 ... fsn ; do space -i $fs ; done X space -i fs1 will look for the /dev/rfs1 file. X X 2/ Make sure the DBs are updated once a day (there's no check X to see if the DBs were already updated or not.) by doing X for fs in fs1 fs2 ... fsn ; do space -u $f ; done X The simplest way is to run it from cron, at night :-) X XHow to Use. X XThe most useful option are : X X -- space -l fs1 X which will list, by decreasing order, all users with the disk space X they are currently using on /dev/rfs1. X X -- space -dn fs1 X which will list, by decreasing order, the variation of the disk space X used between 'n' days ago and today. X XOther options include : X X -- space -s fs1 user1 user2 ... userN X last 32 days space usage on /dev/rfs1 for each user name mentionned X X -- space -Ln fs1 X last 'n' days space usage on dev/rfs1 for each users. X X -- space -Dn fs1 X same as -dn but display percentage instead of difference. X X -- space -tx X display disk usage for everybody on every local fs in /etc/fstab. X the 'x' has the following meaning : X - space -tc or space -t List Current Usage. X - space -tm or space -t- List Minimum Usage. X - space -tM or space -t+ List Maximum Usage. X Really useful if all file-systems are checked. X X XFutur modifications. X XThe main modification will be to introduce some sort of config. file Xcontaining all parameters wich are now #define'd. X XI also plane to introduce some sort of "time granularity" to enable Xthe check to be done on a 1 hour basis or every 2 days, and so on. X XI also intend to add code to get ride of old users and extend the Xlife time of the DBs for more than a year. X XAnd, of course, I'll try to fix bugs as they are reported. Space is Xrunning on our site for more than a 4 months now without much trouble, Xbut it as only be tested on the configuration mentionned above. X SHAR_EOF $TOUCH -am 0213114691 INSTALL && chmod 0644 INSTALL || echo "restore of INSTALL failed" set `wc -c INSTALL`;Wc_c=$1 if test "$Wc_c" != "4037"; then echo original size 4037, current size $Wc_c fi fi exit 0 [fmc] ------------------------------------------------------------------------------- Frederic Chauveau Conservatoire National des Arts et Metiers fmc@cnam.cnam.fr ------------------------------------------------------------------------------- Paradise is exactly like where you are right now, only much, much better. William S. Burroughs ------------------------------------------------------------------------------- exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.