From:	CSBVAX::MRGATE!INFO-VAX-RELAY@KL.SRI.COM@SMTP  8-JUL-1988 20:08
To:	ARISIA::EVERHART
Subj:	routine to copy files (was: LIB$COPY_FILE)


Received: from omnigate.clarkson.edu by KL.SRI.COM with TCP; Thu 5 May 88 08:20:17-PDT
Received: by CLVMS (Jnet BSMTP V0.07) id 1564; Thu,  5 May 88 11:14 EDT
Date:     Thu,  5 May 88 11:14 EDT
From:     Art Stine - Network Engineer <ABSTINE@clvms.clarkson.edu>
Subject:  routine to copy files (was: LIB$COPY_FILE)
To:       INFO-VAX@kl.sri.com
Original_To:  INFO-VAX

     
I wrote this quick copy file routine a few years ago when i needed to
copy files from within a program without incurring the overhead of spawning.
     
art stine
network engineer
clarkson u
     
     
     
cut here------------------------------------------------------------------------
     
        .TITLE  Copy_File       Utility Routines
        .IDENT  "V01-001"
;++
;******************************************************************************
;
;       TITLE:          Copy_File
;
;       VERSION:        V01-001
;
;       FACILITY:       LIB - Utility Routines
;
;
;       ABSTRACT:
;
;               This routine allows the caller to copy one file to another.
;
;
;       ENVIRONMENT:
;
;               VAX-11 MACRO, user mode
;
;       AUTHOR:          A.B. Stine
;
;       CREATION DATE:   2-MAR-1986 17:33:53
;
;       MODIFIED BY:
;
;       V01-001         ABS      12-MAR-1986 12:39:03
;       Added MXV option to FAB for Create so that the version numbers
;       can be superseeded.
;
;******************************************************************************
;--
;++
;******************************************************************************
;
;       FUNCTIONAL DESCRIPTION:
;
;         This procedure copies the file specified by infile to the file
;         specified by outfile.
;
;       CALLING SEQUENCE:
;
;         status = LIB_COPY_FILE( infile, outfile );
;
;       RETURNS:
;
;            VMS USAGE : cond_value
;            TYPE      : longword (unsigned)
;            ACCESS    : write only
;            MECHANISM : by value
;
;       FORMAL ARGUMENT(S):
;
;            Argument  : infile
;            VMS USAGE : char_string
;            TYPE      : character string
;            ACCESS    : read only
;            MECHANISM : by descriptor
;            String specifying the input file to copy from. The infile argument
;            is the address of a descriptor pointing to the file specification
;            string for the input file.
;
;            Argument  : outfile
;            VMS USAGE : char_string
;            TYPE      : character string
;            ACCESS    : read only
;            MECHANISM : by descriptor
;            String specifying the output file to copy from. The outfile
;            argument is the address of a descriptor pointing to the file
;            specification string for the output file.
;
;       IMPLICIT INPUTS:
;
;               file specified by INFILE
;
;       IMPLICIT OUTPUTS:
;
;               file specified by OUTFILE
;
;       COMPLETION STATUS:
;
;         SS$_NORMAL (RMS$_NORMAL)
;               Procedure completed successfully; file was copied.
;
;         STR errors
;               See errors from STR$COPY_DX
;
;         RMS errors
;               See errors from $OPEN, $CONNECT, $READ, $WRITE,
;               $DISCONNECT, $CLOSE services
;
;         others
;               Unknown
;
;       SIDE EFFECTS:
;
;               Creates OUTFILE
;
;******************************************************************************
;--
        .PAGE
        .SUBTITLE       Library and Symbol Definitions
     
        .MACRO  .STR_DESCR      BUFNAM, BUFLEN
     
        .IF     LE      BUFLEN
                .ERROR  1
                .MEXIT
        .ENDC
        .IF     BLANK   BUFNAM
                .ERROR  2
                .MEXIT
        .ENDC
        .IF     GT      BUFLEN
                .IF     NB      BUFNAM
'BUFNAM'_D:     .WORD    BUFLEN
                .WORD    0
                .ADDRESS 'BUFNAM'
'BUFNAM':       .BLKB    BUFLEN
                .ENDC
        .ENDC
        .ENDM   .STR_DESCR
     
        .NOCROSS
        $RMSDEF
        $SSDEF
        BUFFER_SIZE = 512
        .CROSS
     
;*******************************************************************************
     
        .PAGE
        .SUBTITLE       RMS Data PSECT
        .PSECT          _RMS_Data, RD,WRT,NOEXE
     
INFILE_FAB:
        $FAB -
                FAC = <BIO, GET>, -
                XAB = INFILE_XAB
INFILE_RAB:
        $RAB -
                BKT = 0, -
                FAB = INFILE_FAB, -
                UBF = FILE_BUFFER, -
                USZ = BUFFER_SIZE
INFILE_XAB:
        $XABFHC
OUTFILE_FAB:
        $FAB -
                FAC = <BIO, PUT>, -
                FOP = <CBT,MXV>, -
                XAB = OUTFILE_XAB
OUTFILE_RAB:
        $RAB -
                BKT = 0, -
                FAB = OUTFILE_FAB, -
                RBF = FILE_BUFFER
OUTFILE_XAB:
        $XABFHC
     
     
;*******************************************************************************
     
        .PAGE
        .SUBTITLE       Pure Data PSECT
        .PSECT          _Pure_Data, RD,NOWRT,NOEXE
     
