1 EXTEND 2 ! TAPCOP == Copy from one magtape to another & ! & ! This program copies the entire contents of one tape to one or & ! more other tapes or inplace to the same tape. Density may be & ! specified as 800 or 1600 BPI. & ! & ! If "RECOVER" is entered in response to the first prompt, the & ! input tape will not be read, but the output tape(s) will be & ! written using the data previously read from the input tape. & ! & ! This program is provided by Cluster Technology Corp. as a service to & ! the RSTS community. It is provided "AS IS" with no warranties, & ! expressed or implied. & ! & ! Author: & ! Michael Mayfield & ! & ! Edit History: & ! 00 24-May-85 MEM Original version & ! 01 12-May-86 MEM Update for new RSTS versions & ! & ! RSTS Version: & ! V8.0-H, V9.0, V9.1 & ! & ! Variable Usage: & ! BELL$ Constant value of a bell & ! COPIES% Number of copies of input tape & ! COPY.LOOP% Loop counter for making multiple tape copies & ! DATCHN% Channel number for tape data storage I/O & ! DENSITY% Output tape density & ! DEVICE$ Device and account to open tape data files in & ! LENCHN% Channel number for record length data I/O & ! RECLEN% Length of current tape record & ! TAPCHN% Channel number for tape I/O & ! Z% Temporary variable & ! Z$ Temporary variable & 10 DEVICE$="SY:" !Temp file storage device & \ TAPCHN%=1% & \ LENCHN%=2% & \ DATCHN%=3% & \ BELL$=CHR$(7%) & \ ON ERROR GOTO 32000 & ! Define channel numbers for tape I/O, record length file, and & ! tape data file. Enable error trapping. & 100 PRINT "TAPCOP V1.1 == Tape Copy Utility" & \ PRINT & \ INPUT "Mount the tape to copy FROM and press RETURN"; Z$ & \ OPEN "MT0:" FOR INPUT AS FILE TAPCHN%, RECORDSIZE 40%*512% & \ Z%=INSTR(1%,Z$,":") & \ IF Z% THEN & DEVICE$=LEFT(Z$,Z%) & \ Z$=RIGHT(Z$,Z%+1%) 105 IF CVT$$(Z$,-1%)="RECOVER" THEN & PRINT "[Using previous tape data]" & \ RECOVER%=-1% & \ GOTO 125 110 !ELSE & INPUT "Input tape density <1600>"; Z% & \ Z%=FNC.DENSITY%(Z%,1600%) & \ GOTO 110 IF Z%=0% & \ Z%=MAGTAPE(6%,Z%,TAPCHN%) & \ Z%=MAGTAPE(3%,0%,TAPCHN%) & \ OPEN DEVICE$+"TAPREC.TMP" AS FILE LENCHN%, & CLUSTERSIZE 32%, & FILESIZE 32% & \ OPEN DEVICE$+"TAPDAT.TMP" AS FILE DATCHN%, & RECORDSIZE 2% OR NOT(32767%), & CLUSTERSIZE 256%, & FILESIZE 256%*7% & ! Announce ourselves. Ask for the input tape to be mounted. & ! If "RECOVER" was entered in response to the prompt for the input & ! tape, use the data file created by the last use of the TAPCOP. & ! Open the tape for input. Get input tape density from user. & ! Create our work files. & 120 COPIES%=1% & \ INPUT "Is the copy going to be stored on the same tape "; Z$ & \ Z$=CVT$$(Z$,-1%) & \ Z$="Y" IF Z$="" & \ IF LEFT(Z$,1%)="Y" THEN & SAME.TAPE%=-1% & ELSE & IF LEFT(Z$,1%)="N" THEN & SAME.TAPE%=0% & ELSE & PRINT "?Please enter YES or NO" & \ GOTO 120 125 INPUT "Output tape density <1600>"; Z% & \ DENSITY%=FNC.DENSITY%(Z%,1600%) & \ GOTO 125 IF DENSITY%=0% & \ INPUT "Number of copies <1>"; COPIES% IF NOT SAME.TAPE% & \ GOTO 200 IF RECOVER% & \ PRINT "[Copying source tape to disk]" & ! See if we are using more than one reel of tape. See what density & ! to use for the output. If using more than one reel of tape, see & ! how many copies we need. Skip reading the input tape on a recovery. & 130 GET #TAPCHN% & \ RECLEN%=RECOUNT 140 PRINT #LENCHN%, RECLEN% & \ PUT #DATCHN%+SWAP%(TAPCHN%), COUNT INT((RECLEN%+511%)/512%)*512% & \ EOF%=0% & \ GOTO 130 & ! Get the next record from the tape (EOF goes to 32000). & ! Record the length. Store the data in the temp file using & ! block I/O. Reset the "just read an EOF" flag. Repeat until & ! two EOFs read in a row (EOT). & 200 COPIES%=1% IF COPIES%<=0% & \ FOR COPY.LOOP%=1% TO COPIES% & \ IF NOT SAME.TAPE% THEN & PRINT BELL$; IF COPY.LOOP%>1% & \ PRINT "Mount the "; & \ PRINT "next "; IF COPY.LOOP%>1% & \ PRINT "tape to copy TO and press RETURN"; & \ INPUT LINE Z$ 210 PRINT "[Creating output tape]" & \ CLOSE LENCHN%, DATCHN% & \ OPEN DEVICE$+"TAPREC.TMP/RO" FOR INPUT AS FILE LENCHN% & \ OPEN DEVICE$+"TAPDAT.TMP/RO" FOR INPUT AS FILE DATCHN%, & RECORDSIZE 2% OR NOT(32767%) & \ Z%=MAGTAPE(6%,DENSITY%,TAPCHN%) 220 INPUT #LENCHN%, RECLEN% & \ GOTO 240 IF RECLEN%=-2% & \ IF RECLEN%=-1% THEN & Z%=MAGTAPE(2%,0%,TAPCHN%) & ELSE & GET #DATCHN%+SWAP%(TAPCHN%), & COUNT INT((RECLEN%+511%)/512%)*512% & \ PUT #TAPCHN%, COUNT RECLEN% 230 GOTO 220 240 Z%=MAGTAPE(2%,0%,TAPCHN%) & \ Z%=MAGTAPE(1%,0%,TAPCHN%) & \ NEXT COPY.LOOP% & \ KILL DEVICE$+"TAPREC.TMP" & \ KILL DEVICE$+"TAPDAT.TMP" & \ CLOSE #TAPCHN%, LENCHN%, DATCHN% & \ PRINT BELL$; "Finished" & \ PRINT & \ GOTO 32767 & ! All errors are fatal now. For each record originally read & ! from tape... Get the record length. If EOT flag (-2), then & ! finish this tape and do the next one, if any. If EOF flag & ! (-1) then write an EOF, else get the stored data and write & ! it. After writing all records, write third EOF and & ! rewind/offline the tape. Repeat for any additional copies of & ! the tape. Kill our temp files and we're done. & 10000 ! FNC.DENSITY% == Parse magtape density value & ! & ! Returns a the value to use to set the required density in the & ! MAGTAPE() function. & ! & ! Input: & ! VALUE% Value to parse (800, 1600, default, or error) & ! DEFAULT% Default density if VALUE%=0 & ! & ! Output: & ! FNC.DENSITY% MAGTAPE() function parameter value. Returned & ! as 0 if no valid valid passed in VALUE%. & & DEF* FNC.DENSITY%(VALUE%,DEFAULT%) & \ VALUE%=DEFAULT% IF VALUE%=0% & \ IF VALUE%=800% THEN & FNC.DENSITY%=12% & ELSE & IF VALUE%=1600% THEN & FNC.DENSITY%=256% & ELSE & PRINT "?Invalid density. Please enter 800 or 1600." & \ FNC.DENSITY%=0% 10010 FNEND & ! Use default value if no density specified. Use a value of 12 for & ! 800 BPI and 256 for 1600 BPI. Return 0 for invalid density. & 32000 ! ERROR TRAPPING & 32010 IF (ERR=11% AND ERL=100%) THEN & CLOSE TAPCHN%, LENCHN%, DATCHN% & \ RESUME 32767 & ! If ^Z or ^C, close our temp files and exit. & 32020 IF ERR=11% AND EOF%=0% THEN & EOF%=-1% & \ PRINT #LENCHN%, -1% & \ RESUME 130 & ! EOF while reading magtape: & ! If the last record was not also an EOF, write an "EOF read" & ! flag to the record length file and count it as a record. & 32030 IF ERR=11% AND EOF%<>0% THEN & PRINT #LENCHN%, -2% & \ Z%=MAGTAPE(3%,0%,TAPCHN%) IF SAME.TAPE% & \ Z%=MAGTAPE(1%,0%,TAPCHN%) IF NOT SAME.TAPE% & \ CLOSE LENCHN%, DATCHN% & \ RESUME 200 & ! End of tape (EOT) detected by at least two tape marks. & ! Record the EOT point in the record length file. Rewind or & ! Rewind/offline the tape. Change tape density. Continue & ! with second half of copy operation. & 32040 IF ERR=13% THEN & RECLEN%=RECOUNT & \ PRINT "%"; BELL$; BELL$; BELL$; & "Data error reading tape. Continuing..." & \ RESUME 140 & ! DATA ERROR ON DEVICE: & ! Print a warning message but continue on as if nothing & ! happened. & 32099 CLOSE #LENCHN%, DATCHN% & \ ON ERROR GOTO 0 & ! Any other error is fatal. & 32767 END