mirror of
https://github.com/microsoft/MS-DOS.git
synced 2025-04-08 10:51:45 +01:00
1001 lines
26 KiB
NASM
1001 lines
26 KiB
NASM
page 80,132
|
||
; SCCSID = @(#)copy.asm 1.1 85/05/14
|
||
; SCCSID = @(#)copy.asm 1.1 85/05/14
|
||
TITLE COMMAND COPY routines.
|
||
|
||
; MODIFICATION HISTORY
|
||
;
|
||
; 11/01/83 EE Added a few lines at the end of SCANSRC2 to get multiple
|
||
; file concatenations (eg copy a.*+b.*+c.*) to work properly.
|
||
; 11/02/83 EE Commented out the code in CPARSE which added drive designators
|
||
; to tokens which begin with path characters so that PARSELINE
|
||
; will work correctly.
|
||
; 11/04/83 EE Commented out the code in CPARSE that considered paren's to be
|
||
; individual tokens. That distinction is no longer needed for
|
||
; FOR loop processing.
|
||
; 11/17/83 EE CPARSE upper case conversion is now flag dependent. Flag is
|
||
; 1 when Cparse is called from COPY.
|
||
; 11/17/83 EE Took out the comment chars around code described in 11/04/83
|
||
; mod. It now is conditional on flag like previous mod.
|
||
; 11/21/83 NP Added printf
|
||
; 12/09/83 EE CPARSE changed to use CPYFLAG to determine when a colon should
|
||
; be added to a token.
|
||
; 05/30/84 MZ Initialize all copy variables. Fix confusion with destclosed
|
||
; NOTE: DestHand is the destination handle. There are two
|
||
; special values: -1 meaning destination was never opened and
|
||
; 0 which means that the destination has been openned and
|
||
; closed.
|
||
; 06/01/84 MZ Above reasoning totally specious. Returned things to normal
|
||
; 06/06/86 EG Change to fix problem of source switches /a and /b getting
|
||
; lost on large and multiple file (wildcard) copies.
|
||
; 06/09/86 EG Change to use xnametrans call to verify that source and
|
||
; destination are not equal.
|
||
|
||
|
||
.xlist
|
||
.xcref
|
||
INCLUDE comsw.asm
|
||
INCLUDE DOSSYM.INC
|
||
INCLUDE comseg.asm
|
||
INCLUDE comequ.asm
|
||
.list
|
||
.cref
|
||
|
||
|
||
DATARES SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN VERVAL:WORD
|
||
EXTRN RSRC_XA_SEG:WORD ;AN030;
|
||
DATARES ENDS
|
||
|
||
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN BADCD_ptr:word
|
||
EXTRN COPIED_ptr:word
|
||
EXTRN Extend_buf_ptr:word ;AN000;
|
||
EXTRN Extend_buf_sub:byte ;AN000;
|
||
EXTRN file_name_ptr:word
|
||
EXTRN INBDEV_ptr:word ;AC000;
|
||
EXTRN msg_disp_class:byte ;AN000;
|
||
EXTRN overwr_ptr:word
|
||
TRANDATA ENDS
|
||
|
||
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN ALLSWITCH:WORD
|
||
EXTRN ARGC:BYTE
|
||
EXTRN ASCII:BYTE
|
||
EXTRN BINARY:BYTE
|
||
EXTRN BYTCNT:WORD
|
||
EXTRN CFLAG:BYTE
|
||
EXTRN comma:byte
|
||
EXTRN CONCAT:BYTE
|
||
EXTRN concat_xa:byte ;AN000;
|
||
EXTRN copy_num:word ;AC000;
|
||
EXTRN CPDATE:WORD
|
||
EXTRN CPTIME:WORD
|
||
EXTRN cpyflag:byte ;AC000;
|
||
EXTRN CURDRV:BYTE
|
||
EXTRN DESTBUF:BYTE
|
||
EXTRN DestClosed:BYTE
|
||
EXTRN DESTFCB:BYTE
|
||
EXTRN DESTFCB2:BYTE
|
||
EXTRN DESTHAND:WORD
|
||
EXTRN DESTINFO:BYTE
|
||
EXTRN DESTISDIR:BYTE
|
||
EXTRN DESTSIZ:BYTE
|
||
EXTRN DESTSWITCH:WORD
|
||
EXTRN DESTTAIL:WORD
|
||
EXTRN DESTVARS:BYTE
|
||
EXTRN DIRBUF:BYTE
|
||
EXTRN expand_star:byte
|
||
EXTRN FILECNT:WORD
|
||
EXTRN FIRSTDEST:BYTE
|
||
EXTRN FRSTSRCH:BYTE
|
||
EXTRN INEXACT:BYTE
|
||
EXTRN MELCOPY:BYTE
|
||
EXTRN MELSTART:WORD
|
||
EXTRN msg_flag:byte ;AN022;
|
||
EXTRN NOWRITE:BYTE
|
||
EXTRN NXTADD:WORD
|
||
EXTRN objcnt:byte
|
||
EXTRN one_char_val:byte ;AN000;
|
||
EXTRN parse_last:word ;AN018;
|
||
EXTRN PLUS:BYTE
|
||
EXTRN plus_comma:byte
|
||
EXTRN RDEOF:BYTE
|
||
EXTRN RESSEG:WORD
|
||
EXTRN SCANBUF:BYTE
|
||
EXTRN SDIRBUF:BYTE
|
||
EXTRN src_xa_size:word ;AN000;
|
||
EXTRN src_xa_seg:word ;AN000;
|
||
EXTRN SRCBUF:BYTE
|
||
EXTRN SRCHAND:WORD
|
||
EXTRN SRCINFO:BYTE
|
||
EXTRN SRCISDEV:BYTE
|
||
EXTRN SRCPT:WORD
|
||
EXTRN SRCSIZ:BYTE
|
||
EXTRN SRCTAIL:WORD
|
||
EXTRN SRCVARS:BYTE
|
||
EXTRN srcxname:byte
|
||
EXTRN STARTEL:WORD
|
||
EXTRN string_ptr_2:word
|
||
EXTRN TERMREAD:BYTE
|
||
EXTRN TPA:WORD
|
||
EXTRN USERDIR1:BYTE
|
||
EXTRN WRITTEN:WORD
|
||
EXTRN xa_cp_out:byte ;AN030;
|
||
EXTRN xa_list_attr:word ;AC030;
|
||
TRANSPACE ENDS
|
||
|
||
|
||
; ******************************************
|
||
; COPY CODE
|
||
;
|
||
|
||
TRANCODE SEGMENT PUBLIC BYTE
|
||
|
||
EXTRN CERROR:NEAR
|
||
EXTRN COPERR:NEAR
|
||
EXTRN TCOMMAND:NEAR
|
||
|
||
PUBLIC COPY
|
||
|
||
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
|
||
break Copy
|
||
assume ds:trangroup,es:trangroup
|
||
|
||
COPY:
|
||
; First order of buisness is to find out about the destination
|
||
;
|
||
; initialize all internal variables
|
||
;
|
||
xor ax,ax
|
||
mov copy_num,ax
|
||
mov SrcPt,AX
|
||
mov SrcTail,AX
|
||
mov CFlag,AL
|
||
mov NxtAdd,AX
|
||
mov DestSwitch,AX
|
||
mov StartEl,AX
|
||
mov DestTail,AX
|
||
mov DestClosed,AL
|
||
mov DestSiz,AL
|
||
mov SrcSiz,AL
|
||
mov DestInfo,AL
|
||
mov SrcInfo,AL
|
||
mov InExact,AL
|
||
mov DestVars,AL
|
||
mov SrcVars,AL
|
||
mov UserDir1,AL
|
||
mov NoWrite,AL
|
||
mov RdEOF,AL
|
||
mov SrcHand,AX
|
||
mov CpDate,AX
|
||
mov CpTime,AX
|
||
mov xa_list_attr,ax ;AN030; initialize code page to none
|
||
mov SrcIsDev,AL
|
||
mov TermRead,AL
|
||
mov comma,al ;g
|
||
mov plus_comma,al ;g
|
||
mov msg_flag,al ;AN022;
|
||
mov [ALLSWITCH],AX ; no switches
|
||
mov [ARGC],al ; no arguments
|
||
mov [PLUS],al ; no concatenation
|
||
mov [BINARY],al ; Binary not specifically specified
|
||
mov [ASCII],al ; ASCII not specifically specified
|
||
mov [FILECNT],ax ; No files yet
|
||
mov [WRITTEN],ax ; Nothing written yet
|
||
mov [CONCAT],al ; No concatenation
|
||
mov [MELCOPY],al ; Not a Mel Hallerman copy
|
||
mov [concat_xa],al ;AN000; initialize flag for concatenation XA
|
||
mov MelStart,ax ; Not a Mel Hallerman copy
|
||
mov word ptr [SCANBUF],ax ; Init buffer
|
||
mov word ptr [DESTBUF],ax ; Init buffer
|
||
mov word ptr [SRCBUF],ax ; Init buffer
|
||
mov word ptr [SDIRBUF],ax ; Init buffer
|
||
mov word ptr [DIRBUF],ax ; Init buffer
|
||
mov word ptr [DESTFCB],ax ; Init buffer
|
||
mov objcnt,al ; Init command line object count
|
||
dec ax
|
||
mov DestHand,AX ; destination has never been opened
|
||
mov [FRSTSRCH],al ; First search call
|
||
mov [FIRSTDEST],al ; First time
|
||
mov [DESTISDIR],al ; Don't know about dest
|
||
mov src_xa_seg,ax ;AN000; initialize attribute segment to -1
|
||
mov si,81H
|
||
mov bl,plus_chr ; include '+' as a delimiter
|
||
inc byte ptr [expand_star] ; want to include * expansion in cparse
|
||
mov cpyflag,1 ; Turn "CPARSE called from COPY flag" on
|
||
|
||
DESTSCAN:
|
||
xor bp,bp ; no switches
|
||
mov di,offset trangroup:SCANBUF
|
||
mov parse_last,si ;AN018; save start of parsed string
|
||
invoke CPARSE
|
||
PUSHF ; save flags
|
||
inc objcnt
|
||
test bh,80H ; A '+' argument?
|
||
jz NOPLUS ; no
|
||
mov [PLUS],1 ; yes
|
||
NOPLUS:
|
||
test bh,1 ; Switch?
|
||
jz TESTP2 ; no
|
||
|
||
test bp,SwitchV ;AN038; Verify requested?
|
||
jz not_slashv ;AN038; No - set the switch
|
||
test [allswitch],SwitchV ;AN038; Verify already entered?
|
||
jz not_slashv ;AN038; No - set the switch
|
||
;AD018; or [allswitch],FBadSwitch ;AN038; Set up bad switch
|
||
or BP,FBadSwitch ;AN018; Set up bad switch
|
||
|
||
not_slashv: ;AN038;
|
||
or [DESTSWITCH],BP ; Yes, assume destination
|
||
or [ALLSWITCH],BP ; keep tabs on all switches
|
||
|
||
test BP,NOT SwitchCopy ;AN018; Bad switch?
|
||
jz NOT_BAD_SWITCH ;AN018; Switches are okay
|
||
popf ;AN018; fix up stack
|
||
mov ax,BadSwt_ptr ;AN018; get "Invalid switch" message number
|
||
invoke Setup_parse_error_msg ;AN018; setup to print the message
|
||
jmp CERROR ;AC018; exit
|
||
|
||
NOT_BAD_SWITCH: ;AN018; switch okay
|
||
POPF ; get flags back
|
||
jc CHECKDONE ; Hit CR?
|
||
jmp short DESTSCAN
|
||
|
||
TESTP2:
|
||
POPF ; get flags back
|
||
jc CHECKDONE ; Hit CR?
|
||
test bh,80H ; Plus?
|
||
jnz GOTPLUS ; Yes, not a separate arg
|
||
inc [ARGC] ; found a real arg
|
||
GOTPLUS:
|
||
push SI
|
||
mov ax,[STARTEL]
|
||
mov SI,offset trangroup:SCANBUF ; Adjust to copy
|
||
sub ax,SI
|
||
mov DI,offset trangroup:DESTBUF
|
||
add ax,DI
|
||
mov [DESTTAIL],AX
|
||
mov [DESTSIZ],cl ; Save its size
|
||
inc cx ; Include the nul
|
||
rep movsb ; Save potential destination
|
||
mov [DESTINFO],bh ; Save info about it
|
||
mov [DESTSWITCH],0 ; reset switches
|
||
pop SI
|
||
jmp DESTSCAN ;AC018; keep going
|
||
|
||
CHECKDONE:
|
||
cmp plus,1 ; If a statement like "copy file+" is
|
||
jnz cdcont ; entered, complain about it.
|
||
cmp argc,1
|
||
jnz cdcont
|
||
cmp objcnt,2
|
||
jnz cdcont
|
||
mov dx,offset trangroup:overwr_ptr
|
||
jmp coperr
|
||
cdcont:
|
||
mov al,[PLUS]
|
||
mov [CONCAT],al ; PLUS -> Concatination
|
||
shl al,1
|
||
shl al,1
|
||
mov [INEXACT],al ; CONCAT -> inexact copy
|
||
mov al,[ARGC]
|
||
or al,al ; Good number of args?
|
||
jnz TRY_TOO_MANY ;AC000; there are args, see if too many
|
||
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
mov Extend_Buf_ptr,LessArgs_ptr ;AN000; get "Required parameters missing" message number
|
||
jmp short cerror_parsej ;AN000; exit
|
||
|
||
TRY_TOO_MANY:
|
||
cmp al,2
|
||
jbe ACOUNTOK
|
||
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
mov Extend_Buf_ptr,MoreArgs_ptr ;AN000; get "Too many parameters" message number
|
||
|
||
CERROR_PARSEJ:
|
||
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
|
||
CERROR4J:
|
||
jmp CERROR ; no, too many
|
||
|
||
ACOUNTOK:
|
||
mov bp,offset trangroup:DESTVARS
|
||
cmp al,1
|
||
jnz GOT2ARGS
|
||
mov al,[CURDRV] ; Dest is default drive:*.*
|
||
add al,capital_A
|
||
mov ah,':'
|
||
mov [bp.SIZ],2
|
||
mov di,offset trangroup:DESTBUF
|
||
stosw
|
||
mov [DESTSWITCH],0 ; no switches on dest
|
||
mov [bp.INFO],2 ; Flag dest is ambig
|
||
mov [bp.ISDIR],0 ; Know destination specs file
|
||
invoke SETSTARS
|
||
GOT2ARGS:
|
||
cmp [bp.SIZ],2
|
||
jnz NOTSHORTDEST
|
||
mov al,':'
|
||
cmp [DESTBUF+1],al
|
||
jnz NOTSHORTDEST ; Two char file name
|
||
or [bp.INFO],2 ; Know dest is d:
|
||
mov di,offset trangroup:DESTBUF + 2
|
||
mov [bp.ISDIR],0 ; Know destination specs file
|
||
invoke SETSTARS
|
||
NOTSHORTDEST:
|
||
mov di,[bp.TTAIL]
|
||
cmp byte ptr [DI],0
|
||
jnz CHKSWTCHES
|
||
mov dx,offset trangroup:BADCD_ptr
|
||
mov al,':'
|
||
cmp byte ptr [DI-2],al
|
||
jnz CERROR4J ; Trailing '/' error
|
||
mov [bp.ISDIR],2 ; Know destination is d:/
|
||
or [bp.INFO],6
|
||
invoke SETSTARS
|
||
CHKSWTCHES:
|
||
;AD018; mov ax,[ALLSWITCH]
|
||
;AD018; test ax,NOT SwitchCopy
|
||
;AD018; jz NOT_BAD_SWITCH ;AN000; Switches are okay
|
||
;AD018; MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
;AD018; mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
|
||
;AD018; jmp short CERROR_PARSEJ ;AC000; Switch specified which is not known
|
||
|
||
; Now know most of the information needed about the destination
|
||
|
||
;AD018; NOT_BAD_SWITCH:
|
||
if not ibmcopyright
|
||
mov ax, [allswitch] ; Which switches were requested? Hmmm?
|
||
endif
|
||
TEST AX,SwitchV ; Verify requested?
|
||
JZ NOVERIF ; No
|
||
MOV AH,GET_VERIFY_ON_WRITE
|
||
INT int_command ; Get current setting
|
||
PUSH DS
|
||
MOV DS,[RESSEG]
|
||
ASSUME DS:RESGROUP
|
||
XOR AH,AH
|
||
MOV [VERVAL],AX ; Save current setting
|
||
POP DS
|
||
ASSUME DS:TRANGROUP
|
||
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 ; Set verify
|
||
INT int_command
|
||
NOVERIF:
|
||
xor bp,bp ; no switches
|
||
mov si,81H
|
||
mov bl,plus_chr ; include '+' as a delimiter
|
||
SCANFSRC:
|
||
mov di,offset trangroup:SCANBUF
|
||
invoke CPARSE ; Parse first source name
|
||
test bh,1 ; Switch?
|
||
jnz SCANFSRC ; Yes, try again
|
||
or [DESTSWITCH],bp ; Include copy wide switches on dest
|
||
test bp,SwitchB
|
||
jnz NOSETCASC ; Binary explicit
|
||
cmp [CONCAT],0
|
||
JZ NOSETCASC ; Not Concat
|
||
mov [ASCII],SwitchA ; Concat -> ASCII copy if no B switch
|
||
mov [concat_xa],do_xa ;AN000; set up to do XA only on first file
|
||
NOSETCASC:
|
||
call source_set
|
||
call FRSTSRC
|
||
jmp FIRSTENT
|
||
|
||
PUBLIC EndCopy
|
||
ENDCOPY:
|
||
CALL CLOSEDEST
|
||
ENDCOPY2:
|
||
call deallocate_src_xa ;AN030; deallocate xa segment
|
||
invoke free_tpa ;AN000; Make sure work area
|
||
invoke alloc_tpa ;AN000; is reset properly
|
||
MOV DX,OFFSET TRANGROUP:COPIED_ptr
|
||
MOV SI,[FILECNT]
|
||
mov copy_num,si
|
||
invoke std_printf
|
||
JMP TCOMMAND ; Stack could be messed up
|
||
|
||
SRCNONEXIST:
|
||
cmp [CONCAT],0
|
||
jnz NEXTSRC ; If in concat mode, ignore error
|
||
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
|
||
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block
|
||
mov string_ptr_2,offset trangroup:srcbuf ;AC046; get address of failed string
|
||
mov Extend_buf_sub,one_subst ;AC046; put number of subst in control block
|
||
jmp COPERR
|
||
|
||
SOURCEPROC:
|
||
call source_set
|
||
cmp [CONCAT],0
|
||
jnz LEAVECFLAG ; Leave CFLAG if concatination
|
||
FRSTSRC:
|
||
xor ax,ax
|
||
mov [CFLAG],al ; Flag destination not created
|
||
mov [NXTADD],ax ; Zero out buffer
|
||
mov DestClosed,AL
|
||
LEAVECFLAG:
|
||
mov [SRCPT],SI ; remember where we are
|
||
mov di,offset trangroup:USERDIR1
|
||
mov bp,offset trangroup:SRCVARS
|
||
invoke BUILDPATH ; Figure out everything about the source
|
||
mov si,[SRCTAIL] ; Create the search FCB
|
||
return
|
||
|
||
NEXTSRC:
|
||
cmp [PLUS],0
|
||
jnz MORECP
|
||
ENDCOPYJ2:
|
||
jmp ENDCOPY ; Done
|
||
MORECP:
|
||
xor bp,bp ; no switches
|
||
mov si,[SRCPT]
|
||
mov bl,plus_chr ; include '+' as a delimiter
|
||
SCANSRC:
|
||
mov di,offset trangroup:SCANBUF
|
||
invoke CPARSE ; Parse first source name
|
||
JC EndCopyJ2 ; if error, then end (trailing + case)
|
||
test bh,80H
|
||
jz ENDCOPYJ2 ; If no '+' we're done
|
||
test bh,1 ; Switch?
|
||
jnz SCANSRC ; Yes, try again
|
||
call SOURCEPROC
|
||
cmp comma,1 ;g was +,, found last time?
|
||
jnz nostamp ;g no - try for a file
|
||
mov plus_comma,1 ;g yes - set flag
|
||
jmp srcnonexist ;g we know we won't find it
|
||
nostamp: ;g
|
||
mov plus_comma,0 ;g reset +,, flag
|
||
FIRSTENT:
|
||
mov di,FCB
|
||
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
|
||
INT int_command
|
||
CMP BYTE PTR [SI],0 ; parse everything?
|
||
JNZ SrchDone ; no, error, simulate no more search
|
||
mov ax,word ptr [SRCBUF] ; Get drive
|
||
cmp ah,':'
|
||
jz DRVSPEC1
|
||
mov al,'@'
|
||
DRVSPEC1:
|
||
or al,20h
|
||
sub al,60h
|
||
mov ds:[FCB],al
|
||
mov ah,DIR_SEARCH_FIRST
|
||
call SEARCH
|
||
SrchDone:
|
||
pushf ; Save result of search
|
||
invoke RESTUDIR1 ; Restore users dir
|
||
popf
|
||
jz NEXTAMBIG0
|
||
jmp SRCNONEXIST ; Failed
|
||
NEXTAMBIG0:
|
||
xor al,al
|
||
xchg al,[FRSTSRCH]
|
||
or al,al
|
||
jz NEXTAMBIG
|
||
SETNMEL:
|
||
mov cx,12
|
||
mov di,OFFSET TRANGROUP:SDIRBUF
|
||
mov si,OFFSET TRANGROUP:DIRBUF
|
||
rep movsb ; Save very first source name
|
||
NEXTAMBIG:
|
||
xor al,al
|
||
mov [NOWRITE],al ; Turn off NOWRITE
|
||
mov di,[SRCTAIL]
|
||
mov si,offset trangroup:DIRBUF + 1
|
||
invoke FCB_TO_ASCZ ; SRCBUF has complete name
|
||
MELDO:
|
||
cmp [CONCAT],0
|
||
jnz SHOWCPNAM ; Show name if concat
|
||
test [SRCINFO],2 ; Show name if multi
|
||
jz DOREAD
|
||
SHOWCPNAM:
|
||
mov dx,offset trangroup:file_name_ptr
|
||
invoke std_printf
|
||
invoke CRLF2
|
||
DOREAD:
|
||
call DOCOPY
|
||
cmp [CONCAT],0
|
||
jnz NODCLOSE ; If concat, do not close
|
||
call CLOSEDEST ; else close current destination
|
||
jc NODCLOSE ; Concat flag got set, close didn't really happen
|
||
mov [CFLAG],0 ; Flag destination not created
|
||
NODCLOSE:
|
||
cmp [CONCAT],0 ; Check CONCAT again
|
||
jz NOFLUSH
|
||
invoke FLSHFIL ; Flush output between source files on
|
||
; CONCAT so LOSTERR stuff works
|
||
; correctly
|
||
TEST [MELCOPY],0FFH
|
||
jz NOFLUSH
|
||
jmp SHORT DOMELCOPY
|
||
|
||
NOFLUSH:
|
||
call SEARCHNEXT ; Try next match
|
||
jnz NEXTSRCJ ; Finished with this source spec
|
||
mov [DESTCLOSED],0 ; Not created or concat ->...
|
||
jmp NEXTAMBIG ; Do next ambig
|
||
|
||
DOMELCOPY:
|
||
cmp [MELCOPY],0FFH
|
||
jz CONTMEL
|
||
mov SI,[SRCPT]
|
||
mov [MELSTART],si
|
||
mov [MELCOPY],0FFH
|
||
CONTMEL:
|
||
xor BP,BP
|
||
mov si,[SRCPT]
|
||
mov bl,plus_chr
|
||
SCANSRC2:
|
||
mov di,OFFSET TRANGROUP:SCANBUF
|
||
invoke CPARSE
|
||
test bh,80H
|
||
jz NEXTMEL ; Go back to start
|
||
test bh,1 ; Switch ?
|
||
jnz SCANSRC2 ; Yes
|
||
call SOURCEPROC
|
||
invoke RESTUDIR1
|
||
mov di,OFFSET TRANGROUP:DESTFCB2
|
||
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
|
||
INT int_command
|
||
mov bx,OFFSET TRANGROUP:SDIRBUF + 1
|
||
mov si,OFFSET TRANGROUP:DESTFCB2 + 1
|
||
mov di,[SRCTAIL]
|
||
invoke BUILDNAME
|
||
cmp [CONCAT],0 ; Are we concatenating?
|
||
jz meldoj ; No, continue.
|
||
;
|
||
; Yes, turn off nowrite because this part of the code is only reached after
|
||
; the first file has been dealt with.
|
||
;
|
||
mov [NOWRITE],0
|
||
meldoj:
|
||
jmp MELDO
|
||
|
||
NEXTSRCJ:
|
||
jmp NEXTSRC
|
||
|
||
NEXTMEL:
|
||
call CLOSEDEST
|
||
xor ax,ax
|
||
mov [CFLAG],al
|
||
mov [NXTADD],ax
|
||
mov [DESTCLOSED],al
|
||
mov si,[MELSTART]
|
||
mov [SRCPT],si
|
||
call SEARCHNEXT
|
||
jz SETNMELJ
|
||
jmp ENDCOPY2
|
||
SETNMELJ:
|
||
jmp SETNMEL
|
||
|
||
SEARCHNEXT:
|
||
MOV AH,DIR_SEARCH_NEXT
|
||
TEST [SRCINFO],2
|
||
JNZ SEARCH ; Do search-next if ambig
|
||
OR AH,AH ; Reset zero flag
|
||
return
|
||
SEARCH:
|
||
PUSH AX
|
||
MOV AH,SET_DMA
|
||
MOV DX,OFFSET TRANGROUP:DIRBUF
|
||
INT int_command ; Put result of search in DIRBUF
|
||
POP AX ; Restore search first/next command
|
||
MOV DX,FCB
|
||
INT int_command ; Do the search
|
||
OR AL,AL
|
||
return
|
||
|
||
DOCOPY:
|
||
mov si,offset trangroup:SRCBUF ;g do name translate of source
|
||
mov di,offset trangroup:SRCXNAME ;g save for name comparison
|
||
mov ah,xnametrans ;g
|
||
int int_command ;g
|
||
|
||
mov [RDEOF],0 ; No EOF yet
|
||
|
||
MOV AX,EXTOPEN SHL 8 ;AC000; open the file
|
||
mov bx,read_open_mode ;AN000; get open mode for COPY
|
||
xor cx,cx ;AN000; no special files
|
||
mov dx,read_open_flag ;AN000; set up open flags
|
||
mov di,-1 ;AN030; no parameter list
|
||
INT int_command
|
||
|
||
jnc OpenOK
|
||
;
|
||
; Bogosity: IBM wants us to issue Access denied in this case. THey asked
|
||
; for it...
|
||
;
|
||
jmp error_on_source ;AC022; clean up and exit
|
||
|
||
OpenOK:
|
||
mov bx,ax ; Save handle
|
||
mov [SRCHAND],bx ; Save handle
|
||
mov ax,(FILE_TIMES SHL 8)
|
||
INT int_command
|
||
jc src_cp_error ;AN022; If error, exit
|
||
mov [CPDATE],dx ; Save DATE
|
||
mov [CPTIME],cx ; Save TIME
|
||
|
||
mov cx,xa_list_attr ;AN000; get old code page in cx
|
||
push cx ;AN000; save old attribute
|
||
mov xa_list_attr,0 ;AN000; initialize code page
|
||
|
||
mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attribute size
|
||
mov si,-1 ;AN030; no querylist
|
||
xor cx,cx ;AN030; indicate we want size
|
||
int int_command ;AC000;
|
||
jc src_cp_error ;AN022; If error, exit
|
||
mov src_xa_size,cx ;AN000; save size
|
||
cmp cx,0 ;AN000; are there any?
|
||
pop cx ;AN000; get old attribute
|
||
jz no_cp_get ;AN030; no - don't get attributes
|
||
|
||
push cx ;AN030; save old code page
|
||
invoke get_file_code_page_tag ;AN000; get file's code page
|
||
pop cx ;AN030 retrieve old code page
|
||
jnc no_cp_get ;AN000; no error - continue
|
||
src_cp_error: ;AN022;
|
||
jmp error_on_source ;AC022; and exit
|
||
|
||
no_cp_get:
|
||
cmp [concat],0 ;AN000; are we doing concatenation
|
||
jz get_src_xa ;AN000; no get source extended attrib
|
||
cmp [concat_xa],do_xa ;AN000; is this the first file?
|
||
jz get_src_xa ;AN000; yes - get extended attributes
|
||
cmp cx,xa_list_attr ;AN000; no - see if code pages match
|
||
jz no_copy_xa_jmp ;AN000; code pages match - continue
|
||
mov xa_list_attr,inv_cp_tag ;AN000; set invalid code page tag
|
||
no_copy_xa_jmp: ;AC022;
|
||
jmp no_copy_xa ;AN000; don't get extended attributes
|
||
|
||
get_src_xa:
|
||
call deallocate_src_xa ;AN030; deallocate any existing XA segment
|
||
cmp src_xa_size,0 ;AN000; are there any extended attributes?
|
||
jz no_copy_xa_jmp ;AC022; nothing there - don't allocate memory
|
||
push bx ;AN000; save handle
|
||
invoke free_tpa ;AN000; need to make free memory, first
|
||
mov bx,src_xa_size ;AN000; get bytes (size of XA) into bx
|
||
mov cl,4 ;AN000; divide bytes by 16 to convert
|
||
shr bx,cl ;AN000; to paragraphs
|
||
inc bx ;AN000; round up
|
||
mov ax,(alloc SHL 8) ;AN000; allocate memory for XA
|
||
int int_command ;AN000;
|
||
pushf ;AN000; save flags
|
||
mov [src_xa_seg], AX ;AN000; save new segment
|
||
push ds ;AN030; get resident segment
|
||
mov ds,[resseg] ;AN030; and save copy of xa
|
||
assume ds:resgroup ;AN030; segment in resident
|
||
mov [rsrc_xa_seg],ax ;AN030; in case user breaks
|
||
pop ds ;AN030; out or has critical
|
||
assume ds:trangroup ;AN030; error
|
||
invoke alloc_tpa ;AN000; reallocate the work area
|
||
popf ;AN000; restore flags
|
||
pop bx ;AN000; restore handle
|
||
jnc Alloc_for_xa_okay ;AN000; no carry - everything okay
|
||
call closesrc ;AN000; close the source file
|
||
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
|
||
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block
|
||
jmp cerror ;AN000; exit
|
||
|
||
Alloc_for_xa_okay:
|
||
|
||
mov ax,(file_times SHL 8)+get_XA ;AN000; get extended attributes
|
||
push es ;AN000; save es
|
||
mov es,[src_xa_seg] ;AN000; get segment for XA list
|
||
xor di,di ;AN000; offset of return list
|
||
mov si,-1 ;AN030; get all attributes
|
||
mov cx,[src_xa_size] ;AN000; get size of list
|
||
int int_command ;AN000; get all the attributes
|
||
pop es ;AN000; restore es
|
||
jnc no_copy_xa ;AC022; no error - continue
|
||
|
||
error_on_source: ;AN022; we have a BAD error
|
||
invoke set_ext_error_msg ;AN022; set up the error message
|
||
mov string_ptr_2,offset trangroup:srcbuf ;AN022; get address of failed string
|
||
mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block
|
||
invoke std_Eprintf ;AN022; print it
|
||
cmp [srchand],0 ;AN022; did we open the file?
|
||
jz no_close_src ;AN022; no - don't close
|
||
call closesrc ;AN022; clean up
|
||
no_close_src: ;AN022;
|
||
cmp [cflag],0 ;AN022; was destination created?
|
||
jz endcopyj3 ;AN022; no - just cleanup and exit
|
||
jmp endcopy ;AN022; clean up concatenation and exit
|
||
endcopyj3: ;AN022;
|
||
jmp endcopy2 ;AN022;
|
||
no_copy_xa:
|
||
mov bx,[srchand] ;AN022; get handle back
|
||
mov ax,(IOCTL SHL 8)
|
||
INT int_command ; Get device stuff
|
||
and dl,devid_ISDEV
|
||
mov [SRCISDEV],dl ; Set source info
|
||
jz COPYLP ; Source not a device
|
||
cmp [BINARY],0
|
||
jz COPYLP ; ASCII device OK
|
||
mov dx,offset trangroup:INBDEV_ptr ; Cannot do binary input
|
||
jmp COPERR
|
||
|
||
COPYLP:
|
||
mov bx,[SRCHAND]
|
||
mov cx,[BYTCNT]
|
||
mov dx,[NXTADD]
|
||
sub cx,dx ; Compute available space
|
||
jnz GOTROOM
|
||
invoke FLSHFIL
|
||
CMP [TERMREAD],0
|
||
JNZ CLOSESRC ; Give up
|
||
mov cx,[BYTCNT]
|
||
GOTROOM:
|
||
push ds
|
||
mov ds,[TPA]
|
||
ASSUME DS:NOTHING
|
||
mov ah,READ
|
||
INT int_command
|
||
pop ds
|
||
ASSUME DS:TRANGROUP
|
||
jc error_on_source ;AC022; Give up if error
|
||
mov cx,ax ; Get count
|
||
jcxz CLOSESRC ; No more to read
|
||
cmp [SRCISDEV],0
|
||
jnz NOTESTA ; Is a device, ASCII mode
|
||
cmp [ASCII],0
|
||
jz BINREAD
|
||
NOTESTA:
|
||
MOV DX,CX
|
||
MOV DI,[NXTADD]
|
||
MOV AL,1AH
|
||
PUSH ES
|
||
MOV ES,[TPA]
|
||
REPNE SCASB ; Scan for EOF
|
||
POP ES
|
||
JNZ USEALL
|
||
INC [RDEOF]
|
||
INC CX
|
||
USEALL:
|
||
SUB DX,CX
|
||
MOV CX,DX
|
||
BINREAD:
|
||
ADD CX,[NXTADD]
|
||
MOV [NXTADD],CX
|
||
CMP CX,[BYTCNT] ; Is buffer full?
|
||
JB TESTDEV ; If not, we may have found EOF
|
||
invoke FLSHFIL
|
||
CMP [TERMREAD],0
|
||
JNZ CLOSESRC ; Give up
|
||
JMP SHORT COPYLP
|
||
|
||
TESTDEV:
|
||
cmp [SRCISDEV],0
|
||
JZ CLOSESRC ; If file then EOF
|
||
CMP [RDEOF],0
|
||
JZ COPYLP ; On device, go till ^Z
|
||
CLOSESRC:
|
||
mov bx,[SRCHAND]
|
||
mov ah,CLOSE
|
||
INT int_command
|
||
return
|
||
|
||
;
|
||
; We are called to close the destination. We need to note whether or not
|
||
; there is any internal data left to be flushed out.
|
||
;
|
||
CLOSEDEST:
|
||
cmp [DESTCLOSED],0
|
||
retnz ; Don't double close
|
||
MOV AL,BYTE PTR [DESTSWITCH]
|
||
invoke SETASC ; Check for B or A switch on destination
|
||
JZ BINCLOS
|
||
MOV BX,[NXTADD]
|
||
CMP BX,[BYTCNT] ; Is memory full?
|
||
JNZ PUTZ
|
||
invoke TRYFLUSH ; Make room for one lousy byte
|
||
jz NOCONC
|
||
CONCHNG: ; Concat flag changed on us
|
||
stc
|
||
return
|
||
NOCONC:
|
||
XOR BX,BX
|
||
PUTZ:
|
||
PUSH DS
|
||
MOV DS,[TPA]
|
||
MOV WORD PTR [BX],1AH ; Add End-of-file mark (Ctrl-Z)
|
||
POP DS
|
||
INC [NXTADD]
|
||
MOV [NOWRITE],0 ; Make sure our ^Z gets written
|
||
MOV AX,[WRITTEN]
|
||
ADD AX,[NXTADD]
|
||
JC BINCLOS ; > 1
|
||
CMP AX,1
|
||
JZ FORGETITJ ; WRITTEN = 0 NXTADD = 1 (the ^Z)
|
||
BINCLOS:
|
||
invoke TRYFLUSH
|
||
jnz CONCHNG
|
||
cmp [WRITTEN],0
|
||
ForgetItJ:
|
||
jnz no_forget ;AC000; Wrote something
|
||
jmp FORGETIT ;AC000; Never wrote nothing
|
||
no_forget:
|
||
MOV BX,[DESTHAND]
|
||
MOV CX,[CPTIME]
|
||
MOV DX,[CPDATE]
|
||
CMP [INEXACT],0 ; Copy not exact?
|
||
JZ DODCLOSE ; If no, copy date & time
|
||
MOV AH,GET_TIME
|
||
INT int_command
|
||
SHL CL,1
|
||
SHL CL,1 ; Left justify min in CL
|
||
SHL CX,1
|
||
SHL CX,1
|
||
SHL CX,1 ; hours to high 5 bits, min to 5-10
|
||
SHR DH,1 ; Divide seconds by 2 (now 5 bits)
|
||
OR CL,DH ; And stick into low 5 bits of CX
|
||
PUSH CX ; Save packed time
|
||
MOV AH,GET_DATE
|
||
INT int_command
|
||
SUB CX,1980
|
||
XCHG CH,CL
|
||
SHL CX,1 ; Year to high 7 bits
|
||
SHL DH,1 ; Month to high 3 bits
|
||
SHL DH,1
|
||
SHL DH,1
|
||
SHL DH,1
|
||
SHL DH,1 ; Most sig bit of month in carry
|
||
ADC CH,0 ; Put that bit next to year
|
||
OR DL,DH ; Or low three of month into day
|
||
MOV DH,CH ; Get year and high bit of month
|
||
POP CX ; Get time back
|
||
DODCLOSE:
|
||
CMP BX,0
|
||
JLE CloseDone
|
||
MOV AX,(FILE_TIMES SHL 8) OR 1
|
||
INT int_command ; Set date and time
|
||
jc xa_cleanup_err ;AN022; handle error
|
||
|
||
mov ax,(file_times SHL 8)+set_XA ;AN000; set code page
|
||
mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list
|
||
int int_command ;AN000;
|
||
jc xa_cleanup_err ;AN030; exit if error
|
||
|
||
;
|
||
; See if the destination has *anything* in it. If not, just close and delete
|
||
; it.
|
||
;
|
||
no_xa_cleanup_err:
|
||
mov ax,(lseek shl 8) + 2 ; seek to EOF
|
||
xor dx,dx
|
||
mov cx,dx
|
||
int 21h
|
||
;
|
||
; DX:AX is file size
|
||
;
|
||
or dx,ax
|
||
pushf
|
||
mov ax,(IOCTL SHL 8) + 0 ; get the destination attributes
|
||
int 21h
|
||
push dx ; save them away
|
||
MOV AH,CLOSE
|
||
INT int_command
|
||
pop dx
|
||
jnc close_cont ;AN022; handle error on close
|
||
popf ;AN022; get the flags back
|
||
xa_cleanup_err: ;AN022;
|
||
call cleanuperr ;AN022; attempt to delete the target
|
||
call DestDelete ;AN022; attempt to delete the target
|
||
jmp short fileclosed ;AN022; close the file
|
||
close_cont: ;AN022; no error - continue
|
||
popf
|
||
jnz CloseDone
|
||
test dx,80h ; is the destination a device?
|
||
jnz CloseDone ; yes, copy succeeded
|
||
call DestDelete
|
||
jmp short FileClosed
|
||
CloseDone:
|
||
INC [FILECNT]
|
||
FileClosed:
|
||
INC [DESTCLOSED]
|
||
RET50:
|
||
CLC
|
||
return
|
||
|
||
|
||
FORGETIT:
|
||
MOV BX,[DESTHAND]
|
||
CALL DODCLOSE ; Close the dest
|
||
call DestDelete
|
||
MOV [FILECNT],0 ; No files transferred
|
||
JMP RET50
|
||
|
||
DestDelete:
|
||
MOV DX,OFFSET TRANGROUP:DESTBUF
|
||
MOV AH,UNLINK
|
||
INT int_command ; And delete it
|
||
return
|
||
|
||
source_set proc near
|
||
|
||
push SI
|
||
mov ax,[STARTEL]
|
||
mov SI,offset trangroup:SCANBUF ; Adjust to copy
|
||
sub ax,SI
|
||
mov DI,offset trangroup:SRCBUF
|
||
add ax,DI
|
||
mov [SRCTAIL],AX
|
||
mov [SRCSIZ],cl ; Save its size
|
||
inc cx ; Include the nul
|
||
rep movsb ; Save this source
|
||
mov [SRCINFO],bh ; Save info about it
|
||
pop SI
|
||
mov ax,bp ; Switches so far
|
||
invoke SETASC ; Set A,B switches accordingly
|
||
invoke SWITCH ; Get any more switches on this arg
|
||
invoke SETASC ; Set
|
||
return
|
||
|
||
source_set endp
|
||
|
||
|
||
;****************************************************************
|
||
;*
|
||
;* ROUTINE: Cleanuperr
|
||
;*
|
||
;* FUNCTION: Issues extended error message for destination
|
||
;* if not alreay issued
|
||
;*
|
||
;* INPUT: return from INT 21
|
||
;*
|
||
;* OUTPUT: none
|
||
;*
|
||
;****************************************************************
|
||
|
||
cleanuperr proc near ;AN022;
|
||
|
||
cmp msg_flag,0 ;AN022; have we already issued a message?
|
||
jnz cleanuperr_cont ;AN022; yes - don't issue duplicate error
|
||
invoke set_ext_error_msg ;AN022; set up error message
|
||
mov string_ptr_2,offset trangroup:destbuf ;AN022; get address of failed string
|
||
mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block
|
||
invoke std_eprintf ;AN022; issue the error message
|
||
cleanuperr_cont: ;AN022;
|
||
|
||
ret ;AN022; return to caller
|
||
cleanuperr endp ;AN022;
|
||
|
||
;****************************************************************
|
||
;*
|
||
;* ROUTINE: Deallocate_Src_XA
|
||
;*
|
||
;* FUNCTION: Deallocates source extended attribute segment
|
||
;* and resets both resident and transient variables.
|
||
;*
|
||
;*
|
||
;* INPUT: none
|
||
;*
|
||
;* OUTPUT: none
|
||
;*
|
||
;****************************************************************
|
||
|
||
Deallocate_Src_XA proc near ;AN030;
|
||
|
||
cmp [src_xa_seg],no_xa_seg ;AN030; has any XA segment been allocated
|
||
jz no_src_xa ;AN030; no - continue
|
||
push es ;AN030;
|
||
mov es,src_xa_seg ;AN030; yes - free it
|
||
mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call
|
||
int int_command ;AN030;
|
||
pop es ;AN030;
|
||
mov [src_xa_seg],no_xa_seg ;AN030; reset to no segment
|
||
push ds ;AN030; reinitialize resident
|
||
mov ds,[resseg] ;AN030; copy of xa segment
|
||
assume ds:resgroup ;AN030;
|
||
mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment
|
||
pop ds ;AN030;
|
||
assume ds:trangroup ;AN030;
|
||
no_src_xa: ;AN030;
|
||
|
||
ret ;AN030; return to caller
|
||
Deallocate_Src_XA endp ;AN030;
|
||
|
||
|
||
TRANCODE ENDS
|
||
END
|
||
|