.TITLE FILPAT ; ; MCR TASK TO RECONSTRUCT A FILE CORRUPTED BY AN ABORTED TASK. ; ; WRITTEN NOVEMBER 1976 R B FRENCH THE BOEING CO. ; ; CALLING SEQUENCE ; ; MCR>FIL[PATCH] FNAME ; ; FNAME = NAME OF CORRUPTED FILE. ; ; FILPAT WILL UNLOCK THE FILE, IF LOCKED, UNLESS IT IS LOCKED DUE ; TO WRITE ACCESS BY AN ACTIVE TASK. THE FILE WILL THEN BE SCANNED ; TO DETERMINE CERTAIN CRITICAL ATTRIBUTES AND THE CORRECT VALUES OF THE ; ATTRIBUTES WILL BE WRITTEN IN THE FILE HEADER. ; NOTE - THE CURRENT VERSION DOES NOT CHECK FOR FILE HEADER ; EXTENSIONS. THIS CAPABILITY WILL BE ADDED AT A LATER DATE. ; ; TASK BUILD FILE ; ; FIL/-FP/MU=FIL,[1,1]EXEC.STB/SS ; / ; TASK=...FIL ; UNITS=3 ; ASG=TI:2:3 ; PRI=60 ; STACK=64 ; LIBR=SYSRES:RO ; ; ; MAXIMUM BUFFER SIZE. THIS IS THE LARGEST RECORD LENGTH THAT ; THE PROGRAM CAN HANDLE UNLESS FIXED LENGTH RECORDS ARE USED. ; NOTE THAT FORTRAN PROGRAMS ARE NOT RESTRICTED BECAUSE THE ; DIRECT ACCESS FILES ARE R.FIX AND THE SEQUENTIAL FILES HAVE ; A SMALL RECORD LENGTH. ; MAXBUF = 2000 ; ; DEFAULT BUFFER SIZE CASE. THE BUFFER SIZE CAN BE CHANGED WITH ; THE /RL:BUFSIZ SWITCH OR THE /ED SWITCH. /RL TAKES THE RECORD ; SIZE IN DECIMAL BYTES, AND CANNOT BE GREATER THAN MAXBUF. THE ; /ED SWITCH USES EDITOR-SIZED LINES. ; DEFALT = 130. ;EDITOR-SIZED LINES. ; ; SWITCH MASK DEFINITIONS AND MACRO CALLS ; RL = 000001 ED = 000002 ; .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2,QIOW$ .MCALL FINIT$,FSRSZ$,FDBDF$,FDOP$A,OPEN$U,CLOSE$,EXIT$S .MCALL FDRC$A,FHDOF$,GET$,FDRC$R,CSI$SW,CSI$ND,CSI$SV .MCALL FDOP$R,NBOF$L FHDOF$ DEF$L ;DEFINE FILE HEADER OFFSETS NBOF$L ;DEFINE SOME VALUES. CMLERR: CMPB #GE.IOR,GCLBLK+G.ERR ;I/O ERROR? BEQ 10$ ;YES CMPB #GE.EOF,GCLBLK+G.ERR ;END OF FILE? BNE 20$ ;SYNTAX ERROR IF NOT EXIT$S 10$: MOV #IORMSG,QIOW+Q.IOPL MOV #IORLEN,QIOW+Q.IOPL+2 MOV #QIOW,-(SP) CALL .DIRDL EXIT$S 20$: CMPB #GE.OPR,GCLBLK+G.ERR ;OPEN FAILURE? BNE 30$ ;NO MOV #COPMSG,QIOW+Q.IOPL MOV #COPLEN,QIOW+Q.IOPL+2 BR XQIO 30$: CMPB #GE.BIF,GCLBLK+G.ERR ;SYNTAX ERROR IN @ FILE? BNE 40$ ;NO MOV #CSNMSG,QIOW+Q.IOPL MOV #CSNLEN,QIOW+Q.IOPL+2 BR XQIO 40$: CMPB #GE.MDE,GCLBLK+G.ERR ;MAX @ FILE DEPTH? BNE 50$ MOV #CMXMSG,QIOW+Q.IOPL MOV #CMXLEN,QIOW+Q.IOPL+2 BR XQIO 50$: MOV #CUKMSG,QIOW+Q.IOPL MOV #CUKLEN,QIOW+Q.IOPL+2 BR XQIO SERR2: MOV #CP2MSG,QIOW+Q.IOPL MOV #CP2LEN,QIOW+Q.IOPL+2 BR XQIO SVALUE: MOV #ILVMSG,QIOW+Q.IOPL MOV #ILVLEN,QIOW+Q.IOPL+2 BR XQIO SCONF: MOV #CONMSG,QIOW+Q.IOPL MOV #CONLEN,QIOW+Q.IOPL+2 BR XQIO SERR: MOV #SYNMSG,QIOW+Q.IOPL MOV #SYNLEN,QIOW+Q.IOPL+2 XQIO: MOV #QIOW,-(SP) CALL .DIRDL BR START FERR: JMP FCSERR FILPAT: FINIT$ ;INIT FSR ; ; CHANGE OUR HEADER UIC TO [1,3] SO WE WILL LOOK LIKE A SYSTEM TASK ; ; MOV .CRTSK,R0 ;GET ATL NODE ADR ; MOV A.TD(R0),R1 ;GET OUR STD ADDRESS ; MOV S.LZ(R1),R2 ;GET LENGTH OF TASK ; ASH #8.,R2 ;SHIFT TO CORRECT POSITION ; BIC #100377,R2 ;CLEAR OUT GARBAGE ; BIS #6,R2 ;READ/WRITE ACCESS ; MOV R2,-(SP) ;SAVE ON STACK ; MOV A.HA(R0),-(SP) ;MAP APR3 TO OUR HEADER ; JSR PC,..SPD3 ;DO THE MAPPING ; CMP (SP)+,(SP)+ ;CLEAN STACK ; MOV #403,60000+H.UIC ;CHANGE HEADER UIC TO [1,3] ; ; READ AND RECODE THE COMMAND LINE ; START: GCML$ #GCLBLK ;GET COMMAND LINE BCS CMLERR TST GCLBLK+G.CMLD ;ANYTHING? BEQ START ;NO CSI$1 #CSIBLK,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD ;CHECK SYNTAX BCS SERR CSI$2 #CSIBLK,OUTPUT,#SWTAB ;DECODE IT BCS SERR2 ;SYNTAX ERROR IF NOT OK BIT #RL,FLAGS ;RECORD LENGTH SPEC? BEQ 14$ ;NO CMP RECLEN,#MAXBUF ;TOO LONG TO PROCESS? BHI SVALUE ;YES TST RECLEN ;IS IT 0? BEQ SVALUE ;YES -- ERROR BIT #ED,FLAGS ;EDIT FILE TOO? BNE SCONF ;ERROR IF SO. BR 16$ ;SKIP EDIT PROCESSING. 14$: BIT #ED,FLAGS ;EDITOR FILE? BEQ 16$ ;SKIP IF SO MOV #130.,RECLEN ;GET RECORD LENGTH 16$: FDRC$R #FDB,,,RECLEN 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$ JMP FERR ; ; READ THE FILE HEADER AND UNLOCK THE FILE, IF LOCKED AND ; NOT BEING ACCESSED. ; 20$: MOV #RDHDR,READ+Q.IOPL+2 MOV #READ,-(SP) ;READ THE FILE HEADER CALL .DIRDL MOVB IOST,FDB+F.ERR BCS FERR ;CHECK FOR ERRORS. BITB #100,HEADER+H.UCHA ;IS FILE LOCKED? BEQ COUNT ;BRANCH IF NOT MOV #RDSTAT,READ+Q.IOPL+2 ;SET UP TO READ STATISTICS BLOCK MOV #READ,-(SP) CALL .DIRDL MOVB IOST,FDB+F.ERR BCS FERR TST STAT+10 ;IS FILE CURRENTLY IN USE? BEQ 25$ JMP FILUSE 25$: BIC #100,HEADER+H.UCHA ;CLEAR FILE LOCKED BIT MOV #WRITE,-(SP) ;WRITE THE CHARACTERISTICS BLOCK CALL .DIRDL MOVB IOST,FDB+F.ERR BCS FERR ;CHECK IF ALL OK ; ; SCAN THE FILE HEADER MAP AREA AND COUNT THE NUMBER OF ; BLOCKS ACTUALLY ALLOCATED. ; COUNT: MOV #HEADER+134,R1 ;MAP AREA OFFSETS IN R1 MOV R1,R2 ;AND R2 MOVB M.USE(R2),R2 ;NUMBER OF POINTERS IN R2 BIC #177400,R2 BNE 5$ ;FILE EMPTY IF ZERO JMP FILEMP 5$: ASR R2 ADD #M.RTRV+1,R1 ;START OF POINTERS IN R1 CLR R4 10$: MOVB (R1),R3 ;BLOCK COUNT-1 IN R3 BIC #177400,R3 INC R3 ;MAKE IT BLOCK COUNT ADD R3,R4 ;ADD TO TOTAL BLOCK COUNT ADD #4,R1 ;STEP TO NEXT POINTER SOB R2,10$ ; ; OPEN THE FILE AND PUT ACTUAL AATTRIBUTE VALUES IN THE FDB ; OPEN: OPEN$U #FDB ;OPEN THE FILE. BCC 1$ ;ERROR? JMP FCSERR ;YES 1$: MOV #S.FNBW,R1 ;GET SIZE OF FNB MOV #FNBBLK,R2 ;GET ADDR OF TEMP. FNB MOV #FDB+F.FNB,R3 ;GET ADDR OF CURRENT FNB 5$: MOV (R3)+,(R2)+ ;MOVE IT IN SOB R1,5$ ;AND LOOP CLR FDB+F.HIBK ;PUT BLOCK COUNT IN F.HIBK MOV R4,FDB+F.HIBK+2 CLR FDB+F.EFBK ;PUT BLOCK COUNT IN F.EFBK MOV R4,FDB+F.EFBK+2 TST FDB+F.FFBY ;IS THE END OF FILE BYTE DEFINED? BNE 10$ MOV #1000,FDB+F.FFBY ;IF NOT, MAKE IT 1000 10$: BITB #FD.RWM,FDB+F.RACC ;BLOCK MODE ACCESS? BNE CLOSE ;THEN JUST CLOSE THE FILE TST FDB+F.RSIZ ;IS THE RECORD SIZE DEFINED? BNE 20$ MOV RECLEN,FDB+F.RSIZ ;IF NOT MAKE IT DEFAULT 20$: CMPB #R.FIX,FDB+F.NRBD ;FIXED LENGTH RECORDS? BEQ CLOSE ;IF SO, JUST CLOSE THE FILE CLOSE$ #FDB ;CLOSE FILE BCS FCSERR MOV #S.FNBW,R1 ;GET SIZE OF FNB MOV #FNBBLK,R2 ;GET ADDR OF TEMP. FNB MOV #FDB+F.FNB,R3 ;GET ADDR OF CURRENT FNB 25$: MOV (R2)+,(R3)+ ;MOVE IT BACK IN SOB R1,25$ ;AND LOOP FDOP$R R0,#1 FDRC$R R0,#FD.PLC,#HEADER OPEN$U R0 ;RE-OPEN BCS FCSERR ;ERROR? ; ; SCAN THE FILE TO DETERMINE MAXIMUM RECORD SIZE. CONTINUE SCAN ; UNTIL AN ERROR OCCURS. ; CLR R1 ;R1 WILL HAVE MAX REC. LENGTH. SCAN: GET$ ;GET A RECORD BCC 30$ ;CHECK FOR ERROR CMPB #IE.EOF,FDB+F.ERR ;END OF FILE? BEQ 40$ ;IF SO, GO WRAP IT UP 5$: MOV FDB+F.NRBD+2,R2 ;GET POINTER TO LAST RECORD CMP R2,FDB+F.BDB ;IS IT IN BLOCK BUFFER OR USER BUFFER? BLO 10$ SUB FDB+F.BDB,R2 ;SUBTRACT START OF BLOCK BUFFER SUB #S.BFHD,R2 ;ACCOUNT FOR BUFFER HEADER BR 20$ 10$: SUB #HEADER,R2 ;SUBTRACT START OF BUFFER 20$: SUB #2,R2 ;OFFSET FOR COUNTER MOV R2,FDB+F.FFBY ;START OF BAD RECORD IS FIRST FREE BYTE MOV FDB+F.VBN,FDB+F.EFBK ;CHANGE END OF FILE BLOCK MOV FDB+F.VBN+2,FDB+F.EFBK+2 BR 40$ 30$: CMP FDB+F.NRBD,RECLEN ;GREATER THAN RECORD LENGTH? BHI 5$ ;YES CMP R1,FDB+F.NRBD ;CHECK RECORD SIZE BGE SCAN MOV FDB+F.NRBD,R1 ;R1 HAS LARGEST RECORD SIZE BR SCAN 40$: MOV R1,FDB+F.RSIZ ;PUT RECORD SIZE IN FDB ; ; PUT CORRECT ATTRIBUTE VALUES IN FDB AND CLOSE THE FILE ; CLOSE: CLOSE$ #FDB ;CLOSE THE FILE BCS FCSERR ;ERROR? JMP START ; ; ERROR MESSAGES ; FILEMP: MOV #FLEMSG,QIOW+Q.IOPL MOV #FLELEN,QIOW+Q.IOPL+2 BR MSGQIO FILUSE: MOV #FLUMSG,QIOW+Q.IOPL MOV #FLULEN,QIOW+Q.IOPL+2 MSGQIO: MOV #QIOW,-(SP) CALL .DIRDL JMP START FCSERR: MOV #FCSMSG,R1 ;GET FCS MSG MOV #FCSLEN,R2 ;AND LEN CALL .PRFCS ;PRINT CODE CLOSE$ #FDB ;CLOSE FILE JMP START ;AND RESTART QIOW: QIOW$ IO.WVB,2,1,,,,<,,40> FCSMSG: .ASCII /FIL/ FCSLEN = .-FCSMSG SYNMSG: .ASCII /FIL -- SYNTAX ERROR/ SYNLEN = .-SYNMSG FLUMSG: .ASCII /FIL -- FILE BEING ACCESSED/ FLULEN = .-FLUMSG FLEMSG: .ASCII /FIL -- FILE EMPTY/ FLELEN = .-FLEMSG IORMSG: .ASCII "FIL -- I/O ERROR ON @ FILE" IORLEN = .-IORMSG COPMSG: .ASCII /FIL -- OPEN FAILURE FOR @ FILE/ COPLEN = .-COPMSG CSNMSG: .ASCII /FIL -- SYNTAX ERROR FOR @ FILE/ CSNLEN = .-CSNMSG CMXMSG: .ASCII /FIL -- MAX @ FILE DEPTH EXCEEDED/ CMXLEN = .-CMXMSG CUKMSG: .ASCII /FIL -- UNKNOWN COMMAND ERROR/ CUKLEN = .-CUKMSG CP2MSG: .ASCII /FIL -- ILLEGAL SWITCH/ CP2LEN = .-CP2MSG ILVMSG: .ASCII /FIL -- ILLEGAL SWITCH VALUE/ ILVLEN = .-ILVMSG CONMSG: .ASCII /FIL -- CONFLICTING SWITCHES/ CONLEN = .-CONMSG .EVEN ; ; COMMAND LINE MACROS AND DATA BLOCKS ; GCLBLK: GCMLB$ 1,FIL,HEADER,3 CSI$ .EVEN CSIBLK: .BLKB C.SIZE ;CSI BLOCK SWTAB: CSI$SW ED,ED,FLAGS,SET,NEG CSI$SW RL,RL,FLAGS,SET,,SWVAL CSI$ND SWVAL: CSI$SV DECIMAL,RECLEN,2 CSI$ND RECLEN: DEFALT ;RECORD LENGTH FLAGS: 0 ;FLAGS WORD. FNBBLK: .BLKW S.FNBW ; ; BLOCKS TO READ/WRITE FILE HEADER INFORMATION ; READ: QIOW$ IO.RAT,1,1,,IOST,, WRITE: QIOW$ IO.WAT,1,1,,IOST,, IOST: .BLKW 2 RDHDR: .BYTE -12,0 ;BLOCK TO READ FILE HEADER .WORD HEADER .WORD 0 RDSTAT: .BYTE -11,12 ;BLOCK TO READ STATISTICS BLOCK .WORD STAT .WORD 0 WRCHAR: .BYTE 3,1 ;BLOCK TO WRITE FILE CHARACTERISTICS .WORD HEADER+H.UCHA .WORD 0 HEADER: .BLKB MAXBUF STAT: .BLKW 5 ;BUFFER FOR STATISTICS BLOCK ; ; I/O MACROS AND DATA BLOCKS ; FSRSZ$ 1 ;SET UP FOR 1 LUN FDB: FDBDF$ ;START OF FDB FDOP$A 1,CSIBLK+C.DSDS FDRC$A FD.PLC,HEADER,DEFALT ; .END FILPAT