.TITLE RECOVER FIX A LOCKED FILE ; ; MCR TASK TO RECONSTRUCT A FILE CORRUPTED BY AN ABORTED TASK. ; ; WRITTEN NOVEMBER 1976 R B FRENCH THE BOEING COMPANY ; UPDATED BY ROMAN ROMANETTI ; UPDATED BY MIKE BLAKE-KNOX ; ++3 LEN 07/25/79 ; -FIXED CHECK ON ACCESSED FOR WRITE - CHANGED TO DO CHECK BEFORE ; CHECKING FOR LOCKED. ; -FIXED TASK BUILD FILE FOR INDIRECT COMMAND FILE. HAD TO ADD ; ANOTHER UNIT (3) SO ERROR MESSAGES COME OUT WHEN TI: GETS SET ; TO SY: WHEN INDIRECT GETS OPENED. ; -INCLUDED LINE TO MOVE QIO CODE FOR RDHDR TO QIO BLOCK WHEN ; CHECKING NEXT FILE. HEADER WAS NOT GETTING RE-READ ; ++4 -ADDED SWITCHES FOR PRINT (/PRINT:REMOTE) ; AND /DELETE AND /SCAN. IF /SCAN NOT SPECIFIED EOF MARK IS ; SET AT BLOCKS ALLOCATED. IF /SCAN IS SUPPLIED THEN FILE ; IS SCANNED FOR LAST GOOD RECORD. ; ; ; CALLING SEQUENCE ; ;+ ; ; $$$REC - RECOVER LOCKED FILES AS A PRODUCT OF ABORTED TASKS ; ; PDS> REC FNAME[/SWITCHES] ; FNAME = NAME OF CORRUPTED FILE ; OR ; PDS> REC @FNAME ; WHERE FNAME.CMD IS A FILE OF FILENAMES TO BE RESET. ; ; SWITCHES - ; /P(RINT)[:R(EMOTE)] - /P PRINTS ON LP0: AND ; /P:R PRINTS ON TT10: ; /D(ELETE) - DELETE AFTER PRINT, ONLY ; EFFECTIVE IF /P IS SPECIFIED. ; /S(CAN) - SCAN FILE FOR LAST GOOD RECORD. ; IF NOT SPECIFIED EOF MARK IS ; SAME AS BLOCKS ALLOCATED. /S WILL ; RESULT IN A CLEANER END OF FILE, ; BUT MAY TAKE A WHILE TO SCAN LARGE ; FILES. NOT SCANNING IS EQUIVALENT ; TO THE WAY 'RESET' WORKS, AND IS ; THE DEFAULT. ; ; ; RECOVER WILL UNLOCK THE FILE, IF LOCKED. UNLESS IT IS LOCKED DUE ; TO WRITE ACCESS BY AN ACTIVE TASK. THE FILE WILL THEN BE SCANNED (IF /S) ; TO DETERMINE CERTAIN CRITICAL ATTRIBUTES ANSD THE CORRECT VALUES OF ; THE ATTRIBUTES WILL BE WRITTEN IN THE FILE HEADER. ; ;- ; TASK BUILD FILE ; ; LINK/NOFLO/MULTI/TASK:RECOVER/OP RECOVER ; TASK=$$$REC ; UNITS=3 ; ASG=TI:2:3 ; PRI=60 ; UIC=[1,1] ; ACTFIL=3 ; / ; .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2,DIR$,QIOW$ .MCALL FINIT$,FSRSZ$,FDBDF$,FDOP$A,OPEN$U,CLOSE$,EXIT$S .MCALL FDRC$A,FHDOF$,GET$ .MCALL CSI$SW,CSI$ND,CSI$SV FHDOF$ DEF$L ;DEFINE FILE HEADER OFFSETS SERR: JMP SYNERR FERR: JMP FCSERR PATCH: FINIT$ ;INITIALIZE FSR ; ; READ AND RECODE THE COMMAND LINE START: GCML$ #GCLBLK ;GET COMMAND LINE BCC 10$ CMPB #GE.EOF,GCLBLK+G.ERR ;END OF FILE? BNE SERR ;SYNTAX ERROR IF NOT EXIT$S 10$: CLR CSIBLK+C.MKW1 ; RESET ALL SWITCHES CLR REMOTE ; AND /PR:REMOTE SETTING CSI$1 #CSIBLK,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD ;CHECK SYNTAX BCS SERR CSI$2 #CSIBLK,OUTPUT,#SWTAB ;DECODE IT BCS SERR ;SYNTAX ERROR IF NOT OKAY MOV #FDB,R0 ;FDB ADDRESS IN R0 MOV #FDB+F.FNB,R1 ;FNB ADDRESS IN R1 MOV #CSIBLK+C.DSDS,R2 ;DATASET POINTER IN R2 CLR R3 JSR PC,.PARSE ;PARSE THE FDB BCS FERR JSR PC,.FIND ;FIND THE FILE BCC 20$ CMPB #IE.NSF,FDB+F.ERR ;IS NO SUCH FILE? BNE FERR JMP NOFILE ; ; READ THE FILE HEADER AND UNLOCK THE FILE, IF LOCKED AND ; NOT BEING ACCESSED. 20$: MOV #RDHDR,READ+Q.IOPL+2 ;SET UP TO READ HEADER DIR$ #READ ;READ THE FILE HEADER BCS FERR ;CHECK FOR ERRORS MOV #RDSTAT,READ+Q.IOPL+2 ;SET UP TO READ STATISTICS BLOCK DIR$ #READ ;READ STATISTICS BLOCK BCS FERR TST STAT+10 ;IS FILE CURRENTLY IN USE? BEQ .+6 JMP FILUSE BITB #100,HEADER+H.UCHA ;IS FILE LOCKED? BEQ OPEN ;BRANCH IF NOT BIC #100,HEADER+H.UCHA ;CLEAR FILE LOCKED BIT DIR$ #WRITE ;WRITE THE CHARACTERISTICS BLOCK BCS FERR ;CECK IF ALL OK ; ;OPEN THE FILE AND PUT ACTUAL ATTRIBUTE VALUES IN THE FDB. OPEN: OPEN$U #FDB ;OPEN THE FILE BCC 5$ JMP FCSERR 5$: MOV STAT+4,FDB+F.HIBK ;UPDATE HIGH BLOCK MOV STAT+6,FDB+F.EFBK+2 ;AND MOV STAT+4,FDB+F.EFBK ;END OF FILE BLOCK MOV STAT+6,FDB+F.HIBK+2 ;FROM STATISTICS BLOCK INFORMATION TST FDB+F.FFBY ;IS END OF FILE BYTE DEFINED? BNE 10$ MOV #1000,FDB+F.FFBY ;IF NOT, MAKE IT 1000 10$: TST FDB+F.RSIZ ;IS RECORD SIZE DEFINED? BNE 20$ MOV #1000,FDB+F.RSIZ ;IF NOT MAKE IT 1000 20$: CMPB #R.FIX,FDB+F.RTYP ;FIXED LENGTH RECORDS? BEQ CLOSE ;IF SO, JUST CLOSE THE FILE BIT #SCMSK,CSIBLK+C.MKW1 ;CHECK FOR /SC BEQ CLOSE ;/SC NOT SET, GO CLOSE (OMIT SCAN) MOV #FDB+F.FNB,R1 ;CLOSE...AND.. MOV #HEADER,R2 MOV #30.,R3 50$: MOVB (R1)+,(R2)+ SOB R3,50$ CLOSE$ #FDB MOV #FDB+F.FNB,R1 ;MOVE NAME BLOCK BACK MOV #HEADER,R2 MOV #30.,R3 60$: MOVB (R2)+,(R1)+ SOB R3,60$ OPEN$U #FDB ;OPEN,OTHERWISE E-O-F TO FIRST GET BCS FCSERR ; ; SCAN THE FILE TO DETERMINE MAXIMUM RECORD SIZE. CONTINUE SCAN ; UNTIL AN ERROR OCCURS. CLR R1 SCAN: GET$ ;GET A RECORD BCS 25$ MOV FDB+F.VBN+2,R3 MOV FDB+F.NRBD+2,R2 ;GET POINTER TO LAST RECORD CMP R2,FDB+F.BDB ;IS IT IN BLOCK BUFFER OR USER BUF BLT 10$ SUB FDB+F.BDB,R2 ;SUBTRACT START OF BLOCK BUFFER SUB #S.BFHD,R2 ;ACCOUNT FOR BUFFER HEADER SUB #2,R2 ;OFFSET FOR COUNTER MOV R2,FFB MOV R3,VBN 10$: MOV FDB+F.NRBD,R4 ;RECORD SIZE ADD #1,R4 ;FOR ODD SIZE ASR R4 ASL R4 MOV FFB,R5 ADD R4,FFB ;FFBYTE AFTER THIS ADD #2,FFB ;RECORD 15$: CMP FFB,#1000 ;NEXT BLCK? BLE 20$ MOV R5,FFB2 ;YES. LAST GOOD BLOCK MOV VBN,VBN2 17$: SUB #1000,FFB ADD #1,VBN CMP FFB,#1000 BGT 17$ 20$: CMP R1,R4 ;RECORD GREATER? BGE SCAN MOV R4,R1 ;YES BR SCAN 25$: CMPB #IE.EOF,FDB+F.ERR ;EOF? BEQ 30$ MOV FFB2,FDB+F.FFBY ;NO. E-O-F TO LAST GOOD BLOCK MOV VBN2,FDB+F.EFBK+2 BR 40$ 30$: MOV FFB,FDB+F.FFBY ;YES. E-O-F TO LAST BLOCK MOV VBN,FDB+F.EFBK+2 40$: MOV R2,FDB+F.RSIZ ;UPDATE RECORD SIZE IN FDB BR CLOSE VBN: .WORD 1 VBN2: .WORD 1 FFB: .WORD 0 FFB2: .WORD 0 ; ; PUT CORRECT ATTRIBUTE VALUES IN THE FDB AND CLOSE THE FILE ; CLOSE: BIT #PRMSK,CSIBLK+C.MKW1 ;CHECK IF WANT TO PRINT IT BEQ CLOSE2 ;NO, JUST CLOSE MOV #"LP,PDEV ;DEFAULT TO LP CLR PUNIT ; - 0 MOV #1,PRES ;SET FOR PRESERV ON PRINT CMPB #'R,REMOTE ;SEND IT TO TT10: ? BNE NOREM ;NO , TO LP0: MOV #"TT,PDEV ;TT - MOV #10,PUNIT ;10: NOREM: BIT #DEMSK,CSIBLK+C.MKW1 ;CHECK /DE SWITCH BEQ PRINT ;NO DELETE, JUST PRINT IT CLR PRES ;/DE - SET FOR NO PRESERVE PRINT: MOV #QCALL,R5 ;F4P CALLING SEQUENCE JSR PC,QUEFIL ;QUE THE FILE TO LP0: JMP START ;GO DO NEXT FILE CLOSE2: CLOSE$ #FDB ;CLOSE THE FILE JMP START ; ; ERROR MESSAGES FCSERR: MOV #FCSMSG,QIOW+Q.IOPL MOV #15.,QIOW+Q.IOPL+2 MOV #FCSMSG+13,R0 MOVB FDB+F.ERR,R1 CLR R2 JSR PC,$CBDSG BR SYNERR NOFILE: MOV #NFLMSG,QIOW+Q.IOPL MOV #14.,QIOW+Q.IOPL+2 BR SYNERR FILEMP: MOV #FLEMSG,QIOW+Q.IOPL MOV #12.,QIOW+Q.IOPL+2 BR SYNERR FILUSE: MOV #FLUMSG,QIOW+Q.IOPL MOV #21.,QIOW+Q.IOPL+2 BR SYNERR SYNERR: DIR$ #QIOW JMP START QIOW: QIOW$ IO.WLB,3,2,,,, SYNMSG: .ASCII <12>/SYNTAX ERROR/<15> FCSMSG: .ASCII <12>/FCS ERROR /<15> FLUMSG: .ASCII <12>/FILE BEING ACCESSED/<15> FLEMSG: .ASCII <12>/FILE EMPTY/<15> NFLMSG: .ASCII <12>/NO SUCH FILE/<15> .EVEN ; ;COMMAND LINE MACROS AND DATA BLOCKS GCLBLK: GCMLB$ 1,FIL,HEADER,2 CSI$ .EVEN CSIBLK: .BLKB C.SIZE ;CSI BLOCK ; ; SET UP SWITCH TABLE ; SWTAB: CSI$SW S,SCMSK,,,,,LONG CSI$SW P,PRMSK,,,,PRSWV,LONG CSI$SW D,DEMSK,,,,,LONG CSI$ND SCMSK=1 PRMSK=2 DEMSK=4 PRSWV: CSI$SV ASCII,REMOTE,2 CSI$ND REMOTE: .BLKW 1 ; ; BLOCKS TO READ/WRITE FILE HEADER INFORMATION. READ: QIOW$ IO.RAT,1,1,,IOSB,, WRITE: QIOW$ IO.WAT,1,1,,IOSB,, IOSB: .BLKW 2 RDHDR: .BYTE -12,0 ;BLOCK TO READ FILE HEADER .WORD HEADER .WORD 0 RDSTAT: .BYTE -11,12 ;BLOCK TO READ STATICS BLOCK .WORD STAT .WORD 0 WRCHAR: .BYTE 3,1 ;BLOCK TO WRITE FILE CHARACTERIST .WORD HEADER+H.UCHA .WORD 0 HEADER: .BLKB 1000 STAT: .BLKW 5 ;BUFFER FOR STATISTICS BLOCK ; ; I/O MACROS AND DATA BLOCKS FSRSZ$ 1 ;SET UP FOR ONE LUN FDB: FDBDF$ ;START OF FDB FDOP$A 1,CSIBLK+C.DSDS FDRC$A FD.PLC,HEADER,1000 ; ; SET UP FOR F4P CALL TO QUEFIL ; QCALL: .WORD 4 ;NO OF PARMS TO FOLLOW .WORD FDB .WORD PDEV .WORD PUNIT .WORD PRES ; PDEV: .ASCII /LP/ PUNIT: .WORD 0 ; LP0: PRES: .WORD 1 ; PRESERVE FLAG, 0-DELETE, NON-0, PRESERVE .END PATCH .NLIST TTM