[comp.sources.misc] v02i027: newest - print file system summary

rick@pcrat.UUCP (Rick Richardson) (01/31/88)

Comp.sources.misc: Volume 2, Issue 27

Submitted-By: Rick Richardson <rick@pcrat.UUCP>

Archive-Name: newest


Comp.sources.misc: Volume 2, Issue 27
Submitted-By: Rick Richardson <rick@pcrat.UUCP>
Archive-Name: newest

We use this around here when cleaning up our disks.  Maybe
others could use it, too.

-Rick Richardson

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	newest.c
# This archive created: Wed Jan 27 11:15:28 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'newest.c'
then
	echo shar: "will not over-write existing file 'newest.c'"
else
cat << \SHAR_EOF > 'newest.c'
/*
 *	newest:
 *		Print file summary information.
 *		Useful for cleaning up your disk space.
 *
 *	Donated to the public domain by Rick Richardson, 1988.
 *	Use at your own risk. Quick & Dirty Coding Used Here.
 *
 *	Needs System V "ftw" routine or equivalent.
 *	Needs System V "getopt" routine or equivalent.
 *
 *	No makefile needed, just type "make newest".
 *
 *	No man page needed, just type "newest" or "what newest".
 *
 *	Known to work on:
 *		Venix SVR2.3	(80286)
 *		UNIX SVR2	(VAX 785, 8700)
 */

char	*Usage[] =
{	/* Usage info, visible by 'what' */
"@(#)	Usage:	newest [-st] directories ...",
"@(#)	",
"@(#)		Print summary of access/modification/creation times",
"@(#)		and/or file sizes of files found in directories",
"@(#)	",
"@(#)		With no options, prints time information.",
"@(#)		With -s, prints size information.",
"@(#)		With -st, prints both type of information.",
0
};

#include <stdio.h>
#include <ftw.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>

int	unreadable;
long	mtime;
long	atime;
long	Ctime;
char	aname[BUFSIZ];
char	mname[BUFSIZ];
char	Cname[BUFSIZ];
char	bigname[BUFSIZ];
long	bigsize;
int	files;
long	bytes;
int	bigflag;
int	timeflag;
#define	SECS	(60L*60L*24L)
#define	EPOCH	9999999L
long	dayvec[] =
{
	0, 1, 2, 3, 4, 5, 6, 7, 10, 20, 50, 100, 200, 500, EPOCH
};
#define	DAYSIZE	(sizeof(dayvec) / sizeof(dayvec[0]))

long	sizvec[] =
{
	0, 1000, 5000, 10000, 20000, 50000, 100000, 200000, 500000,
	1000000, EPOCH
};
#define	SIZSIZE	(sizeof(sizvec) / sizeof(sizvec[0]))

int	afiles[DAYSIZE];
int	mfiles[DAYSIZE];
int	cfiles[DAYSIZE];
int	sizfiles[SIZSIZE];
long	now;

int
in(mindays, maxdays, when)
long	mindays, maxdays;
long	when;
{
	long	minsecs = mindays * SECS;
	long	maxsecs = maxdays * SECS;

	if ( (now-when)<maxsecs && (now-when)>=minsecs) return (1);
	return (0);
}

int
siz(minsiz, maxsiz, thissiz)
long	minsiz, maxsiz;
long	thissiz;
{
	if ( thissiz<maxsiz && thissiz>=minsiz) return (1);
	return (0);
}

