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

526 lines
18 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
TITLE COPYRPOC ;Procedures called by COPY
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN DEVWMES:BYTE,INBDEV:BYTE,NOSPACE:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN CFLAG:BYTE,NXTADD:WORD,DESTCLOSED: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,MELCOPY:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD
EXTRN DESTTAIL:WORD,DESTINFO:BYTE,INEXACT:BYTE
EXTRN DESTVARS:BYTE,SRCINFO:BYTE,RDEOF:BYTE
EXTRN USERDIR1:BYTE,NOWRITE:BYTE
EXTRN SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
PUBLIC SEARCH,SEARCHNEXT,DOCOPY,CLOSEDEST,FLSHFIL,SETASC
PUBLIC BUILDNAME,COPERR
EXTRN PRINT:NEAR,BUILDPATH:NEAR,RESTUDIR1:NEAR
EXTRN COMPNAME:NEAR,ENDCOPY:NEAR
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SEARCHNEXT:
MOV AH,DIR_SEARCH_NEXT
TEST [SRCINFO],2
JNZ SEARCH ; Do serach-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 [RDEOF],0 ; No EOF yet
mov dx,offset trangroup:SRCBUF
mov ax,OPEN SHL 8
INT int_command
retc ; If open fails, ignore
mov bx,ax ; Save handle
mov [SRCHAND],bx ; Save handle
mov ax,(FILE_TIMES SHL 8)
INT int_command
mov [CPDATE],dx ; Save DATE
mov [CPTIME],cx ; Save TIME
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 ; Cannot do binary input
jmp COPERR
COPYLP:
mov bx,[SRCHAND]
mov cx,[BYTCNT]
mov dx,[NXTADD]
sub cx,dx ; Compute available space
jnz GOTROOM
call 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 CLOSESRC ; 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
CALL 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
CLOSEDEST:
cmp [DESTCLOSED],0
retnz ; Don't double close
MOV AL,BYTE PTR [DESTSWITCH]
CALL SETASC ; Check for B or A switch on destination
JZ BINCLOS
MOV BX,[NXTADD]
CMP BX,[BYTCNT] ; Is memory full?
JNZ PUTZ
call 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 AL,[WRITTEN]
XOR AH,AH
ADD AX,[NXTADD]
JC BINCLOS ; > 1
CMP AX,1
JZ FORGETIT ; WRITTEN = 0 NXTADD = 1 (the ^Z)
BINCLOS:
call TRYFLUSH
jnz CONCHNG
cmp [WRITTEN],0
jz FORGETIT ; Never wrote nothin
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:
MOV AX,(FILE_TIMES SHL 8) OR 1
INT int_command ; Set date and time
MOV AH,CLOSE
INT int_command
INC [FILECNT]
INC [DESTCLOSED]
RET50:
CLC
return
FORGETIT:
MOV BX,[DESTHAND]
CALL DODCLOSE ; Close the dest
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [FILECNT],0 ; No files transferred
JMP RET50
TRYFLUSH:
mov al,[CONCAT]
push ax
call FLSHFIL
pop ax
cmp al,[CONCAT]
return
FLSHFIL:
; Write out any data remaining in memory.
; Inputs:
; [NXTADD] = No. of bytes to write
; [CFLAG] <>0 if file has been created
; Outputs:
; [NXTADD] = 0
MOV [TERMREAD],0
cmp [CFLAG],0
JZ NOTEXISTS
JMP EXISTS
NOTEXISTS:
call BUILDDEST ; Find out all about the destination
CALL COMPNAME ; Source and dest. the same?
JNZ PROCDEST ; If not, go ahead
CMP [SRCISDEV],0
JNZ PROCDEST ; Same name on device OK
CMP [CONCAT],0 ; Concatenation?
MOV DX,OFFSET TRANGROUP:OVERWR
JZ COPERRJ ; If not, overwrite error
MOV [NOWRITE],1 ; Flag not writting (just seeking)
PROCDEST:
mov ax,(OPEN SHL 8) OR 1
CMP [NOWRITE],0
JNZ DODESTOPEN ; Don't actually create if NOWRITE set
mov ah,CREAT
xor cx,cx
DODESTOPEN:
mov dx,offset trangroup:DESTBUF
INT int_command
MOV DX,OFFSET TRANGROUP:FULDIR
JC COPERRJ
mov [DESTHAND],ax ; Save handle
mov [CFLAG],1 ; Destination now exists
mov bx,ax
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
mov [DESTISDEV],dl ; Set dest info
test dl,devid_ISDEV
jz EXISTS ; Dest not a device
mov al,BYTE PTR [DESTSWITCH]
AND AL,ASWITCH+BSWITCH
JNZ TESTBOTH
MOV AL,[ASCII] ; Neither set, use current setting
OR AL,[BINARY]
JZ EXSETA ; Neither set, default to ASCII
TESTBOTH:
JPE EXISTS ; Both are set, ignore
test AL,BSWITCH
jz EXISTS ; Leave in cooked mode
mov ax,(IOCTL SHL 8) OR 1
xor dh,dh
or dl,devid_RAW
mov [DESTISDEV],dl ; New value
INT int_command ; Set device to RAW mode
jmp short EXISTS
COPERRJ:
jmp SHORT COPERR
EXSETA:
; What we read in may have been in binary mode, flag zapped write OK
mov [ASCII],ASWITCH ; Set ASCII mode
or [INEXACT],ASWITCH ; ASCII -> INEXACT
EXISTS:
cmp [NOWRITE],0
jnz NOCHECKING ; If nowrite don't bother with name check
CALL COMPNAME ; Source and dest. the same?
JNZ NOCHECKING ; If not, go ahead
CMP [SRCISDEV],0
JNZ NOCHECKING ; Same name on device OK
; At this point we know in append (would have gotten overwrite error on first
; destination create otherwise), and user trying to specify destination which
; has been scribbled already (if dest had been named first, NOWRITE would
; be set).
MOV DX,OFFSET TRANGROUP:LOSTERR ; Tell him he's not going to get it
CALL PRINT
MOV [NXTADD],0 ; Set return
INC [TERMREAD] ; Tell Read to give up
RET60:
return
NOCHECKING:
mov bx,[DESTHAND] ; Get handle
XOR CX,CX
XCHG CX,[NXTADD]
JCXZ RET60 ; If Nothing to write, forget it
INC [WRITTEN] ; Flag that we wrote something
CMP [NOWRITE],0 ; If NOWRITE set, just seek CX bytes
JNZ SEEKEND
XOR DX,DX
PUSH DS
MOV DS,[TPA]
ASSUME DS:NOTHING
MOV AH,WRITE
INT int_command
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE
JC COPERR ; Failure
sub cx,ax
retz ; Wrote all supposed to
test [DESTISDEV],devid_ISDEV
jz COPERR ; Is a file, error
test [DESTISDEV],devid_RAW
jnz DEVWRTERR ; Is a raw device, error
cmp [INEXACT],0
retnz ; INEXACT so OK
dec cx
retz ; Wrote one byte less (the ^Z)
DEVWRTERR:
MOV DX,OFFSET TRANGROUP:DEVWMES
COPERR:
CALL PRINT
inc [DESTCLOSED]
cmp [CFLAG],0
jz ENDCOPYJ ; Never actually got it open
MOV bx,[DESTHAND]
MOV AH,CLOSE ; Close the file
INT int_command
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [CFLAG],0
ENDCOPYJ:
JMP ENDCOPY
SEEKEND:
xor dx,dx ; Zero high half of offset
xchg dx,cx ; cx:dx is seek location
mov ax,(LSEEK SHL 8) OR 1
INT int_command ; Seek ahead in the file
cmp [RDEOF],0
retz
; If a ^Z has been read we must set the file size to the current
; file pointer location
MOV AH,WRITE
INT int_command ; CX is zero, truncates file
return
SETASC:
; Given switch vector in AX,
; Set ASCII switch if A is set
; Clear ASCII switch if B is set
; BINARY set if B specified
; Leave ASCII unchanged if neither or both are set
; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
AND AL,ASWITCH+BSWITCH
JPE LOADSW ; PE means both or neither are set
PUSH AX
AND AL,BSWITCH
MOV [BINARY],AL
POP AX
AND AL,ASWITCH
MOV [ASCII],AL
OR [INEXACT],AL
LOADSW:
MOV AL,[ASCII]
OR AL,AL
return
BUILDDEST:
cmp [DESTISDIR],-1
jnz KNOWABOUTDEST ; Already done the figuring
MOV DI,OFFSET TRANGROUP:USERDIR1
mov bp,offset trangroup:DESTVARS
call BUILDPATH
call RESTUDIR1
; Now know all about the destination
KNOWABOUTDEST:
xor al,al
xchg al,[FIRSTDEST]
or al,al
jnz FIRSTDST
jmp NOTFIRSTDEST
FIRSTDST:
mov si,[DESTTAIL] ; Create an FCB of the original DEST
mov di,offset trangroup:DESTFCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov ax,word ptr [DESTBUF] ; Get drive
cmp ah,':'
jz DRVSPEC4
mov al,'@'
DRVSPEC4:
MOV CL,[ASCII] ; Save current ASCII setting
sub al,'@'
mov [DESTFCB],al
mov al,[DESTINFO]
mov ah,[SRCINFO]
and ax,0202H
or al,al
jz NOTMELCOPY
cmp al,ah
jnz NOTMELCOPY
cmp [PLUS],0
jz NOTMELCOPY
inc [MELCOPY] ; ambig source, ambig dest, and pluses
xor al,al
jmp short SETCONC
NOTMELCOPY:
xor al,2 ; al=2 if unambig dest, =0 if ambig dest
and al,ah
shr al,1 ; al=1 if unambig dest AND ambig sorce
; Implies concatination
SETCONC:
or al,[PLUS] ; al=1 if concat
mov [CONCAT],al
shl al,1
shl al,1
mov [INEXACT],al ; Concat -> inexact copy
cmp [BINARY],0
jnz NOTFIRSTDEST ; Binary explicitly given, all OK
mov [ASCII],al ; Concat -> ASCII
or cl,cl
jnz NOTFIRSTDEST ; ASCII flag set before, DATA read correctly
or al,al
JZ NOTFIRSTDEST ; ASCII flag did not change states
; At this point there may already be binary read data in the read buffer.
; We need to find the first ^Z (if there is one) and trim the amount
; of data in the buffer correctly.
MOV CX,[NXTADD]
JCXZ NOTFIRSTDEST ; No data, everything OK
MOV AL,1AH
PUSH ES
XOR DI,DI
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ NOTFIRSTDEST ; No ^Z in buffer, everything OK
DEC DI ; Point at ^Z
MOV [NXTADD],DI ; New buffer
NOTFIRSTDEST:
mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars
cmp [CONCAT],0
jz GOTCHRSRC ; Not a concat
mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars
GOTCHRSRC:
mov si,offset trangroup:DESTFCB+1 ; Original dest name
mov di,[DESTTAIL] ; Where to put result
BUILDNAME:
mov cx,8
BUILDMAIN:
lodsb
cmp al,"?"
jnz NOTAMBIG
mov al,byte ptr [BX]
NOTAMBIG:
cmp al,' '
jz NOSTORE
stosb
NOSTORE:
inc bx
loop BUILDMAIN
mov cl,3
cmp byte ptr [SI],' '
jz ENDDEST ; No extension
mov al,'.'
stosb
BUILDEXT:
lodsb
cmp al,"?"
jnz NOTAMBIGE
mov al,byte ptr [BX]
NOTAMBIGE:
cmp al,' '
jz NOSTOREE
stosb
NOSTOREE:
inc bx
loop BUILDEXT
ENDDEST:
xor al,al
stosb ; NUL terminate
return
TRANCODE ENDS
END