;*******************************************************************************
     
        .PAGE
        .SUBTITLE       Impure Data PSECT
        .PSECT          _Impure_Data, RD,WRT,NOEXE
     
        .STR_DESCR      INFILE, 255
        .STR_DESCR      OUTFILE, 255
     
FILE_BUFFER:
        .BLKB   BUFFER_SIZE
;*******************************************************************************
     
        .PAGE
        .SUBTITLE       Code PSECT
        .PSECT          _Code, RD,NOWRT,EXE
     
     
        .PAGE
        .SUBTITLE       LIB_Copy_File
        .ENTRY  LIB_COPY_FILE, ^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
     
        CMPB    #2, (AP)                ; make sure #args => 2
        BGEQ    BEGIN_COPY
        MOVL    #SS$_INSFARG, R0        ; return INSUFFICIENT ARGs
        RET
     
BEGIN_COPY:
        PUSHL   4(AP)                   ; copy INFILE passed to local
        PUSHAQ  INFILE_D                ; data area
        CALLS   #2, G^STR$COPY_DX
        BLBS    R0, 10$                 ; if no error, then continue
        RET                             ; else return
10$:
        PUSHL   8(AP)                   ; copy OUTFILE passed to local
        PUSHAQ  OUTFILE_D               ; data area
        CALLS   #2, G^STR$COPY_DX
        BLBS    R0, 20$                 ; if no error, then continue
        RET                             ; else return
     
20$:
        MOVAB   INFILE, -               ; set up filename for source file
                INFILE_FAB+FAB$L_FNA
        MOVB    INFILE_D, -
                INFILE_FAB+FAB$B_FNS
        MOVL    #0, -                   ; set initial LBN to start read
                INFILE_RAB+RAB$L_BKT
     
;++
; Open INFILE and OUTFILE for Block Mode I/O
;--
COPY_OPEN:
        $OPEN -                         ; open INFILE
                FAB = INFILE_FAB
        BLBS    R0, 10$                 ; if no error, then continue
        PUSHL   R0                      ; else, save error and exit
        BRW     COPY_EXIT
10$:
        $CONNECT -                      ; connect record stream for INFILE
                RAB = INFILE_RAB
        BLBS    R0, 20$                 ; if no error, then continue
        PUSHL   R0                      ; else, save error and exit
        BRW     COPY_EXIT1
20$:
        MOVC3   #FAB$C_BLN, -           ; move all FAB attitributes from
                INFILE_FAB, -           ; input file to output file
                OUTFILE_FAB
        MOVC3   #XAB$C_FHCLEN, -        ; move all file header attributes
                INFILE_XAB, -           ; from input file to output file
                OUTFILE_XAB
        MOVAL   OUTFILE_XAB, -
                OUTFILE_FAB+FAB$L_XAB   ; point outfile to its XAB
     
        CLRW    OUTFILE_XAB+XAB$W_VERLIMIT
                                        ; set no limit of #versions
        CLRW    OUTFILE_FAB+FAB$W_IFI   ; clear internal file id that was copied
        BISL2   #FAB$M_MXV, -           ; maximize version # of created file
                OUTFILE_FAB+FAB$L_FOP
        MOVAB   OUTFILE, -              ; set up filename for destination file
                OUTFILE_FAB+FAB$L_FNA
        MOVB    OUTFILE_D, -
                OUTFILE_FAB+FAB$B_FNS
        MOVL    #0, -                   ; set initial LBN to start write
                OUTFILE_RAB+RAB$L_BKT
        $CREATE -                       ; create OUTFILE
                FAB = OUTFILE_FAB
        BLBS    R0, 30$                 ; if no error, then continue
        PUSHL   R0                      ; else, save error and exit
        BRW     COPY_EXIT2
30$:
        $CONNECT -                      ; connect record stream for OUTFILE
                RAB = OUTFILE_RAB
        BLBS    R0, 40$                 ; if no error, then continue
        PUSHL   R0                      ; else, save error and exit
        BRW     COPY_EXIT3
40$:
;++
; Copy Loop - read block from INFILE, write block to OUTFILE
;--
COPY_READ:
        $READ -                         ; get block from INFILE
                RAB = INFILE_RAB
        BLBS    R0, COPY_WRITE          ; if no error, then goto write
CHECK_EOF:
        CMPL    R0, #RMS$_EOF           ; else if error = EOF then
        BNEQ    10$                     ;
        MOVL    #SS$_NORMAL, R0         ; set NORMAL status
10$:
        PUSHL   R0                      ; save error status
        BRW     COPY_EXIT4
     
COPY_WRITE:
        MOVW    INFILE_RAB+RAB$W_RSZ, - ; set record size for output
                OUTFILE_RAB+RAB$W_RSZ
        $WRITE -                        ; write record to OUTFILE
                RAB = OUTFILE_RAB
        BLBS    R0, COPY_READ           ; if no error, then goto read
        BRB     CHECK_EOF
;++
; Error handling and rundown
;--
COPY_EXIT4:
        $DISCONNECT -                   ; disconnect record stream for OUTFILE
                RAB = OUTFILE_RAB
COPY_EXIT3:
        $CLOSE -                        ; close OUTFILE
                FAB = OUTFILE_FAB
COPY_EXIT2:
        $DISCONNECT -                   ; disconnect record stream for INFILE
                RAB = INFILE_RAB
COPY_EXIT1:
        $CLOSE -                        ; close INFILE
                FAB = INFILE_FAB
COPY_EXIT:
        POPL    R0                      ; retrieve error status saved
        RET                             ; return to caller
     
        .END
-------
