Google
 

Trailing-Edge - PDP-10 Archives - BB-BT99S-BB_1990 - 10,7/backup/backrs.mac
Click 10,7/backup/backrs.mac to see without markup as text/plain
There are 13 other files named backrs.mac in the archive. Click here to see a list.
	TITLE	BACKRS -- MODULE TO DO THE WORK FOR BACKUP -- %6(704)
	SUBTTL	FRANK NATOLI/FJN/PFC/KCM/JEF/MEB/CLRH/VLR/CGN/WMG/DC/BPK/MS/BAH/EDS	7-FEB-90

DECVER==6		;MAJOR VERSION
DECMVR==0		;MINOR VERSION
DECEVR==703		;EDIT NUMBER
CUSTVR==0		;CUSTOMER VERSION


;+
;.AUTOPARAGRAPH.FLAG INDEX.FLAG CAPITAL.LOWER CASE
;.TITLE ^PROGRAM ^LOGIC ^MANUAL FOR ^^BACKRS\\
;.SKIP 10.CENTER;^^BACKRS\\
;.SKIP 1.CENTER;^PROGRAM ^LOGIC ^MANUAL
;.SKIP 1.CENTER;^VERSION 5A
;.SKIP -20.CENTER;<ABSTRACT
;.SKIP 1

;<BACKUP IS A PROGRAM WHICH BACKS UP THE DISK FILE SYSTEM
;ONTO MAG TAPE AND RESTORES FROM THIS TAPE.  <BACKRS IS A
;SEPARATE MODULE (ACTUALLY THE SECOND MODULE) OF THE
;PROGRAM AND HANDLES ALL THE WORK.
;^THE FIRST MODULE IS THE COMMAND SCANNER AND SETUP.
;^THIS WORKER MODULE LIVES IN THE LOW SEGMENT
;AND RELEASES AND RESTORES THE HIGH SEGMENT TO ELIMINATE MOST
;OF THE CORE WHEN RUNNING.

;.PAGE;^^
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1974,1977,1978,1979,1980,1981,1982,1984,1986,1988,1989,1990.
;ALL RIGHT RESERVED.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
;\\
;-\\

;               TABLE OF CONTENTS FOR BACKRS
;
;
;                        SECTION                                   PAGE
;    1. GENERAL INFORMATION.......................................   3
;    2. DEFAULT PARAMETERS........................................   4
;    3. DEFINITIONS...............................................   5
;    4. IMPURE STORAGE............................................  10
;    5. TAPE FORMAT...............................................  12
;    6. INITIALIZATION............................................  24
;    7. DISK TO TAPE MAIN ROUTINES................................  27
;    8. DISK TO TAPE SUBROUTINES..................................  42
;    9. TAPE TO DISK MAIN ROUTINES................................  49
;   10. TAPE TO DISK SUBROUTINES..................................  64
;   11. TAPE INPUT/OUTPUT SUBROUTINES.............................  69
;   12. DISK INPUT/OUTPUT ROUTINE.................................  82
;   13. LIST OUTPUT SUBROUTINES...................................  83
;   14. DATE CONVERSION SUBROUTINES...............................  92
;   15. FILE VERIFICATION SUBROUTINES.............................  94
;   16. SORT SUBROUTINES..........................................  97
;   17. CORE ALLOCATION SUBROUTINES...............................  99
;   18. TELETYPE I/O SUBROUTINES.................................. 100
;   19. ERROR MESSAGES............................................ 104
;+
;.LEFT MARGIN 0.RIGHT MARGIN 60

;.PAGE.SUBTITLE ^TABLE OF ^CONTENTS
;.CENTER;^TABLE OF ^CONTENTS
;.NOFILL.NOAUTOP.LM10.TAB STOPS 15,18.SKIP 2

;1.	^GENERAL ^INFORMATION
;2.	^DEFAULT ^PARAMETERS
;3.	^DEFINITIONS
;		^A^CS
;		^SOFTWARE ^CHANNELS
;		^MACROS
;		^OTHER ^DEFINITIONS
;		^FLAG BITS IN <AC ^F
;		^HOME ^BLOCK ^WORDS
;4.	^IMPURE ^STORAGE
;5.	^TAPE ^FORMAT
;6.	^PROGRAM ^INITIALIZATION
;7.	^DISK TO ^TAPE ^MAIN ^ROUTINES
;8.	^DISK TO ^TAPE ^SUBROUTINES
;9.	^TAPE TO ^DISK ^MAIN ^ROUTINES
;10.	^TAPE TO ^DISK ^SUBROUTINES
;11.	^TAPE ^INPUT/^OUTPUT ^SUBROUTINES
;12.	^DISK ^INPUT/^OUTPUT ^ROUTINE
;13.	^LIST ^OUTPUT ^SUBROUTINES
;14.	^DATE ^CONVERSION ^SUBROUTINES
;15.	^FILE ^VERIFICATION ^SUBROUTINES
;16.	^SORT ^SUBROUTINES
;17.	^CORE ^ALLOCATION ^SUBROUTINES
;18.	^TELETYPE ^I/^O ^SUBROUTINES
;19.	^ERROR ^MESSAGES
;^INDEX

;.PAGE.FILL.AUTOP.LM0.TS5,8

;.PAGE.FILL.AUTOP.LM0.TS5,8
SUBTTL GENERAL INFORMATION

;.CHAPTER GENERAL INFORMATION
;-

	SUBTTL GENERAL INFORMATION

;.CHAPTER GENERAL INFORMATION
;
;^SEARCHES ^^MACTEN, UUOSYM\\ AND ^^SCNMAC\\
;-

	SEARCH	MACTEN,UUOSYM,SCNMAC		;[174]
;%%C==%%C	;SHOW VERSION OF C
%%MACT==%%MACT	;SHOW VERSION OF MACTEN		[174]
%%SCNM==%%SCNM	;SHOW VERSION OF SCNMAC

COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1974,1990.  ALL RIGHTS RESERVED.
\;END COPYRIGHT MACRO

	SALL		;CLEAN LISTING


%%%BKP==:DECVER		;ENSURE CONSISTENT VERSION OF BACKUP
	SUBTTL	DEFAULT PARAMETERS

;+
;.CHAPTER DEFAULT PARAMETERS
;
;\\ ^THE FOLLOWING PARAMETERS CAN NOT BE CHANGED WITHOUT
;RISKING FURTHER DEBUGGING:		^^
;.TS20.LM20.P-20,0.SK.SELECT D
;D+

ND FT$DBG,1		;PARANOIA CODE
ND FT$IND,0		;CODE TO DO ALL DISK IO INDEPENDENTLY
ND FT$RCV,1		;TAPE ERROR RECOVERY CODE
ND FT$CHK,1		;CODE TO COMPUTE CHECKSUMS
ND FT$EMX,1		;CODE TO GIVE UP AFTER MAX NBR TAPE ERRORS
ND FT$FRS,0		;[335] CODE TO SUPPORT FRS **DUPLICATED IN BACKUP**
ND FT$USG,1		;CODE TO SUPPORT USAGE ACCOUNTING **DUPLICATED IN BACKUP**

ND M,^D32		;SIZE OF RECORD HEADER
ND N,4			;NUMBER OF DISK BLOCKS PER RECORD

ND HMBNBR,1		;UNIT HOME BLOCK ADDRESS
ND FORMAT,1		;FORMAT NUMBER
ND NDSKBF,8		;DISK BUFFERS
ND OPRNDB,^D20		;DISK BUFFERS FOR OPERATORS
ND EMAX,^D100		;MAX NUMBER OF TAPE ERRORS BEFORE GIVING UP
ND EOTEMX,1		;MAX NUMBER OF TAPE ERRORS AFTER EOT
			;BEFORE GIVING UP ON WRITING REPEATER RECORDS


;D.SELECT _;
;&.FILL;\\
	SUBTTL	DEFINITIONS

;+
;.FLAGS.LM 0.NOAUTOT.UPPER CASE
;.CHAPTER DEFINITIONS
;.HL1 AC DEFINITIONS
;.NOFILL.TS16;.P0,-1
;-


;AC'S

;&.END SELECT

F=0		;STATUS FLAGS
T1=1		;TEMP
T2=T1+1		; ..
T3=T2+1		; ..
T4=T3+1		; ..
P1=T4+1		;PERMANENT
P2=P1+1		; ..
P3=P2+1		; ..
P4=P3+1		; ..
SP=12		;FILE SPECIFICATION ADDRESS
LVL=13		;SFD LEVEL COUNTER
DBUF=14		;DISK BUFFER ADDRESS
MH=15		;TAPE HEADER REGION ADDRESS
CH=16		;ASCII CHARACTER
P=17		;PUSHDOWN POINTER

			;&

;+
;.HL1 SOFTWARE CHANNELS
;-.NOFILL.END SELECT

F.LIST==1	;LIST CHANNEL (OPEN/CLOSE BY BACKUP) **DUPLICATED IN BACKUP**
F.MTAP==2	;MAG TAPE CHANNEL (OPEN/CLOSE BY BACKUP) **DUPLICATED IN BACKUP**
FILE==3		;FILE
STR==4		;STRUCTURE
MFD==5		;MASTER-FILE-DIRECTORY
UFD==6		;USER-FILE-DIRECTORY
		;UFD+1 THRU UFD+.FXLND-1 RESERVED FOR SFDS

				;&
IFG UFD+.FXLND-17,<PRINTX ? SFD LEVEL TOO DEEP
			PASS2
			END>

HOLD==UFD+.FXLND	;[337] UFD-HOLDING CHANNEL.
;+
;.AUTOP.LOWER CASE

;.HL1 MACROS
;-

;+
;<SAVE$ _<LIST_> PUSHS THE LIST OF LOCATIONS
;ONTO THE STACK.
;-

	DEFINE	SAVE$	(LIST$),<
	XLIST
IRP (LIST$),<	PUSH	P,LIST$	>
	LIST
>


;+
;<RSTR$ _<LIST_> POPS THE LIST OF LOCATIONS FROM THE STACK.
;-

	DEFINE	RSTR$	(LIST$),<
	XLIST
IRP (LIST$),<	POP	P,LIST$	>
	LIST
