;DSK:<FOONEX>DISC.MAC;14 15-Jul-80 11:14:36, Edit by FRENCH
;UNLOCK DIR AFTER GETFDB IN NEWLFP STUFF
;DSK:<FOONEX>DISC.MAC;12 10-Jul-80 13:12:33, Edit by FRENCH
;MAKE SURE FDBBAT GETS INTO FDB (XBBAT MIGHT NOT BE ON IN XB AND
;ASOFN WON'T TURN ON OFNBAT IN SPTH) THIS IS IMPORTANT IF A HIT
;WAS TAKEN IN XB AND ONLY FDB GOT THE BAT BIT SET
;ALSO-PROPAGTE FDBBAT TO OFNBAT IF ASOFN WINS (BAD XB WON)
;SO SPTH CAN BE TESTED FOR BADNESS AS PAGES RELEASED.
;DSK:<FOONEX>DISC.PEF;7  8-Jul-80 14:27:09, Edit by FRENCH
;FIX PLACEMENT OF NEWLF1 LABEL FOR STACK SYNC
;DSK:<FOONEX>DISC.PEF;5  3-Jul-80 13:38:24, Edit by FRENCH
;COMPLETE HANDLING OF OPNX24 ASOFN FAILURE, ADD RNMX13
;DSK:<FOONEX>DISC.PEF;2  2-Jul-80 17:55:14, Edit by FRENCH
;INCOMPLETE HANDLING OF OPNX24 FAILURE OF ASOFN
;DSK:<PEFMON>DISC.MAC;9 24-Jun-80 11:25:17, Edit by FRENCH
;XFER OFNBAT FROM SPTH TO FDB (VIA FDBBAT BIT) IN DSKCLZ
;<134-TENEX>DISC.MAC;8    18-Feb-80 15:47:05    EDIT BY PETERS
; Added bug fixes from ISI
;<134-TENEX>DISC.MAC;7     2-Oct-79 13:32:06    EDIT BY PETERS
;removed losing disms form ofnjfn
;<134-TENEX>DISC.MAC;6    22-Aug-77 16:39:08    EDIT BY DANG
;1 Removed filcnt_min(filcnt,fillen-filbyn) from newwnd to speed output
;<134-TENEX>DISC.MAC;5     3-MAY-76 14:30:30    EDIT BY UNTULIS
;INCREASED DSKFNC FROM 5000 TO 25000
;<134-TENEX>DISC.MAC;4    15-MAR-76 10:48:34    EDIT BY UNTULIS
;ADDED CODE TO SAVE LAST READER IN FDBUSE AND NOT ALLOW CHANGE OF FDBUSE
;<134-TENEX>DISC.MAC;3    20-FEB-76 19:23:33    EDIT BY UNTULIS
;ADDED CODE TO FIX BUG IN LONG FILE PAGES IN CNTLNG
;<134-TENEX>DISC.MAC;2     4-FEB-76 15:27:03    EDIT BY UNTULIS
;ADDED DISK FENCE CODE
;<134-TENEX>DISC.MAC;113    25-JUN-75 12:09:31    EDIT BY ALLEN
; ENABLE PRIOR TO GETFDB CALL FOR FILE BECOMING LONG BECAUSE
; USER MAY HAVE NO ACCESS TO DIRECTORY CONTAINING PMF 
;<134-TENEX>DISC.MAC;112    28-APR-75 15:50:42    EDIT BY CLEMENTS
;<134-TENEX>DISC.MAC;111    28-APR-75 12:39:44    EDIT BY CLEMENTS
;<134-TENEX>DISC.MAC;110    28-APR-75 11:37:44    EDIT BY CLEMENTS
;<134-TENEX>DISC.MAC;109    24-APR-75 14:19:01    EDIT BY CLEMENTS
;<134-TENEX>DISC.MAC;108    31-MAR-75 10:10:12    EDIT BY TOMLINSON
; DSKCLZ: Don't zero rest of page unless writing the file
;<133-TENEX>DISC.MAC;107    11-DEC-74 17:24:20    EDIT BY CLEMENTS
; INTERN'ED USRSPC AND SYSSPC FOR OPRFN
;<133-TENEX>DISC.MAC;106    25-SEP-74 15:11:18    EDIT BY ALLEN
;<133-TENEX>DISC.MAC;105    25-SEP-74 13:16:14    EDIT BY TOMLINSON
; DSKCLZ: CALL GETFDB BEFORE RELOFN TO PROTECT FDB FROM ACCESS
;<133-TENEX>DISC.MAC;104    12-SEP-74 11:45:02    EDIT BY PLUMMER
; CLEAR FDB BACKUP WORDS IN RENAME
;<133-TENEX>DISC.MAC;103    23-AUG-74 14:55:01    EDIT BY PLUMMER
; ALLOW OPERATORS TO OPENF FILES IF DIRECTORY IS OVER ALLOCATION
;<TENEX-132>DISC.MAC;102     9-MAY-74 21:02:16    EDIT BY TOMLINSON
; RETURN OPNX23 ERROR FOR NO WRITE ACCESS TO DIRECTORY
;<TENEX-132>DISC.MAC;100     3-MAY-74 15:16:38	EDIT BY TOMLINSON
; ADD DIRECTORY ACCESS CHECK (WRTF) FOR OPENING FILES
;<TENEX-132>DISC.MAC;99     2-MAY-74 14:49:12	EDIT BY TOMLINSON
; CLEAR FILCNT AND FILWND AT OPENF0
;<TENEX-132>DISC.MAC;98    17-APR-74 21:45:53	EDIT BY TOMLINSON
; FIX LONG-STANDING BUG IN SETWND WHEN CALLED AFTER PMAP OF LONG
;  FILE PAGE (I.E. NOT PT 0)
;<TENEX-132>DISC.MAC;96    25-MAR-74 10:48:40	EDIT BY TOMLINSON
; DSKDEL DOES NOT ZERO FDBSIZ (DONE BY IMPLICIT UNDELETE)
;<TENEX-132>DISC.MAC;95    13-MAR-74 21:37:19	EDIT BY TOMLINSON
; ADDED FDBUND CHECKS IN DELETE AND RENAME
;<TENEX-132>DISC.MAC;93    31-JAN-74 11:20:21	EDIT BY TOMLINSON
; ZERO FDBSIZ OF SOURCE IN RENAME. DEFER FDB CHANGES UNTIL AFTER FILE
;  IS OPENED
;<TENEX-132>DISC.MAC;92    14-MAY-73 11:07:39	EDIT BY TOMLINSON
; Changed RENMSK to retain FDBEPH in dest
;<TENEX-132>DISC.MAC;91     9-APR-73 15:29:08	EDIT BY TOMLINSON
; Changed RENMSK FDBUSE to copy author from source
;<TENEX-132>DISC.MAC;90    13-FEB-73 19:09:50	EDIT BY CLEMENTS
; PATCH TO CLEAR FILWND PAGE ON CLOSE, AS DISTRIBUTED
;<TENEX-130>DISC.MAC;89    28-DEC-72 09:44:14	EDIT BY TOMLINSON
;<TENEX-130>DISC.MAC;88    20-DEC-72 13:50:28	EDIT BY TOMLINSON
;<TENEX-130>DISC.MAC;87    20-DEC-72 10:29:32	EDIT BY TOMLINSON
;<TENEX-130>DISC.MAC;86     7-DEC-72 14:05:02	EDIT BY TOMLINSON
;<TENEX-130>DISC.MAC;85     4-DEC-72 23:28:22	EDIT BY TOMLINSON
; CHANGED REFERENCE DATES TO BE READ DATES
;<TENEX-130>DISC.MAC;84     4-DEC-72 23:13:29	EDIT BY TOMLINSON
; BUG FIXES TO DSK RENAME PAGE COUNTING
;<TENEX-130>DISC.MAC;83    29-NOV-72 13:36:40	EDIT BY CLEMENTS
;CHECK FOR ZERO BYTE SIZE AT DISK CLOSE
;<TENEX-130>DISC.MAC;82    21-NOV-72 16:07:44	EDIT BY WALLACE
;<TENEX-130>DISC.MAC;81    19-NOV-72 23:37:31	EDIT BY WALLACE
;<DLM/TEMP>DISC.MAC;80    30-OCT-72 11:40:53	EDIT BY TOMLINSON
; FIXED CALL TO DELFIL IN DSKREN

	SEARCH	STENEX,PROLOG
	TITLE	DISC
	SUBTTL	R.S.Tomlinson	28 JUN 72	1000:

EXTERN DSKFRC,CAPENB,ERRSAV
EXTERN	BUGHLT,BUGCHK,DSKASN,ASOFN,RELOFN,SETMPG,MRPACS,MSTKOV
EXTERN	DEDSK,BHC,DELOFN
EXTERN	PFILPC,PFILBS
EXTERN	PBYTSZ,PBYTPO
EXTERN	CHKJFN,UNLCKF,DELFIL,FPTA
EXTERN	CPOPJ,SKPRET
EXTERN	MDDDIR,MDDNAM,MDDEXT,MDDVER,INSPRT,INSACT
EXTERN	JOBDIR,ACCCHK,DIRCHK,GETFDB,USTDIR,NFBSZ,ASGPAG,RELPAG
EXTERN	NSKED
EXTERN	RSKED
EXTERN	NXTDMP		; Zero to cause dump of open files
EXTERN	DIDSCA		; Disc address for di
EXTERN	DIDSCI		; Initial disc address for di

DEFINE	NOSKED<AOS NSKED>
DEFINE	OKSKED<SOSG NSKED
		XCT RSKED>

LS(CLASS)		; Class field counter

DSKFNC: ^D25000   ;DISK FENCE FOR CHECKING DIRECTORY OVERALLOCATION ***SRI-AIC***
USRSPC:: USRSCF	; DONT ALLOW WRITE OPEN IF USER EXCEEDED DISK ALLOCATION
SYSSPC:: SYSSCF	; DONT ALLOW WRITE OPEN IF SYSTEM FREE PAGE COUNT IS .L.
		; SYSSPC (ASSUMING SYSSPC .NE. 0 )

	USE	SWAPPC

DSKDTB::MDDDIR
	MDDNAM
	MDDEXT
	MDDVER
	INSPRT
	INSACT
	DSKINS		; Insert status
	DSKOPN
	DSKSQI
	DSKSQO
	DSKCLZ
	DSKREN
	DSKDEL
	DSKDMI
	DSKDMO
	CPOPJ
	CPOPJ
	CPOPJ
	CPOPJ
	CPOPJ		; Device status read
	CPOPJ		; Device status set

DSKDEL:	PUSHJ P,GETFDB
	JRST SKPRET
	PUSH P,A
	HRLI A,WRTF		;TO DELETE MUST HAVE WRITE ACCESS
	PUSHJ P,ACCCHK
	JRST [	SUB P,[XWD 1,1]
		PUSHJ P,USTDIR
		MOVEI A,DELFX1
		POPJ P,]
	POP P,A
	MOVSI B,FDBUND
	 TDNE B,FDBCTL(A)	; UNDELETABLE?
	 JRST DSKDE1		; YES, SKIP THIS
	MOVSI B,FDBDEL
	IORB B,FDBCTL(A)
DSKDE1:	PUSHJ P,USTDIR
	JRST SKPRET

DSKINS:	PUSHJ P,GETFDB
	BUG(HLT,<DSKINS: GETFDB FAILURE.>)
	MOVSI B,FDBTMP
	IORM B,FDBCTL(A)
	PUSHJ P,USTDIR
	POPJ P,

; Disk open routine
; Call:	LH(STS)	; Access desired
;	JFN	; Job file number
;	PUSHJ P,DSKOPN
; Return
;	+1	; Cannot open, reason in a
;	+2	; Success

DSKOPN:	PUSHJ P,GETFDB		; Get pointer to fdb
	JRST [	MOVEI A,OPNX2
		POPJ P,]	; File has been deleted
	HRLM A,0(P)		; SAVE FDB LOCATION IN LH RETURN PC
	MOVSI A,WRTF
	CALL DIRCHK		; CAN WE OPEN FILES IN THIS DIRECTORY?
	 JRST [	PUSHJ P,USTDIR
		MOVEI A,OPNX23
		POPJ P,]
	HLRZ A,0(P)
	HLL A,STS
	PUSHJ P,ACCCHK		; Check access
	 JRST [	PUSHJ P,USTDIR	; Access not allowed
		POPJ P,]
	TEST(CE,RNDF)		; Change flag from "append" to "random"
	 TEST(O,WRTF)		; And if append, allow writing
	TRNE STS,17		; ALLOW ONLY MODE 0
	 JRST [	MOVEI A,OPNX14
		PUSHJ P,USTDIR
		POPJ P,]	; Illegal mode
	TEST(NN,WRTF)
	 JRST OPENF1		; Not write
	MOVE B,CAPENB		; DONT CHECK IF ENABLED WHEEL
	TRNE B,WHEEL!OPR
	 JRST DSKOP2
	MOVE	B,DSKFRC	;FREE SPACE LEFT ***SRI-AIC***
	CAMG	B,DSKFNC	;ABOVE FREE SPACE FENCE? ***SRI-AIC***
	SKIPN USRSPC		; INDIVIDUAL CHECK ON ?
	 JRST DSKOP1		; NO
	HLRZ B,DIRDSK		; GET MAX ALLOCATION THIS DIRECTORY
	HRRE A,DIRDSK		; GET CURRENT ALLOCATION THIS DIRECTORY
	SUB B,A			; COMPUTE DIFFERENCE
	JUMPLE B,[		; IF OVER-ALLOCATED, GIVE ERROR
		MOVEI A,OPNX10
		PUSHJ P,USTDIR
		POPJ P, ]
DSKOP1:	MOVE B,DSKFRC		; FREE SPACE LEFT
	CAMG B,SYSSPC		; AND GIVE ERROR IF LESS THAN SYSSPC
	JRST [	MOVEI A,OPNX10
		PUSHJ P,USTDIR
		POPJ P, ]
DSKOP2:	HLRZ A,0(P)		; GET FDB LOCATION
	SKIPE B,FDBADR(A)	; Get disc address
	 JRST OPENF4
	MOVEI A,0		; NO DISC ADDRESS. GET ONE FREE CHOICE
	PUSHJ P,DSKASN		; Assign a disc address
	 JRST [	MOVEI A,OPNX10
		PUSHJ P,USTDIR
		POPJ P,]
	AOS B,CLASS
	ANDI B,777
	MOVEM B,CLASS
	CAIG B,2
	JRST .-4
	ROT B,4
	TLO A,<(1B3)>(B)
	MOVE B,A
	HLRZ A,0(P)
	MOVEM B,FDBADR(A)
	JRST OPENF4		; CONTINUE WITH WRITE

OPENF1:	HLRZ A,0(P)
	MOVE B,FDBCTL(A)
	TLNN B,FDBNXF		; Does this file exist
	JRST OPENF4
OPENF8:	MOVEI A,OPNX2		; No, cannot be opend
	PUSHJ P,USTDIR
	POPJ P,

OPENF4:	SKIPN FDBADR(A)
	 JRST OPENF8
	MOVEI B,0
	TEST(NE,RNDF)
	TLNE STS,READF!XCTF!ASPF
	MOVE B,FDBSIZ(A)	; Get size of file
	MOVEM B,FILLEN(JFN)	; To open file length
	MOVEM B,FILBYN(JFN)
	TEST(NE,RNDF)
	SETZM FILBYN(JFN)
	LDB A,PFILBS		; Get byte size
	SKIPN A
	MOVEI A,^D36
	LDB B,[POINT 4,STS,35]
	CAIN B,17
	SKIPA B,[^D36]		; Dump mode always 36 bit bytes
	LDB B,PBYTSZ
	CAILE B,^D36
	JRST [	MOVEI A,SFBSX2
		JRST OPENF6]
	PUSHJ P,NFBSZ
	HLRZ B,0(P)
OPENF9:	MOVE A,FDBADR(B)
	MOVE C,FDBCTL(B)
	TRNE STS,1B25		; Thawed access?
	TLO A,(1B2)		; Yes
	TEST(NE,WRTF)
	TLO A,(1B1)
	TLNE C,FDBLNG
	JRST OPNLNG		; Long files are opened peculiarly
	TLNN A,(1B3)
	JRST OPENF2		; Yes

OPENF7:	PUSHJ P,ASOFN		; Get an ofn for the file
	JRST OPENF6
	MOVE 2,(P)		;GET FDBADR
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	HRLZM A,FILOFN(JFN)
	PUSH P,A
	PUSHJ P,ASGPAG		; Get a free page of memory
	JRST [	HLRZ A,FILOFN(JFN)
		PUSHJ P,RELOFN
		SUB P,BHC+1
		MOVEI A,OPNX18
		JRST OPENF6]
	MOVE B,A
	EXCH A,(P)
	HRLI B,140000
	PUSHJ P,SETMPG		; Map the index block
	POP P,A
	HRLZI B,(A)
	HRRI B,1(A)
	SETZM (A)
	BLT B,777(A)		; Zero the index block
	HLRZ B,0(P)
	MOVSI C,(1B3)
	ANDCAM C,FDBADR(B)	; Clear new ib bit
	MOVSI C,FDBNXF
	TRNE STS,1B25
	ANDCAM C,FDBCTL(B)	; Clear non-existent bit for thawed
	HRRZ B,A
	MOVEI A,0
	PUSH P,B
	PUSHJ P,SETMPG		; Unmap the page
	POP P,A
	PUSHJ P,RELPAG		; Return to free pool
	SETZM NXTDMP
	JRST OPENF3

OPENF2:	PUSHJ P,ASOFN		; Get an of for this file
	JRST OPENF6
	MOVE 2,(P)		;GET FDBADR
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	HRLM A,FILOFN(JFN)
OPENF3:	TRNE STS,1B27		; CHANGE DATES?
	 JRST OPENF0
	MOVE B,JOBNO
	HRRZ B,JOBDIR(B)
	HLRZ A,0(P)
	TEST(NE,WRTF)
	HRLM B,FDBUSE(A)	; Save in fdb
	TEST(NE,READF)		; If open read
	HRRM B,FDBUSE(A)	; Record reader
	GTAD			; Get today
	MOVE B,A
	HLRZ A,0(P)
	JUMPL B,OPENF0
	TEST(NE,WRTF,ASPF)
	 MOVEM B,FDBWRT(A)	; Save as date of last write
	TEST(NE,READF,ASPF)
	 MOVEM B,FDBREF(A)
	SETZ B,
	TEST(NE,WRTF,ASPF)
	 MOVSI B,1
	TEST(NE,READF,ASPF)
	 HRRI B,1
	ADDM B,FDBCNT(A)	; Count number of writes and reads
OPENF0:	TEST(O,WNDF)		; No windows yet, and allow size change
	SETZM FILWND(JFN)
	SETZM FILCNT(JFN)
	PUSHJ P,USTDIR
	JRST SKPRET

OPENF6:	CAIN A,OPNX24		; XB READ FROM BAD SPOT?
	 JRST [ HLRZ 2,(P)	; YES-GET FDB ADR
		MOVSI 3,FDBBAT	; THE BAD FILE FILE BIT
		IORM 3,FDBCTL(2)
		JRST .+1]
	PUSHJ P,USTDIR
	POPJ P,

;ACCEPTS 1/ OFN (SECURE)
;	 2/ FDB ADR (CLOBBERED AS WELL AS AC 3)
;SETS OFNBAT IN SPTH FROM FDBBAT IN FDB INCASE ASOFN DID NOT SET
;OFNBAT IN SPTH FROM XBBAT IN XB

FDBSPH:	MOVE 2,FDBCTL(2)	;GET CTL WORD
	MOVSI 3,OFNBAT		;THE BAD FILE BIT IN SPTH
	TLNE 2,FDBBAT		;FDB CLAIMS BAD FILE?
	 IORM 3,SPTH(1)		;YES-SET IN SPTH INCASE ASOFN DID NOT (XBBAT=0)
	RET


OPNLNG:	PUSHJ P,ASOFN		; Assign ofn for pt table
	JRST OPENF6		; Busy
	MOVE 2,(P)		;GET FDBADR
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	HRRM A,FILOFN(JFN)	; Save ofn
	PUSHJ P,ASGPAG		; Assign a page to map the pt table
	JRST OPNLN1		; None available
	HRRM A,FILLFW(JFN)	; Save long file pt location
	MOVE B,A
	HRLI B,140000
	HRRZ A,FILOFN(JFN)
	PUSHJ P,SETMPG		; Map the pt table
	MOVE C,A
	SKIPN A,(B)
	BUG(HLT,<OPNLNG: NO PAGE TABLE 0 IN LONG FILE.>)
	HLLZ C,SPTH(C)
	TLZ C,760017
	TLZ A,40
	IOR A,C
	PUSHJ P,ASOFN		; Assign an ofn for it
	JRST OPNLN2		; This should happen rarely (if at all)
	MOVE 2,(P)		;GET FDBADR
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	HRLM A,FILOFN(JFN)	; Save as ofn of current pt
	TEST(O,LONGF)
	JRST OPENF3		; Set bits and exit

OPNLN2:	PUSH P,A		; Save error code
	HRRZ B,FILLFW(JFN)
	MOVEI A,0
	PUSHJ P,SETMPG
	HRRZ A,B
	PUSHJ P,RELPAG
	JRST OPNLN3

OPNLN1:	PUSH P,[OPNX17]
OPNLN3:	HRRZ A,FILOFN(JFN)
	PUSHJ P,RELOFN
	POP P,A
	JRST OPENF6

; Disc sequential input
; Call:	JFN	; Job file number
;	STS	; File status
;	FILBYT ETC. SETUP PROPERLY FOR NEXT BYTE
;	PUSHJ P,DSKSQI
; Returns +1 with a byte in a

DSKSQI:	MOVE B,FILBYN(JFN)
	CAML B,FILLEN(JFN)
	JRST [	TEST(O,EOFF)
		POPJ P,]
	TEST(NE,WNDF)		; Has window been set up yet?
	PUSHJ P,SETWND		; No, set it up
	SOSGE FILCNT(JFN)
	PUSHJ P,NEWWNI
	ILDB A,FILBYT(JFN)	; Get next byte
	AOS FILBYN(JFN)		; Count bytes
	POPJ P,

NEWWNI:	PUSHJ P,NEWWND
	SOS FILCNT(JFN)
	POPJ P,

; Disc sequential output
; Call:	JFN	; Job file number
;	STS	; File status
;	FIL BYT ETC SET UP
;	A	; A byte
;	PUSHJ P,DSKSQO

DSKSQO:	TEST(NE,WNDF)		; Has a window been set up?
	PUSHJ P,SETWND		; No, set it up
	PUSH P,A
	SOSGE FILCNT(JFN)
	PUSHJ P,NEWWNI
	POP P,A
	IDPB A,FILBYT(JFN)	; Deposit the byte
	AOS B,FILBYN(JFN)	; Count bytes
	CAMGE B,FILLEN(JFN)	; Beyond the end?
	POPJ P,			; No, done.
	TEST(O,EOFF)		; Yes, set eoff
	MOVEM B,FILLEN(JFN)	; Update new length
	POPJ P,

; Disk dump io

DSKDMI:	TDZA B,B
DSKDMO:	MOVEI B,1
	PUSH P,B
	PUSH P,A
	TEST(NE,WNDF)
	 PUSHJ P,SETWND
DMPLP:	SKIPL 0(P)
	 JRST [	SUB P,[XWD 2,2]
		POPJ P,]
	MOVE B,FILBYN(JFN)
	SKIPN -1(P)		; Writing
	CAMGE B,FILLEN(JFN)	; Or not past eof
	SKIPA			; Is ok
	 JRST [	TEST(O,EOFF)
		SUB P,[XWD 2,2]
		POPJ P,]
	SOSGE FILCNT(JFN)
	 PUSHJ P,NEWWNI
	AOS FILCNT(JFN)
	HLRE A,0(P)		; Iowd count
	MOVMS A			; Magnitude
	CAML A,FILCNT(JFN)
	 MOVE A,FILCNT(JFN)	; Keep lesser of the two
	MOVE C,A		; Keep copy of count
	ADDB A,FILBYN(JFN)	; Update filbyn
	CAML A,FILLEN(JFN)
	 MOVEM A,FILLEN(JFN)	; Update length
	MOVN A,C		; Neg of count
	ADDM A,FILCNT(JFN)	; Decrease filcnt
	MOVE A,FILBYT(JFN)	; Get copy of byte pointer
	ADDM C,FILBYT(JFN)	; Update byte pointer
	IBP A			; Gets loc of first word of file
	MOVE B,0(P)		; Get core loc
	HRLZI B,1(B)		; Into left half
	HRR B,A			; Make up blt pointer
	HRL C,C			; Put count in both halves
	ADDM C,0(P)		; Update iowd
	SKIPN -1(P)		; Write?
	 MOVSS B		; No reverse from and to
	ADDI C,-1(B)		; Last address in c
	BLT B,0(C)
	JRST DMPLP

; Set up a window for a file
; Call:	PUSHJ P,SETWND

SETWND:	PUSH P,A
	PUSHJ P,ASGPAG		; Assign a job page
	JRST [	TEST(O,ERRF)
		POP P,A
		POP P,0(P)	; Pop return off stack
		POPJ P,]	; And return one level back
	HRRM A,FILWND(JFN)
	TEST(Z,WNDF)
	PUSHJ P,NEWWND		; Set up window pointers
	POP P,A
	POPJ P,

; Set up pointers to a file
; Call:	FILBYN(JFN)	; File byte number
;	FILBYT(JFN)	; Byte size bits
;	LH(FILWND(JFN))	; Current page number
;	RH(FILWND(JFN))	; File window location
;	ETC.
;	PUSHJ P,NEWWND

NEWWND::TEST(NE,WNDF)
	POPJ P,			; Do nothing if no window yet
	PUSH P,A
	LDB A,PBYTSZ		; Get current byte size
	MOVEI C,^D36
	IDIV C,A		; Get bytes per word
	MOVE B,FILBYN(JFN)	; Get current byte number
	CAMLE B,FILLEN(JFN)
	MOVEM B,FILLEN(JFN)
	IDIV B,C		; Current word in b, offset in b+1
	IMUL B+1,A		; Offset times byte size
	MOVN C,B+1
	ADDI C,^D36
	DPB C,PBYTPO		; Yields byte pointer position
	MOVE C,B
	PUSH P,C		; Save for later
	LSH C,-9		; Get page number
	HLRZ B,FILWND(JFN)	; Get current page number
	TRNE B,777
	CAME B,C
	JRST NEWWNA		; Need to set up a new window

NEWWNZ:	POP P,C			; Restore word number
	ANDI C,777		; Get relative to page origin
	HRRZ B,FILWND(JFN)
	IOR B,C			; Get absolute address
	HRRM B,FILBYT(JFN)	; Put into byte pointer
	LDB A,PBYTSZ		; Get current byte size
	MOVEI C,^D36
	IDIV C,A		; Get bytes per word
	IMULI C,1000		; Get bytes per page
	MOVEM C,FILCNT(JFN)	; Save as count
	MOVN B,FILBYN(JFN)	; Get byte number
	IDIV B,C		; Remainder is negative
	ADDM B+1,FILCNT(JFN)	; Adjust if not at beginning of page
	POP P,A			; Restore a
	POPJ P,

NEWWNA:	HRRZ A,C
	PUSHJ P,JFNOF1		; Get ofn.pn for this page
	JRST [	TEST(O,ENDF)
		POP P,C
		POP P,A
		POPJ P,]
	TEST(NN,ASPF)		; If access is ass specified?
	JRST NEWWN1
	PUSH P,A
	PUSHJ P,MRPACS		; Read access of the page
	LSH A,1			; Shift bits into position for sts
	TLZ STS,READF!WRTF!XCTF	; Change access to that of this page
	AND A,[XWD READF!WRTF!XCTF,0]
	OR STS,A		; Change file access to that of the page
	POP P,A
NEWWN1:	HRRZ B,FILWND(JFN)
	HRLI B,160000
	PUSHJ P,SETMPG		; Map the the page
	MOVE C,(P)
	LSH C,-9
	HRLM C,FILWND(JFN)
	JRST NEWWNZ		; And finish up

; New page table for long file

NEWLFP:	PUSH P,C		; Save pt number
	TEST(NE,LONGF)		; Is this file already long?
	JRST NEWLFT		; Yes, no sweat
	PUSH P,CAPENB		; SAVE CURRENT CAPABILITIES
	HLLOS CAPENB		; GIVE HIM EVERYTHING TEMPORARILY
	PUSHJ P,GETFDB		; No, let's get the fdb
	 JSP A,NEWLFX
	POP P,CAPENB		; RESTORE CAPABILITIES
	MOVE C,FDBCTL(A)	; And see if it's become long
	TLNE C,FDBLNG		; Since we opened it
	JRST NEWFLL		; Yes, it has
	PUSH P,A		; No. save fdb location
	MOVE A,FDBADR(A)	; Get disc address of pt 0
	PUSHJ P,DSKASN		; Assign a page for the pt table
	 JRST [	PUSHJ P,USTDIR	; NO SPACE
		SUB P,[XWD 2,2]	; PULL UP STAKES
		POPJ P,]	; AND FAIL
	HLRZ B,FILOFN(JFN)	; Get ofn of current pt
	HLLZ C,SPTH(B)		; Get class field and write and thawed
	TLZ C,460017		; RETAIN WRITE, THAWED, AND CLASS
	IOR A,C		; COPY INTO NEW DISC ADDRESS
	PUSH P,A		; Save it for later
	TLO A,(1B3)		; Mark as new (can't get opnx24 error)
	MOVE 2,-1(P)		;FDB ADR IN 2	
	PUSHJ P,NEWLFS		; Assign ofn etc
	 JRST [	POP P,A		; GET BACK DISK ADDRESS
		PUSHJ P,DEDSK	; RELEASE IT
		PUSHJ P,USTDIR
		SUB P,BHC+2	; FLUSH THINGS ON STACK
		POPJ P,]	; AND GIVE FAIL RETURN
	HLRZ A,FILOFN(JFN)	; GET OFN OF PT
	MOVSI C,300000		; WRITE AND THAW
	ANDCAM C,SPTH(A)	; REMOVE FROM SPTH
	HRLZ A,B
	HRRI A,1(B)		; Prepare to clear the page
	SETZM (B)
	BLT A,777(B)
	POP P,C			; Get new disc address
	POP P,A			; And fdb location
	TLZ C,300000
	EXCH C,FDBADR(A)	; Store new disc address, get old
	TLZ C,017760		; No class fields in pt table
	TLO C,40
	MOVEM C,0(B)		; Store old disc address as pt 0
	MOVSI D,FDBLNG
	IORM D,FDBCTL(A)	; Mark fdb as long file
	JRST NEWLF1		; Continue with rest

;HERE VIA JSP A,NEWLFX

NEWLFX:	BUG(HLT,<NEWLFP: GETFDB FAILURE FOR OPEN FILE.>)
	JRST (A)		;CONTINUE WHEN FIXED UP

;skip if ok
;no skip and error # or 0 in 1 for failure.
;ACCEPTS 1/ ASOFN ARGS
;	 2/ FDB ADR

NEWLFS:	PUSH P,B		;SAVE FDB ADR
	PUSHJ P,ASOFN		; Assign ofn for (maybe new) disc address
	 JRST [	POP P,B		;RESTORE FDB ADR
		POPJ P,]	; FAIL, error # in A
	POP P,B			;RESTORE FDB ADR
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	HRRM A,FILOFN(JFN)	; Save
	PUSHJ P,ASGPAG		; Get a page to map the pt table
	 JRST [	HRRZ A,FILOFN(JFN)
		HLLZS FILOFN(JFN)
		PUSHJ P,RELOFN
		SETZ 1,		; RET 0 ERROR IF ASGPAG FAILED
		POPJ P,]
	HRRM A,FILLFW(JFN)	; Store location of pt table
	MOVE B,A
	HRLI B,140000
	HRRZ A,FILOFN(JFN)
	PUSHJ P,SETMPG
	JRST SKPRET

NEWFLL:	PUSH P,A		; SAVE FDB LOC
	MOVE B,A		; FDB ADR IN B
	MOVE A,FDBADR(A)	; File became long since we opened
	PUSHJ P,NEWLFS		; Map the pt table, ERROR IN A IF FAILS
	 JRST [	POP P,B		; GET FDB LOC AGAIN
		MOVSI C,FDBBAT	; BAD FILE BIT
		CAIN A,OPNX24	; READ BAD SPOT FROM DISK?
		 IORM C,FDBCTL(B) ;YES-MARK FILE BAD
		PUSHJ P,USTDIR
		SUB P,BHC+1
		POPJ P,]
	POP P,A			; RESYNC STACK
NEWLF1:	PUSHJ P,USTDIR		; Finished with directory
	TEST(O,LONGF)

NEWLFT:	HRRZ B,FILLFW(JFN)	; Get location of pt table
	ADD B,(P)		; Offset by pt # to get disc addr
	NOSKED			; To prevent others from tampering
	SKIPE A,(B)		; Is a disc address assigned for this pt
	JRST NEWLFA		; Yes, use it
	PUSH P,B		; Save location in pt table
	HLRZ A,FILOFN(JFN)	; Get ofn of pt table
	MOVE A,SPTH(A)		; Get disc address of pt table
	PUSHJ P,DSKASN		; Get a new disc address
	 JRST [	OKSKED
		SUB P,BHC+2
		POPJ P,]
	PUSH P,A
	HLRZ A,FILOFN(JFN)
	HLLZ A,SPTH(A)		; Get class bits
	TLZ A,760017
	IOR A,(P)
	TLO A,(1B3)
	PUSHJ P,ASOFN		; Assign ofn for new ib (CAN'T GET OPNX24)
	 JRST [	POP P,A		; UNLIKELY FAILURE OF ASOFN
		PUSHJ P,DEDSK	; BUT DO THE RIGHT THING ANYWAY
		OKSKED
		SUB P,BHC+2
		POPJ P,]
	PUSH P,A		; SAVE OFN
	PUSH P,CAPENB		; SAVE CURRENT CAPABILITIES
	HLLOS CAPENB		; GIVE HIM EVERYTHING TEMPORARILY
	OKSKED			; OH WELL...
	PUSHJ P,GETFDB		; let's get the fdb
	 JSP A,NEWLFX
	NOSKED
	POP P,CAPENB		; RESTORE CAPABILITIES
	MOVE B,A		;FDB IN B
	MOVE A,(P)			;OFN IN A
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	CALL USTDIR
	PUSHJ P,ASGPAG
	 JRST [	POP P,A		; OH NO!, THE WORST THING JUST HAPPENED
		PUSHJ P,DELOFN
		SUB P,BHC+3
		OKSKED
		POPJ P,]

	MOVE B,A
	HRLI B,140000
	MOVE A,(P)
	PUSHJ P,SETMPG		; Map the pt
	HRLZ A,B
	HRRI A,1(B)
	SETZM (B)
	BLT A,777(B)		; Clear pt
	MOVEI A,0
	PUSHJ P,SETMPG
	HRRZ A,B
	PUSHJ P,RELPAG
	POP P,A
	PUSHJ P,RELOFN
	POP P,A
	POP P,B
	TLO A,40
	MOVEM A,(B)
NEWLFA:	OKSKED
	HRRZ B,FILOFN(JFN)	; Get pt table ofn
	HLLZ B,SPTH(B)		; Get class field
	TLZ B,760017
	TLZ A,40
	IOR A,B			; Insert into disc address
	PUSHJ P,ASOFN
	 JRST [	CAIE A,OPNX24	; READ BAD SPOT FROM DISK?
		 JRST [	SUB P,BHC+1	; NO-SOME OTHER ERROR
			POPJ P,]
		PUSH P,CAPENB		;
		HLLOS CAPENB		; GIVE HIM EVERYTHING TEMPORARILY
		PUSHJ P,GETFDB		; let's get the fdb
		 JSP A,NEWLFX
		POP P,CAPENB		; RESTORE CAPABILITIES
		MOVSI B,FDBBAT		; BAD FILE BIT
		IORM B,FDBCTL(A)	; INTO FDB
		CALL USTDIR		; UNLOCK DIR AND GO OKINT
		SUB P,BHC+1
		MOVEI A,OPNX24		; RESTORE ERROR FOR RET
		POPJ P,]
	PUSH P,A		; SAVE OFN, MAY BE NOSKED NOW
	PUSH P,CAPENB		; SAVE CURRENT CAPABILITIES
	HLLOS CAPENB		; GIVE HIM EVERYTHING TEMPORARILY
	PUSHJ P,GETFDB		; let's get the fdb
	 JSP A,NEWLFX
	POP P,CAPENB		; RESTORE CAPABILITIES
	MOVE B,A		;FDB IN B
	MOVE A,(P)		;OFN IN A
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	CALL USTDIR
	POP P,A
	HLRZ B,FILOFN(JFN)
	HRLM A,FILOFN(JFN)
	MOVE A,B
	PUSHJ P,RELOFN
	POP P,C
	JRST SKPRET



; Convert jfn.pn to ofn.pn
; Call:	LH(A)	; Jfn
;	RH(A)	; Page number
;	PUSHJ P,JFNOFN
; Return
;	+1	; Error, illegal jfn or page number too big
;	+2	; Ok
;	LH(A)	; Ofn
;	RH(A)	; Page number

JFNOFN::HLRZ JFN,A
	PUSH P,A
	PUSHJ P,CHKJFN
	JRST [	POP P,ERRSAV
		POPJ P,]	; Garbage designator
	JFCL
	JRST [	POP P,ERRSAV
		MOVEI A,DESX4
		POPJ P,]
	POP P,A
	TEST(NE,ASTF)
	 JRST [	MOVEI A,DESX7
		JRST UNLCKF]
	TEST(NN,OPNF)
	JRST [	MOVEI A,DESX5
		JRST UNLCKF]
	HRRZ B,DEV
	CAIN B,DSKDTB
	TEST(NN,RNDF)
	JRST [	MOVEI A,PMAPX1
		JRST UNLCKF]
	HRRZS A
	PUSHJ P,JFNOF1
	JRST .+2
	AOS (P)
	JRST UNLCKF

JFNOF1::TLNE A,777777
	POPJ P,
	PUSH P,A
	HLRZ B,FILWND(JFN)	; Get current page number
	XOR B,A
	TRNN B,777000		; If different page tables
	JRST JFNOF2
	LSH A,-9		; Need special action
	MOVE C,A
	PUSHJ P,NEWLFP		; Change current page
	 JRST [	SETO A,		; FAILED
		SUB P,BHC+1
		POPJ P,]
	SETZM FILCNT(JFN)	; Force any sequential io to remap
JFNOF2:	MOVE A,(P)
	TRZ A,777
	HRLM A,FILWND(JFN)
	POP P,A
	HLL A,FILOFN(JFN)
	ANDCMI A,777000		; Mask out pt number
	JRST SKPRET

; Convert ofn.pn to jfn.pn
; Call:	LH(A)	; Ofn
;	RH(A)	; Pn
;	PUSHJ P,OFNJFN
; Return
;	+1	; No jfn found
;	+2	; Ok
;	A	; Jfn.pn

OFNJFX::TLO A,400000
OFNJFN::PUSH P,A
	HLRZS A
	ANDI A,377777
	PUSH P,A
	NOINT
	LOCK(JFNLCK,<JRST [
		OKINT
		CAIA
		 JRST .-2
		JSYS BLOCK0##]>)
	MOVE JFN,MAXJFN
	SOS JFN
	LSH JFN,SJFN		; Convert to index
OFNJF1:	MOVE STS,FILSTS(JFN)
	HRRZ A,FILDEV(JFN)
	CAIE A,DSKDTB
	JRST OFNJF2
	MOVE A,FILLFW(JFN)
	TLNN A,777776
	SKIPL -1(P)
	TEST(NN,OPNF)
	JRST OFNJF2
	TEST(NE,LONGF)
	JRST OFNJF3
	HLRZ A,FILOFN(JFN)
	CAME A,(P)
	JRST OFNJF2
OFNJF6:	POP P,A
	POP P,A
	LSH JFN,-SJFN		; Convert back to jfn
	HRL A,JFN
	UNLOCK JFNLCK
	OKINT
	JRST SKPRET

OFNJF3:	MOVE A,(P)		; Get ofn
	MOVE A,SPTH(A)		; Get disc address
	TLZ A,777760
	TLO A,40
	PUSH P,B
	MOVSI B,-1000
	HRR B,FILLFW(JFN)
OFNJF4:	CAMN A,(B)
	JRST OFNJF5
	AOBJN B,OFNJF4
	POP P,B
	JRST OFNJF2

OFNJF5:	SUB B,FILLFW(JFN)	; Get pt number
	HRRZS B
	LSH B,9			; Convert to page offset
	ADDM B,-2(P)		; Augment page number
	POP P,B
	JRST OFNJF6

OFNJF2:	SUBI JFN,1_SJFN	; To next jfn index
	JUMPGE JFN,OFNJF1
	POP P,A
	POP P,A
	UNLOCK JFNLCK
	OKINT
	POPJ P,

; Disk close
; Call:	JFN	; Job file number
;	PUSHJ P,DSKCLZ

DSKCLZ:	MOVE A,FILLEN(JFN)
	TEST(NN,WNDF)		; If no window
	CAME A,FILBYN(JFN)	; Or if not at end of file
	JRST DSKCL9		; Don't fix end
	TEST(NN,WRTF)		; Writing?
	 JRST DSKCL9		; No.
	HRRZ A,FILWND(JFN)	; Get window address
	PUSHJ P,FPTA		; Get ptn.pn
	PUSHJ P,MRPACS		; Read page access
	TLNN A,(1B3)		; Writable?
	 JRST DSKCL9		; No.
	MOVEI A,0
	MOVE B,FILBYT(JFN)
	TLNN B,007700		;ANY BYTE SIZE? 
	JRST DSKCL9		;NO. SHOULD BE, BUT DON'T HANG IN LOOP.
DSKCL7:	IBP B
	TRNN B,777
	JRST DSKCL9
	DPB A,B
	JRST DSKCL7

DSKCL9:	HRRZ B,FILWND(JFN)	; If window page exists
	JUMPE B,DSKCL2
	MOVEI A,0
	PUSHJ P,SETMPG		; Unmap window
	HRRZ A,FILWND(JFN)
	PUSHJ P,RELPAG		; Return page to free list
DSKCL2:	HLLZS FILWND(JFN)	;FORGET WINDOW PAGE ADDRESS
	PUSHJ P,GETFDB		; GET POINTER TO FDB AND LOCKOUT OTHERS
	 SETZ A,		; REMEMBER THAT FDB COULD NOT BE FOUND
	PUSH P,ZERO##		; RESERVE ROOM FOR OFN FLAGS, INIT TO 0
	PUSH P,A		; SAVE FDB FOR LATER
	TEST(NE,LONGF)
	JRST CNTLNG
	HLRZ A,FILOFN(JFN)	; Get ofn
	MOVE C,SPTH(A)		; GET OFN FLAGS - SIMPLE CASE
	IORM C,-1(P)		; AND SAVE ON STACK
	PUSHJ P,RELOFN
DSKCL0:	MOVE B,A		; PAGE COUNT INTO B
	POP P,A			; GET BACK FDB LOCATION
	POP P,C			; GET IOR OF OFN FLAGS
	JUMPE A,DSKCL1		; NOTHING TO DO IF NO FDB
	JUMPGE B,[
		PUSH P,B
		PUSH P,C
		LDB C,PFILPC	;GET OLD DISK PAGES THIS FILE
		SUB B,C		;COMPUTE NET CHANGE
		HRRE C,DIRDSK	;GET CURRENT USED COUNT
		ADD B,C		;COMPUTE NEW USED COUNT
		HRRM B,DIRDSK	;AND SAVE IT
		POP P,C
		POP P,B
		DPB B,PFILPC
		JRST .+1 ]
	MOVSI B,FDBNXF
	ANDCAM B,FDBCTL(A)	; Clear non-existent flag
	MOVSI B,FDBBAT
	TLNE C,OFNBAT		; WAS THERE A BAT BIT ON FOR AN OFN?
	 IORM B,FDBCTL(A)	; YES-LET USER KNOW THRU FDB
	TEST(NE,WRTF)
	TEST(NE,WNDF)
	JRST DSKCL3
	LDB B,PBYTSZ
	DPB B,PFILBS		; Update byte size
	MOVE B,FILLEN(JFN)
	MOVEM B,FDBSIZ(A)
DSKCL3:	PUSHJ P,USTDIR
DSKCL1:	SETZM NXTDMP
	JRST SKPRET

;HERE WITH FDB ADR ON STACK AT 0(P)
;          IOR OF OFN SPTH FLAGS AT -1(P)

CNTLNG:	HLRZ A,FILOFN(JFN)	; Get current page table ofn
	MOVE B,SPTH(A)		; GET ITS OFN FLAGS
	IORM B,-1(P)		; AND CONTRIBUTE TO STACK FLAGS
	PUSHJ P,RELOFN		; Release
	HRRZS FILOFN(JFN)
	PUSH P,ZERO##		;INIT COUNT OF PAGES
	JUMPL A,CNTLN4		; If still in use, skip counting
	MOVSI C,-1000		; Count thru 1000 page tables
	HRR C,FILLFW(JFN)	; At fillfw
CNTLNL:	SKIPN A,(C)
	 JRST CNTLN1
	PUSH P,C
	HRRZ B,FILOFN(JFN)
	HLLZ B,SPTH(B)
	TLZ B,760017
	TLZ A,40
	IOR A,B
	PUSHJ P,ASOFN		; Have to assign ofn for it to map
	 JRST [	MOVSI B,OFNBAT	; BIT TESTED FOR BAD FILE IN SPTH IOR CELL
		CAIN A,OPNX24	; READ XB FROM BAD SPOT?
		 IORM B,-3(P)	; YES-CONTRIBUTE TO BAD FILE IOR
		JRST CNTLN2]	; If failure, skip rest of counting
	MOVE B,-2(P)		;FDB TO B, A/ OFN
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	MOVE B,SPTH(A)		; GET OFN FLAGS FOR THIS PT
	IORM B,-3(P)		; AND CONTRIBUTE TO TOTAL IOR OF FLAGS
	PUSHJ P,RELOFN		; Now release which will count pages
	JUMPL A,CNTLN2		; If any page table busy, stop
	ADDM A,-1(P)		;ADD INTO SUM
	POP P,C
CNTLN1:	AOBJN C,CNTLNL
	JRST CNTLN3

CNTLN2:	POP P,C
CNTLN4:	SETOM 0(P)		; Remember we have no valid page count
CNTLN3:	HRRZ B,FILLFW(JFN)
	SETZ A,
	PUSHJ P,SETMPG		; Remove ptt from map
	HRRZ A,FILLFW(JFN)
	PUSHJ P,RELPAG		; And release storage
	HLLZS FILLFW(JFN)
	HRRZ A,FILOFN(JFN)
	MOVE B,SPTH(A)		;GET OFN FLAGS FOR THIS ONE
	IORM B,-2(P)		;CONTRIBUTE TO TOTAL IOR OF FLAGS
	PUSHJ P,RELOFN		; Release ofn of ptt
	HLLZS FILOFN(JFN)
	POP P,A
	JRST DSKCL0

; Mutlitple directory rename
; Call:	JFN	; Jfn of new name
;	A	; Jfn of existing file
;	PUSHJ P,DSKREN

DSKREN:	PUSH P,A		; SAVE SOURCE JFN
	PUSHJ P,GETFDB		; GET FDB
	JRST [	POP P,A		; NAME GONE
		MOVEI A,RNAMX2
		POPJ P,]
	PUSH P,A
	HRLI A,WRTF
	MOVSI B,FDBUND
	TDNN B,FDBCTL(A)	; NEVER RENAME UNDELETABLE FILES
	PUSHJ P,ACCCHK		; CAN WE WRITE ON SINK
	JRST [	PUSHJ P,USTDIR
		SUB P,[XWD 2,2]
		MOVEI A,RNAMX3
		POPJ P,]
	MOVE A,0(P)		; GET BACK FDB LOCATION
	SKIPN A,FDBADR(A)	; IS THERE A DISK ADDRESS FOR DESTINATION?
	JRST [	MOVEI A,0	; NO, WE'LL HAVE TO ASSIGN ONE
		PUSHJ P,DSKASN	; TO SERVE AS A PLACE HOLDER
		 JRST [	MOVEI A,RNAMX4	; BUT IF THAT FAILS,
			PUSHJ P,USTDIR	; WE CAN'T DO THE RENAME
			SUB P,BHC+2
			POPJ P,]
		MOVE B,(P)
		TLO A,(1B3+777B13)
		MOVEM A,FDBADR(B)
		JRST .+1]
	TLO A,(1B1)
	PUSHJ P,ASOFN		; ASSIGN OFN FOR UNTHAWED WRITING
	JRST [	CAIN A,OPNX24	; READ BAD SPOT SCANNING XB?
		 JRST [	MOVE A,0(P)	;YES-GET FDB LOC
			MOVSI B,FDBBAT	;BAD FILE BIT
			IORM B,FDBCTL(A) ;INTO FDB
			SUB P,[XWD 2,2]
			PUSHJ P,USTDIR
			MOVEI A,RNMX13	;SAY READ BAD SPOT FOR XB
			POPJ P,]
		SUB P,[XWD 2,2]	; CAN'T. BUSY OR BAD PT
		PUSHJ P,USTDIR
		CAIE A,OPNX9	; IF NO BUSY,
		SKIPA A,[RNAMX6]
		MOVEI A,RNAMX5
		POPJ P,]
	MOVE B,(P)		;FDB LOC IN B, OFN IN A
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	MOVEM A,(P)		; SAVE OFN (SMASHES FDB LOC)
	PUSHJ P,USTDIR		; THRU WITH DEST FOR NOW
	EXCH JFN,-1(P)		; SAVE DEST JFN, GET SOURCE JFN
	PUSHJ P,GETFDB		; GET SOURCE FDB
	JRST [	POP P,A		; WHOOPS, SOURCE WENT AWAY
		PUSHJ P,RELOFN	; HAVE TO UNDO WHAT WE DID
		POP P,JFN
		MOVEI A,RNAMX7
		POPJ P,]

DSKREO:	PUSH P,A		; SOURCE Fdb loc
	HRLI A,WRTF
	MOVSI B,FDBUND
	TDNN B,FDBCTL(A)	; NEVER RENAME UNDELETABLE FILES
	PUSHJ P,ACCCHK		; HAVE TO BE ABLE TO DELETE (WRITE)
	 JRST [	MOVEI A,RNAMX8	; AWW, SHUCKS. CAN'T DO THE RENAME
		JRST DSKRE8]
	MOVE A,0(P)		; GET BACK FDB LOC
	SKIPN A,FDBADR(A)
	 JRST [	MOVEI A,RNAMX9	; FROM HAS NO DISK ADDRESS
		JRST DSKRE8]
	TLO A,(1B1)
	PUSHJ P,ASOFN		; ASSIGN OFN FOR UNTHAWED WRITING
	JRST [	CAIN A,OPNX24	; READ BAD SPOT SCANNING XB?
		 JRST [	MOVE A,0(P)	;YES-GET FDB LOC
			MOVSI B,FDBBAT	;BAD FILE BIT
			IORM B,FDBCTL(A) ;INTO FDB
			MOVEI A,RNMX13	;SAY READ BAD SPOT FOR XB
			JRST DSKRE8]
		CAIE A,OPNX9	; BUSY OR BAD PT
		SKIPA A,[RNMX11]
		MOVEI A,RNMX10
		JRST DSKRE8]
	MOVE B,(P)		; GET FDB LOC TO B, A/ OFN
	CALL FDBSPH		;FDBBAT=>OFNBAT (INCASE ASOFN: XBBAT/\>OFNBAT)
	CAMN A,-1(P)		; RENAME TO SELF?
	JRST [	PUSHJ P,RELOFN	; Rename to self
		MOVEI A,RNMX12
		JRST DSKRE8]

; STACK NOW CONTAINS
; 0	; FDB LOC OF SOURCE
; -1	; OFN OF DESTINATION
; -2	; JFN OF DESTINATION
; -3	; RETURN

	MOVE JFN,-2(P)		; GET DESTINATION JFN BACK
	MOVEM A,-2(P)		; STORE SOURCE OFN ON STACK
	MOVEI B,0(P)		; WHERE TO PUT FDB
	MOVE A,0(P)		; RESCUE FDB LOC FIRST
	ADD P,[XWD FDBLEN-1,FDBLEN-1]
	JUMPGE P,MSTKOV
	HRL B,A			; MAKE BLT POINTER
	BLT B,0(P)
	MOVSI B,FDBPRM
	AND B,FDBCTL(A)		; RETAIN PERM BIT
	TLO B,FDBNXF!FDBDEL	; AND DELETE AND NON-EX IT
	HLLM B,FDBCTL(A)	; NEW CONTROL BITS
	LDB B,PFILPC		; GET PAGE COUNT (OLD GUY)
	MOVNS B
	ADD B,DIRDSK
	HRRM B,DIRDSK
	SETZB B,FDBADR(A)	; NO DISC ADDRESS
	DPB B,PFILPC
	SETZM FDBSIZ(A)		; ZERO LENGTH IN CASE RE-CREATED
	PUSHJ P,USTDIR		; FINISHED WITH SOURCE

; STACK NOW HAS
; 0 THRU -FDBLEN+1	; FDB
; -FDBLEN		; DESTINATION OFN
; -1-FDBLEN		; SOURCE OFN
; -2-FDBLEN		; RETURN

	PUSHJ P,GETFDB		; To other fdb (REMEMBER JFN SET ABOVE)
	BUG(HLT,<DSKREN: GETFDB FAILURE FOR OPEN FILE.>)
	EXCH A,-1-FDBLEN(P)	; SAVE FDB LOC, GET SOURCE OFN
	PUSHJ P,RELOFN		; FLUSH IT
	HRRZ A,-FDBLEN(P)	; Get ofn of new name
	PUSHJ P,RELOFN
	MOVE A,-FDBLEN-1(P)	; GET BACK TO FDB LOC
	MOVEI D,-DIRORG(A)
	PUSH P,E
	PUSH P,F
	PUSHJ P,DELFIL		; DELETE OLD CONTENT OF DESTINATION
	 JFCL			; MIGHT FAIL IF PERM NAME
	SKIPLE A,FDBACT+DIRORG(D)
	AOS DIRORG+1(A)		; CONTINUE TO USE OLD PROTECTION
	POP P,F			; RESTORE F AND E
	POP P,E

; NOW READY TO PLANT THE OLD FDB INTO THE NEW
; FIRST TO RECAP THE STACK
; -FDBLEN+1 TO 0	; SOURCE FDB
; -FDBLEN		; PREVIOUS OFN OF DESTINATION (NO LONGER VALID)
; -FDBLEN-1		; DEST FDB LOC
; -FDBLEN-2		; RETURN

DSKRE9:	MOVSI D,-FDBLEN		; PREPARE TO DO ALL FDB ENTRIES
	MOVE A,-1-FDBLEN(P)
	LDB B,PFILPC		; GET PAGES JUST FLUSH BY DELFIL
	MOVNS B
	ADD B,DIRDSK
	HRRM B,DIRDSK
	SETZM FDBBCK-FDBLEN+1(P)	;CLEAR BACKUP WORDS
	SETZM FDBBCK-FDBLEN+2(P)
	SETZM FDBBCK-FDBLEN+3(P)
	SETZM FDBBCK-FDBLEN+4(P)
	SETZM FDBBCK-FDBLEN+5(P)
	HRLI A,D
	MOVEI B,-FDBLEN+1(P)
	HRLI B,D
DSKR9L:	MOVE C,@B		; GET SOURCE
	XOR C,@A		; BIT DIFFERENCE
	ANDCM C,RENMSK(D)		; BITS TO RETAIN FROM DESTINATION
	XORM C,@A
	AOBJN D,DSKR9L
	LDB B,PFILPC		;GET FILE PAGES COUNT
	ADDM B,DIRDSK	;UPDATE NEW GUYS ALLOCATION
	SUB P,[XWD FDBLEN+2,FDBLEN+2]
	PUSHJ P,USTDIR
	SETZM NXTDMP
	JRST SKPRET

; COMMON ERROR ROUTINE

DSKRE8:	MOVEM A,-2(P)
	PUSHJ P,USTDIR
	POP P,A
	POP P,A
	PUSHJ P,RELOFN
	POP P,A
	POPJ P,

; MASKS OF BITS TO RETAIN IN DESTINATION

RENMSK:	-1
	FDBBAT!FDBTMP!FDBPRM!FDBEPH,,-1	; FDBCTL
	-1				; FDBEXT
	0				; FDBADR
	-1				; FDBPRT
	0				; FDBCRE
	0				; FDBUSE
	-1				; FDBVER
	-1				; FDBACT
	0				; FDBBYV
	0				; FDBSIZ
	0				; FDBCRV
	0				; FDBWRT
	0				; FDBREF
	0				; FDBCNT
	REPEAT 5,<0>			; FDBBCK
	0				; FDBUSW

	END

