;------------------------------------------------ ; 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 mov cl,4 shr dx,cl clr ch call putnumber mov al,'.' call putc popm 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 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 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 mov di,offset cgroup: pathbuf2 call getcurdir1 mov al,dl popm 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 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 _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 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 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 _extp equ _prsf equ
_namelen equ _pathlen equ _pvc equ 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 mov bx,es mov si,di call read_a_dir popm 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 movseg es,cs mov di,offset cgroup: psp_dta.dta_pack mov cl,al call check_ex popm 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 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 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 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 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 mov di,offset cgroup: pathbuf call makepath1 popm VZ_RET makesrcpath endp makedstpath proc movseg es,ds pushm call makedstpath1 popm 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 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 call makedstpath1 popm 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 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 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 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 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 call req_cpybf popm 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 call makedstpath popm 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 lds si,[si].cb_dslot call disp_fname popm 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 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 _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 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 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 msdos F_GETTIME pushm 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 msdos F_SETTIME popm 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 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 _endif push si call putfname pop si mov al,[si].dr_ren tst al _ifn z pushm 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 _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 mov dx,si call makedstpath popm 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 mov di,si movseg es,ds call skipstr mov si,di popm 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 cmpsb jne strcmp9 dec si dec di push di clr al mov cx,-1 repnz scasb not cx pop di rep cmpsb strcmp9: popm 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 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 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 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 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 {|[]} [] {/}",CR,LF db " zcopy @filelist [] {/}",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 ;------------------------------------------------