>
;+
;<WARN$ (PREFIX,TEXT) ISSUES WARNING MESSAGE.
;-

	DEFINE	WARN$	(PFX$,TEXT$),<
	PUSHJ	P,WRNMSG
	JRST	E$$'PFX$
	OUTSTR	[ASCIZ\BKP'PFX$\]
	OUTSTR	[ASCIZ \ TEXT$
\]
E$$'PFX$::>


;+
;<WARN$N (PREFIX,TEXT) ISSUES WARNING MESSAGE (NO CARRIAGE RETURN).
;-

	DEFINE	WARN$N	(PFX$,TEXT$),<
	PUSHJ	P,WRNMSG
	JRST	E$$'PFX$
	OUTSTR	[ASCIZ\BKP'PFX$\]
	OUTSTR	[ASCIZ\ TEXT$ \]
E$$'PFX$::>


;+
;<OPER$ (PREFIX,TEXT) ISSUES OPERATOR MESSAGE.
;-

	DEFINE	OPER$	(PFX$,TEXT$),<
E$$'PFX$::OUTSTR	[ASCIZ \
$BKP'PFX$ TEXT$
\]
>
;+
;.HL1 OTHER DEFINITIONS
;.UPPER CASE.TS8,16,24
;-.NOFILL.NOAUTOPARAGRAPH.NOFLAGS.END SELECT

IFNDEF	PS.RSW,<PS.RSW==1B31>	;INCASE NOT IN UUOSYM YET

MTBBKP==M+<200*N>	;SIZE OF BACKUP RECORD ON TAPE
MTBFSZ==MTBBKP		;SIZE OF INPUT READ
IFN FT$FRS,<		;[335]
MTBFRS==24+5*200	;SIZE OF FRS BLOCK ON TAPE
IFG MTBFRS-MTBFSZ,<MTBFSZ==MTBFRS> ;[300]	**DUPLICATED IN BACKUP**
>; END IFN FT$FRS	;[335]
NM$TBF==6		;NUMBER OF TAPE BUFFERS **DUPLICATED IN BACKUP**
CP$INC==^D1000		;CHECKPOINT INCREMENT
CP$MRG==<NM$TBF+1>*N+10	;CHECKPOINT MARGIN
NRIB==.RBTIM+1		;NUMBER OF RIB ARGS USED
IFN FT$USG,<
NRIB==.RBAC8+1		;READ ACCOUNT STRINGS FROM RIB
>
NDCH==.DCBSC+1		;[601] NUMBER OF DSKCHR ARGS USED
LN$SYS==5		;LENGTH OF SYSTEM NAME BLOCK
LN$SSN==6		;LENGTH OF SAVE SET NAME BLOCK **DUPLICATED IN BACKUP**
LN$STR==^D36		;MAX NBR OF STRUCTURES **DUPLICATED IN BACKUP**
FX$MBF==.FXLEN+0	;/MBEFORE	**DUPLICATED IN BACKUP**
FX$MSN==.FXLEN+1	;/MSINCE	**DUPLICATED IN BACKUP**
FX$CNT==.FXLEN+2	;COUNTS MATCHES	**DUPLICATED IN BACKUP**
FX$STR==.FXLEN+3	;STRUCTURE FLAGS **DUPLICATED IN BACKUP**
FX$LEN==.FXLEN+4	;LENGTH OF SCAN BLOCK **DUPLICATED IN BACKUP**
ZERO5==0		;NO ARGS ALLOWED IN LOW ORDER FIVE BITS
IO.END==40		;END OF FILE BIT IN LH OF BUFFER STATUS WORD

VR.CUS==7B2		;CUSTOMER VERSION MASK
VR.MAJ==777B11		;MAJOR VERSION MASK
VR.MIN==77B17		;MINOR VERSION MASK
VR.EDT==777777B35	;EDIT VERSION MASK

				;&.PAGE

IFN FT$RCV,<
		 IFE NM$TBF-1, <
		PRINTX ? TAPE ERROR RECOVERY CODE REQUIRES MULTIPLE BUFFERS
		PASS2
		END>>
;+
;.HL1 FLAG BITS IN AC F
;-.NOFILL.END SELECT

FL$IND==1B0	;INDEPENDENT DISK IO
FL$UFD==1B1	;FIRST FILE USED IN UFD
FL$FLP==1B2	;BUBBLE INVERSION
FL$STR==1B3	;FIRST TIME STRUCTURE USED
FL$EF1==1B4	;FIRST TAPE EOF
FL$EF2==1B5	;SECOND TAPE EOF
FL$INI==1B6	;ENCRIPTION CODE INITIALIZED
FL$PAO==1B7	;PARTIAL ALLOCATION ONLY
FL$MAT==1B8	;FILE SPEC MATCHED
FL$EOV==1B9	;END-OF-VOLUME RECORD BEING SENT
FL$SLE==1B10	;SLE MESSAGE ISSUED
FL$D75==1B11	;MATCH ONLY BECAUSE OF /DATE75
FL$CHK==1B12	;/CHECK
FL$NBF==1B13	;ISSUED NBF MESSAGE
IFN FT$FRS,<		;[335]
FL$FRS==1B14	;DOING FRS CONVERSION
>; END IFN FT$FRS	;[335]
FL$KIL==1B15	;ABORT OPERATION
FL$TPE==1B16	;FILE HAD TAPE I/O ERROR
FL$PSI==1B17	;PSI ENABLED
FL$INP==1B18	;INPUT FORCED
FL$RCV==1B19	;RECOVERY CODE
FL$END==1B20	;END TAPE OUTPUT
FL$OPN==1B21	;DISK OUTPUT FILE IS OPEN
FL$PRN==1B22	;PROTECTION RENAME BIT
FL$FN==1B23	;[231] PRINTING FILENAME FLAG
FL$EST==1B24	;[232] .RBEST RENAME FLAG
FL$SKP==1B25	;[232] SKIP .RBEST RENAME KLUDGE
FL$DFE==1B26	;[254] DISK FILE HAD ERROR ON SAVE
FL$SV1==1B27	;[310] TO WRITE BLANK TAPE ON FIRST OUTPUT
FL$EPR==1B28	;[322] IF FL$PRN IS SET BECAUSE OF EOV
FL$HUF==1B29	;[337] UFD PPB IS BEING HELD
FL$ABS==1B30	;[522] ABORT STRUCTURE SINCE /INITIAL NOT FOUND

				;&

;+.HL1 /INITIAL BIT MASK DEFINITIONS
;.NOFILL.FLAG CONTROL #
;#END SELECT
;-

IB$STR==1	;[522] LOOKING FOR SPECIFIC /INITIAL FILE STRUCTURE
IB$NAM==2	;[522] LOOKING FOR /INITIAL FILENAME AND EXTENSION
IB$UFD==4	;[522] LOOKING FOR /INITIAL UFD
IB$SF1==10	;[522] LOOKING FOR /INITIAL SFD LEVEL 1
IB$SF2==20	;[522] LOOKING FOR /INITIAL SFD LEVEL 2
IB$SF3==40	;[522] LOOKING FOR /INITIAL SFD LEVEL 3
IB$SF4==100	;[522] LOOKING FOR /INITIAL SFD LEVEL 4
IB$SF5==200	;[522] LOOKING FOR /INITIAL SFD LEVEL 5

			;&#FLAG CONTROL

;+.HL1 HOME BLOCK WORDS
;.NOFILL.FLAG CONTROL #
;#END SELECT
;-

.HMNAM==0	;SIXBIT HOM
.HMCNP==16	;BP CLUSTER COUNT (E=7)
.HMCKP==17	;BP CHECKSUM (E=7)
.HMCLP==20	;BP CLUSTER ADDRESS (E=7)
.HMMFD==46	;LOGICAL BLOCK NUMBER WITHIN STRUCTURE OF 1ST RIB FOR MFD

NHOM==.HMMFD+1	;NUMBER OF HOME BLOCK WORDS USED

		;&#FLAG CONTROL . 
	SUBTTL	IMPURE STORAGE

;+
;.TS8,16,24
;.CHAPTER IMPURE STORAGE
;-.NOFILL.NOAUTOPARAGRAPH.NOFLAGS.END SELECT

TSTBLK::	BLOCK	1	; FLAG WORD FOR LOWSEG PASSAGE.		[344]


STOBEG==.		;BEGINNING OF STORAGE

USYSNM:	BLOCK	LN$SYS	;SYSTEM NAME
UMONTP:	BLOCK	1	;MONITOR TYPE
UMONVR:	BLOCK	1	;MONITOR VERSION
MFDPPN:	BLOCK	1	;MFD PPN
UAPRSN:	BLOCK	1	;APR SERIAL NUMBER
UPHYN:	BLOCK	1	;PHYSICAL DEVICE NAME
UMTCHR:	BLOCK	1	;TAPE CHARACTERISTICS
REELID:	BLOCK	1	;CURRENT REELID
PSIVCT:!		;BASE ADDRESS OF PSI VECTORS
PSITTY::BLOCK	4	;PSI VECTOR FOR TTY
PSIMTA::BLOCK	4	;PSI VECTOR FOR MTA

IFN FT$IND,<
CMDHMB:	BLOCK	2	;<IOWD NHOM,HMBBLK>
HMBBLK:	BLOCK	NHOM	;HOME BLOCK
CMDRIB:	BLOCK	2	;<IOWD 200,BLKRIB>
BLKRIB:	BLOCK	200	;RIB BLOCK
>;END IFN FT$IND

DSKHDR:	BLOCK	3	;DISK BUFFER HEADER
MDATA:	BLOCK	1	;POINTS TO INPUT TAPE DATA AREA
XMTABF:	BLOCK	1	;POINTS TO BUFFER TAKEN OUT OF RING
ERRCNT:	BLOCK	1	;COUNT OF TAPE ERRORS
SUSDF:	BLOCK	1	;SUPERSEDE DISK FILE			[206]

LSTFOP:	BLOCK	.FOMAX	;[520] FILOP. BLOCK FOR LISTING FILE

IFN FT$FRS,<		;[335]
FRSHDR:	BLOCK	M	;CONVERTED FRS BLOCK HEADER
FRSTIM:	BLOCK	1	;LABEL TIME	**DON'T CHANGE ORDER**
FRSDAT:	BLOCK	1	;LABEL DATE	**DON'T CHANGE ORDER**
FRSDSD:	BLOCK	1	;LABEL DESTROY DATE **DON'T CHANGE ORDER**
FRSSTM:	BLOCK	1	;SAVE SET TIME	**DON'T CHANGE ORDER**
FRSSDT:	BLOCK	1	;SAVE SET DATE	**DON'T CHANGE ORDER**
FRSSMD:	BLOCK	1	;SAVE SET MODE	**DON'T CHANGE ORDER**
FRSSTK:	BLOCK	1	;SAVE SET TRACKS **DON'T CHANGE ORDER**
FRSSTR:	BLOCK	1	;STR NAME	**DON'T CHANGE ORDER**
FRSNAM:	BLOCK	1	;FILE NAME	**DON'T CHANGE ORDER**
FRSEXT:	BLOCK	1	;EXTENSION	**DON'T CHANGE ORDER**
FRSPPN:	BLOCK	1	;FRS PPN	**DON'T CHANGE ORDER**
FRSRDB:	BLOCK	1	;RELATIVE DATA BLOCK	**DONT' CHANGE ORDER**
FRSSDB:	BLOCK	1	;NBR SDB	**DON'T CHANGE ORDER**
FRSSIZ:	BLOCK	1	;SIZE LAST BLOCK	**DON'T CHANGE ORDER**
FRSLVL:	BLOCK	1	;SFD DEPTH	**DON'T CHANGE ORDER**
FRSHDE==.-1		;END OF FRS CONVERSION BLOCKS
>; END IFN FT$FRS	;[335]
HCSTR:	BLOCK 	1	;[342] HELD STRUCTURE
HCPPN:	BLOCK	1	;[342] HELD PPN
CSTR:	BLOCK	1	;STRUCTURE
CSTRFL:	BLOCK	1	;STRUCTURE FLAGS
ACSTR:	BLOCK	1	;ALIAS STRUCTURE
CNAM:	BLOCK	1	;FILE
CNAMSW:	BLOCK	1	;[416] FILE NAME SWITCH
ACNAM:	BLOCK	1	;ALIAS FILE
CEXT:	BLOCK	1	;EXT
ACEXT:	BLOCK	1	;ALIAS EXT
CBLOCK:	BLOCK	1	;LOGICAL BLOCK ON STRUCTURE
CCDATI:	BLOCK	1	;CREATION DATE/TIME
CADATI:	BLOCK	1	;ACCESS DATE
CMDATI:	BLOCK	1	;MODIFY DATE/TIME
CWSIZE:	BLOCK	1	;BLOCK SIZE
LSTSTR:	BLOCK	1	;LAST STRUCTURE FOR LIST FILE COMPARISON
LSTPTH:	BLOCK	.FXLND+1;PATH FOR LIST FILE COMPARISON
NSEQ:	BLOCK	1	;RELATIVE SEQUENCE NUMBER
SAVADR:	BLOCK	1	;ORIGINAL MATCHED FILE SPECIFICATION
D75ADR:	BLOCK	1	;DITTO DUE TO /DATE75
SRTDIR:	BLOCK	1	;WHERE TO GO TO SORT DIRECTORIES
SRTFIL:	BLOCK	1	;WHERE TO GO TO SORT FILES
CHKCNT:	BLOCK	1	;COUNT OF CHECK DIFFERENCES
PTHCHK:	BLOCK	1	;CHECKSUM OF ASCIZ FULL PATH BLOCK

CURTAP:	BLOCK	1	;[355] CURRENT TAPE NUMBER
PRESTR:	BLOCK	1	;LAST STRUCTURE
PREPPN:	BLOCK	1	;LAST PPN
SAVACS:	BLOCK	10	;PLACE TO SAVE REGISTERS
SVCODE:	BLOCK	1	;SEED WORD
THSRDB:	BLOCK	1	;RELATIVE DATA BLOCK OF FILE
CHKPNT:	BLOCK	1	;CHECKPOINTS
BKSCLS:	BLOCK	1	;BLOCKS PER CLUSTER
DCHBLK:	BLOCK	NDCH	;FOR DSKCHR UUO
DCHARG:	BLOCK	5	;[503] FOR DSKCHR UUO

PRNAME:	BLOCK	1	;[227] RENAME PROTECTION STORAGE
EST:	BLOCK	1	;[232] .RBEST STORAGE
NRPS:	BLOCK	1	;[240] STORAGE TO INSURE ONE REPETITION WITH /<REPEAT
UNIQUE:	BLOCK	1	;UNIQUE EXTENSION NUMBER
IFE FT$USG,<
EXLFIL:	BLOCK	NRIB	;EXTENDED LOOKUPS/ENTERS/RENAMES
>
IFN FT$USG,<
EXLFIL:	BLOCK	200	;EXTENDED LOOKUPS/ENTERS/RENAMES (200 WORDS FOR /USETI)
>
EXLUFD:	BLOCK	NRIB	; ..
EXLUF1:	BLOCK	NRIB	;[530] PRESERVE UFD LOOKUP BLOCK FOR USAGE

DSKBLT:	BLOCK	1	;EITHER BLT OR PUSHJ P,COMPAR
DSKIO:	BLOCK	1	;EITHER DSKIN OR DSKOUT

PTHBLK:	BLOCK	.FXLND+3;ROOM FOR PATHING
UPTBLK:	BLOCK	.FXLND+3;ROOM FOR PATHING
APATH:	BLOCK	.FXLND+3;ROOM FOR PATHING
ADRLST:	BLOCK	.FXLND	;ADDRESS OF RIBS
TAPHLD:	BLOCK	2		;FIRST WORD FOR STATUS BITS
				;SECOND WORD IS ADDRESS OF DYNAMIC BUFFER

IFN FT$DBG,<			;[323]
FSZWDS:	BLOCK	1		;[323] SAVE AREA FOR FILE SIZE IN WORDS
>;END IFN FT$DBG		;[323]
NWPBLK:	BLOCK	1		;NUMBER OF WORDS/DISK BUFFER
NDBPMR:	BLOCK	1		;NUMBER OF DISK BUFFERS/MAGTAPE RECORD
NDBLIB:	BLOCK	1		;NUMBER OF DISK BLOCKS LEFT IN THIS DISK BUFFER
INIBTS::BLOCK	1		;[522] BIT MASK FOR /INITIAL FILESPEC
SAVBTS:	BLOCK	1		;[522] SAVED COPY OF ABOVE
BBSN:	BLOCK	1		;NUMBER OF DISK BLOCKS/TAPE FOR
				; CURRENT RECORD
STOEND==.-1	;END OF STORAGE

				;&
	SUBTTL	TAPE FORMAT

;+.AUTOPA.FLAGS.TS8,16,24,32,,,,,,,,,.P0,-1.FILL.LOWER CASE

;.CHAPTER BACKUP TAPE FORMAT

; <NOTE:  ^BACKUP IS DESIGNED FOR TWO PRIMARY FUNCTIONS; PERFORMING SYSTEM
;BACKUP AND INTERCHANGING FILES BETWEEN SYSTEMS.  ^FOR THE LATTER FUNCTION,
;^BACKUP PROVIDES AN "INTERCHANGE" SWITCH WHICH CAUSES SYSTEM DEPENDENT 
;DATA TO BE IGNORED AND ONLY CRITICAL FILE INFORMATION TO BE WRITTEN ON
;TAPE. ^A RESTORE OPERATION IN INTERCHANGE MODE ALSO IGNORES SYSTEM 
;DEPENDENT DATA, ALLOWING THE OPERATING SYSTEM TO SUPPLY DEFAULTS WHERE
;NECESSARY. ^ITEMS NOT INCLUDED IN INTERCHANGE
;MODE ARE NOTED IN THE DESCRIPTION WHICH FOLLOWS.

;.HL1 TAPE RECORD TYPES

;<BACKUP TAPES ARE MADE UP OF A SERIES OF TAPE RECORDS OF VARIOUS TYPES.
;^EACH RECORD IS SELF IDENTIFYING. ^ALL RECORDS ON THE TAPE ARE WRITTEN
;AT THE STANDARD LENGTH OF 544(10) WORDS, MADE UP OF A 32(10) WORD HEADER
;AND A 512(10) DATA AREA. ^EVEN IF THE DATA AREA IS NOT NEEDED, OR IS
;ONLY PARTIALLY NEEDED, IT IS FULLY WRITTEN. ^ALL UNDEFINED OR UNUSED
;WORDS ARE WRITTEN WITH ZEROS AND IGNORED ON READ. ^THIS MAXIMIZES
;THE PROBABILITY OF READING OLD TAPES. ^ALSO THE TAPE FORMAT IS INCLUDED
;IN THE LABELS AND THE SAVE SET HEADERS.
; ^THE RECORD TYPES ARE:

;.LS

;.LE;<T$LBL -- TAPE LABEL USED TO IDENTIFY REEL <ID AND
;DESTRUCTION DATE/TIME. ^THIS RECORD IS OPTIONAL, BUT IF PRESENT
;MUST BE AT THE START OF THE TAPE.

;.LE;<T$BEG -- BEGINNING OF A SAVE SET USED TO IDENTIFY WHEN
;THE SAVE SET WAS WRITTEN AND ON WHAT DEVICE OF WHAT SYSTEM.
;^IT ALSO INCLUDES THE SAVE SET NAME. ^THIS RECORD IS MANDATORY
;AND MUST BE THE FIRST RECORD OF THE SAVE SET.

;.LE;<T$END -- END OF A SAVE SET. ^THIS IS IDENTICAL TO THE <T$BEG
;RECORD EXCEPT THAT IT APPEARS AT THE END.

;.LE;<T$FIL -- THIS IS THE ACTUAL DATA WHICH HAS BEEN SAVED. ^IT IS
;THE ONLY TYPE OF RECORD WHICH IS ENCRYPTED. ^IT IS SELF-IDENTIFYING
;AS TO THE POSITION WITHIN THE FILE, BUT CONTAINS ONLY PART OF
;THE FULL PATH NAME OF THE FILE.

;.LE;<T$UFD -- CONTAINS THE INFORMATION FOR EACH DIRECTORY. ^IT
;GIVES ALL INFORMATION NECESSARY TO RE-CREATE THE DIRECTORY.
;(^NOT WRITTEN IN INTERCHANGE MODE.)

;.LE;<T$EOV -- INDICATES END OF VOLUME (FUTURE).

;.LE;<T$COM -- COMMENT (IGNORED).

;.LE;<T$CON -- CONTINUATION OF SAVE SET. ^THIS IS IDENTICAL TO
;<T$BEG EXCEPT THAT IT INDICATES THE CONTINUATION OF THE SAVE
;SET AT THE START OF A NEW VOLUME. ^THIS ENSURES THAT EACH
;VOLUME IS COMPLETELY SELF IDENTIFYING.

;-.ELS

T$LBL==1	;LABEL IDENTIFICATION RECORD
T$BEG==2	;SAVE START
T$END==3	;SAVE END
T$FIL==4	;DISK FILE DATA
T$UFD==5	;UFD RIB
T$EOV==6	;END OF VOLUME
T$COM==7	;COMMENT
T$CON==10	;CONTINUE (SAME DATA AS T$BEG-T$END)

T$MAX==T$CON	;MAXIMUM RECORD TYPE
;+.HL1 STANDARD RECORD FORMAT

;^EVERY TAPE RECORD HAS THE SAME GENERAL FORMAT. ^THIS
;CONSISTS OF A 32(10) WORD RECORD HEADER FOLLOWED BY ONE
;PAGE OF DATA (512(10) WORDS). ^ALL RECORD HEADERS START
;WITH THE SAME FIRST TWELVE WORDS. ^THE FIRST SEVEN WORDS ARE:

;.LS.LE;<G$TYPE -- RECORD TYPE AS DESCRIBED IN
;THE PREVIOUS SECTION. ^THIS IS A SMALL POSITIVE INTEGER.

;.LE;<G$SEQ -- RECORD SEQUENCE NUMBER. ^THIS IS INCREMENTED BY
;ONE FOR EACH RECORD ON THE TAPE. ^IF A RECORD IS REPEATED
;BECAUSE OF A TAPE WRITE ERROR, THE NUMBER OF THE REPEATED RECORD
;IS THE SAME AS THAT OF THE ORIGINAL.

;.LE;<G$RTNM -- RELATIVE TAPE NUMBER. ^THIS IS INCREMENTED BY
;ONE FOR EACH VOLUME.

;-.LE;<G$FLAG -- VARIOUS FLAG BITS:

G$TYPE==0	;RECORD TYPE
G$SEQ==1	;SEQUENCE NUMBER
G$RTNM==2	;RELATIVE TAPE NUMBER
G$FLAG==3	;RECORD DEPENDENT BITS

;+.LS.LE;<GF$EOF -- THIS FLAG IS SET IF THIS IS THE LAST TAPE
;RECORD FOR THIS DISK FILE. ^ON SHORT FILES,
;THIS CAN EVEN BE SET ON THE FIRST RECORD OF THE FILE!

;.LE;<GF$RPT -- THIS FLAG IS SET IF THIS TAPE RECORD IS A REPEAT
;OF THE PREVIOUS RECORD. ^THIS IS SET WHENEVER THE RECORD IS
;REWRITTEN BECAUSE OF A TAPE WRITE ERROR.

;.LE;<GF$NCH -- THIS FLAG IS SET IF NO CHECKSUM HAS BEEN
;COMPUTED FOR THE TAPE RECORD.

;.LE;<GF$SOF -- THIS FLAG IS SET IF THIS IS THE FIRST
;TAPE RECORD FOR THIS DISK FILE.

;.LE;<GF$DFE -- ONE OF THESE FLAGS IS SET IF ONE OF THESE DISK RECORDS
;HAD AN ERROR.
;-.ELS

GF$EOF==1B0	;LAST RECORD OF FILE
GF$RPT==1B1	;REPEAT OF LAST RECORD WRITE ERROR
GF$NCH==1B2	;IGNORE CHECKSUM
GF$SOF==1B3	;START OF FILE
GF$DF0==1B4	;[254] DISK FILE HAD ERROR (FIRST BLOCK ON TAPE)
GF$DF1==1B5	;[254] DISK FILE HAD ERROR (SECOND BLOCK ON TAPE)
GF$DF2==1B6	;[254] DISK FILE HAD ERROR (THIRD BLOCK ON TAPE)
GF$DF3==1B7	;[254] DISK FILE HAD ERROR (FOURTH BLOCK ON TAPE)
GF$DFE==GF$DF0!GF$DF1!GF$DF2!GF$DF3	;[254] DISK FILE HAD ERROR

;+.LE;<G$CHK -- CHECKSUM OF THE TAPE RECORD.

;.LE;<G$SIZ -- NUMBER OF WORDS USED FOR DATA IN THIS TAPE RECORD.

;.LE;<G$LND -- NUMBER OF WORDS TO SKIP BEFORE THE DATA STARTS.

;.ELS; ^THE NEXT FOUR WORDS ARE RESERVED FOR FUTURE EXPANSION.
;^THE TWELVTH (LAST) WORD IN THE GENERAL SECTION OF THE RECORD
;HEADER IS RESERVED FOR CUSTOMER USE. ^THE REMAINING 20 WORDS IN THE 
;RECORD HEADER VARY FOR EACH RECORD TYPE, WITH THE LAST WORD OF EACH
;RECORD HEADER BEING RESERVED FOR CUSTOMER USE. ^IN INTERCHANGE MODE,
;CUSTOMER RESERVED WORDS WILL BE WRITTEN WITH ZEROS ON A SAVE AND IGNORED ON A READ.
;-


G$CHK==4	;CHECKSUM
G$SIZ==5	;NUMBER OF DATA WORDS
G$LND==6	;TOTAL LENGTH OF NON-DATA SECTION
G$TBS==7	;TAPE BLOCK SIZE
   GC$BSZ==777777B17 ;SIZE OF THE TAPE BLOCK
   GC$N==777B35	;NUMBER OF DISK BLOCKS/TAPE BLOCK
G$CUSW==13	;RESERVED FOR CUSTOMER USE
;+.HL1 NON-DATA BLOCKS

;^THE DATA PORTION OF A TAPE RECORD IS PRIMARILY FOR STORING FILE DATA, BUT
;MAY BE USED FOR SAVING SOME OVERHEAD INFORMATION. ^ANY NON-DATA
;INFORMATION WRITTEN IN THE DATA AREA OF A TAPE RECORD IS PREFACED
;WITH A CONTROL WORD OF THE FORM:
; <LH = TYPE, <RH = LENGTH IN WORDS INCLUDING THIS WORD.

; ^MORE THAN ONE OVERHEAD REGION CAN APPEAR. ^IN THIS CASE, THEY FOLLOW
;EACH OTHER WITH NO INTERVENING SPACE. ^THE CURRENTLY DEFINED TYPES FOR
;OVERHEAD  BLOCKS ARE:

;.LS

;.LE;<O$NAME --  GIVES THE FULL PATH IDENTIFICATION OF THE FILE WITHOUT
;PUNCTUATION. ^THE PATH COMPONENTS ARE TREATED AS IF THE USER GAVE A 
;QUOTED REPRESENTATION IN "<DEC ^INTEGRATED ^COMMAND ^LANGUAGE".
;^THIS BLOCK CONSISTS OF SUB-BLOCKS IN THE STANDARD ORDER:  DEVICE,
;DIRECTORIES (TOP DOWN), FILE NAME, EXTENTION, VERSION, GENERATION.
;^SUB-BLOCKS CORRESPONDING TO MISSING FIELDS IN THE PATH SPECIFICATION
;ARE OMITTED. ^EACH SUB-BLOCK IS IN THE FORMAT:
; <WORD0: <LH = TYPE, <RH = LENGTH IN WORDS INCLUDING THIS WORD.

; ^THE REST OF THE SUB-BLOCK IS THE PATH FIELD IN <ASCIZ
;WITHOUT LEADING OR IMBEDDED NULLS, TERMINATED BY AT LEAST
;ONE NULL. ^FOR THE <UFD DIRECTORY FIELD, THE PROJECT AND 
;PROGRAMMER HALVES ARE CONVERTED TO OCTAL NUMBERS AND SEPARATED
;BY AN UNDERLINE CHARACTER. ^OMITTED FIELDS WILL BE DEFAULTED. ^IN INTERCHANGE
;MODE, ONLY THE NAME, EXTENSION AND VERSION ARE WRITTEN. ^IN
;INTERCHANGE RESTORE, ONLY NAME, EXTENSION AND VERSION ARE USED.
; ^SUB-BLOCK TYPE CODES ARE:

; 1 = DEVICE
; 2 = NAME
; 3 = EXTENSION
; 4 = VERSION
; 5 = GENERATION
; 40 = DIRECTORY  (LOWER DIRECTORIES ARE 41,42, ...)
;.LE;<O$FILE -- A BLOCK CONTAINING  FILE ATTRIBUTES. ^THE FIRST SECTION
;OF THIS BLOCK IS A FIXED LENGTH HEADER AREA CONTAINING IN FIXED
;LOCATIONS EITHER SINGLE WORD ATTRIBUTES OR BYTE POINTERS TO <ASCIZ
;STRING ATTRIBUTES  LOCATED IN THE REMAINING SECTION. ^ALL DATES AND TIME
;ARE IN UNIVERSAL DATE/TIME FORMAT. ^IN INTERCHANGE MODE ONLY THE CRITICAL
;ATTRIBUTES (STARRED)  WILL BE WRITTEN, AND THE REST OF THIS BLOCK WILL
;CONTAIN ZEROS. ^IN THE DESCRIPTION WHICH FOLLOWS, THE SYMBOLS IN BRACKETS
;REPRESENT THE <RIB DATA FROM WHICH THE ATTRIBUTE VALUES WILL BE CONVERTED.
;(^IF NONE IS GIVEN, THE LOCATION WILL BE ZERO)

;.LS;.LE;<A$FHLN (*) -- FIXED HEADER LENGTH IN WORDS.

;.LE;<A$FLGS -- FLAGS:

;.LS;.LE;<B$PERM -- PERMANENT (NOT DELETABLE) [<RP.NDL]

;.LE;<B$TEMP -- TEMPORARY

;.LE;<B$DELE -- ALREADY DELETED

;.LE;<B$DLRA -- DON'T DELETE FOR LACK OF RECENT ACCESS [<RP.ABU]

;.LE;<B$NQCF -- NOT QUOTA CHECKED [<RP.NQC]

;.LE;<B$NOCS -- DOES NOT HAVE VALID CHECKSUMS [<RP.ABC]

;.LE;<B$CSER -- HAS CHECKSUM ERROR [<RP.FCE]

;.LE;<B$WRER -- HAS DISK WRITE ERROR [<RP.FWE]

;.LE;<B$MRER -- HAD <BACKUP READ ERROR ON <RESTORE [<RP.BFA]

;.LE;<B$DAER -- DECLARED BAD BY DAMAGE ASSESSMENT [<RP.BDA]

;-.ELS

B$PERM==1B0	;PERMANENT
B$TEMP==1B1	;TEMPORARY
B$DELE==1B2	;ALREADY DELETED
B$DLRA==1B3	;DON'T DELETE FOR LACK OF RECENT ACCESS
B$NQCF==1B4	;NOT QUOTA CHECKED
B$NOCS==1B5	;DOES NOT HAVE VALID CHECKSUMS
B$CSER==1B6	;HAS CHECKSUM ERROR
B$WRER==1B7	;HAS DISK WRITE ERROR
B$MRER==1B8	;HAD <BACKUP READ ERROR ON RESTORE
B$DAER==1B9	;DECLARED BAD BY DAMAGE ASSESMENT
;TABLE OF BACKUP FLAGS:

BKPFLG:	EXP	B$PERM
	EXP	B$TEMP
	EXP	B$DELE
	EXP	B$DLRA
	EXP	B$NQCF
	EXP	B$NOCS
	EXP	B$CSER
	EXP	B$WRER
	EXP	B$MRER
	EXP	B$DAER
LN$FLG==.-BKPFLG

;TABLE OF CORRESPONDING RIB FLAGS:

RIBFLG:	EXP	RP.NDL
	EXP	Z
	EXP	Z
	EXP	RP.ABU
	EXP	RP.NQC
	EXP	RP.ABC
	EXP	RP.FCE
	EXP	RP.FWE
	EXP	RP.BFA
	EXP	RP.BDA

;+.LE;<A$WRIT (*) -- DATE/TIME OF LAST WRITE [<RB.CRD AND <RB.CRT]

;.LE;<A$ALLS (*) -- ALLOCATED SIZE IN WORDS [<.RBALC]

;.LE;<A$MODE (*) -- MODE OF LAST WRITE [<RB.MOD]

;.LE;<A$LENG (*) -- LENGTH IN BYTES (1^B0 IF _> 2_^35-1) [<.RBSIZ]

;.LE;<A$BSIZ (*) -- BYTE SIZE (7 OR 36).

;.LE;<A$VERS (*) -- VERSION IDENTIFICATION (<.JBVER FORMAT) [<.RBVER]

;.LE;<A$PROT -- PROTECTION [<RB.PRV]. ^THE PROTECTION FOR DIRECTORIES APPEARS
;IN THE DIRECTORY ATTRIBUTE BLOCK (<O$DIRT). ^FOR FILES, THE PROTECTION
;WORD IS DEFINED AS FOUR FIELDS OF EIGHT BITS EACH WITH A "5" STORED
;IN THE LEFTMOST THREE BITS IN ORDER TO AVOID LOOKING LIKE A BYTE POINTER:

; BITS 0-2		"5"

; BIT  3		RESERVED FOR FUTURE

; BITS 4-11		FUTURE ACCESS

; BITS 12-19		OWNER ACCESS

; BITS 20-27		AFFINITY GROUP ACCESS

; BITS 28-35		"WORLD" ACCESS

; ^EACH FILE ACCESS FIELD IS SUBDIVIDED INTO BYTES WHICH DESCRIBE THE
;ATTRIBUTE, WRITE AND READ (RESPECTIVELY) PROTECTIONS ASSOCIATED WITH THE
;FILE. ^A DESCRIPTION OF THE "WORLD" ACCESS FIELD FOLLOWS, WITH THE
;ASSOCIATED <TOPS-10 PROTECTION GIVEN IN PARENTHESES, IF APPLICABLE.
;^THE OWNER AND AFFINITY GROUP (PROJECT) FIELDS ARE SIMILARLY DEFINED.
;.LS

;.LE;<PR$SPC (BIT 28) -- RESERVED FOR SPECIAL CHECKING. ^THE REST OF THE FIELD IS
;SPECIAL IF THIS BIT IS SET.

;.LE;<PR$ATR (BITS 29-31) -- THE ATTRIBUTE SUBFIELD IS A 3-BIT BYTE INTERPRETED AS FOLLOWS:

; 0 -- FILE IS COMPLETELY HIDDEN.
; 1 -- FLIE NAME IS VISIBLE (7-6).
; 2 -- FILE ATTRIBUTES ARE VISIBLE (5-2).
; 3 -- CAN CHANGE UNPROTECTED ATTRIBUTES.
; 4-5 -- (FUTURE)
; 6 -- CAN CHANGE PROTECTION (0).
; 7 -- CAN DELETE THE FILE (1).

;.LE;<PR$WRT (BITS 32-33) -- THE WRITE ACCESS  SUBFIELD IS DEFINED AS:

; 0 -- NO WRITE ACCESS (7-5).
; 1 -- APPEND (4).
; 2 -- WRITE (3).
; 3 -- SUPERSEDING GENERATION (2-0).

;.LE;<PR$RED (BITS 34-35) -- THE READ ACCESS SUBFIELD IS DEFINED AS:

; 0 -- NO READ ACCESS (7).
; 1 -- EXECUTE ONLY (6).
; 2 -- CAN READ THE FILE (5-0).
; 3 -- (FUTURE).

;.ELS
;.LE;<A$ACCT -- BYTE POINTER TO ACCOUNT STRING

;.LE;<A$NOTE -- BYTE POINTER TO ANNOTATION STRING [<.RBSPL]

;.LE;<A$CRET -- CREATION DATE AND TIME OF THIS GENERATION 

;.LE;<A$REDT -- LAST READ DATE AND TIME OF THIS GENERATION [<RB.ACD]

;.LE;<A$MODT -- MONITOR SET LAST WRITE DATE AND TIME [<.RBTIM]

;.LE;<A$ESTS -- ESTIMATED SIZE IN WORDS [<.RBEST]

;.LE;<A$RADR -- REQUESTED DISK ADDRESS [<.RBPOS]

;.LE;<A$FSIZ -- MAXIMUM FILE SIZE IN WORDS

;.LE;<A$MUSR -- BYTE POINTER TO IDENTIFICATION OF LAST MODIFIER

;.LE;<A$CUSR -- BYTE POINTER TO IDENTIFICATION OF CREATOR [<.RBAUT]

;.LE;<A$BKID -- BYTE POINTER TO IDENTIFICATION OF PREVIOUS <BACKUP [<.RBMTA]

;.LE;<A$BKDT -- DATE AND TIME OF LAST BACKUP

;.LE;<A$NGRT -- NUMBER OF GENERATIONS TO RETAIN

;.LE;<A$NRDS -- NUMBER OF OPENS FOR READ THIS GENERATION

;.LE;<A$NWRT -- NUMBER OF OPENS FOR WRITE THIS GENERATION

;.LE;<A$USRW -- UNDEFINED USER WORD [<.RBNCA]

;.LE;<A$PCAW -- PRIVILEGED CUSTOMER WORD [<.RBPCA]

;.LE;<A$FTYP (*) -- FILE TYPE AND FLAGS WORD [<.RBTYP]

;.LE;<A$FBSZ (*) -- BYTE SIZES [<.RBBSZ]

;.LE;<A$FRSZ (*) -- RECORD AND BLOCK SIZES [<.RBRSZ]

;.LE;<A$FFFB (*) -- APPLICATION/CUSTOMER WORD [<.RBFFB]

;-.ELS

A$FHLN==0	;HEADER LENGTH WORD
A$FLGS==1	;FLAGS
A$WRIT==2	;CREATION DATE/TIME
A$ALLS==3	;ALLOCATED SIZE
A$MODE==4	;MODE
A$LENG==5	;LENGTH
A$BSIZ==6	;BYTE SIZE
A$VERS==7	;VERSION
A$PROT==10	;PROTECTION
A$ACCT==11	;BYTE POINTER ACCOUNT STRING
A$NOTE==12	;BYTE POINTER TO ANONOTATION STRING
A$CRET==13	;CREATION DATE/TIME OF THIS GENERATION
A$REDT==14	;LAST READ DATE/TIME OF THIS GENERATION
A$MODT==15	;MONITOR SET LAST WRITE DATE/TIME
A$ESTS==16	;ESTIMATED SIZE IN WORDS
A$RADR==17	;REQUESTED DISK ADDRESS
A$FSIZ==20	;MAXIMUM FILE SIZE IN WORDS
A$MUSR==21	;BYTE POINTER TO ID OF LAST MODIFIER
A$CUSR==22	;BYTE POINTER TO ID OF CREATOR
A$BKID==23	;BYTE POINTER TO SAVE SET OF PREVIOUS <BACKUP
A$BKDT==24	;DATE/TIME OF LAST BACKUP
A$NGRT==25	;NUMBER OF GENERATIONS TO RETAIN
A$NRDS==26	;NBR OPENS FOR READ THIS GENERATION
A$NWRT==27	;NBR OPENS FOR WRITE THIS GENERATION
A$USRW==30	;USER WORD
A$PCAW==31	;PRIVILEGED CUSTOMER WORD

A$FTYP==32	;FILE TYPE AND FLAGS
A$FBSZ==33	;BYTE SIZES
A$FRSZ==34	;RECORD AND BLOCK SIZES
A$FFFB==35	;APPLICATION/CUSTOMER WORD

LN$AFH==36	;LENGTH OF FIXED HEADER

;PROTECTION BYTES:

AC$OWN==377B19	;OWNER ACCESS FIELD
AC$GRP==377B27	;AFFINITY GROUP ACCESS FIELD
AC$WLD==377B35	;WORLD ACCESS FIELD

PR$ATR==7B31	;ATTRIBUTE PROTECTION SUBFIELD
PR$WRT==3B33	;WRITE PROTECTION SUBFIELD
PR$RED==3B35	;READ PROTECTION SUBFIELD

;+
;^THE REMAINDER OF THIS BLOCK IS RESERVED FOR FUTURE EXPANSION.
;.LE;<O$DIRT -- A BLOCK CONTAINING DIRECTORY ATTRIBUTES (NOT WRITTEN
;IN INTERCHANGE MODE). ^THE FIRST SECTION OF THIS BLOCK IS A FIXED
;LENGTH HEADER AREA CONTAINING EITHER DIRECTORY ATTRIBUTES OR  POINTERS
;TO ATTRIBUTES LOCATED IN THE REMAINING SECTION. ^THE SYMBOLS IN
;BRACKETS REPRESENT THE <RIB DATA USED FOR CONVERSION (THE LOCATION IS ZERO
;IF NONE IS GIVEN). ^THE DIRECTORY PROTECTION WORD APPEARS IN THIS BLOCK
;RATHER THAN IN THE <O$FILE BLOCK (<A$PROT IS ZERO FOR DIRECTORIES).

;.LS
;.LE;<D$FHLN -- FIXED HEADER LENGTH IN WORDS

;.LE;<D$FLGS -- DIRECTORY FLAGS:

;.LS.LE;<DF$FOD -- FILES ONLY DIRECTORY

;.LE;<DF$AAL -- ALPHA ACCOUNTS ARE LEGAL

;.LE;<DF$RLM -- REPEAT LOGIN MESSAGES
;-.ELS

DF$FOD==1B0	;FILES ONLY DIRECTORY
DF$AAL==1B1	;ALPHA ACCOUNTS ARE LEGAL
DF$RLM==1B2	;REPEAT LOGIN MESSAGES

;+.LE;<D$ACCT -- ACCOUNT NUMBER OR <ASCII BYTE POINTER TO ACCOUNT STRING

;.LE;<D$PROT -- DIRECTORY PROTECTION [<RB.PRV]. 
;^THE DIRCTORY PROTECTION WORD IS DIVIDED INTO THE SAME ACCESS FIELDS
;AS THE FILE PROTECTION WORD, <A$PROT, BUT EACH DIRECTORY ACCESS FIELD
;HAS BITS AS FOLLOWS (<RIB BITS GIVEN IN PARENTHESES):

; ^BIT 28 -- RESERVED FOR SPECIAL CHECKING. ^THE REST OF THE
;FIELD IS SPECIAL IS THIS BIT IS SET.
; ^BITS 29-31 -- (FUTURE)
; ^BIT 32 -- CONNECT ALLOWED
; ^BIT 33 -- CAN OPEN FILES (4)
; ^BIT 34 -- CAN CREATE GENERATIONS (2)
; ^BIT 35 -- DIRECTORY CAN BE READ (1)

;.LE;<D$FPRT -- DEFAULT FILE PROTECTION

;.LE;<D$LOGT -- DATE/TIME OF LAST LOGIN IN <DEC-10 UNIVERSAL FORMAT [<RB.CRD AND <RB.CRT]

;.LE;<D$GENR -- DEFAULT NUMBER OF GENERATIONS TO KEEP

;.LE;<D$QTF -- FIRST-COME-FIRST-SERVED LOGGED-IN QUOTA IN WORDS [<.RBQTF]

;.LE;<D$QTO -- LOGGED OUT QUOTA IN WORDS [<.RBQTO]

;.LE;<D$ACSL -- LIST OF GROUPS WHICH CAN ACCESS THIS DIRECTORY (SEE BELOW)

;.LE;<D$USRL -- LIST OF GROUPS WHICH THIS USER IS IN (SEE BELOW)

;.LE;<D$PRVL -- PRIVILEGE LIST (SEE BELOW)

;.LE;<D$PSWD -- <ASCII BYTE POINTER TO PASSWORD
;.ELS

;^THE LIST ATTRIBUTE WORDS GIVEN ABOVE (<D$ACSL, <D$USRL, <D$PRVL)
;MAY BE IN ANY ONE OF THE FOLLOWING FORMATS:

; A) AN <ASCII STRING POINTER
; B) 5^B2 _+ GROUP (OR 5^B2 _+ PRIVILEGE FOR <D$PRVL)
; C) _-^N,,RELATIVE LOCATION OF START OF LIST

; ^IF IN FORMAT (C), EACH WORD OF THE LIST IS 5^B2 _+ GROUP (5^B2 _+ PRIVILEGE FOR <D$PRVL)
;-

D$FHLN==0	;FIXED HEADER LENGTH WORD
D$FLGS==1	;DIRECTORY FLAGS
D$ACCT==2	;ACCOUNT NUMBER
D$PROT==3	;DIRECTORY PROTECTION
D$FPRT==4	;DEFAULT FILE PROTECTION
D$LOGT==5	;LOGIN DATE/TIME
D$GENR==6	;NUMBER GENERATIONS TO KEEP
D$QTF==7	;LOGGED-IN QUOTA
D$QTO==10	;LOGGED-OUT QUOTA
D$ACSL==11	;ACCESS LIST
D$USRL==12	;USER LIST
D$PRVL==13	;PRIVILEGE LIST
D$PSWD==14	;PASSWORD

LN$DFH==15	;LENGTH OF DIRECTORY FIXED HEADER

;+.LE;<O$SYSN -- A BLOCK CONTAINING THE SYSTEM HEADER LINE IN <ASCIZ.

;.LE;<O$SSNM  -- A  BLOCK CONTAINING THE USER SUPPLIED
;SAVE SET NAME IN <ASCIZ (MAX OF 30 CHARACTERS).
;^THIS BLOCK IS OMITTED IF NO SAVE SET NAME WAS SPECIFIED.
;-.ELS

O$NAME==1	;FULL PATH NAME BLOCK
O$FILE==2	;FILE ATTRIBUTE BLOCK
O$DIRT==3	;DIRECTORY ATTRIBUTE BLOCK
O$SYSN==4	;SYSTEM HEADER BLOCK
O$SSNM==5	;SAVE SET NAME BLOCK
;+.HL1 LOCATIONS IN T$LBL RECORD

;^THIS RECORD HAS NO CONTENTS IN THE "DATA" REGION. ^THE REMAINING
;LOCATIONS IN THE RECORD HEADER ARE DEFINED AS FOLLOWS:

;.LS

;.LE;<L$DATE -- DATE/TIME OF LABELLING IN <DEC-10 UNIVERSAL FORMAT
;(I.E. <LH=DAYS SINCE 17-^NOV-1858, <RH=FRACTION OF DAY)

;.LE;<L$FMT -- <BACKUP TAPE FORMAT (CONSTANT = 1).

;.LE;<L$BVER -- VERSION OF <BACKUP WRITING LABEL IN STANDARD
;<.JBVER FORMAT.

;.LE;<L$MON -- MONITOR TYPE (%<CNMNT).

;.LE;<L$SVER -- SYSTEM VERSION (<%CNDVN).

;.LE;<L$APR -- <APR PROCESSOR SERIAL NUMBER ON WHICH
;THIS LABEL WAS WRITTEN (INTEGER).

;.LE;<L$DEV -- PHYSICAL DEVICE ON WHICH THE TAPE WAS WRITTEN
;IN <SIXBIT.

;.LE;<L$MTCH -- <BYTE (31) 0 (1) 7-TRACK (1) 0 (3) DENSITY.
;^DENSITY IS 1=200, 2=556, 3=800, 4=1600, 5=6250.

;.LE;<L$RLNM -- <REELID IN <SIXBIT.

;.LE;<L$DSTR -- DATE/TIME BEFORE WHICH TAPE CAN NOT BE SCRATCHED.
;^BEFORE THIS TIME, THE ONLY VALID OPERATION IS TO APPEND.

;-.ELS

L$DATE==14	;DATE/TIME OF LABELING
L$FMT==15	;BACKUP FORMAT
L$BVER==16	;BACKUP VERSION
L$MON==17	;MONITOR TYPE
L$SVER==20	;SYSTEM VERSION
L$APR==21	;APR SERIAL NUMBER WRITING LABEL
L$DEV==22	;DEVICE ID WRITING LABEL
L$MTCH==23	;TAPE WRITE PAREMETERS
L$RLNM==24	;SIXBIT TAPE REEL NAME
L$DSTR==25	;DATE/TIME FOR DESTRUCTION
L$CUSW==37	;RESERVED CUSTOMER WORD
;+.HL1 LOCATIONS IN T$BEG, T$END, T$CON RECORDS

;^THESE SAVE SET RECORDS ALL HAVE THE SAME FORMAT AND ARE DISTINGUISHED
;BY THEIR RECORD TYPES AND THEIR LOCATION ON THE TAPE. ^ALL ITEMS ARE
;FILLED IN AT THE TIME OF WRITTING. ^THE DATA AREA CONTAINS TWO NON-DATA
;BLOCKS, TYPES <O$SYSN AND <O$SSNM.  ^RECORD HEADER LOCATIONS FOLLOWING
;THE FIRST STANDARD TWELVE WORDS ARE DEFINED AS FOLLOWS:

