[comp.unix.sysv386] using SCSI tape in read/write mode

del@fnx.UUCP (Dag Erik Lindberg) (11/07/90)

I have decided to write a tape archiving utility and am having some
problems figuring out how to use the tape drive. Some background:

What I need is approximately the functional equivalent of 'tar r'
to append files to the end of an archive tape.  Unfortunately, 'tar r'
does not allow blocking factors, and without the blocking start/stop
of the tape is absurd.  While the lost data from inter-record spacing
is not a problem, time to write a file and wear-and-tear on the drive
are objectionable.

I have come up with several approaches for this utility, and I am
currently favoring writing a (fixed size) tape directory to the
front of the tape with pointers to the files on the tape and the
start point for the next file to be written.

Here is the problem:

1) If I make a loop to write 30 x 1k records containing "Record #x",
   rewind the tape, and read 30 records, printf()ing each, there 
   is no problem.  Rewind again, read 15 records, write one record
   containing "Record 15 modified" and rewind the tape.  Now read
   30 records and printf().  Hmmm, nobody got modified.  The write()
   did not return an error.  What am I doing wrong?
2) I have used ioctl()'s to write EOF marks to the tape, and then
   tried to skip 'x' of them with the appropriate ioctl().  This
   does not seem to get me to the correct record #.  For example,
   I write 30 x 1k records containing only "Record #x", with an
   ioctl() in between each one, rewind the tape, then skip 15 of
   them.  Read one and printf the contents.  I seem to come up 
   around #10.

The system is ISC 2.0.2, the tape drive is an Archive 2150s on 1542.
I don't have the code around anymore which demonstrates #2 above, but
here is the hack I've been using to experiment with #1:


#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/gentape.h>

#define NUMRECS 30

struct tc_parms tcp;

main()
{
	char buf[1024],buf1[1024];
	int fd, x;
	/* Note that I am opening the tape in read/write mode. */
	fd = open("/dev/mt0",O_RDWR|O_EXCL);
	strcpy(buf1,"This is a string in the tape output buffer.\n");
	ioctl(fd,TC_REWIND);
	/* Initialize the tape with 30 records. */
	for (x=0; x<NUMRECS; x++) {
printf("Writing buffer %d.\n",x);
		sprintf(buf1,"This is new buffer #%d\n",x);
		if (write(fd,buf1,1024) < 1024)
			printf("Error on write.\n");
#if 0		/* I tried this once to see if I could make file marks. */
		close(fd);
		open("/dev/nmt0",O_RDWR|O_EXCL|O_SYNC);
#endif
	}
  	/* Now done writing the the 30 records.  I am not currently closing
   	   the tape device, but my experience so far indicates it doesn't
	   really make any difference.
	*/
printf("Rewinding\n");
	ioctl(fd,TC_REWIND);

	/* What I want to do here is change one record approximately half
	   way through the tape.  Note that I don't really care if any
	   of the data past the point I make the write operation is
	   trashed, since my application will only ever *append* to the
	   tape.  The point is that I can't get the write() to do
	   anything.
	*/
	for (x=0; x<NUMRECS/2; x++) {
		int err;
		err = read(fd,buf,1024);
		if (err < 1024) {
printf("Error on read...\n");
			ioctl(fd,TC_SEOF,1);
			read(fd,buf,1024);
		}
		printf("Read: %s",buf);
	}
printf("Writing overlay buffer...\n");
	/* This doesn't seem to do anything usefull.... */
	ioctl(fd,TC_WFM);
	/* Either does this :-) */
	ioctl(fd,TC_GETPARMS,&tcp);
	printf("speed: %d, flags: %x, type: %d, recsize: %d\n",
		tcp.tcp_speed, tcp.tcp_flags, tcp.tcp_medtype, tcp.tcp_recsiz);
	strcpy(buf1,"Overlayed buffer.");
	
	/* Neither of these writes gives an error. */
	if (write(fd,buf1,1024) < 1024)
		printf("Error on first write.\n");
	if (write(fd,buf1,1024) < 1024)
		printf("Error on second write.\n");

printf("Rewind...\n");
	ioctl(fd,TC_REWIND);
	/* Note that all the records are read back.... none are changed. */
	for (x=0; x<NUMRECS; x++) {
		int err;
		err = read(fd,buf,1024);
		if (err < 1024) {
printf("Error on read...\n");
			ioctl(fd,TC_SEOF,1);
			read(fd,buf,1024);
		}
		printf("Read: %s",buf);
	}
	ioctl(fd,TC_REWIND);
}

So, the question comes down to, how does tar do it?  I have tried tar, and
it does in fact append to an archive, it just takes so long to get to the
end of the archive I can't even imagine trying to add a file to the end
of a 130 Meg collection.  Everything I try just seems to drop the bits
in a bucket somewhere...  Suggestions appreciated...


-- 
del AKA Erik Lindberg                             uunet!pilchuck!fnx!del
                          Who is John Galt?

bruce@triada.UUCP (Bruce Germolus) (11/08/90)

the first track.  Refer to the Viper(r) SCSI Models 60S, 125S, and 150S
Subject: Re: using SCSI tape in read/write mode
Summary: Don't update blocks on streaming tapes...
Expires: 
References: <755@fnx.UUCP>
Sender: 
Reply-To: bruce@triada.UUCP (Bruce Germolus)
Followup-To: 
Distribution: 
Organization: Triad Systems Corporation, Livermore, CA
Keywords: I'm confused

In article <755@fnx.UUCP> del@fnx.UUCP (Dag Erik Lindberg) writes:
> [some background deleted]
>1) If I make a loop to write 30 x 1k records containing "Record #x",
>   rewind the tape, and read 30 records, printf()ing each, there 
>   is no problem.  Rewind again, read 15 records, write one record
>   containing "Record 15 modified" and rewind the tape.  Now read
>   30 records and printf().  Hmmm, nobody got modified.  The write()
>   did not return an error.  What am I doing wrong?
>
Updating blocks on streaming tapes of this type is *not* a good thing.
The update is not guaranteed to work due to the device's handling of
under-runs and bad blocks on the media (it re-writes duplicate blocks).
In addition, there is an erase head that is activated when writing to
the first track.  Refer to the Viper(r) SCSI Models 60S, 125S, and 150S
1/4-inch Streaming Cartridge Tape Drive "Theory of Operation and
Maintenance Manual" (Archive Manual Part Number 21981-001, rev B.,
sections 6.2.2, 6.3.2, and 6.8.1 contain the relavant material).
The only safe write operations to these devices is appending files to
the end of the tape or overwriting a tape with a new set of files.

>The system is ISC 2.0.2, the tape drive is an Archive 2150s on 1542.
>
With ISC 2.2, with respect to SCSI streaming tapes, write(2) will not
report errors it encounters (neither will read(2) for that matter).
These are known problems (at least here and at ISC).  My hunch is that
ISC 2.0.2 *MAY* contain the same problems, BUT I AM NOT SURE.
>
>-- 
>del AKA Erik Lindberg                             uunet!pilchuck!fnx!del
>                          Who is John Galt?
***************************Views*are*mine*not*TRIAD's***************************
Bruce Germolus                   Livermore, CA (USA) 94550-9559  
TRIAD Systems Corporation        415/449-0606                     
mavrik!bruce@lll-winken.llnl.gov 
-- 
***************************Views*are*mine*not*TRIAD's***************************
Bruce Germolus                   Livermore, CA (USA) 94550-9559  
TRIAD Systems Corporation        415/449-0606                     
mavrik!bruce@lll-winken.llnl.gov