.TITLE UND .IDENT /X1.04/ .ENABL LC .NLIST TOC,SYM ; UU UU NN NN DDDDDD EEEEEEE LL EEEEEEE TTTTTTTT EEEEEEE ; UU UU NNN NN DD DD EE LL EE TT EE ; UU UU NNNN NN DD DD EE LL EE TT EE ; UU UU NN NN NN DD DD EEEEE LL EEEEE TT EEEEE ; UU UU NN NN NN DD DD EE LL EE TT EE ; UU UU NN NNNN DD DD EE LL EE TT EE ; UUUUU NN NNN DDDDDD EEEEEEE LLLLLLL EEEEEEE TT EEEEEEE ; ; ; Author: Richard J D Kirkman, ; Dept of Atmospheric Physics, Clarendon Laboratory, Oxford ; Date: 10th August 1980 ; Reference: "The Multi-Tasker", V15, No 1, 12-18 (July 1981) ; ; Modifications: C J Doran, ; Sira Institute Ltd., South Hill, Chislehurst, Kent, BR7 5EH ; ; Function: To attempt to recover a recently deleted file ; ; Algorithm: Accepts UIC of owner, input and output disks (MUST be different) ; Scans index file of input disk for deleted files, and uses ; IO.RLB form privileged task to read all blocks of a file ; which matches according to the map area of the file. ; ; Note: This program will only succeed in recovering a file if the file ; header has not been re-used. It will not check if the data blocks have been ; re-used, but will simply create a new file containing all the listed blocks ; with the listed attributes. ; ; Assemble as: ; >MAC UND=LB:[1,1]RUNMAC/ML,SY:[g,m]UND ; ; Task-build as: ; >TKB ; TKB>UND/PR:0/FP/MM/CP/-SE=UND ; TKB>/ ; ENTER OPTIONS: ; TKB>LIBR=FCSRES:RO ; TKB>STACK=64 ; TKB>TASK=...UND ; TKB>PRI=100 ; TKB>UNITS=5 ; TKB>ACTFIL=5 ; TKB>ASG=SY:1:2:3:4,TI:5 ; TKB>// .MCALL GCML$,GCMLB$,CSI$,CSI$1,CSI$2,CSI$ND,FHDOF$,FCSMC$,QIOW$M .MCALL EXIT$S,EXST$,EXST$R,QIOW$R,ALUN$S,QIOW$,DIR$,GLUN$S,ALUN$C FHDOF$ DEF$L CSI$ FCSMC$ .PSECT DATA,D,RW,LCL CSIBLK: .BLKB C.SIZE GCLBLK: GCMLB$ 4,UND,,1 OWNER: .WORD 0 ; UIC of owner STBK: .BLKW 8. BUF: .BLKB 80. HDR: .BLKW 256. DATA: .BLKW 256. .NLIST BEX ERR1: .ASCII "UND -*FATAL* Devices must be different" ERR1L=.-ERR1 ERR2: .ASCII "UND -*FATAL* Syntax error. Requires: ou:=in:[ggg,mmm]" ERR2L=.-ERR2 ERR3: .ASCII "UND -*FATAL* Index file open failure" ERR3L=.-ERR3 ERR4: .ASCII "UND -*FATAL* File write error" ERR4L=.-ERR4 ERR5: .ASCII "UND -*FATAL* File open error" ERR5L=.-ERR5 TXTLIN: .ASCII "UNDELETE X1.04: Recovery of " T1: .ASCII " to " T2: .ASCII " " TXTL=.-TXTLIN .EVEN .LIST BEX QIO: QIOW$ IO.WLB,5,5,,,,<,,40> QIO1: QIOW$ IO.WVB,1,1,,,,<,,40> QIO4: QIOW$ IO.RLB,4,4,,,, EXST: EXST$ EX$SUC FDB: FDBDF$ FDRC$A FD.RWM FDBK$A DATA,1000 FDOP$A 2,,DFNB,FO.WRT DFNB: NMBLK$ FILE,DAT,0 INDX: .WORD 0,0,5,INXU,10.,INXF INXU: .ASCII "[0,0]" INXF: .ASCII "INDEXF.SYS" .EVEN INXFDB: FDBDF$ FDRC$A FD.RWM FDBK$A HDR,1000 FDOP$A 3,INDX,,FO.RD FSRSZ$ 1 ; 1 for GCML .PSECT CODE,I,RO,LCL ; Program entry point. START: FINIT$ ALUN$C 1,TI,0,CODE RESTRT: GCML$ #GCLBLK ; Get a command line BCC 10$ DIR$ #EXST ; Exit with status if possible EXIT$S ; without if not supported 10$: CSI$1 #CSIBLK,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD BCS SYNERR CSI$2 ,OUTPUT ; Get output device BCS SYNERR BITB #,C.STAT(%0) BNE SYNERR BITB #CS.DVF,C.STAT(%0) BEQ SYNERR JSR PC,DEVICE ALUN$S #2,%3,%4 CSI$2 #CSIBLK,INPUT BCS SYNERR BITB #,C.STAT(%0) BNE SYNERR BITB #CS.DVF,C.STAT(%0) BEQ SYNERR JSR PC,.RDFUI ; Assume default UIC MOV %1,OWNER BITB #CS.DIF,CSIBLK+C.STAT ; But is one specified? BEQ 20$ ; No, keep default MOV #CSIBLK+C.DIRD,%2 ; Yes, point to ASCII string MOV #OWNER,%3 JSR PC,.ASCPP 20$: JSR PC,DEVICE ALUN$S #3,%3,%4 ALUN$S #4,%3,%4 JSR PC,DEVCHK BCS DEVERR JSR PC,INDEX ; Handle this index file BR START SYNERR: QIOW$M QIO,,,,,,,<#ERR2,#ERR2L> BR RES DEVERR: QIOW$M QIO,,,,,,,<#ERR1,#ERR1L> RES: DIR$ #QIO ; Output message MOV #EX$WAR,EXST+E.XSTS ; Set warning exit status BR RESTRT ; Get a new command line ; Fatal error. FATAL: DIR$ #QIO ; Output message EXST$R EXST,#EX$ERR ; Exit with error status if supported EXIT$S ; without if not ; Device check, returns C if devices on LUNS 2 and 3 are the same. DEVCHK: MOV #HDR,%0 GLUN$S #3,%0 ; Get info on input MOV @%0,%1 ; Save info MOVB 2(%0),%5 MOV #T1,%2 MOV %0,%4 MOVB (%4)+,(%2)+ MOVB (%4)+,(%2)+ MOVB (%4)+,%4 ADD #'0,%4 MOVB %4,(%2)+ MOVB #':,(%2)+ MOV OWNER,%3 CLR %4 JSR PC,.PPASC GLUN$S #2,%0 CMP %1,@%0 BNE 10$ ; Devices differ, OK CMPB %5,2(%0) ; Units BNE 10$ SEC RTS PC 10$: MOV #T2,%4 MOVB (%0)+,(%4)+ MOVB (%0)+,(%4)+ MOVB (%0)+,%0 ADD #'0,%0 MOVB %0,(%4)+ MOVB #':,(%4)+ QIOW$R QIO,,,,,,,<#TXTLIN,#TXTL> CLC RTS PC ; DEVICE -- Routine takes CSI block and returns device name in %3, unit in %4 ; for ALUN$ call. DEVICE: MOV #CSIBLK+C.DEVD,%0 ; Point to descriptor MOV (%0)+,%1 ; Get length MOV @%0,%0 ; and pointer MOVB (%0)+,%3 ; Get 1st char SWAB %3 CLRB %3 BISB (%0)+,%3 ; Get other char SWAB %3 ; Get order correct CLR %4 ; Unit def=0 SUB #2,%1 ; Used 2 of length BEQ 10$ ; If done stop 1$: CMPB @%0,#': ; or if ':' BEQ 10$ ; then also done MOVB (%0)+,%2 ; Else get char SUB #'0,%2 ; as integer ASH #3,%4 ; Multiply old %4 by 8. ADD %2,%4 ; and add in value DEC %1 ; Adjust count BGT 1$ ; More to do 10$: RTS PC ; %3,%4 set up, %0,%1,%2 destroyed ; Routine to handle index files. ; LUN2,LUN3,LUN4 assigned as required. INDEX: MOV #STBK,INXFDB+F.STBK OPEN$R #INXFDB BCC 10$ QIOW$M QIO,,,,,,,<#ERR3,#ERR3L> JMP FATAL 10$: MOV STBK+4,INXFDB+F.HIBK MOV STBK+4,INXFDB+F.EFBK MOV STBK+6,INXFDB+F.HIBK+2 MOV STBK+6,INXFDB+F.EFBK+2 READ$ #INXFDB ; Boot WAIT$ READ$ WAIT$ MOV HDR,%5 20$: READ$ WAIT$ SOB %5,20$ ; Skip bit map 30$: READ$ #INXFDB BCS 50$ WAIT$ BCS 50$ CMP HDR,#27027 ; Never used BNE 40$ TST HDR+2 BNE 40$ ; In use still JSR PC,CHECK BCS 40$ JSR PC,COPY 40$: BR 30$ 50$: CLOSE$ RTS PC ; Return for new command ; This is the main routine to copy a file. Entered after checking header ; is deleted and acceptable. ; ; Enter with HDR (256 words) file header for file to be copied, ; LUN 2 assigned to output device ; LUN 3 open in index file ; LUN 4 for block reads of input disk ; Functions to perform: ; a) Open output file of relevant name on LUN2. ; b) For all blocks of header of file, copy block to data buffer ; and then use WRITE$ to put in output file. ; c) Copy attributes back to FDB and close. ; d) Return -- done. COPY: MOV #HDR,%1 ; Get info address MOVB H.IDOF(%1),%2 ; Get offset to ID area MOVB H.MPOF(%1),%3 ; and to map area ASL %2 ASL %3 ADD %1,%2 ADD %1,%3 MOV #DFNB+N.FNAM,%4 ; Get address to stuff name info .REPT 4 ; Copy file name, type MOV (%2)+,(%4)+ .ENDR CLR @%4 ; But make a new version OPEN$W #FDB ; Open file for writing BCC 20$ QIOW$M QIO,,,,,,,<#ERR5,#ERR5L> JMP FATAL 20$: JSR PC,COPYBK MOV #HDR+H.UFAT,%1 ; Point to user attrib for file MOV #FDB,%0 MOV #7,%5 ; 7 words 30$: MOV (%1)+,(%0)+ SOB %5,30$ CLOSE$ #FDB ; Close with info restored RTS PC ; Routine to copy the file blocks pointed to by the map area. ; File now open on LUN2, %3 addresses map area. COPYBK: CLR %5 BISB M.USE(%3),%5 ADD #M.RTRV,%3 ; Is now pointer to first group 10$: TST %5 ; If nill or <0 then done BLE 50$ ; Now done CLR %1 CLR %4 BISB (%3)+,%4 BISB (%3)+,%1 MOV (%3)+,%2 20$: QIOW$R QIO4,,,,,,,<,,,%4,%2> WRITE$ #FDB BCS 35$ 30$: WAIT$ BCC 40$ 35$: QIOW$M QIO,,,,,,,<#ERR4,#ERR4L> JMP FATAL 40$: ADD #1,%2 ; Step on block number ADCB %4 ; in DP DEC %1 ; Done when neg BPL 20$ ; at least 1 more to do SUB #2,%5 BR 10$ 50$: RTS PC ; Routine to check if file is to be copied to output media ; ; Entered with block HDR conataining file's header. ; ; Result: C set -- do not copy ; C clr -- copy to other media CHECK: CMP HDR+H.FOWN,OWNER ; Correct user? BNE 10$ ; Could insert other checks here. ; ; Display name of file to be recovered. MOV #BUF,%0 MOV #HDR+S.HDHD,%5 MOV (%5)+,%1 JSR PC,$C5TA MOV (%5)+,%1 JSR PC,$C5TA MOV (%5)+,%1 JSR PC,$C5TA MOVB #'.,(%0)+ MOV (%5)+,%1 JSR PC,$C5TA MOVB #';,(%0)+ MOV (%5)+,%1 CLR %2 JSR PC,$CBOMG MOV #BUF,%1 SUB %1,%0 QIOW$R QIO1,,,,,,,<%1,%0> TST (PC)+ ; Clear carry, skipping SEC 10$: SEC RTS PC .END START