view level1/cmds/copy.asm @ 1678:40322608e006

tmode is now made from xmode, dsave modified to handle new tmode parameter
author boisy
date Thu, 29 Jul 2004 19:04:12 +0000
parents cc5f6fa1da23
children abdd67f458dd
line wrap: on
line source

********************************************************************
* Copy - File copy utility
*
* $Id$
*
* Edt/Rev  YYYY/MM/DD  Modified by
* Comment
* ------------------------------------------------------------------
*   9      ????/??/??
* From Tandy OS-9 Level Two VR 02.00.01.
*
*  10      ????/??/??  Ron Lamardo
* Reworked.
*
*  11      2003/01/11  Boisy G. Pitre
* Added useful options, made more robust.

         nam   Copy
         ttl   File copy utility

         ifp1
         use   defsfile
         endc

DOHELP   set   0

tylg     set   Prgrm+Objct   
atrv     set   ReEnt+rev
rev      set   $00
edition  set   11

         mod   eom,name,tylg,atrv,start,size

STACKSZ  equ   128	estimated stack size
PARMSZ   equ   256	estimated parameter size
DDIRBSIZ equ   64	destination directory buffer size

         org   0
rdbufptr rmb   2
parmptr  rmb   2
srcpath  rmb   1
dstpath  rmb   1
devtyp   rmb   1
bufsiz   rmb   2
srcflsiz rmb   4
abortflg rmb   1
quiet    rmb   1
single   rmb   1
rewrite  rmb   1
filecnt  rmb   1
srccnt   rmb   1
srcmode  rmb   1
wopt     rmb   1
vopt     rmb   1
srcfname rmb   2
dstfptr  rmb   2
wfileptr rmb   2
wfilelen rmb   2
lstfopen rmb   2		pointer to name of last file attempted open
lstfopln rmb   2		length of last file atteppted open
srcattr  rmb   1
writemsb rmb   2
writelsb rmb   2
fdbufcpy rmb   16
optbuf   rmb   32
wdest    rmb   DDIRBSIZ		portion after '-w='
         rmb   DDIRBSIZ		additional space
* Note: copy buffer must come just before the stack
vfybuff  rmb   256		verify buffer
         IFGT  Level-1
copybuff rmb   8*1024		8K default buffer for Level 2
         ELSE
copybuff rmb   512		512 byte default buffer for Level 1
         ENDC
         rmb   STACKSZ+PARMSZ
size     equ   .

name     fcs   /Copy/
         fcb   edition

SrcPmpt  fcc   /Ready SOURCE, hit C to continue: /
SrcPmptL equ   *-SrcPmpt
DstPmpt  fcc   /Ready DESTINATION, hit C to continue: /
DstPmptL equ   *-DstPmpt
CrRtn    fcb   C$CR
         IFNE  DOHELP
HlpMsg   fcb   C$LF
         fcc   /Use: Copy [<opts>] <srcpath> [<dstpath>] [<opts>]/
         fcb   C$LF
         fcc   /  -a = abort on error/
         fcb   C$LF
         fcc   /  -p = don't print files copied (use with -w)/
         fcb   C$LF
         fcc   /  -r = rewrite destination/
         fcb   C$LF
         fcc   /  -s = single drive copy/
         fcb   C$LF
         fcc   /  -v = verify the copy/
         fcb   C$LF
         fcc   /  -w=<dir> = copy to <dir>/
         fcb   C$LF
         fcc   /  -x = copy from exec dir/
         fcb   C$CR
HlpMsgL  equ   *-HlpMsg
         ENDC
PLIncmp  fcc   /copy: destination must be complete pathlist/
         fcb   C$CR
TooMany  fcc   /copy: must specify output directory if more than 2 files/
         fcb   C$CR
Copying  fcc   /copying /
CopyingL equ   *-Copying
CopyTo   fcc   / to /
CopyToL  equ   *-CopyTo
Cont     fcc   !Continue (y/n) ?!
ContL    equ   *-Cont
CantCpy  fcc   /copy: can't open /
CantCpyL equ   *-CantCpy
SpcDsh   fcc   / - /
SpcDshL  equ   *-SpcDsh

*   +-----------------+  <--  Y          (highest address)
*   !                 !
*   !   Parameter     !
*   !     Area        !
*   !                 !
*   +-----------------+  <-- X, SP
*   !                 !
*   !                 !
*   !   Data Area     !
*   !                 !
*   !                 !
*   +-----------------+
*   !   Direct Page   !
*   +-----------------+  <-- U, DP       (lowest address)
*
*   D = parameter area size
*  PC = module entry point abs. address
*  CC = F=0, I=0, others undefined

