Mark Zbikowski 656c98b804 MZ is back!
2024-04-25 21:24:10 +01:00

1001 lines
26 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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