;.LS

;.LE;<S$DATE -- DATE/TIME OF WRITING THIS RECORD IN UNIVERSAL FORMAT.

;.LE;<S$FMT -- <BACKUP TAPE FORMAT (CONSTANT = 1).

;.LE;<S$BVER -- <BACKUP VERSION IN <.JBVER FORMAT.

;.LE;<S$MON -- MONITOR TYPE (%<CNMNT).

;.LE;<S$SVER -- SYSTEM VERSION (<%CNDVN).

;.LE;<S$APR -- APR SERIAL NUMBER ON WHICH WRITTEN.

;.LE;<S$DEV -- PHYSICAL NAME OF DEVICE ON WHICH WRITTEN IN <SIXBIT.

;.LE;<S$MTCH -- <BYTE (31) 0 (1) 7-TRACK (1) 0 (3) DENSITY.
;^DENSITY IS 1=200, 2=556, 3=800, 4=1600, 5=6250.

;.LE;<S$RLNM -- <REELID IN <SIXBIT.

;.LE;<S$LBLT -- <LABEL TYPE IN OCTAL.	[426]

;.LE;<S$BLKF -- BLOCKING FACTOR.

;-.ELS

S$DATE==14	;DATE/TIME OF START/END OF SAVE
S$FMT==15	;RETRIEVAL VERSION
S$BVER==16	;BACKUP VERSION
S$MON==17	;MONITOR TYPE
S$SVER==20	;SYSTEM VERSION
S$APR==21	;APR SERIAL NUMBER
S$DEV==22	;DEVICE ID WRITING SAVE SET
S$MTCH==23	;TAPE WRITE PARAMETERS
S$RLNM==24	;REELID
S$LBLT==25	;[426] LABEL TYPE
S$BLKF==26	;BLOCKING FACTOR (DISK BLOCKS PER TAPE BLOCK)
S$CUSW==37	;CUSTOMER WORD
;+.HL1 LOCATIONS IN T$UFD RECORD

;^THIS RECORD IS NOT WRITTEN IN INTERCHANGE MODE.
;^WHEN WRITTEN, THE DATA PORTION CONTAINS TWO OR THREE NON-DATA BLOCKS:
;TYPES <O$NAME, <O$FILE (OPTIONAL) AND <O$DIRT.
;^REMAINING LOCATIONS IN THE HEADER RECORD CONTAIN:

;.LS

;.LE;<D$PCHK -- CHECKSUM OF THE <O$NAME FULL PATH FILE NAME BLOCK.

;.LE;<D$LVL -- DIRECTORY LEVEL: 0=<UFD, 1=FIRST <SFD, ETC.

;.LE;<D$STR -- FILE STRUCTURE NAME STORED IN THE FOLLOWING FORMAT:
;<BYTE (7) DATA TYPE, LENGTH IN WORDS, <ASCII. (^DATA TYPES
;ARE DEFINED IN THE <T$FIL SECTION.)

;-.ELS

D$PCHK==14	;PATH CHECKSUM
D$LVL==15	;UFD LEVEL (UFD=0, SFD1=1, ETC.)
D$STR==16	;STRUCTURE OF UFD ( MAX OF 12(10) WORDS )
D$CUSW==37	;CUSTOMER WORD
;+.HL1 LOCATIONS IN T$FIL RECORD

;^THE FIRST TAPE RECORD FOR A FILE CONTAINS TWO NON-DATA BLOCKS,
;TYPES <O$NAME AND <O$FILE. ^THERE IS ROOM FOR TWO BLOCKS
;OF FILE DATA IN THE FIRST TAPE RECORD, AND IF THE FILE WILL
;COMPLETELY FIT IN ONE TAPE RECORD, THESE WILL BE USED.
;^IF THE FILE IS LONGER THAN TWO BLOCKS, THE FILE WILL
;BE STARTED IN THE SECOND TAPE RECORD, SO ITS PAGES
;WILL BE LINED UP WITH TAPE RECORDS. ^EACH TAPE RECORD
;IDENTIFIES THE LOGICAL DISK WORD WITH WHICH IT STARTS.
;^REMAINING LOCATIONS IN THE RECORD HEADER ARE:

;.LS

;.LE;<F$PCHK -- CHECKSUM OF THE FULL PATH FILE NAME BLOCK (<O$NAME).
;^THIS IS JUST A CONSISTENCY CHECK FOR CONSECUTIVE RECORDS OF THE FILE.

;.LE;<F$RDW -- RELATIVE DATA WORD OF FILE OF THE FIRST DATA WORD IN THIS TAPE RECORD.

;.LE;<F$PTH -- A TWELVE WORD BLOCK USED TO STORE INFORMATION
;SUITABLE FOR A RESTORATION OF THE FILE. ^THIS AREA IS BIG ENOUGH
;TO HOLD THE ENTIRE PATH TO A <TOPS-10 FILE IN A <UFD AND TWO <SFDS.
;^THE PATH INFORMATION WILL BE STORED IN THE STANDARD ORDER OF
;DEVICE, <UFD, FIRST <SFD, FILE NAME, EXTENSION; WITH MISSING FIELDS OMITTED.
;^THE PATH INFORMATION WILL BE STORED IN THE FORMAT:
;
;<BYTE (7) DATA TYPE, LENGTH IN WORDS, <ASCII
;
;WHERE DATA TYPES ARE DEFINED AS:
;
; DEVICE = 001
; FILE NAME = 002
; EXTENSION = 003
; DIRECTORY = 040
; (LOWER DIRECTORIES = 041,042, ...)

;-.ELS

F$PCHK==14	;PATH CHECKSUM
F$RDW==15	;RELATIVE DATA WORD OF FILE
F$PTH==16	;START OF PATH BLOCK
LN$PTH==14	;LENGTH OF F$PTH BLOCK
F$CUSW==37	;RESERVED CUSTOMER WORD

;DATA TYPES:

.FCDEV==1	;DEVICE
.FCNAM==2	;FILE NAME
.FCEXT==3	;EXTENSION
.FCVER==4	;VERSION
.FCGEN==5	;GENERATION
.FCDIR==40	;DIRECTORY
.FCSF1==41	;FIRST SFD
.FCSF2==42	;SECOND SFD
	SUBTTL	INITIALIZATION

;+
;.CHAPTER PROGRAM INITIALIZATION
;-

;+.HL1 INITIALIZATION
;
;^THE START ADDRESS IS ACTUALLY IN THE MODULE <BACKUP. ^WHEN
;COMMANDED TO START A SAVE OR RESTORE OPERATION, IT CALLS THIS MODULE
;AT ENTRY POINT <BACKRS. <BACKRS FIRST CLEARS THE IMPURE STORAGE AREA,
;THEN COPIES VARIOUS MONITOR INFORMATION FOR LATER USE. ^NEXT IT ENABLES
;FOR INTERRUPTS ON TELETYPE INPUT, IF <PSISER IS AVAILABLE IN THE
;MONITOR SOFTWARE CONFIGURATION. ^IT THEN DISPATCHES TO THE APPROPRIATE
;ROUTINE TO EXECUTE THE OPERATION.
;-

BACKRS::SETZB	F,STOBEG	;CLEAR STORAGE
	MOVE	T1,[STOBEG,,STOBEG+1] ;BLT POINTER
	BLT	T1,STOEND	; ..

IFN FT$IND,<
	MOVE	T1,[IOWD NHOM,HMBBLK] ;FOR READING HOME BLOCKS
	MOVEM	T1,CMDHMB	;STORE
	MOVE	T1,[IOWD 200,BLKRIB] ;FOR READING RIB BLOCKS
	MOVEM	T1,CMDRIB	;STORE
>;END IFN FT$IND
	MOVE	T1,S.TPFG##	; GET FLAG BITS FOR TEST.	[347]
	JUMPN	T1,BACKB	; IF = THEN /TPNUM WASN'T SET.	[347]
	SKIPE	TSTBLK		; HAVE WE BEEN HERE BEFORE?	[344]
	SKIPN	S.MULT##	; MULTI-REEL SET?		[344]
	SKIPA			;[371] NO SO GO ON AS PLANNED.
	JRST	BACKB		; SKIP TAPE NUMBER INITIALIZING [344]
	MOVEI	T1,1		;[371] INITIALIZE TAPE COUNTER
	MOVEM	T1,S.NTPE##	; STORE

;HERE TO COPY SYSTEM NAME INTO MY CORE AREA

BACKB:	SETOM	TSTBLK		; TURN ALL BITS ON.		[344]
	MOVSI	T1,-LN$SYS	; FIVE WORDS
	MOVX	T2,%CNFG0	; GETTAB WORD
LOOP1:	MOVE	T3,T2		; GET GETTAB
	GETTAB	T3,		; ACCESS
	  SETZ	T3,		; LOSE
	MOVEM	T3,USYSNM(T1)	; STORE
	ADD	T2,[1,,0]	; NEXT WORD
	AOBJN	T1,LOOP1	; LOOP
;HERE TO COPY VARIOUS OTHER MONITOR WORDS

	MOVX	T1,%CNMNT	;MONITOR TYPE
	GETTAB	T1,		;ACCESS
	  SETZ	T1,		;LOSE
	MOVEM	T1,UMONTP	;STORE

	MOVX	T1,%CNDVN	;MONITOR VERSION
	GETTAB	T1,		;ACCESS
	  SETZ	T1,		;LOSE
	MOVEM	T1,UMONVR	;STORE

IFN FT$RCV,<
	TXZ	T1,VR.WHO!VR.MIN;LEAVE MAJOR VERSION NBR
	LSH	T1,-^D24	;POSITION
	CAIL	T1,602		;SEE IF 6.02 OR LATER
	TXO	F,FL$RCV	;YES, CAN USE RECOVERY CODE
>;END IFN FT$RCV

	MOVX	T1,%LDMFD	;MFD PPN
	GETTAB	T1,		;ACCESS
	  MOVE	T1,[1,,1]	;DEFAULT
	MOVEM	T1,MFDPPN	;STORE

	MOVX	T1,%CNSER	;GET SERIAL NUMBER
	GETTAB	T1,		;ACCESS
	  SETZ	T1,		;LOSE
	MOVEM	T1,UAPRSN	;STORE

;HERE TO ESTABLISH BIG BUFFERS

	MOVE	T1,[.STDEF,,T2]	;SET DEFAULT
	MOVE	T2,[2,,.STDSB]	; BIGBUF NUMBER OF BLOCKS
	MOVEI	T3,N		;NUMBER OF DISK BLOCKS IN A MAGTAPE RECORD
	MOVEI	T4,200*N	;NUMBER OF WORDS IF THIS SUCCEEDS
	SETUUO	T1,		;SET PROGRAM DEFAULT
	  MOVEI	T4,200		;SIGH, NO BIG BUFFERS
	MOVEM	T4,NWPBLK	;SAVE NUMBER OF WORDS PER DISK BUFFER
	IDIVI	T4,200		;NUMBER OF BLOCKS PER DISK BUFFER
	MOVEM	T4,NDBPMR	;SAVE FOR DSKIN
	SETZ	P1,		;INIT TAPHLD BLOCK ADDRESS
	SKIPG	S.OPER##	;READING THE TAPE?
	JRST	NOHOLD		;NO, NO NEED FOR HOLD BUFFER
	MOVE	T1,S.BFSZ##	;GET MAXIMUM TAPE BUFFER SIZE
	PUSHJ	P,UCORE		;GRAB THE CORE
	  SKIPA			;NO CORE AVAILABLE, SKIP
	JRST	NOHOLD		;PROCEED
	WARN$	(NCH,Not enough core for tape buffer)
	POPJ	P,		;RETURN

NOHOLD:	HRRZM	P1,TAPHLD+1	;STORE ADDRESS OF TAPHLD BLOCK
	MOVEI	T1,N		;INITIALIZE BLOCK SIZE
	MOVEM	T1,BBSN		;TO BACKUP DEFAULT VALUE

;HERE TO ENABLE PSI IF AVAILABLE

	MOVX	T1,%CNST2	;SOFTWARE CONFIGURATION
	GETTAB	T1,		;ACCESS
	  SETZ	T1,		;LOSE
	TXNN	T1,ST%PSI	;PSISER AVAILABLE?
	JRST	SETSRT		;SKIP FOLLOWING IF NOT
	TXO	F,FL$PSI	;FLAG PSI

	MOVEI	T1,TTYSER	;TTY SERVICE ROUTINE ADDRESS
	MOVEM	T1,PSITTY+.PSVNP;STORE NEW PC IN PSI VECTOR
	MOVEI	T1,MTASER	;MTA SERVICE ROUTINE
	MOVEM	T1,PSIMTA+.PSVNP;STORE NEW PC IN PSI VECTOR
	MOVX	T1,PS.VTO	;DISABLE WITH DEBRK. UUO
	MOVEM	T1,PSITTY+.PSVFL;STORE
	MOVEM	T1,PSIMTA+.PSVFL;STORE
	MOVEI	T1,PSIVCT	;BASE ADDRESS
	PIINI.	T1,		;INITIALIZE PSI
	  JRST	SETERR		;ERROR--CLEAR PSI FLAG
	MOVE	T1,[PS.FON!PS.FAC+[EXP <'TTY   '>,<<PSITTY-PSIVCT>,,PS.RID>,0]]
	PISYS.	T1,		;TURN PSI ON FOR TTY
	  JRST	SETERR		;FAILED--CLEAR PSI FLAG
	MOVE	T1,[PS.FON!PS.FAC+[EXP F.MTAP,<<PSIMTA-PSIVCT>,,PS.RSW>,0]]
	PISYS.	T1,		;TURN PSI ON FOR MTA
	  JFCL			;MAYBE RUNNING UNDER A PRE-7.03 MONITOR
	SKIPA			;IN ANY CASE DON'T COUNT THIS AS NO PSI
SETERR:	TXZ	F,FL$PSI	;ERROR--ZILCH PSI FLAG
SETSRT:	MOVE	T1,S.SRTD##	;GET SORT INDEX
	HRRZ	T1,SRTDSP(T1)	;GET ADDRESS TO DISPATCH TO
	MOVEM	T1,SRTDIR	;STORE

	MOVE	T1,S.SRTF##	;GET SORT INDEX
	HRRZ	T1,SRTDSP(T1)	;GET ADDRESS TO DISPATCH TO
	MOVEM	T1,SRTFIL	;STORE


SETDEN:	SKIPL	S.OPER##	;WRITING?
	JRST	SETDE1		;NO
	MOVEI	T2,.TFSTS	;FUNCTION CODE
	MOVEI	T3,F.MTAP	;TAPE CHANNEL
	MOVE	T1,[2,,T2]	;SET UP UUO AC
	TAPOP.	T1,		;READ STATUS
	  JRST	SETDE1		;TAKE A GUESS
	TRNN	T1,TF.BOT	;SITTING AT BOT?
	JRST	SETDE1		;NO--DENSITY CAN EASILY BE READ
	MTBLK.	F.MTAP,		;ELSE WRITE A LONG GAP
	MTWAT.	F.MTAP,		;WAIT FOR THE DRIVE TO SETTLE DOWN
	MTREW.	F.MTAP,		;AND PUT US BACK AT THE LOAD POINT
SETDE1:	MOVEI	T2,.TFDEN	;INDICATE DENSITY
	MOVEI	T3,F.MTAP	;TAPE CHANNEL
	MOVE	T1,[XWD 2,T2]	;ARG FOR UUO
	TAPOP.	T1,		;READ DENSITY
	  SETZ	T1,		;LOSE (NO INFO)
	DPB	T1,[POINTR (UMTCHR, MT.DEN)];STORE

	MOVEI	T2,.TFTRK	;TRACK
	MOVE	T1,[XWD 2,T2]	;RESET ARG
	TAPOP.	T1,		;GET TRACK
	  SETZ	T1,		;LOSE
	DPB	T1,[POINTR (UMTCHR, MT.7TR)];STORE TRACK

	SKIPN	UMTCHR		;SEE IF TAPOP. LOST
	JRST	[MOVEI	T1,F.MTAP ;CHANNEL
		 MTCHR.	T1,	;TRY MTCHR. FOR TAPE CHARACTERISTICS
		   SETZ	T1	;LOSE
		 ANDX	T1,MT.DEN!MT.7TR ;CLEAR JUNK
		 MOVEM	T1,UMTCHR;SAVE
		 JRST	.+1]	;PROCEED

	PUSHJ	P,MTADEV	;READ PHYSICAL DEVICE NAME
	PUSHJ	P,MTARID	;READ REELID
	SKIPGE	S.OPER##	;IF WRITE OPERATION,
	PUSHJ	P,DUMOUT	; ISSUE DUMMY OUTPUT

	MOVE	T1,S.OPER##	;RETRIEVE FUNCTION
	PJRST	@CMDTBL-1(T1)	;DISPATCH AND RETURN

CMDTBL:	XWD	ZERO5,CHKALL
	XWD	ZERO5,RSTALL
	XWD	ZERO5,SAVALL

SRTDSP:	EXP	CPOPJ,APHSRT,LOCSRT
	SUBTTL	DISK TO TAPE MAIN ROUTINES

;+
;.CHAPTER DISK TO TAPE MAIN ROUTINES
;-

;+
;<SAVALL IS THE ROUTINE CALLED TO EXECUTE THE SAVE OPERATION. ^IT FIRST WRITES
;A START-OF-SAVE-SET (<T$BEG) RECORD ON TAPE. ^NEXT, IT SELECTS  FROM THE SYSTEM'S
;STRUCTURE LIST, FOR FURTHER PROCESSING, THE FILE STRUCTURES INDICATED BY THE USER
;SPEC LIST PASSED FROM THE <BACKUP MODULE. ^WHEN THE SAVE IS COMPLETED
;AN END-OF-SAVE-SET RECORD (<T$END) IS WRITTEN ON TAPE.
;-

SAVALL:	PUSHJ	P,SAVE1		;SAVE 1 PERMANENT

;FIRST INITIALIZE THE USAGE ACCOUNTING PACKAGE

IFN FT$USG,<
	SKIPN	S.USG##		;USAGE ACCOUNTING REQUESTED
	JRST	.+3		;NO, DON'T BOTHER INITIALIZING IT
	PUSHJ	P,USGINI##	;INITIALIZE IT
	  JRST	[WARN$ (NCU,Not enough Core for Usage accounting)
		 POPJ P,]	;CAN'T DON'T DO SAVE
>

;HERE TO SETUP THE INITIAL FILESPEC BIT MASK BEFORE THE SAVE

	SETZB	T1,INIBTS	;[522] CLEAR THE WORKING BITS
	MOVEM	T1,SAVBTS	;[522] AND THE SAVED COPY
	SKIPE	S.INIT##+.FXDEV	;[522] ANY DEVICE SPECIFIED?
	  TXO	T1,IB$STR	;[522] YES, REMEMBER
	SKIPN	S.INIT##+.FXNAM	;[522] ANY FILENAME SPECIFIED?
	 SKIPE	S.INIT##+.FXEXT	;[522] NO, ANY EXTENSION?
	  TXO	T1,IB$NAM	;[522] YES, FLAG THAT
	MOVEI	T2,.FXDIR+S.INIT## ;[522] POINT AT THE FIRST DIRECTORY WORD
	MOVEI	T3,6		;[522] GET THE NUMBER OF DIRECTORY WORDS
	MOVX	T4,IB$UFD	;[522] GET THE FIRST BIT

SETINT:	SKIPN	(T2)		;[522] DIRECTORY SPECIFIED AT THIS LEVEL?
	  JRST	SETI01		;[522] NO, EXIT THIS LOOP
	TDO	T1,T4		;[522] YES, LITE THE CORRESPONDING BIT
	ADDI	T2,2		;[522] POINT TO THE NEXT DIRECTORY LEVEL
	LSH	T4,1		;[522] SHIFT THE BIT FOR THE NEXT LEVEL
	SOJG	T3,SETINT	;[522] LOOP FOR ALL SPECIFIED LEVELS

SETI01:	MOVEM	T1,SAVBTS	;[522] STORE THE INITIAL FILESPEC BITS
	MOVEM	T1,INIBTS	;[522] IN BOTH PLACES.

;HERE TO WRITE BEGINNING-OF-SAVE RECORD ON TAPE

	MOVEI	T1,T$BEG	;INDICATE START OF SAVE
	SKIPE	S.RSUM##	;SEE IF /RESUME
	JRST	[MTBSR.	F.MTAP,	;BACKSPACE IN CASE CRASH WROTE
		 MTBSR.	F.MTAP,	;JUNK ON TAPE
		 JRST	.+2]	;NO T$BEG RECORD IF RESUMING
	PUSHJ	P,GENSAV	;FILL IN REST OF CHARS

	MOVE	P1,S.NGST##	;AOBJN WORD FOR STRUCTURE LIST

;HERE TO SELECT A STRUCTURE

GETSTR:	SKIPN	T1,S.STRS##(P1)	;GET STRUCTURE NAME
	JRST	FINSTR		;NULL--LIST FINISHED
	MOVSI	T2,(1B0)	;START WITH BIT 0
	MOVNI	T3,(P1)		;SET ARG FOR SHIFTING RIGHT
	LSH	T2,(T3)		;SHIFT TO CORRECT BIT FOR THIS STR
	SKIPE	INIBTS		;[522] ANY /INITIAL SPECIFIER?
	SKIPN	S.INIT+.FXDEV	;ANY INITIAL DEVICE?
	JRST	GETST1		;NO
	CAME	T1,S.INIT##+.FXDEV;SEE IF EXACT MATCH
	TDNE	T2,S.INIT##+FX$STR;OR IF THIS STR INDICATED BY FLAG
	SKIPA			;YES
	JRST	NXTSTR		;NO. DROP THIS STRUCTURE
	MOVX	T4,IB$STR	;[522] YES, GET THE DIRECTORY SPECIFIER
	ANDCAM	T4,INIBTS	;[522] CLEAR THE DEPENDENCY

GETST1:	MOVEM	T1,CSTR		;STORE
	MOVEM	T1,DCHBLK	; ..
	MOVEM	T2,CSTRFL	; ..

;HERE TO CHECK IF ANY FILE SPEC ASKS FOR STRUCTURE

	MOVE	SP,S.FRST##	;LOAD ADDRESS OF SPECS

CHKSTR:	CAME	T1,FX$LEN+.FXDEV(SP);CHECK FOR EXACT MATCH
	TDNE	T2,FX$LEN+FX$STR(SP); OR IF THIS STR FLAGGED BY SPEC DEVICE
	JRST	GOTSTR		;OK. USE THIS STRUCTURE
	ADDI	SP,FX$LEN*2	;NEXT FILE SPEC
	CAMGE	SP,S.LAST##	;SKIP IF DONE
	JRST	CHKSTR		;CONTINUE

	JRST	NXTSTR		;CHECK NEXT STRUCTURE

;HERE IF AT LEAST ONE FILE SPEC NEEDS THIS STRUCTURE

GOTSTR:	PUSH	P,.JBFF##	;SAVE JOBFF
	PUSH	P,.JBREL##	;SAVE JOBREL
	PUSHJ	P,SAVSTR	;SAVE STRUCTURE
	POP	P,T1		;RESTORE JOBREL
	PUSHJ	P,DRPCOR	;DROP CORE USED FOR THIS STR
	POP	P,.JBFF##	;RESTORE JOBFF

	MOVE	T1,SAVBTS	;[522] GET THE SAVED INITIAL BITS
	SKIPE	INIBTS		;[522] DID WE FIND THE INITIAL FILE?
	  MOVEM	T1,INIBTS	;[522] NO, RESET THE SEARCH BITS
	TXZ	F,FL$ABS	;[522] CLEAR STRUCTURE ABORT FLAG
	TXNE	F,FL$KIL	;SEE IF OPERATOR SAID KILL
	POPJ	P,		; YES--QUIT NOW

NXTSTR:	AOBJN	P1,GETSTR	;LOOP FOR ALL STRUCTURES

;HERE TO WRITE END-OF-SAVE RECORD ON TAPE

