2 TITLE XCOPY WITH FULL MEMORY USE
;AN000;
4 ; ##### R E A D M E #####
6 ; This file contains a copy of the XCOPY code. The code has been
7 ; Revised (additions and many parts commented out) to conform to the
10 ; #########################
12 ;****************** START OF SPECIFICATIONS *****************************
15 ; DESCRIPTIVE NAME: selectively copy groups of files, which can include
16 ; lower level subdirectories.
18 ; FUNCTION: The modules of XCOPY will be placed in the following order -
19 ; SSEG, DSEG(MAIN DATA, MAIN MSG), CSEG (MAIN + INIT),
20 ; DSEG_INIT(INIT DATA, INIT MSG)
22 ; HEADER - informations needed about the file, subdirectory ...
23 ; Continue_Info -> 0 - a whole single file in this header
25 ; 1 - Continuation of a small file.
26 ; 2 - Continuation of a Big file
27 ; 3 - Eof of continuation
28 ; Next_Ptr -> points to the next header segment
29 ; Before_Ptr -> points to the old header segment
31 ; By optionally using the Archive bit in the directory of each
32 ; file, XCOPY can be used as an alternative method of creating
33 ; backup files which can be accessed directly by DOS and its
34 ; applications without the need to "restore" the backup files.
36 ; XCOPY is especially useful when several files are being copied
37 ; and there is a generous amount of RAM available, because XCOPY
38 ; will fill the memory with all the source files it can read in
39 ; before starting to create output files. If the memory is not
40 ; enough to hold all the source, this cycle will be repeated until
41 ; the process is completed. For single drive systems, this maximum
42 ; usage of the memory greatly reduces the amount of diskette
43 ; swapping that would be required by the usual COPY command.
47 ; INPUT: (DOS COMMAND LINE PARAMETERS)
49 ; SOURCE OPERAND: TARGET OPERAND:
51 ; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
53 ; [d:] path [filename[.ext]]
55 ; d: [path] [filename[.ext]]
60 ; /A /D /E /M /P /S /V /W
62 ;The /A switch will copy only those files whose archive bit of the attribute is
63 ;set to one. The attribute of the source file is not changed. This option is
64 ;useful when making multiple backups when doing the non-final backup.
65 ;The archive bit is one when a file has be created or Revised since the last
66 ;time the bit was turned off. XCOPY /M or BACKUP /M will turn this bit off.
67 ;The ATTRIB command can also be used to change the setting of the archive bit.
69 ;The /D switch will copy only those files whose date is the same or later than
70 ;the date specified. Depending on the country code you selected using the
71 ;COUNTRY command, the date is specified in the format corresponding to the
74 ;The /E switch will create subdirectories on the target even if they end up
75 ;being empty after all copying is over. If /E is not specified, empty
76 ;subdirectories are not created.
78 ;The /M switch will copy only those files whose archive bit is set in its
79 ;attribute. Unlike the /A switch, /M will cause the archive bit in the source
80 ;file to be turned off. This allows XCOPY to be used in making a final backup.
81 ;The archive bit is one when a file has be created or Revised since the last
82 ;time the bit was turned off. XCOPY /M or BACKUP /M will turn this bit off.
83 ;The ATTRIB command can also be used to change the setting of the archive bit.
85 ;The /P switch will prompt the operator before copying each file. In this
86 ;situation, each file is copied onto the target before reading in the next
87 ;file. The multi-file copy into a large memory buffer is not done. The prompt
88 ;displays the complete filespec it proposes to copy and asks for (Y/N)
89 ;response, which is then read in from the standard input device.
91 ;The /S switch will not only copy the files in the current source directory but
92 ;also those in all the subdirectories below the current one, with XCOPY
93 ;following the Tree of the subdirectories to access these files. /S does not
94 ;create an empty subdirectory on the target (unless /E is also specified).
95 ;If the /S switch is not specified, XCOPY works only within the specified (or
96 ;current) subdirectory of the source.
98 ;The /V switch will cause DOS to verify that the sectors written on the target
99 ;are recorded properly. This option has been provided so you can verify that
100 ;critical data has been correctly recorded. This option will cause XCOPY to
101 ;run more slowly, due to the additional overhead of verification.
103 ;The /W switch will instruct XCOPY to pause before actually starting the
104 ;movement of data, thus permit the copying of diskettes that do not actually
105 ;have XCOPY available on them. The diskette containing XCOPY can be mounted
106 ;first, the XCOPY command given with the /W option, then when the prompt
107 ;requesting permission to continue is given, that diskette can then be removed
108 ;and the source diskette mounted in its place, then the operator can press any
109 ;key to continue after the pause. This feature is especially useful in a
110 ;non-hardfile system.
112 ; EXIT-NORMAL: ERRORLEVEL_0 - This is the normal completion code.
113 ; ERRORLEVEL_2 - This is due to termination via Control-Break.
114 ; ERRORLEVEL_4 - This is used to indicate an error condition.
116 ; There are many types of problems that are detected and result in this
117 ; return code, such as:
119 ; write failure due to hard disk error
121 ; conflict between name of new subdirectory and existing filename
123 ; too many open files
131 ; reserved file name as source
132 ; insufficient memory
133 ; incorrect DOS version
136 ; INTERNAL REFERENCES:
144 ; EXTERNAL REFERENCES:
152 ; NOTES: This module should be processed with the SALUT pre-processor
153 ; with the re-alignment not requested, as:
157 ; To assemble these modules, the sequential
158 ; ordering of segments may be used.
160 ; For LINK instructions:
161 ; link profile ..\lib
163 ; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
164 ; Remove the BELL char.,turn off APPEND during TREE
165 ; search,Extended Attribute processing, Uppercasing
166 ; and "Out Of Space" during write to standard out.
167 ; A001 PTM0011 XCOPY not handling path >63 characters.
168 ; CHK_MAX_LENGTH proc(XCPYINIT) is Revised to err if
170 ; A002 PTM0012 XCOPY unnecessarily accessing current drive.
171 ; ORG_S_T_DEF is Revised to ignore CHDIR if drive
172 ; is not TARGET or SOURCE.
173 ; A003 PTM0088 XCOPY (\) missing in 'FILE SHARING ERROR'.
174 ; This problem is fixed with incorporation of the
175 ; new message services.
176 ; A005 DCR0201 10/9/87 Incorperate new format for EXTENDED
180 ; Label: "DOS XCOPY Utility"
181 ; "Version 4.00 (C) Copyright 1988 Microsoft"
182 ; "Licensed Material - Program Property of Microsoft"
184 ;****************** END OF SPECIFICATIONS *****************************
186 CLEAR_SCREEN2
MACRO;AN000;
188 MOV DX,184Fh
;;AN000; scroll screen from (0,0) tO (24,79)
189 MOV AX,0600h ;;AN000; AH = 6, Scroll Function
190 ;; AL = 0, Clear scroll area
191 MOV BH,7 ;;AN000; video I/O interrupt
193 MOV DX,0 ;;AN000; RKJ-set cursor posn to top right hand corner
194 MOV BH,0 ;;AN000; RKJ
195 MOV AH,2 ;;AN000; RKJ
198 ;--------------------------------
200 ;--------------------------------
201 INCLUDE STRUC.INC ;AN000; SAR
202 INCLUDE XMAINMSG
.EQU
;AN000;message file
203 INCLUDE DOS
.EQU
;AN000;
204 INCLUDE XCOPY
.EQU
;AN000;
205 INCLUDE PAN
-LIST
.INC ;AN111;JW
206 INCLUDE PANEL
.MAC
;AN111;JW
207 INCLUDE CASEXTRN
.INC ;AN111;JW
210 EXTRN FK_ENT
:BYTE ;AN111;JW
211 EXTRN FK_ENT_LEN
:ABS
;AN111;JW
212 EXTRN E_RETURN
:ABS
;AN111;JW
213 EXTRN S_DOS_SHEL_DISK
:WORD ;AN111;JW
214 EXTRN S_DOS_SEL_360
:WORD ;AN111;JW
215 EXTRN E_FILE_ATTR
:ABS
;AN111;JW
217 EXTRN FIND_FILE_ROUTINE
:FAR ;AN111;JW
218 EXTRN EXIT_SELECT
:near ;AN111;JW
220 ;-------------------------------
222 ;-------------------------------
223 ;HEADER - informations needed about the file, subdirectory ...
224 ;Continue_Info -> 0 - a whole single file in this header segment, or dir.
225 ; 1 - Continuation of a small file.
226 ; 2 - Continuation of a Big file
227 ; 3 - EOF of continuation
228 ;Next_Ptr -> points to the next header segment
229 ;Before_Ptr -> points to the old header segment
232 CONTINUE_INFO
DB 0 ;AN000;set for filesize bigger then 0FFD0h
233 NEXT_PTR
DW ?
;AN000;next buffer ptr in para
234 BEFORE_PTR
DW ?
;AN000;before ptr in para
235 DIR_DEPTH
DB ?
;AN000;same as S_DEPTH
236 CX_BYTES
DW 0 ;AN000;actual # of bytes in this buffer seg.
237 ATTR_FOUND
DB ?
;AN000;attribute found
238 FILE_TIME_FOUND
DW ?
;AN000;
239 FILE_DATE_FOUND
DW ?
;AN000;
240 LOW_SIZE_FOUND
DW ?
;AN000;
241 HIGH_SIZE_FOUND
DW ?
;AN000;
242 TARGET_DRV_LET
DB " :" ;AN000;used for writing
243 FILENAME_FOUND
DB 13 DUP (0) ;AN000; FILENAME
244 ATTRIB_LIST
DB ?
;AC005;EXTENDED ATTRIBUTE BUFFER
245 ;-------------------------------------------------------------------
246 ; extended attribute list used by extended open & get extended
247 ;-------------------------------------------------------------------
248 ; ATTRIB_LIST LABEL BYTE extended attribute buffer
250 ;EA STRUC ; EXTENDED ATTRIBUTE
252 ;EAISUNDEF EQU 0 ; UNDEFINED TYPE (ATTRIB SKIPS)
253 ; ; (OR TYPE NOT APPLICABLE)
254 ; ; LENGTH: 0 TO 64K-1 BYTES
255 ;EAISLOGICAL EQU 1 ; LOGICAL (0 OR 1) (ATTRIB DISPLAYS) ; LENGTH: 1 BYTE
256 ;EAISBINARY EQU 2 ; BINARY INTEGER (ATTRIB DISPLAYS)
257 ; ; LENGTH: 1, 2, 4 BYTES
258 ;EAISASCII EQU 3 ; ASCII TYPE (ATTRIB DISPLAYS)
259 ; ; LENGTH: 0 TO 128 BYTES
260 ;EAISDATE EQU 4 ; DOS FILE DATE FORMAT (ATTRIB DISPLAYS)
262 ;EAISTIME EQU 5 ; DOS FILE TIME FORMAT (ATTRIB DISPLAYS)
264 ; ; OTHER VALUES RESERVED
265 ;EA_FLAGS DW ? ; FLAGS
266 ;EASYSTEM EQU 8000H ; EA IS SYSTEM DEFINED
267 ; ; (BUILTIN, NOT APPLICATION DEFINED)
268 ;EAREADONLY EQU 4000H ; EA IS READ ONLY (CANT BE CHANGED)
269 ;EAHIDDEN EQU 2000H ; EA IS HIDDEN FROM ATTRIB
270 ;EACREATEONLY EQU 1000H ; EA IS SETABLE ONLY AT CREATE TIME
271 ; ; OTHER BITS RESERVED
272 ;EA_RC DB ? ; FAILURE REASON CODE (SET BY DOS)
273 ;EARCNOTFOUND EQU 1 ; NAME NOT FOUND
274 ;EARCNOSPACE EQU 2 ; NO SPACE TO HOLD NAME OR VALUE
275 ;EARCNOTNOW EQU 3 ; NAME CAN'T BE SET ON THIS FUNCTION
276 ;EARCNOTEVER EQU 4 ; NAME CAN'T BE SET
277 ;EARCUNDEF EQU 5 ; NAME KNOWN TO THIS FS BUT NOT SUPPORTED
278 ;EARCDEFBAD EQU 6 ; EA DEFINTION BAD (TYPE, LENGTH, ETC)
279 ;EARCACCESS EQU 7 ; EA ACCESS DENIED
280 ;EARCUNKNOWN EQU -1 ; UNDETERMINED CAUSE
281 ;EA_NAMELEN DB ? ; LENGTH OF NAME
282 ;EA_VALLEN DW ? ; LENGTH OF VALUE
283 ;EA_NAME DB ? ; FIRST BYTE OF NAME
285 ;EA_VALUE DB ? ; FIRST BYTE OF VALUE
289 ;;;;SUB_LIST STRUC ; SAR
290 ;;;; DB 11 ; SAR ;AN000;
291 ;;;; DB 0 ; SAR ;AN000;
292 ;;;;DATA_OFF DW 0 ; SAR ;AN000; offset of data to be inserted
293 ;;;;DATA_SEG DW 0 ; SAR ;AN000; offset of data to be inserted
294 ;;;;MSG_ID DB 0 ; SAR ;AN000; n of %n
295 ;;;;FLAGS DB 0 ; SAR ;AN000; Flags
296 ;;;;MAX_WIDTH DB 0 ; SAR ;AN000; Maximum field width
297 ;;;;MIN_WIDTH DB 0 ; SAR ;AN000; Minimum field width
298 ;;;;PAD_CHAR DB 0 ; SAR ;AN000; character for pad field
300 ;;;;SUB_LIST ENDS ; SAR
301 ;******************************************************************************
302 DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; DATA Segment
304 INCLUDE DOSFILES
.INC ;AN000; SAR
306 ;; ERRORLEVEL DB 0 ; SAR ;errorlevel
307 ;; INPUT_DATE DW 0 ; SAR
308 ;; INPUT_TIME DW 0 ; SAR
310 SAV_DEFAULT_DRV
DB ?
;AN000;1 = A, 2 = B etc. saved default
311 SAV_DEF_DIR_ROOT
DB '\';AN000;
312 SAV_DEFAULT_DIR DB 64 DUP (0);AN000;
313 SAV_S_DRV DB 'A
:\' ;AN000;
314 SAV_S_CURDIR
DB 64 DUP (0);AN000;
315 SAV_T_DRV
DB 'B:\' ;AN000;
316 SAV_T_CURDIR DB 64 DUP (0);AN000;
318 PUBLIC SOURCE_PANEL, DEST_PANEL, CHECK_FILE ;AN111;JW
319 SOURCE_PANEL DW ? ;AN111;JW
320 DEST_PANEL DW ? ;AN111;JW
321 CHECK_FILE DW ? ;AN111;JW
323 SOURCE_IN DB ? ;AN111;JW
327 OLD_DTA_SEG DW ? ;AN111;JW
328 OLD_DTA_OFF DW ? ;AN111;JW
332 ;; DISP_S_PATH DB 67 DUP (0) ; SAR ;mirror image of source path. used for display message when copying
333 ;; DISP_S_FILE DB 13 DUP (0) ; SAR
334 ;; DISP_T_PATH DB 67 DUP (0) ; SAR ;mirror image of target path
335 ;; DISP_T_FILE DB 13 DUP (0) ; SAR
337 ;;B_SLASH DB '\',0 ; SAR
340 FILE_COUNT
LABEL WORD ;AN000;
341 FILE_CNT_LOW
DW 0 ;AN000;copied file count
342 FILE_CNT_HIGH
DW 0 ;AN000;
345 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
346 ;; APPENDFLAG DW 0 ; SAR ;append /X status save area
347 FOUND_FILE_FLAG
DB 0 ;AN000;used for showing the message "File not found"
349 S_DRV_NUMBER
DB 0 ;AN000;source, target drv #
350 T_DRV_NUMBER
DB 0 ;AN000;
352 S_DRV_PATH
LABEL BYTE ;AN000;source drv, path used for single_drv_copy
353 S_DRV
DB 'A:\' ;AN000;
354 S_PATH DB 80 DUP (0) ;AN000;Initialized by calling GET CUR DIR
356 S_DRV_1 DB 'A
:' ;AN000;
357 S_FILE DB '????????
.???
',0 ;AN000;default filename to find file
358 ;; S_DIR DB '????????
.???
',0 ; SAR ;to find any subdirectory name
360 ;; S_PARENT DB '..',0 ; SAR ;source parent used for non single_drv_copy
361 S_HANDLE DW 0 ;AN000;file handle opened
363 ;; S_ARC_DRV_PATH LABEL BYTE ; SAR ;informations used to change source file's
364 ;; S_ARC_DRV DB 'A
:\' ; SAR ;archieve bits.
365 ;; S_ARC_PATH DB 64 DUP (0) ; SAR
366 ;; S_ARC_DEPTH DB 0 ; SAR
368 T_DRV_PATH
LABEL BYTE ;AN000;target drv, path used all the time
369 T_DRV
DB 'B:\' ;AN000;
370 T_PATH DB 64 DUP (0) ;AN000;initialized by calling GET CUR DIR in INIT
373 ;; T_FILE LABEL BYTE ; SAR ;target filename for file creation
374 ;; T_DRV_1 DB 'B
:' ; SAR ;target drv letter
375 ;; T_FILENAME DB 13 DUP (0) ; SAR ;target filename
376 ;; T_TEMPLATE DB 11 DUP (0) ; SAR ;if global chr entered, this will be used instead of filename.
378 ;; T_PARENT LABEL BYTE ; SAR
379 ;; T_DRV_2 DB 'B
:' ; SAR
380 ;; T_PARENT_1 DB '..',0 ; SAR
381 T_HANDLE DW 0 ;AN000;target handle created
382 ;; T_MKDIR_LVL DB 0 ; SAR ;# of target starting directories created.
384 ;------------------------------------------
385 ; PRINT_STDOUT input parameter save area
386 ;------------------------------------------
387 ;; SUBST_COUNT DW 0 ; SAR ;AN000; message substitution count
388 ;; MSG_CLASS DB 0 ; SAR ;AN000; message class
389 ;; INPUT_FLAG DB 0 ; SAR ;AN000; Type of INT 21 used for KBD input
390 ;; MSG_NUM DW 0 ; SAR ;AN000; message number
392 ;----------------------------------------------
393 ; Parameter list used by extended open DOS call
394 ;----------------------------------------------
395 PARAM_LIST LABEL WORD;AN000;
396 E_A_LST DD 0 ;AN005; E A LIST POINTER
397 DW 1 ;AN005; number of additional parameters
398 DB 6 ;AN005; ID for IO mode = WORD VALUE
399 DW 1 ;AN005; IO mode = PURE SEQUENTIAL
402 ;; INPUT_BUFF db 20 dup(0) ; SAR ;AN000; keyboard input buffer used
403 ;for user response (Y/N)
405 ;--------------------------------------------------------------
406 ; Following three sublists are used by the Message Retriever
407 ;--------------------------------------------------------------
408 ;;SUBLIST1 LABEL DWORD ; SAR ;AN000;SUBSTITUTE LIST 1
409 ;; DB 11 ; SAR ;AN000;sublist size
410 ;; DB 0 ; SAR ;AN000;reserved
411 ;; DD 0 ; SAR ;AN000;substition data Offset
412 ;; DB 1 ; SAR ;AN000;n of %n
413 ;; DB 0 ; SAR ;AN000;data type
414 ;; DB 0 ; SAR ;AN000;maximum field width
415 ;; DB 0 ; SAR ;AN000;minimum field width
416 ;; DB 0 ; SAR ;AN000;characters for Pad field
419 ;;SUBLIST2 LABEL DWORD ; SAR ;AN000;SUBSTITUTE LIST 2
420 ;; DB 11 ; SAR ;AN000;sublist size
421 ;; DB 0 ; SAR ;AN000;reserved
422 ;; DD 0 ; SAR ;AN000;substition data Offset
423 ;; DB 2 ; SAR ;AN000;n of %n
424 ;; DB 0 ; SAR ;AN000;data type
425 ;; DB 0 ; SAR ;AN000;maximum field width
426 ;; DB 0 ; SAR ;AN000;minimum field width
427 ;; DB 0 ; SAR ;AN000;characters for Pad field
430 ;;SUBLIST3 LABEL DWORD ; SAR ;AN000;SUBSTITUTE LIST 3
431 ;; DB 11 ; SAR ;AN000;sublist size
432 ;; DB 0 ; SAR ;AN000;reserved
433 ;; DD 0 ; SAR ;AN000;substition data Offset
434 ;; DB 3 ; SAR ;AN000;n of %n
435 ;; DB 0 ; SAR ;AN000;data type
436 ;; DB 0 ; SAR ;AN000;maximum field width
437 ;; DB 0 ; SAR ;AN000;minimum field width
438 ;; DB 0 ; SAR ;AN000;characters for Pad field
442 FILE_SEARCH_ATTR DW NORM_ATTR;AN000;
443 ;; DIR_SEARCH_ATTR DW INCL_H_S_DIR_ATTR ; SAR
445 OPEN_MODE DB Read_Only_Deny_Write ;AN000;READ_ONLY_DENY_WRITE ;access, sharing mode
447 ;Equates are defined in XCOPY.EQU
449 MY_FLAG DB 0 ;AN000;informations for a tree walk
450 ; find_first_flag equ 01h ;set MY_FLAG by "OR"
451 ; findfile_flag equ 02h
452 ; no_more_file equ 04h
453 ; single_copy_flag equ 08h ;single copy instead of multi copy
454 ; visit_parent_flag equ 10h ;visit parent node
455 ; found_flag equ 20h ;found flag - for find subdir
456 ; missing_link_flag equ 40h ;insuffiecient info. for not creating empty dir
457 ; is_source_flag equ 80h ;if set, dealing with source
458 ; reset_find_first equ 0FEh ;reset by AND
459 ; reset_findfile equ 0FDh
460 ; reset_no_more equ 0FBh
461 ; reset_visit_parent equ 0EFh
462 ; reset_found equ 0DFh
463 ; reset_missing_link equ 0BFh
464 ; reset_is_source equ 07Fh
466 FILE_FLAG DB 0 ;AN000;
469 ; big_file_flag equ 04h
470 ; file_bigger_flag equ 08h
471 ; created_flag equ 10h
472 ; reset_cont equ 0FEh
474 ; reset_big_file equ 0FBh
475 ; reset_file_bigger equ 0F7h
476 ; reset_created equ 0EFh
477 ; reset_readfile equ 0F0h ;reset FILE_FLAG for read a file
479 COPY_STATUS DB 0;AN000;
480 ; open_error_flag equ 01h
481 ; read_error_flag equ 02h
482 ; create_error_flag equ 04h
483 ; write_error_flag equ 08h
484 ; mkdir_error_flag equ 10h
485 ; chdir_error_flag equ 20h
486 ; maybe_itself_flag equ 40h
487 ; disk_full_flag equ 80h
488 ; reset_open_error equ 0FEh
489 ; reset_read_error equ 0FDh
490 ; reset_create_error equ 0FBh
491 ; reset_write_error equ 0F7h
492 ; reset_close_error equ 0EFh
493 ; reset_chdir_error equ 0DFh
495 ACTION_FLAG DB 0;AN000;
496 ; reading_flag equ 01h ;display "Reading source files..."
497 ; reset_reading equ 0FEh ;do not display.
499 SYS_FLAG DB 0 ;AN000;system information
500 ; one_disk_copy_flag equ 01h ;xcopy with only one logical drive.
501 ; default_drv_set_flag equ 02h ;default drive has been changed by this program
502 ; default_s_dir_flag equ 04h ;source current directory saved.
503 ; default_t_dir_flag equ 08h ;target current directory saved.
504 ; removalble_drv_flag equ 10h
505 ; sharing_source_flag equ 20h ;source shared
506 ; sharing_target_flag equ 40h
507 ; turn_verify_off_flag equ 80h ;turn the verify off when exit to dos
508 ; reset_default_s_dir equ 0FBh ;reset default_s_dir_flag
510 OPTION_FLAG DB 0;AN000;
511 ; slash_a equ 01h ;soft archieve ?
512 ; slash_d equ 02h ;date?
513 ; slash_e equ 04h ;create empty dir?
514 ; slash_m equ 08h ;hard archieve ? (turn off source archieve bit)
515 ; slash_p equ 10h ;prompt?
516 ; slash_s equ 20h ;walk the tree?
517 ; slash_v equ 40h ;verify on?
518 ; slash_w equ 80h ;show "Press any key to begin copying" msg)
519 ; reset_slash_a equ 0FEh ;turn off soft archieve
520 ; reset_slash_m equ 0F7h ;turn off hard archieve
522 MAX_CX DW 0 ;AN000;less than 0FFD0h
523 ACT_BYTES DW 0 ;AN000;actual bytes read.
524 HIGH_FILE_SIZE DW 0;AN000;
525 LOW_FILE_SIZE DW 0;AN000;
527 TOP_OF_MEMORY DW 0 ;AN000;para
528 BUFFER_BASE DW 0 ;AN000;para
529 MAX_BUFFER_SIZE DW 0 ;AN000;para. BUFFER_LEFT at INIT time.
530 BUFFER_LEFT DW 0 ;AN000;para
531 BUFFER_PTR DW 0 ;AN000;para. If buffer_left=0 then invalid value
532 DATA_PTR DW 0 ;AN000;buffer_ptr + 2 (32 bytes)
533 OLD_BUFFER_PTR DW 0 ;AN000;last buffer_ptr
534 SIZ_OF_BUFF DW ? ;AN005;para. EXTENDED ATTRIB BUFF SIZE
535 BYTS_OF_HDR DW ? ;AN005;bytes TOTAL HEADER SIZE
536 PARA_OF_HDR DW ? ;AN005;para. TOTAL HEADER SIZE
537 OPEN_FILE_COUNT DW ? ;AN005;TRACKING OF OPEN FLS FOR BUFFER
540 ;structured data storage allocation
541 FILE_DTA Find_DTA <> ;AN000;DTA for find file
542 DTAS Find_DTA 32 dup (<>) ;AN000;DTA STACK for find dir
543 ;** Througout the program BP will be used for referencing fieldsname in DTAS.
544 ;For example, DS:[BP].dta_filename.
547 ;******************************************************************************
549 SELECT SEGMENT PARA PUBLIC 'SELECT
';AN000;
550 ASSUME CS:SELECT, DS:DATA ;AN000;
552 ;--- START OF A PROGRAM ---
554 PUBLIC MOD_XCOPY ;AN000;
555 MOD_XCOPY PROC NEAR ;AN000; SAR
563 MOV SP_SAVE, SP ;AN000; SAR
565 MOV SOURCE_IN,YES ;AN111;JW
566 .IF < AL eq 1 > ;AN000;
568 .ELSEIF < AL eq 2 > ;AN000;
571 MOV DEST,AL ;AN000; SAR
572 MOV TABLE_OFFSET, BX ;AN000; SAR
573 MOV NUMBER_OF_FILES, CX ;AN000; SAR
574 MOV PATH_OFFSET, SI ;AN000; SAR
575 CALL SAVE_DTA ;AN000;
577 MOV AH, 62H ;AN000; SAR
579 MOV PSP_SEG, BX ;AN000; SAR
581 CALL ALLOCATE ;AN000; SAR
582 .IF < C > ;AN000; SAR
583 JMP JUST_EXIT ;AN000; SAR
587 CALL INIT ;AN000;initialization
588 JC MAIN_EXIT ;AN000;error. (Already message has been displayed)
590 MOV BP, OFFSET DTAS ;AN000;initialize BP
591 OR ACTION_FLAG, READING_FLAG ;AN000;set reading flag for copy message
593 CALL TREE_COPY ;AN000;
595 CALL ORG_S_DEF ;AN000;restore the original source default dir
597 CALL WRITE_FROM_BUFFER ;AN000;write from buffer if we missed it.
599 CALL SWITCH_DTAS ;AN111;JW
602 JMP RESTORE_DIRS ;AN000; SAR
605 ;;;;; MOV BX, DATA ; SAR
606 ;;;;; MOV DS, BX ; SAR re initialize ds, es
607 ;;;;; MOV ES, BX ; SAR exit here if the status of source, target or default drv has been changed.
608 ;;;;; CALL CHK_FILE_NOT_FOUND ; SAR if no files has been found, show the message.
614 MOV BX, DATA ;AN000; SAR
615 MOV DS, BX ;AN000;re initialize ds, es
616 MOV ES, BX ;AN000;exit here if the status of source, target or default drv has been changed.
617 ;;;;; CALL CHK_MKDIR_LVL ; SAR starting target directory has been created?
619 CALL ORG_S_T_DEF ;AN000;restore original target, source, default drv, and verify status
621 JMP DO_DEALLOCATE ;AN000; SAR
622 JUST_EXIT: ;AN000;unconditional immediate exit
623 MOV AX, DATA ;AN000; SAR
624 MOV DS, AX ;AN000; SAR
627 DO_DEALLOCATE: ;AN000; SAR
628 ; Restore the original status of APPEND if active.
629 CALL DEALLOCATE ;AN000; SAR
630 .IF < NC > ;AN000; SAR
631 .IF < NOT_FOUND_FLAG EQ 1 > ;AN000; SAR
637 MOV SP, SP_SAVE ;AN000; SAR
642 ; MOV AH, 4Ch ;return to dos
643 ; MOV AL, ERRORLEVEL ;set return code whatever
646 MOD_XCOPY ENDP;AN000;
650 ;----------------- SUBROUTINES ---------------------------------------------
652 ALLOCATE PROC NEAR ;AN000; SAR
654 MOV BX, 0FFFFH ;AN000; SAR Attempt to allocate as much as possible
655 MOV AH, 48H ;AN000; SAR
657 MOV AH, 48H ;AN000; SAR BX contains the amount of memory available
659 MOV ALLOCATE_START, AX ;AN000; SAR
663 ALLOCATE ENDP ;AN000; SAR
665 DEALLOCATE PROC NEAR ;AN000; SAR
669 MOV AX, ALLOCATE_START ;AN000; SAR
670 MOV ES, AX ;AN000; SAR
671 MOV AH, 49H ;AN000; SAR
678 DEALLOCATE ENDP ;AN000; SAR
683 TREE_COPY PROC NEAR ;AN000;
685 ;Walk the source tree to read files and subdirectories
687 .IF < DEST EQ 1 > ;AN000; SAR Copying to drive b?
688 MOV SI, OFFSET B_TARGET ;AN000; SAR Yes! Copy the drive information
689 MOV CX, LENGTH_B_TARGET ;AN000; SAR
690 .ELSEIF < DEST EQ 3 > ;AN111;JW ; SAR Copying to drive A?
691 MOV SI, OFFSET A_TARGET ;AN111;JW ; SAR Yes! Copy the drive information
692 MOV CX, LENGTH_A_TARGET ;AN111;JW ; SAR
694 MOV SI, PATH_OFFSET ;AN000; SAR No! Copy to this directory.
695 MOV CX, WORD PTR [SI] ;AN000; SAR
696 ADD SI, 2 ;AN000; SAR Adjust for the length word
698 MOV DI,OFFSET T_DRV_PATH ;AN000; SAR
700 REP MOVSB ;AN000; SAR
704 OR MY_FLAG, FINDFILE_FLAG ;AN000;deals with files
705 OR MY_FLAG, FIND_FIRST_FLAG ;AN000;find first
707 MOV NOT_FOUND_FLAG, 0 ;AN000; SAR
709 NEXT_PASS: ;AN000; SAR
711 MOV SI, TABLE_OFFSET ;AN000; SAR
712 MOV DOS_FILE_PTR,SI ;AN000; SAR
713 MOV FILE_NUM,1 ;AN000; SAR
715 CALL SET_MY_DTA ;AN000;set DTA to FILE_DTA
718 AND MY_FLAG, RESET_NO_MORE ;AN000; SAR
719 CALL LOAD_DOS_FILENAME ;AN000; SAR
720 TEST MY_FLAG, NO_MORE_FILE ;AN000; SAR
724 .IF < SOURCE_IN EQ NO > AND ;AN000;
725 .IF < DEST EQ 3 > ;AN000;
726 CALL GET_SOURCE ;AN000;
729 CALL FIND_FILE ;AN000;find first (next) ; SAR
730 .IF < BIT MY_FLAG NAND NO_MORE_FILE > ;AN000; SAR
731 CALL READ_INTO_BUFFER ;AN000; SAR
733 MOV NOT_FOUND_FLAG, 1 ;AN000; SAR
736 JMP SHORT $$DO1 ;AN000;
740 ; \19\19\19\19\19\19\19\19\19 SAR \19\19\19\19\19\19\19\19\19
741 ;;;;;; TEST OPTION_FLAG, SLASH_S ;walk the tree?
744 ; AND MY_FLAG, RESET_FINDFILE ;now, deals with directory
745 ; OR MY_FLAG, FIND_FIRST_FLAG ;find first
747 ; CALL SET_MY_DTA ;set DTA to DTAS according to BP
748 ; CALL FIND_DIR ;find first (next)
749 ; TEST MY_FLAG, NO_MORE_FILE ;no more subdirectory?
750 ; $LEAVE NZ ;then leave this loop to return to caller
752 ; LEA SI, [BP].DTA_FILENAME
753 ; CMP S_PATH, 0 ;root directory?
755 ; MOV AL, 0FFh ;then '\' is already provided
. Just concat
.
757 ; MOV AL, PATH_DELIM ;put delimiter
759 ; CALL CONCAT_ASCIIZ ;make new path
760 ; test option_flag, slash_p ;prompt mode?
762 ; call p_concat_display_path
764 ; INC S_DEPTH ;increase depth
765 ; CALL MAKE_HEADER ;make header in the buffer
766 ; OR MY_FLAG, IS_SOURCE_FLAG ;dealing with source
767 ; AND MY_FLAG, RESET_VISIT_PARENT ;going to visit child node
768 ; CALL CHANGE_S_DIR ;change source dir
769 ; ADD BP, type FIND_DTA ;increase DTAS stack pointer
770 ; CALL TREE_COPY ;tree copy the sub directory
773 ; CMP S_DEPTH, 0 ;starting directory? then exit
775 ; DEC S_DEPTH ;dec depth
776 ; TEST OPTION_FLAG, SLASH_E ;copy subdirectories even if empty?
778 ; CALL DEL_EMPTY ;then check the old_buffer_ptr and
779 ; ;if it is a directory, then restore
780 ; ;buffer_ptr to old.
783 ; CALL LAST_DIR_OUT ;change environments
784 ; test option_flag, slash_p ;prompt mode?
786 ; call p_cut_display_path
788 ; LEA DX, S_DRV_PATH ;before returning to the caller
789 ; OR MY_FLAG, IS_SOURCE_FLAG
790 ; OR MY_FLAG, VISIT_PARENT_FLAG
792 ; SUB BP, type FIND_DTA
794 ;;;;;;; $ENDIF ;walk the tree
796 TREE_COPY ENDP
;AN000;
799 GET_SOURCE PROC
NEAR;AN000;
801 CALL SWITCH_DTAS
;AN000;
805 INIT_PQUEUE PAN_INST_PROMPT
;AN000; initialize queue
806 PREPARE_PANEL SOURCE_PANEL
;AN000; remove select from A: & insert DOS
807 PREPARE_PANEL PAN_HBAR
;AN000;
808 PREPARE_CHILDREN
;AN000; prepare child panels
809 DISPLAY_PANEL
;AN000;
811 GET_FUNCTION FK_ENT
;AN000;
813 .IF < SOURCE_PANEL
eq SUB_REM_DOS_A
> ;AN000;
814 LEA DI, S_DOS_SEL_360
;AN000;
816 LEA DI, S_DOS_SHEL_DISK
;AN000;
818 MOV CX, E_FILE_ATTR
;AN000;
819 CALL FIND_FILE_ROUTINE
;AN000;
820 .LEAVE < nc
> ;AN000;
822 HANDLE_ERROR ERR_DOS_DISK
, E_RETURN
;AN000;
826 ;;;copying files from diskette 1 screen ;
827 INIT_PQUEUE PAN_INSTALL_DOS
;AN000; initialize queue
828 PREPARE_PANEL SUB_COPYING
;AN000; prepare copying from diskette 1 message
829 DISPLAY_PANEL
;AN000;
831 MOV SOURCE_IN
,YES
;AN000;
833 CALL SWITCH_DTAS
;AN000;
836 GET_SOURCE ENDP
;AN000;
838 GET_DEST PROC
NEAR ;AN000;
841 INIT_PQUEUE PAN_INST_PROMPT
;AN000; initialize queue
842 PREPARE_PANEL DEST_PANEL
;AN000; remove select from A: & insert DOS
843 PREPARE_PANEL PAN_HBAR
;AN000;
844 PREPARE_CHILDREN
;AN000; prepare child panels
845 DISPLAY_PANEL
;AN000;
847 GET_FUNCTION FK_ENT
;AN000;
850 ;;;copying files from diskette 1 screen ;
851 INIT_PQUEUE PAN_INSTALL_DOS
;AN000; initialize queue
852 PREPARE_PANEL SUB_COPYING
;AN000; prepare copying from diskette 1 message
853 DISPLAY_PANEL
;AN000;
855 MOV SOURCE_IN
,NO
;AN000;
856 ; SUB DOS_FILE_PTR,12
860 GET_DEST ENDP
;AN000;
862 ;******************************************************************************
863 ; Subroutine: LOAD_DOS_FILENAME - Load the next filename into S_FILE.
865 ; SI - Points to the start of the filename
868 ; The S_FILE field in the data segment is updated.
870 ; SI - At the end, SI points to the end of the filename. It therefore
871 ; also points to the beginning of the next filename.
873 ;******************************************************************************
874 LOAD_DOS_FILENAME PROC
NEAR;AN000;
879 OR MY_FLAG
, FIND_FIRST_FLAG
;AN000; Find first in the directory
881 MOV SI,DOS_FILE_PTR
;AN000;
883 LDF_SEE_IF_DONE: ;AN000;
885 ; See if we are finished this pass of the files
887 OR MY_FLAG
, NO_MORE_FILE
;AN000; For now, assume there are not files found
888 MOV DX, NUMBER_OF_FILES
;AN000; Get the number of files in the table
889 .IF < FILE_NUM BE
DX > ;AN000; Search while there are still more files
890 AND MY_FLAG
, RESET_NO_MORE
;AN000; Indicate that there are more files
891 LEA DI,S_FILE
;AN000; Where to put the name
892 MOV CX,12 ;AN000; Number of bytes
898 MOV DOS_FILE_PTR
,SI ;AN000; Save the pointer to the files
903 LOAD_DOS_FILENAME ENDP
;AN000;
905 READ_INTO_BUFFER PROC
NEAR ;AN000;
906 ;Read *** a *** file into buffer
908 ; \19\19\19\19\19\19\19\19\19 SAR \19\19\19\19\19\19\19\19\19
909 ; TEST MY_FLAG, SINGLE_COPY_FLAG ;single copy?
910 ; $IF Z,AND ;no, multi copy
911 ; TEST ACTION_FLAG, READING_FLAG ;show message?
913 ; MOV AX,MSG_READING_SOURCE ;AN000; message number
914 ; MOV MSG_NUM,AX ;AN000; set message number
915 ; MOV SUBST_COUNT,0 ;AN000; no message substitution
916 ; MOV MSG_CLASS,-1 ;AN000; message class
917 ; MOV INPUT_FLAG,0 ;AN000; no input
918 ; MOV AX,MSG_READING_SOURCE
919 ; CALL PRINT_STDOUT ;show message "Reading source files"
921 ; AND ACTION_FLAG, RESET_READING ;reset it
924 AND FILE_FLAG
, RESET_READFILE
;AN000;reset file_flag to read a file
925 MOV AX,FILE_DTA
.DTA_FILE_SIZE_HIGH
;AN000;
926 MOV HIGH_FILE_SIZE
, AX ;AN000;
927 MOV AX,FILE_DTA
.DTA_FILE_SIZE_LOW
;AN000;
928 MOV LOW_FILE_SIZE
, AX ;AN000;
930 MOV AX, PARA_OF_HDR
;AN005;GET THE HEADER SIZE (para.)
931 CMP MAX_BUFFER_SIZE
,AX ;AN005;IS EA BUFFER TOO LARGE?
932 JB RIB_ERROR
;AN005;CLOSE THE FILE AND GET THE NEXT
934 CALL CMP_FILESIZE_TO_BUFFER_LEFT
;AN000;compare sizes
935 TEST FILE_FLAG
, FILE_BIGGER_FLAG
;AN000;filesize > buffer_left - header?
936 JZ RIB_SMALL
;AN000;if not, then small file
937 MOV BX, S_HANDLE
;AN005;
938 CALL CLOSE_A_FILE
;AN005;ONLY OPENED TO GET BUFFER SIZE
939 CALL WRITE_FROM_BUFFER
;AN000;
941 .IF < SOURCE_IN
EQ NO
> AND ;AN111;JW
942 .IF < DEST
EQ 3 > ;AN111;JW
943 CALL GET_SOURCE
;AN111;JW put source diskette in A:
946 ; JC RIB_ERROR ;any problem with writing?
947 CALL CMP_FILESIZE_TO_BUFFER_LEFT
;AN000;compare again
948 TEST FILE_FLAG
, FILE_BIGGER_FLAG
;AN000;still bigger?
949 JNZ RIB_BIG
;AN000;yes. Big file
951 CALL SMALL_FILE
;AN000;
955 MOV BX, S_HANDLE
;AN005;
956 CALL CLOSE_A_FILE
;AN005;ONLY OPENED TO GET BUFFER SIZE
957 CALL BIG_FILE
;AN000;
960 TEST COPY_STATUS
, OPEN_ERROR_FLAG
;AN000;open error?
961 JNZ RIB_EXIT
;AN000;just exit. find next file
962 MOV BX, S_HANDLE
;AN000;else write error
963 CALL CLOSE_A_FILE
;AN000;close the troubled file
966 TEST MY_FLAG
, SINGLE_COPY_FLAG
;AN000;single copy?
969 CALL WRITE_FROM_BUFFER
;AN000;then write a file
973 READ_INTO_BUFFER ENDP
;AN000;
976 SMALL_FILE PROC
NEAR ;AN000;
977 ;handles a file smaller than max_buffer_size or buffer_left, i.e. fit in memory.
978 ;This routine will call MAKE_HEADER, SET_BUFFER_PTR< READ_A_FILE, OPEN_A_FIEL
979 ;CALC_FILE_SIZE, CMP_FILE_FFD0h, CLOSE_A_FILE.
981 TEST FILE_FLAG
, BIG_FILE_FLAG
;AN000;called from BIG_FILE?
982 JNZ SMF_CONT
;AN000;then need not open a file again
983 CALL OPEN_A_FILE
;AN000;open a file using FILE_DTA
984 JC SMF_ERROR
;AN000;open error?
986 CALL CMP_FILE_FFD0h
;AN000;filesize > 0FFD0h ?
987 TEST FILE_FLAG
, FILE_BIGGER_FLAG
;AN000;
988 JZ SMF_EOF
;AN000;filesize <= 0FFD0h
989 OR FILE_FLAG
, CONT_FLAG
;AN000;filesize > 0FFD0h. set cont_flag
990 MOV CX, 0FFD0h ;AN000;# of bytes to read
991 CALL READ_A_FILE
;AN000;
992 JC SMF_ERROR
;AN000;unsuccessful read?
993 CALL MAKE_HEADER
;AN000;else make header and ready for next
994 CALL CALC_FILE_SIZE
;AN000;filesize = filesize - bytes read
995 JMP SMF_CONT
;AN000;loop. compare again with the rest
998 MOV CX, LOW_FILE_SIZE
;AN000;rest of the bytes to read
999 OR FILE_FLAG
, EOF_FLAG
;AN000;set EOF
1000 CALL READ_A_FILE
;AN000;
1001 JC SMF_ERROR
;AN000;
1002 CALL MAKE_HEADER
;AN000;
1003 MOV BX, S_HANDLE
;AN000;
1004 CALL CLOSE_A_FILE
;AN000;
1005 JMP SMF_EXIT
;AN000;
1010 SMALL_FILE ENDP
;AN000;
1013 BIG_FILE PROC
NEAR ;AN000;
1014 ;handles a file which is bigger than max_buffer_size
1015 ;Needs 2 file handles open concurrently for read and write
1017 OR FILE_FLAG
, BIG_FILE_FLAG
;AN000;
1018 OR FILE_FLAG
, CONT_FLAG
;AN000;
1019 CALL OPEN_A_FILE
;AN000;
1020 JC BIF_ERROR
;AN000;error in open?
1021 CMP MAX_BUFFER_SIZE
, 0FFFh ;AN000;max buffer size > 0FFFh in para ?
1022 JA BIF_BIG
;AN000;yes. large buffer system
1024 MOV CX, MAX_CX
;AN000;CX = max_buffer_size * 16 - 32
1026 CALL READ_A_FILE
;AN000;
1027 JC BIF_ERROR
;AN000;read error?
1028 CALL MAKE_HEADER
;AN000;
1029 CALL WRITE_FROM_BUFFER
;AN000;
1030 JC BIF_ERROR
;AN000;write error?
1031 TEST FILE_FLAG
, EOF_FLAG
;AN000;end of file set by READ_A_FILE?
1032 JZ BIF_SM
;AN000;if not, read again
1033 MOV BX, S_HANDLE
;AN000;
1034 CALL CLOSE_A_FILE
;AN000;
1035 JMP BIF_EXIT
;AN000;finished.
1037 MOV CX, 0FFD0h ;AN000;max # of data bytes this program supports
1039 CALL READ_A_FILE
;AN000;
1040 JC BIF_ERROR
;AN000;
1041 CALL MAKE_HEADER
;AN000;
1042 CALL CALC_FILE_SIZE
;AN000;modify file size
1044 CALL CMP_FILESIZE_TO_BUFFER_LEFT
;AN000;filesize > buffer_left?
1045 TEST FILE_FLAG
, FILE_BIGGER_FLAG
;AN000;yes.
1046 JZ BIF_END
;AN000;if it is not, call small_file
1047 CMP BUFFER_LEFT
, 0FFFh ;AN000;BUFFER_LEFT >= 0FFF0h in bytes?
1048 JAE BIF_BIG
;AN000;then loop again.
1049 CMP BUFFER_LEFT
, 140H
;AN000;else BUFFER_LEFT >= 5 K in bytes? ;minimum buffer size this program supports.
1050 JL BIF_BIG3
;AN000;then flush buffer and try again. **IF system buffer left < 5 K then infinit loop can happen.
1051 MOV AX,BUFFER_LEFT
;AN000;
1052 SUB AX,PARA_OF_HDR
;AC005;FOR HEADER SIZE para.
1053 MOV CX,BYTS_OF_HDR
;AN005;FOR HEADER SIZE bytes.
1054 JMP BIF_BIG1
;AN000;read again
1056 CALL WRITE_FROM_BUFFER
;AN000;
1057 JC BIF_ERROR
;AN000;
1058 JMP BIF_BIG2
;AN000;flush buffer and compare again.
1060 CALL SMALL_FILE
;AN000;when filesize <= buffer_left then SMALL_FILE will finish it.
1061 JC BIF_ERROR
;AN000;something wrong?
1062 CALL WRITE_FROM_BUFFER
;AN000;else finish copying this file
1063 JNC BIF_EXIT
;AN000;
1068 BIG_FILE ENDP
;AN000;
1070 MAKE_HEADER PROC
NEAR ;AN000;
1071 ;When called by READ_A_FILE after the data had been read into the buffer, this
1072 ;routine will put the header which is just below the data area where the
1073 ;current BUFFER_PTR points. The header is 32 (2 para) byte long. And this
1074 ;routine will also call SET_BUFFER_PTR to set the BUFFER_PTR, BUFFER_LEFT
1075 ;for the next process.
1076 ;If called by TREE_COPY for a SUBDIRECTORY handle, this routine should
1077 ;check the BUFFER_LEFT (when called by READ_A_FILE, the caller is assumed
1078 ;to check the size of buffer_left before calling.) In this case, this
1079 ;routine will set the next BUFFER_PTR, BUFFER_LEFT, OLD_BUFFER_PTR
1080 ;instead of SET_BUFFER_PTR routine.
1081 ;Informations are obtained from the DTA area (for file - FILE_DTA.xxx
1082 ;dir - DS:[BP].xxx ) and stored into the header by referencing ES:field;s name.
1083 ;DS - Program Data area
1084 ;ES - will be used for a header segment in the buffer.
1086 PUSH ES ;AN000;save ES
1090 MOV AX,BUFFER_PTR
;AN000;buffer_ptr is a segment
1091 MOV ES, AX ;AN000;now, ES is a header seg.
1093 MOV AX, PARA_OF_HDR
;AN005;GET THE HEADER SIZE (para.)
1094 CMP BUFFER_LEFT
,AX ;AC005;buffer_left=less than NEEDED?
1095 JAE MH_START
;AN000;
1096 CALL WRITE_FROM_BUFFER
;AN000;if so, flush buffer
1097 JC MH_ERROR_BRIDGE
;AN000;write error?
1098 JMP SHORT MH_AGAIN
;AN000;reinitialize ES to new buffer ptr
1100 TEST MY_FLAG
, FINDFILE_FLAG
;AN000;identify caller.
1101 JNZ MH_FILE
;AN000;if a file, jmp to MH_FILE
1102 ;else deals with directory.
1103 MOV ES:CONTINUE_INFO
, 0 ;AN000;not a continuation.
1104 MOV AX,OLD_BUFFER_PTR
;AN000;
1105 MOV ES:BEFORE_PTR
, AX ;AN000;set before_ptr in header
1106 MOV AX,BUFFER_PTR
;AN000;
1107 MOV OLD_BUFFER_PTR
, AX ;AN000;set variable OLD_BUFFER_PTR
1108 ADD AX,PARA_OF_HDR
;AC005;AX = BUFFER_PTR+HEADER(para)
1109 MOV BUFFER_PTR
, AX ;AN000;set new BUFFER_PTR
1110 MOV ES:NEXT_PTR
, AX ;AN000;set NEXT_PTR in the header
1111 MOV AX, PARA_OF_HDR
;AN005;GET THE HEADER SIZE (para.)
1112 SUB BUFFER_LEFT
,AX ;AC005;adjust BUFFER_LEFT
1113 CMP BUFFER_LEFT
,AX ;AC005;less than HEADER SIZE (para) ?
1116 MOV BUFFER_LEFT
, 0 ;AN000;indicate buffer_full
1119 MOV AL, S_DEPTH
;AN000;
1120 MOV ES:DIR_DEPTH
, AL ;AN000;now save other info's
1121 MOV AL, DS:[BP].DTA_ATTRIBUTE
;AN000;
1122 MOV ES:ATTR_FOUND
, AL ;AN000;in this case, DIR
1123 MOV AL, BYTE PTR T_DRV
;AN000;
1124 MOV ES:TARGET_DRV_LET
, AL ;AN000;mov target drive letter
1125 MOV ES:TARGET_DRV_LET
+1, DRV_delim
;AN000; ':'
1127 LEA SI, [BP].DTA_FILENAME
;AN000;DS:SI
1128 MOV DI, OFFSET
ES:FILENAME_FOUND
;AN000;ES:DI
1129 REP MOVSB ;AN000;mov sting until cx = 0
1131 MH_ERROR_BRIDGE: JMP MH_ERROR
;AN000;
1132 MH_FILE: ;AN000;handles a file header hereafter.
1133 TEST FILE_FLAG
, CONT_FLAG
;AN000;continuation?
1134 JZ MH_WHOLE_FILE
;AN000;no, just a whole file
1135 TEST FILE_FLAG
, EOF_FLAG
;AN000;Eof flag set?
1136 JNZ MH_CONT_END
;AN000;yes, must be end of continuation
1137 TEST FILE_FLAG
, BIG_FILE_FLAG
;AN000;Is this a big file?
1138 JNZ MH_BIG
;AN000;yes
1139 MOV ES:CONTINUE_INFO
, 1 ;AN000;else small file continuation.
1140 JMP MH_A_FILE
;AN000;
1141 MH_WHOLE_FILE: ;AN000;
1142 MOV ES:CONTINUE_INFO
, 0 ;AN000;
1143 JMP MH_A_FILE
;AN000;
1144 MH_CONT_END: ;AN000;
1145 MOV ES:CONTINUE_INFO
, 3 ;AN000;
1146 JMP MH_A_FILE
;AN000;
1148 MOV ES:CONTINUE_INFO
, 2 ;AN000;
1150 MOV AX,FILE_DTA
.DTA_FILE_TIME
;AN000;
1151 MOV ES:FILE_TIME_FOUND
, AX;AN000;
1152 MOV AX, FILE_DTA
.DTA_FILE_DATE
;AN000;
1153 MOV ES:FILE_DATE_FOUND
, AX;AN000;
1154 MOV AX, FILE_DTA
.DTA_FILE_SIZE_LOW
;AN000;
1155 MOV ES:LOW_SIZE_FOUND
, AX;AN000;
1156 MOV AX, FILE_DTA
.DTA_FILE_SIZE_HIGH
;AN000;
1157 MOV ES:HIGH_SIZE_FOUND
, AX;AN000;
1158 MOV AL, BYTE PTR T_DRV
;AN000;
1159 MOV ES:TARGET_DRV_LET
, AL;AN000;
1160 MOV ES:TARGET_DRV_LET
+1, DRV_DELIM
;AN000;
1162 MOV SI, OFFSET FILE_DTA
.DTA_FILENAME
;AN000;
1163 MOV DI, OFFSET
ES:FILENAME_FOUND
;AN000;
1166 ; Get Extended Attribute list of the opened file and save in attribute buff.
1169 ; MOV AX,INT_ORDINAL ;AN000; SET THE ORDINAL TO 0
1170 ; MOV ES:QUERY_LIST,AX ;AN000; PUT IT IN THE BUFFER
1171 ; MOV AX,SIZ_OF_BUFF ;AN000; SET THE SIZE TO 510 BYTES
1172 ; MOV ES:BUFR_SIZ,AX ;AN000; PUT IT IN THE BUFFER
1174 ; MOV BX,S_HANDLE ;AN000; BX = handle
1175 ; MOV AX, QUY_ATTRIB ;AN000; extended attribute code 5703H
1176 ; MOV DI, OFFSET QUERY_LIST ;AN000; ES:DI-->QUERY list
1177 ; INT 21H ;AN000; get extended attribute list
1179 MOV BX,S_HANDLE
;AN005; BX = handle
1180 MOV SI,ALL_ATTR
;AN005; SELECT ALL ATTRIBUTES SIZE
1181 MOV CL, PARAGRAPH
;AN005; PARAGRAPH = 4 FOR DIV BY 16
1182 MOV AX,SIZ_OF_BUFF
;AN005; GET THE SIZE EXPRESSED IN para.
1183 SHL AX, CL ;AN005; GET # OF BYTES FROM para.
1184 MOV CX, AX ;AN005; NEEDS TO BE IN CX
1185 MOV DI, OFFSET
ES:ATTRIB_LIST
;AN005; ES:DI = E A LIST IN BUFFER
1186 MOV AX, GET_ATTRIB
;AN005; extended attribute code 5702H
1187 INT 21H
;AN005; get extended attribute list
1189 ; JC MH_ERROR ;AN000; jump if error
1191 MOV AX, OLD_BUFFER_PTR
;AN000;
1192 MOV ES:BEFORE_PTR
, AX;AN000;
1193 MOV AX, ACT_BYTES
;AN000;
1194 MOV ES:CX_BYTES
, AX;AN000;
1195 CALL SET_BUFFER_PTR
;AN000;set buffer_ptr for next. AX is already set.
1196 MOV AX, BUFFER_PTR
;AN000;
1197 MOV ES:NEXT_PTR
, AX ;AN000;next buffer_ptr is next_ptr
1198 MOV AL, S_DEPTH
;AN000;
1199 MOV ES:DIR_DEPTH
, AL ;AN000;same as source depth
1200 MOV AL, FILE_DTA
.DTA_ATTRIBUTE
;AN000;
1201 MOV ES:ATTR_FOUND
, AL ;AN000;attribute found
1204 OR COPY_STATUS
, OPEN_ERROR_FLAG
;AN000;
1205 CALL EXTENDED_ERROR_HANDLER
;AN000;
1210 MAKE_HEADER ENDP
;AN000;
1213 OPEN_A_FILE PROC
NEAR ;AN000;
1215 ;-------------------------------------------------------------------------
1216 ; Use extended open DOS call to open source file,
1217 ; if successfully open, then save filehand to S_HANDLE.
1218 ;-------------------------------------------------------------------------
1219 ; Set drive letter and file name pointer in parameter list
1220 LEA SI,FILE_DTA
.DTA_FILENAME
;AN005; DS:SI-->NAME TO OPEN
1221 MOV DX,OPN_FLAG
;AN000; flag = 0101H
1222 MOV CX,OPN_ATTR
;AN000; attribute = 0
1223 MOV BX,OPN_MODE
;AN000; open mode = 0002H
1224 MOV DI, NUL_LIST
;AN005; ES:DI = -1
1225 MOV AX, Ext_Open
;AN000; = 6Ch
1226 INT 21H
;AN000; OPEN SOURCE FILE
1229 MOV S_HANDLE
, AX ;AN000;save filehandle
1230 INC OPEN_FILE_COUNT
;AN005;UPDATE THE OPEN FILE COUNTER
1233 JMP OF_EXIT
;AN000; exit
1236 OR COPY_STATUS
, OPEN_ERROR_FLAG
;AN000;
1237 CALL EXTENDED_ERROR_HANDLER
;AN000;
1240 OPEN_A_FILE ENDP
;AN000;
1244 CMP_FILE_FFD0h PROC
NEAR;AN000;
1245 ;check whether the filesize in HIGH_FILE_SIZE, LOW_FILE_SIZE is bigger than
1246 ;0FFD0h. If it is, then set FILE_BIGGER_FLAG, else reset it.
1247 CMP HIGH_FILE_SIZE
, 0;AN000;
1250 CMP LOW_FILE_SIZE
, 0FFD0h;AN000;
1253 AND FILE_FLAG
, RESET_FILE_BIGGER
;AN000;filesize <= 0FFD0h
1255 JMP SHORT $$EN8
;AN000;
1257 OR FILE_FLAG
, FILE_BIGGER_FLAG
;AN000;
1261 CMP_FILE_FFD0h ENDP
;AN000;
1264 CALC_FILE_SIZE PROC
NEAR ;AN000;
1265 ;subtract the bytes read (ACT_BYTES) from the filesize in HIGH_FILE_SIZE,
1267 MOV AX, ACT_BYTES
;AN000;
1268 SUB LOW_FILE_SIZE
, AX ;AN000;
1269 SBB HIGH_FILE_SIZE
, 0 ;AN000;
1271 CALC_FILE_SIZE ENDP
;AN000;
1274 READ_A_FILE PROC
NEAR ;AN000;
1276 ;if after reading, AX < CX or AX = 0 the set EOF_FLAG.
1277 ;INPUT:CX - # of bytes to read
1282 ; .IF < SOURCE_IN EQ NO > AND
1287 PUSH DS ;AN000;save program data seg
1289 MOV BX, S_HANDLE
;AN000;
1290 MOV DX, BUFFER_PTR
;AN000;current buffer header seg
1291 ADD DX, PARA_OF_HDR
;AC005;skip the header part
1292 MOV DS, DX ;AN000;now DS = buffer_ptr + 2, data area
1293 XOR DX, DX ;AN000;offset DX = 0
1295 POP DS ;AN000;restore program data area
1296 JC RF_ERROR
;AN000;read error?
1299 OR FILE_FLAG
, EOF_FLAG
;AN000;EOF reached. AX = 0 or AX < CX
1301 CLC ;AN000;clear carry caused from CMP
1302 MOV ACT_BYTES
, AX ;AN000;save actual bytes read
1305 OR COPY_STATUS
, READ_ERROR_FLAG
;AN000;
1306 CALL EXTENDED_ERROR_HANDLER
;AN000;
1309 READ_A_FILE ENDP
;AN000;
1312 FIND_IT PROC
NEAR ;AN000;
1313 ;set first or next depending on FIND_FIRST_FLAG.
1314 ;once called, reset FIND_FIRST_FLAG.
1315 TEST MY_FLAG
, FIND_FIRST_FLAG
;AN000;
1318 MOV AH, Find_First
;AN000;
1320 JMP SHORT $$EN11
;AN000;
1322 MOV AH, Find_Next
;AN000;
1325 AND MY_FLAG
, RESET_FIND_FIRST
;AN000;reset FIND_FIRST_FLAG
1328 FIND_IT ENDP
;AN000;
1330 FIND_FILE PROC
NEAR ;AN000;
1332 ;set NO_MORE_FILE if carry.
1338 ; .IF < SOURCE_IN EQ NO > AND
1345 TEST MY_FLAG
, FIND_FIRST_FLAG
;AN000;find first ?
1348 MOV DX, OFFSET S_FILE
;AN000;
1349 MOV CX, File_Search_Attr
;AN000;normal = 0
1351 JMP SHORT $$EN15
;AN000;
1353 MOV DX, OFFSET FILE_DTA
;AN000;
1356 CALL FIND_IT
;AN000;
1359 OR MY_FLAG
, NO_MORE_FILE
;AN000;no more file in this directory
1361 JMP SHORT $$SR14
;AN000;
1363 MOV FOUND_FILE_FLAG
, 1 ;AN000;set the flag for "File not found" msg.
1364 OR MY_FLAG
, FOUND_FLAG
;AN000; SAR
1365 ;;;;;;; CALL FILTER_FILES ;found. filter it with options
1366 TEST MY_FLAG
, FOUND_FLAG
;AN000;
1367 ; $ENDLOOP NZ ;if found, leave this loop else start again
1369 AND MY_FLAG
, RESET_NO_MORE
;AN000;
1373 FIND_FILE ENDP
;AN000;
1375 SET_MY_DTA PROC
NEAR ;AN000;
1376 ;set DS:DX for find_first(next). If MY_FLAG is set to FINDFILE_FLAG then
1377 ;set it to the offset FILE_DTA, otherwise to BP.
1378 ;DS should be set to the area whre FILE_DTA, DTAS are.
1379 PUSH DX ;AN000;save current DX
1380 TEST MY_FLAG
, FINDFILE_FLAG
;AN000;handling file?
1383 MOV DX, OFFSET FILE_DTA
;AN000;
1385 JMP SHORT $$EN22
;AN000;
1390 MOV AH, Set_DTA
;AN000;
1394 SET_MY_DTA ENDP
;AN000;
1397 SAVE_DTA PROC
NEAR ;AN000;
1398 ; Save old DTA address
1401 MOV AH, Get_DTA
;AN000;
1403 MOV OLD_DTA_SEG
,ES ;AN000;
1404 MOV OLD_DTA_OFF
,BX ;AN000;
1408 SAVE_DTA ENDP
;AN000;
1411 SWITCH_DTAS PROC
NEAR ;AN000;
1412 ; SWITCH DTA ADDRESSES
1415 PUSH OLD_DTA_SEG
;AN000;
1416 PUSH OLD_DTA_OFF
;AN000;
1417 CALL SAVE_DTA
;AN000;
1420 MOV AH, Set_DTA
;AN000;
1424 SWITCH_DTAS ENDP
;AN000;
1427 CHANGE_T_DIR PROC
NEAR ;AN000;
1428 ;change target dir according to t_drv_path.
1429 ;Since this routine is called by WRITE_FROM_BUFFER and DS now points
1430 ;to buffer area while ES points to the program data area, we set DS
1431 ;to data seg again here for the function call Chdir.
1432 PUSH DS ;AN000;save current buffer seg
1433 PUSH ES ;AN000;currentpy es is a data seg
1434 POP DS ;AN000;restore DS value as program data seg
1436 CMP T_DRV
[2], 0 ;AN000;LAST_DIR_OUT took '\' out?
1439 MOV T_DRV
[2], '\' ;AN000;then put it back for root dir
1440 MOV T_DRV[3], 0 ;AN000;
1444 MOV DX, OFFSET T_DRV_PATH ;AN000;
1445 MOV AH, CHDIR ;AN000;
1448 POP DS ;AN000;restore caller's DS value
1450 CHANGE_T_DIR ENDP;AN000;
1453 CMP_FILESIZE_TO_BUFFER_LEFT PROC NEAR;AN000;
1454 ;Compare buffer_left (paragraph) with filesize (high_file_size, low_file_size.)
1455 ;if filesize is bigger than buffer_left, then set FILE_BIGGER_FLAG
1456 ;indicating filesize > buffer_left.
1460 CMP OPEN_FILE_COUNT,NUL ;AN005;ARE THERE ANY OPEN FILES
1461 ; $IF Z ;AN005;NO, THEN GO AHEAD AND OPEN
1463 CALL OPEN_A_FILE ;AN005;OPEN A FILE USING FILE_DTA
1465 ; Get extended Attribute list size.
1467 MOV BX,S_HANDLE ;AN005; BX = handle
1468 MOV AX, GET_ATTRIB ;AN005; extended attribute code 5702H
1469 MOV SI,ALL_ATTR ;AN005; SELECT ALL ATTRIBUTES SIZE
1470 XOR CX,CX ;AN005; JUST QUERY SIZE NEEDED
1471 MOV DI, OFFSET NUL_LIST ;AN005; DI = LIST FOR NO DATA RETURNED
1472 INT 21H ;AN005; get extended attribute SIZE
1473 ADD CX,PARA_BOUND ;AN005; TO FIGURE THE NEXT PARAGRAPH
1475 MOV CL,PARAGRAPH ;AN005; GET PARAGRAPHS (DIV BY 16)
1477 MOV SIZ_OF_BUFF,AX ;AN005;SAVE BUFF SIZE FOR THE HEADER
1478 ADD AX,FIXD_HD_SIZ ;AN005;GET THE TOTAL HEADER SIZE
1479 MOV PARA_OF_HDR,AX ;AN005;SAVE FOR LATER
1480 SHL AX, CL ;AN005;CONVERT BACK TO TOTAL BYTES
1481 MOV BYTS_OF_HDR,AX ;AN005;SAVE FOR LATER
1482 MOV BX,S_HANDLE ;AN005;
1483 CALL CLOSE_A_FILE ;AN005;CLOSE THE FILE OPENED
1487 AND FILE_FLAG, RESET_FILE_BIGGER;AN000;
1488 MOV AX,PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
1489 CMP BUFFER_LEFT,AX ;AC005;buffer_left >= HEADER SIZE
1492 MOV AX, BUFFER_LEFT ;AN000;buffer_left in para
1493 SUB AX,PARA_OF_HDR ;AC005;consider header size in advance
1495 MUL CX ;AN000;* 16. result in DX;AX
1496 CMP HIGH_FILE_SIZE, DX;AN000;
1497 ; $IF A ;if high_filesize > dx
1499 OR FILE_FLAG, FILE_BIGGER_FLAG;AN000;
1501 JMP SHORT $$EN28;AN000;
1505 CMP LOW_FILE_SIZE, AX;AN000;
1508 OR FILE_FLAG, FILE_BIGGER_FLAG;AN000;
1516 JMP SHORT $$EN27 ;AN000;
1518 OR FILE_FLAG, FILE_BIGGER_FLAG ;AN000;buffer_left < 2
1524 CMP_FILESIZE_TO_BUFFER_LEFT ENDP ;AN000;
1527 SET_BUFFER_PTR PROC NEAR ;AN000;
1528 ;set BUFFER_PTR, BUFFER_LEFT, OLD_BUFFER_PTR in paragraph boundary
1529 ;to be used when reading a file into buffer.
1530 ;this routine uses current BUFFER_PTR to figure out the next BUFFER_PTR.
1531 ;So, at initialization time set BUFFER_PTR to CS, and set AX to the offset
1532 ;of INIT, then thr resultant BUFFER_PTR indicates the BUFFER_BASE and
1533 ;OLD_BUFFER_PTR indicates CS.(This means if old_buffer_ptr = cs, then
1534 ;it is the start of buffer)
1535 ;To get the next BUFFER_PTR during multi-copy, just set the AX to the
1536 ;number of bytes read. This routine will add 32 bytes for header size and
1537 ;will set the next BUFFER_PTR.
1538 ;input: AX - offset of buffer
1539 ; Top_of_memory in segment
1540 ; current BUFFER_PTR
1541 ; current OLD_BUFFER_PTR
1542 ; current BUFFER_LEFT
1543 ;output: BUFFER_PTR for next reading
1545 ; BUFFER_LEFT (Top_of_memory - Buffer_Ptr. If it is 0, then indicates
1546 ; the BUFFER is FULL. In this case, the BUFFER_PTR is
1547 ; invalid, but OLD_BUFFER_PTR keep the former buffer_ptr
1548 ; value which says that it is the last header in the buffer)
1549 ;** Currently this program support maxium top of memory in seg 0FFFF - resident
1550 ; area. This routine will check the overflow case to gaurd the next buffer_ptr
1551 ; not to exceed FFFF.
1554 MOV CX, BUFFER_PTR ;AN000;
1555 MOV OLD_BUFFER_PTR, CX ;AN000;set old_buffer_ptr
1557 SHR AX, CL ;AN000;get paragraphs
1558 INC AX ;AN000;get next paragraph
1559 ADD AX,PARA_OF_HDR ;AC005;consider header size
1560 ADD BUFFER_PTR, AX ;AN000;add this to the current buffer_ptr
1562 ; $IF NC,AND ;not exceed 16 bit.
1564 MOV AX, Top_of_memory;AN000;
1565 SUB AX, BUFFER_PTR ;AN000;AX = Top_of_memory - Buffer_ptr
1566 ; $IF A ;if buffer_left > 0
1568 MOV BUFFER_LEFT, AX;AN000;
1570 JMP SHORT $$EN37 ;AN000;
1572 MOV BUFFER_LEFT, 0 ;AN000;indication of buffer full
1577 SET_BUFFER_PTR ENDP ;AN000;
1580 WRITE_FROM_BUFFER PROC NEAR ;AN000;
1581 ;Write from the first header starting at buffer_base until finishes
1582 ;the last header which, actually, happens to be the old_buffer_ptr
1583 ;at the time of the call. After the writing, reset the buffer_ptr
1584 ;to buffer_base again for the next read_into_buffer.
1585 ;If continue_info is 1 or 2 (Continue of small, bigfile) then after
1586 ;the creation of a target file, it will set the CREATED_FLAG.
1587 ;This flag will be reset when it found the continue_info to be 3
1589 ;For convenience of use of function call, ES will be used for
1590 ;the program data seg while DS will be used for the BUFFER seg.
1593 PUSH ES ;AN000;save ds, es
1596 POP ES ;AN000;set ES to program data seg
1598 OR ACTION_FLAG, READING_FLAG ;AN000;show reading message next time
1599 ; AND ES:MY_FLAG, RESET_IS_SOURCE ;now, deals with target
1600 ;set this for change_dir
1601 MOV AX, ES:BUFFER_BASE ;AN000;
1605 CMP ES:OLD_BUFFER_PTR, AX ;AN000;if old_buffer_ptr = CS then
1606 ;buffer is empty. Just exit
1607 JE WFB_EXIT_BRIDGE ;AN000;
1612 .IF < DEST eq 3 > ;AN000;
1613 CALL GET_DEST ;AN000;
1618 CALL CHANGE_T_DIR ;AN000;
1619 JC WFB_ERROR_BRIDGE ;AN000;error?
1621 CMP DS:ATTR_FOUND, Is_subdirectory ;AN000;a subdirectory? = 10H
1622 JNE WFB_FILE ;AN000;no. a file
1624 WFB_CMP_DEPTH: ;AN000;
1625 ; \19\19\19\19\19\19\19\19\19\19\19\19 SAR \19\19\19\19\19\19\19\19\19\19\19\19
1627 ; MOV AH, ES:T_DEPTH ;yes. a subdir.
1628 ; CMP DS:DIR_DEPTH, AH ;DIR_DEPTH > T_DEPTH ?
1629 ; JBE WFB_DEC_DEPTH ;if not, go to parent node
1630 ; LEA DI, ES:T_DRV_PATH ;else goto child node
1631 ; LEA SI, DS:FILENAME_FOUND
1632 ; CMP ES:T_PATH, 0 ;root directory?
1634 ; MOV AL, 0FFh ;then don't need to put delim since it is already there
1636 ; MOV AL, Path_delim ;path_delim '\'
1638 ; CALL CONCAT_ASCIIZ
1639 ; call concat_display_path ;modify the path for display
1641 ; CALL MAKE_DIR ;try to make a new sub directory
1642 ; JC WFB_EXIT_A_BRIDGE ;there exists a file with same name.
1643 ; MOV AX, DS ;current buffer seg = old_buffer_ptr?
1644 ; CMP ES:OLD_BUFFER_PTR, AX
1645 ; JNE WFB_NEXT ;not finished yet. jmp to next
1646 ; OR ES:MY_FLAG, MISSING_LINK_FLAG ;Finished. Missing link condition occurred regarding empty sub dir
1647 ; JMP WFB_EXIT_A ;check archieve options.
1649 ; MOV DS, DS:NEXT_PTR ;let's handles next header.
1650 ; JMP WFB_CD ;change directory first.
1651 WFB_EXIT_BRIDGE: JMP WFB_EXIT
;AN000;
1652 WFB_ERROR_BRIDGE: JMP WFB_ERROR
;AN000;
1653 WFB_EXIT_A_BRIDGE: JMP WFB_EXIT_A
;AN000;
1654 WFB_DEC_DEPTH: ;AN000;
1655 ; LEA DI, ES:T_DRV_PATH
1656 ; CALL RM_EMPTY_DIR ;check flags and remove empty dir
1657 ; CALL LAST_DIR_OUT ;take off the last dir from path
1658 ; call cut_display_path ;modify path for display purpose
1659 ;;;;;; DEC ES:T_DEPTH ;and decrease depth
1660 JMP WFB_CD
;AN000;CHANGE DIR AND compare the depth again.
1663 WFB_FILE: ;AN000;Handling a file
1664 AND ES:MY_FLAG
, RESET_MISSING_LINK
;AN000;if found a file, then current dir is not empty.
1665 TEST ES:FILE_FLAG
, CREATED_FLAG
;AN000; A file handle is created ?
1666 JNZ WFB_WRITE
;AN000;yes, skip create again.
1667 CALL CREATE_A_FILE
;AN000;create a file in the cur dir
1668 JC WFB_ERROR
;AN000;file creation error?
1670 CALL WRITE_A_FILE
;AN000;
1671 JC WFB_EXIT_A
;AN000;target file has been already deleted.
1672 CMP DS:CONTINUE_INFO
, 0;AN000;
1673 ; $IF E,OR ;if continue_info = 0 or 3
1675 CMP DS:CONTINUE_INFO
, 3;AN000;
1679 MOV BX, ES:T_HANDLE
;AN000;
1680 CALL SET_FILE_DATE_TIME
;AN000;then set file's date, time
1681 PUSH DS ;AN005;SAVE THE BUFFER PTR
1682 PUSH ES ;AN005;WE NEED THE DATA PTR
1683 POP DS ;AN005;DS = THE DATA PTR
1684 CALL CLOSE_A_FILE
;AN000;and close the handle
1685 POP DS ;AN005;DS = THE BUFFER PTR AGAIN
1686 ;;;;;;; CALL RESTORE_FILENAME_FOUND ; SAR if filename_found has been changed, restore it for reset_s_archieve.
1687 AND ES:FILE_FLAG
, RESET_CREATED
;AN000;and reset created_flag
1688 CALL INC_FILE_COUNT
;AN000;increase file count
1692 CMP ES:OLD_BUFFER_PTR
, AX ;AN000;current header is the last one?
1693 JE WFB_EXIT_A
;AN000;then exit
1694 MOV DS, DS:NEXT_PTR
;AN000;else set ds to the next ptr
1695 JMP WFB_CHATT
;AN000;handle the next header
1697 jmp main_exit
;AN000;meaningful when MKDIR failed because
1698 ;of there already exist same named file,
1701 test ES:option_flag
, slash_m
;AN000;hard archieve ? - turn off source archieve bit.
1702 jz wfb_exit_B
;AN000;no, chk error flag and exit
1703 ;;;; call reset_s_archieve ; SAR reset source file(s) archieve bit using header info(s).
1705 test ES:copy_status
, mkdir_error_flag
;AN000;mkdir error happened?
1706 JNZ WFB_ERROR
;AN000;yes, exit
1707 test ES:copy_status
, disk_full_flag
;AN000;disk full happened?
1708 JNZ WFB_ERROR
;AN000;yes, exit
1710 MOV ES:OLD_BUFFER_PTR
, CS ;AN000;set old_buffer_ptr to CS
1711 MOV AX, ES:BUFFER_BASE
;AN000;
1712 MOV ES:BUFFER_PTR
, AX ;AN000;set buffer_ptr to base
1713 MOV AX, ES:MAX_BUFFER_SIZE
;AN000;
1714 MOV ES:BUFFER_LEFT
, AX ;AN000;set buffer_left
1717 ;;;; TEST SYS_FLAG, ONE_DISK_COPY_FLAG ; SAR one drive letter copy?
1718 ; ; $IF NZ ; SAR yes
1719 ; ; CALL CHANGE_S_DIR ; SAR then change current dir to s dir
1722 WRITE_FROM_BUFFER ENDP
;AN000;
1724 INC_FILE_COUNT PROC
NEAR;AN000;
1725 ;increase the file count by one.
1726 ;increase file_cnt_low, file_cnt_high.
1729 INC ES:FILE_CNT_LOW
;AN000;
1730 JNZ IFC_EXIT
;AN000;
1731 INC ES:FILE_CNT_HIGH
;AN000;if carry over, then inc file_cnt_high
1734 INC_FILE_COUNT ENDP
;AN000;
1736 CREATE_A_FILE PROC
NEAR;AN000;
1737 ;create a file in the header and return the file handle in T_HANDLE.
1738 ;Set CREATED_FLAG. This will be reset by WRITE_FROM_BUFFER when it
1740 ;this routine will check the T_FILENAME and T_TEMPLATE if any target
1741 ;filename has been entered. If T_FILENAME is there, then DX will
1742 ;points to this (This is the case when the user has specified non_global
1743 ;chr filename and any source filename be changed to this name.)
1744 ;If T_TEMPLATE is present, then modify the filename found in the
1746 ;Also, this routine show copy messages just before a file creation using
1754 ; \19\19\19\19\19 SAR \19\19\19\19\19\19 ;save the original filename from the header
1755 ;;;;; MOV CX, 13 ;max 13 chr
1756 ; LEA SI, DS:FILENAME_FOUND ;original source file name
1757 ; LEA DI, ES:DISP_S_FILE ;filename to be displayed
1758 ; REP MOVSB ;filename_found => disp_s_file
1759 ;;;;; test es:option_flag, slash_p ; SAR
1761 ;;;;; CALL SHOW_COPY_MESSAGE ; SAR he source path, file
1764 ; CMP ES:T_FILENAME, 0
1765 ; $IF NE ;non_global target filename entered.
1766 ; TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG
1768 ; LEA SI, DS:FILENAME_FOUND
1769 ; LEA DI, ES:T_FILENAME
1770 ; CALL COMP_FILENAME ;compare it. if same then show
1771 ; ;file cannot be copied onto itself and
1775 ; CALL SWITCH_DS_ES ;now ds - data, es - buffer
1777 ; LEA SI, DS:T_FILENAME
1778 ; LEA DI, ES:FILENAME_FOUND
1779 ; REP MOVSB ; t_filename => filename_found
1780 ; CALL SWITCH_DS_ES ;now ds - buffer, es - data seg
1783 ; CMP ES:T_TEMPLATE, 0 ;global chr target filename entered?
1784 ; $IF NE ;yes, entered. modify the filename found
1785 ;;;;; CALL MODIFY_FILENAME ; SAR
1786 ; TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG
1788 ; LEA SI, DS:FILENAME_FOUND ;compare the Revised filename
1789 ; LEA DI, ES:DISP_S_FILE ;with original name
1790 ; CALL COMP_FILENAME ;if same, then issue error message and exit
1793 ; TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG ;*.* CASE
1796 ; POP DS ;ds - data seg
1798 ; ; Set message parameters
1799 ;;;;; MOV AX,MSG_COPY_ITSELF ; SAR
1800 ; MOV MSG_NUM,AX ; SAR ;AN000; set message number
1801 ; MOV SUBST_COUNT,0 ; SAR AN000; no message subst.
1802 ; MOV MSG_CLASS,-1 ; SAR AN000; message class
1803 ; MOV INPUT_FLAG,0 ; SAR AN000; no user input
1804 ; CALL PRINT_STDERR ; SAR AN000; display error
1810 ;-------------------------------------------------------------------------
1811 ; Use extended open DOS call to create the target file, use attribute list
1812 ; obtained from the previous Get Extended attribute DOS call
1813 ;-------------------------------------------------------------------------
1815 ; SET ATTRIBUTE LIST POINTER IN PARAMETER LIST
1816 MOV DX, OFFSET
DS:ATTRIB_LIST
;AN005;E A BUFFER IN HEADER
1817 MOV WORD PTR ES:E_A_LST
,DX ;AN005; set offset
1818 MOV WORD PTR ES:E_A_LST
+WORD,DS ;AN005; set segment
1820 MOV AX, Ext_Open
;AN000; = 6Ch
1821 MOV DX,CREATE_FLAG
;AN000; flag = 0111H
1822 MOV BX,CREATE_MODE
;AN000;CREATE MODE = 0011H
1823 MOV CX,CREATE_ATTR
;AN000; attribute = 0
1824 MOV SI,OFFSET TARGET_DRV_LET
;AN005; DS:SI-->NAME TO CREATE
1825 LEA DI,ES:PARAM_LIST
;AN005;PARAMETER LIST (ES:DI)
1826 INT 21H
;AN000; create file
1828 JC CAF_ERROR
;AN000;
1829 MOV ES:T_HANDLE
, AX ;AN000;save handle
1831 ;;;;; CALL CHK_T_RES_DEVICE ; SAR check target handle is a reserved dev
1833 OR ES:FILE_FLAG
, CREATED_FLAG
;AN000;set created_flag
1834 JMP CAF_EXIT
;AN000;
1839 OR COPY_STATUS
, CREATE_ERROR_FLAG
;AN000;
1840 CALL EXTENDED_ERROR_HANDLER
;AN000;
1846 CREATE_A_FILE ENDP
;AN000;
1848 ;COMP_FILENAME PROC NEAR
1849 ;;this routine is called when MAYBE_COPY_ITSELF flag in on.
1850 ;;SI, DI asciiz string will be compared and if they are identical
1851 ;;the show "Cannot copy onto itself" msg and jmp to main_exit.
1852 ;;INPUT: DS - buffer
1858 ; CALL STRING_LENGTH ;CX get the length of string
1859 ; MOV BX, CX ;now, BX got the length of the target filename entered.
1864 ; POP ES ;now ES set to DS
1866 ; POP DI ;now DI points to the source filename found.
1869 ; CALL STRING_LENGTH ;CX got the length of the string
1871 ; POP ES ;restore ES
1872 ; POP BX ;restore BX
1873 ; POP DI ;restore DI
1875 ; CMP BX, CX ;COMPARE LENGTH
1876 ; JNE CF_EXIT ;IF THEY ARE DIFFERENT, EXIT
1878 ; REPE CMPSB ;compare SI, DI until not equal,
1879 ; CMP CX, 0 ;finish at cx = 0?
1884 ; POP DS ;ds = data seg
1886 ;; Set message parameters
1887 ;;;;;; MOV AX,MSG_COPY_ITSELF ; SAR ;AN000; message number
1888 ;; MOV MSG_NUM,AX ; SAR AN000; set message number
1889 ;; MOV SUBST_COUNT,0 ; SAR AN000; no message substitution
1890 ;; MOV MSG_CLASS,-1 ; SAR AN000; message class
1891 ;;; MOV INPUT_FLAG,0 ; SAR AN000; no input
1892 ;; CALL PRINT_STDERR ; SAR AN000; display error message
1898 WRITE_A_FILE PROC
NEAR ;AN000;
1899 ;write a file from the data area in the buffer.
1900 ;Remember the caller is WRITE_FROM_BUFFER which use ES for
1901 ;the program data area and DS for the header in the buffer.
1902 MOV AH, Write
;AN000; = 40h
1903 MOV BX, ES:T_HANDLE
;AN000;handle saved in the program data area
1904 MOV DX, ES:BYTS_OF_HDR
;AC005;skip header
1905 MOV CX, DS:CX_BYTES
;AN000;get the # from the header
1907 JC WAF_ERROR
;AN000;write error
1908 CMP AX, DS:CX_BYTES
;AN000;
1909 JNE WAF_DISKFULL
;AN000;
1910 JMP WAF_EXIT
;AN000;
1912 CALL CLOSE_DELETE_FILE
;AN000;close delete troubled file
1913 OR COPY_STATUS
, WRITE_ERROR_FLAG
;AN000;
1914 CALL SWITCH_DS_ES
;AN000;DS = DATA SEG, ES = BUFFER
1915 CALL EXTENDED_ERROR_HANDLER
;AN000;
1916 CALL SWITCH_DS_ES
;AN000;ES = DATA SEG, DS = BUFFER
1917 WAF_DISKFULL: ;AN000;
1918 ; MOV ERRORLEVEL, 4 ; SAR ;set errorlevel
1920 ; Set message parameters
1921 ; Target disk full, critical error
1923 PUSH DS ;AN000;DS = BUFFER
1924 PUSH ES ;AN000;ES = DATA SEG
1925 POP DS ;AN000;ES => DS = DATA SEG
1926 ;;;;; MOV AX,MSG_DISK_FULL ; SAR ;AN000; message number
1927 ; MOV MSG_NUM,AX ; SAR AN000; set message number
1928 ; MOV SUBST_COUNT,0 ; SAR AN000; no message substitution
1929 ; MOV MSG_CLASS,UTILITY_MSG_CLASS ; SAR AN000; message class
1930 ; MOV INPUT_FLAG,0 ; SAR AN000; no input
1931 ; CALL PRINT_STDERR ; SAR AN000; display error message
1932 OR COPY_STATUS
, DISK_FULL_FLAG
;AN000;set disk_full_flag
1933 POP DS ;AN000;RESTORE DS = BUFFER
1934 CALL CLOSE_DELETE_FILE
;AN000;
1935 STC ;AN000;set carry and return to caller
1938 WRITE_A_FILE ENDP
;AN000;
1940 SET_FILE_DATE_TIME PROC
NEAR;AN000;
1941 ;input: BX - target file handle
1943 MOV AH, File_date_time
;AN000; = 57h
1944 MOV AL, Set_file_time
;AN000; = 1
1945 MOV CX, DS:FILE_TIME_FOUND
;AN000;
1946 MOV DX, DS:FILE_DATE_FOUND
;AN000;
1949 SET_FILE_DATE_TIME ENDP
;AN000;
1951 CLOSE_A_FILE PROC
NEAR ;AN000;
1952 ;INPUT: BX - file handle to be closed
1953 CMP OPEN_FILE_COUNT
,NUL
;AN005;ARE THERE ANY OPEN FILES?
1956 DEC OPEN_FILE_COUNT
;AN005;IF SO, REDUCE THE COUNT BY 1.
1959 MOV AH, Close
;AN000; = 3Eh
1962 CLOSE_A_FILE ENDP
;AN000;
1964 DELETE_A_FILE PROC
NEAR;AN000;
1965 ;input: DS:DX - points to ASCIIZ string
1967 MOV AH, 41h
;AN000; = 41h
1970 DELETE_A_FILE ENDP
;AN000;
1973 ;CHK_DISK_FULL PROC NEAR
1974 ;check target disk space, and if no more clusters then set carry, disk_full_flag.
1975 ;this routine is called by MAKE_DIR routine.
1982 ; MOV AH, 36h ;GET DISK FREE SPACE
1983 ; MOV DL, ES:T_DRV_NUMBER ;OF TARGET
1985 ; CMP BX, 0 ;NO MORE CLUSTER?
1988 ; JMP SHORT CDF_EXIT
1990 ; OR ES:COPY_STATUS, DISK_FULL_FLAG ;SET DISK FULL FLAG
2001 ;;subttl string_length
2003 ;******************************************************************************
2004 ;PURPOSE: Get the length of a string pointed by ES:DI until it encounters
2005 ; the same character given by the user in AL.
2006 ; The length will be an output in CX. The number includes the
2008 ; For example, if you want to determine the length of an ASCIIZ string,
2009 ; set ES:DI to that string and set AL to 0. The output CX is the
2010 ; total length of the ASCIIZ string including 0.
2011 ; So, if the first character pointed by DI is the same as that of AL,
2012 ; then the length will be 1.
2013 ; !!! It is the user's responsibility to make it sure that the string
2014 ; contains the character given in AL. If not, unpredictable
2015 ; results will occur.!!!
2018 ; REGISTERS: AL - ASCII CHARACTER
2019 ; ES:DI - POINTER TO THE STRING.
2021 ; REGISTERS: AX,DX,SI etc - PRESERVED.
2023 ; CX - STRING LENGTH UNTIL FOUND THE GIVEN CHARACTER.
2024 ; DI - POINTS TO THE NEXT CHARACTER AFTER THE STRING.
2025 ; DIRECTION FLAG - CLEARED
2027 ;******************************************************************************
2029 ;STRING_LENGTH PROC NEAR
2030 ;PUBLIC STRING_LENGTH
2031 ; CLD ;CLEAR DIRECTION
2032 ; MOV BX,DI ;SAVE ORIGINAL DI VALUE
2033 ; MOV CX,80H ;TRY MAX 128 BYTES
2034 ; REPNE SCASB ;SCAN THE STRING UNTIL FOUND
2035 ; PUSH DI ;SAVE CURRENT DI VALUE WHICH POINTS TO NEXT CHR AFTER STRING
2036 ; SUB DI,BX ;GET THE LENGTH
2037 ; MOV CX,DI ;MOV THE LENGTH TO CX
2042 ;subttl concat_asciiz
2044 ;******************************************************************************
2045 ;PURPOSE: Concatenate two ASCIIZ string into one ASCIIZ string.
2046 ; The ASCIIZ string pointed by DS:SI will be concatenated to
2047 ; the one pointed by ES:DI. The result string will be pointed by
2049 ; AL is used to put the delimeter character in between the strings.
2050 ; If you *DON'T* like to put the delimeter ***make AL to 0FFh***.
2051 ; For example, assume sting1 "ABCDE",0 pointed by DI and string2
2052 ; "FGHI",0 pointed by SI.
2053 ; If you want a delimeter "\" between two string, set AL to "\"
2054 ; before calling. The result will "ABCDE\FGHI",0 pointed by DI.
2055 ; If you set AL to "0FFh", then it becomes "ABCDEFGHI",0.
2056 ; This feature is useful for handling PATH if you set AL to "\"
2057 ; and, for any general string processes if you set AL to "0FFh".
2058 ; This routine will call subroutine STRING_LENGTH.
2060 ; REGISTERS: AL - DELIMETER OR 0FFh
2061 ; ES:DI - POINTER TO THE DESTINATION STRING.
2062 ; DS:SI - POINTER TO THE SOURCE TO BE CONCATENATED.
2064 ; REGISTERS: AL, DX - preserved
2065 ; DI - preserved. POINTER TO THE RESULT STRING
2067 ; CX - RESULT ASCIIZ STRING LENGTH INCLUDE 0
2068 ; DIRECTION FLAG - CLEARED
2069 ;******************************************************************************
2070 ;CONCAT_ASCIIZ PROC NEAR
2072 ;PUBLIC CONCAT_ASCIIZ
2073 ; PUSH DI ;SAVE POINTER VALUE WHICH WILL BE RETRUNED TO CALLER.
2074 ; PUSH AX ;SAVE VALUE IN AL.
2075 ; MOV AL, 0 ;DEALING WITH ASCIIZ STRING
2076 ; CALL STRING_LENGTH ;LET DI POINTS TO THE NEXT CHR AFTER THIS STRING
2077 ; ;DIRECTION WILL BE CLEARED.
2078 ; DEC DI ;MAKE DI POINT TO THE LAST CHARACTER 0
2079 ; POP AX ;RESTORE AL.
2081 ;; $IF NE ;IF THE USER WANTS TO PUT DIMIMETER,
2083 ; STOSB ; REPLACE 0 WITH IT.
2087 ; DEC CX ;ELSE DECREASE LENGTH BY 1
2092 ; LODSB ;MOV [SI] TO AL
2093 ; STOSB ;STORE AL TO [DI]
2094 ; INC CX ;INCREASE LENGTH
2095 ; CMP AL, 0 ;WAS IT A LAST CHARACTER?
2096 ;; $ENDDO E ;THEN EXIT THIS LOOP
2103 ;subttl last_dir_out
2105 ;******************************************************************************
2106 ;PURPOSE: Take off the last directory name from the path pointed by DI.
2107 ; This routine assumes the pattern of a path to be an ASCIIZ string
2108 ; in the form of "[d:][\]dir1\dir2". Notice that this path does not
2109 ; have entailing "\". This routine will simply travel the string
2110 ; until it found last "\" which will, then, be replaced with 0.
2111 ; If no "\" found, then carry will be set.
2112 ; *** This should be not be used for the path in the form of
2113 ; *** "d:\", 0 for the root directory, since in this case the returned
2114 ; *** string will be "d:",0 and AX value returned be meaningless (Just
2117 ; REGISTERS: DI - points to an ASCIIZ path string.
2118 ; ES - assumed default segment for DI
2120 ; REGISTERS: DI - points to the resultant path string.
2121 ; AX - offset value of the last subdirectory name taken out, in case
2122 ; of the user's need.
2123 ; Other register will be unchanged.
2124 ; CARRY FLAG WILL SET IF NOT FOUND.
2125 ;******************************************************************************
2127 ;LAST_DIR_OUT PROC NEAR
2128 ;PUBLIC LAST_DIR_OUT
2131 ; PUSH SI ;save current DI, SI
2132 ; CLD ;clear direction
2133 ; MOV SI, 0FFFFh ;used as a not_found flag if unchanged.
2138 ;; $LEAVE Z ;if [DI] = 0, then end of string. Ends this loop.
2140 ; DEC DI ;if [DI] <> 0, then go back and scan char again
2141 ; MOV AL, "\" ;to see it was a back slash.
2143 ;; $IF Z ;if it was, then save the addr to SI.
2149 ;; $ENDIF ;else do loop again.
2154 ; CLC ;clear carry flag.
2155 ; CMP SI, 0FFFFh ;Had SI been changed?
2158 ; STC ;No, set the carry. Not found.
2162 ; MOV BYTE PTR ES:[SI], 0 ;Yes, replace "\" with 0. Seg override to get default DI seg.
2164 ; INC AX ;let AX have the last dir offset value.
2168 ; POP SI ;restore original value
2169 ; POP DI ;original string offset
2174 SET_DEFAULT_DRV PROC
NEAR;AN000;
2175 ;change source drv as a default drv for conveniece of find, read operation
2176 ;of source. (handling target should be more specific as for as drive letter
2178 ;input: DL - drive # (0 = A, 1 = B ...)
2180 MOV AH, Select_Disk
;AN000; = 0Eh
2182 OR SYS_FLAG
, DEFAULT_DRV_SET_FLAG
;AN000;indicates default drv has been changed
2183 ;Used for exit the program to restore default drv
2185 SET_DEFAULT_DRV ENDP
;AN000;
2187 ORG_S_DEF PROC
NEAR ;AN000;
2188 ;restore the original source directory.
2193 POP ES ;AN000;DS=ES=data seg
2195 TEST SYS_FLAG
, DEFAULT_S_DIR_FLAG
;AN000;source default direcotry saved?
2198 MOV DX, OFFSET SAV_S_DRV
;AN000;saved source drive letter & directory
2200 INT 21h
;AN000;restore source
2201 AND SYS_FLAG
, RESET_DEFAULT_S_DIR
;AN000;reset the flag
2209 ORG_S_DEF ENDP
;AN000;
2211 ORG_S_T_DEF PROC
NEAR ;AN000;
2212 ;retore original target, source and default drv and directory
2213 ;check default_s(t)_dir_flag, default_drv_set_flag to restore source,
2214 ;or target directory and default drive.
2216 TEST SYS_FLAG
, TURN_VERIFY_OFF_FLAG
;AN000;turn off verify?
2219 MOV AX, 2E00h
;AN000;turn it off
2224 TEST SYS_FLAG
, DEFAULT_DRV_SET_FLAG
;AN000;default drive has been changed?
2227 MOV DL, SAV_DEFAULT_DRV
;AN000;
2229 CALL SET_DEFAULT_DRV
;AN000;restore default drv.
2231 ; Following is a fix for PTR 0000012 . The fix is to skip changing default
2232 ; drive directory if source drive is not the default drive.
2234 MOV AL, S_DRV_NUMBER
;AN002; get source drive number
2235 CMP AL, SAV_DEFAULT_DRV
;AN002; src drive is the default drv ?
2236 JNE SKIP_CH_DIR
;AN002; no, dont change directory
2238 MOV DX, OFFSET SAV_DEF_DIR_ROOT
;AN000;
2239 MOV AH, Chdir
;AN000;
2240 INT 21H
;AN000;restore current dir of default dir
2241 SKIP_CH_DIR: ;AN000;
2245 TEST SYS_FLAG
, DEFAULT_S_DIR_FLAG
;AN000;source default direcotry saved?
2248 MOV DX, OFFSET SAV_S_DRV
;AN000;saved source drive letter & directory
2250 INT 21h
;AN000;restore source. This is for the case of ERROR exit.
2254 TEST SYS_FLAG
, DEFAULT_T_DIR_FLAG
;AN000;target default directory saved?
2255 ; $IF NZ ;then assume both source, target default saved
2257 MOV DX, OFFSET SAV_T_DRV
;AN000;saved target drive letter & directory
2259 INT 21h
;AN000;restore target
2264 ORG_S_T_DEF ENDP
;AN000;
2266 EXTENDED_ERROR_HANDLER PROC
NEAR;AN000;
2267 ;This routine calls fun 59(Get extended error) and
2268 ;check the actions returned. If it is Immediate exit, then jmp to JUST_EXIT
2269 ;If it is abort, then jmp to MAIN_EXIT.
2270 ;Or else, it check the COPY_STATUS flag. If is not open, read, create or
2271 ;write, then it is considered as a critical error and jmp to MAIN_EXIT.
2273 ; too many open files
2277 ;then show the message and jmp to the MAIN_EXIT.
2278 ; *** Currently, this routine directly jump to the main_exit instead of
2279 ; *** returing to the caller. The reason is we regard the above error conditions
2280 ; *** as being not suitable to continue copying and, hence, to simplify
2281 ; *** the error process.
2285 ; ALL THE REG PRESERVED
2287 GOTO_MAIN_EXIT: ;AN000;
2288 JMP MAIN_EXIT
;AN000;restore conditions
2291 JMP JUST_EXIT
;AN000;immediate exit
2295 EXTENDED_ERROR_HANDLER ENDP
;AN000;
2297 CLOSE_DELETE_FILE PROC
NEAR;AN000;
2298 ;when writing error occurs, then this routine is called to
2299 ;clean up the troubled target file.
2300 ;INPUT: DS - buffer seg
2303 MOV BX, ES:T_HANDLE
;AN000;close target file
2304 PUSH DS ;AN005;SAVE THE BUFFER PTR
2305 PUSH ES ;AN005;WE NEED THE DATA PTR
2306 POP DS ;AN005;DS = THE DATA PTR
2307 CALL CLOSE_A_FILE
;AN000;
2308 POP DS ;AN005;DS = THE BUFFER PTR AGAIN
2309 LEA DX, DS:target_drv_let
;AN000;target drv, filename
2310 CALL DELETE_A_FILE
;AN000;delete it
2312 CLOSE_DELETE_FILE ENDP
;AN000;
2316 SWITCH_DS_ES PROC
NEAR;AN000;
2323 SWITCH_DS_ES ENDP
;AN000;
2326 INIT PROC
NEAR ;AN000;
2328 CALL GET_CUR_DRV
;AN000;save current default drv
2329 MOV DL, SAV_DEFAULT_DRV
;AN000;
2330 LEA SI, SAV_DEFAULT_DIR
;AN000;
2332 CALL GET_CUR_DIR
;AN000;save current default dir
2333 CALL GET_DRIVES
;AN000; SAR
2334 CALL TOP_OF_MEM
;AN000;set top_of_memory
2335 CALL INIT_BUFFER
;AN000;init buffer information
2337 MOV DL, T_DRV_NUMBER
;AN000; SAR
2338 .IF < DL AE
3 > ;AN000; SAR
2339 LEA SI, SAV_T_CURDIR
;AN000; SAR
2340 CALL GET_CUR_DIR
;AN000; SAR
2341 OR SYS_FLAG
, DEFAULT_T_DIR_FLAG
;AN000; SAR
2343 AND SYS_FLAG
, NOT DEFAULT_T_DIR_FLAG
;AN000; SAR
2347 MOV DL, S_DRV_NUMBER
;AN000;
2349 CALL SET_DEFAULT_DRV
;AN000;set source as a default drv
2354 GET_DRIVES PROC
NEAR ;AN000;
2355 ;get source and target phisical drive letter from parser area.
2356 ;set ONE_DISK_COPY_FLAG, if the user XCOPY using the same drive letter.
2358 ;;;;; MOV AL, SO_DRIVE ;AN000;source drive letter
2359 ; CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
2360 ; $IF E ;AN000;YES, GET THE DEFAULT
2361 ; MOV AL, SAV_DEFAULT_DRV ;(1=A, 2=B,...)
2362 ; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
2363 ; SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
2366 MOV AL, 1 ;AN000; SAR A is the source drive
2367 MOV S_DRV_NUMBER
, AL ;AN000;SAVE DRV #
2368 ADD AL, BASE_OF_ALPHA_DRV
;AN000;
2370 MOV S_DRV
, AL ;AN000;save source drive letter
2371 MOV S_DRV_1
, AL;AN000;
2372 ;; MOV S_ARC_DRV, AL ; SAR
2373 MOV SAV_S_DRV
, AL;AN000;
2375 .IF < DEST
eq 3 > ;AN111;JW
2378 MOV AL, DEST
;AN000; SAR target drive letter
2381 ;;;;; CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
2382 ; ; $IF E ;AN000;YES, GET THE DEFAULT
2383 ; ; MOV AL, SAV_DEFAULT_DRV ;(1=A, 2=B,...)
2384 ; ; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
2385 ; ; SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
2387 MOV T_DRV_NUMBER
, AL ;AN000;save target drv #
2389 ;;;;; CMP S_DRV_NUMBER, AL ;s_drv_number = t_drv_number?
2391 ; ; OR SYS_FLAG, ONE_DISK_COPY_FLAG ;same logical drv copy
2394 ADD AL, BASE_OF_ALPHA_DRV
;AN000;make target drv # to drive letter
2395 MOV T_DRV
, AL ;AN000;target drive letter
2396 ;; MOV T_DRV_1, AL ; SAR
2397 ;; MOV T_DRV_2, AL ; SAR
2398 MOV SAV_T_DRV
, AL;AN000;
2400 GET_DRIVES ENDP
;AN000;
2402 GET_CUR_DRV PROC
NEAR;AN000;
2403 ;get the current default drive number (0 = A, 1 = B ..),
2404 ;change it to BIOS drive number and save it.
2405 MOV AH, Current_Disk
;AN000; = 19h
2407 INC AL ;AN000;(1 = A, 2 = B ..)
2408 MOV SAV_DEFAULT_DRV
, AL ;AN000;save it
2410 GET_CUR_DRV ENDP
;AN000;
2412 GET_CUR_DIR PROC
NEAR ;AN000;
2413 ;get current directory and save it
2414 ;input: DL - drive # (0 = default, 1 = A etc)
2415 ; DS:SI - pointer to 64 byte user memory
2417 MOV AH, Get_Current_Directory
;AN000;
2420 GET_CUR_DIR ENDP
;AN000;
2422 TOP_OF_MEM PROC
NEAR ;AN000;
2425 MOV BX, PSP_SEG
;AN000;
2427 MOV AX, ES:2 ;AN000;PSP top of memory location
2428 SUB AX, 100H
;AN000;subtract dos transient area (4k)
2429 MOV TOP_OF_MEMORY
, AX ;AN000;save it for buffer top
2432 TOP_OF_MEM ENDP
;AN000;
2434 INIT_BUFFER PROC
NEAR ;AN000;
2435 ;initialize buffer information
2436 ;set buffer_base, max_buffer_size
2437 ; call set_block ;SET BLOCK FOR BUFFR (for new 3.2 linker)
2438 MOV AX, 0 ;AN000; SAR
2439 ;;;; PUSH CS ; SAR cs segment is the highest segment in this program
2441 MOV DX, ALLOCATE_START
;AN000; SAR
2442 MOV BUFFER_PTR
, DX ;AN000;
2443 CALL SET_BUFFER_PTR
;AN000;
2444 MOV AX, BUFFER_PTR
;AN000;
2445 MOV BUFFER_BASE
, AX ;AN000;set buffer_base
2446 MOV AX, BUFFER_LEFT
;AN000;
2447 CMP AX, 140h
;AN000;BUFFER_LEFT < 5K which is the minimum size this program supports?
2449 ;;;;;; PUSH AX ; SAR ;AN000;
2450 ; MOV AX, MSG_INSUF_MEMORY ; SAR ;AC000;GET THE MESSAGE ID
2451 ; MOV MSG_NUM,AX ; SAR ;AN000;NEED MESSAGE ID FOR PRINT
2452 ; MOV SUBST_COUNT,NUL ; SAR ;AN000;NO SUBSTITUTION TEXT
2453 ; MOV INPUT_FLAG,NUL ; SAR ;AN000;NO INPUT = 0
2454 ; MOV MSG_CLASS,UTILITY_MSG_CLASS ; SAR ;AN000;MESSAGE CLASS = -1
2455 ; CALL PRINT_STDERR ; SAR ;print error. AX points to message ID
2456 ; POP AX ; SAR ;AN000;
2457 ; MOV ERRORLEVEL, 4 ; SAR ;abnormal termination
2458 JMP MAIN_EXIT_A
;AN000;terminate this program
2460 MOV MAX_BUFFER_SIZE
, AX ;AN000;set max buffer size in para
2461 CMP AX, 0FFFh ;AN000;max_buffer_size > 64 K in para ?
2465 MUL CX ;AN000;AX = AX * 16 (DX part will be 0)
2466 SUB AX, 544 ;AN000;AN000;subtrack header size
2467 MOV MAX_CX
, AX ;AN000;this will be max_cx
2469 JMP SHORT $$EN65
;AN000;
2471 MOV MAX_CX
, 0FFD0h ;AN000;else max_cx = fff0 - 32 bytes
2472 ;which is the max # this program can support.
2473 ; $ENDIF ;(min # this program support for buffer is 5 k
2475 ; which has been decided by BIG_FILE )
2477 INIT_BUFFER ENDP
;AN000;