V10/cmd/findo.c

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

#include "sys/param.h"
#include "sys/ino.h"
#include "sys/inode.h"
#include "sys/dir.h"
#include "sys/filsys.h"
#include "stdio.h"
#include "sys/stat.h"
#include <pwd.h>
#include <ctype.h>

#define MONTH	3600*24L*7L*4L
#define	DAY	(3600*24L)
#define	WEEK	3600*24L*7L
#define	DAY3	3600*24L*3L
#define	NUID	20000

int	uid = -2;
int	nflag = 0;

#define biton(x, n)	x[(n)>>3] |= 1 << ((n)&7)
#define isdir(p)	(((p)->di_mode & S_IFMT) == S_IFDIR)
#define isold(p)	(p->di_mtime + WEEK < nowtime)
#define isvold(p)	(p->di_mtime + MONTH < nowtime)
#define	isuser(p)	((p->di_uid>=NUID||isbad[p->di_uid]) && (nflag==0 || p->di_mtime + DAY3 >= nowtime))
#define isnt(p)		!(p->di_mode & S_IFMT)
#define istrue(x, n)	x[(n)>>3] & (1<<((n)&7))

extern int screen(), consider();
char dlist[8192], olist[8192], slist[8192], tlist[8192];
int szlist[65536];
int days[65536];
char curdir[256];
long nowtime;
char	isbad[NUID];
struct stat origstat;

main(argc, argv) char **argv;
{
	int i;

	(void) time(&nowtime);
	isbad[uid] = 1;
	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-n")==0) {
			nflag++;
			continue;
		}
		if (i < argc-2 && strcmp(argv[i], "-u")==0) {
			isbad[uid] = 0;
			uid = atoi(argv[i+1]);
			isbad[uid] = 1;
			i++;
			continue;
		}
		if (strcmp(argv[i], "-f")==0) {
			getbad();
			continue;
		}
		break;
	}
	if (i>argc-2) {
		fprintf(stderr, "findo /dev/device /place-it-is-mounted\n");
		exit(1);
	}
	finit();
	eachinode(argv[i], screen);
	if (chdir(argv[++i])) {
		perror(argv[i]);
		exit(1);
	}
	strcpy(curdir, argv[i]);
	stat(curdir, &origstat);	/* where we started */
	alldir(0, consider);
	exit(0);
}

finit()
{	int i;
	for (i = 0; i < sizeof(olist); i++)
		olist[i] = 0;
	for (i = 0; i < sizeof(dlist); i++)
		dlist[i] = 0;
	for (i = 0; i < sizeof(slist); i++)
		slist[i] = 0;
	for (i = 0; i<sizeof(tlist); i++)
		tlist[i] = 0;
	for (i = 0; i < sizeof(szlist)/sizeof(szlist[0]); i++)
		szlist[i] = days[i] = 0;
}

screen(n, p) struct dinode *p; unsigned int n;
{
	if(isnt(p)) return;
	szlist[n] = p->di_size;
	days[n] = (nowtime - p->di_mtime) / DAY;
	if(isdir(p)) {
		biton(dlist, n);
	}
	if(isuser(p)) {
		biton(slist, n);
		return;
	}
	if(isitroff(p)) {
		biton(tlist, n);
		return;
	}
	if(isold(p)) {
		biton(olist, n);
		if (isvold(p))
			biton(tlist, n);
		return;
	}
}

newsys()
{
	struct stat dot;

	stat(".", &dot);
	return dot.st_dev != origstat.st_dev;
}

consider(n, p) struct direct *p;
{	int j;
	char buf[DIRSIZ+1];
	if(istrue(dlist, p->d_ino)) {
		for(j = 0; j < DIRSIZ; j++)
			buf[j] = p->d_name[j];
		buf[j] = 0;
		j = strlen(curdir);
		if(strcmp(".", buf) == 0 || strcmp("..", buf) == 0)
			return;	/* of course this can't happen (ha) */
		strcat(curdir, "/");
		strcat(curdir, buf);
		if(chdir(buf) == -1)
			perror(curdir);
		else {
			if(!newsys())
				alldir(n+1, consider);
			if (chdir("..") < 0) {
				fprintf(stderr, "bad '..' in %s\n", curdir);
				curdir[j] = '\0';
				chdir(curdir);
			}
		}
		curdir[j] = 0;
	}
	if (istrue(slist, p->d_ino)) {
		printf("user\t%8d %8d\t", szlist[p->d_ino], days[p->d_ino]);
		file(p->d_name);
	}
	if (istrue(olist, p->d_ino)) {
		if(badname(p->d_name, istrue(tlist, p->d_ino))) {
			printf("old\t%8d %8d\t", szlist[p->d_ino], days[p->d_ino]);
			file(p->d_name);
		}
		return;
	}
	if (istrue(tlist, p->d_ino)) {
		printf("troff\t%8d %8d\t", szlist[p->d_ino], days[p->d_ino]);
		file(p->d_name);
	}
}

