v13i041: Derez, remove stale files from system, Part02/02

Rich Salz rsalz at bbn.com
Sat Feb 13 08:11:09 AEST 1988


Submitted-by: A. Nonymous
Posting-number: Volume 13, Issue 41
Archive-name: derez3/part02

The author will deny being the author of this program.

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ x$1 = x-a ]; then
	all=TRUE
fi
/bin/echo 'Extracting derez.c'
sed 's/^X//' <<'//go.sysin dd *' >derez.c
X/* Derez, the great stale file archiver.  It stages stale files
into a MORGUE directory for later removal with tar or rerez.
	*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <strings.h>
#include <errno.h>
extern int errno;

#define MAXLEN 10240
#define USAGE "derez [-t days] [dir1 dir2 dir3 ...]\n"

#include <stdio.h>

main(argc, argv)
int argc;
char **argv;
{
	FILE *fptr;
	struct stat statbuf;
	char filename[MAXLEN];
	char cmd[MAXLEN];
	char dirlist[MAXLEN];
	int since;
	int teflag = 0;

	dirlist[0] = NULL;
	since = 180;


	/* Check for the existence and access permissions on the MORGUE.
		*/
	if(stat("MORGUE", &statbuf)) {
		perror("derez: MORGUE");
		exit(1);
	}
	if(!(statbuf.st_mode & S_IFDIR)) {
		fprintf(stderr, "derez: MORGUE is not a directory\n");
		exit(1);
	}
	if(access("MORGUE", R_OK | W_OK | X_OK)) {
		fprintf(stderr, "derez: The MORGUE must have read, write and execute perms\n");
		exit(1);
	}

	if(argc > 1) {
		if(strcmp(argv[1], "-t") == 0) {
			if(argc < 3) {
				fprintf(stderr, USAGE);
				exit(1);
			}
			if(sscanf(argv[2], "%d", &since) != 1) {
				fprintf(stderr, "derez: bad arg for -t option %s\n", argv[2]);
				exit(1);
			}
			if(since < 0 || since > 10000) {
				fprintf(stderr, "derez: bad value for -t argument\n");
				exit(1);
			}
			argv += 2;
			argc -= 2;
		}
		else if(strcmp(argv[1], "-te") == 0) {
			if(argc < 3) {
				fprintf(stderr, USAGE);
				exit(1);
			}
			if(sscanf(argv[2], "%d", &since) != 1) {
				fprintf(stderr, "derez: bad arg for -t option %s\n", argv[2]);
				exit(1);
			}
			if(since < 0 || since > 10000) {
				fprintf(stderr, "derez: bad value for -te argument\n");
				exit(1);
			}
			teflag = 1;
			argv += 2;
			argc -= 2;
		}
		while(argc > 1) {
			if((strncmp(argv[1], "/", strlen("/")) == 0) || (strncmp(argv[1], "../", strlen("../")) == 0)) {
				fprintf(stderr, "derez: Directories must be relative to .\n");
				exit(1);
			}
			if(lstat(argv[1], &statbuf)) {
				fprintf(stderr, "The directory %s must exist\n", argv[1]);
				exit(1);
			}
			if(statbuf.st_mode & S_IFDIR) {
				if(dirlist[0] != NULL)
					strcat(dirlist, " ");
				strcat(dirlist, argv[1]);
				argv += 1;
				argc -= 1;
			}
			else {
				fprintf(stderr, "derez: %s is not a directory\n", argv[1]);
				exit(1);
			}
		}
	}
	if(teflag) {
		sprintf(cmd, "find %s -type f -atime %d -print > MORGUE/DEREZ",
			(dirlist[0] == NULL ? "." : dirlist), since);
	}
	else {
		sprintf(cmd, "find %s -type f -atime +%d -print > MORGUE/DEREZ",
			(dirlist[0] == NULL ? "." : dirlist), since);
	}

	printf("%s\n", cmd);
	if(system(cmd) != 0) {
		fprintf(stderr, "derez: The attempt to create MORGUE/DEREZ failed\n");
		exit(1);
	}
	if((fptr = fopen("MORGUE/DEREZ", "r")) == NULL) {
		fprintf(stderr, "Open of MORGUE/DEREZ for reading failed\n");
		exit(1);
	}
	while(fgets(filename, MAXLEN, fptr) != NULL) {
		char *rightslash;
		/* Kill off the newline. */
		if(filename[strlen(filename) - 1] != '\n') {
			fprintf(stderr, "missing \\n on %s\n", filename);
			continue;
		}
		filename[strlen(filename) - 1] = NULL;

		/* If the path name is too long we want to leave the file
		alone so that the enmorgued tree can be archived using tar.
			*/
		if(strlen(filename) > 99)
			continue;

		/* If the file basename is of the form .* we want to
		leave it alone to prevent removal of someones login
		directory or setup files.  Of course if you take this
		code out you get automatic removal of directories
		associated with inactive accounts.
			*/
		if((rightslash = rindex(filename, '/')) != NULL) {
			if(rightslash[1] == '.')
				continue;
		}
		
		if(
			/* We don't want to mess with files already in the MORGUE.
				*/
			(strncmp(filename, "./MORGUE/", strlen("./MORGUE/")) != 0)
			&& (strncmp(filename, "MORGUE/", strlen("MORGUE/")) != 0)
			/* The lost+found directory is a sacred system item.
				*/
			&& (strncmp(filename, "./lost+found/", strlen("./lost+found/")) != 0)
			&& (strncmp(filename, "lost+found/", strlen("lost+found/")) != 0)
			/* Some systems have a directory local that needs to
			be left alone.
				*/
			&& (strncmp(filename, "./local/", strlen("./local/")) != 0)
			&& (strncmp(filename, "local/", strlen("local/")) != 0)
			/* If we were to enmorgue a file named DEREZ, we
			would overwrite the list of files to move.
				*/
			&& (strcmp(filename, "./DEREZ") != 0)
			&& (strcmp(filename, "DEREZ") != 0)
		){
			/* We get to move the bugger.  We first create any fix up
			the modes and ownership of any needed directories and then
			link the file over.
				*/
			char target[MAXLEN];
			char *source = filename;
			char *dest;

			strcpy(target, "MORGUE");
			dest = target;
			while(*dest != NULL) dest += 1;
			while(*source == '.' || *source == '/') source += 1;
			while(1) {
				/* Peel off the next name in the chain.
					*/
				*dest++ = '/';
				*dest = NULL;
				while(*source != '/' && *source != NULL) *dest++ = *source++;
				*dest = NULL;
				source += 1;
				if(stat(target + strlen("MORGUE/"), &statbuf)) {
					fprintf(stderr, "derez: stat on %s failed\n", target + strlen("MORGUE/"));
					perror("stat");
					exit(1);
				}
				if(statbuf.st_mode & S_IFDIR) {
					int owner = statbuf.st_uid;
					int group = statbuf.st_gid;
					int mode = statbuf.st_mode;
					if(mkdir(target, 0x777)) {
						if(errno != EEXIST) {
							fprintf(stderr, "derez: %s does not exist, but attempt to make it failed\n", target);
							perror("derez: mkdir");
							exit(1);
						}
						if(stat(target, &statbuf)) {
							perror("derez: stat");
							exit(1);
						}
						if(statbuf.st_uid != owner) {
							fprintf(stderr, "derez: Inconsistent owner for %s\n", target);
							exit(1);
						}
						if(statbuf.st_gid != group) {
							fprintf(stderr, "derez: Inconsistent group for %s\n", target);
							exit(1);
						}
						if(statbuf.st_mode != mode) {
							fprintf(stderr, "derez: Inconsistent mode for %s\n", target);
							exit(1);
						}
					}
					else {
						if(geteuid() == 0) {
							if(chown(target, owner, group)) {
								fprintf(stderr, "derez: chown of newly created directory %s failed\n", target);
								exit(1);
							}
						}
						else {
							sprintf(cmd, "/bin/chgrp %d %s", group, target);
							if(system(cmd)) {
								fprintf(stderr, "%s failed\n", cmd);
								exit(1);
							}
						}
						if(chmod(target, mode)) {
							fprintf(stderr, "derez: chmod of newly created directory %s failed\n", target);
							exit(1);
						}
					}
				}
				else {
					if(*(source - 1) != NULL) {
						fprintf(stderr, "derez: sanity check failed\n");
						exit(1);
					}
					if(!(statbuf.st_mode & S_IFREG)) {
						fprintf(stderr, "derez: %s is not a regular file\n", target + strlen("MORGUE/"));
						exit(1);
					}
					if(link(target + strlen("MORGUE/"), target)) {
						fprintf(stderr, "derez: link for %s failed\n", target);
						exit(1);
					}
					break;
				}
			}
			
			fprintf(stderr, "enmorgue of %s succeeded\n", filename);
#define RIPEM
#ifdef RIPEM
			unlink(filename);
#else
			fprintf(stderr, "Would have unlinked %s\n", filename);
#endif
			/* If it was the last file in the directory
			we also want to remove the directory.
				*/
			while(1) {
			while(strlen(filename) > 0 && filename[strlen(filename) - 1] != '/') {
				filename[strlen(filename) - 1] = NULL;
			}
			if(strlen(filename) == 0 || strcmp(filename, "./") == 0)
				break;
			
			filename[strlen(filename) - 1] = NULL;
#ifdef RIPEM
			rmdir(filename);
#else
			fprintf(stderr, "would have rmdir'ed %s if empty\n", filename);
#endif
			}
		}
	}
	fclose(fptr);
}
//go.sysin dd *
if [ `wc -c < derez.c` != 7617 ]; then
	made=FALSE
	/bin/echo 'error transmitting "derez.c" --'
	/bin/echo 'length should be 7617, not' `wc -c < derez.c`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 derez.c
	/bin/echo -n '	'; /bin/ls -ld derez.c
