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?