.TITLE CPY -- WRITE LARGE BLOCKED FILES .IDENT -000100- ;+ ; ABSTRACT: CPY ; THIS PROGRAM WILL WRITE A FILE FROM ONE DISK TO ANOTHER ; OR TO THE SAME ONE USING MULTI-BLOCK READS AND WRITES. ; ; OPERATING PROCEDURES: ; MCR>RUN CPY$ ; CPY>DEV:OUTFILE=DEV:INFILE ; CPY>^Z ; MCR> ; ; SWITCHES: ; ; /CO FILE IS TO BE CONTIGUOUS. IF THE INPUT FILE IS ; CONTIGUOUS, THIS IS THE DEFAULT; IF IT IS NOT, ; THEN THE DEFAULT IS /-CO. ; (NOTE: THIS AND /CP APPLY ONLY TO THE EXTEND ; OPERATION ON THE FILE. FOR A NEW FILE, /CO WILL ; IN FACT PRODUCE A CONTIGUOUS FILE, BUT FOR AN OLD ; FILE PROCESSED WITH THE /UP SWITCH, ALL THAT IS ; GUARANTEED IS THAT ANY NECESSARY EXTEND WILL BE ; DONE CONTIGUOUSLY). ; /CP FILE IS TO BE "AS CONTIGUOUS AS POSSIBLE" ; WITHOUT NECESSARILY BEING CONTIGUOUS. ; /SU FILE IS TO SUPERSEDE ANY EXISTING OUTPUT FILES. ; /UP OUTPUT FILE IS TO BE OPENED IN UPDATE MODE. ; /NV FILE IS TO BE FORCED TO NEXT VERSION NUMBER. ; ; FILES: ; OUTFILE THE OUTPUT FILENAME (DEFAULTS TO SY0:) ; INFILE THE INPUT FILENAME (DEFAULTS TO SY0:.LST) ; ; ERRORS: ; COMMAND STRING ERRORS ARE SELF-EXPLANATORY. IF AN ERROR ; OCCURRS ON THE FILES PROCESSED, THE ERROR CODE WILL BE ; PRINTED. ALL ERRORS ARE REPORTED TO TI: ONLY. ; ; LIMITATIONS: ; AS NOTED IN THE NOTE ABOVE UNDER "OPERATING PROCEDURES" ; ; ALSO, NOTE THAT A BLOCKING FACTOR OF 64. BLOCKS IS NOT ; POSSIBLE, REGARDLESS OF WHAT THE I/O OPERATIONS ; REFERENCE MANUAL SAYS. IF YOU TRY TO SPECIFY A LENGTH ; OF 32767. ON THE READ$/WRITE$ OPERATION, NO I/O WILL ; ACTUALLY TAKE PLACE, AND IF YOU SPECIFY A LENGTH OF ; 32768., YOU WILL GET AN FCS ERROR OF "INVALID OPERATION ; ON FDB". ; ; WRITTEN: ; BRUCE C. WRIGHT ; CLINICAL EPIDEMIOLOGY LABORATORY ; DUKE UNIVERSITY MEDICAL CENTER ; DURHAM, N. C. 27710 ; 01-OCT-78 ; MODIFIED: 22-JAN-79, -0.1.0-, BRUCE C. WRIGHT ; ADDED /SU, /UP, AND /NV SWITCHES, MADE "OUTFILE NAME" DEFAULT TO ; "INFILE NAME" TO BE MORE COMPATIBLE WITH ...PIP. ; VERIFIED: 22-JAN-79, -0.1.0-, BRUCE C. WRIGHT ;- .SBTTL MACRO CALLS .MCALL EXIT$S,QIOW$ .MCALL OPNS$R,OPEN$,CLOSE$,FINIT$,DELET$ .MCALL READ$,WRITE$,WAIT$ .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2,CSI$SW,CSI$ND .MCALL FDAT$R,FDRC$R,FDOP$R,FDBF$R,FDBK$R .MCALL FSRSZ$,FDBDF$,NMBLK$,BDOFF$ .MCALL FHDOF$,NBOFF$,FDOFF$,FCSBT$ FHDOF$ DEF$L ;DEFINE FILE HEADER OFFSETS. NBOFF$ DEF$L ;DEFINE FILENAME BLOCK OFFSETS. FDOFF$ DEF$L ;DEFINE FDB OFFSETS. FCSBT$ DEF$L ;DEFINE FCS BIT MASKS. .MACRO ERROR STRING,LEN,SEV MOV STRING,R0 MOV LEN,R1 .IF IDN , CLR R2 .ENDC .IF NDF CMDQIO BR CMDQIO .IFF .IF GT .-CMDQIO JMP CMDQIO .IFF BR CMDQIO .ENDC .ENDC .ENDM .SBTTL PARAMETER SYMBOL DEFINITIONS NOBLKS = 63. ;NUMBER OF BUFFERS. EX.ENA = 200 EX.ADF = 010 EX.FCO = 004 EX.AC2 = 002 EX.AC1 = 001 BDOFF$ DEF$L .SBTTL READ A COMMAND LINE .PSECT CODE,RO,I START: FINIT$ MOV SP,SPSAVE BEGIN: MOV SPSAVE,SP GCML$ #CMLBLK ;GET COMMAND LINE BCC GETOK ;SKIP IF GOTTEN OK. MOV #1,R2 ;ASSUME WE WILL LEAVE. CMPB CMLBLK+G.ERR,#GE.IOR BEQ CMDERR ;I/O ERROR CMPB CMLBLK+G.ERR,#GE.OPR BEQ CMDOPE ;OPEN ERROR CMPB CMLBLK+G.ERR,#GE.BIF BEQ CMDSYN ;SYNTAX ERROR CMPB CMLBLK+G.ERR,#GE.MDE BEQ CMDMAX ;MAX @ FILE DEPTH CMPB CMLBLK+G.ERR,#GE.EOF BNE CMDUNK ;EOF ON COMMAND FILE EXIT$S CMDERR: ERROR #M.ERR,#L.ERR,FATAL CMDOPE: ERROR #M.OPE,#L.OPE,CONT CMDSYN: ERROR #M.SYN,#L.SYN,CONT CMDMAX: ERROR #M.MAD,#L.MAD,CONT CMDPS1: ERROR #M.PS1,#L.PS1,CONT CMDPS2: ERROR #M.PS2,#L.PS2,CONT CMDUNK: ERROR #M.UNK,#L.UNK,FATAL CMDQIO: MOV R0,$QIOW+Q.IOPL+0 MOV R1,$QIOW+Q.IOPL+2 MOV #$QIOW,-(SP) CALL .DIRDL CLOSE$ #FDBIN CLOSE$ #FDBOUT TST R2 ;LEAVE YET? BEQ BEGIN ;NO EXIT$S .SBTTL PARSE THE COMMAND LINE GETOK: TST CMLBLK+G.CMLD BEQ BEGIN ;LOOP IF NULL INPUT LINE. CLR SWORD ;CLEAR SWITCHES. MOV #FDBIN,R0 ;POINT TO THE FDB'S MOV #FDBOUT,R1 ; MOV #S.FDB/2,R2 ;GET FDB SIZE. 10$: CLR (R0)+ ;CLEAR OUT FDB'S CLR (R1)+ ; SOB R2,10$ ;AND LOOP. CSI$1 #CSIBLK,CMLBLK+G.CMLD+2,CMLBLK+G.CMLD BCS CMDPS1 ;PRINT ERROR MESSAGE IF SYNTAX ERROR CSI$2 #CSIBLK,INPUT,#CSITAB BCS 21$ ;PRINT ERROR MESSAGE IF TOO MANY SWITCHES FDRC$R #FDBIN,#FD.RWM ;R/W MODE FDBK$R R0,#BUFFER,#<1000*NOBLKS>,,#2 FDOP$R R0,#2,,#INDFN OPNS$R #FDBIN,,#CSIBLK+C.DSDS,,,,CMDOPN MOV #READ,-(SP) ;GET READY TO READ FILE HEADER. CALL .DIRDL ;READ THE HEADER. MOVB IOST,F.ERR(R0) ;GET F.ERR STATUS BMI 12$ ;SKIP IF THAT'S THE PROBLEM. MOV @#$DSW,F.ERR(R0) ;WHAT ABOUT $DSW? BGE 14$ ;THAT'S NOT IT EITHER. 12$: JMP CMDOPN ;OPEN ERROR ON INPUT. 14$: BITB #UC.CON,HEADER+H.UCHA ;IS THE FILE CONTIGUOUS? BEQ 15$ ;NO, KEEP AS NOW. MOV #SW.CO,SWORD ;YES, FORCE SWORD TO DEFAULT TO /CO 15$: CSI$1 #CSIBLK,CMLBLK+G.CMLD+2,CMLBLK+G.CMLD ;RE-PARSE CSI$2 #CSIBLK,INPUT,#CSITAB BITB #CS.WLD,CSIBLK+C.STAT ;WILD CARDS? BEQ 18$ ;NO 16$: ERROR #M.WLD,#L.WLD,CONT ;YES 18$: BITB #CS.MOR,CSIBLK+C.STAT ;MORE THAN 1 INPUT FILE? BEQ 20$ ;NO 19$: ERROR #M.TOO,#L.TOO,CONT ;YES 20$: CSI$2 #CSIBLK,OUTPUT BCC 22$ 21$: JMP CMDPS2 22$: BITB #CS.WLD,CSIBLK+C.STAT ;WILD CARDS? BNE 16$ ;YES BITB #CS.MOR,CSIBLK+C.STAT ;MORE THAN 1 OUTPUT FILE? BNE 19$ ;YES MOV FDBIN+F.RSIZ,R1 ;GET THE RECORD SIZE. BNE 25$ ;SKIP IF INITIALISED. MOV #1000,R1 ;OTHERWISE INITIALISE TO 512.. 25$: MOVB FDBIN+F.RATT,R2 ;GET RECORD ATTRIBUTES. MOV FDBIN+F.ALOC,R4 ;DEFAULT EXPANSOPN. BITB #FD.SQD!FD.REC,FDBIN+F.RCTL ;SEQUENTIAL? BEQ 30$ ;NO ERROR #M.SEQ,#L.SEQ,CONT 30$: FDAT$R #FDBOUT,FDBIN+F.RTYP,R2,R1,,R4 FDRC$R R0,#FD.RWM ;YES FDBK$R R0,#BUFFER,#,,#3 FDOP$R R0,#3,,#OUTDFN ; ; SET UP THE DEFAULT FILENAME BLOCK FOR THE OUTPUT FILE. THE FILENAME ; BLOCK RESIDING IN THE INPUT FDB (FDBIN) IS NOT ACCEPTIBLE BECAUSE ; IT HAS INFORMATION IN IT WHICH WE DON'T WANT, SUCH AS THE DIRECTORY, ; DEVICE, AND UNIT NUMBER. ALL WHICH WE WILL COPY WILL BE THE FILE ; NAME, FILE TYPE, AND VERSION NUMBER. WE WILL FORCE THE OUTPUT DEVICE ; TO BE SY0: ; MOV #OUTDFN,R0 ;POINT TO OUTPUT DEFAULT FILE NAME BLOCK. MOV #S.FNB/2,R1 ;GET SIZE OF FILE NAME BLOCK IN WORDS. 31$: CLR (R0)+ ;CLEAR FILENAME BLOCK. SOB R1,31$ ; MOV FDBIN+F.FNB+N.FNAM,OUTDFN+N.FNAM ;INIT NAME MOV FDBIN+F.FNB+N.FNAM+2,OUTDFN+N.FNAM+2 MOV FDBIN+F.FNB+N.FNAM+4,OUTDFN+N.FNAM+4 MOV FDBIN+F.FNB+N.FTYP,OUTDFN+N.FTYP ;SET UP TYPE. BIT #SW.NV,SWORD ;IS THIS TO BE FORCED TO A NEW VERSION? BNE 32$ ;YES MOV FDBIN+F.FNB+N.FVER,OUTDFN+N.FVER ;SET UP VERSION. BR 33$ ;AND SKIP ERROR CHECKS. 32$: BIT #SW.SU!SW.UP,SWORD ;/NV CONFLICTS WITH /SU AND /UP. BEQ 33$ ;NOT SPECIFIED, OK ERROR #M.ISW,#L.ISW,CONT ;ERROR MESSAGE -- ILLEGAL SWITCHES. 33$: MOV #"SY,OUTDFN+N.DVNM ;SET UP DEVICE MOV #0,OUTDFN+N.UNIT ;AND UNIT. ; ; NOW WE SET UP THE TYPE OF ACCESS WHICH WE WILL WANT. ; PUT THIS INTO R1. ; MOV #FO.WRT,R1 ;DEFAULT TO WRITING A NEW FILE. BIT #SW.SU,SWORD ;ARE WE TO SUPERSEDE THE OUTPUT FILE? BNE 40$ ;YES -- SKIP THIS STUFF. BIS #FA.NSP,R1 ;NO -- FORCE NO SUPERSEDE ON OUTPUT. BIT #SW.UP,SWORD ;RUN IN UPDATE MODE? BEQ 50$ ;NO, JUST TAKE IT LIKE IT IS. MOV #FO.UPD,R1 ;YES, NOTIFY FCS OF IT. BR 50$ ;AND OPEN THE FILE 40$: BIT #SW.UP,SWORD ;WAS UPDATE SPECIFIED TOO? BEQ 50$ ;NO -- JUST OPEN THE FILE. ERROR #M.ISW,#L.ISW,CONT ;ERROR -- ILLEGAL SWITCH COMBINATION. 50$: OPEN$ #FDBOUT,R1,,#CSIBLK+C.DSDS,#OUTDFN,,,,CMDOPN BITB #FD.SQD!FD.REC,FDBOUT+F.RCTL ;SEQUENTIAL DEVICE? BEQ 60$ ;NO ERROR #M.SEQ,#L.SEQ,CONT 60$: MOV FDBIN+F.EFBK+2,R1 ;GET THE LOW ORDER EF BLOCK MOV FDBIN+F.EFBK,R2 ;AND HI ORDER EF BLOCK TST FDBIN+F.FFBY ;IS THERE NOTHING USED LAST BLOCK? BNE 70$ ;SOMETHING USED -- DON'T DELETE SUB #1,R1 ;LAST BLOCK; OTHERWISE, DON'T SBC R2 ;ALLOCATE OR USE LAST BLOCK. 70$: MOV FDBOUT+F.EFBK+2,R3 ;GET OUTPUT EF BLOCK MOV FDBOUT+F.EFBK,R4 ;AND HI ORDER TST FDBOUT+F.FFBY ;IS THERE NOTHING USED LAST BLOCK? BNE 71$ ;SOMETHING USED -- DON'T DELETE SUB #1,R3 ;LAST BLOCK - DELETE. SBC R4 ; 71$: CMP R2,R4 ;ARE BLOCKS NEEDED? BLO 200$ ;NO, R4 (OLD BLOCKS) > R2 (NEW BLOCKS) BNE 72$ ;YES, R4 < R2 CMP R1,R3 ;MAYBE, WHAT ABOUT LOW ORDER?? BLOS 200$ ;NO, R3 (OLD BLOCKS) > R1 (NEW BLOCKS) 72$: SUB R4,R2 ;COMPUTE REAL NUMBER OF BLOCKS TO ADD SUB R3,R1 ;SUBTRACT LOW ORDER TOO SBC R2 ;SUBTRACT ANY CARRY. SWAB R2 ;GET THE BITS INTO THE HI ORDER. CLRB R2 ;CLEAR LOW ORDER R2 BYTE. BIS #EX.ENA,R2 ;SET OPTION BIT. BIT #SW.CO,SWORD ;CONTIGUOUS OUTPUT? BNE 121$ ;YES BIT #SW.CP,SWORD ;"NEARLY" CONTIGUOUS OUTPUT? BEQ 123$ ;NO BIS #EX.AC2!EX.AC1,R2 ;SET OPTION BITS FOR "NEARLY CO" BR 123$ ;AND CONTINUE. 121$: BIS #EX.AC1!EX.FCO,R2 ;SET OPTION BITS FOR "CO" 123$: CALL .EXTND ;EXTEND THE FILE AS DESIRED. BCC 200$ ;SKIP ON OK. BIT #SW.UP,SWORD ;DON'T SET TO DELETE ON UPDATE. BNE 190$ ; JMP CMDOP1 ;AND GO TO THE ERROR ROUTINE. 190$: JMP CMDOPN ;AND PRINT THE ERROR MESSAGE. 200$: CLR FDBOUT+F.EFBK ;FORCE OUTPUT FILE TO BEGIN AT BLOCK 0. CLR FDBOUT+F.EFBK+2 ;DITTO CLR FDBOUT+F.FFBY ;DITTO .SBTTL COPY THE FILE MOV FDBIN+F.EFBK+2,R3 ;GET THE NUMBER OF BLOCKS TO MOVE. MOV FDBIN+F.EFBK,R2 ;AND HI ORDER. TST FDBIN+F.FFBY ;CHECK FIRST FREE BYTE. BNE LOOP ;SKIP IF BYTE OK. SUB #1,R3 ;IF NO BYTES USED LAST BLOCK, DEC SBC R2 ;THE BLOCK COUNT. LOOP: SUB #NOBLKS,R3 ;SUBTRACT OFF # BKOCKS SBC R2 ;AND FROM HI ORDER. BLT ENDLP ;AND LEAVE IF DONE. READ$ #FDBIN ;READ FROM INPUT FDB. BCS EOFMOD ;SKIP OUT ON ERROR. WAIT$ R0 ;WAIT FOR IT. BCS EOFMOD ;SKIP OUT ON ERROR. WRITE$ #FDBOUT ;WRITE OUTPUT FDB. BCS EOFMOD ;ERROR? WAIT$ R0 ;AND WAIT ON IT. BCS EOFMOD ;ERROR? BR LOOP ;LOOP UNTIL DONE. ENDLP: ADD #NOBLKS,R3 ;GET THE # TO BE TRANSFERRED. BEQ CLOSIT ;CLOSE FILES IF DONE. ASH #9.,R3 ;CONVERT # BLOCKS TO BLOCK SIZE. READ$ #FDBIN,,R3 ;READ A BLOCK BCS EOFMOD WAIT$ R0 ;WAIT ON IT BCS EOFMOD WRITE$ #FDBOUT,,R3 ;WRITE A BLOCK BCS EOFMOD WAIT$ R0 ;WAIT ON IT BCS EOFMOD ; ; NORMAL EXIT ROUTINE. COPY THE END-OF-FILE INFO ; FROM THE INPUT FILE TO THE OUTPUT FILE (READ$/WRITE$ ; CANNOT TELL WHERE VARYING LENGTH RECORDS ARE, FOR ; EXAMPLE, AND THUS CANNOT REALLY SET THESE FIELDS ; CORRECTLY ITSELF). ; CLOSIT: MOV FDBIN+F.EFBK,FDBOUT+F.EFBK MOV FDBIN+F.EFBK+2,FDBOUT+F.EFBK+2 MOV FDBIN+F.FFBY,FDBOUT+F.FFBY CLOSE$ #FDBIN ;CLOSE FDBIN BCS EOFMOD CLOSE$ #FDBOUT ;AND FDBOUT BCS EOFMOD JMP BEGIN ;AND TRY AGAIN. .SBTTL PRINT ERROR MESSAGES EOFMOD: ; ; THE ERROR HANDLING ROUTINE. ; IF AN END-OF-FILE IS DETECTED, THE PROGRAM JUST EXITS. ; CLR R5 ;SET DELETE FLAG TO 0. BR CMD01 ; CMDOP1: MOV #1,R5 ;SET DELETE FLAG TO 1. BR CMD01 CMDOPN: CLR R5 ;SET DELETE FLAG TO FALSE. CMD01: MOV #M.IOR,R1 ;GET I/O ERROR MSG MOV #L.IOR,R2 ;AND LENGTH TST @#$DSW ;DSW ERROR? BGT 10$ ;NO MOV @#$DSW,F.ERR(R0) ;MOVE IN ERROR CODE 10$: CALL .PRFCS ; CLOSE$ #FDBIN ; MOV #FDBOUT,R0 TST R5 ;DELETE? BEQ 20$ ;NO DELET$ R0 ;DELETE FILE NEVER USED. BR 30$ 20$: CALL .TRNCL ;TRUNCATE. 30$: JMP BEGIN ;AND RESTART .SBTTL ERROR MESSAGE STRINGS .PSECT PDATA,RO,D .NLIST BIN M.ERR: .ASCII "CPY -- I/O ERROR ON @ FILE" L.ERR = .-M.ERR .EVEN M.OPE: .ASCII "CPY -- OPEN ERROR ON @ FILE" L.OPE = .-M.OPE .EVEN M.SYN: .ASCII "CPY -- SYNTAX ERROR FOR @ FILE" L.SYN = .-M.SYN .EVEN M.MAD: .ASCII "CPY -- MAX @ FILE DEPTH EXCEEDED" L.MAD = .-M.MAD .EVEN M.UNK: .ASCII "CPY -- UNKNOWN COMMAND ERROR" L.UNK = .-M.UNK .EVEN M.PS1: .ASCII "CPY -- SYNTAX ERROR" L.PS1 = .-M.PS1 .EVEN M.PS2: .ASCII "CPY -- ILLEGAL SWITCH" L.PS2 = .-M.PS2 .EVEN M.SEQ: .ASCII "CPY -- CANNOT COPY TO/FROM A SEQUENTIAL DEVICE" L.SEQ = .-M.SEQ .EVEN M.IOR: .ASCII /CPY/ L.IOR = .-M.IOR .EVEN M.ISW: .ASCII "CPY -- ILLEGAL SWITCH COMBINATION" L.ISW = .-M.ISW .EVEN M.WLD: .ASCII "CPY -- WILDCARDS NOT ALLOWED" L.WLD = .-M.WLD .EVEN M.TOO: .ASCII "CPY -- TOO MANY FILES - COMMAND AMBIGUOUS" L.TOO = .-M.TOO .EVEN .SBTTL DATA AREA .PSECT IDATA,RW,D CSITAB: CSI$SW CO,SW.CO,SWORD,SET,NEG CSI$SW CP,SW.CP,SWORD,SET,NEG CSI$SW UP,SW.UP,SWORD,SET,NEG CSI$SW SU,SW.SU,SWORD,SET,NEG CSI$SW NV,SW.NV,SWORD,SET,NEG CSI$ND SWORD: .WORD 0 SW.CO = 000002 ;CONTIGUOUS FILE SW.CP = 000004 ;PARTIALLY CONTIGUOUS SW.UP = 000010 ;UPDATE MODE SW.SU = 000020 ;SUPERSEDE MODE SW.NV = 000040 ;/NV SWITCH CMLBLK: GCMLB$ 1,CPY,USRBUF,1 USRBUF: .BLKB 82. .EVEN CSI$ .EVEN CSIBLK: .BLKB C.SIZE FSRSZ$ 1 .PSECT IDATA,RW,D FDBIN: FDBDF$ INDFN: NMBLK$ ,,,SY,0 FDBOUT: FDBDF$ OUTDFN: NMBLK$ .EVEN SPSAVE: .WORD 0 READ: QIOW$ IO.RAT,2,2,,IOST,, IOST: .WORD 0,0 RDHDR: .BYTE -12,0 .WORD HEADER .WORD 0 HEADER: BUFFER: .BLKB <1000*NOBLKS> .EVEN $QIOW: QIOW$ IO.WVB,4,4,,,,<0,0,40> .END START