.TITLE DELFID -- Delete file by file ID .ENABL LC .SBTTL Title page .IDENT -010100- ;+ ; Abstract: DELFID ; ; This task will delete a file by file IID. It does not ; do it legally (i. e., like PIP does), but goes directly into ; the index file and deallocates the file header. The disk ; must be mounted as /UNL in order to run this task. It is ; not intended for general use, but for disk maintenance (such ; as deleting files with bad file headers without running DSC ; or doing things manually with ZAP). ; ; After this task is run, it is strongly reccommended ; that VFY be run to rebuild the bitmap. ; ; Operating procedures: ; ; This task can be run either as an MCR command or by ; saying RUN $DELFID$. It prompts with ; ; FID> ; ; and expects a command string of the form: ; ; DEV:/SWITCHES ; ; where DEV: is the device on which the file resides, ; and defaults to SY0:. ; ; Switches: ; ; /FI:nnnn:mmmm - The file ID which is to be deleted. ; ; Task: DELFID ; ; Limitations: ; ; This task will only work on IAS/RSX-11D systems. ; It will not work on RSX-11M, RSX-11M+, VAX/VMS, or RSTS. ; Modifications for RSX-11M and RSX-11M+ should be trivial ; (the only change is how it would check for privileged users), ; but VAX/VMS and RSTS don't have any hope because the internal ; on-disk file structure is completely different. ; ; Nonstandard features: ; ; Written in MACRO-11. This is necessary to bypass a ; number of things which would get in the way in a higher-level ; language, and also, alas, to do bit twiddling. ; ; Does not use the FCS READ$/WRITE$ macro's to do I/O ; to the files!! It uses some "similar" macros which expand ; to QIO's; the problem with the FCS macro's is that the ; INDEXF.SYS and BITMAP.SYS files don't have a complete FCS ; context, and setting up one manually will mess up the files ; when they are closed. ; ; Written: 22-Jul-1980, -1.0.0-, Bruce C. Wright ; Modified: 31-Jan-1981, -1.1.0-, Bruce C. Wright ; General cleanup. ; Verified: 31-Jan-1981, -1.1.0-, Bruce C. Wright ;- .SBTTL MACRO CALLS .MCALL QIOW$,WSIG$S,EXIT$S,QIOW$S .MCALL OPNS$M,CLOSE$ .MCALL CSI$,CSI$1,CSI$2,CSI$SW,CSI$SV,CSI$ND .MCALL GCML$,GCMLB$ .MCALL FDBDF$,FSRSZ$,FDRC$A,FDBK$A,FDOP$A .MCALL FDOF$L,FCSBT$,FHDOF$,HMBOF$ FDOF$L FCSBT$ FHDOF$ DEF$L HMBOF$ DEF$L CMDLUN=1 CMDEVF=1 INDLUN=2 INDEVF=2 MSGLUN=3 MSGEVF=3 .SBTTL MACRO DEFINITIONS .MACRO MSG ARG .NCHR $$$, .WORD $$$ .ASCII "ARG" .EVEN .ENDM .MACRO TYPE STR,LEN MOV STR,-(SP) MOV LEN,-(SP) CALL TYPE CMP (SP)+,(SP)+ .ENDM .MACRO TYPMSG ARG TYPE #ARG+2,ARG .ENDM .MACRO ONERR ARG BCC .+6 JMP ARG .ENDM .MACRO READ FDB,BUFFER,SIZE MOV FDB,R0 .IIF NB BUFFER MOV BUFFER,F.BKDS+2(R0) .IIF NB SIZE MOV SIZE,F.BKDS(R0) JSR PC,READ .ENDM READ .MACRO WRITE FDB,BUFFER,SIZE MOV FDB,R0 .IIF NB BUFFER MOV BUFFER,F.BKDS+2(R0) .IIF NB SIZE MOV SIZE,F.BKDS(R0) JSR PC,WRITE .ENDM WRITE .SBTTL MAIN LINE CODE BEGIN:: MOV SP,SPSAVE MOV .CRTSK,R0 ; Get our ATL node. MOV A.TI(R0),R0 ; Get our PUD block. BITB #UT.PR,U.TF(R0) ; Is this guy privileged? BNE RSTART ; J if so -- OK TYPMSG M.PRIV ; Privileged user message EXIT$S ; And get out. RSTART: MOV SPSAVE,SP ; Restore SP CLOSE$ #INDEX ; Close index file just in case. GCML$ #CMLBLK ; BCC GETOK ;GOT A LINE CMPB CMLBLK+G.ERR,#GE.EOF ;EOF? BNE 10$ ;NO EXIT$S ;YES 10$: CMPB CMLBLK+G.ERR,#GE.IOR ;I/O ERROR? BNE 20$ ;NO TYPMSG M.IOR EXIT$S ;THIS IS FATAL 20$: CMPB CMLBLK+G.ERR,#GE.OPR ;OPEN ERROR? BNE 30$ TYPMSG M.OPR BR RSTART 30$: CMPB CMLBLK+G.ERR,#GE.BIF ;SYNTAX ERROR? BNE 40$ ;NO TYPMSG M.BIF BR RSTART 40$: CMPB CMLBLK+G.ERR,#GE.MDE ;MAX @ DEPTH? BNE 50$ TYPMSG M.MDE BR RSTART 50$: TYPMSG M.UNK ;UNKNOWN ERROR EXIT$S ;AND LEAVE GETOK: TST CMLBLK+G.CMLD ;INPUT? BEQ RSTART ;NO CLR SWORD ; Default to no switches CSI$1 #CSIBLK,CMLBLK+G.CMLD+2,CMLBLK+G.CMLD ; BCC 10$ TYPMSG M.PS1 BR RSTART 10$: CSI$2 #CSIBLK,OUTPUT,#SWTAB ; BCC 20$ ;OK? TYPMSG M.PS2 ;NO BR RSTART ;RESTART 20$: MOV #DEVLEN,DSPT ;SET UP DSPT MOV #DEVSTR,DSPT+2 ;FOR THE OPEN MACRO BITB #CS.EQU!CS.NMF!CS.DIF!CS.WLD!CS.MOR,CSIBLK+C.STAT BEQ 30$ ;ANY ILLEGAL BITS SET? TYPMSG M.BAD ;YES -- BAD PARAMETERS JMP RSTART ; 30$: BITB #CS.DVF,CSIBLK+C.STAT ;DEV STRING? BEQ OPEN ;NO MOV CSIBLK+C.DEVD,DSPT ;MOVE IN DEVICE DESC. MOV CSIBLK+C.DEVD+2,DSPT+2 OPEN: BIT #SW.FID,SWORD ; /FI switch specified? BNE 10$ ; J if so. TYPMSG M.FILE ; /FI switch must be specified. JMP RSTART ; Skip if not. ; ; First open the INDEXF.SYS file and read the home block. ; 10$: CLOSE$ #INDEX ; Close index file if necessary. OPNS$M #INDEX,,#DSPT ;OPEN THE INDEX FILE ONERR ERROR CLR INDEX+F.BKVB ;CLEAR HI ORDER BLOCK # MOV #2,INDEX+F.BKVB+2 ;INIT LO ORDER BLOCK # READ R0,#HOME,#1000 ;READ HOME BLOCK ONERR ERROR ; ; Now verify that the file ID is within range. ; CMP FID,#5 ; Is the file ID too small? BHI 12$ ; J if not. TYPMSG M.SMAL ; No, print small message. JMP RSTART ; And re-start the task. 12$: CMP FID,HOME+H.FMAX ; Within legal limits? BLOS 14$ ; J if so. TYPMSG M.BIG ; File ID too big. JMP RSTART ; And try again. ; ; Next, ensure that the file ID is allocated. ; 14$: MOV FID,R1 ; Get the File ID DEC R1 ; Make it 0-origin. MOV R1,R2 ; Get into R2 ASH #-12.,R2 ; Get the block # in the bitmap. BIC #^C<17>,R2 ; Clean off unused bits (sign extend) ADD #3,R2 ; Account for bootstrap, home block, ; and one-origin of blocks in file. MOV R2,INDEX+F.BKVB+2 ; Set in the virtual block number. MOV R1,R3 ; Get the File ID in R3 as well. ASH #-3.,R3 ; Get byte offset within block. BIC #^C<777>,R3 ; Clean off unused bits (block number) MOV R1,R4 ; Get File ID in R4 also. BIC #^C7,R4 ; Get the bit number in R4 MOV #1,R5 ; Get a bit mask into R5 ASH R4,R5 ; Shift it to appropriate bit in byte. READ R0,#BITMAP,#1000 ; Read the bitmap block. ONERR ERROR BITB R5,BITMAP(R3) ; Is it allocated in the bitmap? BNE 15$ ; J if so. TYPMSG M.ALL ; File ID not allocated. JMP RSTART ; And try again. ; ; Now delete the file in its file header. ; 15$: MOV FID,R1 ; Get the file ID ADD HOME+H.IBSZ,R1 ; Account for index file bitmap. ADD #2,R1 ; Account for misc. stuff in index file MOV R1,INDEX+F.BKVB+2 ; Set into index file block # CLR INDEX+F.BKVB ; Clear high order block # READ R0,#HEADER,#1000 ; Read the file header. ONERR ERROR ; CMP HEADER+H.FNUM,FID ; Correct file number? BEQ 20$ ; J if so. TYPMSG M.FID ; File ID message. ; (nonfatal) MOV FID,HEADER+H.FNUM ; Force the file ID to be correct. 20$: CMP HEADER+H.FSEQ,FSEQN ; Correct sequence number? BEQ 30$ ; J if so. TYPMSG M.FSEQ ; File sequence number message. ; (nonfatal) 30$: BISB #SC.MDL,HEADER+H.SCHA ; Mark the file for delete. INC HEADER+H.FSEQ ; Increment file sequence number. ; ; Compute the checksum and write the header back out. ; MOV #HEADER,R2 ; Point to the header. MOV #255.,R3 ; Get the size of the header. CLR R4 ; Clear checksum word. 40$: ADD (R2)+,R4 ; Count up checksum. SOB R3,40$ ; Loop over header. MOV R4,HEADER+H.CKSM ; Set the new checksum. MOV R1,F.BKVB+2(R0) ; Set the low order block number. CLR F.BKVB(R0) ; Clear high order block number. WRITE R0,#HEADER,#1000 ; Write the header back out. ONERR ERROR ; ; ; Now delete the file header from the index file bitmap. ; MOV FID,R1 ; Get the File ID DEC R1 ; Make it 0-origin. MOV R1,R2 ; Get into R2 ASH #-12.,R2 ; Get the block # in the bitmap. BIC #^C<17>,R2 ; Clean off unused bits (sign extend) ADD #3,R2 ; Account for bootstrap, home block, ; and one-origin of blocks in file. MOV R2,INDEX+F.BKVB+2 ; Set in the virtual block number. MOV R1,R3 ; Get the File ID in R3 as well. ASH #-3.,R3 ; Get byte offset within block. BIC #^C<777>,R3 ; Clean off unused bits (block number) MOV R1,R4 ; Get File ID in R4 also. BIC #^C7,R4 ; Get the bit number in R4 MOV #1,R5 ; Get a bit mask into R5 ASH R4,R5 ; Shift it to appropriate bit in byte. READ R0,#BITMAP,#1000 ; Read the bitmap block. ONERR ERROR BICB R5,BITMAP(R3) ; Clear appropriate bit in bitmap. MOV R2,INDEX+F.BKVB+2 ; Set in virtual block number again. WRITE R0,#BITMAP,#1000 ; Write the bitmap block. ONERR ERROR CLOSE$ R0 ; Close out index file. JMP RSTART ; And start over again. .SBTTL TYPE MESSAGE TO THE TERMINAL ; ; THIS SUBROUTINE TYPES A MESSAGE TO THE TERMINAL ; TYPE: MOV 2(SP),QMSG+Q.IOPL+2 ;LENGTH MOV 4(SP),QMSG+Q.IOPL ;BUFFER ADDRESS MOV #QMSG,-(SP) ;DO I/O CALL .DIRDL ; BCS 10$ ; RETURN ;RETURN TO CALLER 10$: BPT ;ERROR? ; .SBTTL Print error message to the terminal. ; ERROR: MOV #BLKPR,R1 ; Get the message buffer MOV #BLKSZ,R2 ; Get the message length CALL .PRFCS ; Print the FCS error CLOSE$ R0 ; Close the file. JMP RSTART ; And start again. .SBTTL READ - Read from a file ; READ: MOV R1,-(SP) ; Save R1 MOV R2,-(SP) ; Save R2 MOV R3,-(SP) ; And R3 CLR -(SP) ; Room for IOST CLR -(SP) ; ... MOV SP,R3 ; Point to it. MOVB F.LUN(R0),R1 ; Get the LUN. MOVB F.BKEF(R0),R2 ; Get the event flat # BNE 10$ ; J if specified. MOV #32.,R2 ; Use 32. by default. 10$: QIOW$S #IO.RVB,R1,R2,,R3,, MOV F.BKDS(R0),R1 ; Get the buffer size. ADD #777,R1 ; Round up to next block. ASH #-9.,R1 ; Make it into blocks. ADD R1,F.BKVB+2(R0) ; Get to the next block. ADC F.BKVB+2(R0) ; ... MOV F.BKST(R0),R2 ; Any I/O Status blocks? BEQ 20$ ; J if not. MOV (SP),(R2)+ ; Return IOST MOV 2(SP),(R2)+ ; ... 20$: TST @#$DSW ; Any errors? BMI 30$ ; J if so. TST (SP) ; Well? BGE 40$ ; J if not. 30$: SEC ; Indicate error. 40$: MOV (SP)+,(SP)+ ; Pop IOST. MOV (SP)+,R3 ; Recover registers. MOV (SP)+,R2 ; ... MOV (SP)+,R1 ; ... RETURN ; And return to the caller. .SBTTL WRITE - Write to a file ; WRITE: MOV R1,-(SP) ; Save R1 MOV R2,-(SP) ; Save R2 MOV R3,-(SP) ; And R3 CLR -(SP) ; Room for IOST CLR -(SP) ; ... MOV SP,R3 ; Point to it. MOVB F.LUN(R0),R1 ; Get the LUN. MOVB F.BKEF(R0),R2 ; Get the event flat # BNE 10$ ; J if specified. MOV #32.,R2 ; Use 32. by default. 10$: QIOW$S #IO.WVB,R1,R2,,R3,, MOV F.BKDS(R0),R1 ; Get the buffer size. ADD #777,R1 ; Round up to next block. ASH #-9.,R1 ; Make it into blocks. ADD R1,F.BKVB+2(R0) ; Get to the next block. ADC F.BKVB+2(R0) ; ... MOV F.BKST(R0),R2 ; Any I/O Status blocks? BEQ 20$ ; J if not. MOV (SP),(R2)+ ; Return IOST MOV 2(SP),(R2)+ ; ... 20$: TST @#$DSW ; Any errors? BMI 30$ ; J if so. TST (SP) ; Well? BGE 40$ ; J if not. 30$: SEC ; Indicate error. 40$: MOV (SP)+,(SP)+ ; Pop IOST. MOV (SP)+,R3 ; Recover registers. MOV (SP)+,R2 ; ... MOV (SP)+,R1 ; ... RETURN ; And return to the caller. .SBTTL DATA AREA ; ; DATA AREA FOR THE INDEX FILE SCANNER PROGRAM. ; SPSAVE: .WORD 0 ;SAVE AREA FOR SP IOST: .WORD 0,0 ;IO STATUS BLOCK FID: .WORD 0 ; File ID to be deleted FSEQN: .WORD 0 ; File sequence number to be deleted. HEADER: .BLKB 1000 ; Header area. BITMAP: .BLKB 1000 ;BITMAP BUFFER AREA BITEND: ;END OF BITMAP AREA HOME: .BLKB 1000 ;HOME BLOCK AREA M.PRIV: MSG M.IOR: MSG M.OPR: MSG M.BIF: MSG M.MDE: MSG M.UNK: MSG M.PS1: MSG M.PS2: MSG M.BAD: MSG M.FILE: MSG M.SMAL: MSG M.BIG: MSG M.ALL: MSG M.FID: MSG M.FSEQ: MSG BLKPR: .ASCII /DELFID/ BLKSZ = .-BLKPR .EVEN INDEX: FDBDF$ ;FDB FOR INDEX FILE FDRC$A FD.RWM ;USE BLOCK IO FDBK$A ,1000,,INDEVF,IOST FDOP$A INDLUN FSRSZ$ 1 ;NO BLOCKING BUFFERS NEEDED CMLBLK: GCMLB$ 2,FID,USRBUF,CMDLUN USRBUF: .BLKB 82. .EVEN CSI$ CSIBLK: .BLKB C.SIZE .EVEN SWTAB: CSI$SW FI,SW.FID,SWORD,SET,,FIDDSC CSI$ND FIDDSC: CSI$SV OCTAL,FID,2 CSI$SV OCTAL,FSEQN,2 CSI$ND SW.FID = 000001 ;/FI: SWITCH SWORD: .WORD QMSG: QIOW$ IO.WVB,MSGLUN,MSGEVF,,IOST,,<0,0,40> DSPT: .WORD DEVLEN,DEVSTR .WORD UICLEN,UICSTR .WORD FILLEN,FILSTR DEVSTR: .ASCII /SY0:/ DEVLEN = .-DEVSTR .EVEN UICSTR: .ASCII /[0,0]/ UICLEN = .-UICSTR .EVEN FILSTR: .ASCII /INDEXF.SYS/ FILLEN = .-FILSTR .EVEN .END BEGIN