VZEditor/PATCHED/zcopy.asm
2025-04-02 08:44:47 +09:00

3422 lines
52 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.

;------------------------------------------------
; zcopy.asm
;
; Copyright (c) 1992-93 by c.mos
;------------------------------------------------
STDSEG equ TRUE
;DEBUG equ TRUE
NEWBLOCK equ TRUE
include std.inc
;------------------------------------------------
; Equations
;------------------------------------------------
;
;----- Options -----
OPT_C equ 00000001b ; Compare
OPT_G equ 00000010b ; Gather files
OPT_I equ 00000100b ; Incremental
OPT_N equ 00001000b ; No overwrite
OPT_O equ 00010000b ; Overwrite only
OPT_S equ 00100000b ; XCOPY /S
OPT_U equ 01000000b ; Update
OPT_V equ 10000000b ; Verify
OPT_A equ 00000001b ; XCOPY /A
OPT_B equ 00000010b ; XCOPY /M
OPT_DEL equ 00000100b ; Delete
OPT_M equ 00001000b ; Move
OPT_E equ 00010000b ; Echo
OPT_T equ 01000000b ; Time stamp
OPT_X equ 10000000b ; X:hidden
;
;----- Parse path result -----
PRS_WILD equ 00000001b
PRS_EXT equ 00000010b
PRS_NAME equ 00000100b
PRS_DIR equ 00001000b
PRS_DRV equ 00010000b
PRS_ROOT equ 00100000b
PRS_ENDBSL equ 01000000b
PRS_ENDDIR equ 10000000b
;
;----- flags -----
MASK_WILD equ 00000001b
MASK_FILE equ 00000110b
MASK_DIR equ 00001000b
MASK_NOT equ 10000000b
CPY_MASK equ 00000001b
CPY_XMASK equ 00000010b
MOV_SAMEDRV equ 00000100b
CPY_MKDIR equ 00001000b
CPY_DST equ 00010000b
RESPFILE equ 00100000b
DR_EXIST equ 0000001b
DR_MIN equ 0000010b
DR_LARGE equ 0000100b
DR_SMALL equ 0001000b
;
;----- Error code -----
ER_HELP equ 81h
ER_SYNTAX equ 83h
ER_OPTION equ 84h
ER_FILENG equ 85h
ER_PATHNG equ 86h
ER_DEST equ 87h
ER_SAME equ 88h
ER_ACCESS equ 89h
ER_DSKFULL equ 8Ah
ER_VERIFY equ 8Bh
EL_OK equ 0
EL_NOFILE equ 1
EL_DISK equ 3
EL_INIT equ 4
EL_VERIFY equ 6
EL_UNEXP equ 7
EL_BREAK equ 8
;
;----- Misc. -----
OPTCNT equ 16
STACKSZ equ 256
FA_DIRONLY equ FA_SEL
CPYBFPARA equ 0800h
CPYBFSIZE equ 08000h
HANDLE_DIR equ -1
HANDLE_FULL equ -2
CMPSIZE equ 1000h
CMPMIN equ 256
F_SETDATE equ 2Bh ; Set Date
F_GETTIME equ 2Ch ; Get Time
F_SETTIME equ 2Dh ; Set Time
;----- Structures -----
Work struc
option db ?
option2 db ?
swchr db ?
mode db ?
srcdir dw ?
srcmask dw ?
dstdir dw ?
parmlist dw ?
parmcnt dw ?
heap dw ?
dslottop dw ?
dslotseg dw ?
dslotp dw ?
dslotend dw ?
dslotmax dw ?
dslotbtm dw ?
verifyseg dw ?
cpybftop dw ?
cpybfend dw ?
cpybf_p dw ?
cpybf_q dw ?
totalsize dd ?
totalfiles dw ?
totalng dw ?
fh_w dw ?
fh_v dw ?
fh_c dw ?
fh_full dw ?
dslot_t dd ?
dslot_w dd ?
readmsgf db ?
openwcnt db ?
reftop dw ?
refend dw ?
Work ends
Parmlist struc
pl_prsf db ?
pl_parmp dw ?
pl_namep dw ?
pl_nextp dw ?
Parmlist ends
Dirslot struc
dr_pack db 13 dup(?)
dr_attr db ?
dr_time dw ?
dr_date dw ?
dr_size dd ?
dr_flag db ?
dr_ren db ?
Dirslot ends
;
CBheader struc
cb_next dw ?
cb_size dw ?
cb_dslot dd ?
cb_fh_w dw ?
cb_seek dd ?
dw ?
CBheader ends
Dta struc
db 15h dup(?)
dta_attr db ?
dta_time dw ?
dta_date dw ?
dta_size dd ?
dta_pack db 13 dup(?)
Dta ends
DSheader segment at 0
ds_size dw 1 dup(?)
ds_prev dw 1 dup(?)
ds_mode db 1 dup(?)
ds_dirname db 59+16 dup(?)
ds_header label byte
DSheader ends
;----- Macros -----
tstl macro var
mov ax,word ptr var
or ax,word ptr var+2
endm
clrl macro var
mov word ptr var,0
mov word ptr var+2,0
endm
ldl macro var
mov ax,word ptr var
mov dx,word ptr var+2
endm
stl macro var
mov word ptr var,ax
mov word ptr var+2,dx
endm
addl macro var
add ax,word ptr var
adc dx,word ptr var+2
endm
subl macro var
sub ax,word ptr var
sbb dx,word ptr var+2
endm
cmpl macro var
local cmpl1
cmp dx,word ptr var+2
jne cmpl1
cmp ax,word ptr var
cmpl1:
endm
;------------------------------------------------
; ZCOPY main
;------------------------------------------------
cseg
org 02h
psp_maxseg label word
org 80h
psp_dta label byte
org 81h
psp_cmdline label byte
org 100h
entry:
mov bp,offset cgroup: bpwork
call init
call parse_parm
_if c
call disp_error
jmps exit
_endif
IFDEF DEBUG
call disp_parm
ENDIF
call init2
mov sp,dx
call confirm
jc exit
call read_dirs
test [bp].option,OPT_S+OPT_G
_ifn z
call putcrlf
_endif
call init3
test [bp].option2,OPT_M
_ifn z
call init_move
_endif
test [bp].option2,OPT_E
jnz copy_e
test [bp].option2,OPT_DEL
_if z
copy_e: call do_copy
jc error
_endif
test [bp].option2,OPT_M+OPT_DEL
_ifn z
call do_delete
_endif
_if c
error: call putcrlf
call disp_error
_endif
push ax
call disp_info
pop ax
exit:
msdos F_TERM
;----- Init -----
init proc
mov di,bp
mov cx,type Work
clr al
rep stosb
mov ax,offset cgroup: heaptop
mov [bp].heap,ax
msdos F_SWITCHAR,0
mov [bp].swchr,dl
VZ_RET
init endp
init2 proc
mov dx,offset cgroup: psp_dta
msdos F_SETDTA
mov ax,[bp].heap
add ax,STACKSZ
call ofs2seg
mov cx,cs
add ax,cx
mov [bp].dslottop,ax
mov [bp].dslotseg,ax
VZ_RET
init2 endp
init3 proc
mov ax,[bp].dslotseg
mov [bp].dslotmax,ax
test [bp].option,OPT_V+OPT_C
_ifn z
mov [bp].verifyseg,ax
add ax,CPYBFPARA
_endif
mov [bp].cpybftop,ax
VZ_RET
init3 endp
ofs2seg proc
push cx
add ax,15
and ax,0FFF0h
mov dx,ax
mov cl,4
shr ax,cl
pop cx
VZ_RET
ofs2seg endp
nextseg proc
call ofs2seg
mov dx,ds
add ax,dx
VZ_RET
nextseg endp
;----- Display copied info -----
disp_info proc
mov dx,[bp].totalfiles
call disp_files
test [bp].option2,OPT_E
_ifn z
test [bp].option2,OPT_DEL
jnz info_del
mov si,offset cgroup: mg_found
jmp info8
_endif
test [bp].option,OPT_C
_ifn z
mov si,offset cgroup: mg_comped
mov dx,[bp].totalng
tst dx
_ifn z
call putmsg
call putcrlf
call disp_files
mov si,offset cgroup: mg_compng
_endif
jmp info8
_endif
test [bp].mode,MOV_SAMEDRV
_ifn z
mov si,offset cgroup: mg_moved
jmps info8
_endif
test [bp].option2,OPT_DEL
_ifn z
info_del: mov si,offset cgroup: mg_deleted
jmps info8
_endif
mov al,'('
call putc
ldl [bp].totalsize
cmp dx,16
_if ae
pushm <ax,dx>
mov cl,4
shr dx,cl
clr ch
call putnumber
mov al,'.'
call putc
popm <dx,ax>
mov cl,12
shl dx,cl
mov cl,4
shr ax,cl
or ax,dx
clr dx
mov cx,6554
div cx
add al,'0'
call putc
mov al,'M'
_else
tst dx
_if z
tst ax
_ifn z
cmp ax,1024
_if b
mov ax,1024
_endif
_endif
_endif
mov cl,10
shr ax,cl
mov cl,6
shl dx,cl
or dx,ax
clr ch
call putnumber
mov al,'K'
_endif
push ax
call putspc
pop ax
call putc
mov si,offset cgroup: mg_copied
test [bp].option2,OPT_M
jz info8
mov si,offset cgroup: mg_Bmoved
info8: call putmsg
call putcrlf
VZ_RET
disp_info endp
disp_files proc
mov ch,10
call putnumber
mov si,offset cgroup: mg_files
call putmsg
VZ_RET
disp_files endp
;----- Display error message -----
;--> AL :error code
; DX :parameter
;<-- AL :error level
disp_error proc
movseg ds,cs
mov si,offset cgroup: mg_error
cmp al,5
_if e
mov al,ER_ACCESS
_endif
tst al
_ifn s
push ax
call putmsg
pop dx
clr ch
call putnumber
mov al,EL_UNEXP
_else
mov cx,ax
and cx,7Fh
push ax
_repeat
call strskip
_loop
lodsb
mov cl,al
pop ax
call putmsg
cmp al,ER_OPTION
_if e
mov al,[bp].swchr
call putc
mov al,dl
call putc
_else
cmp al,ER_ACCESS
_if e
mov si,dx
cmp si,offset cgroup: pathbuf
_if e
call puts
_endif
_endif
_endif
mov al,cl
_endif
call putcrlf
VZ_RET
disp_error endp
;----- Display parameters -----
;--> AL :error code
IFDEF DEBUG
disp_parm proc
mov si,[bp].srcdir
tst si
_ifn z
mov al,'<'
call putc
call puts
call putcrlf
_endif
mov si,[bp].srcmask
tst si
_ifn z
_repeat
lodsb
tst al
_break z
tst al
_if s
mov al,'-'
_else
mov al,'+'
_endif
call putc
call puts
_until
call putcrlf
_endif
mov si,[bp].dstdir
tst si
_ifn z
mov al,'>'
call putc
call puts
call putcrlf
_endif
VZ_RET
disp_parm endp
ENDIF
;------------------------------------------------
; Parse paramters
;------------------------------------------------
;<-- CY :error (AL:error code)
parse_parm proc
mov di,[bp].heap
mov [bp].parmlist,di
mov [bp].parmcnt,0
mov si,offset cgroup: psp_cmdline
parm_read:
call skipspc
jc parm_src
cmp al,[bp].swchr
_if e
inc si
call read_option
jnc parm_read
VZ_RET
_endif
cmp al,'['
_if e
test [bp].mode,MASK_NOT
jnz syntax1
mov [bp].mode,MASK_NOT
jmps parm_ex
_endif
cmp al,']'
_if e
test [bp].mode,MASK_NOT
jz syntax2
mov [bp].mode,0
parm_ex: inc si
jmp parm_read
_endif
cmp al,'@' ; @filelist
_if e
or [bp].mode,RESPFILE
push si
inc si
cmp byte ptr [si],SPC
_if be
clr dl
pop cx
jmp defref
_endif
jmps parmpars
_endif
push si
parmpars: call parse_path
pop cx
jmpl c,parm_syntax
tst dl
syntax2: jz parm_syntax
or dl,[bp].mode
defref: mov [di].pl_prsf,dl
mov [di].pl_parmp,cx
mov [di].pl_namep,bx
mov [di].pl_nextp,si
add di,type Parmlist
inc [bp].parmcnt
jmp parm_read
parm_src:
test [bp].mode,MASK_NOT
syntax1: jnz parm_syntax
tstw [bp].parmcnt
mov al,ER_HELP
jz parm_x
call read_ref
jc parm_x
jz parm_mask
call loadparmlist
test dl,MASK_NOT
_if z
test dl,PRS_NAME
_ifn z
test dl,PRS_WILD
_if z
call file_to_dir
mov al,ER_FILENG
jc parm_x
_endif
_endif
_endif
xchg bx,cx
mov [bp].srcdir,di
call mkfullpath
mov cx,bx
test dl,PRS_NAME+PRS_EXT
jz parm_mask
mov [bp].srcmask,di
mov al,dl
and al,MASK_NOT+MASK_FILE+MASK_WILD
call copy_mask1
parm_mask:
_repeat
clr si
clr cx
clr dl
parmmsk1: tstw [bp].parmcnt
parmend1: jz parm_end
call read_ref
jc parm_x
jz parmmsk1
call loadparmlist
test dl,PRS_ROOT
_ifn z
tstw [bp].parmcnt
jz parm_dst
parm_syntax: mov al,ER_SYNTAX
parm_x: stc
VZ_RET
_endif
test dl,PRS_EXT+PRS_WILD
_if z
tstw [bp].parmcnt
_if z
test [bp].option,OPT_N+OPT_O+OPT_U
jnz parm_dst
test [bp].option2,OPT_DEL
jz parm_dst
_endif
_endif
tstw [bp].srcmask
_if z
mov [bp].srcmask,di
_endif
call copy_mask
_until
parm_dst:
or [bp].mode,CPY_DST
test dl,PRS_WILD
mov al,ER_DEST
jnz parm_x
test dl,PRS_NAME+PRS_ENDBSL
jz parm_end
test dl,PRS_ENDBSL
_ifn z
dec cx
and dl,not PRS_ENDBSL
_endif
call file_to_dir
_ifn c
mov al,ER_DEST
jz parm_x
_else
test [bp].option,OPT_C
mov al,ER_PATHNG
jnz parm_x
or [bp].mode,CPY_MKDIR
or dl,PRS_ENDDIR
_endif
parm_end:
clr al
stosb
mov [bp].dstdir,di
call mkfullpath
clr al
stosb
mov [bp].heap,di
test [bp].option2,OPT_DEL
jnz parm9
mov si,[bp].srcdir
mov di,[bp].dstdir
call strcmp
mov al,ER_SAME
je parm_x
parm9: clc
VZ_RET
parse_parm endp
;----- Load parameter list -----
;--> DI :parmlist ptr
loadparmlist proc
push di
mov di,[bp].parmlist
mov si,[di].pl_parmp
mov dl,[di].pl_prsf
mov bx,[di].pl_namep
mov cx,[di].pl_nextp
add [bp].parmlist,type Parmlist
dec [bp].parmcnt
pop di
VZ_RET
loadparmlist endp
;----- Read response file -----
;<--
; ZR :no more parm
; CY :@file not found
read_ref proc
mov bx,[bp].parmlist
mov si,[bx].pl_parmp
lodsb
cmp al,'@'
jne rref9
tstb [bx].pl_prsf
_if z
mov dx,offset cgroup:nm_files
_else
mov bx,[bx].pl_nextp
mov byte ptr [bx],0
mov dx,si
_endif
msdos F_OPEN,O_READ
jc rref_x
mov bx,ax
mov cx,8000h
mov dx,di
msdos F_READ
jc rref_x
mov [bp].reftop,di
add dx,ax
mov di,dx
mov [bp].refend,di
msdos F_CLOSE
add [bp].parmlist,type Parmlist
dec [bp].parmcnt
tstw [bp].srcdir
_if z
call set_srcdir
_endif
stz
rref9: clc
VZ_RET
rref_x: mov al,ER_FILENG
stc
VZ_RET
read_ref endp
;----- Set src dir from filelist -----
set_srcdir proc
mov [bp].srcdir,di
mov si,[bp].reftop
push si
call parse_path
pop si
test dl,PRS_DRV+PRS_DIR
_ifn z
mov cx,bx
sub cx,si
rep movsb
clr al
stosb
_else
call getcurdir1
call skipstr
_endif
VZ_RET
set_srcdir endp
;----- Copy mask -----
copy_mask proc
mov al,dl
and al,MASK_NOT+MASK_DIR+MASK_FILE+MASK_WILD
test dl,PRS_EXT+PRS_WILD
_if z
or al,MASK_DIR
stosb
_else
copy_mask1: stosb
mov al,'*'
test dl,PRS_NAME
_if z
stosb
_endif
tst dl
_if s
or [bp].mode,CPY_XMASK
_else
push bx
mov bx,si
test dl,PRS_NAME
_ifn z
cmp [bx],al
jne cpym1
inc bx
_endif
cmp word ptr [bx],'*.'
_ifn e
cpym1: or [bp].mode,CPY_MASK
_endif
pop bx
_endif
_endif
; test dl,PRS_ENDBSL
; _ifn z
; dec cx
; _endif
test dl,PRS_EXT
_ifn z
push bx
mov bx,cx
cmp byte ptr [bx-1],'.'
_if e
dec cx
_endif
pop bx
_endif
; call copy_parm
; VZ_RET
copy_mask endp
;----- Copy a parameter -----
;--> SI :parm. top ptr
; CX :parm. end ptr
; *DI :dst. ptr
copy_parm proc
push cx
sub cx,si
jng cpypar1
mov ah,cl
_repeat
lodsb
call toupper
cmp al,'/'
_if e
mov al,'\'
_endif
stosb
call iskanji
_if c
movsb
dec cx
jz cpypar1
_endif
_loop
call isbslash
jne cpypar1
cmp ah,1
je cpypar1
dec di
cpypar1:
clr al
stosb
pop cx
VZ_RET
copy_parm endp
;----- Make full path -----
;--> SI :parm. top ptr
; CX :parm. end ptr
; DL :result bit (PRS_xxx)
; *DI :dst. ptr
mkfullpath proc
pushm <bx,cx,dx>
call getcurdir
push ax
push di
mov bx,si
mov si,offset cgroup: pathbuf2
movsw
test dl,PRS_DRV
_ifn z
inc bx
inc bx
_endif
test dl,PRS_DIR
jz mkfull1
mov al,[bx]
call isbslash
_ifn e
mkfull1: call strcpy
cmp cx,bx
_if a
cmp si,offset cgroup: pathbuf2 + 4
_if a
mov al,'\'
stosb
_endif
_endif
_endif
mov si,bx
call copy_parm
pop dx
msdos F_CHDIR
pop si
jc mkfull9
xchg si,dx
mov di,si
add si,3
msdos F_CURDIR
call skipstr
call setcurdir
mkfull9: popm <dx,cx,bx>
mov si,cx
VZ_RET
mkfullpath endp
;----- Get drive No. -----
;--> SI :path name ptr
;<-- AL :drive No. (A=1,B=2,..)
getdrive proc
msdos F_CURDRV
tst si
_ifn z
cmp byte ptr [si+1],':'
_if e
mov al,[si]
call toupper
sub al,'A'
_endif
_endif
inc al
VZ_RET
getdrive endp
;----- Get/Set current directory -----
;--> SI :src/dst dir
; AL :drive No.
getcurdir proc
pushm <dx,si,di>
mov di,offset cgroup: pathbuf2
call getcurdir1
mov al,dl
popm <di,si,dx>
VZ_RET
getcurdir endp
getcurdir1 proc
call getdrive
mov dl,al
add al,'A'-1
stosb
mov ax,'\:'
stosw
mov si,di
msdos F_CURDIR
VZ_RET
getcurdir1 endp
setcurdir proc
mov dx,offset cgroup: pathbuf2
msdos F_CHDIR
VZ_RET
setcurdir endp
;----- Change to root directory -----
cd_rootdir proc
mov dx,offset cgroup: pathbuf2
mov si,offset cgroup: pathbuf2 + 3
clr al
xchg [si],al
push ax
msdos F_CHDIR
pop ax
mov [si],al
VZ_RET
cd_rootdir endp
;----- File to directory -----
;--> SI :path ptr
; CX :next ptr
;<-- CY :path not found
; NC,NZ :FA_DIREC
file_to_dir proc
pushm <bx,cx,dx>
mov dx,si
mov bx,cx
clr al
xchg al,[bx]
push ax
msdos F_ATTR,0
pop ax
mov [bx],al
mov ax,cx
popm <dx,cx,bx>
_ifn c
test al,FA_DIREC
_ifn z
and dl,not (PRS_NAME+PRS_EXT)
or dl,PRS_DIR+PRS_ENDDIR
mov bx,cx
_endif
_endif
VZ_RET
file_to_dir endp
;----- Make destination directory -----
;<-- CY :error
make_dstdir proc
pushm <si,ds>
movseg ds,cs
test [bp].mode,CPY_MKDIR
_ifn z
and [bp].mode,not CPY_MKDIR
mov si,[bp].dstdir
_repeat
lodsb
tst al
jz mkdst1
call isbslash
_if e
mov byte ptr [si-1],0
mkdst1: push ax
mov dx,[bp].dstdir
msdos F_MKDIR
pop ax
tst al
jz mkdst8
mov [si-1],al
_else
call iskanji
_if c
inc si
_endif
_endif
_until
_endif
mkdst8: popm <ds,si>
VZ_RET
make_dstdir endp
;----- Read option -----
;<-- CY :unknown option (AL,DL)
read_option proc
lodsb
call toupper
cmp al,'?'
je ropt_help
cmp al,'H'
je ropt_help
push di
mov di,offset cgroup: optsym
mov cx,OPTCNT
repne scasb
pop di
jne ropt_x
cmp al,'D'
_if e
lodsb
call toupper
mov ah,al
lodsb
call toupper
cmp ax,'EL'
mov al,'D'
jne ropt_x
_endif
sub cx,OPTCNT-1
neg cx
mov ax,1
shl ax,cl
or word ptr [bp].option,ax
VZ_RET
ropt_x: mov dl,al
mov al,ER_OPTION
stc
VZ_RET
ropt_help: mov al,ER_HELP
stc
VZ_RET
read_option endp
;----- Parse path name -----
;-->*DS:SI :path name ptr
;<-- CY :syntax error
; DL :result bit (PRS_xxx)
; BX :file name ptr
; CX :file ext ptr
_namep equ <bx>
_extp equ <cx>
_prsf equ <dl>
_namelen equ <dh>
_pathlen equ <di>
_pvc equ <ah>
parse_path proc
push di
clr al
clr _prsf
clr _pathlen
prs_loop1: clr _namelen
prs_loop2: mov _pvc,al
lodsb
inc _pathlen
cmp al,20h
jbe prsdone1
cmp al,':'
je prs_drive
cmp al,'\'
je prs_dir
cmp al,'/'
je prs_dir1
cmp al,'.'
je prs_ext
cmp al,'*'
je prs_wild
cmp al,'?'
je prs_wild
tst al
js prs_name
call isfilename
jc prs_name
prsdone1: jmp prs_done
prs_error:
stc
pop di
VZ_RET
prs_drive:
cmp _pvc,'A'
jne prs_done
cmp _pathlen,2
jne prs_done
or _prsf,PRS_DRV+PRS_ROOT
jmps prsdir2
prs_dir1:
cmp [bp].swchr,'-'
jne prs_done
mov al,'\'
prs_dir:
cmp _pvc,'\'
je prs_error
cmp _pathlen,1
_if e
or _prsf,PRS_ROOT
_endif
prsdir1: or _prsf,PRS_DIR
prsdir2: and _prsf,not (PRS_NAME+PRS_EXT+PRS_WILD)
jmp prs_loop1
prs_ext:
cmp _pvc,'.'
je prsdir1
test _prsf,PRS_EXT
jnz prs_done
or _prsf,PRS_EXT
mov _extp,si
test _prsf,PRS_NAME
_if z
or _prsf,PRS_WILD
_endif
jmp prs_loop1
prs_wild:
or _prsf,PRS_WILD
jmps prsname1
prs_name:
test _prsf,PRS_EXT
_ifn z
cmp _namelen,3
jae prs_error
_endif
cmp _namelen,8
jae prs_error
prsname1: inc _namelen
cmp _pvc,'*'
je prs_error
test _prsf,PRS_EXT
_if z
cmp _namelen,1
_if be
or _prsf,PRS_NAME
mov _namep,si
_endif
_endif
call isalpha
_if c
mov al,'A'
_endif
call iskanji
_if c
inc si
inc _namelen
inc _pathlen
_endif
jmp prs_loop2
prs_done:
cmp _pvc,'.'
_if e
test _prsf,PRS_NAME
_if z
and _prsf,not (PRS_EXT+PRS_WILD)
or _prsf,PRS_DIR+PRS_ENDDIR
_endif
_endif
cmp _pvc,'\'
_if e
test _prsf,PRS_DRV
_ifn z
dec _pathlen
dec _pathlen
_endif
cmp _pathlen,2
_if a
or _prsf,PRS_ENDBSL
_endif
_endif
test _prsf,PRS_EXT
_if z
mov _extp,si
_endif
test _prsf,PRS_NAME
_if z
mov _namep,_extp
_endif
dec _namep
dec _extp
dec si
clc
pop di
VZ_RET
parse_path endp
isbslash proc
cmp al,'\'
_ifn e
cmp al,'/'
_endif
VZ_RET
isbslash endp
;------------------------------------------------
; Read directory
;------------------------------------------------
;
;----- Read directories -----
;<-- CY :out of memory
read_dirs proc
test [bp].option,OPT_S+OPT_G
_ifn z
mov si,offset cgroup: mg_readdir
call putmsg
jmps readdirs1
_endif
mov si,[bp].srcmask
mov cl,MASK_DIR
call scan_mask
jnc readdirs1
_repeat
push si
clr bx
call read_a_dir
pop si
_break c
call strskip
mov cl,MASK_DIR
call scan_mask
_while c
VZ_RET
readdirs1:
clr si
clr bx
; call read_a_dir
; VZ_RET
read_dirs endp
;----- Read a directory -----
;--> SI :sub dir ptr
; BX :parent dir seg
;<-- CY :out of memory
; CX :file count (/S)
read_a_dir proc
test [bp].option,OPT_S+OPT_G
_ifn z
mov al,'.'
call putc
_endif
mov ax,psp_maxseg
sub ax,[bp].dslotseg
jc radir91
cmp ax,0FFFh
_if a
mov ax,0FFFh
_endif
mov cl,4
shl ax,cl
sub ax,64
mov [bp].dslotmax,ax
mov es,[bp].dslotseg
clr di
clr ax
stosw ; ds_size
mov ax,es
xchg [bp].dslotbtm,ax
stosw ; ds_prev
clr al
stosb ; ds_mode
push ds
tst bx
_ifn z
push si
mov ds,bx
mov si,di
tstb [si]
_ifn z
call strcpy
mov al,'\'
stosb
_endif
pop si
mov ds,bx
_else
movseg ds,cs
_endif
tst si
_ifn z
call strcpy
_endif
pop ds
clr al
stosb
mov [bp].dslotp,offset ds_header
tst bx
_if z
test [bp].option,OPT_S+OPT_G
_ifn z
mov si,[bp].srcmask
mov cl,MASK_DIR
call scan_mask
_if c
_repeat
mov cl,FA_DIREC+FA_DIRONLY
call get_dirs
radir91: jc radir9
call strskip
mov cl,MASK_DIR
call scan_mask
_while c
jmps radir8
_endif
_endif
_endif
mov si,offset cgroup: mask_all
test [bp].mode,CPY_MASK
_if z
clr cl
test [bp].option,OPT_S+OPT_G
_ifn z
mov cl,FA_DIREC
_endif
tstw [bp].reftop ; @filelist
_ifn z
call get_files
mov [bp].reftop,0
_else
call get_dirs
_endif
jc radir9
_else
test [bp].option,OPT_S+OPT_G
_ifn z
mov cl,FA_DIREC+FA_DIRONLY
call get_dirs
jc radir9
_endif
mov si,[bp].srcmask
_repeat
mov cl,MASK_FILE
call scan_mask
_break nc
clr cl
call get_dirs
jc radir9
call strskip
_until
_endif
radir8:
clr di
mov ax,[bp].dslotp
stosw ; ES:[0] <-- dslot size
call ofs2seg
add [bp].dslotseg,ax
test [bp].option,OPT_S+OPT_G
jnz read_subdir
radir9: VZ_RET
read_a_dir endp
;----- Read sub-directory -----
read_subdir proc
clr cx
mov di,offset ds_header
_repeat
cmp di,es:ds_size
_break ae
test es:[di].dr_attr,FA_DIREC
_ifn z
push cx
pushm <di,es>
mov bx,es
mov si,di
call read_a_dir
popm <es,di>
pop ax
jc radir9
tst cx
_if z
test [bp].mode,CPY_MASK+CPY_XMASK
_ifn z
mov byte ptr es:[di],0
_endif
_endif
add cx,ax
_else
tstb es:[di]
_ifn z
inc cx
_endif
_endif
add di,type Dirslot
_until
clc
VZ_RET
read_subdir endp
;----- Get directories -----
;--> CL :attribute
; SI :file mask ptr
; ES :dirslot seg
;<-- CY :out of memory
get_dirs proc
push si
mov dx,si
call makesrcpath
mov di,[bp].dslotp
mov bl,cl
mov bh,[bp].option
and cl,FA_DIREC
test [bp].option2,OPT_X
_ifn z
or cl,FA_HIDDEN+FA_SYSTEM
_endif
clr ch
msdos F_FINDDIR
_repeat
jc gdirs8
cmp psp_dta.dta_pack,'.'
je gdirs2
mov al,psp_dta.dta_attr
test al,FA_DIREC
_ifn z
mov al,MASK_NOT+MASK_DIR
jmps gdir_ex
_else
tst bl ; FA_DIRONLY
js gdirs2
test [bp].option2,OPT_A+OPT_B
_ifn z
test al,FA_ARCH
jz gdirs2
_endif
test [bp].mode,CPY_XMASK
_ifn z
mov al,MASK_NOT+MASK_FILE
gdir_ex: pushm <cx,di,es>
movseg es,cs
mov di,offset cgroup: psp_dta.dta_pack
mov cl,al
call check_ex
popm <es,di,cx>
jc gdirs2
_endif
_endif
gdir1:
push cx
mov si,offset cgroup: psp_dta.dta_pack
mov cx,13
rep movsb
mov si,offset cgroup: psp_dta.dta_attr
mov cx,9
rep movsb
clr ax
stosw
pop cx
cmp di,[bp].dslotmax
jae gdirs_x
gdirs2: msdos F_NEXTDIR
_until
gdirs8:
pop dx
push dx
tst bl ; FA_DIRONLY
_ifn s
test bh,OPT_C+OPT_I+OPT_N+OPT_O+OPT_U
_ifn z
call check_dst
_endif
_endif
mov [bp].dslotp,di
clc
skip1
gdirs_x:
stc
pop si
VZ_RET
get_dirs endp
;----- Get files by response file -----
;--> CL :attribute
;<-- CY :out of memory
get_files proc
test [bp].option2,OPT_X
_ifn z
or cl,FA_HIDDEN+FA_SYSTEM
_endif
mov si,[bp].reftop
mov di,[bp].dslotp
gfiles1:
call get_a_file
jc gfiles8
msdos F_FINDDIR
jc gfiles1
cmp psp_dta.dta_pack,'.'
je gfiles1
mov al,psp_dta.dta_attr
test al,FA_DIREC
_if z
test [bp].option2,OPT_A+OPT_B
_ifn z
test al,FA_ARCH
jz gfiles1
_endif
_endif
pushm <cx,si>
mov si,offset cgroup: psp_dta.dta_pack
mov cx,13
rep movsb
mov si,offset cgroup: psp_dta.dta_attr
mov cx,9
rep movsb
clr ax
stosw
popm <si,cx>
cmp di,[bp].dslotmax
jb gfiles1
stc
VZ_RET
gfiles8:
mov dx,offset cgroup: mask_all
mov bh,[bp].option
test bh,OPT_C+OPT_I+OPT_N+OPT_O+OPT_U
_ifn z
call check_dst
_endif
mov [bp].dslotp,di
clc
VZ_RET
get_files endp
;---- Get a file from filelist -----
;-->
;*SI :filelist ptr
;<--
; DS:DX :path buffer ptr
get_a_file proc
cmp si,[bp].refend
_if ae
stc
VZ_RET
_endif
pushm <cx,di,es>
movseg es,ds
push si
call parse_path
pop si
mov di,offset cgroup: pathbuf
test dl,PRS_DRV+PRS_DIR
mov dx,di
_if z
push si
mov si,[bp].srcdir
call strcpy
mov al,'\'
cmp [di-1],al
_ifn e
stosb
_endif
pop si
_endif
_repeat
lodsb
cmp al,SPC
_break be
stosb
_until
clr al
stosb
_repeat
lodsb
cmp al,SPC
_until a
dec si
popm <es,di,cx>
clc
VZ_RET
get_a_file endp
;----- Make read path -----
;--> CS:SI :src/dst dir ptr
; ES :dslot seg
; DS:DX :file mask ptr
;<-- DS:DX :path buffer ptr
makesrcpath proc
mov si,[bp].srcdir
makepath: pushm <di,es>
mov di,offset cgroup: pathbuf
call makepath1
popm <es,di>
VZ_RET
makesrcpath endp
makedstpath proc
movseg es,ds
pushm <dx,ds>
call makedstpath1
popm <ds,si>
tst si
_ifn z
mov al,[si].dr_ren
tst al
_ifn z
call inc_ext
_endif
_endif
movseg ds,cs
VZ_RET
makedstpath endp
makedstpath1 proc
mov si,[bp].dstdir
test [bp].option,OPT_S
_if z
clr ax
mov es,ax
_endif
call makepath
VZ_RET
makedstpath1 endp
makepath1 proc
push bx
pushm <di,ds,es>
movseg ds,cs
movseg es,cs
call strcpy
pop ax
tst ax
_ifn z
mov ds,ax
mov si,offset ds_dirname
tstb [si]
_ifn z
cmp word ptr es:[di-2],'\:'
_ifn e
mov al,'\'
stosb
_endif
call strcpy
_endif
_endif
pop ds
tst dx
_ifn z
cmp word ptr es:[di-2],'\:'
_ifn e
mov al,'\'
stosb
_endif
mov si,dx
call strcpy
_endif
clr al
stosb
pop dx
pop bx
movseg ds,cs
VZ_RET
makepath1 endp
;----- Check destination directory -----
;-->*DI :dslot end ptr
; DX :file mask ptr
; BH :option
check_dst proc
mov [bp].dslotend,di
pushm <di,es>
call makedstpath1
popm <es,di>
mov cx,FA_RDONLY+FA_HIDDEN+FA_SYSTEM
test bh,OPT_O+OPT_C
_ifn z
test bh,OPT_S+OPT_G
_ifn z
or cx,FA_DIREC
_endif
_endif
msdos F_FINDDIR
_if c
test bh,OPT_O+OPT_C
_ifn z
mov di,[bp].dslotp
_endif
VZ_RET
_endif
xdst_loop:
mov di,[bp].dslotp
mov si,offset cgroup: psp_dta.dta_pack
_repeat
cmp di,[bp].dslotend
jae xdst_next
call strcmp
_break e
add di,type Dirslot
_until
test es:[di].dr_attr,FA_DIREC+FA_LABEL
jnz xdst_next
mov si,offset cgroup: psp_dta
test bh,OPT_N
_ifn z
tstl [si].dta_size
jnz xdst_neg
_endif
or es:[di].dr_flag,DR_EXIST
test bh,OPT_I+OPT_U+OPT_C
_ifn z
test bh,OPT_I+OPT_C
_ifn z
push dx
clr bl
ldl [si].dta_size
cmpl es:[di].dr_size
_ifn e
mov bl,DR_SMALL
_if b
mov bl,DR_LARGE
_endif
_endif
tst dx
_if z
tst ax
_ifn s
or bl,DR_MIN
_endif
_endif
or es:[di].dr_flag,bl
pop dx
_endif
test [bp].option,OPT_I+OPT_U
_ifn z
mov ax,[si].dta_date
cmp ax,es:[di].dr_date
jne xdst_new
mov ax,[si].dta_time
cmp ax,es:[di].dr_time
xdst_new: jb xdst_next
xdst_neg: mov byte ptr es:[di],0
_endif
_endif
xdst_next:
msdos F_NEXTDIR
jmpln c,xdst_loop
test bh,OPT_O+OPT_C
_ifn z
xdst_clr:
mov di,[bp].dslotp
_repeat
cmp di,[bp].dslotend
_break ae
test es:[di].dr_attr,FA_DIREC
_if z
test es:[di].dr_flag,DR_EXIST
_if z
mov byte ptr es:[di],0
_endif
_endif
add di,type Dirslot
_until
_endif
mov di,[bp].dslotend
VZ_RET
check_dst endp
;----- Check exclusive dir/mask -----
;--> ES:DI :dir ptr
;<-- CY :found
check_ex proc
mov si,[bp].srcmask
_repeat
call scan_mask
_break nc
call comp_mask
_break c
call strskip
_until
VZ_RET
check_ex endp
;----- Scan mask -----
;--> SI :mask ptr
; CL :search MASK
;<-- CY :found
scan_mask proc
push cx
tst si
jz scmask9
mov ch,cl
and cl,not MASK_NOT
_repeat
lodsb
tst al
jz scmask9
test al,cl
_ifn z
xor al,ch
jns scmask_c
_endif
call strskip
_until
scmask_c: stc
scmask9: pop cx
VZ_RET
scan_mask endp
;----- Compare mask -----
;--> DS:SI :mask ptr
; ES:DI :target name ptr
;<-- CY :matching
comp_mask proc
test byte ptr [si-1],MASK_WILD
_if z
call strcmp
clc
_if e
stc
_endif
VZ_RET
_endif
pushm <si,di>
cpmsk1:
_repeat
lodsb
cmp al,'*'
je cpmsk_a
cmp al,'?'
je cpmsk_q
scasb
jne cpmsk2
tst al
_until z
cpmsk_o: stc
jmps cpmsk9
skip1
cpmsk2:
cmp al,'.'
_if e
dec di
tstb es:[di]
jz cpmsk1
_endif
clc
cpmsk9: popm <di,si>
VZ_RET
cpmsk_a:
_repeat
mov al,es:[di]
inc di
tst al
_break z
cmp al,'.'
_until e
dec di
jmp cpmsk1
cpmsk_q:
mov al,es:[di]
tst al
_ifn z
cmp al,'.'
_ifn e
inc di
_endif
_endif
jmp cpmsk1
comp_mask endp
;------------------------------------------------
; Do copy
;------------------------------------------------
;
;----- Copy main -----
;<-- CY :error
; AX :error code/level
assume ds:DSheader
do_copy proc
mov ax,[bp].cpybftop
mov [bp].cpybfend,ax
mov ax,[bp].dslottop
_repeat
cmp ax,[bp].dslotmax
_break ae
mov ds,ax
mov si,offset ds_header
_repeat
cmp si,ds_size
_break ae
tstb [si]
_ifn z
pushm <si,ds>
test [bp].option2,OPT_E
_ifn z
call echo_file
_else
test [bp].mode,MOV_SAMEDRV
_if z
call copy_file
_else
call move_file
_endif
_endif
popm <ds,si>
jc docpy9
_endif
add si,type Dirslot
_until
mov ax,si
call nextseg
_until
test [bp].option2,OPT_E
_if z
test [bp].mode,MOV_SAMEDRV
_if z
call do_flush
jc docpy9
_endif
_endif
mov al,EL_OK
docpy9: VZ_RET
do_copy endp
assume ds:cgroup
;----- Copy a file -----
;--> DS:SI :dslot ptr
;<-- CY :error
copy_file proc
mov word ptr [bp].dslot_t,si
mov word ptr [bp].dslot_t+2,ds
push ds
pushm <si,ds>
call req_cpybf
popm <ds,si>
jc cfile9
mov word ptr es:[di].cb_dslot,si
mov word ptr es:[di].cb_dslot+2,ds
test [si].dr_attr,FA_DIREC
_ifn z
clr ax
clr bx
movseg ds,es
jmps cfile2
_endif
push es
movseg es,ds
mov dx,si
call makesrcpath
pop es
msdos F_OPEN,O_READ
jc cfile9
mov bx,ax
test [bp].option,OPT_I
_ifn z
test [bp].option,OPT_C
_if z
call check_inc
jc cfile9
_endif
_endif
_repeat
call disp_readmsg
movseg ds,es
mov cx,CPYBFSIZE
mov dx,type CBheader
msdos F_READ
jc cfile9
cfile2: push ax
mov [di].cb_size,ax
call nextseg
inc ax
mov [di].cb_next,ax
mov [bp].cpybfend,ax
pop ax
cmp ax,CPYBFSIZE
_break b
push bx
call req_cpybf
pop bx
jc cfile9
_until
tst bx
_ifn z
msdos F_CLOSE
_endif
cfile9: pop ds
VZ_RET
copy_file endp
;----- Requst copy buffer -----
;<-- ES:DI :copy buffer seg.
; CY :error
req_cpybf proc
mov ax,[bp].cpybfend
add ax,CPYBFPARA+1
cmp ax,cs:psp_maxseg
_if ae
call do_flush
jc req9
ldl [bp].dslot_t
stl [bp].dslot_w
_endif
mov es,[bp].cpybfend
clr di
clr ax
mov cx,8
rep stosw
clr di
req9: VZ_RET
req_cpybf endp
;----- Flush buffer -----
;<-- CY :error
do_flush proc
call make_dstdir
mov [bp].fh_c,0
test [bp].option,OPT_C
jnz flush1
mov bx,[bp].fh_w
tst bx
_ifn z
clr cx
clr dx
msdos F_SEEK,1
mov es,[bp].cpybftop
stl es:cb_seek
_endif
mov ax,[bp].cpybftop
_repeat
mov [bp].cpybf_p,ax
mov bx,[bp].fh_w
tst bx
_if z
mov al,CR
_else
call putspc
mov al,BS
_endif
call putc
call open_write
jc flush9
call do_write
jc flush9
mov di,bx
call close_file
jc flush9
mov [bp].fh_w,di
mov ax,[bp].cpybf_q
cmp ax,[bp].cpybfend
_until ae
test [bp].option,OPT_V
_ifn z
tstw [bp].fh_w
_if z
mov si,offset cgroup: mg_verify
call putmsg
mov al,CR
call putc
_else
mov al,'V'
call putc
mov al,BS
call putc
_endif
flush1: call do_verify
jc flush9
mov bx,[bp].fh_c
tst bx
_ifn z
lds si,[bp].dslot_w
call close1
_endif
_endif
mov ax,[bp].cpybftop
mov [bp].cpybfend,ax
flush9: VZ_RET
do_flush endp
;----- Open for write -----
;<-- CY :error
open_write proc
mov ax,[bp].cpybf_p
openw1:
cmp ax,[bp].cpybfend
jmpl ae,openw5
mov es,ax
clr bx
lds dx,es:[bx].cb_dslot
tst dx
_ifn z
push es
pushm <dx,ds>
call makedstpath
popm <es,si>
mov ax,es
test es:[si].dr_attr,FA_DIREC
pop es
_ifn z
test [bp].option,OPT_G
_if z
push es
mov es,ax
call makedir
pop es
jc openw9
_endif
clr ax
mov ax,HANDLE_DIR
_else
openw2:
test [bp].option,OPT_G
_ifn z
tstb [bp].openwcnt
jnz openw3
_endif
call open_w
_ifn c
test [bp].option,OPT_G
_ifn z
call open_gather
jc openw2
_endif
_else
cmp ax,5
_if e
clr cx
msdos F_ATTR,1
call open_w
jnc openw4
_endif
cmp ax,2
_if e
create1: clr cx
msdos F_CREATE
jnc openw4
_endif
cmp ax,4
stc
jne openw9
openw3: mov ax,es
jmps openw5
_endif
openw4: inc [bp].openwcnt
_endif
mov es:cb_fh_w,ax
_endif
mov ax,es:cb_next
jmp openw1
openw5:
mov [bp].cpybf_q,ax
clc
openw9: VZ_RET
open_write endp
open_w proc
mov al,O_WRITE
test [bp].option,OPT_V
_ifn z
mov al,O_UPDATE
_endif
msdos F_OPEN
VZ_RET
open_w endp
;----- Open for /g -----
;<-- CY :rename and retry
open_gather proc
push dx
push ax
clr cx
msdos F_FINDDIR
lds si,es:cb_dslot
ldl cs:psp_dta.dta_time
cmpl [si].dr_time
_if e
ldl cs:psp_dta.dta_size
cmpl [si].dr_size
_if e
pop ax
pop dx
clc
VZ_RET
_endif
_endif
pop bx
msdos F_CLOSE
inc [si].dr_ren
mov al,[si].dr_ren
pop dx
call inc_ext
stc
VZ_RET
open_gather endp
inc_ext proc
aam
add ax,3030h
xchg al,ah
push ax
movseg ds,cs
mov si,dx
_repeat
lodsb
cmp al,'.'
_break e
tst al
_until z
mov word ptr [si-1],'0.'
inc si
pop [si]
mov byte ptr [si+2],0
VZ_RET
inc_ext endp
;----- Write file -----
;<-- CY :error
; BX :active handle
do_write proc
mov ax,[bp].cpybf_p
mov bx,[bp].fh_w
_repeat
cmp ax,[bp].cpybf_q
_break ae
mov ds,ax
clr si
mov ax,[si].cb_fh_w
tst ax
_ifn z
cmp ax,HANDLE_DIR
je write2
mov bx,ax
pushm <si,ds>
lds si,[si].cb_dslot
call disp_fname
popm <ds,si>
call do_seek
jc write9
_endif
mov cx,[si].cb_size
mov dx,type CBheader
msdos F_WRITE
jc write9
cmp ax,cx
_if b
mov [bp].fh_full,bx
clr bx
jmps write8
_endif
cmp cx,CPYBFSIZE
_if b
tst cx
_ifn z
clr cx
msdos F_WRITE
jc write9
_endif
clr bx
call putcrlf
_else
mov al,'.'
call putc
_endif
write2: mov ax,[si].cb_next
_until
mov al,0
tst bx
_ifn z
mov al,-1
_endif
mov [bp].readmsgf,al
write8: clc
write9: VZ_RET
do_write endp
;----- Close files -----
;<-- CY :error
; DI :active handle
close_file proc
mov bx,[bp].fh_w
tst bx
_ifn z
cmp bx,di
je close9
tstw [bp].fh_v
_ifn z
mov [bp].fh_c,bx
_else
lds si,[bp].dslot_w
call close1
jc close9
_endif
_endif
mov ax,[bp].cpybf_p
_repeat
cmp ax,[bp].cpybf_q
_break ae
mov ds,ax
clr si
mov bx,[si].cb_fh_w
tst bx
_ifn z
cmp bx,di
_ifn e
mov [si].cb_fh_w,si
cmp bx,HANDLE_DIR
_ifn e
push ds
lds si,[si].cb_dslot
call close1
pop ds
jc close9
_endif
_endif
_endif
clr si
mov ax,[si].cb_next
_until
tstw [bp].fh_full
_ifn z
mov al,ER_DSKFULL
stc
_endif
close9: VZ_RET
close_file endp
;----- Close/Delete a file -----
;<-- CY :error
close1 proc
dec [bp].openwcnt
mov ax,[bp].fh_full
cmp ax,HANDLE_FULL
je delete1
cmp bx,ax
_if e
mov [bp].fh_full,HANDLE_FULL
delete1: msdos F_CLOSE
mov dx,si
call makedstpath
msdos F_DELETE
_else
inc [bp].totalfiles
ldl [si].dr_size
add word ptr [bp].totalsize,ax
adc word ptr [bp].totalsize+2,dx
mov cx,[si].dr_time
mov dx,[si].dr_date
msdos F_STAMP,1
msdos F_CLOSE
jc close19
test [bp].option2,OPT_B
_ifn z
pushm <si,ds>
movseg es,ds
mov dx,si
call makesrcpath
msdos F_ATTR,0
_ifn c
and cl,not FA_ARCH
msdos F_ATTR,1
_endif
popm <ds,si>
_endif
mov al,[si].dr_attr
test al,FA_RDONLY+FA_HIDDEN+FA_SYSTEM
_ifn z
; test [bp].option,OPT_I+OPT_U
; _if z
push ax
mov dx,si
call makedstpath
msdos F_ATTR,0
pop ax
or cl,al
msdos F_ATTR,1
; _endif
_endif
_endif
close19: VZ_RET
close1 endp
;----- Verify destination file -----
;<-- CY :error
do_verify proc
mov ax,[bp].cpybftop
mov es,ax
mov bx,[bp].fh_v
test [bp].option,OPT_C
_if z
tst bx
jnz verify1
_endif
_repeat
cmp ax,[bp].cpybfend
_break ae
mov es,ax
mov ax,es:cb_fh_w
tst ax
_ifn z
mov bx,ax
jmps verify1
_endif
lds si,es:cb_dslot
tst si
jz verify2
test [si].dr_attr,FA_DIREC
_if z
push si
test [bp].option,OPT_C
_ifn z
inc [bp].totalfiles
call disp_fname
pop si
test [si].dr_flag,DR_LARGE+DR_SMALL
_ifn z
mov ax,offset cgroup: mg_large
test [si].dr_flag,DR_SMALL
_ifn z
mov ax,offset cgroup: mg_small
_endif
mov si,ax
call putmsg
call putcrlf
inc [bp].totalng
jmps verify3
_endif
push si
_endif
pop dx
push es
call makedstpath
pop es
msdos F_OPEN,O_READ
jc verify9
mov bx,ax
verify1:
mov dx,word ptr es:cb_seek
mov cx,word ptr es:cb_seek+2
msdos F_SEEK,0
jc verify9
verify2: tst bx
_ifn z
call verify_block
jc verify9
_endif
_endif
verify3: mov ax,es:cb_next
_until
clc
mov [bp].fh_v,bx
verify9: VZ_RET
do_verify endp
;----- Verify one block -----
;<-- CY :error
verify_block proc
clr si
mov cx,es:[si].cb_size
mov ds,[bp].verifyseg
clr dx
msdos F_READ
jc verb9
cmp cx,CPYBFSIZE
_if b
cmp bx,[bp].fh_c
_ifn e
push ax
msdos F_CLOSE
pop ax
_endif
clr bx
_endif
push ax
cmp ax,cx
jne verb_x
clr si
mov di,type CBheader
shr cx,1
lahf
repe cmpsw
jne verb_x
test ah,1
_ifn z
cmpsb
_ifn e
verb_x:
pop ax
test [bp].option,OPT_C
_ifn z
mov si,offset cgroup: mg_mis
call putmsg
call putcrlf
inc [bp].totalng
tst bx
_ifn z
msdos F_CLOSE
jc verb9
clr bx
_endif
VZ_RET
_else
mov al,ER_VERIFY
stc
VZ_RET
_endif
_endif
_endif
pop ax
test [bp].option,OPT_C
_ifn z
cmp ax,CPYBFSIZE
_if b
call putcrlf
_else
mov al,'.'
call putc
_endif
_endif
clc
verb9: VZ_RET
verify_block endp
;----- Check for Incremental copy -----
;--> ES :copy buffer seg
; BX :read handle
check_inc proc
lds si,es:cb_dslot
cmp [si].dr_flag,DR_EXIST+DR_LARGE
clc
jne chkinc9
mov dx,si
push es
call makedstpath
pop es
msdos F_OPEN,O_READ
jc chkinc9
push bx
mov bx,ax
clr cx
clr dx
msdos F_SEEK,2
sub ax,CMPMIN
sbb dx,0
and ax,not(CMPSIZE-1)
pushm <ax,dx>
mov cx,dx
mov dx,ax
msdos F_SEEK,0
movseg ds,es
mov cx,CMPSIZE+CMPMIN
mov dx,type CBheader
mov si,dx
msdos F_READ
push ax
msdos F_CLOSE
pop ax
popm <cx,dx>
pop bx
push ax
msdos F_SEEK,0
pop cx
mov dx,type CBheader
add dx,cx
mov di,dx
msdos F_READ
clr dx
repe cmpsb
mov di,0
je chkinc8
_ifn cxz
clr cx
msdos F_SEEK,0
jmps chkinc9
_endif
not cx
not dx
chkinc8:
msdos F_SEEK,1
stl [di].cb_seek
chkinc9: VZ_RET
check_inc endp
;---- Seek file -----
;<-- CY :error
do_seek proc
mov dx,word ptr [si].cb_seek
mov cx,word ptr [si].cb_seek+2
mov ax,cx
or ax,dx
_ifn z
msdos F_SEEK,0
shl ax,1
rcl dx,1
mov cx,dx
_ifn cxz
_repeat
mov al,'*'
call putc
_loop
_endif
_endif
VZ_RET
do_seek endp
;----- Make directory -----
;--> ES:SI :dslot ptr
; DS:DX :dir name
;<-- CY :error
makedir proc
msdos F_ATTR,0
_ifn c
test cl,FA_DIREC
jnz mkdir9
_endif
test [bp].option2,OPT_T
_if z
msdos F_MKDIR
jc mkdir9
_else
mov di,dx
msdos F_GETDATE
pushm <cx,dx>
msdos F_GETTIME
pushm <cx,dx>
mov ax,es:[si].dr_date
mov dx,ax
mov cl,3
shl dx,cl
and dh,1111b
mov dl,al
and dl,11111b
mov cl,9
shr ax,cl
add ax,1980
mov cx,ax
msdos F_SETDATE
mov ax,es:[si].dr_time
mov dh,al
shl dh,1
and dh,111110b
clr dl
mov cl,3
shr ax,cl
mov cx,ax
shrm cl,2
msdos F_SETTIME
mov dx,di
msdos F_MKDIR
popm <dx,cx>
msdos F_SETTIME
popm <dx,cx>
msdos F_SETDATE
mov dx,di
_endif
mov cl,es:[si].dr_attr
test cl,FA_RDONLY+FA_HIDDEN+FA_SYSTEM
_ifn z
and cl,not FA_DIREC
clr ch
msdos F_ATTR,1
_endif
clc
mkdir9: VZ_RET
makedir endp
;----- Display read message -----
disp_readmsg proc
tstb [bp].readmsgf
_if le
mov [bp].readmsgf,TRUE
_if z
mov si,offset cgroup: mg_read
call putmsg
_else
mov al,'R'
call putc
mov al,BS
call putc
_endif
_endif
VZ_RET
disp_readmsg endp
;----- Display file name -----
;--> DS:SI :dslot ptr
assume ds:DSheader
disp_fname proc
mov al,TRUE
xchg ds_mode,al
tst al
_if z
pushm <si,ds,es>
movseg es,ds
clr dx
call makesrcpath
mov si,offset cgroup: mg_blank
call putmsg
call putcrlf
mov si,dx
call puts
test [bp].option2,OPT_DEL
_if z
call putspc
mov si,offset cgroup: mg_arrow
test [bp].option,OPT_C
_if z
inc si
_endif
call putmsg
clr dx
movseg ds,es
call makedstpath
mov si,dx
call putmsg
_endif
call putcrlf
popm <es,ds,si>
_endif
push si
call putfname
pop si
mov al,[si].dr_ren
tst al
_ifn z
pushm <ds,es>
push ax
mov dx,offset cgroup: pathbuf
mov di,dx
movseg es,cs
call strcpy
pop ax
call inc_ext
mov si,offset cgroup: mg_as
call putmsg
mov si,dx
call putfname
popm <es,ds>
_endif
VZ_RET
disp_fname endp
putfname proc
call putspc
call putspc
clr cx
_repeat
lodsb
tst al
_break e
cmp al,'.'
_break e
call putc
inc cx
_until
dec si
_repeat
cmp cx,8
_break e
call putspc
inc cx
_until
_repeat
lodsb
tst al
_break e
call putc
inc cx
_until
_repeat
cmp cx,14
_break e
call putspc
inc cx
_until
VZ_RET
putfname endp
assume ds:cgroup
;----- Echo files -----
echo_file proc
test [si].dr_attr,FA_DIREC
_if z
call disp_fname
call putcrlf
test [bp].option2,OPT_DEL
_if z
inc [bp].totalfiles
_endif
_endif
VZ_RET
echo_file endp
;------------------------------------------------
; Do move / delete
;------------------------------------------------
;
;----- Init move -----
init_move proc
mov si,[bp].srcdir
call getdrive
push ax
mov si,[bp].dstdir
call getdrive
pop dx
cmp al,dl
_if e
or [bp].mode,MOV_SAMEDRV
_endif
VZ_RET
init_move endp
;----- Move file -----
;--> DS:SI :dslot ptr
;<-- CY :error
move_file proc
call make_dstdir
pushm <si,ds>
mov dx,si
call makedstpath
popm <es,si>
test es:[si].dr_attr,FA_DIREC
_ifn z
call makedir
jc move9
_else
push dx
mov dx,si
mov si,[bp].srcdir
mov di,offset cgroup: pathbuf2
movseg ds,es
call makepath1
pop di
movseg es,ds
msdos F_RENAME
_if c
cmp ax,5
stc
jne move9
xchg dx,di
clr cx
msdos F_ATTR,1
msdos F_DELETE
xchg dx,di
msdos F_RENAME
xchg dx,di
jc move9
_endif
inc [bp].totalfiles
_endif
move9: VZ_RET
move_file endp
;----- Do delete -----
;<-- CY :error
; AX :error code/level
do_delete proc
test [bp].mode,MOV_SAMEDRV
_ifn z
test [bp].mode,CPY_MASK+CPY_XMASK
jnz dodel9
test [bp].option,OPT_S+OPT_G
jz dodel9
_else
test [bp].option2,OPT_M
_ifn z
test [bp].option2,OPT_E
jnz dodel9
mov si,offset cgroup: mg_delete
call putmsg
call delete_dirs
call putcrlf
jmps dodel9
_endif
_endif
call delete_dirs
dodel9: mov al,EL_OK
clc
VZ_RET
do_delete endp
;----- Init delete -----
init_del proc
movseg ds,cs
movseg es,cs
mov di,offset cgroup: fcb
mov byte ptr [di-7],0FFh
mov al,FA_RDONLY
test [bp].option2,OPT_X
_ifn z
or al,FA_HIDDEN+FA_SYSTEM
_endif
mov [di-1],al
mov si,[bp].srcdir
call getdrive
stosb
mov al,'?'
mov cx,11
rep stosb
call getcurdir
call cd_rootdir
VZ_RET
init_del endp
;----- Delete directories -----
assume ds:DSheader
delete_dirs proc
call init_del
msdos F_CTRL_C,0
push dx
mov dl,1
msdos F_CTRL_C,1
mov ax,[bp].dslotbtm
_repeat
mov ds,ax
mov es,ax
test [bp].mode,MOV_SAMEDRV
_if z
test [bp].mode,CPY_MASK+CPY_XMASK+CPY_DST+RESPFILE
_if z
call del_fcb
_else
call del_handle
_endif
_endif
tstb ds_dirname
_ifn z
push ds
clr dx
call makesrcpath
call rmdir
pop ds
_endif
mov ax,ds_prev
tst ax
_until z
movseg ds,cs
mov dx,[bp].srcdir
call rmdir
call setcurdir
pop dx
msdos F_CTRL_C,1
VZ_RET
delete_dirs endp
rmdir proc
test [bp].mode,CPY_MASK+CPY_XMASK
_if z
test [bp].option,OPT_S+OPT_G
_ifn z
msdos F_RMDIR
_endif
_endif
VZ_RET
rmdir endp
;----- Delete by FCB -----
del_fcb proc
mov si,offset ds_header
mov al,FALSE
_repeat
cmp si,ds_size
_break ae
tstb [si]
_ifn z
test [si].dr_attr,FA_DIREC
_if z
mov al,TRUE
test [bp].option2,OPT_DEL
_ifn z
inc [bp].totalfiles
_endif
_endif
_endif
add si,type Dirslot
_until
tst al
_ifn z
push ds
clr dx
call makesrcpath
msdos F_CHDIR
_ifn c
mov dx,offset cgroup: extfcb
msdos 13h ; Delete by FCB
call cd_rootdir
_endif
pop ds
_endif
VZ_RET
del_fcb endp
;----- Delete by file handle -----
del_handle proc
mov si,offset ds_header
_repeat
cmp si,ds_size
_break ae
tstb [si]
_ifn z
test [si].dr_attr,FA_DIREC
_if z
push ds
push si
mov dx,si
call makesrcpath
pop si
test es:[si].dr_attr,FA_RDONLY+FA_HIDDEN+FA_SYSTEM
_ifn z
clr cx
msdos F_ATTR,1
_endif
msdos F_DELETE
_ifn c
test [bp].option2,OPT_DEL
_ifn z
inc [bp].totalfiles
_endif
_endif
pop ds
_endif
_endif
add si,type Dirslot
_until
VZ_RET
del_handle endp
;----- Confirmation -----
confirm proc
test [bp].option2,OPT_DEL
_ifn z
test [bp].option,OPT_S
_ifn z
mov si,[bp].srcdir
tstb [si+3]
_if z
push si
mov si,offset cgroup: mg_confirm
call puts
pop si
lodsb
call putc
mov si,offset cgroup: mg_sure
call puts
msdos F_CONINE
push ax
call putcrlf
pop ax
call toupper
cmp al,'Y'
_ifn e
mov al,EL_BREAK
stc
_endif
_endif
_endif
_endif
VZ_RET
confirm endp
assume ds:cgroup
;------------------------------------------------
; Subroutines
;------------------------------------------------
;
;----- Skip SPC,TAB -----
;<--
; CY :end of line
skipspc proc
lodsb
skipspc1:
cmp al,TAB
je skipspc
cmp al,SPC
je skipspc
skpspc8: dec si
VZ_RET
skipspc endp
;
;----- Skip string -----
;-->*DS:SI :str ptr
strskip proc
pushm <di,es>
mov di,si
movseg es,ds
call skipstr
mov si,di
popm <es,di>
VZ_RET
strskip endp
skipstr proc
push cx
clr al
mov cx,-1
repnz scasb
mov ax,cx
pop cx
VZ_RET
skipstr endp
;
;----- Char to upper case -----
;--> AL :char
;<-- CY :converted
public toupper
toupper proc
call islower
_if c
sub al,'a'-'A'
stc
_endif
VZ_RET
toupper endp
;
;----- Copy string -----
;-->
; DS:SI :source ptr
; ES:DI :destin ptr
public strcpy
strcpy proc
_repeat
lodsb
stosb
tst al
_until z
dec di
VZ_RET
strcpy endp
;
;----- Compare two strings -----
;--> SI,DI :string ptr
;<-- ZR :equal
public strcmp
strcmp proc
pushm <cx,si,di>
cmpsb
jne strcmp9
dec si
dec di
push di
clr al
mov cx,-1
repnz scasb
not cx
pop di
rep cmpsb
strcmp9: popm <di,si,cx>
VZ_RET
strcmp endp
;
;----- Put char/string -----
putspc proc
mov al,SPC
putc proc
push dx
mov dl,al
msdos F_DSPCHR
pop dx
VZ_RET
putc endp
putspc endp
putcrlf proc
push ax
mov al,CR
call putc
mov al,LF
call putc
pop ax
VZ_RET
putcrlf endp
puts proc
pushm <ax,bx,cx,dx,di,es>
movseg es,ds
mov di,si
mov dx,si
clr al
mov cx,-1
repnz scasb
mov si,di
not cx
dec cx
jz puts9
mov bx,1
msdos F_WRITE
puts9: popm <es,di,dx,cx,bx,ax>
VZ_RET
puts endp
putmsg proc
push ds
movseg ds,cs
call puts
pop ds
VZ_RET
putmsg endp
;
;----- Put number -----
;--> DX :word value
; CH :put columns
public putnumber
putnumber proc
putnm1:
cmp ch,6
jbe putnm2
call putspc
dec ch
jmp putnm1
putnm2:
pushm <bx,dx>
mov bx,10000
clr cl
putnm3:
mov ax,dx
clr dx
div bx
tst cl
jnz putnm4
cmp bx,1
je putnm4
tst ax
jnz putnm4
tst ch
jz putnm6
mov al,SPC
jmps putnm5
putnm4:
inc cx
add al,'0'
putnm5: call putc
putnm6: push dx
mov ax,bx
clr dx
mov bx,10
div bx
mov bx,ax
pop dx
tst bx
jnz putnm3
popm <dx,bx>
VZ_RET
putnumber endp
include ctype.inc
;------------------------------------------------
; Messages
;------------------------------------------------
optsym db "CGINOSUVABDME?TX"
mask_all db "*.*",0
nm_files db "\FILES.$$$",0
mg_readdir db "Reading dir(s) ",0
mg_read db "Reading ...",0
mg_verify db "Verify ...",0
mg_delete db "Delete source files ...",0
mg_blank db " ",0
mg_mis db "mismatch!",0
mg_large db "longer",0
mg_small db "shorter",0
mg_arrow db "<--> ",0
mg_as db "as",0
mg_files db " File(s) ",0
mg_copied db "B) copied",0
mg_comped db "compared",0
mg_compng db "mismatched",0
mg_Bmoved db "B) "
mg_moved db "moved",0
mg_deleted db "deleted",0
mg_found db "found",0
mg_confirm db "All files in drive ",0
mg_sure db ": will be deleted!",CR,LF
db "Are you sure (Y/N)? ",0
mg_error label byte
db "Unexpected DOS error: ",0
db EL_OK
db "ZCOPY Version 1.20 Copyright (C) 1992-93 by c.mos",CR,LF
db "Usage: zcopy <src> {<mask>|[<mask>]} [<dst>] {/<opt>}",CR,LF
db " zcopy <src> @filelist [<dst>] {/<opt>}",CR,LF
db 9,"/a: Archive(xcopy /a)",9,9,"/n: No overwrite",CR,LF
db 9,"/b: Backup (xcopy /m)",9,9,"/o: Overwrite only",CR,LF
db 9,"/c: Compare (do not copy)",9,"/s: Subdirectories",CR,LF
db 9,"/del: Delete",9,9,9,"/t: Time stamp copy (with /s)",CR,LF
db 9,"/e: Echo",9,9,9,"/u: Update new files",CR,LF
db 9,"/g: Gather",9,9,9,"/v: Verify",CR,LF
db 9,"/i: Incremental copy",9,9,"/x: hidden files too",CR,LF
db 9,"/m: Move",0
db EL_INIT, "Syntax error",0
db EL_INIT, "Unknown option: ",0
db EL_NOFILE,"File not found",0
db EL_INIT, "Path not found",0
db EL_INIT, "Destination must be a path",0
db EL_INIT, "Source and destination are the same path",0
db EL_INIT, "Access denied: ",0
db EL_DISK, "Insufficient disk space",0
db EL_VERIFY,"Verify failure",0
bpwork Work <>
pathbuf db 80 dup(?)
pathbuf2 db 80 dup(?)
extfcb db 7 dup(?)
fcb db 37 dup(?)
heaptop label byte
endcs
end entry
;------------------------------------------------
; End of zcopy.asm
;------------------------------------------------