.TITLE UNDELETE Utility to restore deleted files $ATRDEF $FATDEF $FH2DEF $FI2DEF $FIBDEF $HM2DEF $IODEF $LNMDEF $RMSDEF $SSDEF .PSECT DATA,LONG,WRT,NOEXE,NOSHR ; SYS_LOGNAME_TABLE: .ASCID /LNM$PROCESS/ SCRATCH_DEVICE_LOGNAME: .ASCID /UND$SCRATCH_DEVICE/ SCRATCH_DEVICE_ITMLST: .WORD SCRATCH_DEVICE_LEN,LNM$_STRING .ADDRESS SCRATCH_DEVICE_BUF,SCRATCH_DEVICE_DESC .LONG 0 SCRATCH_DEVICE_DESC: .LONG SCRATCH_DEVICE_LEN .ADDRESS SCRATCH_DEVICE_BUF SCRATCH_DEVICE_BUF: .BLKB 32 SCRATCH_DEVICE_LEN=.-SCRATCH_DEVICE_BUF ; ; ; TARGET_DEVICE_DESC: .ASCID /SYS$DISK/ TARGET_FILE_DESC: .LONG TARGET_FILE_LEN .ADDRESS TARGET_FILE_BUF TARGET_FILE_BUF: .BLKB 32 TARGET_FILE_LEN=.-TARGET_FILE_BUF TARGET_FILE_NUM_DESC: .LONG TARGET_FILE_NUM_LEN .ADDRESS TARGET_FILE_NUM_BUF TARGET_FILE_NUM_BUF: .BLKB 8 TARGET_FILE_NUM_LEN=.-TARGET_FILE_NUM_BUF TARGET_FILE_NUMBER: .BLKL 1 DEFAULT_DIR_DESC: .LONG DEFAULT_DIR_LEN .ADDRESS DEFAULT_DIR_BUF DEFAULT_DIR_BUF: .BLKB 32 DEFAULT_DIR_LEN=.-DEFAULT_DIR_BUF .ALIGN LONG TARGET_FAB: $FAB - FOP=,- NAM=TARGET_NAM TARGET_NAM: $NAM DIR_FAB: $FAB - NAM=DIR_NAM DIR_NAM: $NAM COPY_FAB: $FAB - NAM=COPY_NAM COPY_NAM: $NAM ; ; ; CLI_DEVICE_DESC: .ASCID /DEVICE/ CLI_FILE_DESC: .ASCID /FILE/ CLI_FID_DESC: .ASCID /FID/ ; ; ; DISK_CHAN: .BLKW 1 DISK_IOSB: .BLKQ 1 DISK_BUFFER: .BLKB 512 HOME_BUFFER: .BLKB 512 INDEXF_FIB_DESC: .WORD INDEXF_FIB_LEN,0 .ADDRESS INDEXF_FIB INDEXF_FIB: .LONG FIB$M_WRITE!FIB$M_NOWRITE!FIB$M_NOLOCK .WORD 1,1,0 INDEXF_FIB_LEN=.-INDEXF_FIB INDEXF_ATR: .WORD INDEXF_FAT_LEN,ATR$C_RECATTR .ADDRESS INDEXF_FAT .LONG 0 ; terminator INDEXF_FAT: .BLKB 32 INDEXF_FAT_LEN=.-INDEXF_FAT TARGET_CHAN: .BLKW 1 TARGET_IOSB: .BLKQ 1 TARGET_FIB_DESC: .WORD TARGET_FIB_LEN,0 .ADDRESS TARGET_FIB TARGET_FIB: .LONG FIB$M_NOLOCK TARGET_FID_NUM: .WORD 0 TARGET_FID_SEQ: .WORD 0 TARGET_FID_RVN: .WORD 0 TARGET_FIB_LEN=.-TARGET_FIB TARGET_ATR: .WORD TARGET_FAT_LEN,ATR$C_RECATTR .ADDRESS TARGET_FAT .LONG 0 ; terminator TARGET_FAT: .BLKB 32 TARGET_FAT_LEN=.-TARGET_FAT ; COMMAND_DESC: .LONG 0 .ADDRESS COMMAND_BUF COMMAND_BUF: .BLKB 80 COMMAND_ROOT: .ASCID /RECOVER/ ; ; ; .SUBTITLE UNDELETE mainline program .PAGE ; ; ; .PSECT UNDEL,LONG,EXE,SHR,NOWRT .ENTRY UNDELETE,^M $TRNLNM_S - TABNAM=SYS_LOGNAME_TABLE,- LOGNAM=SCRATCH_DEVICE_LOGNAME,- ITMLST=SCRATCH_DEVICE_ITMLST BLBS R0,10$ $EXIT_S R0 10$: PUSHAQ CLI_FID_DESC CALLS #1,G^CLI$PRESENT BLBS R0,20$ BRW 50$ 20$: PUSHAL TARGET_FILE_NUM_DESC PUSHAQ TARGET_FILE_NUM_DESC PUSHAQ CLI_FID_DESC CALLS #3,G^CLI$GET_VALUE BLBS R0,30$ $EXIT_S R0 30$: PUSHAL TARGET_FILE_NUMBER PUSHL TARGET_FILE_NUM_DESC+4 PUSHL TARGET_FILE_NUM_DESC CALLS #3,G^LIB$CVT_DTB BLBS R0,40$ $EXIT_S R0 40$: 50$: PUSHAL TARGET_FILE_DESC PUSHAQ TARGET_FILE_DESC PUSHAQ CLI_FILE_DESC CALLS #3,G^CLI$GET_VALUE BLBS R0,60$ $EXIT_S R0 60$: ; ; ; .PAGE ; ; at this point we have all our parameters. ; $ASSIGN to the disk ; HAVE_PARAMETERS: $ASSIGN_S - CHAN= DISK_CHAN,- DEVNAM=TARGET_DEVICE_DESC BLBS R0,10$ $EXIT_S R0 10$: $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_ACCESS!IO$M_ACCESS,- IOSB= DISK_IOSB,- P1= INDEXF_FIB_DESC,- P5= #INDEXF_ATR BLBS R0,19$ $EXIT_S R0 19$: BLBS DISK_IOSB,20$ $EXIT_S DISK_IOSB 20$: ROTL #16,INDEXF_FAT+FAT$L_EFBLK,R6 ; R6 now contain the EOF Block TSTW INDEXF_FAT+FAT$W_FFBYTE BNEQ 25$ DECL R6 ; see note on EFBLK p1-22 I/O User's Guide 25$: $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_READVBLK,- IOSB= DISK_IOSB,- P1= HOME_BUFFER,- P2= #512,- P3= #2 BLBS R0,29$ $EXIT_S R0 29$: BLBS DISK_IOSB,30$ $EXIT_S DISK_IOSB 30$: TSTL TARGET_FILE_NUMBER BEQL 31$ MOVZWL HOME_BUFFER+HM2$W_IBMAPVBN,R2 MOVZWL HOME_BUFFER+HM2$W_IBMAPSIZE,R3 ADDL3 R2,R3,R6 ADDL2 TARGET_FILE_NUMBER,R6 31$: $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_READVBLK,- IOSB= DISK_IOSB,- P1= DISK_BUFFER,- P2= #512,- P3= R6 BLBS R0,39$ $EXIT_S R0 39$: BLBS DISK_IOSB,40$ BRW 95$ 40$: TSTL TARGET_FILE_NUMBER BNEQ 50$ CMPC3 TARGET_FILE_DESC,- ; length TARGET_FILE_BUF,- ; source string DISK_BUFFER+FH2$C_LENGTH+FI2$T_FILENAME ; search string BNEQ 80$ ; ; HOT DAMN, WE FOUND THE FILE ; 50$: CALLS #0,UNDEL_FILE BLBS R0,70$ $EXIT_S R0 70$: CALLS #0,ENTER_FILE BLBS R0,75$ $EXIT_S R0 75$: MOVAB COMMAND_BUF,R3 MOVC3 COMMAND_ROOT,@COMMAND_ROOT+4,(R3) MOVB #^A/ /,(R3)+ MOVC3 TARGET_FILE_DESC,@TARGET_FILE_DESC+4,(R3) MOVB #^A/ /,(R3)+ MOVC3 SCRATCH_DEVICE_DESC,@SCRATCH_DEVICE_DESC+4,(R3) MOVAB COMMAND_BUF,R2 SUBL3 R2,R3,COMMAND_DESC PUSHAQ COMMAND_DESC CALLS #1,G^LIB$DO_COMMAND $EXIT_S R0 ; return with success from enter_file ; ; ; 80$: SOBGTR R6,90$ BRW 95$ 90$: BRW 30$ 95$: $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_DEACCESS BLBC R0,99$ ; report deaccess code if deacess fails $DASSGN_S - CHAN= DISK_CHAN ; report dessign status if deassign fails BLBC R0,99$ MOVL #RMS$_FNF,R0 ; else report file is not in that directory 99$: $EXIT_S R0 RET ; ; ; .SUBTITLE UNDEL_FILE change the marked for deletion bit in file hdr .PAGE ; ; ; .ENTRY UNDEL_FILE,^M ; ; ok, the buffer contains the file header, and R6 contains the ; record number. All we need to do is ; ;check to see if deleted, and don't restore it if not BBS #FH2$V_MARKDEL,DISK_BUFFER+FH2$L_FILECHAR,10$ BRW 90$ 10$: ; ; clear the delete bit if it is deleted ; BICL #FH2$M_MARKDEL,DISK_BUFFER+FH2$L_FILECHAR ; ; setup the file number ; MOVZWL HOME_BUFFER+HM2$W_IBMAPVBN,R2 MOVZWL HOME_BUFFER+HM2$W_IBMAPSIZE,R3 ADDL2 R2,R3 ; R3 now contains the address of the first DECL R3 ; directory block - 1 SUBL3 R3,R6,R4 MOVW R4,DISK_BUFFER+FH2$W_FID_NUM MOVW DISK_BUFFER+FH2$W_FID_NUM,TARGET_FID_NUM MOVW DISK_BUFFER+FH2$W_FID_SEQ,TARGET_FID_SEQ MOVW DISK_BUFFER+FH2$W_FID_RVN,TARGET_FID_RVN ; ; now checksum the buffer ; MOVZWL #255,R4 MOVAW DISK_BUFFER,R3 CLRL R2 20$: ADDW2 (R3)+,R2 SOBGTR R4,20$ MOVW R2,DISK_BUFFER+FH2$W_CHECKSUM ; ; then rewrite the buffer ; $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_WRITEVBLK,- IOSB= DISK_IOSB,- P1= DISK_BUFFER,- P2= #512,- P3= R6 BLBS R0,29$ RET 29$: BLBS DISK_IOSB,30$ MOVL DISK_IOSB,R0 RET 30$: $QIOW_S - CHAN= DISK_CHAN,- FUNC= #IO$_DEACCESS,- IOSB= DISK_IOSB BLBS R0,39$ ; report deaccess code if deacess fails RET 39$: BLBS DISK_IOSB,40$ MOVL DISK_IOSB,R0 RET 40$: $DASSGN_S - CHAN= DISK_CHAN ; report dessign status if deassign fails RET ; return in any case 90$: MOVL #RMS$_FNF,R0 RET ; ; ; .SUBTITLE ENTER_FILE ; enter newly recovered file in a directory .PAGE ; ; ; .ENTRY ENTER_FILE,^M PUSHAQ DEFAULT_DIR_DESC PUSHAL DEFAULT_DIR_DESC PUSHL #0 CALLS #3,G^SYS$SETDDIR BLBS R0,10$ RET 10$: MOVL DEFAULT_DIR_DESC,R0 MOVL DEFAULT_DIR_DESC+4,R1 LOCC #^A/./,R0,(R1) BNEQ 20$ BRW 40$ 20$: MOVL R0,R3 MOVL R1,R4 ; save pointer in R4 DECL R0 INCL R1 LOCC #^A/./,R0,(R1) BEQL 30$ BRB 20$ 30$: MOVB #^A/]/,(R4) DECL R3 INCL R4 LOCC #^A/]/,R3,(R4) MOVL #^A/.DIR/,(R1) MOVL DEFAULT_DIR_DESC+4,DIR_FAB+FAB$L_FNA ADDB3 #3,DEFAULT_DIR_DESC,DIR_FAB+FAB$B_FNS BRB 50$ 40$: ADDL3 DEFAULT_DIR_DESC,DEFAULT_DIR_DESC+4,R4 DECL R4 MOVL #^A/.DIR/,(R4) ADDL3 #1,DEFAULT_DIR_DESC+4,DIR_FAB+FAB$L_FNA ADDB3 #4,DEFAULT_DIR_DESC,DIR_FAB+FAB$B_FNS 50$: $OPEN FAB=DIR_FAB BLBS R0,60$ RET 60$: MOVL DIR_NAM+NAM$W_FID,TARGET_NAM+NAM$W_DID ; copy NUM & SEQ MOVW DIR_NAM+NAM$W_FID+4,TARGET_NAM+NAM$W_FID+4 ; and RVN $CLOSE FAB=DIR_FAB BLBS R0,70$ RET 70$: MOVL TARGET_FID_NUM,TARGET_NAM+NAM$W_FID ; copy NUM & SEQ MOVW TARGET_FID_RVN,TARGET_NAM+NAM$W_FID+4 ; and RVN MOVAL TARGET_FILE_BUF,TARGET_NAM+NAM$L_ESA ; specify name MOVB TARGET_FILE_DESC,TARGET_NAM+NAM$B_ESL ; and name length MOVZBL DIR_NAM+NAM$T_DVI,R4 MOVB R4,TARGET_NAM+NAM$T_DVI MOVC3 R4,- DIR_NAM+NAM$T_DVI+1,- TARGET_NAM+NAM$T_DVI+1 $ENTER FAB=TARGET_FAB ; try and stuff name in directory BLBS R0,80$ RET ; failure 80$: RET ; success 90$: MOVL #RMS$_FNM,R0 RET .END UNDELETE