start    pshs  u,x
         leax  <wdest,u
         pshs   x
clrnxt   clr   ,u+
         cmpu  ,s
         bne   clrnxt
         leas  2,s
         puls  x,u
         leay  copybuff,u	point Y to copy buffer offset in U
         stx   <parmptr		save parameter pointer
         sty   <rdbufptr	save pointer to buffer
         tfr   s,d		place top of stack in D
         pshs  y		save Y on stack
         subd  ,s++		get size of space between copybuf and X
         subd  #STACKSZ+PARMSZ	subtract out our stack
         std   <bufsiz		size of our buffer
         lbsr  SkipSpcs         move past any spaces on command line
         cmpa  #C$CR		CR?
         lbeq  ShowHelp		if so, show help
GetNChr  lda   ,x+
         cmpa  #C$CR		CR?
         lbeq  CpyFiles		branch if so
         cmpa  #'-		option?
         beq   GetDash
         inc   <filecnt         must be a file
         lbsr  SkipNSpc         else go past non-spaces
ChkDash  lbsr  SkipSpcs         and any following spaces
         bra   GetNChr          and check for Cr
GetDash  lda   #C$SPAC
         sta   -1,x
GetDash2 ldd   ,x+		load option char and char following
         anda  #$5F
         cmpa  #'S		single drive copy?
         bne   IsItA		branch if not
         inc   <single
         lbra  FixCmdLn
IsItA    cmpa  #'A		abort option?
         bne   IsItP		branch if not
         inc   <abortflg
         lbra  FixCmdLn
IsItP    cmpa  #'P		supress output?
         bne   IsItV		branch if not
         inc   <quiet
         bra   FixCmdLn
IsItV    cmpa  #'V		supress output?
         bne   IsItX		branch if not
         inc   <vopt
         bra   FixCmdLn
IsItX    cmpa  #'X		execution dir?
         bne   IsItW		branch if not
         lda   #EXEC.		else get EXEC.
         sta   <srcmode		and save as source mode
         bra   FixCmdLn
IsItW    cmpa  #'W		directory specification?
         bne   IsItR		branch if not
         tst   <wopt		already specified?
         bne   BadOpt		show help if so
         cmpb  #'=		2nd char =?
         bne   BadOpt		show help if not
         inc   <wopt		else tag wopt as specified
         ldb   #C$SPAC		get space
         stb   -$01,x		write over w
         stb   ,x+		and = sign, inc X to dest dir
* check for valid char after -w=
         lda   ,x
         cmpa  #C$SPAC
         lbeq  ShowHelp         
         cmpa  #C$COMA
         lbeq  ShowHelp         
         cmpa  #C$CR
         lbeq  ShowHelp         
         leay  <wdest,u		point Y to parameber buffer
         sty   <dstfptr		save pointer to destination file
         tfr   y,d		transfer Y to D
         addd  #DDIRBSIZ	add size
         pshs  b,a		save updated ptr value
         ldb   #C$SPAC		get space
L0339    lda   ,x		get byte at X
         stb   ,x+		store space at X and inc
         sta   ,y+		save loaded byte at Y and inc
         cmpy  ,s		are we at end?
         beq   L035D		branch if so (buffer too small)
         cmpa  #C$SPAC		else is char in A a space?
         beq   L0350		branch if so
         cmpa  #C$COMA		coma?
         beq   L0350		branch if so
         cmpa  #C$CR		cr?
         bne   L0339		get next byte if not
L0350    leax  -1,x
         sta   ,x		restore previous A
         lda   #PDELIM		get pathlist delimiter
         sta   -$01,y		save slash at end (for building path later)
         sty   <wfileptr	save pointer for -w pathlist file copying
         leas  $02,s		kill stack
         lbra  ChkDash
L035D    leas  $02,s
         ldb   #$BF		else buffer size too small
         orcc  #Carry
         lbra  Exit
IsItR    cmpa  #'R		rewrite?
         bne   BadOpt		branch if not
         inc   <rewrite
FixCmdLn lda   #C$SPAC		get space
         sta   -$01,x		and wipe out option character
         cmpb  #'0
         lblt  ChkDash		start dash option processing again
         lbra  GetDash		possibly another option following?

BadOpt   puls  x
         lbra  ShowHelp

