.Title NetBackup - DECnet based backup .Ident /V01.000/ .Enable SUP .Default Displacement, Word .Subtitle Introduction ;+ ; ; ----- NetBackup: DECnet based backup ; ; ; Facility: ; ; VAX/VMS system management, backup procedures. ; ; Abstract: ; ; This routine will operate as a network server to catch save ; sets from systems which do not have tape drives. This routine ; requires some help from NetBackup.COM. ; ; Environment: ; ; VAX/VMS V4.0 or later, NETMBX privilege. ; ; ; Version: V01.000 ; Date: 21-Jan-1986 ; ; Gerard K. Newman 21-Jan-1986 ; Science Applications International ; 800 Oak Ridge Turnpike ; Oak Ridge, TN 37830 ; (615) 482-9031 ; ; ; Modifications: ; ; ;- .Page .Subtitle Local definitions .NoCross ; Save a tree $IODEF ; I/O function codes $RMSDEF ; RMS junk $SSDEF ; System service codes .Cross ; Turn CREF back on ; Local definitions ; Block size from the backup save set header. This information taken from ; BACKDEF.SDL, fiche 9 B15. $DEFINI BBH ; Start of the Backup Block Header $DEF BBH$W_SIZE .Blkw ; Size of this structure $DEF BBH$W_OPSYS .Blkw ; Operating system ID $DEF BBH$W_SUBSYS .Blkw ; Subsystem ID $DEF BBH$W_APPLIC .Blkw ; Application ID $DEF BBH$L_NUMBER .Blkl ; Block sequence number $DEF BBH$B_FILL1 .Blkb 20 ; Spares $DEF BBH$K_COMMON ; Length of the common header $DEF BBH$W_STRUCLEV ; Structure level, which is composed of: $DEF BBH$B_STRUCVER .Blkb ; The structure version $DEF BBH$B_STRUCLEV .Blkb ; The structure level $EQU BBH$K_LEVEL1 257 ; Structure level 1, version 1 $DEF BBH$W_VOLNUM .Blkw ; Volume number $DEF BBH$L_CRC .Blkl ; Block CRC $DEF BBH$L_BLOCKSIZE .Blkl ; Block size $DEF BBH$L_FLAGS .Blkl ; Flags $DEF BBH$T_SSNAME .Blkb 32 ; .Ascic save set name $DEF BBH$W_FID ; Current FID $DEF BBH$W_FID_NUM .Blkw ; File header number $DEF BBH$W_FID_SEQ .Blkw ; File sequence number $DEF BBH$W_FID_RVN ; Relative volume number $DEF BBH$B_FID_RVN .Blkb ; Relative volume number $DEF BBH$B_FID_RVX .Blkb ; Relative volume file header extension (?) $DEF BBH$W_DID ; Current DID $DEF BBH$W_DID_NUM .Blkw ; Directory header number $DEF BBH$W_DID_SEQ .Blkw ; Directory sequence number $DEF BBH$W_DID_RVN ; Directory relative volume number $DEF BBH$B_DID_RVN .Blkb ; Ditto $DEF BBH$B_DID_RVX .Blkb ; Relative volume file header extension (?) $DEF BBH$T_FILENAME .Blkb 128 ; Current file name $DEF BBH$B_RTYPE .Blkb ; Record type of the current file $DEF BBH$B_RATTRIB .Blkb ; Record attributes $DEF BBH$W_RSIZE .Blkw ; Record size of the current file $DEF BBH$B_BKTSIZE .Blkb ; Bucket size of the current file $DEF BBH$B_VFCSIZE .Blkb ; VFC size of the current file $DEF BBH$W_MAXREC .Blkw ; Maximum record size of the current file $DEF BBH$L_FILESIZE .Blkl ; Size of the current file in blocks $DEF BBH$T_RESERVED2 .Blkb 22 ; Reserved $DEF BBH$W_CHECKSUM .Blkw ; Header checksum $DEF BBH$K_LENGTH ; Length of the Backup Block Header $DEFEND BBH ; End of the Backup Block Header ; Buffer size we allocate to catch blocks from the network. Do not make ; this bigger than 32K, as VMS can't cope with transfers larger than that ; from DECnet. MAX_BUFF = 32768 ; Largest buffer we care to cope with .Page .Subtitle Impure storage .Psect IMPURE_DATA NOEXE, RD, WRT, PIC, NOSHR, PAGE ; RMS control blocks to create the file on our tape drive. This is easier ; to do than trying to figure out how to use the ACP QIO interface. TAPE_FAB: $FAB - ; FAB for the tape drive DNM = , - ; Default file name FAC = , - ; Write access FNA = NODE_BUFF, - ; File name address FOP = , - ; Let me do the I/O RFM = ; Fixed length records ; Random data NET_CHAN: .Blkw ; Channel to the network IOSB: .Blkq ; Random I/O status block BUFF_DESC: .Long MAX_BUFF, 0 ; Buffer descriptor NODE_DESC: .Long 64 ; Node name .Address NODE_BUFF ; descriptor NODE_BUFF: .Blkb 64 ; Space for our node name .Page .Subtitle Pure storage .Psect PURE_DATA NOEXE, RD, NOWRT, PIC, SHR, PAGE ; Random strings SYS$NET: .Ascid "SYS$NET" ; To confirm our connect SYS$BACKUP: .Ascid "SYS$BACKUP" ; Saveset Name .Page .Subtitle Entry point .Psect CODE EXE, RD, NOWRT, PIC, SHR, PAGE .Entry START, ^M<> ; Entry here ; First things first. Confirm our DECnet connection. $ASSIGN_S DEVNAM = SYS$NET, - ; Assign a channel CHAN = NET_CHAN ; to confirm the connection BLBC R0, 10$ ; Die if we can't ; Allocate a buffer big enough to hold onto backup save sets PUSHAL BUFF_DESC+4 ; Return the address here PUSHAL BUFF_DESC ; We need this much memory CALLS #2, G^LIB$GET_VM ; Go allocate some memory BLBC R0, 10$ ; Sigh. MOVQ BUFF_DESC, R10 ; Address our buffer ; Read the Backup Block Header record to find out how big to make the ; blocks, etc. $QIOW_S CHAN = NET_CHAN, - ; Read from the network FUNC = #IO$_READLBLK, - ; to find out how big IOSB = IOSB, - ; to make our blocks P1 = (R11), P2 = R10 ; Put the data here MOVZWL IOSB, R0 ; Grab the I/O status BLBS R0, 20$ ; Branch if we won 10$: BRW 50$ ; Leave if error ; Fill in the block size and maximum record size. 20$: $FAB_STORE FAB = TAPE_FAB, - ; Store the BLS = BBH$L_BLOCKSIZE(R11), - ; Block size MRS = BBH$L_BLOCKSIZE(R11) ; Maximum record size ; Use the node name as the save set name, as the save set name in the ; BBH looks a lot like "Task = NetBackup", which is no good at all. $TRNLOG_S LOGNAM = SYS$BACKUP, - ; Get the NCB RSLBUF = NODE_DESC, - ; Put it here RSLLEN = NODE_DESC ; Tell me how long it is MOVQ NODE_DESC, R0 ; Grab a copy of the descriptor LOCC #^A/:/, R0, (R1) ; See if we can find a node name SUBL3 R0, NODE_DESC, R1 ; Compute the length of the node name $FAB_STORE FAB = TAPE_FAB, - ; Store the FNS = R1 ; Save set name size ; Create the file, but let me do I/O to it. Use RMS, as it's a lot easier ; than the QIO interface to the ACPs... $CREATE FAB = TAPE_FAB ; Create the file BLBS R0, 40$ ; Branch into the rest of this if ; we won RET ; Lose otherwise ; Ok - now all we have to do is to loop copying records from the network ; into our file. When we deassign the channel at the end of all of this we ; should be just fine. 30$: $QIOW_S CHAN = NET_CHAN, - ; Read another record FUNC = #IO$_READLBLK, - ; from the network IOSB = IOSB, - ; I/O status here P1 = (R11), P2 = R10 ; Buffer is here MOVZWL IOSB, R0 ; Get the I/O status BLBC R0, 50$ ; Maybe the other guy quit 40$: MOVZWL IOSB+2, R1 ; Get the size of the buffer to write $QIOW_S CHAN = TAPE_FAB+FAB$L_STV, - ; Write out FUNC = #IO$_WRITEVBLK, - ; the next block IOSB = IOSB, - ; on the tape P1 = (R11), P2 = R1 ; ... MOVZWL IOSB, R0 ; Get the I/O status BLBS R0, 30$ ; Loop if successful 50$: CMPL #SS$_LINKDISCON, R0 ; Did the other guy go away? BEQL 60$ ; If EQL yes, not an error CMPL #SS$_LINKABORT, R0 ; This happens sometimes, too BNEQ 70$ ; Must be a real error 60$: MOVL #SS$_NORMAL, R0 ; Else not an error 70$: RET ; Back to DCL (all deassigns done ; for me) .End START