.TITLE FILFIX 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 ; ; CALLING SEQUENCE ; ; MCR>FIL[FIX] FNAME ; FNAME = NAME OF CORRUPTED FILE ; ; PATCH WILL UNLOCK THE FILE. IF LOCKED. INLESS IT IS LOCKED DUE ; TO WRITE ACCESS BY AN ACTIVE TASK. THE FILE WILL THEN BE SCANNED ; TO DETERMINE CERTAIN CRITICAL ATTRIBUTES ANSD THE CORRECT VALUES OF ; THE ATTRIBUTES WILL BE WRITTEN IN THE FILE HEADER. ; ; TASK BUILD FILE ; ; FILFIX/-FP=FILFIX ; / ; TASK=...PAT ; UNITS =2 ; ASG=TI:2 ; PRI=60 ; STACK=21 ; // ; .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$ 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$: CSI$1 #CSIBLK,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD ;CHECK SYNTAX BCS SERR CSI$2 #CSIBLK,OUTPUT ;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$: 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 BITB #100,HEADER+H.UCHA ;IS FILE LOCKED? BEQ OPEN ;BRANCH IF NOT TST STAT+10 ;IS FILE CURRENTLY IN USE? BEQ .+6 JMP FILUSE 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 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: CLOSE$ #FDB ;CLOSE THE FILE JMP START ; ; ERROR MESSAGES 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 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 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 ; ; 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 ; .END PATCH