CopyToW  ldx   <srcfname	get ptr to next file to process
* In case the source file name has a / in it (i.e. /dd/x/y/fname),
* we go past the file and then back up to either the first / we
* encounter, or a space (be sure we don't go past parmptr)
         lda   ,x
         cmpa  #C$CR		carriage return?
         lbeq  ExitOk		yep, no more files
         lbsr  SkipNSpc		skip over filename
* X points to first char after file name (space, comma or CR)
L038B    cmpx  <parmptr         are we at start of command line?
         beq   PlugIt2		if so, we can't go further back
         lda   ,-x		get byte
         cmpa  #PDELIM		path delimiter?
         beq   PlugIt           branch if so
         cmpa  #C$SPAC		space?
         beq   PlugIt           branch if so
         cmpa  #C$COMA		comma?
         beq   PlugIt           branch if so
         bra   L038B		else get next char 
PlugIt   leax  1,x		go forward 1
PlugIt2  ldy   <wfileptr	get address past xxxx/ (specified by -w=)
         lbsr  StrCpy		copy filename
         std   <wfilelen	save file length
         lda   #C$CR		get CR
         sta   ,y		and terminate
*         ldx   <wopt
*         stx   <wfileptr
         rts   

* At this point options are processed, so we need to start copying files
CpyFiles tst   <filecnt		we should have at least one file on cmdline
         lbeq  ShowHelp		if not, exit with error
         ldx   <parmptr		get our parameter pointer off stack
         lbsr  SkipSpcs		skip any leading spaces
         tst   <wopt		-w specified?
         beq   L03C5		branch if not
         stx   <srcfname	else save start of parameter pointer as next file
         clr   <single		no single option with -w
L03BE    bsr   CopyToW		copy file at <srcfname to -w buffer
         bra   OpenSrc
* This code handles single file copy (i.e. copy file1 file2)
* or a single disk copy (i.e. copy -s abc)
L03C5    lbsr  GetSDFl		else get source/destination files
         bcc   L03D4		branch if we got both ok
         tst   <single		is this a single drive copy?
         lbne  PListErr		if not, user didn't specify enough files
         lbcs  Exit		if error, exit
* test for right number of files
L03D4    lda   <filecnt		get total file count
         cmpa  #2               should be no more than two files
         ble   OpenSrc
         leax  TooMany,pcr
         lbsr  WrLine
         lbra  ExitOk
OpenSrc  
         ldd   #$0000
         std   <writemsb	clear writemsb/lsb
         std   <writelsb
         ldx   <srcfname	get file to open
         pshs  x
         lbsr  StrLen		get length
         std   <lstfopln	save length
         puls  x
         lda   #READ.		read mode
         ora   <srcmode		or in any additional modes (i.e. EXEC.)
         stx   <lstfopen	save pointer to last file open var
         os9   I$Open   	open source file
         bcc   L03FA		branch if open ok
         cmpx  <srcfname	did open go past pathlist?
         bne   OpenFail		branch if so
         lbsr  SkipNSpc         else skip over failed filename
         lbsr  SkipSpcs         and any trailing spaces
OpenFail stx   <srcfname	save updated pathlist pointer (points to next file on cmd line)
         lbra  ShutDown
L03FA    sta   <srcpath		save source path
         pshs  a		save path
         lbsr  SkipSpcs		destroy any leading spaces
         stx   <srcfname	and save pointer to next source filename
         lbsr  StrLen		get length
         std   <lstfopln	save length
         puls  a		get path off stack
         leax  <fdbufcpy,u	point to FD buffer
         ldy   #FD.SEG		number of bytes
         ldb   #SS.FD
         os9   I$GetStt 	get file's file descriptor
         bcs   L041B		branch if error
         tst   <single		single drive copy?
         beq   L041B		branch if not
         lda   [<dstfptr,u]	get first char of destination filename
         ldb   #E$BPNam		prepare for possible error
         cmpa  #PDELIM		path has leading slash?
         lbne  PListErr		if not, show error
L041B    lda   <srcpath		get source path
         leax  <optbuf,u	point to options buffer
         clrb			was: ldb #SS.Opt
         os9   I$GetStt 	get path options
         lbcs  ShutDown		branch if error
         lda   ,x		get device type
         sta   <devtyp		save
         ldb   #$0F
         cmpa  #DT.RBF		rbf device?
         bne   L0449		branch if not
         pshs  u,x		save regs
         lda   <srcpath		get source path
         ldb   #SS.Size
         os9   I$GetStt 	get size
         lbcs  ShutDown
         stx   <srcflsiz	save file size
         stu   <srcflsiz+2
         puls  u,x		restore regs
         ldb   <PD.ATT-PD.OPT,x	get source file's attributes
L0449    stb   <srcattr		save
         lda   #$01
         lbsr  SwapDsk		check for single disk copy and prompt if necessary
L0450    ldx   <dstfptr		point to destination file
         pshs  x
         lbsr  StrLen		get length
         std   <lstfopln	save length
         puls  x
         lda   #UPDAT.		update mode (in case we have to verify)
         ldb   <srcattr		get source attributes
         stx   <lstfopen
         os9   I$Create 	create file
         bcc   L048B		branch if create ok
         tst   <rewrite		rewrite flag set?
         lbeq  ShutDown		branch if no
         cmpb  #E$CEF		file already exists?
         lbne  ShutDown		branch if any other error
L047A    os9   I$Delete 	delete file first
         lbcs  ShutDown		branch if error
         bra   L0450		else try opening again
L048B    sta   <dstpath		save destination path
         tst   <wopt		w option specified?
         beq   GetOpts		branch iff not
         tst   <quiet		p option specified?
         bne   GetOpts		branch if so
         pshs  a		else save dest path on stack
         leax  >Copying,pcr	else print 'Copying...'
         ldy   #CopyingL
         lbsr  WritSOut		write it to stdout
         ldx   <wfileptr	get pointer to file being copied
         ldy   <wfilelen	get file name length
         lbsr  WritSOut		print file name
         leax  >CopyTo,pcr	print ' to '
         ldy   #CopyToL
         lbsr  WritSOut		write it to stdout
         ldx   <dstfptr		get pointer to file being copied
         lbsr  WrLine		print file with CR
         puls  a		restore dest path
GetOpts  leax  <optbuf,u	point to option buffer
         clrb			was: ldb #SS.Opt
         os9   I$GetStt 	get options
         lbcs  ShutDown		branch if error
         ldb   ,x		get device type
         cmpb  #DT.RBF		rbf?
         bne   CopyLoop		if not rbf device, don't get file size or fd seg
L04B4    lda   <devtyp		get device type
         cmpa  #DT.RBF		rbf?
         bne   CopyLoop		branch if not
         pshs  u		save our statics ptr
         lda   <dstpath		else get dest path
         ldb   #SS.Size		and setstat option
         ldx   <srcflsiz	get file size of source
         ldu   <srcflsiz+2
         os9   I$SetStt 	and set dest file to same size
         lbcs  ShutDown		branch if error
         puls  u		restore U
         lda   <dstpath		get dest path
         leax  <fdbufcpy,u	point to file desc. buffer
         ldy   #FD.SEG		get size
         ldb   #SS.FD
         os9   I$SetStt 	write src fd seg to dest file
* Copy loop is here
CopyLoop ldx   <rdbufptr	get ptr to read buffer
         clra  			A = 0 = source prompt if needed
         lbsr  SwapDsk		check for single disk copy and prompt if so
         lda   <srcpath		get source path
         ldy   <bufsiz		get buffer size
         os9   I$Read   	read it!
         bcs   L0558		branch if error
         lda   #$01		A = 1 = dest prompt
         lbsr  SwapDsk		check for single disk copy and prompt if so
         lda   <dstpath		get dest path
         os9   I$Write  	write it out!
         lbcs  ShutDown		branch if error
         tst   <vopt		verify on?
         beq   chkeof
         lbsr  DoVerify
chkeof   lda   <srcpath		get source path
         ldb   #SS.EOF
         os9   I$GetStt 	are we at end of file?
         bcc   CopyLoop		branch if not
         cmpb  #E$EOF		end of file error?
         beq   L0561		branch if so
L0558    cmpb  #E$EOF		end of file rror?
         bne   ShutDown		branch if not
         lda   #$01		prompt destination flag
         lbsr  SwapDsk		check for single drive copy and prompt if necessary
L0561    lda   <dstpath		get destination path
         os9   I$Close  	close that file
         bcs   ShutDown		branch if error
         clr   <dstpath		else clear dest path
         lda   <srcpath		get source path
         os9   I$Close  	close it
         bcs   ShutDown		branch if error
         clr   <srcpath		clear src path
         tst   <wopt		-w specified
         lbeq  ExitOk		branch if not
         lbra  L03BE

* Entry: X = ptr to data to write, Y = length
WritSOut lda   #$01		standard out
         os9   I$Write  	write it
         rts   

PListErr leax  >PLIncmp,pcr
         bsr   WrLine
         bra   ExitOk

ShutDown pshs  b
         lda   <srcpath		get source path
         beq   L05AA		branch if none
         os9   I$Close  	close it
L05AA    lda   <dstpath		get dest path
         beq   L05B1		branch if none
         os9   I$Close  	close it
L05B1    clr   <srcpath		clear source path
         clr   <dstpath		and destination
         leax  >CantCpy,pcr	else show can't copy error
         ldy   #CantCpyL
         bsr   WritSOut		write out
         ldx   <lstfopen	show filename that failed
         ldy   <lstfopln	get length
         bsr   WritSOut
         leax  >SpcDsh,pcr
         ldy   #SpcDshL
         bsr   WritSOut		write out
         puls  b
PrintErr os9   F$PErr   	print error
         tst   <wopt		-w used?
         beq   ExitOk		branch if not
         tst   <abortflg	abort flag set?
         bne   ExitOk		branch if so
AskAgain leax  >Cont,pcr	point to continue prompt
         ldy   #ContL		get length
         bsr   WritSOut		write
         clra                   ADDED +BGP+
         ldx   <rdbufptr	get pointer at readbuf
         ldy   #$0002		2 bytes
         os9   I$ReadLn 	read form stdin
         lda   ,x		get byte at X
         anda  #$5F
         cmpa  #'Y		user wants to continue?
         lbeq  L03BE		branch if so
         cmpa  #'N		no?
         beq   ExitOk		branch if so
         bra   AskAgain		else ask again

ShowHelp equ   *
         IFNE  DOHELP
         leax  >HlpMsg,pcr	point to help message
         ldy   #HlpMsgL		get length
         lda   #$02		std error
         os9   I$WritLn 	write it
         ENDC
ExitOk   clrb  			clear carry
Exit     os9   F$Exit   	and exit

* Write line passed in X
WrLine   ldy   #$00A0
WrNBytes lda   #$01
         os9   I$WritLn 
         rts   

* Prompt User for Source or Destination Disk
SwapDsk  tst   <single		single disk copy?
         beq   NoSwap		branch if not
         pshs  y,x
L0626    pshs  a
         tsta  
         bne   L0635
         leax  >SrcPmpt,pcr	point to source prompt
         ldy   #SrcPmptL	get size
         bra   L063D		write it and get input
L0635    leax  >DstPmpt,pcr	point to dest prompt
         ldy   #DstPmptL	get size
L063D    bsr   WrNBytes		write it
         leax  ,-s		point to stack for temp buffer
         ldy   #$0001		one byte
         clra  			from std in
         os9   I$Read   	read byte from user
         lda   ,s+		get char
         eora  #'C
         anda  #$DF
         beq   L0657		branch if C
         bsr   L065E
         puls  a
         bne   L0626
L0657    bsr   L065E
         puls  a
         puls  y,x
NoSwap   rts   
L065E    pshs  y,x,a
         lda   #$01
         leax  >CrRtn,pcr
         ldy   #80
         os9   I$WritLn 
         puls  pc,y,x,a

* StrLen
*
* Entry:
*   X = ptr to string (space, comma or CR terminated)
* Exit:
*   D = length of string
*   X = ptr to byte after string
StrLen   pshs  u
         ldu   #$0000
StrLenLp lda   ,x+
         cmpa  #C$SPAC
         beq   StrLenEx
         cmpa  #C$COMA
         beq   StrLenEx
         cmpa  #C$CR
         beq   StrLenEx
         leau  1,u
         bra   StrLenLp
StrLenEx tfr   u,d
         puls  u,pc

* StrCpy
*
* Entry:
*   X = ptr to src string
*   Y = ptr to dest string
* Exit:
*   D = number of bytes copied
*   X = ptr to byte after original string
*   X = ptr to byte after copied string
StrCpy   pshs  u
         ldu   #$0000
CopyFnLp lda   ,x+
         cmpa  #C$SPAC
         beq   CopyFnEx
         cmpa  #C$COMA
         beq   CopyFnEx
         cmpa  #C$CR
         beq   CopyFnEx
         sta   ,y+
         leau  1,u
         bra   CopyFnLp
CopyFnEx tfr   u,d
         puls  u,pc

* Skip over spaces and commas
*
* Entry:
*   X = ptr to string
* Exit:
*   X = ptr to first non-whitespace char
*   A = non-whitespace char
SkipSpcs lda   ,x+
         cmpa  #C$SPAC
         beq   SkipSpcs
         cmpa  #C$COMA
         beq   SkipSpcs
         leax  -1,x
         rts

* Skip over non-spaces and non-commas
*
* Entry:
*   X = ptr to string
* Exit:
*   X = ptr to first non-whitespace char
*   A = non-whitespace char
SkipNSpc lda   ,x+
         cmpa  #C$SPAC
         beq   EatOut
         cmpa  #C$COMA
         beq   EatOut
         cmpa  #C$CR
         bne   SkipNSpc
EatOut   leax  -1,x
         rts

* Get source file in <srcfname and destination file in <dstfptr
GetSDFl  leay  <srcfname,u	point X to next file pointer
         bsr   SrchFile		skip white spaces, look for name on cmd line
         bcs   L067D		branch if end
         inc   <srccnt		else increment souce count
         leay  <dstfptr,u	point Y to destination file
         bsr   SkipSpcs		destroy any leading spaces
         bsr   SrchFile		skip white spaces, look for name on cmd line
L067D    rts   

* Starting at X, parse for a filename, skipping leading white spaces
SrchFile lda   ,x
         cmpa  #C$CR		CR?
         beq   L06A2		branch if so
         stx   ,y		else store X at Y
SkipFile bsr   SkipNSpc         skip non-spaces
ParseOk  clrb  			clear B
         rts  			return 
L06A2    tst   <srccnt		any file specified?
         bne   L06AA		branch if so
BadPName ldb   #E$BPNam		else no source was specified
         coma  
         rts   

L06AA    ldx   <srcfname	get pointer
L06AC    lda   ,x+		get char
         cmpa  #C$SPAC		space?
         beq   L06C4		branch if so
         cmpa  #C$COMA		comma?
         beq   L06C4		branch if so
         cmpa  #C$CR		carriage return?
         beq   L06C4		branch if so
         cmpa  #PDELIM		pathlist delimiter?
         bne   L06AC		branch if not
         clr   <srccnt		else clear file count
         stx   ,y		and store
         bra   L06AC		continue parsing
L06C4    tst   <srccnt		file count 0?
         beq   L06D2		branch if so
         tst   <srcmode		source mode? (exec or data dir)
         beq   BadPName		branch if data
         ldx   <srcfname	else get pointer
         stx   ,y		save
         bra   ParseOk		branch 
L06D2    lda   -$02,x
         cmpa  #PDELIM
         beq   BadPName
         bra   ParseOk

DoVerify
         pshs  u,y        save registers
         ldx   <writemsb  get 2 msb's of last write
         ldu   <writelsb  get 2 lsb's of last write
         lda   <dstpath   get out path number
         os9   I$Seek
         lbcs  Exit       exit on error
         ldu   2,s        get original u back
         leau  copybuff,u point to buffer start
         ldd   ,s         get bytes written
         addd  <writelsb  add on to current 2 lsb positions
         std   <writelsb  save them
         ldd   ,s         get bytes written
         bcc   vfy000     skip if no carry
         leax  1,x        bump up 2 msb's
         stx   <writemsb  and save them

vfy000   ldy   #$0100     chars to read for verify
         std   ,s         save it
         tsta             did we write more than 255 bytes ?
         bne   vfy010     yes...only read 256
         tfr   d,y        else xfer amount we did write

vfy010   ldx   2,s        get u register
         leax  vfybuff,x  point to start of verify buffer
         lda   <dstpath   get output path number
         os9   I$Read     read a block in
         lbcs  Exit       exit on error

vfy020   lda   ,u+        get char from in buffer
         cmpa  ,x+        get char from out buffer
         bne   snderr1    not equal...send write verfiy msg
         leay  -1,y       decrement read count
         bne   vfy020     if more..loop back
         ldd   ,s         get write count back
         subd  #$0100     subtract verify buffer size
         bhi   vfy000     if more left...loop back
         puls  u,y,pc     else restore registers and return

snderr1  leax  errmsg1,pcr address of 'write verify failed' msg
         lbsr  WrLine     send it
         comb             set carry
         ldb   #$01       set error
         lbra  Exit       exit

errmsg1  fcb   C$BELL
         fcc   /Error - write verification failed./
         fcb   C$CR
         
         emod
eom      equ   *
         end