badname(s, voflg)
register char *s;
{
	register char *p;
	register int k;

	if(strncmp("core", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("a.out", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("junk", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("ed.hup", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("jim.recover", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("sam.save", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("sam.err", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("~~sam~~", s, DIRSIZ) == 0)
		return(1);
	if(strncmp(".pilog", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("mon.out", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("qed.hup:", s, 8) == 0)
		return(1);
	if(strncmp("x", s, DIRSIZ) == 0)
		return(1);
	if(strncmp("dead.letter", s, DIRSIZ) == 0)
		return(1);
	if (strend(".dvi", s))
		return(1);
	if (strncmp("junk", s, 4)==0 || strncmp("temp", s, 4)==0)
		return 1;
	if (strlen(s) == 1 && islower(s[0]))
		return 1;
	if (strncmp("foo", s, 3)==0 ||
	   (strncmp("rst", s, 3)==0 && strlen(s)>5)) {
		p = s+3;
		while (p < s+DIRSIZ) {
			if (*p == 0)
				return(1);
			if (!isdigit(*p))
				break;
			p++;
		}
	}
	if (strncmp(".jx", s, 3) == 0)
		return(1);
	if (s[5]=='.' && isdigit(s[3]) && isdigit(s[4]) && isdigit(s[7])
	 && isdigit(s[8]) && s[6]=='a')
		return(1);
	if (voflg==0)
		return(0);
	p = s+DIRSIZ;
	if (strend(".o", s))
		return(1);
	return(0);
}

strend(e, s)	/* is e the end of s? */
	register char *e, *s;
{
	register char *t=s;
	while(*t)
		t++;
	t-=strlen(e);
	return(strcmp(e, t)==0);
}

file(s) char *s;
{	int i;
	char buf[DIRSIZ+1];
	for(i = 0; i < DIRSIZ; i++)
		buf[i] = *s++;
	buf[i] = 0;
	printf("%s/%s\n", curdir, buf);
}

isitroff(ip)
register struct dinode *ip;
{
	long dska[13];
	char tbuf[BSIZE(0)];
	if ((ip->di_mode&IFMT) != IFREG)
		return(0);
	if (ip->di_mode&IEXEC)
		return(0);
/*	if (ip->di_size < 512)
/*		return(0);
*/
	if (ip->di_mtime + DAY > nowtime)
		return(0);
/*	if (ip->di_mtime +(200*DAY) < nowtime)
/*		return(0);
*/
	l3tol(dska, ip->di_addr, 13);
	bread(dska[0], tbuf, BSIZE(0));
	if (troffint(tbuf))
		return(1);
	return(0);
}

char *troff[] = {	/* troff intermediate lang */
	"x T ", "x res ", "x init", "V0", "x font ", 0 };
int ntroff[] = {
	4,	 6,	   6,	     2,    7 };

troffint(bp)
register char *bp;
{
	register char **tp;
	register i, j, k = 0, oi, n;

	for (i = oi = n = 0; i < BSIZE(0) && k < 15; i++) {
		if (bp[i] == '\n') {
			k++;
			bp[i] = '\0';
			for (j = 0; troff[j]; j++)
				if (strncmp(bp+oi, troff[j], ntroff[j]) == 0)
					n++;
			oi = i+1;
		}
	}
	return n > 5;
}

word(p1, p2)
register char *p1, *p2;
{
	while (*p1++ == *p2++)
		;
	if (*--p1 != '\0')
		return(0);
	if (*--p2 !=' ' && *p2!='\n')
		return(0);
	return(1);
}

#define	ITABSZ	BUFSIZE/sizeof(long)
#define	ISIZ	(BUFSIZE/sizeof(struct dinode))
static	struct	filsys	sblock;
static	struct	dinode	itab[ITABSZ];
static	fi;
struct stat stb;
int dev;


eachinode(file, func)
char *file;
int (*func)();
{	unsigned ino;
	int nfiles = 0;
	register unsigned i, j;

	fi = open(file, 0);
	if(fi < 0 || fstat(fi, &stb) != 0) {
		fprintf(stderr, "cannot open %s\n", file);
		return;
	}
	dev = stb.st_rdev;
	bread((long)1, (char *)&sblock, sizeof sblock);
	nfiles = (sblock.s_isize-2)*(BSIZE(dev)/sizeof(struct dinode));
	ino = 1;
	for(i=2+((ino-1)/INOPB(dev)); ino<nfiles; i ++) {
		bread((long)i, (char *)itab, BSIZE(dev));
		for (j=0; j<INOPB(dev) && ino<nfiles; j++) {
			(*func)(ino, &itab[j]);
			ino++;
		}
	}
}

bread(bno, buf, cnt)
long bno;
char *buf;
{	int i;

	lseek(fi, bno*BSIZE(dev), 0);
	if (read(fi, buf, cnt) != cnt) {
		printf("read error %u\n", bno);
		for(i=0; i<cnt;i++)
			buf[i] = 0;
	}
}

alldir(n, f) int (*f)();
{	struct direct p;
	FILE *fd;
	fd = fopen(".", "r");
	if(fd == NULL) {
		perror(".");
		return(0);
	}
	(void) fseek(fd, (long)2 * sizeof(p), 0);	/* skip . and .. */
	for(;;) {
		(void) fread((char *)&p, 1, sizeof(p), fd);
		if(feof(fd)) break;
		if(p.d_name[0] != 0 && p.d_ino != 0)
			(*f)(n, &p);
	}
	(void) fclose(fd);
	return(1);
}

getbad()
{
	register struct passwd *p;
	extern struct passwd *getpwent();
	register i;

	for (i=0; i<NUID; i++)
		isbad[i] = 1;
	while (p = getpwent()) {
		if (p->pw_uid>=0 && p->pw_uid<NUID)
			isbad[p->pw_uid] = 0;
	}
}