[net.sources] tapeCheck: check tape quality

johanw@ttdsv.UUCP (Johan Wide'n) (06/06/84)

Here is a small program that writes a pattern repeatedly on a tape.
It then attempts to read the tape. If what is read does not match the
pattern written, an error message is produced.

An error indicates that the tape is bad or that the tape station needs
maintenance.

Warning: No claim is made that this program will catch all tape-errors.

I use it to check backup tapes. It's also a good idea to run it on
new (fresh from the factory) tapes.

When you check a new tape you may get transient errors. That is:
the errors may disappear when you check the tape a second time.
This is related to the quality of the tape station and the tape.

There is one optional argument: maxBlock
This is the number of tape blocks (10 kBytes/block) that will be written.
The argument is useful on tapes with a faulty end of tape marker.
If no argument is given the whole tape up to the end of tape marker is
written.

Further work: The pattern written is chosen only becuse it's easy
to generate. It's probably far from optimal. What is a good test pattern?

{decvax,philabs}!mcvax!enea!ttds!johanw         Johan Widen

--------Cut-at-this-line-----------------------------------
: This is a shar archive.  Extract with sh, not csh.
echo x - tapeCheck.c
cat > tapeCheck.c << '!Funky!Stuff!'
#include <stdio.h>

/*
 * tapeCheck: check tape quality.
 *
 * SYNOPSIS
 *      tapeCheck [maxBlock]
 *
 * writes a pattern on a tape, rewinds the tape and checks that
 * the pattern read is the pattern written.
 * maxBlock is the number of (10 kByte) blocks written.
 *
 * Compile with:
 *      cc -O -o tapeCheck tapeCheck.c
 */

#define BLOCKSIZE 20*512
char    tstPattern[BLOCKSIZE], sample[BLOCKSIZE];
int     tape;
char    tapeDev[] = "/dev/rmt8";

init () {
    register char  *cp;
    char   *endCp;
    register int    i;

    cp = tstPattern;
    endCp = &tstPattern[BLOCKSIZE];
    while (cp < endCp)
	for (i = 1; i <= 128; i++)
	    *cp++ = i;
    tstPattern[BLOCKSIZE - 1] = 0;
    tstPattern[BLOCKSIZE - 2] = 0;
    if ((tape = open (tapeDev, 1)) < 0) {
	fprintf (stderr, "Can't open %s\n", tapeDev);
	exit (-1);
    }
}

main (argc,argv)
int argc; char **argv;
{
    long numBlocks = 0;
    long i;
    register    short * ip1, *ip2;
    long maxBlock = 10000000;

    if(argc > 1) sscanf(argv[1],"%ld",&maxBlock);
    if(maxBlock <= 0L) {
	fprintf(stderr,"usage: %s [ maxBlock ]\n", argv[0]);
	exit(-1);
    }
    init ();
    while (write (tape, tstPattern, BLOCKSIZE) == BLOCKSIZE) {
	numBlocks++;
	if(numBlocks >= maxBlock) break;
    }
    if (numBlocks < 10) {
	fprintf (stderr, "Can't write %s\n", tapeDev);
	exit (-1);
    }
    fprintf (stderr, "wrote %ld*20 blocks\n", numBlocks);
    close (tape);
    while ((tape = open (tapeDev, 0)) < 0)
	sleep (10);
    sleep(10);
    for (i = 0; i < numBlocks; i++) {
	if (read (tape, sample, BLOCKSIZE) != BLOCKSIZE) {
	    fprintf (stderr, "read failed: block %ld*20\n", i + 1);
	    exit (-1);
	}
	ip1 = (short *) tstPattern;
	ip2 = (short *) sample;
	while (*ip1)
	    if (*ip1++ != *ip2++) {
		fprintf (stderr, "bad block: %ld*20 %d\n", i + 1,
			 ((char *) ip1) - tstPattern);
		break;
	    }
	if (!*ip1 && *ip2)
	    fprintf (stderr, "bad block: %ld*20\n", i + 1);
    }
}
!Funky!Stuff!