[comp.sources.unix] v10i030: Find and remove stale files from a disk.

rs@uunet.UU.NET (Rich Salz) (07/02/87)

Submitted by: maddog!root
Mod.Sources: Volume 10, Number 30
Archive-Name: derez

Derez, a program to find and enmourge stale files on a disk.

[  This is great -- my first "anonymous" contribution.  I couldn't find
   "enmourge" in my Webster's Universal; it apparently means remove.
   --  r$ ]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README makefile derez.1 readbyte.1 derez.c readbyte.c
# Wrapped by rs@uunet on Wed Jul  1 22:52:21 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1140 characters\)
sed "s/^X//" >README <<'END_OF_README'
XDerez, a program to find and enmourge stale files on a disk.
X
XThis code is explicitly placed in the public domain by the author
Xand may be used for fun or profit.  It is explicitly not copyrighted
Xand contains no references to the author's true name.  This is by
Xdesign as the author does not what to become "known" as the author of
XDerez.
X
XAnyone having problems with derez should send a mail request to maddog!root
Xfor possible help or suggestions.  Anyone who fixes some of derez's bugs or
Xinadequacies is invited to send maddog!root a copy of the patches.  We can
Xalways use a better, but not necessarily less Draconian, derez on our system.
X
XDerez does not contain a mechanism to warn users about the impending
Xremoval of stale files.  We have found that doing this only invites the
Xusers to go and defeat the effects of derez totally without archiving
Xtheir stale files to tape and removing them from disk.  On systems with
Xcooperative users, perhaps a separate program that sends users mail about
Xtheir stale files, listing their path names might be helpful.
X
XXXXXXXXXXXXXXXXXXXXX Cut here and feed it to /bin/sh XXXXXXXXXXXXXXXXXXX
END_OF_README
if test 1140 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile\"
else
echo shar: Extracting \"makefile\" \(414 characters\)
sed "s/^X//" >makefile <<'END_OF_makefile'
XCFLAGS = -O
XPROGS = derez readbyte
XMANS = derez.1 readbyte.1
X
Xall : $(PROGS)
X
Xinstall : all $(MANS)
X	install -c derez /usr/local/bin
X	install -c -m 644 derez.1 /usr/man/manl/derez.l
X	install -c readbyte /usr/local/bin
X	install -c -m 644 readbyte.1 /usr/man/manl/readbyte.l
X
Xclean :
X	rm -f *.o
X
Xclobber : clean
X	rm -f $(PROGS)
X
Xderez : derez.c
X	cc -o derez derez.c
X
Xreadbyte : readbyte.c
X	cc -o readbyte readbyte.c
END_OF_makefile
if test 414 -ne `wc -c <makefile`; then
    echo shar: \"makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f derez.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"derez.1\"
