john@x.UUCP (John Woods) (05/08/85)
Due to a surprising number of requests for the CCC tape tester program, I am submitting it for your amusement. It worked well for a number of years at CCC, testing scavenged tapes on scavenged hardware... -------------chop--slice--grate--and--cut--here---------------------------- echo extract with sh, not csh echo x README cat > README << '!Funky!Stuff!' This is the tape testing program from the Concourse Computer Center at the Massachussetts Institute of Technology. I believe it was originated by Mark Plotnick, but most of the CCC crowd has had a hand in doing things to it since then. Arguments to it are: -v Verbose, tells what's going on (quite chatty) -n Nice, renices itself and does a lot of sleep(2)ing. This flag may be repeated for increased effect. -r Set the record size of testing. -o Set the initial offset from beginning of tape (which is achieved by doing a write that large). -f Change the default drive from /dev/rmt0. tptest writes a pattern out to the tape in uniform blocks until an error occurs (which is assumed to be End of Tape). It then rewinds and tries to verify the pattern. Then, a second pass writes a short block at the beginning of the tape and then writes the pattern to end of tape; this verifies (or tries to verify) that the tape in the inter-record-gaps of the first pass is OK. When it is all done, if the tape was OK, it gets a sequence number from /usr/lib/tapeseq and tells it to you (so you can uniquely label tapes). We generally ignored this after the first few dozen, but it seemed a keen idea at first. This program ran under V7 and 2.8BSD, on our IBM 729 tape drive (7 track, 200/556/800 bpi, well over a half-ton weight!) and on a slightly more modern TU-10. The tapeopen() routine assumes that if it can't open the tape drive, it must be rewinding. Those with different drivers may need to change that. John Woods, ihnp4!mit-eddie!jfw, decvax!frog!john !Funky!Stuff! echo x makefile cat > makefile << '!Funky!Stuff!' CFLAGS = -O tptest: tptest.o cc -o tptest tptest.o install: tptest cp tptest /usr/lbin clean: rm *.o tptest !Funky!Stuff! echo x tptest.c cat > tptest.c << '!Funky!Stuff!' #include <stdio.h> #define DFLTRECSIZE 5120 #define DFLTOFFSET 2048 #define MAXRECSIZE (5120*4) #define SLEEPEVERY 10 char buf[MAXRECSIZE]; char pattern[MAXRECSIZE]; int Recsize = DFLTRECSIZE; struct flags { int slow; int verbose; } Flags; int Tapefd, Seed; char *drivename = "/dev/rmt0"; /* default drive name */ genpat(seed) { register int i = Recsize; register char *patp = pattern; register char *p = buf; seed += Seed; while(--i) { *patp++ = seed++ /* & 0377 */ ; *p++ = 0; } patp = pattern; strncpy(patp,"tptest",6); } check() { register int i = Recsize; register char *patp = pattern; register char *p = buf; while(--i) if (*patp++ != *p++) return (-1); return (0); } main(argc,argv) int argc; char **argv; { int nrecords; int offset = DFLTOFFSET; long time(); if (getuid()) nice(20); close(2); dup(1); setbuf(stdout, NULL); /* both stdout and stderr go to same place and are unbuffered */ printf("pid %d\n",getpid()); while (argc > 1 && argv[1][0]=='-') { switch(argv[1][1]) { case 'n': Flags.slow++; break; case 'v': Flags.verbose++; break; case 'r': Recsize = atoi(&argv[1][2]); if (Recsize <= 0 || Recsize > MAXRECSIZE) { printf("recsize %d too large\n", Recsize); exit(1); } break; case 'o': offset = atoi(&argv[1][2]); if (offset <= 0 || offset > MAXRECSIZE) { printf("offset %d too large\n", offset); exit(1); } if (offset > DFLTRECSIZE) printf("offset %d is rather large\n", offset); break; case 'f': drivename = &argv[1][2]; break; } argv++, argc--; } printf("slow=%d, Recsize=%d, offset for pass2 = %d\n", Flags.slow, Recsize, offset); printf("Pass 1:\n"); Seed = (int)time((char *)0); if (Flags.verbose) printf("Seed=%d\n", Seed); tapeopen(1, 0); nrecords = tapewrite(0); /* test with an offset of 0 */ tapeopen(0, 10); taperead(0, nrecords); printf("Finished pass 1\n"); tapeopen(1, 10); printf("Beginning pass 2\n"); Seed = (int)time((char *)0); if (Flags.verbose) printf("Seed=%d\n", Seed); nrecords = tapewrite(offset); tapeopen(0, 10); taperead(offset, nrecords); printf("finished pass 2\nDone, no errors\n"); newseqnumber(); exit(0); } tapewrite(offset) { int nrecords, n; long tplength = 0; printf("Writing...\n"); if (Flags.verbose) printf("offset=%d\n", offset); if (offset) write(Tapefd, buf, offset); /* who cares what buf contains? */ for(nrecords=0;;nrecords++) { genpat(nrecords); if ((n=write (Tapefd,pattern,Recsize))!=Recsize) { if (n == -1) perror("Tape write error (presumably EOT)"); /* this isn't fatal, really...*/ break; } if (Flags.verbose) printf("w"); tplength += Recsize; if (Flags.slow && ((nrecords%SLEEPEVERY) == 0)) { sleep(Flags.slow); if (Flags.verbose) printf("s"); } } printf ("%d records, unformatted tape length = %ld bytes\n", nrecords, tplength); printf("Finished writing; Rewinding...\n"); close (Tapefd); return(nrecords); } taperead(offset, nrecords) { register int r2, n; printf ("Reading ...\n"); if (Flags.verbose) printf("offset=%d, nrecords=%d\n", offset, nrecords); if (offset) read(Tapefd, buf, offset); for (r2=0;r2<nrecords;r2++) { genpat(r2); if ((n=read(Tapefd,buf,Recsize)) != Recsize) { if (n == -1) perror("Read error"); else printf ("recsiz error, record %d;", r2), printf ("actual=%d, expected=%d\n", n, Recsize); exit(3); } if (Flags.verbose) printf("r"); if (check()<0) { printf ("data error: record %d\n", r2); exit(4); } if (Flags.slow && ((r2%SLEEPEVERY) == 0)) { sleep(Flags.slow); if(Flags.verbose) printf("s"); } } printf("Done reading; Rewinding...\n"); close(Tapefd); } newseqnumber() { FILE *seqfd; int seqnum; if ((seqfd=fopen ("/usr/lib/tapeseq","r+")) == NULL) { printf ("warning: creating new sequence file\n"); umask(000); close(creat ("/usr/lib/tapeseq",0666)); seqfd = fopen ("/usr/lib/tapeseq","r+"); fprintf(seqfd, "0"); rewind(seqfd); } fscanf (seqfd,"%d",&seqnum); rewind(seqfd); fprintf(seqfd,"%d\n",seqnum+1); printf("Sequence number = %d\n", seqnum+1); fclose (seqfd); } tapeopen(mode, sleeptime) { if (Flags.verbose) printf("mode=%d, sleeptime=%d\n", mode, sleeptime); if (sleeptime==0) { /* means die if can't open immediately */ Tapefd = open (drivename, mode); if (Tapefd == -1) { perror("Can't open tape drive"); exit(2); } else return; } while ((Tapefd=open(drivename, mode)) < 0) { if(Flags.verbose) printf("s"); sleep(sleeptime); } return; } !Funky!Stuff! exit 0 -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA "MU" said the Sacred Chao...