fi
/bin/echo 'Extracting readbyte.c'
sed 's/^X//' <<'//go.sysin dd *' >readbyte.c
#include <stdio.h>

main(argc,argv)
int argc;
char *argv[];
{
	int fd;
	char cbuffer[512];

	if(argc != 2) {
		fprintf(stderr,"usage: readbyte file\n");
		exit(1);
	}
	if((fd=open(argv[1],0)) < 0) {
		fprintf(stderr,"cant open %s\n",argv[1]);
		exit(1);
	}
	if(read(fd,cbuffer,1) != 1) {
		fprintf(stderr,"cant read byte from file %s\n",argv[1]);
		exit(1);
	}
}
//go.sysin dd *
if [ `wc -c < readbyte.c` != 363 ]; then
	made=FALSE
	/bin/echo 'error transmitting "readbyte.c" --'
	/bin/echo 'length should be 363, not' `wc -c < readbyte.c`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 readbyte.c
	/bin/echo -n '	'; /bin/ls -ld readbyte.c
fi
/bin/echo 'Extracting agehist.c'
sed 's/^X//' <<'//go.sysin dd *' >agehist.c
X/* Agehist prints out file age histograms for the listed directories.
	*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

FILE *popen();

#define MAXLEN 1024

#define MAXDAYS 180

int data[MAXDAYS];

main(argc, argv)
int argc;
char **argv;
{
	int dir;
	int i;
	int ageindays;
	FILE *list;
	char filename[MAXLEN];
	char cmd[MAXLEN];
	struct stat statbuf;
	time_t time();
	time_t marker;

	marker = time((time_t *)0);

	for(dir = 1; dir < argc; dir += 1) {

	for(i = 0; i < MAXDAYS; i += 1) data[i] = 0;

	fprintf(stdout, "directory %s\n", argv[dir]);
	sprintf(cmd, "find %s -type f -print", argv[dir]);
	if((list = popen(cmd, "r")) == NULL) {
		fprintf(stderr, "Failed to open pipe\n");
		exit(1);
	}
	while(fgets(filename, MAXLEN, list) != NULL) {
		if(strlen(filename) >= MAXLEN-1) {
			fprintf(stderr, "path name too long\n");
			exit(1);
		}
		filename[strlen(filename)-1] = NULL;
		if(stat(filename, &statbuf)) {
			perror("agehist: stat");
			exit(1);
		}
		ageindays = (marker - statbuf.st_atime) / (24 * 60 * 60);
	/*	fprintf(stdout, "%d %s\n", ageindays, filename);*/
		if(ageindays > MAXDAYS-1) ageindays = MAXDAYS-1;
		if(ageindays < 0) ageindays = 0;
		data[ageindays] += 1;
	}
	for(i = 0; i < MAXDAYS; i += 1) {
		if(i % 10 == 0) fprintf(stdout, "%4d |", i);
		fprintf(stdout, "%4d", data[i]);
		if(i % 10 == 9) fprintf(stdout, "\n");
	}
	fprintf(stdout, "\n");
	pclose(list);
	}
}
//go.sysin dd *
if [ `wc -c < agehist.c` != 1411 ]; then
	made=FALSE
	/bin/echo 'error transmitting "agehist.c" --'
	/bin/echo 'length should be 1411, not' `wc -c < agehist.c`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 agehist.c
	/bin/echo -n '	'; /bin/ls -ld agehist.c
