;FIXDEL.M68 Recover a file that has been accidently erased
;Completely rewritten 03-86
;No longer is DSKANA required to retrieve the lost disk blocks
;11-27-86 Change FNDUFD to use Alpha Micro's Call $FNPPN
; Allow File Spec on command line when calling program
; (FIXDEL DSK0:[75,1])
; written by Steve Farnum
OBJNAM FIXDEL.LIT
GETIMP D.DDB,MFD ; DDB for MFD & UFD directories
GETIMP D.DDB,BDDB ; DDB for bitmap area
CMPB (A2),#15 ; anything entered
BNE CHKINP ; yep, start processing
START:
TYPESP <Enter Erased File Device & PPN (DEVN:[P,PN]) >
KBD ENDIT
CMPB (A2),#15 ; anything entered ?
JEQ ENDIT ; no, tell user
CHKINP:
CALL OPNFIL ; open ddb buffers
CLR FLAGS ; clear flag counter
CALL FNDUFD ; find desired UFD
TST FLAGS ; UFD found ?
JNE NOPPN ; no exit
CALL DSPDEL ; display deleted records in ppn
TST FLAGS ; any record found
JEQ NODR ; no exit
NEWNAM:
PUSH DSPLY ; save buffer index offset
PUSH D.REC(UFD) ; save ufd record
CALL GETBMP ; index bitmap area and hash total
CLR FLAGS
CRLF
TYPESP <Resetting Bitmap >
CMPW CONTIG(BUFF),#DELREC ; is the file contiguous
BNE SETBLK ; no, find all blocks
MOVW BLOCKS(BUFF),COUNTR ; no of block to reallocate
CNTFIL:
CALL SETBIT ; set block in use in bitmap
TST FLAGS ; block already in use bad news
JNE BADFIL ; tell user
INC RECNO ; set next block
SOB COUNTR,CNTFIL ; set all blocks
JMP GODFIL ; release bitmap
SETBLK:
MOV RECNO,D.REC(UFD) ; set up to read next linked block
READ (UFD) ; read block
CALL SETBIT ; set block in use in bitmap
TST FLAGS ; block already in use bad news
JNE BADFIL ; tell user
MOV D.BUF(UFD),BUFF ; check if there is another block linked
MOVW (BUFF),RECNO ; next link
TST RECNO
BNE SETBLK ; yes, set bit
JMP GODFIL
SETBIT:
CLR DSPLY ; clear work reg
PUSH RECNO ; save record number
DIV RECNO,#^H10 ; divide by 16 (a word)
MOVW RECNO,OFFSET ; compute bitmap word
ASL OFFSET ; mul * 2 to find correct offset
MOVW 0(BADD)[~OFFSET],DSPLY ; get bitmap word
SWAP RECNO ; get remainder = bit to set
BTST RECNO,DSPLY ; is block free
BEQ SETOK ; yes, ok to set block
SET FLAGS ; no output error message
BR ENDBIT
SETOK:
SUB DSPLY,HASH ; calculate new hash total
BSET RECNO,DSPLY ; set block in bitmap
MOVW DSPLY,0(BADD)[~OFFSET] ; write new bitmap block word
ADD DSPLY,HASH ; update hash total
TYPE <.>
ENDBIT:
POP RECNO ; restore record number
RTN
GETBMP:
DSKBMR (BDDB) ; read & lock bitmap
MOV D.ARG(BDDB),BMP ; get address of bitmap area
MOV BMP,BADD ; save bitmap address
SUB #BM.SIZ,BMP ; index bitmap ddb
MOV D.SIZ(BMP),BMPSIZ ; no of bytes in bitmap + hash total
SUB #4,BMPSIZ ; compute bitmap size in bytes
MOV D.BUF(BMP),HADD ; compute hash total address
ADD BMPSIZ,HADD ;
MOV (HADD),HASH ; get bitmap hash total
SWAP HASH ;
RTN
; Allocate DDB For reading and writing
OPNFIL:
PUSH A2 ; save file spec pointer
CLR D.DEV(BDDB)
CLR D.FIL(BDDB)
CLR D.EXT(BDDB)
CLR D.DEV(MFD)
CLR D.FIL(MFD)
CLR D.EXT(MFD)
FSPEC (BDDB) ; setup for bitmap read
INIT (BDDB)
POP A2 ; restore ascii file spec
FSPEC (MFD)
INIT (MFD) ; get buffers for input ddb
RTN
; Read the MFD and find desired UFD on specified device
FNDUFD:
CLR D1
MOVW D.PPN(MFD),D1 ; octal ppn now in d1
MOV MFD,A2 ; set A2 fo ppn find call
CALL $FNPPN
MOV D0,FLAGS ; D0 = completions codes
CLR RECNO
CLR OFFSET
MOVW UFDLNK(MFD),RECNO ; store ufd link address
MOV A2,MFD
RTN
;Target PPN found check for deleted records
DSPDEL:
REDPPN:
CLR FLAGS ; no deleted records yet
TST RECNO ; at end of ufd link
JEQ ENDDSP ; yes exit program
MOV RECNO,D.REC(UFD) ; set up for block read
READ (UFD) ; read ufd
MOV D.BUF(UFD),BUFF ; save buffer address
MOVW #^H0FF00,DSPLY ; clear screen
TCRT
CRLF
MOV #UFDTOT,COUNTR ; max ufd's per block
MOVW (BUFF)+,RECNO ; next ufd block link 1st word
CLR DSPLY
PPNLOP:
CMPW (BUFF),#DELREC ; deleted record ?
BNE NXTFIL ; no, look at nxt file
TYPE <(> ; output file name to screen
DCVT 2,OT$TRM
TYPE <)>
PRNAM (BUFF)
INC OFFSET
CMP OFFSET,#WIDTH
BLT SPACE
CRLF
CLR OFFSET
BR NOSPAC
SPACE:
TAB
NOSPAC:
SET FLAGS ; deleted records found
NXTFIL:
INC DSPLY ; index next filname
ADDW #UFDSIZ,BUFF ; and display it
SOB COUNTR,PPNLOP
;Check for another UFD for this PPN
;Or for the file to save
NXTUFD:
TST FLAGS ; any deleted records found
JEQ REDPPN ; no read next ufd link
CRLF
CRLF
TYPESP <Enter Number Of Erase File or CR For Next Block >
KBD ENDIT
CMPB (A2),#15 ; anything entered ?
JEQ REDPPN ; no, check for another ufd
CLR DSPLY ; conver ascii to a number
GTDEC
TYPESP <Enter New Filename (FILNAM.EXT) >
KBD ENDIT
MOV D.BUF(UFD),BUFF ; index buffer start
ADD #2,BUFF ; skip link word
MUL DSPLY,#UFDSIZ ; calulate offset size * ufdsiz
ADD DSPLY,BUFF ; index offset
FILNAM D.FIL(UFD) ; write new file name to ufd
MOVW BLOKNO(BUFF),RECNO ; set up to read the block
ENDDSP:
RTN
GODFIL:
POP D.REC(UFD) ; restore ufd record number
READ (UFD) ; re-read ufd record
POP DSPLY
MOV D.BUF(UFD),BUFF ; index buffer start
ADD #2,BUFF ; skip link word
ADD DSPLY,BUFF ; index offset
MOVW D.FIL(UFD),(BUFF) ; write new file name to ufd
MOV <D.FIL+2>(UFD),2(BUFF)
WRITE (UFD) ; rewrite UFD block
SWAP HASH ; write out new bitmap
MOV HASH,(HADD) ; hash total
ORW #BM$REW,<BM.SIZ-2>(BMP) ; set bitmap rewrite flag
XORW #BM$LOK,<BM.SIZ-2>(BMP) ; clear bitmap lock flag
DSKBMW (BDDB) ; rewite bitmap
CRLF
CRLF
TYPECR <Your Erased File Has Now Been Restored !!!!!! >
JMP ENDIT
BADFIL:
POP ; clear stack
POP ; clear stack
XORW #BM$LOK,<BM.SIZ-2>(BMP) ; clear bitmap lock flag
CRLF
TYPECR <I am sorry your file cannot be fully recovered.>
TYPECR <Some blocks have already been reassigned to another file.>
TYPECR <Run DSKANA to recover any blocks that may have been set.>
TYPECR <You should really be more carefull in the future>
BR ENDIT
NOPPN:
TYPECR <That PPN does not exist on specified device>
BR ENDIT
NODR:
TYPECR <No deleted records found in specified PPN>
BR ENDIT
ENDIT:
CRLF
TYPESP <Want to unerase another File ??? >
KBD THEEND
CMPB (A2),#15 ; anything entered ?
BEQ THEEND ; no, tell user
CMPB (A2),#'N
BEQ THEEND
CMPB (A2),#'n
BEQ THEEND
JMP START
THEEND:
CRLF
EXIT
END