int
fn(name, sp, what)
char	*name;
register struct stat	*sp;
{
	register int i;

	if (what != FTW_F && what != FTW_D)
	{
		++unreadable;
		return (0);
	}
	bytes += sp->st_size;
	if (what != FTW_F) return(0);
	++files;
	for (i = 1; i < DAYSIZE; ++i)
	{
		if (in(dayvec[i-1], dayvec[i], sp->st_mtime)) mfiles[i]++;
		if (in(dayvec[i-1], dayvec[i], sp->st_atime)) afiles[i]++;
		if (in(dayvec[i-1], dayvec[i], sp->st_ctime)) cfiles[i]++;
	}
	for (i = 1; i < SIZSIZE; ++i)
		if (siz(sizvec[i-1], sizvec[i], sp->st_size)) sizfiles[i]++;
	if (sp->st_mtime>mtime)
		{mtime = sp->st_mtime; (void)strcpy(mname, name);}
	if (sp->st_ctime>Ctime)
		{Ctime = sp->st_ctime; (void)strcpy(Cname, name);}
	if (sp->st_atime>atime)
		{atime = sp->st_atime; (void)strcpy(aname, name);}
	if (sp->st_size>bigsize)
		{bigsize = sp->st_size; (void)strcpy(bigname, name);}
	return (0);
}

int
main(argc, argv)
int	argc;
char	*argv[];
{
	char	*ctime();
	long	time();
	register int i, c, errflag = 0;
	extern char	*optarg;
	extern int	optind, opterr;

	while (( c = getopt(argc, argv, "st")) != EOF)
		switch (c)
		{
		case 's':	bigflag = 1; break;
		case 't':	timeflag = 1; break;
		default:	errflag = 1; break;
		}
	if (optind == argc || errflag)
	{
		usage();
		return (1);
	}
	now = time( (long *) 0);
	for (i = optind; i < argc; ++i)
	{
		init();
		walk(argv[i]);
		stats(argv[i]);
		graf(afiles, mfiles, cfiles);
	}
	return (0);
}

init()
{
	register int	i;

	unreadable = 0;
	mtime = 0;
	atime = 0;
	Ctime = 0;
	bigsize = 0;
	files = 0;
	bytes = 0;
	for (i = 1; i < DAYSIZE; ++i)
	{
		afiles[i] = 0;
		mfiles[i] = 0;
		cfiles[i] = 0;
	}
	for (i = 1; i < SIZSIZE; ++i)
		sizfiles[i] = 0;
}

walk(name)
register char	*name;
{
	while (ftw(name, fn, 10) > 0)
		;
}

stats(name)
char	*name;
{
	(void)printf("\nDirectory:     %s\n", name);
	(void)printf("Newest access: %s at %s", aname, ctime(&atime));
	(void)printf("Newest modify: %s at %s", mname, ctime(&mtime));
	(void)printf("Newest change: %s at %s", Cname, ctime(&Ctime));
	(void)printf("Largest file:  %s is %ld bytes\n", bigname, bigsize);
	if (unreadable)
		(void) printf("Unreadable directories/files found\n");
}

graf(avec, mvec, cvec)
int	avec[];
int	mvec[];
int	cvec[];
{
	register int	i;

	if (!bigflag || timeflag)
	{
		for (i = 1; i < DAYSIZE; ++i)
		{
			if (dayvec[i] == EPOCH)
				(void) printf(
		"%5ld - EPOCH days: %5d accessed %5d modified %5d changed\n",
					dayvec[i-1], avec[i], mvec[i], cvec[i]);
			else
				(void) printf(
		"%5ld - %5ld days: %5d accessed %5d modified %5d changed\n",
					dayvec[i-1], dayvec[i],
					avec[i], mvec[i], cvec[i] );
		}
		(void) printf(
		"                    %5d TOTAL FILES, %7ld TOTAL BYTES\n\n",
			files, bytes);
	}

	if (bigflag)
	{
		for (i = 1; i < SIZSIZE; ++i)
		{
			if (sizvec[i] == EPOCH)
				(void)printf("%7ld -  ULIMIT bytes: %5d files\n",
					sizvec[i-1], sizfiles[i] );
			else
				(void)printf("%7ld - %7ld bytes: %5d files\n",
					sizvec[i-1], sizvec[i], sizfiles[i] );
		}
		(void)printf("                    %7ld TOTAL BYTES\n", bytes);
	}
}

usage()
{
	register int	i;

	for (i = 0; Usage[i]; ++i)
		(void)fprintf(stderr, "%s\n", &Usage[i][5]);
}
SHAR_EOF
fi
exit 0
#	End of shell archive