[comp.unix.ultrix] Copying a TK50 tape under Ultrix

cliffb@isavax.isa.com (cliff bedore*) (01/13/91)

In article <422@opus.NMSU.Edu> sberger@nmsu.edu ( Steve Berger ) writes:
>I'm trying to copy the boot tape that I have for Ultrix.
>
>We had our original TK50 get trashed in the tape drive,
>now I have a new one and I want to make a backup copy of it
>so I can use the copy and save my original.
>
>Could someone kindly send me the correct command sequence
>to copy a bootable TK50 tape?
>
>I imagine it can be done with dd  but I can't figure out
>which parameters to use.
>
>Thanks,
>
>Steve Berger
>
>sberger@nmsu.edu

I had the same problem with a different tape but the logic below should
work.  The distr tapes have a variety of file lengths and block sizes so you
need the program tape map supplied below by a kind gentleman.  I use it to
create a tape log of block sizes using tapemap and then read the tape using
the shell script readtape naming all the files sequentially (1, 2 etc). I
then used the shell program writetape to write the files back out in
numerical order and voila a copy of the tape.  I lay no claim to originality
but it does work on any arbitrary tape thanks almost completely to the
tapemap program supplied to me by the gentleman whose name i'v forgotten but
his mail address is included below.

Cliff

readtape

#!/bin/csh -f
set count=1
foreach filedes (`cat filedata | cut -f3`)
#foreach filedes (`cat filedata `)
 /bin/echo " $count   $filedes"
 dd if=/dev/nrmt0h of=/e/cliffb/brad/$count bs=$filedes
 @ count++
end

writetape

#!/bin/csh -f
set count=1
foreach filedes (`cat filedata | cut -f3`)
#foreach filedes (`cat filedata `)
 /bin/echo " $count   $filedes"
 dd if=/e/cliffb/brad/$count of=/dev/nrmt0h bs=$filedes
 @ count++
end



From uunet!sbphy!hbo Fri Dec 21 22:27:05 1990
Received: by isavax.ISA.COM (5.57/UUCP-Project/02.16.86)
	id AA16773; Fri, 21 Dec 90 22:26:59 EST
From: uunet!sbphy!hbo
Received: from sbphy.ucsb.edu by uunet.uu.net (5.61/1.14) with SMTP 
	id AA13276; Fri, 21 Dec 90 19:35:58 -0500
Received: from localhost by sbphy with SMTP (5.61/PCS-v1.0-eef)
	id AA01014; Fri, 21 Dec 90 16:38:29 -0800
Message-Id: <9012220038.AA01014@sbphy>
To: wdg@gatech.edu, isavax!cliffb, rtc@westford.ccur.com,
        jmoore@ecn.purdue.edu, jrr%beta@LANL.GOV
Subject: Tapemap
Date: Fri, 21 Dec 90 16:38:28 PST
Status: OR

#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./tapemap.c`
then
echo "writing ./tapemap.c"
cat > ./tapemap.c << '\End\Of\Shar\'
/*
 * Constraints on MAX_BLKSIZE:
 * - MAX_BLKSIZE % 512 == 0
 * - MAX_BLKSIZE <= 65536
 * - (int)MAX_BLKSIZE > 0
 */
#define	MAX_BLKSIZE	64512

#include <stdio.h>

extern int      optind;

#define	ERROR		(-1)

main(argc, argv)
	int             argc;
	char          **argv;
{
	int             fd;
	int             opt;
	int             verbose = 0;

	while ((opt = getopt(argc, argv, "v")) != EOF) {
		switch (opt) {
		case 'v':
			verbose = 1;
			break;

		default:
			(void) printf("Usage: %s [ -v ] device\n", argv[0]);
			exit(1);
		}
	}

	if (argv[optind] == NULL) {
		(void) printf("Usage: %s [ -v ] device\n", argv[0]);
		exit(1);
	}

	fd = open(argv[optind], 0);
	if (fd == ERROR) {
		perror(argv[optind]);
		exit(1);
	}

	setlinebuf(stdout);
	exit(tapemap(fd, verbose));
}

tapemap(fd, verbose)
	int             fd;
	register int    verbose;
{
	register int    blk;		/* last successful block #	 */
	register int    blksize;	/* current block size		 */
	char            buf[MAX_BLKSIZE];	/* read buffer		 */
	int             file;		/* current file #		 */
	int             maxsize;	/* max block size		 */
	int             minsize;	/* min block size		 */
	register int    eofcount;	/* # consecutive EOF's read	 */

	if (verbose) {
		(void) printf("file\tblock\tsize\n");
		(void) printf("----\t-----\t-----\n");
	}
	else {
		(void) printf("file\tblocks\tsize range\n");
		(void) printf("----\t------\t----------\n");
	}

	for (eofcount = 0, file = 1;; ++file) {
		if (!verbose) {
			maxsize = 0;
			minsize = sizeof(buf);
		}

		for (blk = 0; (blksize = read(fd, buf, sizeof(buf))) > 0;) {
			++blk;
			eofcount = 0;

			if (verbose) {
				(void) printf("%d\t%d\t%d\n",
					      file, blk, blksize);
			}
			else {
				if (blksize > maxsize) {
					maxsize = blksize;
				}

				if (blksize < minsize) {
					minsize = blksize;
				}
			}
		}

		if (blksize < 0) {
			(void) printf("read error: file %d block %d\n",
				      file, blk + 1);
			return (1);
		}
 /*
  * if we get here, we just read an EOF
  */
		if (++eofcount > 1) {
			break;		/* end of tape */
		}

		if (!verbose) {
			(void) printf("%d\t%d\t%d", file, blk, minsize);

			if (maxsize > minsize) {
				(void) printf("\t%d", maxsize);
			}

			putchar('\n');
		}
	}

	return (0);
}
\End\Of\Shar\
else
  echo "will not over write ./tapemap.c"
fi
if `test ! -s ./tapemap.1`
then
echo "writing ./tapemap.1"
cat > ./tapemap.1 << '\End\Of\Shar\'
.TH TAPEMAP 1 "20 January 1988" "UCSB CSL"
.SH NAME
tapemap \- map a mystery tape
.SH SYNOPSIS
.B tapemap
[
.B \-v
] device
.SH DESCRIPTION
.I Tapemap
reads the tape mounted on
.IR device ,
producing one line of output for each file on the tape.
The output format is:
.IP
file#<tab>#blocks<tab>max-blocksize<tab>min-blocksize
.PP
File and block numbers start at 1.
Block sizes are given in bytes.
.SH OPTIONS
.TP
.B \-v
verbose mode.
Superseding the default output,
one line of output is printed for each block on the tape.
The output format is:
.IP
file#<tab>record#<tab>blocksize
.\".SH FILES
.\".SH SEE ALSO
.SH DIAGNOSTICS
.B
read error: file
.I f
.B block
.I b
.PP
Plus the usual \*(lqcan't open ...\*(rq\-type stuff.
.SH AUTHOR
J. Frew,
Computer Systems Laboratory,
UCSB
.SH BUGS
Tape blocks longer than
64512
bytes will cause read errors.
.PP
.IR Tapemap 's
output is silly (but harmless) if
.I device
is not a tape drive.
\End\Of\Shar\
else
  echo "will not over write ./tapemap.1"
fi
echo "Finished archive 1 of 1"
exit