.TITLE CPY - BLOCK MODE COPY / FILE CREATE UTILITY FOR LARGE FILES .SBTTL INTRODUCTION .IDENT /V01/ .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2,CSI$SW,CSI$ND,DIR$,PUT$ .MCALL FDBDF$,FDAT$R,NMBLK$,OPEN$,CLOSE$,QIO$,WTSE$S,GET$,EXIT$S .MCALL READ$,WRITE$,FDBK$R,QIOW$,OFNB$,CSI$SV,FSRSZ$,SPND$S .MCALL RSUM$S,QIOW$S,ASTX$S,FDOP$R,QIO$S,WAIT$,CLEF$S,SETF$S .NLIST BEX ;+ ; VERSION 01 ; ; REID L BROWN 1-NOV-77 ; ; MODIFIED BY: ; ; NO MODIFICATIONS ; ; ; ; CPY - ; ; THIS PROGRAM IS DESIGNED TO REPLACE THE FUNCTION OF PIP FOR COPIES AND ; CREATIONS OF LARGE FILES (GREATER THAN 28656. BLOCKS). IT SUPPORTS ONLY ; MULTI-BUFFERED BLOCK MODE TRANSFERS, AND CANNOT BE USED WITH RECORD- ; ORIENTED DEVICES. THE COMMAND FORMAT IS: ; ; CPY FILE.EXT[/BL:NNN][/EX] - TO CREATE OR EXTEND A FILE ; CPY FILE.EXT[/BL:NNN][/UP]=OLDFILE.EXT - TO COPY AN EXISTING FILE ; ;- ; ; LOCAL MACROS ; .MACRO ERRMSG MESSAG,WHERE,?A,?B,?C BR C A: .ASCII ^MESSAG^ B: .EVEN C: MOV #A,QIO+Q.IOPL MOV #B-A,QIO+Q.IOPL+2 DIR$ #QIO .IIF DF,WHERE JMP WHERE .ENDM ERRMSG .MACRO PAUSE CLEF$S #16. WTSE$S #16. .ENDM PAUSE .MACRO RESUME SETF$S #16. .ENDM RESUME .SBTTL CSI & FCS DATA & BUFFERS ; ; FILE DESCRIPTOR BLOCKS & RELATED INFORMATION ; FSRSZ$ 3 FDBST: ; START OF FDB'S FDBOUT::FDBDF$ ; DEFINE OUTPUT FDB FDBIN:: FDBDF$ ; DEFINE INPUT FDB FDBEND: ; END ADDR OF FDB'S GCMBLK: GCMLB$ 3,CPY,,TILUN ; COMMAND LINE CONTROL BLOCK OUTDFN: NMBLK$ ,DAT ; DEFAULT FILENAME EXTENSION: 'DAT' INDFN: NMBLK$ ,DAT ; DEFAULT INPUT FILENAME EXTENSION: 'DAT' ; ; BUFFERS ; BLKFCT = 8. ; BLOCKING FACTOR = 8 BLKSIZ = 512.*BLKFCT ; BLOCKSIZE = 4096. BUFF0: .BLKB BLKSIZ ; BLOCK BUFFER #0 BUFF1: .BLKB BLKSIZ ; BLOCK BUFFER #1 BUFF2: .BLKB BLKSIZ ; BUFFER #2 MIOST: 0,0,BUFF0,0,0 ; MULTI-BUFFER IO STATUS ENTRY #0 0,0,BUFF1,0,0 ; ... #2 0,0,BUFF2,0,0 ; ... #3 MIOND =. MIOSZ = 12 ; SIZE OF EACH ENTRY BLOCKL: .WORD 0 ; LOW ORDER BLOCK# BLOCKH: .WORD 0 ; HIGH ORDER BLOCK# FLAGS: .WORD 0 ; FLAG WORD ; DONE = 1 ; I/O DONE ERR = 2 ; I/O ERROR STBIN: .BLKW 6. ; STATISTICS BLOCK FOR INPUT STBOUT: .BLKW 6. ; STATISTICS BLOCK FOR OUTPUT IOST: .BLKW 2 ; I/O STATUS BLOCK ; ; LUNS ; OUTLUN= 2 ; OUTPUT FILE ON 2 INLUN= 3 ; INPUT ON LUN 3 TILUN= 5 ; GCML & QIO'S TO #5 (DEFAULT FROM TKB) ; ; ACCESS CONTROL BITS ; EX.ENA = 200 ; ENABLE ACCESS EX.AC1 = 1 ; ACCESS CONTROL 1 EX.AC2 = 2 ; ACCESS CONTROL 2 EX.FCO = 4 ; CONTIGUOUS ALLOCATION CONTROL ; ; COMMAND STRING INTERPRETER ; CSIFLG: .WORD 0 ; FLAG WORD FOR COMMAND SWITCHES HLPMSK= 1 ; /HE - PRINT HELP MESSAGE BLKMSK= 2 ; /BL - BLOCK ALLOCATE MASK EXTMSK= 4 ; /EX - EXTEND EXISTING FILE UPDMSK= 10 ; /UP - UPDATE (OVERWRITE) MASK EQUMSK= 100000 ; '=' SIGN SEEN (CS.EQU IN C.STAT) CSISW: CSI$SW HE,HLPMSK,CSIFLG CSI$SW BL,BLKMSK,CSIFLG,,,BLKTAB CSI$SW EX,EXTMSK,CSIFLG CSI$SW UP,UPDMSK,CSIFLG CSI$ND BLKTAB: CSI$SV ASCII,BLKSTR,10. CSI$ND BLKSTR: .BLKB 10. ; RESERVE A 10-BYTE STRING FOR ASCII VALUE BLKHI: .WORD 0 ; HIGH ORDER DOUBLE-PRECISION RESULT BLKLO: .WORD 0 ; LOW ORDER DOUBLE-PRECISION RESULT CSI$ CSI: .BLKB C.SIZE ; DEFINE THE CSI WORK AREA .EVEN .SBTTL HELP MESSAGE & TEXT ; ; ERROR MESSAGE PROCESSING & HELP ; QIO:: QIOW$ IO.WVB,TILUN,1,,IOSTAT,,<.-.,.-.,40,.-.,.-.,.-.> IOSTAT::.WORD 0,0 ERRBUF: .BLKB 80. HLPMSG: .ASCIZ 'CPY - BLOCK MODE FILE COPY / CREATE UTILTIY FOR LARGE FILES' .ASCIZ ' THIS ROUTINE IS DESIGNED TO BE USED IN PLACE OF "PIP" FOR LARGE' .ASCIZ ' FILE TRANSFER OPERATIONS, WHERE PIP CANNOT HANDLE THE ALLOCA-' .ASCIZ ' TIONS INVOLVED. IF ONLY AN OUTPUT FILE IS SPECIFIED, THE OPER-' .ASCIZ ' STION IS ASSUMED TO BE A FILE CREATE (OR EXTEND). IF AN OUTPUT' .ASCIZ ' AND INPUT ARE SPECIFIED, THEN IT IS A COPY (OR UPDATE). THE' .ASCIZ ' COMMAND SYNTAX IS:' .ASCIZ ' ' .ASCIZ ' CPY FILENAME.EXT[/BL:NNN][/EX] -CREATE/EXTEND' .ASCIZ ' CPY FILENAME.EXT[/BL:NNN][/UP]=OLDFILE -COPY/UPDATE' .ASCIZ ' ' .ASCIZ ' SWITCHES FOR "CPY" ARE:' .ASCIZ ' ' .ASCIZ ' /HE - THIS HELP TEXT' .ASCIZ ' /BL:[+/-]NNN. - THE NO. OF BLOCKS TO ALLOCATE OR EXTEND' .ASCIZ ' WHERE + IS CONTIGUOUS & - IS NON-CONTIGUOUS.' .ASCIZ ' /EX - EXTEND AN EXISTING FILE (DEFAULT IS CREATE)' .ASCIZ ' /UP - UPDATE (OVERWRITE) EXISTING FILE, RATHER THAN' .ASCIZ ' CREATE NEW OUTPUT FILE.' HLPEND= . IOERM: .ASCIZ 'CPY -- I/O ERROR ON OPEN. CODE=%D' IO1ERM: .ASCIZ 'CPY -- ERROR ON EXTEND. CODE=%D' IO2ERM: .ASCIZ 'CPY -- I/O ERROR ON DISK BLOCK TRANSFER. CODE=%D' .EVEN .SBTTL PARSE INPUT SPECIFICATION & CHOOSE ACTION ; ; GET COMMAND LINE, PARSE IT & START ALL FILES ; START: CALL CLOSE ; INSURE ALL FILES ARE CLOSED (IGNORE ERRORS) MOV #FDBST,R0 ; POINT TO THE FIRST FDB 110$: CLR (R0)+ ; CLEAR OUT THE FILE DESCRIPTOR BLOCKS CMP R0,#FDBEND ; AT END YET? BLO 110$ ; NO - CONTINUE CLR CSIFLG ; RESET THE COMMAND STRING FLAGS CLR BLKHI ; RESET HIGH & LOW BLOCK VALUES CLR BLKLO ; ... GCML$ #GCMBLK ; READ A COMMAND LINE BCC 130$ ; CONTINUE IF NO ERRORS CMPB #GE.EOF,G.ERR(R0) ; END OF COMMAND INPUT? BNE 120$ ; NO - COMMAND INPUT ERROR EXIT$S 120$: ERRMSG BR START 130$: CSI$1 #CSI,GCMBLK+G.CMLD+2,GCMBLK+G.CMLD ; PARSE COMMAND LINE BCC 140$ ; CONTINUE IF NO ERRORS 135$: ERRMSG BR START 140$: BITB #CS.EQU,C.STAT(R0) ; INPUT FILE SPECIFIED? BEQ 145$ ; NO - CONTINUE BIS #EQUMSK,CSIFLG ; YES - FLAG IT FOR LATER 145$: CSI$2 R0,OUTPUT,#CSISW ; PARSE OUTPUT FILESPEC & SWITCHES BCC 160$ ; NO ERRORS - CONTINUE 150$: ERRMSG JMP START 160$: BITB #,C.STAT(R0) BNE 135$ BIT #HLPMSK,CSIFLG ; DID THE USER WANT HELP? BEQ 165$ ; NO - CONTINUE JMP HELP ; GIVE HIM HELP 165$: FDAT$R #FDBOUT,#R.VAR,#FD.CR ; INIT THE FDB FDOP$R R0,#OUTLUN BIT #,CSIFLG ; EXTEND OR UPDATE EXISTING FILE? BEQ 170$ ; NO - CREATE A NEW ONE MOV #FO.UPD,R5 ; YES - MODE='UPDATE' MOV #STBOUT,F.STBK(R0) ; SETUP TO READ THE STATISTICS BLOCK BR 180$ ; CONTINUE 170$: MOV #FO.WRT,R5 ; SET MODE='WRITE' CLR F.STBK(R0) ; RESET STATISTICS BLOCK READ 180$: OPEN$ R0,R5,#OUTLUN,#CSI+C.DSDS,#OUTDFN,#FD.RWM BCC 190$ ; NO ERRORS - CONTINUE MOV F.ERR(R0),-(SP) ; STACK UP ERROR CODE MOV #IOERM,R1 ; R1 = ERROR STRING JMP ERROR ; GO PROCESS ERROR 190$: BIT #BLKMSK,CSIFLG ; ANY /BLOCKS SPEC? BEQ 300$ ; NO - SEE IF COPY DESIRED MOV #BLKHI,R3 ; R3 = OUTPUT DATA ADDRESS MOV #10.,R4 ; R4 = CONVERSION COUNT (MAX) MOV #BLKSTR,R5 ; R5 = STRING POINTER MOV R5,R2 ; SAVE IT IN R2 ADD R4,R5 ; POINT TO END OF STRING + 1 195$: TSTB -(R5) ; IS THIS A NULL? BNE 198$ ; NO - CONTINUE SOB R4,195$ ; CONTINUE IF COUNT .GT. 0 BR 300$ ; NO EXTEND SIZE SPECIFIED!! 198$: MOV R2,R5 ; RESTORE THE STRING ADDRESS CALL .OD2CT ; CONVERT IT ; ; CALL THE .EXTEND SUBROUTINE TO EXTEND THE FILE. IN THE CASE OF A NON- ; CONTIGUOUS EXTEND, NOTE THAT THE PROGRAM TRIES TO ALLOCATE THE LARGEST ; CONTIGUOUS AREA IT CAN. ; 200$: MOV #,R2 ; ASSUME CONTIGUOUS EXTEND TST BLKHI ; IS THIS TRUE (NON-NEGATIVE) BPL 210$ ; YES - CONTINUE NEG BLKHI ; MAKE THE NO. OF BLOCKS POSITIVE NEG BLKLO ; ... SBC BLKHI ; (PROPAGATE CARRY) MOV #,R2 ; SET FOR NON-CONTIGUOUS 210$: MOV BLKHI,R3 ; R3 = HIGH ORDER BLOCK NO. BITS SWAB R3 ; MOVE BITS 16-23 TO HIGH BYTE CLRB R3 ; RESET LOW BYTE BIS R3,R2 ; 'OR' HIGH BLOCK BITS INTO R2 MOV BLKLO,R1 ; R1 = LOW ORDER NO. BLOCKS CALL .EXTND BCC 300$ ; CONTINUE IF NO ERROR 250$: MOV #IO1ERM,R1 ; SETUP ERROR MESSAGE MOV F.ERR(R0),-(SP) ; & STACK UP ERROR CODE JMP ERROR ; ; IF INPUT FILE SPECIFIED, OPEN THE INPUT FILE & COPY THE ATTRIBUTES SECTION ; TO THE OUTPUT FILE. THEN, COPY THE INPUT FILE TO THE OUTPUT FILE. ; 300$: BIT #EQUMSK,CSIFLG ; WAS AN INPUT FILE SPECIFIED? BNE 305$ ; YES - PROCESS IT JMP 900$ ; NO - WE ARE DONE 305$: CSI$2 #CSI,INPUT ; PARSE THE INPUT FILESPEC BCC 310$ ; CONTINUE IF NO ERROR JMP 150$ ; INVALID SWITCH 310$: BITB #,C.STAT(R0) ; NO WILDCARDS OR ADD'L SPECS. BEQ 320$ ; CONTINUE IF OK JMP 135$ ; COMMAND LINE SYNTAX ERROR 320$: MOV #FDBIN,R0 ; R0 = INPUT FDB ADDR MOV #STBIN,F.STBK(R0) ; SETUP THE STATISTICS BLOCK OPEN$ R0,#FO.RD,#INLUN,#CSI+C.DSDS,#INDFN,#FD.RWM BCC 330$ ; CONTINUE IF NO OPEN ERROR MOV F.ERR(R0),-(SP) ; PUT ERROR ON STACK MOV #IOERM,R1 ; OPEN ERROR JMP ERROR ; REPORT IT 330$: MOV R0,R5 ; R5 = INPUT FDB MOV #FDBOUT,R0 ; R0 = OUTPUT FDB POINTER BIT #BLKMSK,CSIFLG ; WAS "/BL" SPECIFIED ON OUTPUT? BNE 340$ ; YES - CONTINUE MOV F.EFBK+2(R5),R1 ; R1 = LOW END OF FILE BLOCK NO. MOV F.EFBK(R5),R2 ; R2 = HIGH ORDER BLOCK NO. SWAB R2 ; PUT IN HIGH BYTE CLRB R2 ; RESET FLAGS BYTE BITB #FA.CRE,F.FACC(R0) ; NEW FILE (NO ALLOCATION?) BEQ 335$ ; NO - EXTEND IT BISB #,R2 ; SELECT CONTIGUOUS EXTEND CALL .EXTND ; TRY TO EXTEND IT BCC 340$ ; CONTINUE IF NO ERROR 335$: MOV STBIN+4,R2 ; RETRIEVE FULL HIGH ORDER SIZE FROM INPUT SUB STBOUT+6,R1 ; SUBTRACT CURRENT NO. IN OUTPUT FILE SBC R2 ; PROPAGATE CARRY... SUB STBOUT+4,R2 ; IF NEGATIVE, THERE IS ENOUGH ROOM BMI 340$ ; YES - DON'T EXTEND THE FILE SWAB R2 ; MOVE HIGH 8 BITS TO HIGH BYTE CLRB R2 ; RESET LOW FLAG BYTE BISB #,R2 ; ENABLE NON-CONTIGUOUS EXTEND CALL .EXTND ; EXTEND OUTPUT BCC 340$ ; CONTINUE IF NO ERROR JMP 250$ ; ELSE DECLARE EXTEND ERROR 340$: MOV #FDBIN,R1 ; R1 = INPUT FDB ADDRESS MOV #,R2 ; R2 = NO. OF ATTRIBUTE BYTES 345$: MOVB (R1)+,(R0)+ ; COPY THE ATTRIBUTES TO THE OUTPUT FDB SOB R2,345$ ; ... ; ; COPY FILES ; ; THE FILE COPY IS ACCOMPLISHED VIA AN AST DRIVEN, MULTI-BUFFERED ; QIO XFER. ALSO, MULTI-BLOCK XFERS ARE USED TO OPTIMIZE THE DISK ; THROUGHPUT ; 350$: MOV #MIOST,R5 ; R5 = START OF I/O STATUS BLOCKS CLR BLOCKH ; SET BLOCK NO. TO 1 MOV #1,BLOCKL ; ... 360$: MOV BLOCKH,6(R5) ; SETUP BLOCK NO. FOR THIS QIO MOV BLOCKL,10(R5) ; ... QIO$S #IO.RVB,#INLUN,,,R5,#370$,<4(R5),#BLKSIZ,,6(R5),10(R5)> ADD #BLKFCT,BLOCKL ; ADVANCE BLOCK # ADC BLOCKH ; ... ADD #MIOSZ,R5 ; POINT TO NEXT I/O STATUS NODE CMP R5,#MIOND ; DONE? BLO 360$ ; NO - CONTINUE PAUSE ; WAIT FOR I/O TO COMPLETE BIT #ERR,FLAGS ; ANY ERRORS? BEQ 900$ ; NO - DONE! MOV IOST,-(SP) ; PUT ERROR ON STACK MOV #IO2ERM,R1 ; & GET ERROR MESS ADDR JMP ERROR ; ; READ COMPLETE AST ; 370$: MOV R0,-(SP) ; SAVE R0 MOV 2(SP),R0 ; R0 = IO STATUS ADDR MOV R1,2(SP) ; SAVE R1 CLR R1 ; INDICATE WRITE REQ'D ; ; COMMON AST PROCESSOR ; 371$: BIT #,FLAGS ; IS I/O COMPLETE? BNE 377$ ; YES - EXIT CMPB #IE.EOF,(R0) ; WAS THIS AN EOF? BNE 372$ ; NO - CONTINUE BIS #DONE,FLAGS ; YES - FLAG IT RESUME ; CONTINUE THE MAIN TASK BR 377$ ; EXIT AST 372$: TSTB (R0) ; I/O ERROR? BPL 375$ ; NO - CONTINUE BIS #ERR,FLAGS ; INDICATE ERROR MOV (R0),IOST ; SAVE ERROR CODE RESUME ; CONTINUE MAIN TASK BR 377$ ; EXIT AST 375$: TST R1 ; READ OR WRITE REQ'D? BMI 385$ ; READ - GET NEXT BLOCK OF INPUT QIO$S #IO.WVB,#OUTLUN,,,R0,#380$,<4(R0),2(R0),,6(R0),10(R0)> 377$: MOV (SP)+,R0 ; RESTORE R0 MOV (SP)+,R1 ; RESTORE R1 ASTX$S ; ; WRITE COMPLETE AST ; 380$: MOV R0,-(SP) ; SAVE R0 MOV 2(SP),R0 ; GET IO STATUS ADDR MOV R1,2(SP) ; SAVE R1 MOV #-1,R1 ; INDICATE READ OPERATION REQ'D BR 371$ ; GO TO COMMON CODE 385$: MOV BLOCKL,10(R0) ; LOAD NEXT BLOCK# TO READ MOV BLOCKH,6(R0) ; ... QIO$S #IO.RVB,#INLUN,,,R0,#370$,<4(R0),#BLKSIZ,,6(R0),10(R0)> ADD #BLKFCT,BLOCKL ; UPDATE THE BLOCK NO. ADC BLOCKH ; ... BR 377$ ; $ EXIT THE AST 900$: JMP START ; ; CLOSE - CLOSE FILES AT END OF RUN ; CLOSE: CLOSE$ #FDBOUT ; CLOSE OUTPUT CLOSE$ #FDBIN RETURN ; ; HELP - LIST OUT THE HELP TEXT ON TI: ; HELP: MOV #HLPMSG,R0 ; R0 = HELP MESSAGE TEXT ADDRESS MOV #40,QIO+Q.IOPL+4; SET THE CC-TYPE TO CR-LF 10$: MOV R0,QIO+Q.IOPL ; PUT THE ADDRESS IN THE DPB MOV R0,R1 ; SAVE THE BEGINNING ADDRESS IN R1 20$: TSTB (R0)+ ; SCAN TO NULL AT END BNE 20$ ; CONTINUE TILL NULL CHARACTER MOV R0,R2 ; R2 = ENDING LINE ADDRESS + 1 DEC R2 ; BACKUP TO END OF LINE SUB R1,R2 ; R2 = LENGTH OF LINE MOV R2,QIO+Q.IOPL+2 ; PUT LENGTH IN QIO DPB DIR$ #QIO ; OUTPUT THE LINE CMP R0,#HLPEND ; ANY MORE TEXT TO GO? BLO 10$ ; YES - CONTINUE JMP START .SBTTL ERROR - ERROR PROCESSOR ; ; ERROR-PROCESS ERROR MESSAGES. THIS ROUTINE OUTPUTS ERROR MESSAGES TO ; THE USERS TERMINAL USING $EDMSG. THE PATTERN STRING IS ASSUMED ; TO BE POINTED TO BY R1, AND THE ERROR CODE ON THE STACK. THIS ; ROUTINE SHOULD BE PASSED CONTROL VIA 'JMP ERROR'. ; ERROR: MOV #ERRBUF,R0 ; R0 = OUTPUT BUFFER POINTER MOVB (SP),R2 ; GET & SIGN EXTEND THE ERROR CODE MOV R2,(SP) ; PUT IT BACK ON STACK MOV SP,R2 ; R2 = PARAMETER POINTER CALL $EDMSG ; EDIT THE MESSAGE MOV #ERRBUF,QIO+Q.IOPL ; SETUP THE QIO DPB MOV R1,QIO+Q.IOPL+2 ; ... TST (SP)+ ; POP THE PARAMETER FROM THE STACK DIR$ #QIO ; OUTPUT IT JMP START ; RESTART .END START