.TITLE BRM -- Disk Cleaning Program .IDENT /2/ ; 12-SEP-1990 09:27:28 ; This program runs in one of two modes: ; ; 1. Erase all the free space on a mounted disk so that ; deleted files are truly deleted. It does this by allocating a ; temporary file on the disk and writing a buffer of 0's to each ; block of the file. The size of the file is made equal to the ; number of free blocks on the volume. NOTE: It is strongly ; recommended that BRM be used only on quiescent devices as the ; program allocates every available block on the device! ; BRM ddn: ; where ddn is a mounted Files-11 device. ; ; 2. Write zeroes to all blocks of an existing file. This ; could be used to erase the contents of a file before it's deleted ; or ensure that a file has known initial contents. ; BRM ddn:[group,member]filename.ext;ver ; where ddn defaults to SY:; ; [group,member] defaults to the current UIC; ; filename.ext must be specified; ; ;ver defaults to the latest version .MCALL QIOW$,DIR$,EXST$S,OPNT$D,OPEN$M,CLOSE$,WAIT$,WRITE$ .MCALL FSRSZ$,FINIT$,FDBDF$,FDAT$A,FDRC$A,FDBK$A,FDOP$A .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2,NMBLK$ .MACRO PRINT,.BUFF.,.LEN. MOV .BUFF.,-(SP) MOV .LEN.,-(SP) CALL $OUT .ENDM .NLIST BEX TILUN = 1 ;LUN for terminal messages TIEF = 1 ;Event flag for messages FILUN = 2 ;LUN for disk operations FIEF = 5 ;Event flag for file writes EX.ENA = 200 ;Non-contiguous file extend $WRT: QIOW$ IO.WLB,TILUN,TIEF,,,,<0,0,40> IOSTAT: .BLKW 2 ;I/O status block PFSIZ: .WORD FSIZ ;Pointer to number of blocks FSIZ: .BLKW 2 ;Number of blocks in file OUTBUF: .BLKB 80. ;Message output buffer NBLKS: .BLKW 1 ;Number of blocks per write BSIZ: .BLKW 1 ;Size of output buffer (in bytes) CMDBLK: GCMLB$ ,BRM,,TILUN ;Define working storage for GCML CSI$ CSIBLK: .BLKB C.SIZE ;CSI working storage GCLMSG: .ASCIZ "BRM -- Error getting command line" GCLMSL = .-GCLMSG CMDMSG: .ASCIZ "BRM -- Command line error" CMDMSL = .-CMDMSG BADMSG: .ASCIZ "BRM -- Device is not a mounted Files-11 volume" BADMSL = .-BADMSG OPNMSG: .ASCIZ "BRM -- Error opening file:" OPNMSL = .-OPNMSG WRTMSG: .ASCIZ "BRM -- Error writing to file:" WRTMSL = .-WRTMSG FCSMSG: .ASCIZ "BRM -- FCS Error %D." FINMSG: .ASCIZ "BRM -- %T. blocks erased" .EVEN FSRSZ$ 1 ;Allocate FSR buffer OFDBD: FDBDF$ ;Allocate 1 FDB FDAT$A R.FIX,FD.BLK ;Set file attributes FDRC$A FD.RWM ;Set record attributes FDBK$A FILBUF,,,FIEF,IOSTAT ;Set block access FDOP$A FILUN,DSPT,,FO.WRT!FA.TMP ;Set file open section DSPT: .WORD 0,0 ;Dataset descriptor .WORD 0,0 .WORD FILLEN,FILSTR FILSTR: .ASCII /BRM.TMP/ ;Temporary filename FILLEN = .-FILSTR .EVEN OFDBF: FDBDF$ ;Allocate 1 FDB FDRC$A FD.RWM ;Set record attributes FDBK$A FILBUF,,,FIEF,IOSTAT ;Set block access FDOP$A FILUN,CSIBLK+C.DSDS,OUTDFN,FO.WRT ;Set file open section OUTDFN: NMBLK$ ,,,SY ;Default file name BRM:: FINIT$ ;Initialize the file system NEXT: GCML$ #CMDBLK ;Get the command line BCC 10$ JMP GCLERR ;If CS, an error occurred 10$: TST CMDBLK+G.CMLD ;Was it an empty command line? BEQ NEXT ;If EQ, yes CSI$1 #CSIBLK,CMDBLK+G.CMLD+2,CMDBLK+G.CMLD BCS 20$ ;If CS, an error occurred MOV #CSIBLK,R0 ;Set CSI block address CSI$2 ,OUTPUT ;Decode the command BCS 20$ ;If CS, an error occurred BITB #CS.EQU!CS.WLD!CS.MOR,C.STAT(R0) BNE 20$ ;If NE, illegal bits are set BITB #CS.DIF!CS.NMF,C.STAT(R0) BNE 30$ ;If NE, file mode is requested BITB #CS.DVF,C.STAT(R0) ;Was a device specified? BNE 40$ 20$: JMP CMDERR ;If EQ, no 30$: OPEN$M #OFDBF ;Open the specified file BCC 90$ JMP OPNERR 40$: MOV C.DEVD(R0),DSPT ;Set up the device descriptor MOV C.DEVD+2(R0),DSPT+2 OPNT$D #OFDBD ;Open a temp. file marked for delete BCC 50$ JMP OPNERR ;If CS, open error 50$: MOV $HEADR,R1 ;Get our header MOV H.LUN+<*4>(R1),R5 ;Get the UCB address for the device 60$: MOV U.RED(R5),R5 ;Follow the redirection chain CMP U.RED(R5),R5 ;Are we at the end? BNE 60$ ;If NE, no BIT #DV.DIR,U.CW1(R5) ;Directory device? BEQ 70$ ;If EQ, no BIT #DV.SDI!DV.SQD,U.CW1(R5);Single directory or sequential device? BNE 70$ ;If NE, yes BIT #DV.MNT,U.CW1(R5) ;Mountable? BEQ 70$ ;If EQ, no BIT #DV.F11,U.CW1(R5) ;Is it a Files-11 device? BEQ 70$ ;If EQ, no BITB #US.FOR,U.STS(R5) ;Is the volume mounted foreign? BNE 70$ ;If NE, yes MOV U.VCB(R5),R3 ;Get the Volume Control Block BNE 80$ 70$: JMP BADDEV ;If EQ, none there 80$: MOV V.FRBK+2(R3),R1 ;Get the lower 2 bytes of free blocks CLR R2 ;Clear R2 for byte load BISB V.FRBK(R3),R2 ;Get the high byte of free blocks SWAB R2 ;Move it to the high byte of R2 BIS #EX.ENA,R2 ;Non-contiguous extension CALL .EXTND ;Extend it all the way out BCS 140$ ;If CS, extend failed 90$: MOV #160000,R2 ;Get buffer maximum ending address SUB #FILBUF,R2 ;Compute size of buffer BIC #777,R2 ;Truncate it to an even number of blocks MOV R2,BSIZ ASH #-9.,R2 ;Convert it to number of blocks MOV R2,NBLKS MOV #FILBUF,R1 ;Clear entire buffer to zeroes MOV BSIZ,R2 ASR R2 ;Convert to words 100$: CLR (R1)+ SOB R2,100$ MOV BSIZ,F.BKDS(R0) ;Initialize buffer size MOV F.HIBK+2(R0),R1 ;Get the length of the file MOV F.HIBK(R0),R2 MOV R1,FSIZ+2 ;Save number of free blocks as file size MOV R2,FSIZ 110$: TST R1 ;Are there any blocks left to write? BNE 120$ ;If NE, yes TST R2 BEQ CLOSE ;If EQ, we're done 120$: SUB NBLKS,R1 ;Will this overwrite the file? SBC R2 BPL 130$ ;If PL, no ADD NBLKS,R1 ;In blocks ASH #9.,R1 ;Convert it to bytes MOV R1,F.BKDS(R0) ;Reset buffer size CLR R1 ;Remember that we're done CLR R2 130$: WRITE$ R0 ;Write a block BCS 140$ ;If CS, write error WAIT$ R0 ;Wait for I/O completion BCC 110$ ;If CC, I/O was successful 140$: PRINT #WRTMSG,#WRTMSL ;Output the message CALL WRTFCS ;Output the FCS error code BR CLOSE2 CLOSE: MOV #OUTBUF,R0 ;Set the output buffer address MOV #FINMSG,R1 ;Set the format string MOV #PFSIZ,R2 ;Set the argument block CALL $EDMSG ;Edit the message PRINT #OUTBUF,R1 ;Print it CLOSE2: CLOSE$ #OFDBD ;Close the file CLOSE$ #OFDBF ;Close the file JMP NEXT ;Go get another command GCLERR: CMPB #GE.EOF,CMDBLK+G.ERR ;End of file instead of command? BNE 10$ ;If EQ, no EXST$S #EX$SUC ;Exit gracefully 10$: PRINT #GCLMSG,#GCLMSL ;Print error message BR EXERR ;Exit with error status CMDERR: PRINT #CMDMSG,#CMDMSL ;Print command error message JMP NEXT ;Get another command OPNERR: PRINT #OPNMSG,#OPNMSL ;Output the message CALL WRTFCS ;Output the FCS error code EXERR: EXST$S #EX$ERR ;Exit with error status BADDEV: PRINT #BADMSG,#BADMSL ;Illegal device BR CLOSE2 ;Close the file ; Print the FCS error code WRTFCS: MOV #-1,-(SP) ;Ready the stack MOVB F.ERR(R0),(SP) ;Push the FCS error MOV #OUTBUF,R0 ;Set the output buffer MOV #FCSMSG,R1 ;Set the format string MOV SP,R2 ;Set the argument block CALL $EDMSG ;Make it pretty TST (SP)+ ;Clean the stack PRINT #OUTBUF,R1 ;Output the message RETURN ; Output a string to TI: $OUT: MOV 2(SP),$WRT+Q.IOPL+2 ;Set buffer length BEQ 10$ ;If EQ, nothing to print MOV 4(SP),$WRT+Q.IOPL ;Set buffer address DIR$ #$WRT ;Perform I/O 10$: MOV (SP),4(SP) ;Move return address CMP (SP)+,(SP)+ ;Clean the stack RETURN .PSECT ...ZZZ,D,RW,GBL ;This is expanded by TKB ; to fill available virtual space FILBUF: .BLKB 1000 ;File output buffer .END BRM