FINSTR:	TXO	F,FL$END	;WILL FORCE OUTPUT OF ALL BUFFERS
	MOVEI	T1,T$END	;INDICATE END OF SAVE
	PUSHJ	P,GENSAV	;WRITE REST OF RECORDS
	CLOSE	F.MTAP,		;CLOSE CHANNEL
	SKIPE	INIBTS		;[522] DID WE EVER FIND THE /INITIAL FILE?
	  JRST	CPOPJ1		;[522] YES, RETURN TO BACKUP WITH OPERATION DONE
	SETZM	S.INIT##	;[522] CLEAR THE
	MOVE	T1,[S.INIT##,,S.INIT##+1] ;[522] INITIAL
	BLT	T1,S.INIT##+FX$LEN-1	;[522] FILESPEC
	JRST	CPOPJ1		;RETURN TO BACKUP WITH OPERATION DONE
;+
;<GENSAV IS A SUBROUTINE TO GENERATE THE SAVE SET RECORDS.
;^IT IS CALLED WITH ^T1 = RECORD TYPE (<T$BEG, <T$CON, <T$END).
;-

GENSAV:	MOVEM	T1,G$TYPE(MH)	;STORE
	MOVE	T1,UMONTP	;GET MONITOR TYPE
	MOVEM	T1,S$MON(MH)	;STORE
	MOVE	T1,UMONVR	;GET MONITOR VERSION
	MOVEM	T1,S$SVER(MH)	;STORE
	MOVEI	T1,FORMAT	;CURRENT BACKUP FORMAT
	MOVEM	T1,S$FMT(MH)	;STORE
	MOVE	T1,.JBVER##	;BACKUP VERSION
	MOVEM	T1,S$BVER(MH)	;STORE
	MOVX	T1,%CNDTM	;GET DATE/TIME
	GETTAB	T1,		;ACCESS O/S
	  SETZ	T1,		;SUBSTITUTE ZERO
	MOVEM	T1,S$DATE(MH)	;STORE
	MOVE	T1,UPHYN	;GET PHYSICAL DEVICE NAME
	MOVEM	T1,S$DEV(MH)	;STORE
	MOVE	T1,UAPRSN	;GET SERIAL NUMBER
	MOVEM	T1,S$APR(MH)	;STORE
	MOVE	T1,UMTCHR	;GET CHARACTERISTICS
	MOVEM	T1,S$MTCH(MH)	;STORE
	MOVE	T2,UPHYN	;PHYSICAL TAPE NAME
	MOVE	T1,REELID	;GET REELID
	MOVEM	T1,S$RLNM(MH)	;STORE
	MOVE	T1,TAPLBL##	;[426] GET THE LABEL TYPE
	MOVEM	T1,S$LBLT(MH)	;[426] SAVE FOR LATER
	MOVE	T1,S.BFCT##	;GET BLOCKING FACTOR
	MOVEM	T1,S$BLKF(MH)	;SAVE IN SAVE-SET HEADER
	MOVEI	T2,M(MH)	;LOC FOR SYSTEM NAME BLOCK
	MOVEI	T1,LN$SYS+2	;TOTAL LENGTH
	HRLI	T1,O$SYSN	;TYPE CODE
	MOVEM	T1,(T2)		;STORE
	MOVEI	T1,1(T2)	;LOC FOR SYSTEM NAME
	HRLI	T1,USYSNM	;WHERE I HAVE IT
	BLT	T1,LN$SYS(T2)	;XFR
	SETZM	LN$SYS+1(T2)	;INSURE TRAILING NULL FOR ASCIZ
	ADDI	T2,LN$SYS+2	;UPDATE POINTER
	SKIPN	S.SSNM##	;SEE IF SAVE SET NAME SUPPLIED
	JRST	LSTSAV		;NO, OMIT O$SSNM BLOCK
	HRLI	T1,O$SSNM	;TYPE CODE FOR SAVE SET NAME
	HRRI	T1,LN$SSN+2	;NUMBER OF WORDS
	MOVEM	T1,(T2)		;STORE CONTROL WORD
	MOVEI	T1,1(T2)	;LOC FOR SAVE SET NAME
	HRLI	T1,S.SSNM##	;WHERE IT IS
	BLT	T1,LN$SSN(T2)	;XFR
	SETZM	LN$SSN+1(T2)	;INSURE TRAILING NULL
	ADDI	T2,LN$SSN+2	;UPDATE
LSTSAV:	SETZM	(T2)		;FIRST CLEAR REST OF TAPE BUFFER
	MOVSI	T1,(T2)		;MAKE BLT POINTER
	HRRI	T1,1(T2)	; ...
	PUSHJ	P,BIGBLT	;DO THE BLT
	SUBI	T2,M(MH)	;SUBTRACT START ADDRESS
	MOVEM	T2,G$LND(MH)	;STORE TOTAL LENGTH NON-DATA
	SKIPE	S.NLDV		;[375] NULL TAPE DEVICE?
	JRST	LSTXXX		;[375] YES, LIST AND RETURN
	PUSHJ	P,LSTXXX	;LIST START/END OF SAVE
	JRST	MTAOUT		;SEND BUFFER & RETURN
;+
;<SAVSTR IS CALLED ONCE FOR EACH STRUCTURE INDICATED BY THE USER'S SPEC
;LIST. <IO CHANNELS ARE INITIALIZED AND THE FILE STRUCTURE'S <MFD READ
;INTO CORE, AND SORTED IF NEEDED. ^THEN THE ^^UFD\\S SPECIFIED FOR THE 
;CURRENT STRUCTURE ARE CHOSEN OUT OF THE <MFD FOR FURTHER PROCESSING.
;-

SAVSTR:	PUSHJ	P,SAVE2		;SAVE 2 PERMANENTS

	TXZ	F,FL$STR	;INITIALIZE STRUCTURE SEEN BIT

;HERE TO GET CHARACTERISTICS OF STRUCTURE

IFN FT$USG,<			;IF USAGE ACCOUNTING
	MOVE	T1,DCHBLK	;GET STRUCTURE WE ARE SAVING
	SKIPE	S.USG##		;ARE WE DOING USAGE ACCOUNTING
	PUSHJ	P,USGNST##	;YES, TELL PACKAGE OF NEW STRUCTURE
>
	MOVE	T1,[NDCH,,DCHBLK] ;CALL TO DSKCHR UUO
	DSKCHR	T1,UU.PHY	;GET STATUS OF STRUCTURE
	  TDZA	T1,T1		;ASSUME NO SUPER I/O
	SKIPE	T1,DCHBLK+.DCBSC;[601] BLOCKS/SUPERCLUSTER
	SKIPA			;[601] 
	LDB	T1,[POINTR (DCHBLK+.DCUCH,DC.UCC)] ;GET BLOCKS PER CLUSTER
	MOVEM	T1,BKSCLS	;STORE

;HERE TO INITIALIZE ALL STRUCTURE CHANNELS

	MOVE	T1,[EXP UU.PHS+.IODMP] ;DUMP MODE
	MOVE	T2,CSTR		;CURRENT STRUCTURE
	SETZ	T3,		;NO BUFFERS

	OPEN	MFD,T1		;OPEN CHANNEL FOR MFD
	  JRST	DVFAIL		;LOSE
	OPEN	STR,T1		;OPEN CHANNEL FOR SCREWING AROUND
	  JRST	DVFAIL		;LOSE
	OPEN	HOLD,T1		;[337] OPEN CHANNEL FOR HOLDING ONTO PPB
	  JRST	DVFAIL		;[337] LOSE

	MOVE	P1,[-.FXLND,,UFD] ;LEVELS AND CHANNELS
OPNCHN:	HRLZ	T4,P1		;GET LEVEL
	LSH	T4,5		;SHIFT TO AC FIELD
	IOR	T4,[OPEN T1]	;FORM OPEN UUO
	XCT	T4		;OPEN LEVEL
	  JRST	DVFAIL		;LOSE
	AOBJN	P1,OPNCHN	;LOOP FOR ALL LEVELS

	MOVX	T1,UU.PHS+UU.LBF+.IOBIN ;LARGE BUFFERS + BUFFERED BINARY MODE
	MOVE	T2,CSTR		;CURRENT STRUCTURE
	MOVEI	T3,DSKHDR	;BUFFER HEADER

	OPEN	FILE,T1		;OPEN CHANNEL FOR DISK FILE
	  JRST	DVFAIL		;LOSE

	MOVEI	T1,NDSKBF	;NBR DISK BUFFERS
	SKIPE	S.FFA##		;SEE IF [1,2]
	MOVEI	T1,OPRNDB	;USE LARGER NBR DISK BUFFERS
	INBUF	FILE,(T1)	;GENERATE DISK BUFFERS

IFN FT$IND,<
	TXNN	F,FL$IND	;INDEPENDENT IO?
	JRST	CONT1		;NO--CONTINUE

	MOVE	T1,[STR_5,,[EXP HMBNBR]] ;ARG FOR SUPER USETI
	SUSET.	T1,		;SET TARGET BLOCK
	  HALT	.		;***TEMP***
	INPUT	STR,CMDHMB	;READ INTO CORE

	MOVSI	T1,'HOM'	;INSURE HOME BLOCK
	CAME	T1,HMBBLK+.HMNAM; ..
	JRST	NOHOME		;TELL HIM IT IS INACCESSABLE

	MOVE	T1,[STR_5,,HMBBLK+.HMMFD] ;ARG FOR SUPER USETI
	SUSET.	T1,		;SET TARGET BLOCK
	  HALT	.		;***TEMP***
	INPUT	STR,CMDRIB	;READ IN RIB
>;END IFN FT$IND
;HERE TO READ MFD INTO CORE

CONT1:	SETZM	EXLUFD		;ZERO EXTENDED BLOCK
	MOVE	T1,[EXLUFD,,EXLUFD+1] ; ..
	BLT	T1,EXLUFD+NRIB-1; ..

	MOVEI	T1,NRIB-1	;SET BLOCK FOR LOOKUP
	MOVEM	T1,EXLUFD+.RBCNT; ..
	MOVE	T1,MFDPPN	; ..
	MOVEM	T1,EXLUFD+.RBPPN; ..
	MOVEM	T1,EXLUFD+.RBNAM; ..
	MOVSI	T1,'UFD'	; ..
	MOVEM	T1,EXLUFD+.RBEXT; ..

	LOOKUP	MFD,EXLUFD	;EXTENDED LOOKUP
	  JRST	ELUFD		;LOSE

	SKIPG	T1,EXLUFD+.RBSIZ;HOW BIG IS IT?
	JRST	RLSSTR		;NULL--DROP IT
	PUSHJ	P,UCORE		;GET CORE TO READ MFD
	  SKIPA			;CORE NOT AVAILABLE
	JRST	CONT2		;CONTINUE
	WARN$N (CCM,Cannot copy MFD for)
 	MOVE	T1,CSTR		;TYPE STR NAME
	PUSHJ	P,SIXOUT	; ...
	OUTSTR	CRLF		;<CR><LF>
	JRST	RLSSTR		;DROP THIS STR

CONT2:	MOVNS	T1		;NEGATE
	HRL	P1,T1		;PUT NEGATIVE SIZE IN LH P1
	SUBI	P1,1		;ADJUST IOWD FOR INPUT CMD
	SETZ	P2,		;ZERO NEXT CMD WORD
	INPUT	MFD,P1		;TRY TO READ MFD INTO CORE
	PUSHJ	P,@SRTDIR	;SORT IT

;HERE TO SELECT A UFD

GETUFD:	SKIPE	T1,1(P1)	;GET FIRST UFD
	CAMN	T1,MFDPPN	;DO NOT REPEAT MFD
	JRST	NXTUFD		;LOSE
	HLRZ	T2,2(P1)	;GET EXTENSION
	CAIE	T2,'UFD'	;IT HAD BETTER BE UFD
	JRST	NXTUFD		;NOT--FORGET THIS ONE
	SKIPE	INIBTS		;[522] ANY /INITIAL SPECIFIER?
	SKIPN	S.INIT##+.FXDIR	;ANY INITIAL PPN?
	JRST	GETUF1		;NO
	CAME	T1,S.INIT##+.FXDIR;MATCH?
	JRST	NXTUFD		;NO--DROP PPN
	MOVX	T4,IB$UFD	;[522] YES, GET THE UFD SPECIFIER BIT
	ANDCAM	T4,INIBTS	;[522] CLEAR THE DEPENDENCY
GETUF1:	MOVEM	T1,PTHBLK+.PTPPN;STORE IN PATH BLOCK
	SETZM	PTHBLK+.PTPPN+1	;ZILCH NEXT WORD
;HERE TO CHECK IF ANY FILE SPEC ASKS FOR THIS UFD ON THIS STRUCTURE

	MOVE	SP,S.FRST##	;GET ADDRESS OF SPECS

CHKUFD:	MOVE	T1,CSTRFL	;GET STRUCTURE FLAG
	TDNN	T1,FX$LEN+FX$STR(SP);CHECK INPUT STR SPEC
	JRST	CHKUF1		;STR NO GOOD

	MOVE	T3,PTHBLK+.PTPPN;GET CURRENT PPN
	XOR	T3,FX$LEN+.FXDIR(SP) ;GET DIFF
	AND	T3,FX$LEN+.FXDIM(SP) ;ZERO DON'T CARES
	JUMPE	T3,GOTUFD	;BRANCH IF GOOD PPN

CHKUF1:	ADDI	SP,FX$LEN*2	;NEXT SPEC
	CAMGE	SP,S.LAST##	;SKIP IF DONE
	JRST	CHKUFD		;CHECK NEXT SPEC
	JRST	NXTUFD		;NO ONE WANTS IT

;HERE IF AT LEAST ONE FILE SPEC NEEDS THIS UFD ON THIS STR

GOTUFD:	MOVEI	LVL,0		;START AT LEVEL ZERO
	TXZ	F,FL$UFD	;UFD USE FLAG
	PUSH	P,.JBFF##	;SAVE JOBFF
	PUSH	P,.JBREL##	;SAVE JOBREL
	TXZ	F,FL$HUF	;[337] TURN OFF UFD-PPB-HELD FLAG
	PUSHJ	P,SAVUFD	;SAVE FILES
IFN FT$USG,<
	SKIPN	S.USG##		;USAGE ACCOUNTING WANTED?
	JRST	GOTUF1		;[413] NO
	PUSHJ	P,USGEND##	;YES, TELL WE ARE AT END OF A UFD
	RENAME	UFD,EXLUF1	;[530][413] RENAME FOR ACCOUNTING PURPOSES
	JFCL			;[413] RENAME FAILED
>
GOTUF1:	TXZE	F,FL$HUF	;[413] TURN OFF UFD-PPB-HELD. WAS IT HELD?
	CLOSE	HOLD,CL.ACS	;[337] YES - CLOSE THE FILE
	POP	P,T1		;RESTORE JOBREL
	PUSHJ	P,DRPCOR	;DROP CORE USED FOR THIS UFD
	POP	P,.JBFF##	;RESTORE JOBFF
	SKIPE	INIBTS		;[522] DID WE FIND THE /INITIAL FILE?
	  TXO	F,FL$ABS	;[522] ONLY GOT PART OF IT - BLOW THIS STR OFF

	TXNE	F,FL$KIL!FL$ABS	;[522] SEE IF OPERATOR SAID KILL OR ABORT SET
	JRST	RLSSTR		;YES

NXTUFD:	AOBJN	P1,.+1		;SKIP ONE WORD
	AOBJN	P1,GETUFD	;CHECK NEXT UFD

;HERE TO RELEASE ALL STR CHANNELS

RLSSTR:	RELEAS	FILE,		;DONE
	RELEAS	STR,		; ..
	RELEAS	MFD,		; ..
	RELEAS	HOLD,		;[376][337] ..
	MOVE	T1,[-.FXLND,,UFD] ;LEVELS AND CHANNELS
RLSUFD:	HRLZ	T2,T1		;GET CHANNEL INTO LH
	LSH	T2,5		;SHIFT TO AC POSITION
	TLO	T2,(<RELEAS>)	;FORM RELEASE UUO
	XCT	T2		;EXECUTE
	AOBJN	T1,RLSUFD	;LOOP FOR ALL
	POPJ	P,		;RETURN
;+
;<SAVUFD IS CALLED ONCE FOR EACH <UFD AND <SFD WHICH MATCHES A DIRECTORY
;SPEC IN THE USER'S LIST. ^THE <UFD OR <SFD <RIB IS READ INTO CORE AND SAVED
;FOR LATER USE IN  WRITING <T$UFD RECORDS ON TAPE. ^NEXT, THE <UFD
;OR <SFD ITSELF IS READ INTO CORE AND SORTED, IF NEEDED. ^THE DIRECTORY
;IS THEN SEARCHED FOR FILES WHICH MATCH AN ENTRY IN THE USER'S SPEC LIST.
;^FILES WHICH MATCH A SPEC ARE THEN CHECKED TO SEE IF THEY ALSO
;MATCH ALL USER SET SWITCH RESTRICTIONS. ^FOR A FILE WHICH MATCHES,
;A <T$UFD RECORD IS WRITTEN ON TAPE FOR EACH DIRECTORY IN THE FILE'S
;PATH (UNLESS THE <INTERCHANGE SWITCH WAS GIVEN) AND THEN THE FILE IS SAVED.
;-

SAVUFD:	PUSHJ	P,SAVE2		;SAVE C(P1) & C(P2)

;HERE TO LOOKUP THE UFD

	SETZM	EXLUFD		;ZERO BLOCK
	MOVE	T1,[EXLUFD,,EXLUFD+1] ; ..
	BLT	T1,EXLUFD+NRIB-1; ..

	MOVEI	T1,NRIB-1	;SET BLOCK
	MOVEM	T1,EXLUFD+.RBCNT; ..
	JUMPG	LVL,SETSFD	;SET SFD BLOCK?
	MOVE	T1,MFDPPN	; ..
	MOVE	T2,PTHBLK+.PTPPN;CURRENT PPN
	MOVSI	T3,'UFD'	; ..
	JRST	SETFIN		;FINISH UP
SETSFD:	MOVE	T1,[PTHBLK,,UPTBLK] ;BLT POINTER
	BLT	T1,UPTBLK+.PTPPN-1(LVL) ;TRANSFER
	SETZM	UPTBLK+.PTPPN(LVL) ;ZILCH LAST ONE
	MOVEI	T1,UPTBLK	;PATH BLOCK
	MOVE	T2,PTHBLK+.PTPPN(LVL) ;GET SFD NAME
	MOVSI	T3,'SFD'	;EXTENSION
SETFIN:	MOVEM	T1,EXLUFD+.RBPPN;STORE
	MOVEM	T2,EXLUFD+.RBNAM; ..
	MOVEM	T3,EXLUFD+.RBEXT; ..

	MOVSI	T1,UFD(LVL)	;GET CHANNEL IN LH
	LSH	T1,5		;PUT IN AC FIELD
	IOR	T1,[LOOKUP EXLUFD] ;FORM UUO
	XCT	T1		;EXEC IT
IFE FT$USG,<
	  JRST	ELUFD		;LOSE
>
IFN FT$USG,<
	  JRST	[SKIPN S.USG##	;DOING USAGE ACCOUNTING
		 JRST ELUFD	;NO, JUST REPORT ERROR
		 MOVEI T1,EXLUFD ;POINT TO LOOKUP BLOCK THAT FAILED
		 PUSHJ P,USGNDI## ;FIRST SAY IT IS A NEW DIRECTORY
		 SKIPN	LVL	;[530] IS THIS A UFD LOOKUP?
		 PUSHJ	P,UFDCOP;[530] YES. SAVE EXLUFD FOR RENAME IN GOTUFD
		 PUSHJ P,USGDIP## ;THEN SAY DIRECTORY PROTECTION FAILURE
		 JRST ELUFD]	;THEN REPORT IT TO THE OPERATOR
	MOVEI	T1,EXLUFD	;POINT TO THE EXTENDED LOOKUP BLOCK
	SKIPN	S.USG##		;[530] WANT USAGE ENTRIES
	JRST	SETFI1		;[530] NO.
	PUSHJ	P,USGNDI##	;YES, CALL ACCOUNTING PACKAGE
	SKIPN	LVL		;[530] IS THIS A UFD LOOKUP?
	PUSHJ	P,UFDCOP	;[530] YES. SAVE EXLUFD FOR RENAME IN GOTUFD
SETFI1:
>
;HERE TO SAVE A COPY OF THE UFD RIB FOR LATER USE.
;THE RIB INFO IS WRITTEN ON TAPE IN A T$UFD RECORD AND IS USED WHEN
;IN ORDER TO ENTER A SUBSEQUENT FILE ON TAPE THIS UFD IS NEEDED

	MOVEI	T1,NRIB		;NEED CORE
	PUSHJ	P,UCORE		;GET IT
	  SKIPA			;CORE NOT AVAILBLE
	JRST	CNTUFD		;CONTINUE
	WARN$N (CCR,Cannot copy UFD/SFD RIB for)
UFDERR:	MOVEI	P1,EXLUFD	;INDICATE WHICH
	PUSHJ	P,GUUO		;TYPE SPEC
IFN FT$USG,<
	MOVEI	T1,EXLUFD	;POINT TO LOOKUP BLOCK WE CAN'T COPY
	SKIPE	S.USG##		;DOING USAGE ACCOUNTING
	PUSHJ	P,USGDIP##	;YES, TELL DOWNSTREAM BILLING OF PROBLEM
>
	JRST	CLSUF1		;LOSE

CNTUFD:	MOVEM	P1,ADRLST(LVL)	;STORE FOR LATER REF

	MOVE	T1,P1		;WHERE TO SAVE IT
	HRLI	T1,EXLUFD	;WHERE IT NOW IS
	BLT	T1,NRIB(P1)	;XFR

;HERE TO READ THE DIRECTORY INTO CORE

	SKIPG	T1,EXLUFD+.RBSIZ;SEE IF SIZABLE
	JRST	CLSUF1		;DROP IT IF NULL
	PUSHJ	P,UCORE		;EXPAND CORE
	  SKIPA			;CORE NOT AVAILABLE
	JRST	CNTLVL		;CONTINUE
	WARN$N (CCU,Cannot copy UFD/SFD for)
	JRST	UFDERR		;TAKE COMMON ERROR EXIT

CNTLVL:	MOVNS	T1		;NEGATE LENGTH
	HRL	P1,T1		;MAKE DUMP MODE IO COMMAND WORD
	SUBI	P1,1		;COMPUTE IOWD
	SETZ	P2,		;ZERO NEXT CMD WORD
	MOVSI	T1,UFD(LVL)	;GET CHANNEL IN LH
	LSH	T1,5		;PUT IN AC FIELD
	IOR	T1,[INPUT P1]	;FORM UUO
	XCT	T1		;EXEC IT
	PUSHJ	P,@SRTFIL	;SORT IT

;HERE TO SELECT A FILE

GETFIL:	SKIPN	T1,1(P1)	;GET A FILE NAME
	JRST	NXTFIL		;NOT INTERESTED IN NULLS
	MOVEM	T1,CNAM		;STORE
	SETOM	CNAMSW		;[416] STORE 
	SETZM	THSRDB		;[421] SET BLOCK SIZE TO ZERO
	HLRZ	T1,2(P1)	;GET EXTENSION
	CAIE	T1,'SFD'	;SFD?
	JRST	NOTSFD		;NO--DO NORMAL HANDLING
;***START OF SFD NESTING HANDLER***

	CAIGE	LVL,.FXLND-1	;LEVEL EXCEEDED?
	AOJA	LVL,SAFE1	;NO--CONTINUE

	TXON	F,FL$SLE	;ISSUE ONCE
	WARN$	(SLE,SFD level exceeded)
	JRST	NXTFIL		;GET NEXT FILE

SAFE1:	MOVE	T2,LVL		;COPY LEVEL
	IMULI	T2,2		;MAKE INDEX FOR S.INIT SPEC
	SKIPN	INIBTS		;[524][522] ANY /INITIAL SPECIFIER?
	JRST	SAFE2		;[524] NO
	SKIPN	T3,S.INIT+.FXDIR(T2) ;ANY INITIAL SFD?
	JRST	NXTFIL		;[524] NO
	CAME	T3,CNAM		;SEE IF MATCH
	SOJA	LVL,NXTFIL	;NO, DROP IT
	MOVX	T4,IB$UFD	;[522] YES, GET THE DIRECTORY SEEN BIT
	LSH	T4,(LVL)	;[522] SHIFT TO THE RIGHT SFD LEVEL
	ANDCAM	T4,INIBTS	;[522] CLEAR THE BIT FOR THIS LEVEL

SAFE2:	HRLZM	T1,CEXT		;SAVE 'SFD' EXTENSION
	MOVE	T2,CNAM		;GET SFD NAME
	MOVEM	T2,PTHBLK+.PTPPN(LVL) ;STORE IN PATH BLOCK
	SETZM	PTHBLK+.PTPPN+1(LVL) ;ZILCH NEXT ENTRY

	MOVE	SP,S.FRST##	;ADDRESS OF SPECS

CHKSFD:	PUSHJ	P,VER1		;VERIFY STR,UFD,SFD'S
	  JRST	CHKSF1		;NO GOOD--SKIP THIS SPEC

	PUSH	P,.JBFF##	;SAVE C(JOBFF)
	PUSH	P,.JBREL##	;SAVE JOBREL
	PUSHJ	P,SAVUFD	;MATCH--CALL UFD(SFD) HANDLER
	POP	P,T1		;RESTORE JOBREL
	PUSHJ	P,DRPCOR	;DROP CORE IF SAVINGS OF 2K
	POP	P,.JBFF##	;RESTORE C(JOBFF)
	SKIPE	INIBTS		;[522] DID WE FIND THE /INITIAL FILE?
	  TXO	F,FL$ABS	;[522] NO, YES - ABORT THIS STRUCTURE

	SETZM	PTHBLK+.PTPPN(LVL) ;ZERO
	TXNE	F,FL$KIL!FL$ABS	;[522] SEE IF OPERATOR SAID KILL OR ABORT SET
	SOJA	LVL,CLSUF1	;YES--UNNEST
	SOJA	LVL,NXTFIL	;CONTINUE

CHKSF1:	ADDI	SP,FX$LEN*2	;UP ADDRESS
	CAMGE	SP,S.LAST##	;SKIP IF DONE
	JRST	CHKSFD		;CHECK NEXT

	SETZM	PTHBLK+.PTPPN(LVL) ;ZERO
	SOJA	LVL,NXTFIL	;CONTINUE

;***END OF SFD NESTING HANDLER***
;HERE IF THE CURRENT FILE IS NOT AN SFD

NOTSFD:	SKIPN	T4,INIBTS	;[522] LOOKING FOR /INITIAL FILE?
	  JRST	SETEXT		;[522] NO, GO AHEAD WITH THIS FILE
	CAXE	T4,IB$NAM	;[522] YES, JUST LOOKING FOR FILENAME?
	  JRST	NXTFIL		;[522] NO, DROP THIS FILE
	HLRZ	T3,S.INIT+.FXEXT;GET INITIAL EXTENSION
	MOVE	T2,S.INIT+.FXNAM;[522] GET THE /INITIAL FILENAME
	CAMN	T2,CNAM		;MATCH?
	CAME	T3,T1		;EXTENSION MUST MATCH TOO
	JRST	NXTFIL		;NO, DROP IT
	SETZM	INIBTS		;[522] YES, NO MORE /INITIAL SPEC

SETEXT:	HRLZM	T1,CEXT		;STORE
	HRRZ	T1,2(P1)	;GET COMPRESSED-FILE-POINTER
	IMUL	T1,BKSCLS	;COMPUTE LOGICAL BLOCK ON STR
	MOVEM	T1,CBLOCK	;STORE
	TLNE	T1,(77774B14)	;MAKE SURE IT FITS IN SUSET.
	SETZM	CBLOCK		;IF NOT, CLEAR

;HERE TO CHECK IF ANY FILE SPEC ASKS FOR THIS FILE

	MOVE	SP,S.FRST##	;ADDRESS OF SPECS
	SETZ	P2,		;FLAG INITIAL READ OF FILE RIB

CHKFIL:	PUSHJ	P,VER1		;CHECK FILE ID
	  JRST	CHKFI1		;NO GOOD
	PUSHJ	P,VER2		; ..
	  JRST	CHKFI1		; ..

	JUMPL	P2,CHKSWT	;IF READ & DECODED ALREADY, GO CHECK SWITCHES

	SKIPN	S.USET##	;SKIP IF SHOULD USE SUPER USETIS
	JRST	STNCHK		;NO--USE LOOKUP UUO

	MOVSI	T1,STR_5	;GET CHANNEL
	ADD	T1,CBLOCK	;GET BLOCK NUMBER
	SKIPE	CBLOCK		;IF SET,
	SUSET.	T1,		;SET TARGET BLOCK
	  JRST	STNCHK		;FAILURE

IFE FT$USG,<
	MOVE	T1,[IOWD NRIB,EXLFIL] ;MAKE COMMAND WORD
>
IFN FT$USG,<
	MOVE	T1,[IOWD 200,EXLFIL] ;MAKE COMMAND WORD
>
	SETZ	T2,		;ZILCH SECOND COMMAND WORD
	INPUT	STR,T1		;READ INTO CORE

	MOVE	T1,EXLFIL+.RBPPN;VERIFY RIB BLOCK
	CAME	T1,PTHBLK+.PTPPN; ..
	JRST	STNCHK		; ..
	MOVE	T1,EXLFIL+.RBNAM; ..
	CAME	T1,CNAM		; ..
	JRST	STNCHK		; ..
	HLLZ	T1,EXLFIL+.RBEXT; ..
IFE FT$USG,<
	CAMN	T1,CEXT		; ..
	JRST	DECODE		;GO DECODE RIB
>
IFN FT$USG,<
	CAME	T1,CEXT		; ..
	JRST	STNCHK		; ..
	MOVE	T2,EXLFIL+.RBACT ;GET AOBJN POINTER TO ACCOUNT STRING
	SETZM	EXLFIL+.RBACT	;CLEAR OUT WORDS FOR IT IN RIB
	MOVE	T1,[EXLFIL+.RBACT,,EXLFIL+.RBACT+1]
	BLT	T1,EXLFIL+.RBACT+7 ;CLEAR IT
	JUMPGE	T2,DECODE	;IF NO POINTER, PROCEED, ACCT STR = 0
	HLRZ	T3,T2		;[417] GET NEG. WORD LENGTH
	HRRZ	T1,T2		;[417] GET OFFSET FROM RIB START
	CAIGE	T1,200		;[417] GREATER THAN MAX. RIB SIZE?
	CAIGE	T3,-10		;[417] GREATER THAN MAX. ACCT. STRING LENGTH?
	JRST	DECODE		;[417] YES, IGNORE POINTER
	SETZ	T3,		;CLEAR INDEX
CHKFI2:	MOVE	T1,EXLFIL(T2)	;PICK UP WORD OF ACCOUNT STRING
	MOVEM	T1,EXLFIL+.RBACT(T3) ;STORE WHERE LOOKUP WOULD HAVE PUT IT
	AOS	T3		;BUMP INDEX
	AOBJN	T2,CHKFI2	;MOVE ALL THE WORDS
	JRST	DECODE		;AND PROCEED
>
STNCHK:	SETZM	EXLFIL		;ZERO LOOKUP BLOCK
	MOVE	T1,[EXLFIL,,EXLFIL+1] ; ..
	BLT	T1,EXLFIL+NRIB-1; ..

	MOVEI	T1,NRIB-1	;LIMIT OF ARGS
	MOVEM	T1,EXLFIL+.RBCNT; ..
	CAIGE	LVL,1		;SEE IF FILE ACTUALLY IN SFD
	SKIPA	T1,PTHBLK+.PTPPN;IT IS IN UFD. DO NOT SUPPLY PATH ADDR
	MOVEI	T1,PTHBLK	;PPN AND SFD PATH
	MOVEM	T1,EXLFIL+.RBPPN; ..
	MOVE	T1,CNAM		;NAME
	MOVEM	T1,EXLFIL+.RBNAM; ..
	MOVE	T1,CEXT		;EXT
	MOVEM	T1,EXLFIL+.RBEXT; ..

	LOOKUP	STR,EXLFIL	; ..
IFE FT$USG,<
	  JRST	GOTFIL		;ASSUME FILE IS GOOD
>
IFN FT$USG,<
	  JRST	[MOVEI T1,EXLFIL ;POINT TO FAILING LOOKUP BLOCK
		 SKIPE S.USG##	;DOING USAGE ACCOUNTING
		 PUSHJ P,USGFIP## ;YES, TELL DOWNSTREAM BILLING OF LOOKUP FAILURES
		 JRST GOTFIL]	;AND ASSUME FILE IS GOOD
>
	CLOSE	STR,CL.ACS	; ..

;HERE TO CHECK IF FILE SATISFIES USER SWITCH RESTRICTIONS

DECODE:
IFN FT$USG,<
	MOVEI	T1,EXLFIL	;POINT TO RIB OF FILE
	SKIPE	S.USG##		;WANT DISK SPACE ACCOUNTING
	PUSHJ	P,USGFIL##	;YES, TELL ACCOUNTING PACKAGE OF NEW FILE
>
	MOVEI	T1,RP.NFS	;CHECK NO SAVE BIT
	MOVEI	T2,1		;[241] PRIME THE PUMP FOR NFS CHECK
	TDNE	T1,EXLFIL+.RBSTS;ON?
	CAMN	T2,S.NFS##	;[241] NFS SET?
		SKIPA		;[241] YES-- CONTINUE WITH FILE
	JRST	NXTFIL		;YES--SKIP THIS ONE

	MOVE	T1,EXLFIL+.RBSIZ;GET FILE SIZE
	MOVEM	T1,CWSIZE	;STORE

	SETZ	T1,		;ZERO ACCESS TIME
	LDB	T2,[POINTR (EXLFIL+.RBEXT,RB.ACD)] ;GET ACCESS DATE
	PUSHJ	P,CONVDT	;CONVERT TO SMITHSONIAN DATE/TIME
	MOVEM	T1,CADATI	;STORE

	LDB	T1,[POINTR (EXLFIL+.RBPRV,RB.CRT)] ;GET CREATION TIME
	IMULI	T1,^D60000	;CONVERT TO MILLISECONDS
	LDB	T2,[POINTR (EXLFIL+.RBEXT,RB.CRX)] ;GET EXTENSION OF CREATION
	LSH	T2,^D12		;SHIFT OVER
	LDB	T3,[POINTR (EXLFIL+.RBPRV,RB.CRD)] ;GET BASE CREATION DATE
	IOR	T2,T3		;UNITE
	PUSHJ	P,CONVDT	;CONVERT TO SMITHSONIAN DATE/TIME
	MOVEM	T1,CCDATI	;STORE
	MOVE	T1,EXLFIL+.RBTIM ;GET INTERNAL DATE/TIME
	MOVEM	T1,CMDATI	;SET FOR CHECKER

	SETO	P2,		;FLAG DECODING DONE

CHKSWT:	PUSHJ	P,CHKLIM	;CHECK LIMITS
	  JRST	CHKFI1		;NO GOOD
	  JRST	[TXON  F,FL$D75	;ONLY GOOD BECAUSE DATE75
		 MOVEM SP,D75ADR; SAVE FOR LATER
		 JRST  CHKFI1]	;CONTINUE LOOP, NOT COUNTING MATCH

	TXON	F,FL$MAT	;FLAG FIND
	MOVEM	SP,SAVADR	;SAVE ADDRESS
	AOS	FX$CNT(SP)	;COUNT MATCH
CHKFI1:	ADDI	SP,FX$LEN*2	;ADVANCE TO NEXT SPEC
	CAMGE	SP,S.LAST##	;SKIP IF DONE
	JRST	CHKFIL		;CHECK NEXT SPEC

	TXZN	F,FL$MAT	;ANY FILE MATCH?
	JRST	[TXZN F,FL$D75	;NOT MATCH, SEE IF DATE75 WORKS
		 JRST NXTFIL	;NO--JUST IGNORE FILE
		 MOVE SP,D75ADR	;YES--USE DATE75 MATCH
		 JRST GOTFIL]	;AND PROCEED

	MOVE	SP,SAVADR	;YES. RESTORE C(SP)

;HERE IF AT LEAST ONE FILE SPEC NEEDS THIS FILE

GOTFIL:	SETOM	NRPS		;[240] INITIALIZE ONE REPETITION SWITCH
GOTFL2:	SKIPE	S.TYMS##	;[240] SKIP IF TYPE OUT WANTED
	TXOE	F,FL$UFD	;FIRST FILE--ANY PREVIOUS?
	JRST	GOTFL1		;YES--GO SAVE IT

	HLRZ	T1,PTHBLK+.PTPPN;GET PROJECT
	PUSHJ	P,OCTOUT	;TYPE
	OUTCHR	COMMA		; ..

	HRRZ	T1,PTHBLK+.PTPPN;GET PROGRAMMER
	PUSHJ	P,OCTOUT	;TYPE
	TXOE	F,FL$STR	;SEE IF FIRST TIME FOR STR
	JRST	RECUFD		;NOPE--FORGET THIS

	OUTCHR	TAB		;TAB OVER
	MOVE	T1,CSTR		;GET STR NAME
	PUSHJ	P,SIXOUT	;TYPE IT
RECUFD:	OUTSTR	CRLF		;<CR><LF>

GOTFL1:	PUSHJ	P,XALIAS	;DO ALIASING
	SKIPN	S.INTR##	;SEE IF /INTERCHANGE 
	PUSHJ	P,WRTUFD	;NO--WRITE T$UFD RECORDS ON TAPE

	MOVEI	T1,2		;SEE IF FILE NAMES WANTED
	CAMN	T1,S.TYMS##	;SKIP IF NOT
	PUSHJ	P,TYPFIL	;TYPE FILE NAME

	MOVE	T1,S.NTPE##	;[355] SAVE CURRENT TAPE NUMBER
	MOVEM	T1,CURTAP	;[355]
	PUSHJ	P,SAVFIL	;SAVE THE FILE
	MOVE	T1,CURTAP	;[355] GET TAPE NUMBER BACK

	TXNE	F,FL$KIL	;SEE IF OPERATOR SAID KILL
	JRST	CLSUF1		;YES, STOP NOW

	CAMN	T1,S.NTPE##	;SEE IF TAPE NUMBER CHANGED
	JRST	NXTFIL		;NO, PROCEED
	TXZ	F,FL$UFD	;ZILCH SO PPN WILL BE TYPED

	SKIPN	S.REPT##	;[240] /REPEAT?
	JRST	NXTFIL		;[240] YES--SAVE THIS FILE AGAIN
	SETZM	THSRDB		;[432] Init block for WHAT and routine CONREC
	AOSG	NRPS		;[240] DEFENSE AGAINST ENDLESS REPETITION
	JRST	GOTFL2		;[240] REPEAT ONLY ONCE
NXTFIL:	AOBJN	P1,.+1		;ONE WORD
	AOBJN	P1,GETFIL	;TWO
;HERE TO TERMINATE I/O TO THIS UFD

CLSUF1:	MOVSI	T1,UFD(LVL)	;GET CHANNEL IN LH
	LSH	T1,5		;PUT IN AC FIELD
	IOR	T1,[CLOSE CL.ACS] ;FORM UUO
	XCT	T1		;EXEC IT

	SETZM	ADRLST(LVL)	;ZILCH IN CASE NO FILE FOUND
	SKIPN	S.LIST##	;SEE IF /LIST,
	POPJ	P,		;NO--RETURN

;AVOID SPAWNING A ZILLION FILES - I.E. ONE/PPN			[176]

	MOVEI	T1,F.LIST		;MUST USE CHANNEL 1	[217]
	DEVTYP	T1,		; GET DEVICE TYPE BITS		[176]
	 JRST	CLSUF2		; ERROR RET - IGNORE		[176]
	JUMPE	T1,CLSUF2	; NOT A DEVICE OR NOT INITED	[176]
	LDB	T1,[POINT 6,T1,35]; GET DEVICE TYPE		[176]
	CAIN	T1,.TYLPT	; IS IT A LPT?			[176]
	POPJ	P,		; YES, AVOID PRESERVE CODE	[176]

;HERE TO PRESERVE LISTING FILE IN CASE OF SYSTEM CRASH

CLSUF2:	HRLI	T1,F.LIST	;[520] CHANNEL NUMBER OF LISTING FILE
	HRRI	T1,.FOURB	;[520] CHECKPOINT FUNCTION
	MOVEM	T1,LSTFOP+.FOFNC;[520] FIRST WORD OF FILOP BLOCK
	MOVEI	T1,S.LENT##	;[520] LOOKUP/ENTER BLOCK ADDRESS
	MOVEM	T1,LSTFOP+.FOLEB;[520]
	MOVE	T1,[.FOMAX,,LSTFOP] ;[520]
	FILOP.	T1,
	  JRST	LSTERR		;[520] REPORT THE ERROR
	POPJ	P,		;[520] RETURN

LSTERR:	WARN$N (LF,Listing file error)
	SETZM	S.LIST##	;ZILCH TO PREVENT FURTHER TROUBLE
	MOVEI	P1,S.LENT##	;SPEC ADDRESS
	JRST	EGUUO		;TYPE OUT ERROR MESSAGE & RETURN


;UFDCOP - Routine to preserve the LOOKUP block of the UFD if doing /USAGE
;	accounting so that the RENAME in GOTUFD does the correct thing instead
;	of renaming the last SFD looked up.

UFDCOP:	MOVE	T1,[EXLUFD,,EXLUF1];[530] SET UP THE BLT
	BLT	T1,EXLUF1+NRIB-1;[530]
	POPJ	P,		;[530]

;+
;<WRTUFD IS A ROUTINE TO WRITE A <T$UFD RECORD ON TAPE FOR EACH DIRECTORY IN 
;THE FILE PATH.
;-

WRTUFD:	SKIPE	S.NLDV##	;[375] IF NUL TAPE DEVICE THEN
	POPJ	P,		;[375]  DON'T NEED THIS
	PUSHJ	P,SAVE2		;SAVE C(P1) & C(P2)
	MOVSI	P1,-.FXLND	;HOW MANY LEVELS PLUS ONE
WRIB:	SKIPG	P2,ADRLST(P1)	;ANYTHING TO WRITE?
	JRST	NORIB		;NO--CONTINUE
	HRROS	ADRLST(P1)	;YES--FLAG LH

	SETZM	M(MH)		;CLEAR BUFFER FIRST
	MOVSI	T1,M(MH)	;MAKE BLT POINTER
	HRRI	T1,M+1(MH)	; ...
	PUSHJ	P,BIGBLT	;DO THE BLT

	MOVEI	T1,T$UFD	;LOAD UFD TYPE
	MOVEM	T1,G$TYPE(MH)	;STORE IN HEADER
	HRRZM	P1,D$LVL(MH)	;STORE LEVEL

	MOVEI	T3,D$STR(MH)	;MAKE BP TO D$STR IN HEADER
	HRLI	T3,440700	;...
	MOVE	T1,ACSTR	;GET ALIAS STRUCTURE NAME
	MOVEI	T2,.FCDEV	;INDICATE DATA TYPE
	PUSHJ	P,SETPTH	;STORE IN HEADER

	MOVE	T1,D$LVL(MH)	;INDICATE LEVEL
	PUSHJ	P,SETASC	;STORE O$NAME FULL PATH OF DIRECTORY
	MOVEM	T1,D$PCHK(MH)	;SAVE CHECKSUM OF PATH IN HEADER
	PUSHJ	P,SAVATR	;SAVE O$FILE ATTRIBUTE BLOCK ON TAPE

;HERE TO WRITE O$DIRT NON-DATA BLOCK IN T$UFD RECORD. OUTPUT PLACED AT M+400(MH)

	MOVEI	T1,200		;LENGTH OF BLOCK
	ADDM	T1,G$LND(MH)	;ADD TO NON-DATA LENGTH
	HRLI	T1,O$DIRT	;POSITION CONTROL CODE
	MOVEM	T1,400+M(MH)	;STORE CONTROL WORD
	MOVEI	T1,401+M(MH)	;MAKE POINTER TO DIRECTORY ATTRIBUTES
	MOVEI	T2,LN$DFH	;FIXED HEADER LENGTH
	MOVEM	T2,D$FHLN(T1)	;STORE
	MOVEI	T2,201+M(MH)	;MAKE POINTER TO O$FILE
	MOVE	T3,A$WRIT(T2)	;GET CREATION DATE/TIME FROM O$FILE BLOCK
	MOVEM	T3,D$LOGT(T1)	;SAVE FOR LOGIN TIME
	SETZB	T3,A$PROT(T2)	;ZILCH FILE PROTECTION WORD
	LDB	T4,[POINTR (.RBPRV(P2), RB.PRV)];GET RIB PROTECTION
	LSHC	T3,^D30		;POSITION PROGRAMMER PROTECTION IN T3
	DPB	T3,[POINTR (D$PROT(T1), AC$OWN)];SET OWNER ACCESS
	SETZ	T3,		;CLEAR
	LSHC	T3,3		;POSITION PROJECT PROTECTION IN T3
	DPB	T3,[POINTR (D$PROT(T1), AC$GRP)];SET AFFINITY GROUP PROT.
	LSH	T4,-^D33	;POSITION WORLD PROTECTION IN T4
	TLO	T4,(5B2)	;SET "5"
	IORM	T4,D$PROT(T1)	;STORE DIRECTORY PROTECTION
	MOVE	T2,.RBQTF(P2)	;GET QUOTA IN BLOCKS FROM RIB
	ASH	T2,7		;MULTIPLY BY 200 FOR QUOTA IN WORDS
	MOVEM	T2,D$QTF(T1)	;STORE
	MOVE	T2,.RBQTO(P2)	;GET LOGGED OUT QUOTA FROM RIB
	ASH	T2,7		;MULTIPLY BY 200 FOR QUOTA IN WORDS
	MOVEM	T2,D$QTO(T1)	;STORE

	PUSHJ	P,MTAOUT	;EXEC I/O
NORIB:	AOBJN	P1,WRIB		;CIRCLE
	POPJ	P,		;RETURN
;+
;<SAVFIL IS A ROUTINE TO MOVE AN INDIVIDUAL FILE FROM DISK TO TAPE.
;-

SAVFIL:	SKIPE	S.NLDV		;[400] ARE WE WRITING TO A NUL TAPE DEVICE?
	JRST	[		;[400] YES,
		MOVE	T1,S.LIST##	;[400] LET'S SEE IF THERE'S ANY
		IOR	T1,S.SDEL##	;[400] REASON TO DO A LOOKUP
		IOR	T1,S.DELT##	;[400] (I.E. LIST, SDELETE OR DELETE)
		JUMPN	T1,.+1		;[400] JUMP IF THERE'S A REASON
		POPJ	P,]		;[400] NOPE, JUST EXIT
	PUSHJ	P,SAVE3		;SAVE SOME ACS

	MOVEI	T1,NRIB-1	;SET FOR EXTENDED LOOKUP
	MOVEM	T1,EXLFIL+.RBCNT; ..
	CAIGE	LVL,1		;IF SFD, LOAD ADDRESS OF PATH BLOCK
	SKIPA	T1,PTHBLK+.PTPPN; ..
	MOVEI	T1,PTHBLK	; ..
	MOVEM	T1,EXLFIL+.RBPPN; ..
	MOVE	T1,CNAM		; ..
	MOVEM	T1,EXLFIL+.RBNAM; ..
	MOVE	T1,CEXT		; ..
	MOVEM	T1,EXLFIL+.RBEXT; ..

	LOOKUP	FILE,EXLFIL	;LOOKUP FILE
	  JRST	ELFIL		;LOSE

	SKIPE	S.NLDV##	;[375] IF NUL TAPE DEVICE THEN
	JRST	[			;[375] WE CAN SKIP LOTS OF STUFF
		SKIPN	S.LIST##	;[375] SKIP IF LISTING ORDERED
		JRST	CHKDEL		;[375] NO, DON'T NEED THE REST
		MOVEI	P2,EXLFIL	;[375] SET ADDR OF LOOKUP BLOCK
		PUSHJ	P,SAVATR	;[375] SETUP O$FILE BLOCK
		MOVEI	T1,M+200(MH)	;[375] POINT TO O$FILE BLOCK
		PUSHJ	P,LSTFIL	;[375] DO THE LISTING
		JRST	CHKDEL]		;[375] FINISH OFF

	MOVEI	T1,CP$INC	;CHECKPOINT INCREMENT
	ADDI	T1,CP$MRG	;CHECKPOINT MARGIN
	MOVEM	T1,CHKPNT	;SET INITIAL CHECKPOINT

	SKIPN	T1,S.RSUM##	;RESUMING?
	JRST	STREC		;NO, PROCEED WITH FIRST BLOCK

	PUSHJ	P,.USETI	;[357] POSITION USING FILOP
	ADDI	T1,CP$MRG	;ADD ON MARGIN
	ADDI	T1,CP$INC	;ADD ON INCREMENT
	MOVEM	T1,CHKPNT	;SET NEXT CHECKPOINT
;HERE TO FILL IN THE TAPE RECORD HEADER

STREC:	MOVEI	T1,T$FIL	;FILE DATA RECORD
	MOVEM	T1,G$TYPE(MH)	;STORE
	MOVSI	T3,440700	;MAKE INITIAL BP
	HRRI	T3,F$PTH(MH)	;ADDRESS OF F$PTH BLOCK
	SKIPE	S.INTR##	;SEE IF /INTERCHANGE
	JRST	CONREC		;YES--DON'T INCLUDE PATH INFO
	MOVE	T1,ACSTR	;GET FS NAME
	MOVEI	T2,.FCDEV	;INDICATE DATA TYPE
	PUSHJ	P,SETPTH	;STORE IN HEADER BLOCK
	MOVE	T1,APATH+.PTPPN	;GET DIRECTORY
	MOVEI	T2,.FCDIR	;INDICATE DATA TYPE
	PUSHJ	P,SETPTH	;STORE
	MOVE	T1,APATH+.PTPPN+1;GET FIRST SFD NAME
	MOVEI	T2,.FCSF1	;INDICATE DATA TYPE
	PUSHJ	P,SETPTH	;STORE
	MOVE	T1,APATH+.PTPPN+2;SECOND SFD NAME
	MOVEI	T2,.FCSF2	;TYPE CODE
	PUSHJ	P,SETPTH	;STORE

CONREC:	MOVE	T1,ACNAM	;GET FILE NAME
	MOVEI	T2,.FCNAM	;DATA TYPE
	PUSHJ	P,SETPTH	;STORE
	MOVE	T1,ACEXT	;GET EXTENSION
	MOVEI	T2,.FCEXT	;DATA TYPE
	PUSHJ	P,SETPTH	;STORE
	SKIPE	T1,THSRDB	;LOAD RELATIVE DATA BLOCK
	SUBI	T1,1		;CALCULATE RELATIVE DATA WORD
	IMULI	T1,200		; ...
	MOVEM	T1,F$RDW(MH)	;STORE
	MOVE	T1,PTHCHK	;GET PATH CHECKSUM
	MOVEM	T1,F$PCHK(MH)	;SAVE IN HEADER

	TXNN	F,FL$PSI	;SKIP FOLLOWING IF PSI ENABLED
	JRST	[PUSHJ	P,OPRCMD##;HANDLE ANY TTY INPUT
		  TXO	F,FL$KIL;RETURN HERE IF OPERATOR SAID KILL
		 JRST	.+1]	;CONTINUE

	SKIPE	THSRDB		;FIRST BLOCK?
	JRST	STBLK		;NO
;HERE TO HANDLE THE FIRST TAPE RECORD FOR A FILE

	MOVX	T1,GF$SOF	;YES, LOAD START OF FILE FLAG
	SKIPN	S.RSUM##	;UNLESS RESUMING,
	IORM	T1,G$FLAG(MH)	;SET IN HEADER

	SETZM	M(MH)		;CLEAR FIRST TAPE RECORD FOR FILE
	MOVSI	T1,M(MH)	;MAKE BLT POINTER
	HRRI	T1,M+1(MH)	; ...
	PUSHJ	P,BIGBLT	;DO THE BLT

	MOVEI	T1,.FXLND	;INDICATE FILE
	MOVEI	P2,EXLFIL	;SET ADDRESS OF LOOKUP BLOCK
	PUSHJ	P,SETASC	;SAVE O$NAME BLOCK
	MOVEM	T1,F$PCHK(MH)	;SAVE CHECKSUM IN HEADER
	MOVEM	T1,PTHCHK	;AND FOR LATER USE

	PUSHJ	P,SAVATR	;SAVE FILE ATTRIBUTES
	MOVEI	T1,M+200(MH)	;SET POINTER TO O$FILE BLOCK
	SKIPN	S.RSUM##	;UNLESS RESUMING,
	PUSHJ	P,LSTFIL	;LIST THIS FILE

	PUSHJ	P,DSKIN		;GET FIRST DISK BLOCK
	  JRST	CLSFIL		;ERROR -- QUIT
	  JRST	[SKIPE	S.RSUM## ;EOF RETURN
		 JRST	RSMERR  ;IF RESUMING MEANS USER GAVE BAD CHECKPOINT
		 JRST	SNDLST]	;IF NOT, MEANS ZERO LENGTH FILE -- DONE

	SKIPN	T1,S.RSUM##	;IF RESUMING, GET BLOCK NUMBER
	MOVEI	T1,1		;FIRST BLOCK
	MOVEM	T1,THSRDB	;STORE RELATIVE BLOCK NUMBER

	SKIPE	S.RSUM##	;IF RESUMING,
	PUSHJ	P,TYPRSM	;TYPE RESUME MESSAGE
	SETZM	S.RSUM##	; AND ZILCH

	MOVE	T1,EXLFIL+.RBSIZ;GET SIZE OF FILE
	CAIL	T1,<N*2*200>	;WOULD A BIG BLOCK BE USEFUL?
	SKIPA	T2,S.BFCT##	;YES, GET BLOCKING FACTOR
	MOVEI	T2,N		;ELSE USE STANDARD VALUE
	MOVEM	T2,BBSN		;SAVE DISK BLOCKS/TAPE BLOCK
	SUBI	T2,2		;ACCOUNT FOR STUFF USED BY HEADER
	IMULI	T2,200		;TIMES SIZE OF A DISK BLOCK
	CAMLE	T1,T2		;SEE IF SHOULD START IN SECOND TAPE BLOCK
	JRST	SNDREC		;YES, START FILE IN 2ND TAPE RECORD

	MOVEI	P2,M+400(MH)	;WHERE TO START
	MOVE	P1,BBSN		;MAXIMUM NUMBER OF BLOCKS FOR FIRST RECORD
	SUBI	P1,2		;MINUS 2 USED BY HEADER STUFF
	CAIG	T1,200		;IF ONLY ONE BLOCK,
	MOVEI	P1,1		;ADJUST P1
;HERE TO TRANSFER A DISK BLOCK TO THE TAPE BUFFER

STBLK:	MOVSI	T1,(DBUF)	;ADDRESS OF DATA
	ADDI	DBUF,200	;NEXT BLOCK IN DISK BUFFER
	HRRI	T1,(P2)		;WHERE TO GO IN TAPE BUFFER
	BLT	T1,177(P2)	;XFR DISK BLOCK

	MOVEI	T1,200		;LENGTH OF BLOCK
	ADDM	T1,G$SIZ(MH)	;ADD TO RECORD SIZE COUNT
	MOVNI	P3,200		;WORDS IN THIS BLT
	ADDB	P3,DSKHDR+.BFCTR;SAVE ACTUAL NUMBER OF WORDS
	ADDI	P2,200		;NEXT BLOCK SLOT
	SOSE	NDBLIB		;MORE DATA IN THIS DISK BUFFER?
	JRST	STBLK1		;YES, JUST MOVE IT TO THE TAPE BUFFER
	PUSHJ	P,DSKIN		;GET NEXT DATA BLOCK
	 JRST	[MOVX	T2,GF$DF0	;[254] SET DISK FILE ERROR BIT
		HRRZ	T3,S.MBPT	;[254] TAPE BUFFER POINTER
		ADDI	T3,M+2		;[254] TO START OF DATA
		SUB	T3,P2		;[254] SUBTRACT CURRENT ADDRESS
		IDIVI	T3,200		;[254] TO NEGATIVE BLOCKS
		LSH	T2,(T3)		;[254] SHIFT BIT TO POSITION
		IORM	T2,G$FLAG(MH)	;[254] INTO RECORD FLAG WORD
		JRST	.+2]		;[254] AND CONTINUE
	  JRST	FINFIL		;EOF--DONE
STBLK1:	AOS	T1,THSRDB	;ANOTHER BLOCK READ
	SKIPE	S.CKPT##	;CHECKPOINTING?
	PUSHJ	P,TYPCKP	;YES
	SOJG	P1,STBLK	;GO XFR NEXT ONE

SNDREC:	PUSHJ	P,GETFCT	;GET BLOCKING FACTOR IN T1
	MOVEM	T1,G$TBS(MH)	;STORE IN HEADER
	PUSHJ	P,MTAOUT	;SEND TAPE RECORD

	MOVE	P1,BBSN		;GET NUMBER OF DISK BLOCKS/TAPE BLOCK
	MOVEI	P2,M(MH)	;WHERE TO WRITE
	TXNN	F,FL$KIL	;SEE IF OPERATOR SAID KILL
	JRST	STREC		;NO--GO START AGAIN

	PUSHJ	P,EAFIL		;YES--ABORT FILE
	MOVEI	T1,[ASCIZ/
	% SAVE ABORTED
/]
	SKIPE	S.LIST		;SKIP IF NO LISTING NEEDED
	PUSHJ	P,LSTMSG	;SEND TO LISTING FILE
	JRST	CLSFIL		;CLOSE FILE
;	HERE ON DISK EOF

FINFIL:	ADDM	P3,G$SIZ(MH)	;TO USE ACTUAL WORD SIZE OF LAST DISK BLOCK
	SOJLE	P1,SNDLST	;IF BUFFER FULL, SEND LAST RECORD
	SETZM	(P2)		;CLEAR REMAINDER OF BUFFER
	MOVSI	T1,(P2)		;MAKE BLT POINTER
	HRRI	T1,1(P2)	; ...
	PUSHJ	P,BIGBLT	;DO THE BLT

SNDLST:	MOVX	T1,GF$EOF	;MARK AS LAST BLOCK
	IORM	T1,G$FLAG(MH)	;SET FLAG
	PUSHJ	P,GETFCT	;GET BLOCKING FACTOR IN T1
	MOVEM	T1,G$TBS(MH)	;STORE IN HEADER
	PUSHJ	P,MTAOUT	;SEND LAST BUFFER
	MOVEI	T1,N		;RESET BLOCK SIZE
	MOVEM	T1,BBSN		;...
	SKIPN	S.REPT##	;[355] /REPEAT?
	JRST	CHKDEL		;[355] NO, SAFE TO DELETE IF NECESSARY
	MOVE	T1,CURTAP	;[355] SEE IF TAPE NUMBERS HAVE CHANGED
	CAMN	T1,S.NTPE##	;[355]
	JRST	CHKDEL		;[355] SAME TAPE
	SKIPE	NRPS		;[355] HAS A REPEAT ALREADY BEEN DONE?
	JRST	CLSFIL		;[355] NO, SO DON'T TRY DELETING
CHKDEL:	SKIPN	S.SDEL##	;[230] /SDELETE?
	JRST	DELSWT		;[230] NO, CHECK /DELETE
	MOVEI	T1,T2		;[230] YES,SET UP CHKACC
	LDB	T2,[POINTR(EXLFIL+.RBPRV,RB.PRV)] ;[230] GET PROTECTION
	MOVE	T3,EXLFIL+.RBPPN	;[230] GET POINTER OR PPN
	TLNN	T3,-1		;[230] IS IT S POINTER?
	MOVE	T3,.PTPPN(T3)	;[230][317] YES, GO GET PPN
	MOVE	T4,.MYPPN##	;[230] GET USER PPN
	HRLI	T2,.ACREN	;[230] SET UP CHKACC FOR RENAME
	CHKACC	T1,		;[230] SEE IF DELETION VIA RENAME WILL WORK
	JFCL			;[230] IGNORE ERROR
	JUMPE	T1,DELFIL	;[230] YES,GO DELETE
	MOVSI	T1,700000	;[230] NO,MUST LOWER OWNER PROTECTION
	ANDCAM	T1,EXLFIL+.RBPRV	;[230] CLEAR OWNER PROTECTION
	RENAME 	FILE,EXLFIL	;[230] RENAME FILE PROTECTION
	JFCL			;[230] IGNORE ERROR
	JRST	DELFIL		;[230] GO DELETE FILE
DELSWT:	SKIPN	S.DELT##	;[230] /DELETE?
	JRST	CLSFIL		;NO, FINISH FILE
DELFIL:	TXNN	F,FL$HUF	;[342] SKIP IF HOLDING FILE ALREADY
	PUSHJ	P,HOLDIT	;[337] GO HOLD FILE IF NECESSARY
	MOVE	T1,EXLFIL+.RBNAM ;[230] SAVE FILENAME IN CASE OF ERROR
	SETZM	EXLFIL+.RBNAM	;ZILCH TO DELETE
	RENAME	FILE,EXLFIL	;DELETE FILE
	  SKIPA			;ERROR RETURN
	POPJ	P,		;OK--THATS ALL
	WARN$N	(CDF,Cannot delete file)
	MOVEM	T1,EXLFIL+.RBNAM ;RESTORE FILENAME,
	MOVEI	P1,EXLFIL	;SET POINTER
	JRST	EGUUO		;TELL WHICH AND RETURN

CLSFIL:	TXNN	F,FL$HUF	;[342] SKIP IF ALREADY HELD.
	PUSHJ	P,HOLDIT	;[337] HOLD IF NECESSARY.
	CLOSE	FILE,CL.ACS	;INHIBIT ACCESS DATE UPDATING
	 POPJ	P,		;RETURN



;HOLDIT -- Routine to LOOKUP the file (information at EXLFIL) so that the
;	monitor will not do extra disk accesses for the UFD. Uses P1-P4,
;	carefully saving and restoring them.  Do the test of FL$HUF here,
;	just to be safe.

HOLDIT:	TXNE	F,FL$HUF	;[436] ARE WE HOLDING THE UFD PPB?
	POPJ	P,		;[436] YES. JUST RETURN
	PUSHJ	P,SAVE4		;[436] PRESERVE P1-P4
	MOVE	P1,EXLFIL+.RBNAM;[436] FILENAME
	HLLZ	P2,EXLFIL+.RBEXT;[436] EXTENSION
	MOVEI	P3,0		;[436] ZERO THIRD WORD
	MOVE	P4,EXLFIL+.RBPPN;[436] PPN OR PATH POINTER
	LOOKUP	HOLD,P1		;[436] LOOKUP FILE ON HOLD CHANNEL
	  POPJ	P,		;[436] JUST CONTINUE IF ERROR.
	TXO	F,FL$HUF	;[436] SUCCESSFUL LOOKUP - FLAG IT
	POPJ	P,		;[436] RESTORE P1-P4 AND RETURN
HOLDRL:	TXZE	F,FL$HUF	;[342] HOLDING UFD?
	CLOSE	HOLD,CL.ACS	;[342] YES - CLOSE THE FILE
	RELEAS	HOLD,		;[376][342] IN ANY CASE, RELEASE CHANNEL
	SETZM	HCSTR		;[342] ZERO CURRENTLY HELD STRUCTURE
	SETZM	HCPPN		;[342] AND PPN
	POPJ	P,		;[342] RETURN

	SUBTTL	DISK TO TAPE SUBROUTINES

;+
;.CHAPTER DISK TO TAPE SUBROUTINES
;-

;+
;<XALIAS IS THE SUBROUTINE TO DO ALIASING.
;^EACH MASKED CHARACTER IN THE OUTPUT FILE SPEC PATH IS REPLACED
;WITH THE CORRESPONDING CHARACTER OF THE CURRENT FILE BEING PROCESSED.
;^THE DEVICE IS SIMPLY RENAMED.
;-

XALIAS:	MOVE	T1,.FXDEV(SP)	;GET ALIAS STR
	CAMN	T1,[SIXBIT /ALL/] ;SKIP IF NOT ALL
	MOVE	T1,CSTR		;ALL. GET ORIGINAL STR BACK
	MOVEM	T1,ACSTR	;STORE

	MOVE	T1,CNAM		;GET FILE NAME
	TDZ	T1,.FXNMM(SP)	;ZILCH
	MOVE	T2,.FXNAM(SP)	;GET ALIAS
	AND	T2,.FXNMM(SP)	;ZILCH
	IOR	T1,T2		;FORM ALIAS FILE NAME
	MOVEM	T1,ACNAM	;STORE

	MOVE	T1,CEXT		;GET EXTENSION
	HRLZ	T2,.FXEXT(SP)	;GET MASK
	TDZ	T1,T2		;ZILCH
	HLLZ	T3,.FXEXT(SP)	;GET ALIAS
	AND	T3,T2		;ZILCH
	IOR	T1,T3		;FORM ALIAS FILE NAME
	MOVEM	T1,ACEXT	;STORE

	MOVSI	T1,-.FXLND		;START AT UFD LEVEL
	MOVE	T2,SP		;GET SPEC ADDRESS

XAPATH:	MOVE	T3,PTHBLK+.PTPPN(T1) ;GET UFD-SFD
	TDZ	T3,.FXDIM(T2)	;ZILCH
	MOVE	T4,.FXDIR(T2)	;GET ALIAS
	AND	T4,.FXDIM(T2)	;ZILCH
	IOR	T3,T4		;FORM ALIAS UFD-SFD
	MOVEM	T3,APATH+.PTPPN(T1) ;STORE
	JUMPE	T3,CPOPJ	;RETURN NOW IF END OF PATH

	ADDI	T2,2		;NEXT DIR-MSK PAIR
	AOBJN	T1,XAPATH	;GET NEXT UFD-SFD

	SETZM	APATH+.PTPPN(T1) ;INSURE TRAILING ZERO
	POPJ	P,		;RETURN
;+
;<SAVATR IS A ROUTINE TO HANDLE PUTTING FILE ATTRIBUTE INFORMATION ONTO THE TAPE.
;^IT PLACES <O$FILE AS THE SECOND BLOCK IN THE TAPE RECORD. ^INPUT IS
;FROM THE EXTENDED LOOKUP BLOCK (ADDRESS IN ^P2). ^OUTPUT PLACED AT ^M+200(<MH).
;-

SAVATR:	PUSHJ	P,SAVE1		;MAKE SOME ROOM
	MOVEI	T1,200		;LENGTH OF BLOCK
	ADDM	T1,G$LND(MH)	;ADD TO NON-DATA TOTAL
	HRLI	T1,O$FILE	;BLOCK TYPE
	MOVEM	T1,M+200(MH)	;STORE CONTROL WORD
	MOVEI	P1,M+201(MH)	;MAKE POINTER TO FIXED LENGTH SUBBLOCK
	MOVEI	T1,LN$AFH	;FIXED HEADER LENGTH
	MOVEM	T1,A$FHLN(P1)	;STORE
	SKIPE	T1,S.INTR##	;SEE IF /INTERCHANGE
	JRST	SETIME		;YES, IGNORE FLAGS
	MOVE	T2,.RBSTS(P2)	;GET FILE FLAGS
	MOVSI	T3,-LN$FLG	;FLAG TABLE LENGTH
SETFLG:	TDNE	T2,RIBFLG(T3)	;IF RIB FLAG SET,
	IOR	T1,BKPFLG(T3)	; SET CORRESPONDING BACKUP FLAG
	AOBJN	T3,SETFLG	;LOOP
	MOVEM	T1,A$FLGS(P1)	;STORE FLAGS

SETIME:	LDB	T1,[POINTR (.RBPRV(P2), RB.CRT)];GET CREATION TIME
	IMULI	T1,^D60000	;CONVERT TO MILLISECONDS
	LDB	T2,[POINTR (.RBEXT(P2) ,RB.CRX)];HIGH ORDER CREATION BITS
	LSH	T2,^D12		;POSITION
	LDB	T3,[POINTR (.RBPRV(P2), RB.CRD)];LOW ORDER CREATION BITS
	IOR	T2,T3		;UNITE
	PUSHJ	P,CONVDT	;CONVERT TO UNIVERSAL DATE/TIME
	MOVEM	T1,A$WRIT(P1)	;STORE DATE/TIME
	MOVE	T1,.RBALC(P2)	;NUMBER BLOCKS ALLOCATED
	ASH	T1,7		;WORDS PER BLOCK
	MOVEM	T1,A$ALLS(P1)	;STORE NBR WORDS ALLOCATED
	LDB	T1,[POINTR (.RBPRV(P2), RB.MOD)];GET MODE
	MOVEM	T1,A$MODE(P1)	;STORE
	MOVEI	T2,^D36		;ASSUME BINARY
	CAIG	T1,.IOASL	;SEE IF ASCII
	MOVEI	T2,7		;YES--CORRECT BYTE SIZE
	MOVEM	T2,A$BSIZ(P1)	;STORE BYTE SIZE
	MOVE	T2,.RBSIZ(P2)	;GET SIZE IN WORDS
	CAIG	T1,.IOASL	;SEE IF ASCII MODE
	IMULI	T2,5		;YES--GET SIZE IN BYTES
	TLZ	T2,(1B0)	;MAKE SURE BIT 0 IS CLEARED
	MOVEM	T2,A$LENG(P1)	;STORE LENGTH IN BYTES
	SKIPE	T1,.FXVER(SP)	;[316] GET VERSION NUMBER, IF NULL
	CAMN	T1,[-1]		;[316] OR DEFAULT, USER .RBVER
	MOVE	T1,.RBVER(P2)	;IF NOT, USE VERSION FROM FILE
	MOVEM	T1,A$VERS(P1)	;STORE VERSION ON TAPE
	MOVE	T1,.RBTYP(P2)	;GET FILE TYPE
	MOVEM	T1,A$FTYP(P1)	;STORE
	MOVE	T1,.RBBSZ(P2)	;GET BYTE SIZES
	MOVEM	T1,A$FBSZ(P1)	;STORE
	MOVE	T1,.RBRSZ(P2)	;RECORD AND BLOCK SIZES
	MOVEM	T1,A$FRSZ(P1)	;STORE
	MOVE	T1,.RBFFB(P2)	;GET APPLICATION/CUSTOMER WORD
	MOVEM	T1,A$FFFB(P1)	;STORE
	SKIPE	T1,S.INTR##	;SEE IF /INTERCHANGE
	POPJ	P,		;YES--THAT'S ALL FOR O$FILE
;HERE TO FILL REST OF O$FILE BLOCK FOR NON-INTERCHANGE MODE

	LDB	T2,[POINTR (.RBEXT(P2), RB.ACD)];GET ACCESS DATE
	PUSHJ	P,CONVDT	;CONVERT TO SMITHSONIAN
	MOVEM	T1,A$REDT(P1)	;STORE
	LDB	T1,[POINTR (.FXMOD(SP),FX.PRO)];GET /PROTECTION
	LDB	T2,[POINTR (.FXMOM(SP),FX.PRO)];SEE IF SET
	SKIPN	T2		;IF SET, USE IT
	LDB	T1,[POINTR (.RBPRV(P2),RB.PRV)];USE RIB PROTECTION
	PUSHJ	P,SETPRO	;CONVERT TO BACKUP PROTECTION
	MOVEM	T1,A$PROT(P1)	;STORE
	MOVE	T1,.RBTIM(P2)	;GET MONITOR SET CREATION DATE/TIME
	MOVEM	T1,A$MODT(P1)	;STORE
	SKIPG	T1,.FXEST(SP)	;GET USER ESTIMATE, IF SET
	MOVE	T1,.RBEST(P2)	;IF NOT, USE FILE ESTIMATE

	ASH	T1,7		;CONVERT TO WORD ESTIMATE
	MOVEM	T1,A$ESTS(P1)	;STORE
	MOVE	T1,.RBPOS(P2)	;GET LOGICAL BLOCK NUMBER
	ASH	T1,7		;CONVERT TO LOGICAL DISK ADDRESS
	MOVEM	T1,A$RADR(P1)	;STORE
	MOVE	T1,.RBNCA(P2)	;SAVE CUSTOMER WORDS
	MOVEM	T1,A$USRW(P1)	; ...
	MOVE	T1,.RBPCA(P2)	; ...
	MOVEM	T1,A$PCAW(P1)	; ...
	MOVSI	T3,440700	;MAKE ASCII BYTE POINTER
	HRRI	T3,LN$AFH	;POINT TO END OF FIXED HEADER SUBBLOCK
IFN FT$USG,<
	SKIPN	.RBACT(P2)	;ANY ACCOUNT STRING GIVEN
	JRST	SETANT		;NO, SKIP THIS
	HRLI	T1,.RBACT(P2)	;POINT TO ACCOUNT STRING
	HRRI	T1,M+201+LN$AFH(MH) ;POINT TO PHYSICAL PLACE FOR IT
	BLT	T1,M+201+LN$AFH+7(MH) ;MOVE THE ACCOUNT STRING
	MOVEM	T3,A$ACCT(P1)	;STORE WHERE YOU CAN FIND IT
	ADDI	T3,10		;INCREMENT ABSOLUTE BYTE POINTER
>
SETANT:	SKIPE	T1,.RBSPL(P2)	;GET ANNOTATION IN SIXBIT
	MOVEM	T3,A$NOTE(P1)	;STORE ANNOTATION STRING BYTE POINTER
	ADDI	T3,M+201(MH)	;ADJUST FOR PHYSICAL ADDRESS
	PUSHJ	P,SETASZ	;STORE ASCIZ STRING
	MOVE	T2,T3		;COPY BYTE POINTER
	SUBI	T2,M+201(MH)	;MAKE RELATIVE BYTE POINTER
	SKIPE	T1,.RBAUT(P2)	;GET AUTHOR PPN
	MOVEM	T2,A$CUSR(P1)	;STORE CREATOR STRING BYTE POINTER
	PUSHJ	P,SETPPN	;STORE ASCIZ STRING
	SKIPN	T1,.RBMTA(P2)	;GET REEL ID OF LAST TAPE
	POPJ	P,		;IF NULL, DONE
	MOVE	T2,T3		;COPY NEW BYTE POINTER
	SUBI	T2,M+201(MH)	;MAKE RELATIVE BYTE POINTER
	MOVEM	T2,A$BKID(P1)	;STORE BP TO LAST BACKUP TAPE
				;FALL INTO SETASZ
;+
;<SETASZ IS A SUBROUTINE TO CONVERT A <SIXBIT WORD TO AN <ASCIZ STRING.
;^CALLED WITH ^T1 = <SIXBIT WORD AND ^T3 = <ASCII BYTE POINTER. ^USES ^T1-^T3.
;-

SETASZ:	JUMPE	T1,CPOPJ	;NOTHING TO STORE
	PUSHJ	P,STASSX	;CONVERT TO ASCII STRING
	MOVEI	T1,0		;NULL
	JRST	STASCH		;SET NULL & RETURN

;+
;<SETPRO IS A SUBROUTINE TO RETURN THE <BACKUP PROTECTION WORD FROM
;THE <TOPS-10 PROTECTION VALUE. ^CALL WITH ^T1 = <TOPS-10 PROTECTION,
;RETURNS <BACKUP PROTECTION IN ^T1. ^USES ^T1-^T4.
;-

SETPRO:	MOVE	T3,T1		;COPY PROTECTION
	SETZB	T1,T2		;CLEAR
	LSHC	T2,^D30		;POSITION PROGRAMMER PROTECTION IN T2
	PUSHJ	P,SETPRT	;SET OWNER ACCESS FIELD
	LSH	T1,^D8		;POISTION
	MOVEI	T2,0		;ZILCH
	LSHC	T2,3		;GET PROJECT PROTECTION IN T2
	PUSHJ	P,SETPRT	;SET AFFINITY GROUP ACCESS FIELD
	LSH	T1,^D8		;POSITION
	MOVEI	T2,0		;ZILCH
	LSHC	T2,3		;GET RIB WORLD PROTECTION
	PUSHJ	P,SETPRT	;SET WORLD ACCESS FIELD
	TLO	T1,(5B2)	;SET "5"
	POPJ	P,		;RETURN WITH PROTECTION IN T1

;+
;<SETPRT IS A SUBROUTINE TO SET A <BACKUP FILE ACCESS SUBFIELD. ^CALLED WITH
;^T2 = <TOPS-10 PROTECTION DIGIT, RETURNS WITH ACCESS SUBFIELD SET IN ^T1.
;^CLOBBERS ^T4.
;-

SETPRT:	MOVEI	T4,1		;ASSUME 1 FOR ATTRIBUTE ACCESS VALUE
	CAIG	T2,5		;SEE IF PROTECTION GREATER THAN FIVE
	ADDI	T4,1		;NO, STEP ATTRIBUTE ACCESS
	CAIG	T2,1		;SEE IF RIB PROTECTION > 1
	ADDI	T4,5		;NO, INCREMENT ACCESS FIELD
	SKIPG	T2		;SEE IF EQUAL TO ZERO
	SUBI	T4,1		;YES--ACCESS = 6
	DPB	T4,[POINTR (T1,PR$ATR)];SET ATTRIBUTE SUBFIELD

;HERE TO SET THE WRITE PROTECTION BITS

	MOVEI	T4,0		;START WITH ZERO
	CAIG	T2,4		;SEE IF RIB PROTECTION > 4
	ADDI	T4,1		;INCREMENT WRITE ACCESS SUBFIELD
	CAIG	T2,3		;CHECK RIB PROTECTION
	ADDI	T4,1		;INCREMENT WRITE ACCESS SUBFIELD
	CAIG	T2,2		;CHECK RIB PROTECTION
	ADDI	T4,1		;INCREMENT WRITE ACCESS SUBFIELD
	DPB	T4,[POINTR (T1, PR$WRT)];SET WRITE ACCESS SUBFIELD

;HERE TO SET READ PROTECTION BITS
	MOVEI	T4,0		;START WITH ZERO
	CAIG	T2,6		;CHECK RIB PROTECTION
	ADDI	T4,1		;INCREMENT READ ACCESS SUBFIELD
	CAIG	T2,5		;CHECK RIB PROTECTION
	ADDI	T4,1		;STEP READ ACCESS SUBFIELD
	DPB	T4,[POINTR (T1, PR$RED)];SET READ ACCESS SUBFIELD
	POPJ	P,		;RETURN
;+
;<SETASC IS A SUBROUTINE TO PUT A FILE'S CANONICAL FULL PATH NAME IN THE
;TAPE RECORD IN <O$NAME BLOCK FORMAT. ^SUB-BLOCKS APPEAR IN THE STANDARD
;ORDER: DEVICE, DIRECTORIES (TOP DOWN), FILE NAME, EXTENSION.
;^CALLED WITH  ^T1 = DIRECTORY LEVEL OR <.FXLND IF FILE.
;^INPUT FROM ALIAS INFO, OUTPUT PLACED AT <M(MH).
;^RETURNS CHECKSUM OF <O$NAME BLOCK IN ^T1. ^USES ^T1-^T4.
;-

SETASC:	PUSHJ	P,SAVE2		;SAVE SOME ACS
	SAVE$	T1		;SAVE LEVEL FOR LATER
	MOVEI	T1,200		;LENGTH OF BLOCK
	ADDM	T1,G$LND(MH)	;ADD TO TOTAL
	HRLI	T1,O$NAME	;INDICATE BLOCK TYPE
	MOVEM	T1,M(MH)	;STORE CONTROL WORD
	MOVEI	P1,M+1(MH)	;INITIALIZE SUB-BLOCK POINTER
	MOVE	T1,ACSTR	;GET DEVICE
	MOVEI	T2,.FCDEV	;DEVICE DATA TYPE
	PUSHJ	P,SETBLK	;SET SUB-BLOCK
	SKIPE	S.INTR##	;SEE IF /INTERCHANGE
	JRST	SETAS2		;YES--SKIP PATH INFO

	MOVN	P2,(P)		;GET NEGATIVE LEVEL OR .FXLND IF FILE
	HRLZS	P2		;FORM AOBJN WORD
SETAS1:	SKIPN	T1,APATH+.PTPPN(P2);SEE IF THIS ONE SET
	JRST	SETAS2		;NO--ALL DONE WITH DIRECTORIES
	MOVEI	T2,.FCDIR(P2)	;GET TYPE CODE
	PUSHJ	P,SETBLK	;SET SUB-BLOCK
	AOBJN	P2,SETAS1	;LOOP DOWN SFD CHAIN

SETAS2:	RSTR$	P2
	CAIE	P2,.FXLND	;SEE IF FILE
	JRST	SETAS3		;SKIP FOLLOWING IF DIRECCTORY
	MOVE	T1,ACNAM	;GET FILE NAME
	MOVEI	T2,.FCNAM	;INDICATE FILE NAME
	PUSHJ	P,SETBLK	;SET SUB-BLOCK
	HLLZ	T1,ACEXT	;GET EXTENSION
	MOVEI	T2,.FCEXT	;INDICATE TYPE
	PUSHJ	P,SETBLK	;SET SUB-BLOCK

;HERE TO COMPUTE CHECKSUM OF THE O$NAME BLOCK

SETAS3:	SETZ	T1,		;CLEAR FOR CHECKSUM
	MOVSI	T2,-200		;LENGTH OF BLOCK
	HRRI	T2,M(MH)	;START OF BLOCK
SETAS4:	ADD	T1,(T2)		;CHECKSUM O$NAME BLOCK
	ROT	T1,1		; ...
	AOBJN	T2,SETAS4	; ...
	POPJ	P,		;RETURN WITH CHECKSUM IN T1
;+
;<SETBLK IS A SUBROUTINE CALLED BY <SETASC TO SET CONSECUTIVE SUB-BLOCKS
;IN THE <O$NAME BLOCK. ^CALLED WITH ^T1 = PATH FIELD, ^T2 = PATH TYPE CODE.
;^ASSUMES ^P1 = ADDRESS TO START SUB-BLOCK.
;^UPDATES ^P1 TO FIRST ADDRESS PAST SUB-BLOCK. ^USES ^T1-^T4.
;-

SETBLK:	JUMPE	T1,CPOPJ	;OMIT SUB-BLOCK IF NULL PATH FIELD
	HRLM	T2,(P1)		;STORE PATH TYPE CODE
	MOVSI	T3,440700	;MAKE ASCII BYTE POINTER
	HRRI	T3,1(P1)	;START ADDRESS FOR ASCIZ STRING
	MOVEI	T4,SETASZ	;ASSUME SIXBIT CONVERSION ROUTINE
	CAIN	T2,.FCDIR	;SEE IF UFD
	MOVEI	T4,SETPPN	; YES--USE PPN CONVERSION ROUTINE
	PUSHJ	P,(T4)		;STORE ASCIZ STRING
	HRRZS	T3		;CLEAR LEFT HALF
	SUBI	T3,-1(P1)	;COMPUTE LENGTH OF SUB-BLOCK
	HRRM	T3,(P1)		;STORE IN CONTROL WORD
	ADD	P1,T3		;UPDATE POINTER
	POPJ	P,		;RETURN

;+
;<SETPPN IS A SUBROUITNE TO CONVERT A <PPN TO AN <ASCIZ STRING. ^THE PROJECT
;AND PROGRAMMER NUMBERS ARE SEPARATED BY AN UNDERLINE CHARACTER.
;^CALLED WITH ^T1 = <PPN AND ^T3 = <ASCII BYTE POINTER. ^USES ^T1-^T4.
;-

SETPPN:	SKIPN	T4,T1		;SAVE COPY FOR LATER
	POPJ	P,		;RETURN IF PPN NULL
	HLRZS	T1		;POSITION PROJECT NBR
	PUSHJ	P,STASOC	;SET ASCII STRING
	MOVEI	T1,"_"		;USE UNDERLINE AS DIVIDER
	IDPB	T1,T3		;SET IN STRING
	HRRZ	T1,T4		;GET PROGRAMMER NBR
	PUSHJ	P,STASOC	;SET ASCII STRING
	MOVEI	T1,0		;NULL
	JRST	STASCH		;SET NULL & RETURN

;+
;<STASSX IS A SUBROUTINE TO CONVERT A <SIXBIT WORD TO AN <ASCII STRING.
;^CALLED WITH ^T1 = <SIXBIT WORD AND ^T3 = <ASCII BYTE POINTER. ^USES ^T1-^T3.
;-

STASSX:	MOVE	T2,T1		;POSITION VALUE
STASS1:	JUMPE	T2,CPOPJ	;RETURN WHEN DONE
	MOVEI	T1,0		;CLEAR ACCUMULATOR
	LSHC	T1,6		;GET NEXT CHARACTER
	ADDI	T1," "-' '	;CONVERT TO ASCII
	PUSHJ	P,STASCH	;SET CHARACTER
	JRST	STASS1		;LOOP
;+
;<STASOC IS A SUBROUTINE TO CONVERT AN OCTAL NUMBER TO AN <ASCII STRING.
;^CALL WITH ^T1 = OCTAL VALUE AND ^T3 = <ASCII BYTE POINTER. ^USES ^T1-^T3.
;-

STASOC:	IDIVI	T1,10		;SPLIT DIGIT
	HRLM	T2,(P)		;STORE DIGIT
	SKIPE	T1		;UNLESS DONE,
	PUSHJ	P,STASOC	; DO IT AGAIN
	HLRZ	T1,(P)		;GET BACK DIGIT
	ADDI	T1,"0"		;CONVERT TO ASCII
				;FALL INTO STASCH

;+
;<STASCH IS A SUBROUTINE TO OUTPUT A CHARACTER TO A STRING.
;^CALL WITH ^T1 = CHARACTER AND BYTE POINTER IN ^T3.
;-

STASCH:	IDPB	T1,T3		;POINTER IS IN T3
	POPJ	P,		;RETURN

;+
;<SETPTH IS A SUBROUTINE TO STORE FILE PATH INFOMATION IN THE FORMAT:
;<BYTE (7) DATA TYPE, LENGTH IN WORDS, <ASCII CHARACTERS (<F$PTH FORMAT).
;^CALLED WITH ^T1 = FILE INFO, ^T2 = DATA TYPE, BYTE POINTER IN ^T3.
;^USES ^T1-^T4.
;-

SETPTH:	JUMPE	T1,CPOPJ	;OMIT IN F$PTH IF NULL
	IDPB	T2,T3		;SET DATA TYPE
	MOVE	T4,T3		;SAVE COPY OF BP FOR LATER
	IBP	T3		;INCREMENT BP
	CAIE	T2,.FCDIR	;SEE IF DIRECTORY
	JRST	SETPT1		;NO, MUST BE SIXBIT WORD
	SAVE$	T1		;SAVE COPY FOR LATER
	HLRZS	T1		;GET PROJECT NUMBER
	PUSHJ	P,STASOC	;CONVERT TO ASCII STRING
	MOVEI	T1,"_"		;UNDERLINE
	IDPB	T1,T3		;SET UNDERLINE IN STRING
	RSTR$	T1		;GET PROGRAMMER NUMBER BACK
	HRRZS	T1		;CLEAR LEFT HALF
	PUSHJ	P,STASOC	;CONVERT TO ASCII
	SKIPA			;SKIP SIXBIT CONVERSION
SETPT1:	PUSHJ	P,STASSX	;CONVERT SIXBIT WORD TO ASCII STRING
	ADDI	T3,1		;ADVANCE TO NEXT LOCATION
	HRLI	T3,440700	;MAKE NEW BP
	HRRZ	T2,T3		;CALCULATE # OF WORDS USED
	SUBI	T2,(T4)		;...
	IDPB	T2,T4		;SAVE IN PROPER PLACE
	POPJ	P,		;RETURN
;+
;<BIGBLT IS A SUBROUTINE TO BLT USING THE SIZE OF A LARGE BLOCK.
;^IT REPLACES ALL "<BLT <T1,<MTBBKP-1(MH)" INSTRUCTIONS.  ^THIS
;ROUTINE COMPUTES THE LENGTH OF THE RECORD USING <BBSN.
;-

BIGBLT:	PUSH	P,T2		;SAVE AN AC
	MOVE	T2,B.BBKP##	;ADD IN SIZE OF A BACKUP BLOCK ON TAPE
				;$ (CONSTANT INITIALIZED BY INIBBS IN BACKUP)
	ADDI	T2,-1(MH)	;COMPUTE END ADDRESS
	BLT	T1,(T2)		;DO THE BLT
	POP	P,T2		;RESTORE THE AC
	POPJ	P,		;RETURN

;+
;<GETFCT RETURNS THE BLOCKING FACTOR IN <T1.  ^IF NOT WRITING BIG
;BLOCKS, ZERO IS RETURNED.
;-

GETFCT:	MOVE	T1,BBSN		;GET BLOCKING FACTOR
	SKIPE	S.INTR##	;BUT WAS /INTERCHANGE SPECIFIED?
	MOVEI	T1,N		;YES, THEN DON'T USE BIG BUFFERS
	CAILE	T1,N		;IS THIS A BIG BLOCK?
	JRST	GETFC1		;YES
	SETZ	T1,		;NO, RETURN ZERO
	POPJ	P,		;RETURN

GETFC1:	PUSH	P,T2		;SAVE AN AC
	MOVE	T2,T1		;GET A COPY
	IMULI	T2,200		;CONVERT TO WORDS
	ADDI	T2,M		;ADD IN HEADER
	DPB	T2,[POINTR T1,GC$BSZ] ;STORE IN T1
	POP	P,T2		;RESTORE AN AC
	POPJ	P,		;RETURN
	SUBTTL	TAPE TO DISK MAIN ROUTINES

;+
;.CHAPTER TAPE TO DISK MAIN ROUTINES
;-

;+
;<CHKALL IS THE <CHECK COMMAND ENTRY POINT TO THE TAPE READ ROUTINE.
;^FOR THE <CHECK VERB, DISK FILES ARE READ (INSTEAD OF WRITTEN) AND
;COMPARED WORD BY WORD WITH THE TAPE FILES. "^INPUT" IS SET AS THE
;OPERATION FOR DISK <I/O, AND THE <COMPAR SUBROUTINE IS SET
;FOR LATER USE INSTEAD OF A <BLT INSTRUCTION.
;-

CHKALL:	TXO	F,FL$CHK	;INDICATE /CHECK
	MOVE	T1,[PUSHJ P,COMPAR] ;COMPARE DATA
	MOVEI	T2,DSKIN	;INPUT FROM DISK
	JRST	CHKRST		;GO TO COMMON HANDLER
;+
;<RSTALL IS THE ENTRY POINT TO THE TAPE READ ROUTINE FOR THE <RESTORE AND
;<PRINT COMMANDS. "^OUTPUT" IS SET AS THE DISK <I/O OPERATION AND A <BLT
;INSTRUCTION TO TRANSFER DATA FROM THE TAPE TO DISK BUFFERS IS SET
;FOR LATER EXECUTION INSTEAD OF THE <COMPAR SUBROUTINE.
;-

RSTALL:	TXZ	F,FL$CHK	;INDICATE NOT /CHECK
	MOVE	T1,[BLT T1,(T2)] ;COPY DATA
	MOVEI	T2,DSKOUT	;OUTPUT TO DISK


;+
;<CHKRST MARKS THE START OF COMMON CODE FOR THE TAPE READ ROUTINE.
;^IF A PARTICULAR SAVE SET HAS BEEN SPECIFIED, THE TAPE IS SEARCHED
;FROM THE CURRENT POSITION TO <EOT FOR THE START OF THE SAVE SET.
;^OTHERWISE, READING BEGINS FROM THE CURRENT TAPE POSITION.
;^THE CODE BRANCHES BASED ON THE TYPE OF RECORD IN THE TAPE BUFFER.
;-

CHKRST:	MOVEM	T1,DSKBLT	;SAVE OPERATION
	MOVEM	T2,DSKIO	;SAVE DISK ROUTINE
	PUSHJ	P,SAVE3		;SAVE C(P1), C(P2) & C(P3)

	SETZM	PRESTR		;ZERO LAST STR WORD
	SETZM	PREPPN		;ZERO LAST PPN WORD

	MOVEI	T1,NRIB*.FXLND	;WORDS FOR UFD & SFD RIBS
	PUSHJ	P,UCORE		;GET IT
	  POPJ	P,		;LOSE--BACK TO BACKUP
	MOVEM	P1,ADRLST	;SAVE FOR LATER

	MOVE	P2,S.SSNM##	;[237] SAVE SET SPECIFIED?
	JUMPE	P2,RSTREC	;[237] PUNT, IF NOT SPECIFIED
	CAME	P2,[ASCII/all/]	;[237] SEE IF LOWER CASE ALL
	CAMN	P2,[ASCII/ALL/]	; AND NOT "ALL"
	JRST	RSTREC		;NO--PUNT
;HERE TO FIND THE USER SPECIFIED SAVE SET ON TAPE

SPCSET:	PUSHJ	P,XMTAIN	;GET RECORD
	  SKIPA			;HERE ON EOF OR KILL
	JRST	SAVSET		;SEE IF SAVE SET RECORD
	TXNE F,FL$KIL		;SEE IF USER TYPED KILL
	POPJ P,			;YES, RETURN TO BACKUP
	TXNN F,FL$EF2		;EOT?
	JRST SPCSET		;NO, CONTINUE
	WARN$N (SNF,Save set not found)
	OUTSTR	S.SSNM##	;TELL WHICH
	OUTSTR	CRLF		;
	POPJ P,			;LOSE

SAVSET:	MOVE	T1,G$TYPE(MH)	;GET RECORD TYPE
	CAIE	T1,T$CON	;CONTINUE SAVE?
	CAIN	T1,T$BEG	;START OF SAVE?
	SKIPA			;YES
	JRST	SPCSET		;NEITHER--KEEP GOING

	MOVEI	T3,M(MH)	;START OF DATA AREA
	ADD	T3,G$LND(MH)	;END OF NON-DATA PORTION
	CAILE	T3,MTBFSZ(MH)	;RANGE CHECK, IN CASE JUNK ON TAPE
	MOVEI	T3,MTBFSZ(MH)	;USE MAX
	SKIPA	T1,MDATA	;LOAD START ADDRESS
FNDSSN:	ADD	T1,(T1)		;POINT TO NEXT BLOCK
	CAIG	T3,(T1)		;SEE IF DONE
	JRST	SPCSET		;YES, SAVE SET NOT SPECIFIED ON TAPE, SO REJECT
	HLRZ	T2,(T1)		;GET BLOCK TYPE CODE
	CAIE	T2,O$SSNM	;RIGHT ONE?
	JRST	FNDSSN		;NO, KEEP LOOKING

;HERE TO SEE IF SAVE SET NAMES MATCH (IGNORE UPPER/LOWER CASE DIFFERENCES)

	HRRZ	P1,(T1)		;GET LENGTH OF SSNAME BLOCK
	SOS	P1		;MINUS CONTROL WORD
	IMULI	P1,5		;GET COUNT OF CHARACTERS
	MOVSI	T3,440700	;MAKE ASCII BYTE POINTER TO USER SSNAME
	HRRI	T3,S.SSNM##	;ADDRESS OF USER SUPPLIED NAME
	ADDI	T1,1		;STEP TAPE POINTER
	HRLI	T1,440700	;MAKE ASCII BYTE POINTER TO TAPE SSNAME
CHKSSN:	SOJL	P1,SPCSET	;REJECT IF TAPE OVERFLOW
	ILDB	T2,T1		;GET CHARACTER FROM TAPE
	CAIL	T2,"a"		;SEE IF LOWER CASE ALPHABETIC
	CAILE	T2,"z"		; ...
	SKIPA			;NOT.
	SUBI	T2,40		;CONVERT TO UPPER CASE
	ILDB	T4,T3		;GET CHARACTER FROM USER SSNAME
	CAIL	T4,"a"		;SEE IF LOWER CASE ALPHABETIC
	CAILE	T4,"z"		; ...
	SKIPA			;NOT.
	SUBI	T4,40		;CONVERT TO UPPER CASE
	CAME	T2,T4		;COMPARE CHARACTERS
	JRST	SPCSET		;NO MATCH
	SKIPE	T2		;DONE IF NULL FOUND
	JRST	CHKSSN		;LOOP FOR MORE CHARACTERS
	PUSHJ	P,LSTXXX	;LIST RECORD
	SETZM	S.SSNM##	;[265] DON"T LOOK FOR THIS ONE AGAIN
;HERE TO GET A TAPE RECORD AND DISPATCH BY RECORD TYPE

RSTREC:	PUSHJ	P,XMTAIN	;GET A BUFFER
	  JRST	[TXNE	F,FL$EF2;EOT?
		 AOSA	(P)	; YES--GIVE OPERATION DONE RETURN
		 TXNE	F,FL$KIL ;/KILL?
		 PJRST	HOLDRL	;[342] RELEASE HOLD CHANNEL AND RETURN
		 JRST RSTREC]	;CONTINUE

	MOVE	T1,G$TYPE(MH)	;GET RECORD TYPE
	CAIN	T1,T$END	;END OF SAVE?
	JRST	HAVEND		;YES

	CAIN	T1,T$UFD	;IS IT UFD DATA?
	JRST	[PUSHJ	P,HAVUFD;YES--CREATE RIB
		 JRST	RSTREC]	;CONTINUE

	CAIN	T1,T$FIL	;IS IT FILE DATA?
	JRST	HAVFIL		;YES--CHECK IT OUT

	CAIE	T1,T$CON	;CONTINUATION OF SAVE SET?
	CAIN	T1,T$BEG	;START OF NEW SAVE SET?
	JRST	[PUSHJ P,LSTXXX	;[515] YES, LIST IT AND
		 JRST  RSTREC]  ;[515] CONTINUE

	JUMPLE	T1,NOSUCH	;UNRECOGNIZABLE RECORD TYPE
	CAIG	T1,T$MAX	;KNOW OF IT?
	JRST	RSTREC		;YES--CONTINUE READING

NOSUCH:	WARN$N	(URT,Unknown record type)
	PUSHJ	P,OCTOUT	; ..
	OUTSTR	CRLF		;<CR><LF>
	JRST	RSTREC		;GET NEXT
;HERE IF HAVE T$END TYPE RECORD IN BUFFER

HAVEND:	PUSHJ	P,LSTXXX	;LIST RECORD
	MOVE	T1,S.SSNM##	;SAVE SET SPECIFIED?
	CAME	T1,[ASCII/all/]	;[237] NOT "all"
	CAMN	T1,[ASCII/ALL/]	; AND NOT "ALL"
	JRST	RSTREC		;NO--KEEP GOING
	PUSHJ	P,HOLDRL	;[342] RELEASE ANYTHING ON HOLD CHANNEL
	JRST	CPOPJ1		;YES--THIS MUST BE END
;+
;<HAVUFD IS A SUBROUTINE CALLED TO RECREATE THE DIRECTORY <RIB FROM
;THE CURRENT TAPE <T$UFD RECORD. ^OUPUT PLACED AT <ADRLST _+ (36 _* LEVEL).
;^THE <RIB IS USED IF IT IS NECESSARY TO CREATE THE DIRECTORY
;IN ORDER TO RESTORE THE FILE TO THE USER SPECIFIED PATH.
;-

HAVUFD:	SKIPE	S.INTR##	;SEE IF /INTERCHANGE,
	POPJ	P,		;YES, IGNORE T$UFD RECORDS
	PUSHJ	P,SAVE3		;MAKE SOME ROOM
	SKIPL	P2,D$LVL(MH)	;GET UFD LEVEL
	CAILE	P2,.FXLND-1	;SEE IF LEVEL IN RANGE
	POPJ	P,		; IF NOT, DROP RECORD
	IMULI	P2,NRIB		;WORDS PER RIB
	ADD	P2,ADRLST	;ADD IN BASE ADDRESS

;HERE TO RE-CREATE DIRECTORY RIB FROM T$UFD RECORD

	MOVE	P3,MDATA	;GET START OF DATA
	ADD	P3,G$LND(MH)	;POINT TO END
	SKIPA	P1,MDATA	;GET START ADDRESS AND SKIP
GETRIB:	ADD	P1,(P1)		;ADD LENGTH OF NON-DATA BLOCK
	CAIG	P3,(P1)		;END OF NON-DATA YET?
	POPJ	P,		;YES--DROP RECORD
	HLRZ	T1,(P1)		;GET BLOCK TYPE CODE
	HRRZS	P1		;PREVENT ILL MEM REF AT RSTRIB	[207]
	CAIE	T1,O$FILE	;IS IT O$FILE?			[216]
	JRST	GETRI1		;NO				[216]
	SETZM	(P2)		;INITIALIZE RIB BLOCK		[216]
	HRLI	T2,(P2)		; --				[216]
	HRRI	T2,1(P2)	; --				[216]
	BLT	T2,NRIB-1(P2)	; DOIT				[216]
	TXO	F,FL$SKP	;[232] SKIP .RBEST RENAME IF UFD
	PUSHJ	P,RSTRIB	;CONVERT TO RIB
	TXZ	F,FL$SKP	;[232] RESET .RBEST SKIP
GETRI1:	HLRZ	T1,(P1)		;GET BLOCK TYPE BACK		[216]
	CAIE	T1,O$DIRT	;IS IT O$DIRT?
	JRST	GETRIB		;NO--LOOP

;HERE TO FILL IN PROTECTION AND QUOTAS FROM O$DIRT BLOCK

	ADDI	P1,1		;POINT TO DIRECTORY DATA
	LDB	T1,[POINTR (D$PROT(P1), AC$OWN)];GET OWNER ACCESS
	LSH	T1,3		;SHIFT PROGRAMMER PROTECTION
	LDB	T2,[POINTR (D$PROT(P1), AC$GRP)];GET GROUP ACCESS
	IOR	T1,T2		;UNITE PROGRAMMER & PROJECT PROTECTIONS
	LSH	T1,3		;POSITION PROTECTIONS
	LDB	T2,[POINTR (D$PROT(P1), AC$WLD)];GET WORLD ACCESS
	IOR	T1,T2		;UNITE
	DPB	T1,[POINTR (.RBPRV(P2), RB.PRV)];SET RIB PROTECTION

	MOVE	T1,D$QTF(P1)	;GET FCFS LOGGED IN QUOTA IN WORDS
	IDIVI	T1,200		;COMPUTE QUOTA IN BLOCKS
	SKIPE	T2		;SEE IF OVERFLOW
	AOS	T1		;YES, ONE MORE BLOCK
	MOVEM	T1,.RBQTF(P2)	;SET QUOTA IN RIB
	MOVE	T1,D$QTO(P1)	;GET LOGGED OUT QUOTA IN WORDS
	IDIVI	T1,200		;COMPUTE QUOTA IN BLOCKS
	SKIPE	T2		;SEE IF OVERFLOW
	AOS	T1		;YES, ONE MORE BLOCK
	MOVEM	T1,.RBQTO(P2)	;SET QUOTA IN RIB
	POPJ	P,		;RETURN
;+
;^A BRANCH TO <HAVFIL OCCURS TO HANDLE FILE DATA RECORDS. ^MUST HAVE
;START OF FILE RECORD, UNLESS </RESUME WAS TYPED. ^FILE IDENTIFICATION
;INFO IS READ FROM THE <O$NAME BLOCK, OR THE RECORD HEADER IF RESUMING.
;^THEN THE USER'S SPECS AND SWITCHES ARE CHECKED AGAINST THE TAPE FILE,
;AND <RSTFIL IS CALLED IF THE TAPE FILE SHOULD BE RESTORED.
;-

HAVFIL:	MOVX	T1,GF$SOF	;START OF FILE?
	TDNN	T1,G$FLAG(MH)	;SEE IF FLAG SET
	JRST	[SKIPE	S.WRIT## ;NOT. SEE IF /NOWRITE
		 SKIPN	S.RSUM## ;UNLESS /RESUME,
		 JRST	RSTREC   ;DROP RECORD
		 SETZ	P2,	;FLAG TO USE RECORD HEADER INFO
		 JRST	GETINF] ;GO GET INFO FROM TAPE RECORD HEADER

	MOVE	P2,MDATA	;GET ADDRESS OF START OF DATA
	HLRZ	T1,(P2)		;GET BLOCK TYPE
	CAIE	T1,O$NAME	;SHOULD BE O$NAME BLOCK
	JRST	RSTREC		;BALK IF NOT

	MOVEI	P1,1(P2)	;FIRST O$NAME SUB-BLOCK
	HRRZ	T1,(P2)		;LENGTH OF O$NAME BLOCK
	ADD	P2,T1		;POINT TO END OF O$NAME BLOCK

;HERE TO GET THE PATH INFO FROM THE O$NAME BLOCK OR RECORD HEADER IF P2 = 0.

GETINF:	MOVSI	T1,'DSK'	;SET DSK AS DEVICE FOR INTERCHANGE MODE
	TXNE	F,FL$CHK	;[403] UNLESS /CHECK
	MOVSI	T1,'ALL'	;[403] THEN USE ALL
	SKIPE	T2,S.INTR##	;SEE IF INTERCHANGE MODE
	MOVEM	T1,CSTR		; YES--SET DEVICE
	JUMPG	T2,GETNAM	; AND SKIP COPYING PATH INFO FROM TAPE

	MOVEI	T1,.FCDEV	;INDICATE DATA TYPE
	PUSHJ	P,GETDAT	;GET DEVICE NAME
	MOVEM	T1,CSTR		;STORE

	MOVE	SP,S.FRST	; ADDRESS OF SPECS		[175]
	PUSHJ	P,SETSTR	;[262] GET FLAG WORD
GETIN1:	MOVSI	T2,-.FXLND	;START AT UFD LEVEL		[175]
GETPTH:	SAVE$	T2		;SAVE C(T2)
	MOVEI	T1,.FCDIR(T2)	;INDICATE WHICH DIRECTORY
	PUSHJ	P,GETDAT	;GET DIRECTORY NAME
	RSTR$	T2		;RESTORE C(T2)
	MOVEM	T1,PTHBLK+.PTPPN(T2);STORE
	SKIPE	T1		;DONE IF NULL
	AOBJN	T2,GETPTH	;LOOP
	MOVEM	T1,PTHBLK+.PTPPN(T2); ZERO THE REST OF PTHBLK	[177]
	AOBJN	T2,.-1		; DO IT				[177]
GETNAM:	MOVEI	T1,.FCNAM	;INDICATE FILE NAME
	PUSHJ	P,GETDAT	;GET FROM O$NAME BLOCK
	MOVEM	T1,CNAM		;STORE
	SETOM	CNAMSW		;[416] STORE
	MOVEI	T1,.FCEXT	;INDICATE EXTENSION
	PUSHJ	P,GETDAT	;GET EXTENSION
	MOVEM	T1,CEXT		;STORE

;HERE TO CHECK FOR /INITIAL

	SKIPE	S.INTR##	;SEE IF /INTERCHANGE
	JRST	ININAM		;YES, IGNORE ANY INITIAL PATH
	SKIPN	T1,S.INIT+.FXDEV;SEE IF ANY INITIAL DEVICE
	JRST	GOTINI		;NO
	MOVE	T2,CSTRFL	;GET STRUCTURE FLAG
	CAME	T1,CSTR		;SEE IF EXACT MATCH
	TDNE	T2,S.INIT##+FX$STR;OR IF STR FLAGGED
	SKIPA			;YES, CHECK PATH
	JRST	RSTREC		;NO, DROP THIS FILE

	MOVSI	T1,-.FXLND	;CHECK ENTIRE PATH
	SETZ	T2,		;ZILCH
INIPTH:	SKIPN	T3,S.INIT+.FXDIR(T2)	;SEE IF ANY INITIAL DIRECTORY
	JRST	ININAM			;DONE, CHECK FILE NAME
	CAME	T3,PTHBLK+.PTPPN(T1)	;MATCH?
	JRST	RSTREC			;NO, DROP THIS FILE
	ADDI	T2,2			;NEXT
	AOBJN	T1,INIPTH		;LOOP FOR ALL

ININAM:	MOVE	T1,S.INIT+.FXNAM;GET INITIAL FILE NAME, IF ANY
	CAME	T1,CNAM		;MATCH?
	JUMPN	T1,RSTREC	;NO, DROP THIS FILE
	HLLZ	T2,S.INIT+.FXEXT;GET INITIAL EXT, IF ANY
	CAME	T2,CEXT		;MATCH?
	SKIPN	S.INIT+.FXEXT	;NO, OKAY IF NO EXTENSION SET
	SKIPA			;MATCH FOUND
	JRST	RSTREC		;DROP FILE
	SETZM	S.INIT+.FXDEV	;ZILCH
	SETZM	S.INIT+.FXNAM	; ...
	SETZM	S.INIT+.FXEXT	; ...

GOTINI:	MOVE	SP,S.FRST##	;ADDRESS OF SPECS

;HERE TO CHECK IF FILE MATCHES USER SPECS AND SWITCHES

RSTVER:	PUSHJ	P,SETSTR	;[503][262] SET UP STRUCTURE MASK
	SKIPE	S.INTR##	;SEE IF /INTERCHANGE
	JRST	RSTVR2		;YES--ONLY FILE NAME AND EXT MUST MATCH
	PUSHJ	P,VER0		;COMPARE			[175]
	  JRST	RSTNOT		;NO GOOD
	AOS	FX$CNT+FX$LEN(SP);INDICATE SPEC DIRECTORY FOUND
RSTVR2:	PUSHJ	P,VER2		;COMPARE
	  JRST	RSTNOT		;NO GOOD

	SKIPE	S.RSUM##	;SEE IF /RESUME
	JRST	RSTYES		; YES, SKIP FOLLOWING
	HLRZ	T1,(P2)		;GET TYPE CODE OF NEXT BLOCK
	CAIE	T1,O$FILE	;CHECK IF O$FILE IS NEXT
	JRST	RSTYES		;NO--ASSUME GOOD
	MOVE	P1,P2		;COPY POINTER TO O$FILE
	MOVEI	T4,1(P1)	;MAKE POINTER TO ATTRIBUTE DATA

	MOVE	T1,A$LENG(T4)	;GET LENGTH IN BYTES
	SETZ	T2,		;ZILCH
	MOVE	T3,A$MODE(T4)	;GET MODE FROM TAPE
	CAIG	T3,.IOASL	;SEE IF ASCII
	IDIVI	T1,5		;CALCULATE LENGTH IN WORDS
	SKIPE	T2		;SEE IF REMAINDER,
	AOS	T1		; YES, ONE MORE WORD
	MOVEM	T1,CWSIZE	;STORE

	MOVE	T1,A$WRIT(T4)	;GET CREATION DATE/TIME
	MOVEM	T1,CCDATI	;STORE
	MOVE	T1,A$REDT(T4)	;GET ACCESS DATE
	MOVEM	T1,CADATI	;STORE
	MOVE	T1,A$MODT(T4)	;GET MONITOR SET DATE/TIME
	MOVEM	T1,CMDATI	;STORE FOR CHECKER

	PUSHJ	P,CHKLIM	;CHECK LIMITS
	  JRST	RSTNOT		;NO GOOD
	  JRST	[TXON  F,FL$D75;INDICATE GOOD ONLY BECAUSE /DATE75
		 MOVEM SP,D75ADR;SAVE POINTER
		 JRST  RSTNOT]	;AND PROCEED, NOT COUNTING MATCH


RSTYES:	TXON	F,FL$MAT	;MATCH?
	MOVEM	SP,SAVADR	;STORE
	AOS	FX$CNT(SP)	;COUNT MATCH

RSTNOT:	ADDI	SP,FX$LEN*2	;NEXT SPEC
	CAMGE	SP,S.LAST##	;SKIP IF DONE
	JRST	RSTVER		;CONTINUE

	TXZN	F,FL$MAT	;MATCH?
	JRST	[TXZN F,FL$D75	;NO--SEE IF DATE75 WIN
		 JRST LSTFNS	;NO--CONTINUE SCANNING TAPE	[172]
		 MOVE SP,D75ADR	;YES--RETRIEVE ADDRESS
		 JRST .+2]	;AND ACCEPT MATCH
	MOVE	SP,SAVADR	;YES. GET COPY OF ADDR

	PUSH	P,.JBFF##	;SAVE JOBFF
	PUSHJ	P,RSTFIL	;RESTORE FILE
	POP	P,.JBFF##	;RESTORE JOBFF

	TXZ	F,FL$OPN	;FILE WAS CLOSED
	SETZM	SUSDF		; CLEAR SUPERSEDING DSK FILE FLAG	[206]
	TXNE	F,FL$KIL	;SEE IF OPERATOR SAID KILL
	JRST	RSTKIL		;YES
	SETZM	CNAMSW		;[416] INDICATE DONE WITH FILE FOR MASTRX ROUTINE
	JRST	CNTSCN		;CONTINUE SCANNING TAPE		[172]
;HERE TO PRINT FILES ON STRUCTURES NOT IN SYS SEARCH LIST

LSTFNS:	SKIPN	S.PRNT##	;IS THIS A "PRINT" OPERATION?	[172]
	JRST	CNTSCN		;  NO				[172]
	MOVE	T1,MDATA	;GET START OF DATA BLOCK	[172]
	ADDI	T1,200		;POINT TO O$FILE BLOCK		[172]
	PUSHJ	P,LSTFIL	;LIST THE FILE			[172]

CNTSCN:	MOVE	T1,S.SSNM##	;SAVE SET SPECIFIED?
	CAME	T1,[ASCII/all/]	; lower case ALL?		[350]
	CAMN	T1,[ASCII/ALL/]	;AND NOT ALL?
	JRST	RSTREC		;NO--CONTINUE SCANNING TAPE FOR FILES

;HERE IF SAVE SET NAME IS NOT "ALL". STOP SCANNING IF SPEC LIST SATISFIED.

	SKIPA	SP,S.FRST##	;START ADDRESS OF SPEC LIST

SPCSAT:	ADDI	SP,FX$LEN*2	;NEXT SPEC PAIR
	CAML	SP,S.LAST##	;END OF SPEC LIST?
	JRST	CPOPJ1		;YES - ALL DONE
	SKIPE	S.INTR		;[273] DON'T CHECK SFD IF /INTER
	JRST	SPCSA2		;[273]
	MOVSI	T2,-.FXLND+1	;[270] NUMBER OF SFD'S
	HRRI	T2,.FXDIR+FX$LEN+2(SP)	;[270] CHECK FIRST FOR WILD SFD
SPCSA4:	SETCM	T1,1(T2)		;[270] ANY WILD SFD"S
	JUMPN	T1,RSTREC		;[270]YES, GO BACK
	ADDI	T2,1			;[270] INDEX BY TWO
	AOBJN	T2,SPCSA4		;[270] TO CHECK THEM ALL
	PUSHJ	P,SETSTR	;[262] SET UP STRUCTURE MASK
	SKIPN	FX$CNT+FX$LEN(SP);THIS DIRECTORY FOUND?
	JRST	RSTREC		;NO--CONTINUE LOOKING
	MOVE	T1,.FXDEV+FX$LEN(SP)	;[352] YES--IF INPUT DEVICE IS
	CAME	T1,[SIXBIT/ALL/]	;[352] ALL OR DSK, MAYBE ANOTHER
	CAMN	T1,[SIXBIT/DSK/]	;[352] STRUCTURE LATER.
	JRST	SPCSA2		;[352] YES--DONE ONLY IF FILE FOUND
	PUSHJ	P,VER0		;[352][175] NO--IS IT THE CURRENT ONE?
	  JUMPE	T1,SPCSAT	;NO--PASSED IT			[204]
SPCSA2:	SKIPN	FX$CNT(SP)	;[273] YES--ANY FILES MATCH YET?
	JRST	RSTREC		;NO--KEEP LOOKING
	MOVE	T1,.FXNMM+FX$LEN(SP);GET FILENAME MASK
	CAME	T1,[-1]		;ANY WILD CARDS?
	JRST	RSTREC		;YES--CONTINUE SCAN OF TAPE
	HRRO	T1,.FXEXT+FX$LEN(SP);GET EXTENSION MASK
	CAME	T1,[-1]		;WILD?
	JRST	RSTREC		;YES--CONTINUE SCAN OF TAPE
	JRST	SPCSAT		;NO--THIS SPEC SATISFIED


RSTKIL:	MOVEI	T1,[ASCIZ/
	% RESTORE ABORTED
/]
	TXNE	F,FL$CHK	;SEE IF /CHECK
	MOVEI	T1,[ASCIZ/
	% CHECK ABORTED
/]
	SKIPE	S.PRNT##	;SEE IF /PRINT			[212]
	MOVEI	T1,[ASCIZ/
	% PRINT ABORTED
/]				;				[212]
	SKIPE	S.LIST		;SKIP IF LISTING NOT NEEDED
	PUSHJ	P,LSTMSG	;SEND MESSAGE TO LISTING FILE
	PJRST	HOLDRL		;[342] RELEASE HOLD CHANNEL AND RETURN
;+
;<RSTFIL IS A ROUTINE TO RESTORE A SINGLE FILE FROM TAPE TO DISK.
;-

RSTFIL:	SETZM	CHKCNT		;CLEAR CHECK COUNT
	TXZ	F,FL$PAO!FL$TPE!FL$DFE	;[254] ZERO FLAGS
	MOVE	T1,G$FLAG(MH)	;[254] GET FLAG WORD
	TXNE	T1,GF$DFE	;[254] DFE BIT ON?
	 PUSHJ	P,DSKDFE	;[254] YES, PRINT MESSAGE

	SKIPN	S.WRIT##	;SEE IF /NOWRITE
	TXNE	F,FL$CHK	; UNLESS /CHECK
	SKIPA			;NEED TO INITIALIZE DISK CHANNELS
	JRST	TYPOUT		;SKIP UNNECESSARY CODE

;HERE TO COMPUTE ALIAS NAMES AND INITIALIZE CHANNELS

	PUSHJ	P,XALIAS	;DO ALIASING

;NOTE: CODE WHICH WAS HERE PREVIOUSLY TO SCATTER FILES
;OVER FILE STRUCTURE UNITS WAS DELETED SINCE 5.02 AND
;LATER MONITORS PERFORM THIS FUNCTION AUTOMATICALLY

	MOVEI	T1,.IODMP	;DUMP MODE
	SKIPN	T2,ACSTR	;[406] LOAD ALIAS STR NAME
	MOVSI	T2,'DSK'	;[406] DEFAULT TO DSK:
	SETZ	T3,		;NO BUFFERS

	OPEN	UFD,T1		;OPEN CHANNEL FOR CREATING UFD
	  JRST	FAIL0		;LOSE

	MOVX	T1,.IOBIN+UU.LBF;BUFFERED BINARY
	MOVSI	T3,DSKHDR	;OUTPUT BUFFER HEADER ADDDRESS
	TXNE	F,FL$CHK	;IF /CHECK
	MOVSS	T3		; USE FOR INPUT BUFFER

	OPEN	FILE,T1		;OPEN CHANNEL FOR WRITING FILE
	  JRST	FAIL0		;LOSE
	TXO	F,FL$OPN	;NOW DISK OUTPUT FILE IS OPEN

	CAMN	T2,HCSTR	;[342] ALIAS STRUCTURE SAME AS HELD STR?
	JRST	RSTFL2		;[342] YES - JUMP TO CHECK PPN
	PUSHJ	P,HOLDRL	;[342] NO - RELEASE THIS STR
	OPEN	HOLD,T1		;[342] OPEN ALIAS STR ON HOLD CHANNEL
	  JRST	FAIL0		;[342] LOSE
	MOVEM	T2,HCSTR	;[342] REMEMBER HOLD STRUCTURE
RSTFL2:	MOVE	T1,APATH+.PTPPN	;[342] GET ALIAS PPN
	CAMN	T1,HCPPN	;[342] SAME AS CURRENTLY HELD PPN?
	JRST	RSTFL3		;[342] YES - JUMP TO FILL ENTER BLOCK
	MOVEM	T1,HCPPN	;[342] NO - REMEMBER THE PPN CHANGE
	TXZE	F,FL$HUF	;[342] ZERO THE HELD-FLAG
	CLOSE	HOLD,CL.ACS	;[342] AND CLOSE PREVIOUS FILE IF ANY
RSTFL3:				;[342]
	SETZM	EXLFIL		;CLEAR EXTENDED ENTER BLOCK
	MOVE	T1,[EXLFIL,,EXLFIL+1]; ...
	BLT	T1,EXLFIL+NRIB-1; ...

;HERE TO FILL ENTER BLOCK

	MOVE	T1,ACNAM	;GET ALIAS FILE NAME
	MOVEM	T1,EXLFIL+.RBNAM;STORE IN ENTER BLOCK
	MOVE	T1,ACEXT	;GET ALIAS EXTENSION
	MOVEM	T1,EXLFIL+.RBEXT;STORE
	MOVE	T1,APATH+.PTPPN ;ASSUME UFD LEVEL
	SKIPE	APATH+.PTPPN+1	;SEE IF FILE LOCATED IN SFD,
	MOVEI	T1,APATH	; YES--SET UP PATH POINTER
	MOVEM	T1,EXLFIL+.RBPPN;STORE
	MOVEI	P2,EXLFIL	;SET ADDRESS OF ENTER BLOCK
	SKIPN	S.RSUM##	;SKIP IF RESUMING
	PUSHJ	P,RSTRIB	;FILL IN O$FILE INFO

;HERE TO RESET ENTER VALUES FROM USER OUTPUT SWITCHES

	LDB	T1,[POINTR (.FXMOD(SP),FX.PRO)] ;GET /PROTECTION FROM USER
	LDB	T2,[POINTR (.FXMOM(SP),FX.PRO)] ;SEE IF SET
	SKIPN	T2		;[356] IF NOT SET,
	LDB	T1,[POINTR (EXLFIL+.RBPRV,RB.PRV)] ;[356] GET FILE PROT.
	MOVEM	T1,PRNAME	;[356] AND REMEMBER FOR LATER
	SKIPN	S.FFA		;[356] AM I [1,2]
	JRST	LBL1		;[356] NO, ALWAYS DO PROT. RENAME
	TRZN	T1,400		;[356] FILDAE PROTECTED?
	JUMPN	T1,LBL		;[356] NO, DON'T NEED RENAME UNLESS PROT <000>
	TROA	T1,377		;[356] YES, NEED PROT. RENAME
LBL1:	MOVEI	T1,100		;[356] NON-OPR RENAMED PROTECTION
	TXO	F,FL$PRN	;[356] FLAG RENAME NEEDED
LBL:	DPB	T1,[POINTR (EXLFIL+.RBPRV,RB.PRV)] ;[356] SET IN FILE
	SKIPE	T1,.FXVER(SP)	;[316] GET /VERSION FROM USER, IF SET
	CAMN	T1,[-1]		;[316]
	  SKIPA			;[316]
	MOVEM	T1,EXLFIL+.RBVER ;SET IN ENTER BLOCK

	SKIPLE	T1,.FXEST(SP)	;IF /ESTIMATE,
	JRST	[IDIVI	T1,200	;CONVERT TO BLOCKS
		 SKIPE	T2	;SEE IF OVERFLOW
		 AOS	T1	; YES, ONE MORE BLOCK
		 MOVEM	T1,EXLFIL+.RBEST; SET IN ENTER BLOCK
		 JRST	.+1]	;PROCEED

	SKIPE	S.RSUM##	;SEE IF /RESUME,
	JRST	TYPOUT		; YES--ASSUME NORMAL HANDLING
;HERE TO CHECK WHETHER COPY ON DISK (IF ANY) SHOULD BE SUPERSEDED

CHKSUP:	SETZM	SUSDF		;CLEAR THE SUPERSEDING DSK FILE FLAG [206]
	MOVEI	T1,1		;SEE IF SUPERSEDE ALLOWED
	CAMN	T1,S.SUPR##	;SKIP IF NOT ALWAYS
	TXNE	F,FL$CHK	;OR IF /CHECK
	SKIPA			;YES--NEED LOOKUP
	JRST	TYPOUT		;NO--MUCH FASTER

	MOVX	T1,.PTSCN	;[501] NO SCAN
	MOVEM	T1,APATH+.PTSWT	;[501] SET PATH SWITCH

	MOVE	T1,EXLFIL+.RBNAM;GET FILE NAME
	HLLZ	T2,EXLFIL+.RBEXT;GET EXT
	MOVEI	T3,0		;ZERO PRIV WORD
	MOVE	T4,EXLFIL+.RBPPN ;GET DIRECTORY

	LOOKUP	FILE,T1		;FILE THERE?
	JRST	NOFILE		;NOPE--GOODIE

	TXNN	F,FL$HUF	;[436][342] IF NOT ALREADY HELD,
	PUSHJ	P,HOLDIT	;[436][342] HOLD THIS PPN

	TXNE	F,FL$CHK	;IF /CHECK
	JRST	TYPOUT		;ASSUME NORMAL HANDLING

	MOVE	T1,S.SUPR##	;GET SUPERSEDE CODE
	CAIN	T1,3		;SKIP IF NOT SUPERSEDE NEVER
	JRST	CLSFL1		;CLOSE FILE CORRECTLY

	LDB	T1,[POINTR (T3,RB.CRT)] ;GET CREATION TIME
	IMULI	T1,^D60000	;CONVERT TO MILLISECONDS
	LDB	T2,[POINTR (T2,RB.CRX)] ;GET EXTENSION
	LSH	T2,^D12		;SHIFT OVER
	LDB	T3,[POINTR (T3,RB.CRD)] ;GET BASE
	IOR	T2,T3		;UNITE
	PUSHJ	P,CONVDT	;CONVERT TO SMITHSONIAN DATE/TIME
	CAML	T1,CCDATI	;SKIP IF DISK FILE OLDER THAN TAPE FILE	[203]
	JRST	CLSFL1		;DO NOT OVER-WRITE

	SETOM	SUSDF		;SET "SUPERSEDE DSK FILE" FLAG	[206]
	CLOSE	FILE,		;DONE WITH FILE

NOFILE:	TXNN	F,FL$CHK	;NEW FILE--SEE IF /CHECK
	JRST	TYPOUT		;NOT /CHECK
	WARN$N (CNF,Check file not on disk)
	MOVEI	P1,EXLFIL	;ADDRESS OF LOOKUP BLOCK
	PUSHJ	P,GUUO		;TYPE INFO

;HERE TO CLOSE FILE CHANNEL AND NOT DISTURB FILE

CLSFL1:	CLOSE	FILE,CL.ACS	;CLOSE
	POPJ	P,		;RETURN
TYPOUT:	SKIPN	S.TYMS##	;SKIP IF TYPE OUT NEEDED
	JRST	TYPE2		;FORGET IT

	SKIPE	S.INTR##	;SEE IF INTERCHANGE MODE
	JRST	TYPE1		;SKIP TYPING PATH INFO IF SO
	MOVE	T1,CSTR		;GET CURRENT STR
	MOVE	T2,PTHBLK+.PTPPN;GET CURRENT PPN
	CAMN	T1,PRESTR	;SAME AS LAST?
	JRST	STRSAM		;STRUCTURE IS THE SAME
	MOVEM	T1,PRESTR	;STORE NEW LAST STR
	MOVEM	T2,PREPPN	;STORE
	PUSHJ	P,TYLPPN	;TYPE LAST PPN
	OUTCHR	TAB		;TAB OVER
	MOVE	T1,PRESTR	;GET STR NAME
	PUSHJ	P,SIXOUT	;TYPE STR NAME
	JRST	TYPE0		;TYPE <CR><LF> AND RESTORE

STRSAM:	CAMN	T2,PREPPN	;SAME AS LAST?
	JRST	TYPE1		;YES--RESTORE
	MOVEM	T2,PREPPN	;NO--REPLACE
	PUSHJ	P,TYLPPN	;TYPE LAST PPN
TYPE0:	OUTSTR	CRLF		;<CR><LF>

TYPE1:	MOVEI	T1,2		;SEE IF FILE NAMES WANTED
	CAMN	T1,S.TYMS##	;SKIP IF NOT
	PUSHJ	P,TYPFIL	;TYPE FILE NAME

TYPE2:	SKIPE	S.WRIT##	;UNLESS /NOWRITE
	SKIPN	T1,S.RSUM##	;[357] SEE IF RESUMING
	JRST	NEWFIL		;NOT. ASSUME NORMAL HANDLING

	MOVEI	T2,4		;[357] NBR ARGS FOR LOOKUP
	MOVEM	T2,EXLFIL	;[357] STORE
	MOVE	T2,EXLFIL+.RBPPN  ;[357][261] SAVE PATH TO FILE
	LOOKUP	FILE,EXLFIL	;FILE SHOULD BE THERE
	JRST	[MOVEM	T2,EXLFIL+.RBPPN  ;[357][261] RESTORE PATH
		SETZM	S.RSUM##	;[261] NOT. ZILCH
		 CAIG	T1,1	;[357] IF REALLY NEW FILE,
		 JRST	NEWFIL	;THAT'S OK
		 JRST	ELFIL]	;OTHERWISE DIE
	MOVEM	T2,EXLFIL+.RBPPN	;[357][261] RESTORE PATH

	TXNN	F,FL$HUF	;[342] IF NOT ALREADY HELD,
	PUSHJ	P,HOLDIT	;[342] HOLD THIS PPN
	TXNE	F,FL$CHK	;SEE IF /CHECK,
	JRST	POSITN		;YES, GO POSITION
	ENTER	FILE,EXLFIL	;RE-ENTER TO UPDATE
	 JRST	[MOVEM	T2,EXLFIL+.RBPPN	;[357][261] RESTORE PATH
		SETZM	S.RSUM##	;[261] ZILCH
		 JRST	EEFIL]	;ABORT FILE
	MOVEM	T2,EXLFIL+.RBPPN	;[261] RESTORE PATH

POSITN:	PUSHJ	P,.USETI	;[357] POSITON USING FILOP
	PUSHJ	P,GENDBF	;GENERATE DISK BUFFERS
;HERE TO READ IN THE DISK BLOCK OR DO A DUMMY OUTPUT

	PUSHJ	P,@DSKIO	;EXEC
	  JRST	XFRERR		;DISK I/O ERROR
	  JRST	RSMERR		;EOF--MEANS USER GAVE INVALID CHECKPOINT

	PUSHJ	P,TYPRSM	;TYPE RESUMING MESSAGE
	MOVE	T1,S.RSUM##	;BLOCK NBR WE ARE STARTING AT
	MOVEM	T1,THSRDB	;STORE
	ADDI	T1,CP$INC	;ADD ON CHECKPOINT INCREMENT
	MOVEM	T1,CHKPNT	;SET NEW CHECKPOINT
	MOVE	T1,F$PCHK(MH)	;GET PATH CHECKSUM FROM TAPE RECORD HEADER
	MOVEM	T1,PTHCHK	;SAVE IT
	SETZM	S.RSUM##	;ZILCH
	JRST	CNTFIL		;CONTINUE WITH FILE

NEWFIL:	MOVE	T1,MDATA	;GET START OF DATA AREA
	ADDI	T1,200		;POINT TO O$FILE BLOCK
	PUSHJ	P,LSTFIL	;LIST THIS FILE
	TXNN	F,FL$PSI	;SKIP FOLLOWING IF PSI ENABLED
	JRST	[PUSHJ	P,OPRCMD##;HANDLE ANY TTY INPUT
		  TXO	F,FL$KIL;RETURN HERE IF OPERATOR SAID KILL
		 JRST	.+1]	;CONTINUE
	TXNE	F,FL$CHK	;IF /CHECK,
	JRST	NORMAL		; SKIP ENTER
	SKIPN	S.WRIT##	;IF /NOWRITE,
	POPJ	P,		; QUIT NOW
;HERE TO ENTER TAPE FILE ON DISK
	ADDI	P1,1		;ADJUST TO POINT TO ATTRIBUTE DATA
	MOVE	T1,A$MODE(P1)	;GET CREATION MODE
	MOVEI	T2,FILE		;[510] CHANNEL
	DEVCHR	T2,		;[510] GET LEGAL DATA MODES FOR THIS DEVICE
	MOVEI	T3,1		;[510] ADJUST TO THE BIT POSITION OF THE GIVEN
	LSH	T3,(T1)		;[510]  DATA MODE TO COMPARE WITH BITS RETURNED
	TDNE	T2,T3		;[510]  BY THE DEVCHR.  IS THE DATA MODE KNOWN?
	JRST	NEWFL1		;[510] YES
	WARN$N	(IDM,Illegal data mode)	;[510] NO. REPORT IT
	PUSHJ	P,OCTOUT	;[510] DISPLAY ILLEGAL DATA MODE
	OUTSTR	[ASCIZ / for file /]	;[510]

	PUSHJ	P,TYSPEC	;[510] DISPLAY FILE SPEC
	OUTSTR	[ASCIZ/, assuming image mode.
/]
	MOVEI	T1,.IOIMG	;[510] USE BINARY MODE INSTEAD
NEWFL1:	SETSTS	FILE,(T1)	;FAKE OUT FILSER
	PUSHJ	P,SETFIL	;SET UP FILE ENTER BLOCK
	SETOM	UNIQUE		;RESET UNIQUE EXTENSION NUMBER
NEWFL2:	MOVX	T1,RB.NSE	;NON-SUPERSEDING ENTER BIT
	MOVX	T2,FX.SUP	;SCAN SUPERSEDE BIT
	SKIPG	S.UNIQ##	;UNIQUE EXTENSIONS?
	TDNE	T2,.FXMOD(SP)	;/ERSUPERSEDE?
	IORM	T1,EXLFIL+.RBCNT ;YES
	MOVE	T1,EXLFIL+.RBPPN	;[261] SAVE PATH
	ENTER	FILE,EXLFIL	;TRY TO ENTER FILE
	 JRST	[MOVEM	T1,EXLFIL+.RBPPN	;[261] RESTORE PATH
		JRST	CHKWHY	]	;[261] LOSE--TRY TO RECOVER
	MOVEM	T1,EXLFIL+.RBPPN	;[261] RESTORE PATH
	SKIPGE	UNIQUE		;WAS A UNIQUE EXTENSION GENERATED?
	JRST	NORMAL		;NO
	WARN$N	(UEG,<Unique extension generated>)
	PUSH	P,P1		;SAVE P1
	MOVEI	P1,EXLFIL	;POINT TO ENTER BLOCK
	PUSHJ	P,GUUO		;TYPE FILESPEC
	POP	P,P1		;RESTORE P1
;FILE IS ENTERED. HERE TO TRANSFER ACTUAL DATA.

NORMAL:	PUSHJ	P,GENDBF	;GENERATE DISK BUFFERS

	MOVE	P2,MDATA	;GET ADDRESS OF START OF DATA
	ADD	P2,G$LND(MH)	;SKIP NON-DATA SECTION
	MOVE	P1,G$SIZ(MH)	;GET NUMBER OF WORDS OF DATA
	MOVE	T1,BBSN		;GET NUMBER OF DISK BLOCKS/TAPE BLOCK
	SUBI	T1,2		;SKIP OVERHEAD STUFF
	IMULI	T1,200		;CONVERT TO WORDS
	CAMLE	P1,T1		;IS IT IN RANGE?
	MOVE	P1,T1		;NO, USE DEFAULT

	MOVEI	T1,CP$INC	;CHECKPOINT INCREMENT
	MOVEM	T1,CHKPNT	;SET INITIAL CHECKPOINT

	MOVEI	T1,1		;START WITH RELATIVE-DATA-BLOCK 1
	MOVEM	T1,THSRDB	;STORE
	MOVE	T1,F$PCHK(MH)	;GET FILE PATH CHECKSUM
	MOVEM	T1,PTHCHK	;SAVE FOR LATER CHECKING

	PUSHJ	P,@DSKIO	;GET FIRST BUFFER OR DO DUMMY OUTPUT
	  JRST	XFRERR		;ERROR RETURN
	  JRST	DSKEO1		;EOF RETURN--NULL DISK FILE

	JUMPLE	P1,CHKEND	;MAY BE 0 BLOCKS ON TAPE

XFR1:	MOVSI	T1,(P2)		;TAPE BUFFER ADDRESS
	HRRI	T1,(DBUF)	;DISK BUFFER ADDRESS
	MOVEI	T2,177(T1)	;USUALLY 200 WORDS
	CAIL	P1,200		;SEE IF LAST BLOCK IN THIS TAPE BLOCK
	JRST	XFR2		;NO
	MOVEI	T2,-1(T1)	;OFFSET
	ADD	T2,P1		;POINT TO END

XFR2:	XCT	DSKBLT		;COPY OR COMPARE DATA
	TXNN	F,FL$CHK	;SEE IF /CHECK
	CAIL	P1,200		;IS THIS THE LAST BLOCK?
	JRST	NOTLST		;NO--CONTINUE
;HERE IF LAST DISK BLOCK TO BE WRITTEN
	MOVE	T1,[CLOSE FILE,CL.ACS!CL.DAT] ;[304]WILL DO OUTPUT
	MOVN	T2,P1		;NEGATE WORD COUNT
	ADDM	T2,DSKHDR+.BFCTR;DECREMENT BYTE COUNT
	MOVNS	T2		;NEGATE AGAIN
	PUSHJ	P,ALTDSK	;PERFORM SPECIAL OUTPUT
	  JRST	XFRERR		;ERROR RETURN
	  HALT	.		;***TEMP***
	JRST	ENDBLK		;DONE
;HERE TO CONTINUE TRANSFERING FILE

NOTLST:	MOVEI	T1,200		;ADJUST BYTE POINTER
	ADDM	T1,DSKHDR+.BFPTR
	MOVE	T1,DSKHDR+.BFCTR;ADJUST BYTE COUNT
	SUBI	T1,200
	MOVEM	T1,DSKHDR+.BFCTR
	ADDI	DBUF,200	;NEXT BLOCK IN DISK BUFFER
	SOSE	NDBLIB		;IS THIS THE LAST BLOCK OF THE DISK BUFFER?
	JRST	ENDBLK		;NO. CONTINUE TRANSFERRING
	PUSHJ	P,@DSKIO	;ADVANCE DISK BUFFER
	  JRST	XFRERR		;ERROR RETURN
	  JRST	DSKEOF		;EOF RETURN
ENDBLK:	ADDI	P2,200		;ADVANCE TO NEXT BLOCK IN RECORD
	SUBI	P1,200		;SUBTRACT BLOCK FROM DATA COUNT
	AOS	T1,THSRDB	;COUNT OF BLOCKS+1 SO FAR
	PUSHJ	P,RSTCKP	;DO CHECKPOINTING, IF NEEDED
	  JRST	XFRERR		;ERROR DURING CHECKPOINTING
	JUMPG	P1,XFR1		;SEE IF ANY MORE TO GO

CHKEND:	MOVX	T1,GF$EOF	;EOF BIT
	TDNN	T1,G$FLAG(MH)	;SKIP IF ON
	JRST	NOTNEW		;GO GET NEXT TAPE RECORD
	TXNN	F,FL$CHK	;SEE IF /CHECK,
	JRST	XFRDON		;NO--TRANSFER DONE

;HERE IF /CHECK AND TAPE EOF

	WARN$N	(CTS,Check tape file shorter)
	PUSHJ	P,DOWHAT	;TYPE FULL FILE PATH
	MOVEI	T1,[ASCIZ/	% Check tape file shorter
/]
	SKIPE	S.LIST		;SEE IF LISTING NEEDED
	PUSHJ	P,LSTMSG	;SEND MESSAGE TO LISTING FILE
	JRST	XFRDON		;DONE

;HERE TO GET ANOTHER TAPE RECORD

NOTNEW:	PUSHJ	P,XMTAIN	;GET NEXT RECORD
	  JRST	XFRERR		;EOF OR KILL--ABORT FILE

	MOVE	T1,G$TYPE(MH)	;GET RECORD TYPE

	CAIE	T1,T$BEG	;START OF SAVE SET?
	CAIN	T1,T$CON	;CONTINUATION OF SAVE SET?
	JRST	[PUSHJ	P,LSTXXX;YES, LIST IT
		 JRST	NOTNEW]	;AND CONTINUE

	CAIN	T1,T$UFD	;SEE IF DIRECTORY RECORD
	JRST	[PUSHJ	P,HAVUFD;CREATE RIB
		 JRST	NOTNEW]	;CONTINUE

	CAIN	T1,T$LBL	;SEE IF LABEL RECORD
	JRST	NOTNEW		;***TEMP***

	CAIE	T1,T$FIL	;SHOULD BE FILE DATA
	JRST	XFRERR		;NO GOOD
;HERE TO CONTINUE WITH FILE SINCE RECORD CONTAINS FILE DATA.

CNTFIL:	MOVE	T1,G$FLAG(MH)	;[254] GET FLAG WORD
	TXNE	T1,GF$DFE	;[254] DFE BIT ON?
	 PUSHJ	P,DSKDFE	;[254] YES, PRINT MESSAGE
	SKIPG	P1,G$SIZ(MH)	;[254] ANY SIGNIFICANT DATA?
	JRST	CHKEND		;NO--SHOULD BE END
	MOVE	P2,BBSN		;GET NUMBER OF DISK BLOCKS/TAPE BLOCK
	IMULI	P2,200		;CONVERT TO WORDS
	CAMLE	P1,P2		;SEE IF IN RANGE
	MOVE	P1,P2		;NO, USE MAXIMUM
	MOVE	P2,MDATA	;START OF DATA

	MOVX	T1,GF$SOF	;SEE IF START OF FILE,
	TDNE	T1,G$FLAG(MH)	;TEST FLAG IN HEADER
	JRST	MISMAT		;YES--MISSED EOF
	MOVE	T1,F$PCHK(MH)	;GET PATH CHECKSUM
	CAME	T1,PTHCHK	;MAKE SURE STILL ON SAME FILE
	JRST	MISMAT		;NOT. BAD NEWS

	MOVE	T1,F$RDW(MH)	;GET TAPE RELATIVE DATA WORD
	ASH	T1,-7		;CALCULATE RELATIVE DATA BLOCK
	AOS	T1		; ...
	CAMN	T1,THSRDB	;[321] BLOCK EXPECTED?
	JRST	XFR1		;[321] YES - GO USE IT
	MOVE	T2,THSRDB	;LOAD NEEDED DISK BLOCK NUMBER
	MOVE	T3,BBSN		;GET NUMBER OF DISK BLOCKS/TAPE BLOCK
	ADDI	T3,(T1)		;COMPUTE END OF RANGE
	CAML	T2,T1		;NEEDED BLOCK GE FIRST BLOCK IN RECORD?
	CAML	T2,T3		;AND ALSO LT FIRST BLOCK IN NEXT RECORD?
	JRST	NOTINB		;[321] NO - GO RESET DISK POINTERS

	SUB	T2,T1		;YES, GET DIFFERENCE
	ASH	T2,7		;MULTIPLY BY 200 WORDS
	ADD	P2,T2		;ADD TO DATA ADDRESS POINTER
	SUB	P1,T2		;AND SUBTRACT FROM WORD COUNT
	JUMPG	P1,XFR1		;GO TRANSFER OVER
	JRST	CHKEND		;FOUL UP?


NOTINB:	CAML	T1,THSRDB	;[321] PREVIOUS BLOCK?
	JRST	RSTMSD		;[321] NO - WE MISSED A BLOCK
	MOVEM	T1,THSRDB	;[321] YES - RESET FILE INDEX
	WARN$N	(PBR,Prior block repeated) ;[321] WARN USER
	MOVEI	T2,[ASCIZ/rewriting from /] ;[321] MESSAGE
	TXNE	F,FL$CHK	;[321] CHECKING?
	MOVEI	T2,[ASCIZ/rereading from /] ;[321] YES - OTHER MSG
	OUTSTR	@T2		;[321]
	PUSHJ	P,TYEFIL	;[321] TELL USER FILE AND BLOCK
	JRST	RSTUST		;[321] GO USE IT
RSTMSD:	PUSH	P,T1		;[321] SAVE THIS RDB
	WARN$N	(BMT,Block missed on tape, expected) ;[321] WARN
	PUSHJ	P,TYEFIL	;[321] DISPLAY FILE AND BLOCK
	POP	P,THSRDB	;[321] UPDATE FILE INDEX
	WARN$N	(FLC,File continuing with) ;[321] SHOW WHAT'S HAPPENING
	PUSHJ	P,TYEFIL	;[321] DITTO
RSTUST:	MOVE	T1,THSRDB	;[321] GET BLOCK NUMBER
	TXNN	F,FL$CHK	;[321] CHECKING?
	JRST	[PUSHJ	P,.USETO	;[357] NO, USETO DISK FILE (USE FILOP)
		 JRST	XFR1]		;[321] GO USE THE BLOCK
	WAIT	FILE,		;[521] WAIT FOR DISK ACTIVITY TO SETTLE DOWN
	MOVSI	T2,400000	;[321] CHECKING - MUST RESET INPUT BUFFERS
	IORB	T2,DSKHDR	;[321] FLAG BUFFER RING AS EMPTY
	MOVEI	T3,NDSKBF	;[321] PREPARE TO INVALIDATE ALL BUFFERS
RSTUS1:	SOJL	T3,RSTUS2	;[321] ANY MORE BUFFERS?
	MOVE	T4,(T2)		;[321] YES - GET NEXT .BFHDR
	TXZ	T4,BF.IOU	;[321] CLEAR THE USE BIT
	MOVEM	T4,(T2)		;[321] PUT IT BACK
	MOVE	T2,T4		;[321] POINT TO NEXT BUFFER IN RING
	JRST	RSTUS1		;[321] GO CHECK FOR MORE
RSTUS2:	PUSHJ	P,.USETI	;[357] RING INVALIDATED, USETI DISK FILE
	PUSHJ	P,@DSKIO	;[321] READ THE NEEDED DISK BLOCK
	  JRST	XFRERR		;[321] PROBLEM WITH DISK
	  JRST	DSKEO1		;[321] NO MORE DISK FILE
	JRST	XFR1		;[321] GO COMPARE

DSKEOF:	SUBI	P1,200		;COUNT LAST DATA XFR
DSKEO1:	MOVX	T1,GF$EOF	;SEE IF LAST TAPE BLOCK
	TDNE	T1,G$FLAG(MH)	;EOF BIT SHOULD BE ON
	JUMPLE	P1,XFRDON	;IF NO TAPE DATA LEFT, OK
	WARN$N (CDS,Check disk file shorter)
	MOVEI	P1,EXLFIL	;ADDRESS OF LOOKUP BLOCK
	PUSHJ	P,GUUO		;TYPE FULL FILE PATH
	MOVEI	T1,[ASCIZ/	% Check disk file shorter
/]
	SKIPE	S.LIST		;SKIP IF LISTING NOT NEEDED
	PUSHJ	P,LSTMSG	;SEND MESSAGE TO LISTING
				;FALL INTO XFRDON
;HERE WHEN RESTORE OR CHECK DONE. CLOSE DISK FILE AND CHECK.

XFRDON:	SKIPLE	.FXEST(SP)	;[232] /ESTIMATE SET?
	SKIPA	T1,[CLOSE FILE,CL.ACS!CL.DLL!CL.DAT]; [236] YES,LOAD PROPER CLOSE
	MOVE	T1,[CLOSE FILE,CL.ACS!CL.DAT]	;[236] NO,LOAD PROPER CLOSE
	TXNE	F,FL$PAO		;[232] PAO FLAG ON?
	TRZ	T1,CL.DLL		;[232] YES,CLEAR CL.DLL
	XCT	T1			;[232] EXECUTE UUO
	TXNE	F,FL$HUF	;[342] PPN HELD ALREADY?
	JRST	XFRDO2		;[342] YES - SKIP HOLDING STUFF
	PUSHJ	P,SETFIL	;[342] NO - RESET LOOKUP BLOCK
	PUSHJ	P,HOLDIT	;[342] AND CALL PPN HOLDER

XFRDO2:				;[342]
IFN FT$DBG,<			;[323]
	SETOM	FSZWDS		;[323] FLAG # WORDS UNDETERMINED
>;END IFN FT$DBG		;[323]
	TXNN	F,FL$CHK	;[260] SKIP IF /CHECK
	TXNN	F,FL$PRN!FL$EST		;[232] EITHER PROT. OR .RBEST TO BE RENAMED?
	JRST 	CONT			;[232] NO,SKIP AROUND RENAME LOGIC
	PUSHJ	P,SETFIL		;[232] YES,RESET ENTER BLOCK
	MOVE	T2,EXLFIL+.RBPRV	;[315] SAVE REAL CREATION DATE
	MOVE	T1,EXLFIL+.RBPPN	;[324] SAVE PATH
	MOVE	T3,EXLFIL+.RBEXT	;[354] SAVE HIGH ORDER CREATION BITS
	LOOKUP	FILE,EXLFIL		;[232] LOOKUP FILE
		JRST ELFIL		;[232] TELL USER BAD NEWS
	MOVEM	T3,EXLFIL+.RBEXT	;[354] REPLACE HIGH ORDER CREATION BITS
	MOVEM	T1,EXLFIL+.RBPPN	;[324] RESTORE PATH
	MOVEM	T2,EXLFIL+.RBPRV	;[315] REPLACE REAL CREATION DATE
IFN FT$DBG,<				;[323]
	MOVE	T2,EXLFIL+.RBSIZ	;[323] GET FILE SIZE IN WORDS
	MOVEM	T2,FSZWDS		;[323] SAVE IT
>;END IFN FT$DBG			;[323]
	TXNN	F,FL$PRN		;[354][232] PROTECTION TO BE RENAMED?
	JRST	XFRDO3			;[354] NO...
	SKIPE	T2,PRNAME		;[354] YES, GET ORIGINAL PROTECTION
	JRST	STPROT			;[354] JUMP IF NOT ZERO
	TXZE	F,FL$EPR		;[354] EOV?
	JRST	XFRDO3			;[354] YES
	SKIPN	S.INTR			;[354] INTERCHANGE MODE?
STPROT:	DPB	T2,[POINTR(EXLFIL+.RBPRV,RB.PRV)] ;[354][232] NO, SET IN BLOCK
XFRDO3:	TXNE	F,FL$EST		;[232] .RBEST TO BE RENAMED?
	JRST	[MOVE	T2,EST		;[232] YES,GET ORIGINAL .RBEST
		 SKIPG	.FXEST(SP)	;[232] IF /ESTIMATE SET RETURN
		 MOVEM	T2,EXLFIL+.RBEST ;[232] SET IN ENTER BLOCK
		 JRST	.+1]	;[232] RETURN
	MOVEI	T2,12			;[232] SHORTEN ENTE BLOCK
	MOVEM	T2,EXLFIL		;[232] SET IN BLOCK 
	RENAME	FILE,EXLFIL		;[232] RENAME THE FILE
	 PUSHJ	P,ERFIL		;[260] [232] GIVE WARNING MESSAGE
	MOVEM	T1,EXLFIL+.RBPPN	;[324] RESTORE PATH
	TXZ	F,FL$PRN!FL$EST		;[232] RESET RENAME FLAGS

CONT:	TXZE	F,FL$DFE	;[254] ANY DISK ERRORS WHEN SAVED?
	PUSHJ	P,DFETST	;[424][254] YES, PRINT ERROR MESSAGE
	TXNE	F,FL$CHK	;[254] SEE IF /CHECK
	JRST	[SKIPE	T1,CHKCNT;SEE IF ANY DIFFERENCES
		 SKIPN	S.LIST	;AND IF LISTING NEEDED
		 JRST	RLSFIL	;NO, SKIP LISTING COUNT
		 PUSHJ	P,LSTTAB;TAB OVER
		 PUSHJ	P,LSTDEC;LIST COUNT OF DIFFERENCES
		 MOVEI	T1,[ASCIZ \ difference(s) found
\]
		 PUSHJ	P,LSTMSG;SEND TO FILE
		 JRST	RLSFIL]	;SKIP SIZE CHECK

IFN FT$DBG,<
	SKIPE	S.INTR		;[323] INTERCHANGE MODE?
	  JRST	TAPERR		;[323] YES - SKIP SIZE CHECK IN CASE DUMPER
	MOVE	T1,FSZWDS	;[323] NO - GET FILE SIZE IN WORDS
	CAME	T1,[-1,,-1]	;[323] DO WE REALLY HAVE IT?
	  JRST	SIZCHK		;[323] YES - GO COMPARE SIZES.
				;[323] NO - MUST DO A LOOKUP
	PUSHJ	P,SETFIL	;RESET LOOKUP/ENTER BLOCK
	MOVE	T1,EXLFIL+.RBPPN	;[324] SAVE PATH
	LOOKUP	FILE,EXLFIL	;GET IT AGAIN
	  JRST	ELFIL		;OUCH
	MOVEM	T1,EXLFIL+.RBPPN	;[324] RESTORE PATH
	MOVE	T1,EXLFIL+.RBSIZ;GET FILE SIZE IN WORDS
SIZCHK:	CAMN	T1,CWSIZE	;SAME A