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