.title RMVFIL - remove an unknown open file header .ident /RMVFIL V1.0/ .link "sys$system:sys.stb"/selective_search .library /sys$share:lib/ ;++ ; ; Program: RMVFIL.MAR V1.0 ; ; Author: David G. North, CCP ; 1333 Maywood Ct ; Plano, Texas 75023 ; (214) 653-1231 ; ; Date: 90.11.16 ; ; Revisions: ; Who Date Description ; D.North 901116 DECUS release ; ; VMS versions: Problem verified for V5.1-1 and V5.3. This program ; worked under both these versions. ; ; Disclaimer: There are absolutely *no* guarantees whatsoever about the ; applicability or reliability of this code under *any* ; conditions. *USE AT YOUR OWN RISK* ; ; License: ; Ownership of and rights to these programs is retained by the author(s). ; Limited license to use and distrubute the software in this library is ; hereby granted under the following conditions: ; 1. Any and all authorship, ownership, copyright or licensing ; information is preserved within any source copies at all times. ; 2. Under absolutely *NO* circumstances may any of this code be used ; in any form for commercial profit without a written licensing ; agreement from the author(s). This does not imply that such ; a written agreement could not be obtained. ; 3. Except by written agreement under condition 2, source shall ; be freely provided with all executables. ; 4. Library contents may be transferred or copied in any form so ; long as conditions 1, 2, and 3 are met. Nominal charges may ; be assessed for media and transferral labor without such charges ; being considered 'commercial profit' thereby violating condition 2. ; ; Warranty: ; These programs are distributed in the hopes that they will be useful, but ; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ; or FITNESS FOR A PARTICULAR PURPOSE. ; ; ; Description: ; The INSTALL utility under VMS V5.1-1 and VMS V5.3 (at least) has ; a problem with the replace command. If a version number is specified ; as the replacement target, and the original file is installed /open, ; it will be replaced, but the original file will still be held open. ; A further problem develops if you try to dismount the volume in that ; the volume will enter a dismount pending state, and become unusable. ; This program may be used to forcibly close the open file even in the ; case that a dismount is pending. ; ; Usage: ; First rule: Don't use INSTALL REPLACE and specify a version number. ; Second rule: Reboot your system to fix the problem if possible. ; Make *SURE* that all INSTALL'ed files on the volume are removed!!!! ; *DO NOT* use this program to harrass INDEXF.SYS, or QUOTA.SYS!!! ; Get all users off the drive, and off the system if possible. ; Type: $ SET COMMAND RMVFIL, and $ RMVFIL . ; ; RMVFIL.CLD: (remove ';' from these lines for RMVFIL.CLD) ; define verb rmvfil ; image sys$disk:[]rmvfil.exe ; parameter p1, label=file, ; prompt="File", ; value(required,type=$FILE) ; Assembly & linking: ; $ MACRO rmvfil ; $ LINK rmvfil ; ;-- $ssdef $rmsalldef $ucbdef $vcbdef $fcbdef $ccbdef $chfdef $dcdef $devdef $wcbdef $pcbdef .psect $$data,noexe,rd,wrt,noshr sfab: $fab ;save space for copy of ffab ffab: $fab - nam = fnam,- fac = snam: $nam ;save space for copy of fnam fnam: $nam - esa = fesa,- ess = NAM$C_MAXRSS,- rsa = frsa,- rss = NAM$C_MAXRSS,- nop = fesa: .blkb NAM$C_MAXRSS frsa: .blkb NAM$C_MAXRSS clifna: .ascid /FILE/ filnam: .ascid /............................................................/ devnam: .long 0,0 devchn: .long 0 devucb: .long 0 chnccb: .long 0 .psect $$code,exe,rd,nowrt,shr bug_catcher: ;condition handler for kernel oops! .word ^m movl CHF$L_SIGARGLST(AP),r4 ;signal argument list cmpl CHF$L_SIG_NAME(r4),#SS$_UNWIND ;is this an unwind??? beql 10$ ;yep... keep on unwinding movl CHF$L_MCHARGLST(AP),r5 ;get mechanism list address movl CHF$L_SIG_NAME(r4),CHF$L_MCH_SAVR0(r5) ;copy signal name $UNWIND_S ;Wipe out gracefully movl #SS$_CONTINUE,r0 ;Continue from exception 10$: ret ;return to caller of excepted procedure ;++ ; Following subr tries to $OPEN the spec'd file to get devname & fid ; possibility is that the device is marked DMT, but hung up because of ; the non-removed file problem. To deal with this situation, we will ; go to kernel, and remove the DMT bit temporarily so we can $OPEN the ; spec'd file & get its fid. The DMT bit will be recleared and we will ; proceed normally. Upon success of this program, the final $dassgn will ; free the last reference to the drive & it will dismount normally. ;-- hook_device: movc3 #FAB$S_FABDEF,ffab,sfab ;store these in case they need movc3 #NAM$S_NAMDEF,fnam,snam ; to be re-initialized $open fab=ffab ;try open call blbs r0,10$ cmpl r0,#RMS$_DNR beql 30$ ;do special stuff for DMT dev's rsb ;return any goofs 10$: $close fab=ffab ;close file... we now have FID blbs r0,20$ rsb 20$: movl #^x010e0000,devnam ;build a descrip for dev name bisb fnam+nam$b_dev,devnam ;pop in the length movl fnam+nam$l_dev,devnam+4 ;and stuff in the address $assign_s - ;try to get a channel to device devnam = devnam,- chan = devchn rsb ;all done.. got FID & chn ; here we have a bit of a problem... gotta 'fixup' the device so we can $open 30$: movl #^x010e0000,devnam ;get device from $open fail bisb fnam+nam$b_dev,devnam ;pop in the length movl fnam+nam$l_dev,devnam+4 ;and stuff in the address $assign_s - ;get channel so we can find UCB devnam = devnam,- chan = devchn blbs r0,40$ rsb ;tough luck...can't talk to dev 40$: movc3 #FAB$S_FABDEF,sfab,ffab ;restore fab & nam stuff movc3 #NAM$S_NAMDEF,snam,fnam ; ...needed later movzwl devchn,r0 ;prep to find UCB jsb g^IOC$VERIFYCHAN ;callable from user mode! blbs r0,50$ rsb ;sorry... VMS didn't like chn 50$: movl r1,chnccb ;save CCB address movl CCB$L_UCB(r1),devucb ;save UCB address $cmkrnl_s - ;goto kernel & routin = undmt ; try to un-dmt device blbs r0,60$ rsb ;something went wrong... bye 60$: pushab 80$ ;***MUST*** repair DMT stuff $open fab=ffab ;*NOW* try open call blbs r0,70$ rsb ;$open still failed... go DMT 70$: $close fab=ffab ;got FID, now close file rsb ;auto-call re-dmt 80$: pushl r0 ;save status $cmkrnl_s - ;goto kernel & routin = redmt ; re-dmt device popl r0 ;recover status rsb ;back to original caller ; Following code is in Kernel!!! .entry undmt, ^m ;Clear DMT if appropriate movaw bug_catcher,(FP) ;set a bugtrap movl devucb,r2 ;point @ device UCB movzwl #SS$_DEVNOTMOUNT,r0 ;prep an error ret bbs #DEV$V_MNT,UCB$L_DEVCHAR(r2),20$;Ok so far... 10$: ret ;return error in hand 20$: bbcci #DEV$V_DMT,UCB$L_DEVCHAR(r2),10$;No dismount pending if jmp ; we must have just cleared DMT status movzwl #SS$_NORMAL,r0 ;all went OK ret .entry redmt, ^m ;Set DMT movaw bug_catcher,(FP) ;set a bugtrap movl devucb,r2 ;point @ device UCB bbssi #DEV$V_DMT,UCB$L_DEVCHAR(r2),10$;force dmt pending 10$: movzwl #SS$_NORMAL,r0 ;all went OK ret .entry start, ^m pushaw filnam pushaq filnam pushaq clifna calls #3,g^CLI$GET_VALUE ;get filename from CLI blbs r0,10$ ret 10$: movb filnam,ffab+fab$b_fns ;poke it into the FAB movab @filnam+4,ffab+fab$l_fna bsbw hook_device ;hook channel to dev & get FID blbs r0,40$ ret ;couldn't open file or device 40$: movzwl devchn,r0 jsb g^IOC$VERIFYCHAN ;callable from user mode! blbs r0,50$ ret ;VMS doesn't like our channel 50$: movl r1,chnccb ;save CCB address for later movl CCB$L_UCB(r1),devucb ;save UCB address too ; we do not $DASSGN_S the channel, because we will hook the CCB into the ; non-deallocated WCB, fixup the WCB, and $DASSGN_S the channel to remove ; the installed file... also, from here on, we must be in Kernel...but first ; lock in the kernel pages $lkwset_s - ;lock down the high IPL kernel pages inadr = 55$ blbs r0,60$ ret 55$: .address start_locked_code ;address_range for high IPL .address stop_locked_code ; kernel pages ; Nowwww we can goto kernel 60$: $cmkrnl_s - ;hop into kernel & try to grab WCB routin = trytofix blbs r0,70$ ret ;something didn't go right... leave 70$: $dassgn_s - ;try to blow off the file chan = devchn ret ;Ha! system still running... goto DCL ; Following in Kernel!!! .entry trytofix, ^m movaw bug_catcher,(FP) ;set a trap in case of OOPS movl devucb,r1 ;get UCB address cmpb ucb$b_devclass(r1),#dc$_disk ;is this a disk? bneq 10$ ;issue an oops bbc #dev$v_ssm,ucb$l_devchar2(r1),20$ ;shadowsets not ok 10$: movl #SS$_NOTFILEDEV,r0 ;illegal devtype ret ;backhome 15$: movl #SS$_BUGCHECK,r0 ;program is confused... quit now ret ;backhome 20$: movl ucb$l_vcb(r1),r2 ;get VCB for given device beql 15$ ;issue I'm confused error & die tstw vcb$w_rvn(r2) ;is it part of volume set? bneq 10$ ;can't do volume sets either movl chnccb,r6 ;get CCB now (this page isn't locked) cmpl CCB$L_UCB(r6),r1 ;is this the right UCB? bneq 15$ ;no... drop dead movzwl fnam+nam$w_fid+0,r7 ;get FID (page is not locked) movzwl fnam+nam$w_fid+2,r8 ;get FID movzwl fnam+nam$w_fid+4,r9 ;get FID before we lock down ; *** FOLLOWING CODE @ ELEVATED IPL, SPINLOCK HELD *** start_locked_code: lock lockname = filsys,- ;Lockdown all FCB's preserve = no ;trashes only R0 pushab 701$ ;nosuchfile error exit movl vcb$l_fcbfl(r2),r3 ;get first FCB bneq 100$ ;begin processing rsb ;exit with nosuchfile ; FCB loop is here 100$: cmpl r2,r3 ;all FCB's done? bneq 110$ ;do another FCB rsb ;exit with nosuchfile 110$: tstw fcb$w_acnt(r3) ;is FCB active bneq 130$ ;branch to testFCB if active 120$: movl fcb$l_fcbfl(r3),r3 ;jmp thru to next FCB brb 100$ ;and start processing that FCB 130$: tstw fcb$w_segn(r3) ;is it an FCB extension segment? bneq 120$ ;yes... skipit & go to next FCB cmpw fcb$w_fid_num(r3),r7 ;matching num??? bneq 120$ ;nope... skip this FCB cmpw fcb$w_fid_seq(r3),r8 ;matching seq??? bneq 120$ ;nope... skip this FCB cmpw fcb$w_fid_rvn(r3),r9 ;matching rvn??? bneq 120$ ;nope... skip this FCB ; now... supposedly, we've found the file to remove... check characteristics movl fcb$l_wlfl(r3),r5 ;get WCB address beql 120$ ;no WCB... can't proceed with this FCB tstl wcb$l_pid(r5) ;see that no PID's got it & no refcnt bneq 120$ ;this ain't it! bbc #WCB$V_SHRWCB,WCB$B_ACCESS(r5),120$ ;this ain't it either! pushab 702$ ;temporary death-trap cmpl r1,WCB$L_ORGUCB(r5) ;is this *really* the right UCB? beql 140$ ;yes... ok to fixup the WCB rsb ;no... I'm confused... bye 140$: addl #4,SP ;remove temp trap ; supposedly we've found the right fellow... now munge the WCB adawi #1,WCB$W_REFCNT(r5) ;insert self to refcnt ; and... hook it to our CCB for closeup movl r5,CCB$L_WIND(r6) ;insert WCB address into our CCB addl #4,SP ;remove nosuchfile trap brb 888$ ;get outta here & try it now! 701$: movzwl #SS$_NOSUCHFILE,r0 ;I couldn't find a suitable file brb 999$ 702$: movzwl #SS$_BUGCHECK,r0 ;I got confused, so I quit brb 999$ 888$: movzwl #SS$_NORMAL,r0 ;All went ok... try to $dassgn now 999$: movl r0,r2 ;save return status unlock lockname = filsys ;return to caller setipl #0,unviron=uniprocessor ;lower IPL movl r2,r0 ;restore return status ret ;and back to USER stop_locked_code: ; *** END ELEVATED IPL CODE *** .end start