MS-DOS/v2.0/source/COPY.ASM

579 lines
20 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
TITLE COMMAND COPY routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
EXTRN VERVAL:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADARGS:BYTE,BADCD:BYTE,BADSWT:BYTE,COPIED_PRE:BYTE
EXTRN COPIED_POST:BYTE
EXTRN INBDEV:BYTE,OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN NOSPACE:BYTE,DEVWMES:BYTE,NOTFND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN MELCOPY:BYTE,SRCPT:WORD,MELSTART:WORD,SCANBUF:BYTE
EXTRN DESTFCB2:BYTE,SDIRBUF:BYTE,SRCTAIL:WORD,CFLAG:BYTE
EXTRN NXTADD:WORD,DESTCLOSED:BYTE,ALLSWITCH:WORD,ARGC:BYTE
EXTRN PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
EXTRN WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
EXTRN SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,FRSTSRCH:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD,STARTEL:WORD
EXTRN DESTTAIL:WORD,DESTSIZ:BYTE,DESTINFO:BYTE,INEXACT:BYTE
EXTRN CURDRV:BYTE,DESTVARS:BYTE,RESSEG:WORD,SRCSIZ:BYTE
EXTRN SRCINFO:BYTE,SRCVARS:BYTE,USERDIR1:BYTE,NOWRITE:BYTE
EXTRN RDEOF:BYTE,SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
; **************************************************
; COPY CODE
;
TRANCODE SEGMENT PUBLIC BYTE
EXTRN RESTUDIR:NEAR,CERROR:NEAR,SWITCH:NEAR,DISP32BITS:NEAR
EXTRN PRINT:NEAR,TCOMMAND:NEAR,ZPRINT:NEAR,ONESPC:NEAR
EXTRN RESTUDIR1:NEAR,FCB_TO_ASCZ:NEAR,CRLF2:NEAR,SAVUDIR1:NEAR
EXTRN SETREST1:NEAR,BADCDERR:NEAR,STRCOMP:NEAR,DELIM:NEAR
EXTRN UPCONV:NEAR,PATHCHRCMP:NEAR,SCANOFF:NEAR
EXTRN CPARSE:NEAR
EXTRN SEARCH:NEAR,SEARCHNEXT:NEAR,DOCOPY:NEAR,CLOSEDEST:NEAR
EXTRN FLSHFIL:NEAR,SETASC:NEAR,BUILDNAME:NEAR,COPERR:NEAR
PUBLIC COPY,BUILDPATH,COMPNAME,ENDCOPY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
DOMELCOPY:
cmp [MELCOPY],0FFH
jz CONTMEL
mov SI,[SRCPT]
mov [MELSTART],si
mov [MELCOPY],0FFH
CONTMEL:
xor BP,BP
mov si,[SRCPT]
mov bl,'+'
SCANSRC2:
mov di,OFFSET TRANGROUP:SCANBUF
call CPARSE
test bh,80H
jz NEXTMEL ; Go back to start
test bh,1 ; Switch ?
jnz SCANSRC2 ; Yes
call SOURCEPROC
call 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]
call BUILDNAME
jmp MELDO
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
COPY:
; First order of buisness is to find out about the destination
ASSUME DS:TRANGROUP,ES:TRANGROUP
xor ax,ax
mov [ALLSWITCH],AX ; no switches
mov [ARGC],al ; no arguments
mov [PLUS],al ; no concatination
mov [BINARY],al ; Binary not specifically specified
mov [ASCII],al ; ASCII not specifically specified
mov [FILECNT],ax ; No files yet
mov [WRITTEN],al ; Nothing written yet
mov [CONCAT],al ; No concatination
mov [MELCOPY],al ; 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
dec ax
mov [FRSTSRCH],al ; First search call
mov [FIRSTDEST],al ; First time
mov [DESTISDIR],al ; Don't know about dest
mov si,81H
mov bl,'+' ; include '+' as a delimiter
DESTSCAN:
xor bp,bp ; no switches
mov di,offset trangroup:SCANBUF
call CPARSE
PUSHF ; save flags
test bh,80H ; A '+' argument?
jz NOPLUS ; no
mov [PLUS],1 ; yes
NOPLUS:
POPF ; get flags back
jc CHECKDONE ; Hit CR?
test bh,1 ; Switch?
jz TESTP2 ; no
or [DESTSWITCH],BP ; Yes, assume destination
or [ALLSWITCH],BP ; keep tabs on all switches
jmp short DESTSCAN
TESTP2:
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 short DESTSCAN ; keep going
CHECKDONE:
mov al,[PLUS]
mov [CONCAT],al ; PLUS -> Concatination
shl al,1
shl al,1
mov [INEXACT],al ; CONCAT -> inexact copy
mov dx,offset trangroup:BADARGS
mov al,[ARGC]
or al,al ; Good number of args?
jz CERROR4J ; no, not enough
cmp al,2
jbe ACOUNTOK
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,'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
call SETSTARS
GOT2ARGS:
cmp [bp.SIZ],2
jnz NOTSHORTDEST
cmp [DESTBUF+1],':'
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
call SETSTARS
NOTSHORTDEST:
mov di,[bp.TTAIL]
cmp byte ptr [DI],0
jnz CHKSWTCHES
mov dx,offset trangroup:BADCD
cmp byte ptr [DI-2],':'
jnz CERROR4J ; Trailing '/' error
mov [bp.ISDIR],2 ; Know destination is d:/
or [bp.INFO],6
call SETSTARS
CHKSWTCHES:
mov dx,offset trangroup:BADSWT
mov ax,[ALLSWITCH]
cmp ax,GOTSWITCH
jz CERROR4J ; Switch specified which is not known
; Now know most of the information needed about the destination
TEST AX,VSWITCH ; 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,'+' ; include '+' as a delimiter
SCANFSRC:
mov di,offset trangroup:SCANBUF
call 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,BSWITCH
jnz NOSETCASC ; Binary explicit
cmp [CONCAT],0
JZ NOSETCASC ; Not Concat
mov [ASCII],ASWITCH ; Concat -> ASCII copy if no B switch
NOSETCASC:
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
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; Set
call FRSTSRC
jmp FIRSTENT
ENDCOPY:
CALL CLOSEDEST
ENDCOPY2:
MOV DX,OFFSET TRANGROUP:COPIED_PRE
CALL PRINT
MOV SI,[FILECNT]
XOR DI,DI
CALL DISP32BITS
MOV DX,OFFSET TRANGROUP:COPIED_POST
CALL PRINT
JMP TCOMMAND ; Stack could be messed up
SRCNONEXIST:
cmp [CONCAT],0
jnz NEXTSRC ; If in concat mode, ignore error
mov dx,offset trangroup:SRCBUF
call zprint
CALL ONESPC
mov dx,offset trangroup:NOTFND
jmp COPERR
SOURCEPROC:
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 sorce
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; 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 ; Not created -> not closed
LEAVECFLAG:
mov [SRCPT],SI ; remember where we are
mov di,offset trangroup:USERDIR1
mov bp,offset trangroup:SRCVARS
call 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,'+' ; include '+' as a delimiter
SCANSRC:
mov di,offset trangroup:SCANBUF
call 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
FIRSTENT:
mov di,FCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov ax,word ptr [SRCBUF] ; Get drive
cmp ah,':'
jz DRVSPEC1
mov al,'@'
DRVSPEC1:
sub al,'@'
mov ds:[FCB],al
mov ah,DIR_SEARCH_FIRST
call SEARCH
pushf ; Save result of search
call 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
call 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:SRCBUF
call ZPRINT
call 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
CALL FLSHFIL ; Flush output between source files on CONCAT
; so LOSTERR stuff works correctly
TEST [MELCOPY],0FFH
jz NOFLUSH
jmp DOMELCOPY
NOFLUSH:
call SEARCHNEXT ; Try next match
jnz NEXTSRCJ ; Finished with this source spec
mov [DESTCLOSED],0 ; Not created or concat -> not closed
jmp NEXTAMBIG ; Do next ambig
NEXTSRCJ:
jmp NEXTSRC
BUILDPATH:
test [BP.INFO],2
jnz NOTPFILE ; If ambig don't bother with open
mov dx,bp
add dx,BUF ; Set DX to spec
mov ax,OPEN SHL 8
INT int_command
jc NOTPFILE
mov bx,ax ; Is pure file
mov ax,IOCTL SHL 8
INT int_command
mov ah,CLOSE
INT int_command
test dl,devid_ISDEV
jnz ISADEV ; If device, done
test [BP.INFO],4
jz ISSIMPFILE ; If no path seps, done
NOTPFILE:
mov dx,word ptr [BP.BUF]
cmp dh,':'
jz DRVSPEC5
mov dl,'@'
DRVSPEC5:
sub dl,'@' ; A = 1
call SAVUDIR1
mov dx,bp
add dx,BUF ; Set DX for upcomming CHDIRs
mov bh,[BP.INFO]
and bh,6
cmp bh,6 ; Ambig and path ?
jnz CHECKAMB ; jmp if no
mov si,[BP.TTAIL]
cmp byte ptr [si-2],':'
jnz KNOWNOTSPEC
mov [BP.ISDIR],2 ; Know is d:/file
jmp short DOPCDJ
KNOWNOTSPEC:
mov [BP.ISDIR],1 ; Know is path/file
dec si ; Point to the /
DOPCDJ:
jmp short DOPCD
CHECKAMB:
cmp bh,2
jnz CHECKCD
ISSIMPFILE:
ISADEV:
mov [BP.ISDIR],0 ; Know is file since ambig but no path
return
CHECKCD:
call SETREST1
mov ah,CHDIR
INT int_command
jc NOTPDIR
mov di,dx
xor ax,ax
mov cx,ax
dec cx
repne scasb
dec di
mov al,[DIRCHAR]
mov [bp.ISDIR],2 ; assume d:/file
cmp al,[di-1]
jz GOTSRCSLSH
stosb
mov [bp.ISDIR],1 ; know path/file
GOTSRCSLSH:
or [bp.INFO],6
call SETSTARS
return
NOTPDIR:
mov [bp.ISDIR],0 ; assume pure file
mov bh,[bp.INFO]
test bh,4
retz ; Know pure file, no path seps
mov [bp.ISDIR],2 ; assume d:/file
mov si,[bp.TTAIL]
cmp byte ptr [si],0
jz BADCDERRJ2 ; Trailing '/'
cmp byte ptr [si],'.'
jz BADCDERRJ2 ; If . or .. pure cd should have worked
cmp byte ptr [si-2],':'
jz DOPCD ; Know d:/file
mov [bp.ISDIR],1 ; Know path/file
dec si ; Point at last '/'
DOPCD:
xor bl,bl
xchg bl,[SI] ; Stick in a NUL
call SETREST1
mov ah,CHDIR
INT int_command
xchg bl,[SI]
retnc
BADCDERRJ2:
JMP BADCDERR
SETSTARS:
mov [bp.TTAIL],DI
add [bp.SIZ],12
mov ax,('.' SHL 8) OR '?'
mov cx,8
rep stosb
xchg al,ah
stosb
xchg al,ah
mov cl,3
rep stosb
xor al,al
stosb
return
COMPNAME:
PUSH CX
PUSH AX
MOV si,offset trangroup:SRCBUF
MOV di,offset trangroup:DESTBUF
MOV CL,[CURDRV]
MOV CH,CL
CMP BYTE PTR [SI+1],':'
JNZ NOSRCDRV
LODSW
SUB AL,'A'
MOV CL,AL
NOSRCDRV:
CMP BYTE PTR [DI+1],':'
JNZ NODSTDRV
MOV AL,[DI]
INC DI
INC DI
SUB AL,'A'
MOV CH,AL
NODSTDRV:
CMP CH,CL
jnz RET81P
call STRCOMP
jz RET81P
mov ax,[si-1]
mov cx,[di-1]
push ax
and al,cl
pop ax
jnz RET81P ; Niether of the mismatch chars was a NUL
; Know one of the mismatch chars is a NUL
; Check for ".NUL" compared with NUL
cmp al,'.'
jnz CHECKCL
or ah,ah
jmp short RET81P ; If NUL return match, else no match
CHECKCL:
cmp cl,'.'
jnz RET81P ; Mismatch
or ch,ch ; If NUL return match, else no match
RET81P:
POP AX
POP CX
return
TRANCODE ENDS
END