else
echo shar: Extracting \"derez.1\" \(3578 characters\)
sed "s/^X//" >derez.1 <<'END_OF_derez.1'
X.TH DEREZ LOCAL "2 February 1987"
X.UC 4
X.SH NAME
Xderez \- find stale files, and move them into a MORGUE directory
X.SH SYNOPSIS
X.br
X\fBderez [-t days] [dir1 dir2 dir3 ...]\fP
X.SH DESCRIPTION
X.I Derez
Xis a program which is used to archive stale files.
XMost if not \fIall\fP UNIX systems suffer from the finite disk size problem.
XIf this problem is aggravated by users which have stale files that have not
Xbeen read for some time,
Xderez offers a solution.
XIt moves the stale files to a \fIMORGUE\fP directory so that they can
Xlater be archived using \fItar\fP.
X.sp
X\fIDerez\fP uses the access times,
Xtime last \fIread\fP not time last \fBwritten\fP,
Xof the files to determine their staleness.
XThe default number of days since last access is 180 days,
Xbut this can be changed using the \fB-t\fP option.
XIf no directory list is given to derez it searches current directory,
Xexcept the subdirectory \fIMORGUE\fP.
XThe \fB-t\fP option and a directory list can be used to give special handling to
Xantisocial users.
X.sp
XDerez can be defeated by using \fIfind\fP and \fIreadbyte\fP to find and read all
Xof the files in a directory tree.
XAlthough doing this might be reasonable for some directory that you haven't
Xlooked at in some time, but will be using in a few days,
Xdoing this to \fBall\fP of your files to defeat derez is considered antisocial
Xand is dealt with using back up options.
XThese options include:
Xchanging derez's definition of staleness from several months to one day or less for the
Xantisocial user,
Xarchiving directories of the antisocial user by hand and
Xremoval of the antisocial user's account from the machine.
XIf you are going to use \fIreadbyte\fP to save some files from derez,
Xyou should check with \fBroot\fP first to make sure that the action won't be
Xinterpreted as antisocial.
X.sp
XThe best way to avoid getting derez'ed is to actively archive your stale files
Xonto tape using tar and keep them off line.
XIf a user actively archives his stale files onto tape,
Xa rather large disk usage for truly active files will be tolerated.
X.sp
XAlthough derez was written for \fBroot's\fP use,
Xan individual user can use it to find and archive his stale files.
XThis is done by making a subdirectory with the name \fIMORGUE\fP in any directory
Xyou would like to archive the descendant stale files.
XYou then run \fIderez\fP.
XDerez will create a list of stale files,
Xwith the name \fIMORGUE/DEREZ\fP and then move the stale files into the directory
XMORGUE.
XIf a file that is removed is the last file in it's parent directory,
Xthe parent directory is removed.
XThe contents of the morgue directory can be archived using tar and then removed from the disk.
XThe use of \fIderez\fP for stale file control is highly recommended.
XScratch tapes can be found next to the system console.
X.sp
XFiles that have been derez'ed by root can be recovered from the archive tape using
X\fItar\fP.
XTo recover all one's stale files without moving some or all off line
Xwith personal archive tapes is considered antisocial.
X.SH SEE ALSO
Xfind, readbyte
X.ta 3.0i
X.SH FILES
X/usr/local/morgue/derez.mm.dd.yy	Lists of files derez'ed by root.
X.br
XMORGUE/DEREZ	The files derez will enmorgue.
X.br
XMORGUE/*	The enmorgued files.
X.SH "BUGS(Not to be taken advantage of)"
XDEREZ shares tar's limits on path name lengths.
X.br
XDerez does not archive files with more than one hard link as they
Xwould get seperated into several copies of the files in the current
Ximplementation.
X.br
XMORGUE and DEREZ are reserved names.
X.br
XDerez will not move files with path names of the form MORGUE/* or DEREZ
Xfor obvious reasons.
END_OF_derez.1
if test 3578 -ne `wc -c <derez.1`; then
    echo shar: \"derez.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f readbyte.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"readbyte.1\"
else
echo shar: Extracting \"readbyte.1\" \(631 characters\)
sed "s/^X//" >readbyte.1 <<'END_OF_readbyte.1'
X.TH READBYTE LOCAL "2 February 1987"
X.UC 4
X.SH NAME
Xreadbyte \- Read the first byte of a file, removing its staleness
X.SH SYNOPSIS
X.br
X\fBreadbyte filename\fP
X.SH DESCRIPTION
X.I Readbyte
Xreads the first byte of the specified file,
Xchanging its access date.
XIt is used to remove staleness of a file to prevent derez from
Xputting the file in the morgue for archival onto tape.
XExcessive use of \fIreadbyte\fP, or any other means of updating
Xthe access date of a file to defeat \fIderez\fP,
Xis interpreted as antisocial by root.
XAntisocial behavior is dealt with as described in the man page for \fIderez\fP.
X.SH SEE ALSO
Xfind, derez
END_OF_readbyte.1
if test 631 -ne `wc -c <readbyte.1`; then
    echo shar: \"readbyte.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f derez.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"derez.c\"
else
echo shar: Extracting \"derez.c\" \(4388 characters\)
sed "s/^X//" >derez.c <<'END_OF_derez.c'
X/* This program archives and removes all files on /u0
Xthat have not been accessed in 180 days.
X	*/
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <strings.h>
X
X#define MAXLEN 10240
X#define USAGE "derez [-t days] [dir1 dir2 dir3 ...]\n"
X
X#include <stdio.h>
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	FILE *fptr;
X	struct stat statbuf;
X	char filename[MAXLEN];
X	char cmd[MAXLEN];
X	char dirlist[MAXLEN];
X	int since;
X
X	dirlist[0] = NULL;
X	since = 180;
X
X
X	/* Check for the existence and access permissions on the MORGUE.
X		*/
X	if(stat("MORGUE", &statbuf)) {
X		perror("derez: MORGUE");
X		exit(1);
X	}
X	if(!(statbuf.st_mode & S_IFDIR)) {
X		fprintf(stderr, "derez: MORGUE is not a directory\n");
X		exit(1);
X	}
X	if(access("MORGUE", R_OK | W_OK | X_OK)) {
X		fprintf(stderr, "derez: The MORGUE must have read, write and execute perms\n");
X		exit(1);
X	}
X
X	if(argc > 1) {
X		if(strcmp(argv[1], "-t") == 0) {
X			if(argc < 3) {
X				fprintf(stderr, USAGE);
X				exit(1);
X			}
X			if(sscanf(argv[2], "%d", &since) != 1) {
X				fprintf(stderr, "derez: bad arg for -t option %s\n", argv[2]);
X				exit(1);
X			}
X			if(since < 1 || since > 1000) {
X				fprintf(stderr, "derez: bad value for -t argument\n");
X				exit(1);
X			}
X			argv += 2;
X			argc -= 2;
X		}
X		while(argc > 1) {
X			if((strncmp(argv[1], "/", strlen("/")) == 0) || (strncmp(argv[1], "../", strlen("../")) == 0)) {
X				fprintf(stderr, "derez: Directories must be relative to .\n");
X				exit(1);
X			}
X			if(lstat(argv[1], &statbuf)) {
X				fprintf(stderr, "The directory %s must exist\n", argv[1]);
X				exit(1);
X			}
X			if(statbuf.st_mode & S_IFDIR) {
X				if(dirlist[0] != NULL)
X					strcat(dirlist, " ");
X				strcat(dirlist, argv[1]);
X				argv += 1;
X				argc -= 1;
X			}
X			else {
X				fprintf(stderr, "derez: %s is not a directory\n", argv[1]);
X				exit(1);
X			}
X		}
X	}
X	/* We currently only derez files with 1 link as derez would
X	break up two links to the same file into seperate files.
X	We will have to steal code from tar to do an internal link table
X	and drop the use of tar completely.
X		*/
X	sprintf(cmd, "find %s -type f -links 1 -atime +%d -print > MORGUE/DEREZ",
X		(dirlist[0] == NULL ? "." : dirlist), since);
X
X	printf("%s\n", cmd);
X	if(system(cmd) != 0) {
X		fprintf(stderr, "derez: The attempt to create MORGUE/DEREZ failed\n");
X		exit(1);
X	}
X	if((fptr = fopen("MORGUE/DEREZ", "r")) == NULL) {
X		fprintf(stderr, "Open of MORGUE/DEREZ for reading failed\n");
X		exit(1);
X	}
X	while(fgets(filename, MAXLEN, fptr) != NULL) {
X		char *rightslash;
X		/* Kill off the newline. */
X		if(filename[strlen(filename) - 1] != '\n') {
X			fprintf(stderr, "missing \\n on %s\n", filename);
X			continue;
X		}
X		filename[strlen(filename) - 1] = NULL;
X
X		/* If the file path name is too long we don't want
X		to see the error message from tar.
X			*/
X		if(strlen(filename) > 99)
X			continue;
X
X		/* If the file basename is of the form .* we want to
X		leave it alone to prevent removal of someones login
X		directory or setup files.  Of course if you take this
X		code out you get automatic removal of directories
X		associated with inactive accounts.
X			*/
X		if((rightslash = rindex(filename, '/')) != NULL) {
X			if(rightslash[1] == '.')
X				continue;
X		}
X		
X		if(
X			/* We don't want to mess with files already in the MORGUE.
X				*/
X			(strncmp(filename, "./MORGUE/", strlen("./MORGUE/")) != 0)
X			&& (strncmp(filename, "MORGUE/", strlen("MORGUE/")) != 0)
X			/* The lost+found directory is a sacred system item.
X				*/
X			&& (strncmp(filename, "./lost+found/", strlen("./lost+found/")) != 0)
X			&& (strncmp(filename, "lost+found/", strlen("lost+found/")) != 0)
X			/* If we were to enmorgue a file named DEREZ, we
X			would overwrite the list of files to move.
X				*/
X			&& (strncmp(filename, "./DEREZ") != 0)
X			&& (strcmp(filename, "DEREZ") != 0)
X		){
X			sprintf(cmd, "tar cf - %s | (cd MORGUE; tar xpf -)", filename);
X			if(system(cmd) == 0) {
X				fprintf(stderr, "enmorgue of %s succeeded\n", filename);
X				unlink(filename);
X				/* If it was the last file in the directory
X				we also want to remove the directory.
X					*/
X				while(strlen(filename) > 0 && filename[strlen(filename) - 1] != '/') {
X					filename[strlen(filename) - 1] = NULL;
X				}
X				filename[strlen(filename) - 1] = NULL;
X				rmdir(filename);
X			}
X			else {
X				fprintf(stderr, "enmorgue of %s FAILED, file removal was inhibited\n", filename);
X			}
X		}
X	}
X	fclose(fptr);
X}
END_OF_derez.c
if test 4388 -ne `wc -c <derez.c`; then
    echo shar: \"derez.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f readbyte.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"readbyte.c\"
else
echo shar: Extracting \"readbyte.c\" \(363 characters\)
sed "s/^X//" >readbyte.c <<'END_OF_readbyte.c'
X#include <stdio.h>
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int fd;
X	char cbuffer[512];
X
X	if(argc != 2) {
X		fprintf(stderr,"usage: readbyte file\n");
X		exit(1);
X	}
X	if((fd=open(argv[1],0)) < 0) {
X		fprintf(stderr,"cant open %s\n",argv[1]);
X		exit(1);
X	}
X	if(read(fd,cbuffer,1) != 1) {
X		fprintf(stderr,"cant read byte from file %s\n",argv[1]);
X		exit(1);
X	}
X}
END_OF_readbyte.c
if test 363 -ne `wc -c <readbyte.c`; then
    echo shar: \"readbyte.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
his aot