.TITLE FILSAV - TO SAVE A FILE AFTER IT HAS BEEN DELETED ; ; THIS PROGRAM ATTEMPTS TO RECOVER A FILE THAT HAS BEEN DELETED. ; TO DO THIS IS READS THE DISK TO FIND THE FILE HEADER FOR THE FILE ; (WHICH IS NOT TOUCHED WHEN THE FILE IS DELETED) AND THEN READS ; THE BLOCKS THAT MADE UP THE FILE AND OUTPUTS THEM TO THE OUTPUT ; FILE (WHICH IS CALLED THE SAME AS THE ONE BEING RESTORED). ; ; NOTE THAT: 1) THE DISK ON WHICH THE FILE RESIDED MUST BE DISMOUNTED ; 2) THE OUTPUT FILE WILL BE CREATED AS IF IT WERE AN EDITED FILE ; ; ; ; Written by:- ; ; Phil Stephensen-Payne, ; c/o Systime Ltd., ; Concourse Computer Centre, ; 432 Dewsbury Road, ; LEEDS LS11 7DF, ; England. ; .MCALL QIOW$S,EXIT$S,$CALLG,EXIT$S,NMBLK$,$BASTS,GTSK$S .MCALL FSRSZ$,FINIT$,GCMLB$,GCMLD$,GCML$ .MCALL WTSE$S,SPWN$,DIR$,ALUN$S FSRSZ$ 2 GCML: GCMLB$ 1,FSV,,6 ;1 INDIRECT FILE, PROMPT FSV>, LUN 6 GCMLD$ ;DEFINE OFFSETS DIRFNB:: ;FILENAME BLOCK FOR DIRECTORY SEARCH .BLKW 3 ;FILE ID (UNKNOWN) DIRNAM:: .RAD50 /001202 / ;FILENAME .RAD50 /DIR/ ;EXTENSION .WORD 1 ;VERSION .WORD 0,0 ;STATUS AND NEXT .WORD 4,4,0 ;MFD DIRECTORY ID .ASCII /SY/ ;DEVICE .WORD 0 ;NUMBER MLGATT:: .BYTE 5,12 ;ATTRIBUTE LIST FOR CREATION .WORD MLGFNB+N.FNAM ;FILENAME .BYTE 4,16 ;FILE ATTRIBUTES .WORD MLGFTT .BYTE 1,4 ;UIC AND PROTECTION .WORD UIC .WORD 0 MLGFTT:: .BYTE 2,2 ;RECORD TYPE & ATTRIBUTES .WORD 512. ;RECORD SIZE .WORD 0 ;HIGH-BLOCK HIB: .WORD 0 .WORD 0 ;END-OF-FILE.. EOF: .WORD 0 FFB: .WORD 0 ;FIRST FREE BYTE UIC:: .WORD 602,0 ;UIC & PROTECTION (RWED EVERYWHERE) NOMSG: .ASCII /NO SUCH FILE!/ NOMSL=.-NOMSG ENDMSG: .ASCII /DONE!/ ENDMSL=.-ENDMSG .EVEN HLSPWN: SPWN$ MCR...,,,,,1,,,HELCMD,HELCML HELCMD: .ASCII /HELP FSV/ HELCML=.-HELCMD .EVEN ; STATUS: .WORD ;STATUS RETURN FOR SUBROUTINES CNVTMP: .BLKB 6 ;STORE FOR CONVERTING DIRECTORY NAME VERS: .BLKW 2 ;STORE FOR THE VERSION NUMBER MLGFNB: ;AREA FOR FILENAME BLOCK .WORD 0,0,0 ;UNKNOWN FILE ID STRING: .BLKW 5 ;FILENAME TO BE SEARCHED FOR .WORD 0,0,0,0,0 ;UNKNOWN OTHER BITS .ASCII /SY/ .WORD 0 BLKS=90. BUFFER: .BLKB 512.*BLKS INDBLK: .BLKB 512. ;INDEX FILE HEADER IOSB: .BLKW 2 NUMCHR: .WORD 6 RADIX: .WORD 8. INBUF: .BLKB 30. OUTSTR: ASC1: .BLKB 9. .ASCII /./ ASC2: .BLKB 3 .ASCII /;/ ASC3: .BLKB 6 .ASCII / - / SIZE: .BLKB 6 .ASCII / BLOCKS./ OUTLEN=.-OUTSTR .EVEN BLOCK: .BLKW 2 BLKSTR: .BLKW 2 BLOCK1: .BLKW 2 ; START: ALUN$S #6,#"TI,#0 ; Assign prompt lun to TI: FINIT$ ; CLR BLKSTR CLR BLKSTR+2 ; NEXT: GCML$ #GCML ;GET A COMMAND LINE BCC OK ;IF CC OK JMP EXIT ;ELSE GIVE UP ; OK: MOV GCML+G.CMLD+2,R0 ; Get address of input CMPB (R0)+,#'/ ; Help required? BNE 5$ ; No - carry on CMPB (R0)+,#'H ; Sure? BNE 5$ ; no - carry on CMPB (R0)+,#'E ; Positive? BNE 5$ ; No - carry on DIR$ #HLSPWN ; Yes - ask for help WTSE$S #1 ; Wait for it to finish BR NEXT ; Get next line ; 5$: MOV #8.,RADIX ;SET RADIX AS OCTAL $CALLG ASCBIN,#GCML+G.CMLD,GCML+G.CMLD+2,#RADIX,#BLOCK,#STATUS TST STATUS ;OK? BNE 10$ ;IF NE NO - MUST BE FILENAME MOV BLOCK,BLKSTR ;YES - RESET BLOCK STORE MOV BLOCK+2,BLKSTR+2 ; BR NEXT ;AND GET NEXT ; 10$: GTSK$S #BUFFER ;GET TASK PARAMETERS MOV #BUFFER,R0 ;GET ADDRESS OF BUFFER MOV G.TSPC(R0),UIC ;STORE UIC FOR FILE CREATIONS CLR MLGFNB+10 ;REINITIALISE VERSION NUMBER $CALLG ASCFNM,GCML+G.CMLD+2,#GCML+G.CMLD,#MLGFNB,#UIC,#STATUS ;CONVERT THE INPUT FILENAME MOV BLKSTR,BLOCK ;INITIALISE THE BLOCK NUMBER MOV BLKSTR+2,BLOCK+2 ; CLR BLOCK1 ;INITIALISE THE BLOCK NUMBER CLR BLOCK1+2 ; CLR EOF ; LOOP1: QIOW$S #IO.RLB,#1,#1,,#IOSB,,<#BUFFER,#512.*BLKS,,BLOCK+2,BLOCK> ;READ THE NEXT SET OF BLOCKS ; MOV #BLKS,R4 ;GET NUMBER OF BLOCKS TO CHECK MOV #BUFFER,R3 ;GET ADDRESS OF BLOCKS ; 10$: MOV #STRING,R2 ;GET ADDRESS OF STRING TO CHECK MOV R3,-(SP) ;SAVE THE BUFFER ADDRESS ADD #56,R3 ;OFFSET TO START OF FILENAME MOV #4,R0 ;GET NUMBER THAT MUST MATCH EXACTLY ; 12$: CMP (R3)+,(R2)+ ;SAME SO FAR? BNE 13$ ;IF NE NO - EXIT SOB R0,12$ ;YES - TRY NEXT ONE TST (R2) ;FILE VERSION TO CHECK? BEQ 14$ ;IF EQ NO - THIS COULD BE THE ONE CMP (R3),(R2) ;YES - IS THIS IT? BEQ 14$ ;IF EQ YES - CARRY ON ; 13$: MOV (SP)+,R3 ;GET BUFFER ADDRESS BACK JMP 25$ ;NO - REJECT IT ; 14$: MOV (R3),VERS+2 ;STORE VERSION NUMBER MOV (SP),R3 ;GET BACK START ADDRESS ADD #144,R3 ;SET TO START OF ALLOCATION POINTERS CLR HIB ; MOV (R3)+,R0 ;GET NUMBER OF WORDS USED BIC #177400,R0 ;WIPE OUT TOP BYTE ASR R0 ;CONVERT TO ELEMENTS BEQ 17$ ;IF EQ NONE - CARRY ON ; 16$: TSTB (R3)+ ;IGNORE HIGH VBN FOR NOW MOVB (R3)+,R1 ;GET THE NUMBER OF BLOCKS TST (R3)+ ;IGNORE LOW VBN BIC #177400,R1 ;IGNORE ANY SIGN-EXTENSION INC R1 ;ALLOW FOR ZERO-OFFSETTING ADD R1,HIB ;ADD TO RUNNING TOTAL SOB R0,16$ ;AND TRY NEXT ONE ; 17$: CMP HIB,EOF ;LARGEST SO FAR? BLT 18$ ;IF LT NO - OMIT RESET MOV HIB,EOF ;YES - RESET TO THIS FILE MOV VERS+2,VERS ;STORE VERSION MOV BLOCK,BLOCK1 ;STORE THE BLOCK MOV BLOCK+2,BLOCK1+2 ; ; 18$: TST (R2) ;FOUND WHAT WE'RE AFTER? BNE 20$ ;IF NE YES - OMIT MESSAGE MOV #3,NUMCHR ;CONVERT THREE RAD50 WORDS $CALLG RADASC,#NUMCHR,#STRING,#ASC1 MOV #1,NUMCHR ;AND ONE FOR THE FILETYPE $CALLG RADASC,#NUMCHR,#STRING+6,#ASC2 MOV #6,NUMCHR ;AND SIX FOR THE VERSION MOV #8.,RADIX ;WHICH IS OCTAL MOV VERS+2,IOSB ;SET UP DOUBLEWORD CLR IOSB+2 $CALLG BINASC,#IOSB,#NUMCHR,#RADIX,#ASC3,#STATUS MOV #10.,RADIX ;RESET RADIX FOR NUMBER OF BLOCKS MOV HIB,IOSB ;STORE IT $CALLG BINASC,#IOSB,#NUMCHR,#RADIX,#SIZE,#STATUS QIOW$S #IO.WVB,#5,#1,,#IOSB,,<#OUTSTR,#OUTLEN,#40> ; 20$: MOV (SP)+,R3 ;GET ADDRESS OF BLOCK BACK TST (R2) ;FOUND WHAT WE'RE AFTER? BNE CREATE ;IF NE YES - CREATE THE FILE ; 25$: ADD #1,BLOCK ADC BLOCK+2 ; 30$: ADD #512.,R3 DEC R4 ;COUNT IT BEQ 35$ ;IF EQ EXIT LOOP JMP 10$ ;NO - DO AGAIN ; 35$: TST BLOCK+2 ;IN TOP BIT YET? BEQ 40$ CMP BLOCK,#62464. ;FINISHED DISK? BHI CREATE ;YES - EXIT ; 40$: JMP LOOP1 ;NO - CARRY ON ; ; FIRST CREATE THE OUTPUT FILE ; CREATE: TST BLOCK1 ;ANYTHING TO DO? BNE 10$ ;IF NE YES - CARRY ON TST BLOCK1+2 ;NOTHING? BNE 10$ ;IF NE OK - CARRY ON QIOW$S #IO.WVB,#5,#1,,#IOSB,,<#NOMSG,#NOMSL,#40> JMP NEXT ;DO NEXT ; 10$: TST STRING+8. ;ANY VERSION? BNE 12$ ;IF NE YES - CARRY ON MOV VERS,STRING+8. ;NO - STORE THE VERSION ; 12$: MOV BLOCK1+2,BLOCK+2 ;NOW SET UP DIRECTORY BLOCK NUMBER MOV BLOCK1,BLOCK ; CLR BLOCK1 CLR BLOCK1+2 MOV EOF,HIB ;SET UP FILE SIZE QIOW$S #IO.RLB,#1,#1,,#IOSB,,<#BUFFER,#512.,,BLOCK+2,BLOCK> ;READ FILE HEADER MOV #BUFFER+144,R5 ;GET ADDRESS OF HEADER MOV #BUFFER+16,R0 ;GET ADDRESS OF ATTRIBUTES MOV #MLGFTT,R1 ;DITTO MOV #7,R2 ;AND LENGTH ; 20$: MOV (R0)+,(R1)+ ;COPY NEXT WORD SOB R2,20$ ; MOV (R5)+,R4 ;GET NUMBER OF WORDS USED BIC #177400,R4 ;WIPE OUT TOP BYTE ASR R4 ;CONVERT TO ELEMENTS CLR BUFFER+512. ; CLEAR A DOUBLEWORD CLR BUFFER+514. ; MOVB UIC+1,BUFFER+512. ;GET GROUP NUMBER MOVB #8.,RADIX ;SET RADIX FOR OCTAL $BASTS STATUS,RIGHT,ZEROS ;RIGHT-ADJUSTED WITH LEADING ZEROES MOVB #3,NUMCHR ;THREE OUTPUT CHARACTERS $CALLG BINASC,#BUFFER+512.,#NUMCHR,#RADIX,#CNVTMP,#STATUS ;CONVERT FIRST HALF OF DIRECTORY NAME MOVB UIC,BUFFER+512. ; GET MEMBER NUMBER $BASTS STATUS,RIGHT,ZEROS ;SET CONVERSION TYPE AGAIN $CALLG BINASC,#BUFFER+512.,#NUMCHR,#RADIX,#CNVTMP+3,#STATUS ;AND CONVERT SECOND HALF MOVB #6,NUMCHR ;NOW CONVERT TO RAD50.. $CALLG ASCRAD,#NUMCHR,#CNVTMP,#DIRNAM ;..LIKE SO QIOW$S #IO.FNA,#2,#1,,#IOSB,,<,,,,,#DIRFNB> ;FIND DIRECTORY ID MOV DIRFNB+N.FID,MLGFNB+N.DID ;PUT DIRECTORY ID IN FILENAME BLOCK MOV DIRFNB+N.FID+2,MLGFNB+N.DID+2 ; MOV DIRFNB+N.FID+4,MLGFNB+N.DID+4 ; CLR MLGFNB+N.FID ;REINITIALISE FILE ID CLR MLGFNB+N.FID+2 CLR MLGFNB+N.FID+4 ; QIOW$S #IO.CRE,#2,#1,,#IOSB,,<#MLGFNB+N.FID,#MLGATT,#100000,HIB> QIOW$S #IO.ENA,#2,#1,,#IOSB,,<,,,,,#MLGFNB> ;ENTER FILE IN DIRECTORY QIOW$S #IO.ACE,#2,#1,,#IOSB,,<#MLGFNB+N.FID,,,,#100200> ;ACCESS FILE FOR READ ONLY ; LOOP2: MOVB (R5)+,BLOCK+2 ;GET HIGH VBN MOVB (R5)+,R3 ;AND NUMBER OF BLOCKS BIC #177400,R3 ;WIPE OUT ANY SIGN-EXTENSION MOV (R5)+,BLOCK ;GET LOW VBN INC R3 ;ALLOW FOR 0-OFFSET ; 10$: INC BLOCK1 ;SET TO NEXT OUTPUT BLOCK QIOW$S #IO.RLB,#1,#1,,#IOSB,,<#BUFFER+512.,#512.,,BLOCK+2,BLOCK> QIOW$S #IO.WVB,#2,#1,,#IOSB,,<#BUFFER+512.,#512.,,BLOCK1+2,BLOCK1> INC BLOCK BVC 20$ ;IF NO OVERFLOW OK INC BLOCK+2 ;ELSE INCREMENT HIGH VBN ; 20$: SOB R3,10$ ;AND DO NEXT ONE SOB R4,LOOP2 ;AND SO ON QIOW$S #IO.DAC,#2,#2 QIOW$S #IO.WVB,#5,#1,,#IOSB,,<#ENDMSG,#ENDMSL,#40> JMP NEXT ;DO NEXT ; EXIT: EXIT$S ;YES - GIVE UP .END START