fi
/bin/echo 'Extracting derez.1'
sed 's/^X//' <<'//go.sysin dd *' >derez.1
X.TH DEREZ LOCAL "2 February 1987"
X.UC 4
X.SH NAME
derez \- find stale files, and move them into a MORGUE directory
X.SH SYNOPSIS
X.br
\fBderez [-t[e] days] [dir1 dir2 dir3 ...]\fP
X.SH DESCRIPTION
X.I Derez
is a program which is used to enmorgue stale files.
Most if not \fIall\fP UNIX systems suffer from the finite disk size problem.
If this problem is aggravated by users which have stale files that have not
been read for some time,
derez offers a solution.
It moves the stale files to a \fIMORGUE\fP directory so that they can
later be archived using \fItar\fP.
Derez finds the stale files and moves them to the \fIMORGUE\fP directory,
creating directories as needed.
The files are moved using \fIlink()\fP,
so the process is fast and preserves modification times of the files.
As target directories are created,
their ownership and modes are adjusted to be identical to those of the
source directories.
X.sp
\fIDerez\fP uses the access times,
time last \fIread\fP not time last \fIwritten\fP,
of the files to determine their staleness.
The default number of days since last access is 180 days,
but this can be changed using the \fB-t\fP option.
Normally,
derez considers the files not accessed in the specified number of days or more
to be stale.
If the optional \fBe\fP appears,
derez attacks only those files whose access dates are exactly the specified
number of days in the past.
If no directory list is given to derez it searches current directory,
except the subdirectory \fIMORGUE\fP.
The \fB-t\fP option and a directory list can be used to give special handling to
antisocial users.
See the man page for \fIagehist\fP for useful tool in this regard.
Using agehist and the -te option,
unreasonable peaks in the age spectrum of the files can be specifically attacked.
This is done ruthlessly for any user which destroys the access date information
in his files,
whether intentionally or accidentally.
Your files will be removed first,
and then questions will be asked later.
X.sp
One can attempt to defeat derez by using \fIfind\fP and \fIreadbyte\fP to find and read all
of the files in a directory tree.
Using \fIfind\fP and \fIreadbyte\fP to update the access dates of files
is reasonable for some \fIsmall\fP directory that you haven't
looked at in some time, but will be using in a \fIfew days\fP.
Doing this to a large fraction of your files will cause those files to
be archived onto tape and removed from disk.
Updating the staleness date of a directory tree using find and readbyte is not
guaranteed to save the files from derez in any event.
The derez daemon actively uses \fIagehist\fP to find such cases and tends to
have a rather small staleness limit for these files.
The more abnormal the age distribution of a user's files,
the shorter the cutoff date gets.
The system simply does not have enough disk capacity for
archival store and user's are expected to use tape for such purposes.
X.sp
The best way to avoid getting derez'ed is to actively archive your stale files
onto tape using \fItar\fP or \fIrerez\fP and keep them off line.
\fIRerez\fP has the advantage that it remembers access dates,
\fItar\fP does not and assumes the worst possibility.
The current limits used by the derez daemon are 90 days,
with reasonable peaks in the age spectrum being tolerated for 30 days
and antisocial behavior being dealt with instantly and ruthlessly.
The above limits are subject to change,
on a per user basis,
without notice.
We will try to be reasonable.
If you,
however,
are unreasonable and attempt to mung the access date information in your files
we can be more unreasonable than you might imagine.
X.sp
Users should do a clean up of their stale files on a monthly basis
and should actively move files associated with their various projects off line
when these projects become inactive for more than a month or so.
Derez itself is the recommended tool for this work as it does not
modify the access dates of files you want to keep on the disk.
If you don't keep your stale files off line,
the derez daemon will do it for you automatically.
Two copies of each derez tape archive are made and carefully
checked for quality.
This data is probably safer than the data left on the disk.
The second tape archive is kept in a repository.
If some of your files get archived,
and you really need to use them in the next week or so,
simply spool the \fIneeded\fP files back onto disk using \fIrerez\fP,
or \fItar\fP(for the older derez archives).
You should be very careful in doing this it might overwrite any existing files
on the disk.
\fITar\fP sets the access dates to the creation time of the file,
\fIrerez\fP preserves access dates properly on it's archives.
Don't be surprised if the files you spool back onto the disk,
and do not actually use before the next run of \fIderez\fP,
go right back out on tape.
Did they need to be on disk if you didn't use them?
X.sp
The derez daemon is quite young and,
like any newborn,
wakes up whenever it gets hungry.
The derez daemon is implemented using the latest 6'th generation AI technology
and will learn appropriate algorithms to keep the required amount of disk
space free.
Abusive users will be handled on a case by case basis,
with suitable ruthless application of rules which are changed by the
daemon at will.
Abuse of the disk space will not be tolerated.
Large usage is acceptable,
provided that no efforts are made that defeat the operation of derez.
We have enough disk space for everyone to get their work done,
but not a single byte for users to use as archival store.
X.sp
Although derez was written for the derez daemon's use,
an individual user can use it to find and archive his stale files.
This is done by making a subdirectory with the name \fIMORGUE\fP in any directory
you would like to archive the descendant stale files.
You then run \fIderez\fP.
Derez will create a list of stale files,
with the name \fIMORGUE/DEREZ\fP and then move the stale files into the directory
MORGUE.
If a file that is removed is the last file in it's parent directory,
the parent directory is removed.
The contents of the morgue directory can be archived using tar and then removed from the disk.
The use of \fIderez\fP for stale file control is the only foolproof
way to stay ahead of the derez daemon as it leaves the age distribution of
the remaining files on disk unmodified.
Scratch tapes can be found next to the system console.
X.sp
Files that have been derez'ed by the derez daemon can be recovered from the archive tape using
\fIrerez\fP or \fItar\fP as noted on the tape.
You should recover only those files that you are going to use.
Files which you recover and don't use will be archived again at the next
time the derez daemon wakes up.
X.SH SEE ALSO
find, readbyte, agehist, rerez, tar
X.ta 3.0i
X.SH FILES
X/usr/local/morgue/u#.mm.dd.yy	Lists of files derez'ed by the derez daemon.
X.br
MORGUE/DEREZ	The files derez will enmorgue.
X.br
MORGUE/*	The enmorgued files.
X.SH "ARCHIVE TAPES"
The archive tapes with dates matching the above file names are located
next to the dump tapes in the machine room.
These tapes should never be write enabled or removed from the machine room.
A second copy of every archive tape is kept in a repository so any archived
files are secure.
X.SH "Attempts to defeat Derez"
Will NOT be tolerated.
You might save a small handful of files using \fIreadbyte\fP
but that is about it.
It is not recommended to attempt to save a large number of files from
\fIderez\fP.
The \fIderez\fP daemon will detect such attempts and archive the affected
files.
Attempting to save a large number of files using \fIfind\fP and \fIreadbyte\fP
only produces a nice highly visible target for the the derez daemon.
If you want to beat the derez daemon effectively, use derez yourself to clean
your stale files off of the disk.
This should be done monthly with a cutoff date less that that used by
the derez daemon.
X.SH BUGS
DEREZ shares tar's limits on path name lengths.
X.br
MORGUE and DEREZ are reserved names.
X.br
In an ideal world \fIderez\fP would eventually archive itself onto tape.
We don't live in an ideal world.
X.br
Using the recursive (-r) option of cp can get you in serious
trouble as it will caused peaks in the age distribution of your files.
These peaks will be excised at each run of derez.
Use \fItar\fP or \fIrerez\fP to duplicate directory trees.
//go.sysin dd *
if [ `wc -c < derez.1` != 8340 ]; then
	made=FALSE
	/bin/echo 'error transmitting "derez.1" --'
	/bin/echo 'length should be 8340, not' `wc -c < derez.1`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 derez.1
	/bin/echo -n '	'; /bin/ls -ld derez.1
fi
/bin/echo 'Extracting readbyte.1'
sed 's/^X//' <<'//go.sysin dd *' >readbyte.1
X.TH READBYTE LOCAL "2 February 1987"
X.UC 4
X.SH NAME
readbyte \- Read the first byte of a file, removing its staleness
X.SH SYNOPSIS
X.br
\fBreadbyte filename\fP
X.SH DESCRIPTION
X.I Readbyte
reads the first byte of the specified file,
changing its access date.
It is used to remove staleness of a file to prevent derez from
putting the file in the morgue for archival onto tape.
Excessive use of \fIreadbyte\fP, or any other means of updating
the access date of a file to defeat \fIderez\fP,
is interpreted as antisocial by root.
Antisocial behavior is dealt with as described in the man page for \fIderez\fP.
X.SH SEE ALSO
find, derez, agehist
//go.sysin dd *
if [ `wc -c < readbyte.1` != 640 ]; then
	made=FALSE
	/bin/echo 'error transmitting "readbyte.1" --'
	/bin/echo 'length should be 640, not' `wc -c < readbyte.1`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 444 readbyte.1
	/bin/echo -n '	'; /bin/ls -ld readbyte.1
fi
/bin/echo 'Extracting agehist.1'
sed 's/^X//' <<'//go.sysin dd *' >agehist.1
X.TH AGEHIST LOCAL "3 April 1987"
X.UC 4
X.SH NAME
agehist \- Display a histogram of file ages
X.SH SYNOPSIS
X.br
\fBagehist dir [dir2 dir3 ...]\fP
X.SH DESCRIPTION
X.I Agehist
prints a histogram of the age distribution, in days,
of the files in the specified directory trees.
Agehist is the latest in high technology tooling to detect users
that insist on mass use of \fIreadbyte\fP to defeat \fIderez\fP.
The derez daemon,
which is based on the latest 6'th generation AI technology,
enmorgues files which form unreasonable peaks in the age distribution
even though the access date is less than the usual cutoff.
X.SH SEE ALSO
find, derez, readbyte
//go.sysin dd *
if [ `wc -c < agehist.1` != 642 ]; then
	made=FALSE
	/bin/echo 'error transmitting "agehist.1" --'
	/bin/echo 'length should be 642, not' `wc -c < agehist.1`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 444 agehist.1
	/bin/echo -n '	'; /bin/ls -ld agehist.1
fi
/bin/echo 'Extracting rerez.1'
sed 's/^X//' <<'//go.sysin dd *' >rerez.1
X.TH REREZ 1 "10 March 1987"
X.SH NAME
rerez \- tape archiver, that remembers access dates
X.SH SYNOPSIS
X.B rerez
[ key ] [ name ... ]
X.SH DESCRIPTION
X.PP
X.I Rerez
saves and restores multiple files on a single file (usually a magnetic
tape, but it can be any file).  
Rerez is a munged version of \fItar\fP that remembers access dates.
X.IR Rerez 's
actions are controlled by the
X.I key
argument.  The
X.I key
is a string of characters containing at most one function letter and possibly
one or more function modifiers.  Other arguments to 
X.I rerez
are file or directory names specifying which files to dump or restore.
In all cases, appearance of a directory name refers to
the files and (recursively) subdirectories of that directory.
X.PP
The function portion of the key is specified by one of the following letters:
X.TP 8
X.B r
The named files are written on the end of the tape.  The
X.B c
function implies this.
X.TP 8
X.B x
The named files are extracted from the tape.  If the named file
matches a directory whose contents had been written onto the tape, this
directory is (recursively) extracted.  The owner, modification time, and mode
are restored (if possible).  If no file argument is given, the entire content
of the tape is extracted.  Note that if multiple entries specifying the same
file are on the tape, the last one overwrites all earlier.
X.TP 8
X.B t
The names of the specified files are listed each time they occur on
the tape.  If no file argument is given, all of the names on the tape
are listed.
X.TP 8
X.B u
The named files are added to the tape if either they are not
already there or have been modified since last put on the tape.
X.TP 8
X.B c
Create a new tape; writing begins on the beginning of the tape
instead of after the last file.  This command implies
X.BR r .
X.TP 8
X.B o
On output, rerez normally places information specifying owner and modes
of directories in the archive.  Former versions of rerez, when encountering
this information will give error message of the form
X.br
	"<name>/: cannot create".
X.br
This option will suppress the directory information.
X.TP 8
X.B p
This option says to restore files to their original modes,
ignoring the present
X.IR umask (2).
Setuid and sticky information
will also be restored to the super-user.
X.PP
The following characters may be used in addition to the letter
which selects the function desired.
X.TP 10
X.B 0, ..., 9
This modifier selects an alternate drive on which the tape is mounted.
The default is drive 0 at 1600 bpi, which is normally /dev/rmt8.
X.TP 10
X.B v
Normally
X.I rerez
does its work silently.  The
X.B v
(verbose) option makes
X.I rerez
type the name of each file it treats preceded by the function
letter.  With the
X.B t
function, the verbose option
gives more information about the tape entries than just their names.
X.TP 10
X.B w
X.I Rerez
prints the action to be taken followed by file name, then
wait for user confirmation. If a word beginning with `y'
is given, the action is done. Any other input means don't do it.
X.TP 10
X.B f
X.I Rerez
uses the next argument as the name of the archive instead of
X/dev/rmt?.
X.sp
If the file name has the form
X.IR system [. user ]:/dev/???
X.I rerez
will use the tape drive /dev/??? on the remote system
X.IR system ,
via
X.IR rsh (1),
and
X.IR rmt (8).
The optional
X.I user
portion of the pathname specifies the login name to use on the
remote system.
If it is not supplied, the current user's login name will be used.
In all the cases, the user must have the appropriate
permissions on the remote machine, in order to use this facility.
X.sp
If the name of the file is `\-', rerez writes to standard output or
reads from standard input, whichever is appropriate. Thus,
X.I rerez
can be used as the head or tail of a filter chain.
X.I Rerez
can also be used to move hierarchies with the command
X.ce 1
cd fromdir; rerez cf - . | (cd todir; rerez xf -)
X.TP 10
X.B b
X.I Rerez
uses the next argument as the blocking factor for tape records. The
default is 20 (the maximum). This option should only be used with raw magnetic
tape archives (See 
X.B f
above).  The block size is determined automatically
when reading tapes (key letters `x' and `t').
X.TP 10
X.B l
tells 
X.I rerez
to complain if it cannot resolve all of the links to the
files dumped. If this is not specified, no error messages are printed.
X.TP 10
X.B m
tells 
X.I rerez
to print the message ``\fBYou must be joking!\fP'' and exit.
X.TP 10
X.B h
Force 
X.I rerez
to follow symbolic links as if they were normal files or
directories.  Normally, 
X.I rerez
does not follow symbolic links.
X.TP 10
X.B B
Forces input and output blocking to 20 blocks per record.  This option
was added so that 
X.I rerez
can work across a communications channel where the blocking may not
be maintained.
X.PP
If a file name is preceded by 
X.BR \-C ,
then 
X.I rerez
will perform a
X.IR chdir (2)
to that file name.  This allows multiple directories not
related by a close common parent to be archived using short
relative path names.  For example, to archive files from /usr/include
and from /etc, one might use
X.ti +0.5i
rerez c -C /usr include -C / etc
X.PP
Previous restrictions dealing with
X.IR rerez 's
inability to properly handle blocked archives have been lifted.
X.PP
X.SH FILES
X/dev/rmt?
X.br
X/tmp/tar*
X.SH DIAGNOSTICS
Complaints about bad key characters and tape read/write errors.
X.br
Complaints if enough memory is not available to hold the link tables.
X.SH BUGS
There is no way to ask for the
X.IR n -th
occurrence of a file.
X.br
Tape errors are handled ungracefully.
X.br
The 
X.B u
option can be slow.
X.br
The current limit on file name length is 100 characters.
X.br
There is no way to selectively follow symbolic links.
X.br
Using a remote system's tape drive can be slow.
X.SH NOTE
\fIRerez\fP was created in order to have a means of archiving files
on tape in a way that restored their access dates upon extraction.
When \fIrerez\fP is used to extract these files the creation and
access dates are restored to their original values.
If the user does not actually use the files by the next run of \fIderez\fP
the files did not need to be on disk and will be archived again.
\fITar\fP was used for these archives in the past,
but the loss of access dates caused peaks in the age spectrum and
resulted in a rather aggressive derez daemon.
Rerez has been modified to set access dates to be the same as the
creation dates of a files to avoid future problems.
As the creation date of a file may be substantially older than
the date of last access,
users of tar are at somewhat of a disadvantage.
A \fIrerez\fP archive is unfortunately not compatible with tar,
and therefore not portable to other machines.
//go.sysin dd *
if [ `wc -c < rerez.1` != 6645 ]; then
	made=FALSE
	/bin/echo 'error transmitting "rerez.1" --'
	/bin/echo 'length should be 6645, not' `wc -c < rerez.1`
else
	made=TRUE
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 rerez.1
	/bin/echo -n '	'; /bin/ls -ld rerez.1
fi
exit
-- 
For comp.sources.unix stuff, mail to sources at uunet.uu.net.



More information about the Comp.sources.unix mailing list