]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/SELECT/MOD_COPY.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / SELECT / MOD_COPY.ASM
1 PAGE, 132 ;AN000;\ f
2 TITLE XCOPY WITH FULL MEMORY USE ;AN000;
3
4 ; ##### R E A D M E #####
5 ;
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
8 ; needs of SELECT.
9 ;
10 ; #########################
11
12 ;****************** START OF SPECIFICATIONS *****************************
13 ; MODULE NAME: XCOPY
14 ;
15 ; DESCRIPTIVE NAME: selectively copy groups of files, which can include
16 ; lower level subdirectories.
17 ;
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)
21 ;
22 ; HEADER - informations needed about the file, subdirectory ...
23 ; Continue_Info -> 0 - a whole single file in this header
24 ; segment, or dir.
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
30 ;
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.
35 ;
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.
44 ;
45 ; ENTRY POINT: MAIN
46 ;
47 ; INPUT: (DOS COMMAND LINE PARAMETERS)
48 ;
49 ; SOURCE OPERAND: TARGET OPERAND:
50 ;
51 ; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
52 ; or
53 ; [d:] path [filename[.ext]]
54 ; or
55 ; d: [path] [filename[.ext]]
56 ;
57 ;
58 ; SWITCHES:
59 ;
60 ; /A /D /E /M /P /S /V /W
61 ;
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.
68 ;
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
72 ;indicated country.
73 ;
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.
77 ;
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.
84 ;
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.
90 ;
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.
97 ;
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.
102 ;
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.
111 ;
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.
115 ;
116 ; There are many types of problems that are detected and result in this
117 ; return code, such as:
118 ;
119 ; write failure due to hard disk error
120 ; disk full
121 ; conflict between name of new subdirectory and existing filename
122 ; access denied
123 ; too many open files
124 ; sharing violation
125 ; lock violation
126 ; general failure
127 ; file not found
128 ; path not found
129 ; directory full
130 ; invalid parms
131 ; reserved file name as source
132 ; insufficient memory
133 ; incorrect DOS version
134 ;
135 ;
136 ; INTERNAL REFERENCES:
137 ;
138 ; ROUTINES:
139 ;
140 ;
141 ; DATA AREAS:
142 ;
143 ;
144 ; EXTERNAL REFERENCES:
145 ;
146 ; ROUTINES:
147 ;
148 ;
149 ; DATA AREAS:
150 ;
151 ;
152 ; NOTES: This module should be processed with the SALUT pre-processor
153 ; with the re-alignment not requested, as:
154 ;
155 ; SALUT XCOPY,NUL,;
156 ;
157 ; To assemble these modules, the sequential
158 ; ordering of segments may be used.
159 ;
160 ; For LINK instructions:
161 ; link profile ..\lib
162 ;
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
169 ; >63 chrs.
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
177 ; ATTRIBUTES.
178 ;
179 ;
180 ; Label: "DOS XCOPY Utility"
181 ; "Version 4.00 (C) Copyright 1988 Microsoft"
182 ; "Licensed Material - Program Property of Microsoft"
183 ;
184 ;****************** END OF SPECIFICATIONS *****************************
185
186 CLEAR_SCREEN2 MACRO;AN000;
187 MOV CX,0 ;;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
192 INT 10H ;;AN000;
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
196 INT 10H ;;AN000; RKJ
197 ENDM ;;AN000;
198 ;--------------------------------
199 ; Include Files
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
208
209
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
216
217 EXTRN FIND_FILE_ROUTINE:FAR ;AN111;JW
218 EXTRN EXIT_SELECT:near ;AN111;JW
219
220 ;-------------------------------
221 ; Structures
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
230
231 HEADER STRUC ;AN000;
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
249 ;
250 ;EA STRUC ; EXTENDED ATTRIBUTE
251 ;EA_TYPE DB ? ; TYPE
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)
261 ; ; LENGTH: 2 BYTES
262 ;EAISTIME EQU 5 ; DOS FILE TIME FORMAT (ATTRIB DISPLAYS)
263 ; ; LENGTH: 2 BYTES
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
284 ;
285 ;EA_VALUE DB ? ; FIRST BYTE OF VALUE
286 ;
287 HEADER ENDS ;AN000;
288
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
299 ;;;; ; SAR
300 ;;;;SUB_LIST ENDS ; SAR
301 ;******************************************************************************
302 DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; DATA Segment
303
304 INCLUDE DOSFILES.INC ;AN000; SAR
305
306 ;; ERRORLEVEL DB 0 ; SAR ;errorlevel
307 ;; INPUT_DATE DW 0 ; SAR
308 ;; INPUT_TIME DW 0 ; SAR
309 PSP_SEG DW ? ;AN000;
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;
317
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
322
323 SOURCE_IN DB ? ;AN111;JW
324 YES EQU 0 ;AN111;JW
325 NO EQU 1 ;AN111;JW
326
327 OLD_DTA_SEG DW ? ;AN111;JW
328 OLD_DTA_OFF DW ? ;AN111;JW
329
330 ;
331
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
336 ;
337 ;;B_SLASH DB '\',0 ; SAR
338
339
340 FILE_COUNT LABEL WORD ;AN000;
341 FILE_CNT_LOW DW 0 ;AN000;copied file count
342 FILE_CNT_HIGH DW 0 ;AN000;
343 ;
344
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"
348 ;
349 S_DRV_NUMBER DB 0 ;AN000;source, target drv #
350 T_DRV_NUMBER DB 0 ;AN000;
351 ;
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
355 S_DEPTH DB 0 ;AN000;
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
359
360 ;; S_PARENT DB '..',0 ; SAR ;source parent used for non single_drv_copy
361 S_HANDLE DW 0 ;AN000;file handle opened
362
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
367
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
371 T_DEPTH DB 0 ;AN000;
372
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.
377
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.
383 ;
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
391
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
400
401
402 ;; INPUT_BUFF db 20 dup(0) ; SAR ;AN000; keyboard input buffer used
403 ;for user response (Y/N)
404
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
417 ;; ; SAR
418 ;; ; SAR
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
428 ;; ; SAR
429 ;; ; SAR
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
439 ;;
440
441
442 FILE_SEARCH_ATTR DW NORM_ATTR;AN000;
443 ;; DIR_SEARCH_ATTR DW INCL_H_S_DIR_ATTR ; SAR
444 ;
445 OPEN_MODE DB Read_Only_Deny_Write ;AN000;READ_ONLY_DENY_WRITE ;access, sharing mode
446 ;
447 ;Equates are defined in XCOPY.EQU
448
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
465
466 FILE_FLAG DB 0 ;AN000;
467 ; cont_flag equ 01h
468 ; eof_flag equ 02h
469 ; big_file_flag equ 04h
470 ; file_bigger_flag equ 08h
471 ; created_flag equ 10h
472 ; reset_cont equ 0FEh
473 ; reset_eof equ 0FDh
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
478 ;
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
494 ;
495 ACTION_FLAG DB 0;AN000;
496 ; reading_flag equ 01h ;display "Reading source files..."
497 ; reset_reading equ 0FEh ;do not display.
498 ;
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
509 ;
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
521
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;
526 ;
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
538 ; ;SIZE CALCULATION.
539 ;
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.
545 DATA ENDS ;AN000;
546
547 ;******************************************************************************
548
549 SELECT SEGMENT PARA PUBLIC 'SELECT';AN000;
550 ASSUME CS:SELECT, DS:DATA ;AN000;
551
552 ;--- START OF A PROGRAM ---
553
554 PUBLIC MOD_XCOPY ;AN000;
555 MOD_XCOPY PROC NEAR ;AN000; SAR
556
557
558 PUSH ES ;AN000; SAR
559 PUSH BP ;AN000; SAR
560 ; SAR
561 PUSH DS ;AN000; SAR
562 POP ES ;AN000; SAR
563 MOV SP_SAVE, SP ;AN000; SAR
564 ; SAR
565 MOV SOURCE_IN,YES ;AN111;JW
566 .IF < AL eq 1 > ;AN000;
567 MOV AL,2 ;AN000;
568 .ELSEIF < AL eq 2 > ;AN000;
569 MOV AL,1 ;AN000;
570 .ENDIF ;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;
576
577 MOV AH, 62H ;AN000; SAR
578 INT 21H ;AN000; SAR
579 MOV PSP_SEG, BX ;AN000; SAR
580
581 CALL ALLOCATE ;AN000; SAR
582 .IF < C > ;AN000; SAR
583 JMP JUST_EXIT ;AN000; SAR
584 .ENDIF ;AN000; SAR
585
586 XCOPY_INIT: ;AN000;
587 CALL INIT ;AN000;initialization
588 JC MAIN_EXIT ;AN000;error. (Already message has been displayed)
589
590 MOV BP, OFFSET DTAS ;AN000;initialize BP
591 OR ACTION_FLAG, READING_FLAG ;AN000;set reading flag for copy message
592
593 CALL TREE_COPY ;AN000;
594
595 CALL ORG_S_DEF ;AN000;restore the original source default dir
596
597 CALL WRITE_FROM_BUFFER ;AN000;write from buffer if we missed it.
598
599 CALL SWITCH_DTAS ;AN111;JW
600
601 CLC ;AN000; SAR
602 JMP RESTORE_DIRS ;AN000; SAR
603
604 MAIN_EXIT: ;AN000;
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.
609
610 MAIN_EXIT_A: ;AN000;
611 STC ;AN000; SAR
612
613 RESTORE_DIRS:;AN000;
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?
618 PUSHF ;AN000; SAR
619 CALL ORG_S_T_DEF ;AN000;restore original target, source, default drv, and verify status
620 POPF ;AN000; SAR
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
625 STC ;AN000; SAR
626
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
632 STC ;AN000; SAR
633 .ELSE ;AN000; SAR
634 CLC ;AN000; SAR
635 .ENDIF ;AN000; SAR
636 .ENDIF ;AN000; SAR
637 MOV SP, SP_SAVE ;AN000; SAR
638 POP BP ;AN000; SAR
639 POP ES ;AN000; SAR
640 RET ;AN000; SAR
641
642 ; MOV AH, 4Ch ;return to dos
643 ; MOV AL, ERRORLEVEL ;set return code whatever
644 ; INT 21H
645
646 MOD_XCOPY ENDP;AN000;
647 ;
648
649
650 ;----------------- SUBROUTINES ---------------------------------------------
651
652 ALLOCATE PROC NEAR ;AN000; SAR
653 ; SAR
654 MOV BX, 0FFFFH ;AN000; SAR Attempt to allocate as much as possible
655 MOV AH, 48H ;AN000; SAR
656 INT 21H ;AN000; SAR
657 MOV AH, 48H ;AN000; SAR BX contains the amount of memory available
658 INT 21H ;AN000; SAR
659 MOV ALLOCATE_START, AX ;AN000; SAR
660 ; SAR
661 RET ;AN000; SAR
662 ; SAR
663 ALLOCATE ENDP ;AN000; SAR
664 ; SAR
665 DEALLOCATE PROC NEAR ;AN000; SAR
666 ; SAR
667 PUSHF ;AN000; SAR
668 PUSH ES ;AN000; SAR
669 MOV AX, ALLOCATE_START ;AN000; SAR
670 MOV ES, AX ;AN000; SAR
671 MOV AH, 49H ;AN000; SAR
672 INT 21H ;AN000; SAR
673 POP ES ;AN000; SAR
674 POPF ;AN000; SAR
675 ; SAR
676 RET ;AN000; SAR
677 ; SAR
678 DEALLOCATE ENDP ;AN000; SAR
679
680
681
682
683 TREE_COPY PROC NEAR ;AN000;
684
685 ;Walk the source tree to read files and subdirectories
686
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
693 .ELSE ;AN000; 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
697 .ENDIF ;AN000; SAR
698 MOV DI,OFFSET T_DRV_PATH ;AN000; SAR
699 CLD ;AN000; SAR
700 REP MOVSB ;AN000; SAR
701
702
703
704 OR MY_FLAG, FINDFILE_FLAG ;AN000;deals with files
705 OR MY_FLAG, FIND_FIRST_FLAG ;AN000;find first
706
707 MOV NOT_FOUND_FLAG, 0 ;AN000; SAR
708 ; SAR
709 NEXT_PASS: ;AN000; SAR
710 ; SAR
711 MOV SI, TABLE_OFFSET ;AN000; SAR
712 MOV DOS_FILE_PTR,SI ;AN000; SAR
713 MOV FILE_NUM,1 ;AN000; SAR
714
715 CALL SET_MY_DTA ;AN000;set DTA to FILE_DTA
716 ; $DO
717 $$DO1: ;AN000;
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
721 ; $LEAVE NZ ; SAR
722 JNZ $$EN1 ;AN000;
723
724 .IF < SOURCE_IN EQ NO > AND ;AN000;
725 .IF < DEST EQ 3 > ;AN000;
726 CALL GET_SOURCE ;AN000;
727 .ENDIF ;AN000;
728
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
732 .ELSE ;AN000; SAR
733 MOV NOT_FOUND_FLAG, 1 ;AN000; SAR
734 .ENDIF ;AN000; SAR
735 ; $ENDDO ; SAR
736 JMP SHORT $$DO1 ;AN000;
737 $$EN1: ;AN000;
738 CLC ;AN000; SAR
739
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?
742 ; $IF NZ,LONG
743 ;
744 ; AND MY_FLAG, RESET_FINDFILE ;now, deals with directory
745 ; OR MY_FLAG, FIND_FIRST_FLAG ;find first
746 ; $DO
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
751 ; LEA DI, S_DRV_PATH
752 ; LEA SI, [BP].DTA_FILENAME
753 ; CMP S_PATH, 0 ;root directory?
754 ; $IF E
755 ; MOV AL, 0FFh ;then '\' is already provided. Just concat.
756 ; $ELSE
757 ; MOV AL, PATH_DELIM ;put delimiter
758 ; $ENDIF
759 ; CALL CONCAT_ASCIIZ ;make new path
760 ; test option_flag, slash_p ;prompt mode?
761 ; $IF NZ
762 ; call p_concat_display_path
763 ; $ENDIF
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
771 ; $ENDDO
772 ;
773 ; CMP S_DEPTH, 0 ;starting directory? then exit
774 ; $IF NE ;else
775 ; DEC S_DEPTH ;dec depth
776 ; TEST OPTION_FLAG, SLASH_E ;copy subdirectories even if empty?
777 ; $IF Z
778 ; CALL DEL_EMPTY ;then check the old_buffer_ptr and
779 ; ;if it is a directory, then restore
780 ; ;buffer_ptr to old.
781 ; $ENDIF
782 ; LEA DI, S_DRV_PATH
783 ; CALL LAST_DIR_OUT ;change environments
784 ; test option_flag, slash_p ;prompt mode?
785 ; $IF NZ
786 ; call p_cut_display_path
787 ; $ENDIF
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
791 ; CALL CHANGE_S_DIR
792 ; SUB BP, type FIND_DTA
793 ; $ENDIF
794 ;;;;;;; $ENDIF ;walk the tree
795 RET ;AN000;
796 TREE_COPY ENDP;AN000;
797
798
799 GET_SOURCE PROC NEAR;AN000;
800
801 CALL SWITCH_DTAS;AN000;
802
803 .REPEAT ;AN000;
804
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;
810 ;
811 GET_FUNCTION FK_ENT ;AN000;
812
813 .IF < SOURCE_PANEL eq SUB_REM_DOS_A > ;AN000;
814 LEA DI, S_DOS_SEL_360 ;AN000;
815 .ELSE ;AN000;
816 LEA DI, S_DOS_SHEL_DISK ;AN000;
817 .ENDIF ;AN000;
818 MOV CX, E_FILE_ATTR ;AN000;
819 CALL FIND_FILE_ROUTINE ;AN000;
820 .LEAVE < nc > ;AN000;
821 ;
822 HANDLE_ERROR ERR_DOS_DISK, E_RETURN ;AN000;
823 ;
824 .UNTIL ;AN000;
825
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;
830
831 MOV SOURCE_IN,YES ;AN000;
832
833 CALL SWITCH_DTAS ;AN000;
834
835 RET ;AN000;
836 GET_SOURCE ENDP ;AN000;
837
838 GET_DEST PROC NEAR ;AN000;
839
840
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;
846 ;
847 GET_FUNCTION FK_ENT ;AN000;
848 ;
849
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;
854
855 MOV SOURCE_IN,NO ;AN000;
856 ; SUB DOS_FILE_PTR,12
857 ; DEC FILE_NUM
858
859 RET ;AN000;
860 GET_DEST ENDP ;AN000;
861 ;
862 ;******************************************************************************
863 ; Subroutine: LOAD_DOS_FILENAME - Load the next filename into S_FILE.
864 ; INPUT:
865 ; SI - Points to the start of the filename
866 ;
867 ; OUTPUT:
868 ; The S_FILE field in the data segment is updated.
869 ;Registers Affected:
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.
872 ;
873 ;******************************************************************************
874 LOAD_DOS_FILENAME PROC NEAR;AN000;
875
876 PUSH DI ;AN000;
877 PUSH ES ;AN000;
878
879 OR MY_FLAG, FIND_FIRST_FLAG ;AN000; Find first in the directory
880
881 MOV SI,DOS_FILE_PTR ;AN000;
882
883 LDF_SEE_IF_DONE: ;AN000;
884 ;
885 ; See if we are finished this pass of the files
886 ;
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
893 CLD ;AN000;
894 REP MOVSB ;AN000;
895 INC FILE_NUM ;AN000;
896 .ENDIF ;AN000;
897
898 MOV DOS_FILE_PTR,SI ;AN000; Save the pointer to the files
899 POP ES ;AN000;
900 POP DI ;AN000;
901 RET ;AN000;
902
903 LOAD_DOS_FILENAME ENDP ;AN000;
904 ;
905 READ_INTO_BUFFER PROC NEAR ;AN000;
906 ;Read *** a *** file into buffer
907
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?
912 ; $IF NZ ;yes.
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"
920 ;
921 ; AND ACTION_FLAG, RESET_READING ;reset it
922 ;;;;;;; $ENDIF
923
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;
929
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
933
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;
940
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:
944 .ENDIF ;AN111;JW
945
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
950 RIB_SMALL: ;AN000;
951 CALL SMALL_FILE;AN000;
952 JC RIB_ERROR ;AN000;
953 JMP RIB_EXIT ;AN000;
954 RIB_BIG: ;AN000;
955 MOV BX, S_HANDLE ;AN005;
956 CALL CLOSE_A_FILE ;AN005;ONLY OPENED TO GET BUFFER SIZE
957 CALL BIG_FILE ;AN000;
958 JNC RIB_EXIT ;AN000;
959 RIB_ERROR: ;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
964 ;and find next file
965 RIB_EXIT: ;AN000;
966 TEST MY_FLAG, SINGLE_COPY_FLAG ;AN000;single copy?
967 ; $IF NZ
968 JZ $$IF4 ;AN000;
969 CALL WRITE_FROM_BUFFER ;AN000;then write a file
970 ; $ENDIF
971 $$IF4: ;AN000;
972 RET ;AN000;
973 READ_INTO_BUFFER ENDP ;AN000;
974 ;
975
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.
980
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?
985 SMF_CONT: ;AN000;
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
996
997 SMF_EOF: ;AN000;
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;
1006 SMF_ERROR: ;AN000;
1007 ;
1008 SMF_EXIT: ;AN000;
1009 RET ;AN000;
1010 SMALL_FILE ENDP ;AN000;
1011 ;
1012
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
1016
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
1023 ;else small buffer
1024 MOV CX, MAX_CX ;AN000;CX = max_buffer_size * 16 - 32
1025 BIF_SM: ;AN000;
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.
1036 BIF_BIG: ;AN000;
1037 MOV CX, 0FFD0h ;AN000;max # of data bytes this program supports
1038 BIF_BIG1: ;AN000;
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
1043 BIF_BIG2: ;AN000;
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
1055 BIF_BIG3: ;AN000;
1056 CALL WRITE_FROM_BUFFER;AN000;
1057 JC BIF_ERROR ;AN000;
1058 JMP BIF_BIG2 ;AN000;flush buffer and compare again.
1059 BIF_END: ;AN000;
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;
1064 BIF_ERROR: ;AN000;
1065 ;what happened?
1066 BIF_EXIT: ;AN000;
1067 RET ;AN000;
1068 BIG_FILE ENDP ;AN000;
1069 ;
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.
1085 ;
1086 PUSH ES ;AN000;save ES
1087 PUSH AX ;AN000;
1088
1089 MH_AGAIN: ;AN000;
1090 MOV AX,BUFFER_PTR ;AN000;buffer_ptr is a segment
1091 MOV ES, AX ;AN000;now, ES is a header seg.
1092 ;
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
1099 MH_START: ;AN000;
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) ?
1114 ; $IF B
1115 JNB $$IF6 ;AN000;
1116 MOV BUFFER_LEFT, 0 ;AN000;indicate buffer_full
1117 ; $ENDIF
1118 $$IF6: ;AN000;
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; ':'
1126 MOV CX, 13 ;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
1130 JMP MH_EXIT ;AN000;
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;
1147 MH_BIG: ;AN000;
1148 MOV ES:CONTINUE_INFO, 2 ;AN000;
1149 MH_A_FILE: ;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;
1161 MOV CX, 13 ;AN000;
1162 MOV SI, OFFSET FILE_DTA.DTA_FILENAME;AN000;
1163 MOV DI, OFFSET ES:FILENAME_FOUND;AN000;
1164 REP MOVSB ;AN000;
1165
1166 ; Get Extended Attribute list of the opened file and save in attribute buff.
1167
1168 ; old method
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
1173 ;
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
1178 ;
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
1188
1189 ; JC MH_ERROR ;AN000; jump if error
1190
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
1202 JMP MH_EXIT ;AN000;
1203 MH_ERROR: ;AN000;
1204 OR COPY_STATUS, OPEN_ERROR_FLAG ;AN000;
1205 CALL EXTENDED_ERROR_HANDLER ;AN000;
1206 MH_EXIT: ;AN000;
1207 POP AX ;AN000;
1208 POP ES ;AN000;
1209 RET ;AN000;
1210 MAKE_HEADER ENDP ;AN000;
1211 ;
1212
1213 OPEN_A_FILE PROC NEAR ;AN000;
1214
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
1227
1228 JC OF_ERROR;AN000;
1229 MOV S_HANDLE, AX ;AN000;save filehandle
1230 INC OPEN_FILE_COUNT ;AN005;UPDATE THE OPEN FILE COUNTER
1231
1232
1233 JMP OF_EXIT ;AN000; exit
1234
1235 OF_ERROR: ;AN000;
1236 OR COPY_STATUS, OPEN_ERROR_FLAG;AN000;
1237 CALL EXTENDED_ERROR_HANDLER;AN000;
1238 OF_EXIT: ;AN000;
1239 RET ;AN000;
1240 OPEN_A_FILE ENDP;AN000;
1241 ;
1242
1243
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;
1248 ; $IF E,AND
1249 JNE $$IF8 ;AN000;
1250 CMP LOW_FILE_SIZE, 0FFD0h;AN000;
1251 ; $IF BE
1252 JNBE $$IF8 ;AN000;
1253 AND FILE_FLAG, RESET_FILE_BIGGER ;AN000;filesize <= 0FFD0h
1254 ; $ELSE
1255 JMP SHORT $$EN8 ;AN000;
1256 $$IF8: ;AN000;
1257 OR FILE_FLAG, FILE_BIGGER_FLAG ;AN000;
1258 ; $ENDIF
1259 $$EN8: ;AN000;
1260 RET ;AN000;
1261 CMP_FILE_FFD0h ENDP ;AN000;
1262 ;
1263
1264 CALC_FILE_SIZE PROC NEAR ;AN000;
1265 ;subtract the bytes read (ACT_BYTES) from the filesize in HIGH_FILE_SIZE,
1266 ;LOW_FILE_SIZE.
1267 MOV AX, ACT_BYTES ;AN000;
1268 SUB LOW_FILE_SIZE, AX ;AN000;
1269 SBB HIGH_FILE_SIZE, 0 ;AN000;
1270 RET ;AN000;
1271 CALC_FILE_SIZE ENDP ;AN000;
1272 ;
1273
1274 READ_A_FILE PROC NEAR ;AN000;
1275 ;read a file.
1276 ;if after reading, AX < CX or AX = 0 the set EOF_FLAG.
1277 ;INPUT:CX - # of bytes to read
1278 ; BUFFER_PTR
1279 ; S_HANDLE
1280 ;OUTPUT: ACT_BYTES
1281
1282 ; .IF < SOURCE_IN EQ NO > AND
1283 ; .IF < DEST EQ 3 >
1284 ; CALL GET_SOURCE
1285 ; .ENDIF
1286
1287 PUSH DS ;AN000;save program data seg
1288 MOV AH, Read;AN000;
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
1294 INT 21H ;AN000;
1295 POP DS ;AN000;restore program data area
1296 JC RF_ERROR ;AN000;read error?
1297 CMP AX, CX ;AN000;
1298 JE RF_OK ;AN000;
1299 OR FILE_FLAG, EOF_FLAG ;AN000;EOF reached. AX = 0 or AX < CX
1300 RF_OK: ;AN000;
1301 CLC ;AN000;clear carry caused from CMP
1302 MOV ACT_BYTES, AX ;AN000;save actual bytes read
1303 JMP RF_EXIT ;AN000;
1304 RF_ERROR: ;AN000;
1305 OR COPY_STATUS, READ_ERROR_FLAG;AN000;
1306 CALL EXTENDED_ERROR_HANDLER;AN000;
1307 RF_EXIT: ;AN000;
1308 RET ;AN000;
1309 READ_A_FILE ENDP ;AN000;
1310 ;
1311
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;
1316 ; $IF NZ ;yes
1317 JZ $$IF11 ;AN000;
1318 MOV AH, Find_First;AN000;
1319 ; $ELSE
1320 JMP SHORT $$EN11 ;AN000;
1321 $$IF11: ;AN000;
1322 MOV AH, Find_Next;AN000;
1323 ; $ENDIF
1324 $$EN11: ;AN000;
1325 AND MY_FLAG, RESET_FIND_FIRST ;AN000;reset FIND_FIRST_FLAG
1326 INT 21H ;AN000;
1327 RET ;AN000;
1328 FIND_IT ENDP ;AN000;
1329 ;
1330 FIND_FILE PROC NEAR ;AN000;
1331 ;find a file
1332 ;set NO_MORE_FILE if carry.
1333 ; $SEARCH
1334
1335 ; PUSH DS
1336 ; MOV DX,DATA
1337 ; MOV DS,DX
1338 ; .IF < SOURCE_IN EQ NO > AND
1339 ; .IF < DEST EQ 3 >
1340 ; CALL GET_SOURCE
1341 ; .ENDIF
1342 ; POP DS
1343
1344 $$DO14: ;AN000;
1345 TEST MY_FLAG, FIND_FIRST_FLAG ;AN000;find first ?
1346 ; $IF NZ
1347 JZ $$IF15 ;AN000;
1348 MOV DX, OFFSET S_FILE ;AN000;
1349 MOV CX, File_Search_Attr ;AN000;normal = 0
1350 ; $ELSE
1351 JMP SHORT $$EN15 ;AN000;
1352 $$IF15: ;AN000;
1353 MOV DX, OFFSET FILE_DTA ;AN000;
1354 ; $ENDIF
1355 $$EN15: ;AN000;
1356 CALL FIND_IT ;AN000;
1357 ; $EXITIF C
1358 JNC $$IF14 ;AN000;
1359 OR MY_FLAG, NO_MORE_FILE ;AN000;no more file in this directory
1360 ; $ORELSE
1361 JMP SHORT $$SR14 ;AN000;
1362 $$IF14: ;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
1368 JZ $$DO14 ;AN000;
1369 AND MY_FLAG, RESET_NO_MORE;AN000;
1370 ; $ENDSRCH
1371 $$SR14: ;AN000;
1372 RET ;AN000;
1373 FIND_FILE ENDP ;AN000;
1374 ;
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?
1381 ; $IF NZ
1382 JZ $$IF22 ;AN000;
1383 MOV DX, OFFSET FILE_DTA;AN000;
1384 ; $ELSE
1385 JMP SHORT $$EN22 ;AN000;
1386 $$IF22: ;AN000;
1387 MOV DX, BP ;AN000;
1388 ; $ENDIF
1389 $$EN22: ;AN000;
1390 MOV AH, Set_DTA ;AN000;
1391 INT 21H ;AN000;
1392 POP DX ;AN000;
1393 RET ;AN000;
1394 SET_MY_DTA ENDP ;AN000;
1395 ;
1396 ;
1397 SAVE_DTA PROC NEAR ;AN000;
1398 ; Save old DTA address
1399 PUSH ES ;AN000;
1400 PUSH BX ;AN000;
1401 MOV AH, Get_DTA ;AN000;
1402 INT 21H ;AN000;
1403 MOV OLD_DTA_SEG,ES ;AN000;
1404 MOV OLD_DTA_OFF,BX ;AN000;
1405 POP BX ;AN000;
1406 POP ES ;AN000;
1407 RET ;AN000;
1408 SAVE_DTA ENDP ;AN000;
1409 ;
1410 ;
1411 SWITCH_DTAS PROC NEAR ;AN000;
1412 ; SWITCH DTA ADDRESSES
1413 PUSH DS ;AN000;
1414 PUSH DX ;AN000;
1415 PUSH OLD_DTA_SEG ;AN000;
1416 PUSH OLD_DTA_OFF ;AN000;
1417 CALL SAVE_DTA ;AN000;
1418 POP DX ;AN000;
1419 POP DS ;AN000;
1420 MOV AH, Set_DTA ;AN000;
1421 INT 21H ;AN000;
1422 POP DX ;AN000;
1423 POP DS ;AN000;
1424 SWITCH_DTAS ENDP ;AN000;
1425 ;
1426 ;
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
1435
1436 CMP T_DRV[2], 0 ;AN000;LAST_DIR_OUT took '\' out?
1437 ; $IF E
1438 JNE $$IF25 ;AN000;
1439 MOV T_DRV[2], '\' ;AN000;then put it back for root dir
1440 MOV T_DRV[3], 0 ;AN000;
1441 ; $ENDIF
1442 $$IF25: ;AN000;
1443
1444 MOV DX, OFFSET T_DRV_PATH ;AN000;
1445 MOV AH, CHDIR ;AN000;
1446 INT 21H ;AN000;
1447
1448 POP DS ;AN000;restore caller's DS value
1449 RET ;AN000;
1450 CHANGE_T_DIR ENDP;AN000;
1451 ;
1452
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.
1457 PUSH DX ;AN000;
1458 PUSH AX ;AN000;
1459
1460 CMP OPEN_FILE_COUNT,NUL ;AN005;ARE THERE ANY OPEN FILES
1461 ; $IF Z ;AN005;NO, THEN GO AHEAD AND OPEN
1462 JNZ $$IF28A ;AN000;
1463 CALL OPEN_A_FILE ;AN005;OPEN A FILE USING FILE_DTA
1464
1465 ; Get extended Attribute list size.
1466
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
1474 MOV AX,CX ;AN005;
1475 MOV CL,PARAGRAPH ;AN005; GET PARAGRAPHS (DIV BY 16)
1476 SHR AX,CL ;AN005;
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
1484 ; $ENDIF
1485 $$IF28A: ;AN000;
1486
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
1490 ; $IF AE
1491 JNAE $$IF27 ;AN000;
1492 MOV AX, BUFFER_LEFT ;AN000;buffer_left in para
1493 SUB AX,PARA_OF_HDR ;AC005;consider header size in advance
1494 MOV CX, 16 ;AN000;
1495 MUL CX ;AN000;* 16. result in DX;AX
1496 CMP HIGH_FILE_SIZE, DX;AN000;
1497 ; $IF A ;if high_filesize > dx
1498 JNA $$IF28 ;AN000;
1499 OR FILE_FLAG, FILE_BIGGER_FLAG;AN000;
1500 ; $ELSE
1501 JMP SHORT $$EN28;AN000;
1502 $$IF28: ;AN000;
1503 ; $IF E
1504 JNE $$IF30 ;AN000;
1505 CMP LOW_FILE_SIZE, AX;AN000;
1506 ; $IF A
1507 JNA $$IF31 ;AN000;
1508 OR FILE_FLAG, FILE_BIGGER_FLAG;AN000;
1509 ; $ENDIF
1510 $$IF31: ;AN000;
1511 ; $ENDIF
1512 $$IF30: ;AN000;
1513 ; $ENDIF
1514 $$EN28: ;AN000;
1515 ; $ELSE
1516 JMP SHORT $$EN27 ;AN000;
1517 $$IF27: ;AN000;
1518 OR FILE_FLAG, FILE_BIGGER_FLAG ;AN000;buffer_left < 2
1519 ; $ENDIF
1520 $$EN27: ;AN000;
1521 POP AX ;AN000;
1522 POP DX ;AN000;
1523 RET ;AN000;
1524 CMP_FILESIZE_TO_BUFFER_LEFT ENDP ;AN000;
1525 ;
1526
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
1544 ; OLD_BUFFER_PTR
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.
1552
1553 PUSH CX ;AN000;
1554 MOV CX, BUFFER_PTR ;AN000;
1555 MOV OLD_BUFFER_PTR, CX ;AN000;set old_buffer_ptr
1556 MOV CL, 4 ;AN000;
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
1561
1562 ; $IF NC,AND ;not exceed 16 bit.
1563 JC $$IF37 ;AN000;
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
1567 JNA $$IF37 ;AN000;
1568 MOV BUFFER_LEFT, AX;AN000;
1569 ; $ELSE
1570 JMP SHORT $$EN37 ;AN000;
1571 $$IF37: ;AN000;
1572 MOV BUFFER_LEFT, 0 ;AN000;indication of buffer full
1573 ; $ENDIF
1574 $$EN37: ;AN000;
1575 POP CX ;AN000;
1576 RET ;AN000;
1577 SET_BUFFER_PTR ENDP ;AN000;
1578 ;
1579
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
1588 ;(End of contine).
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.
1591 ;
1592 PUSH DS ;AN000;
1593 PUSH ES ;AN000;save ds, es
1594
1595 PUSH DS ;AN000;
1596 POP ES ;AN000;set ES to program data seg
1597
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;
1602 MOV DS, AX ;AN000;
1603 PUSH CS ;AN000;
1604 POP AX ;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;
1608
1609 PUSH DS ;AN000;
1610 MOV DX,DATA ;AN000;
1611 MOV DS,DX ;AN000;
1612 .IF < DEST eq 3 > ;AN000;
1613 CALL GET_DEST ;AN000;
1614 .ENDIF ;AN000;
1615 POP DS ;AN000;
1616
1617 WFB_CD: ;AN000;
1618 CALL CHANGE_T_DIR ;AN000;
1619 JC WFB_ERROR_BRIDGE ;AN000;error?
1620 WFB_CHATT: ;AN000;
1621 CMP DS:ATTR_FOUND, Is_subdirectory ;AN000;a subdirectory? = 10H
1622 JNE WFB_FILE ;AN000;no. a file
1623
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
1626 ;;;;;;;
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?
1633 ; $IF E
1634 ; MOV AL, 0FFh ;then don't need to put delim since it is already there
1635 ; $ELSE
1636 ; MOV AL, Path_delim ;path_delim '\'
1637 ; $ENDIF
1638 ; CALL CONCAT_ASCIIZ
1639 ; call concat_display_path ;modify the path for display
1640 ; INC ES:T_DEPTH
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.
1648 WFB_NEXT: ;AN000;
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.
1661
1662
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?
1669 WFB_WRITE: ;AN000;
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
1674 JE $$LL40 ;AN000;
1675 CMP DS:CONTINUE_INFO, 3;AN000;
1676 ; $IF E
1677 JNE $$IF40 ;AN000;
1678 $$LL40: ;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
1689 ; $ENDIF
1690 $$IF40: ;AN000;
1691 MOV AX, DS ;AN000;
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
1696 WFB_ERROR: ;AN000;
1697 jmp main_exit ;AN000;meaningful when MKDIR failed because
1698 ;of there already exist same named file,
1699 ;or disk_full case.
1700 WFB_EXIT_A: ;AN000;
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).
1704 WFB_EXIT_B: ;AN000;
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
1709 WFB_EXIT: ;AN000;
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
1715 POP ES ;AN000;
1716 POP DS ;AN000;
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
1720 ;;;; $ENDIF
1721 RET ;AN000;
1722 WRITE_FROM_BUFFER ENDP ;AN000;
1723 ;
1724 INC_FILE_COUNT PROC NEAR;AN000;
1725 ;increase the file count by one.
1726 ;increase file_cnt_low, file_cnt_high.
1727 ;input: DS - buffer
1728 ; ES - data seg
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
1732 IFC_EXIT: ;AN000;
1733 RET ;AN000;
1734 INC_FILE_COUNT ENDP ;AN000;
1735 ;
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
1739 ;close the handle.
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
1745 ;header part.
1746 ;Also, this routine show copy messages just before a file creation using
1747 ;FILENAME_FOUND.
1748 ;ES - data seg
1749 ;DS - buffer seg
1750
1751 PUSH DS ;AN000;
1752 PUSH ES ;AN000;
1753
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
1760 ;;;;; $IF Z ; SAR
1761 ;;;;; CALL SHOW_COPY_MESSAGE ; SAR he source path, file
1762 ;;;;; $ENDIF ; SAR
1763 ;
1764 ; CMP ES:T_FILENAME, 0
1765 ; $IF NE ;non_global target filename entered.
1766 ; TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG
1767 ; $IF NZ
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
1772 ; ;abort
1773 ; $ENDIF
1774 ;
1775 ; CALL SWITCH_DS_ES ;now ds - data, es - buffer
1776 ; MOV CX, 13
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
1781 ;
1782 ; $ELSE
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
1787 ; $IF NZ
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
1791 ; $ENDIF
1792 ; $ELSE
1793 ; TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG ;*.* CASE
1794 ; $IF NZ
1795 ; PUSH ES
1796 ; POP DS ;ds - data seg
1797 ;
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
1805 ; JMP MAIN_EXIT
1806 ; $ENDIF
1807 ; $ENDIF
1808 ;;;;;; $ENDIF
1809
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 ;-------------------------------------------------------------------------
1814
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
1819
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
1827
1828 JC CAF_ERROR ;AN000;
1829 MOV ES:T_HANDLE, AX ;AN000;save handle
1830
1831 ;;;;; CALL CHK_T_RES_DEVICE ; SAR check target handle is a reserved dev
1832
1833 OR ES:FILE_FLAG, CREATED_FLAG ;AN000;set created_flag
1834 JMP CAF_EXIT ;AN000;
1835 CAF_ERROR: ;AN000;
1836 PUSH DS ;AN000;
1837 PUSH ES ;AN000;
1838 POP DS ;AN000;
1839 OR COPY_STATUS, CREATE_ERROR_FLAG;AN000;
1840 CALL EXTENDED_ERROR_HANDLER ;AN000;
1841 POP DS ;AN000;
1842 CAF_EXIT: ;AN000;
1843 POP ES ;AN000;
1844 POP DS ;AN000;
1845 RET ;AN000;
1846 CREATE_A_FILE ENDP ;AN000;
1847 ;
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
1853 ;; ES - data seg
1854 ;
1855 ; CLD
1856 ; MOV AL, 0
1857 ; PUSH DI ;save DI
1858 ; CALL STRING_LENGTH ;CX get the length of string
1859 ; MOV BX, CX ;now, BX got the length of the target filename entered.
1860 ; PUSH BX ;save BX
1861 ; PUSH ES ;save ES
1862 ;
1863 ; PUSH DS
1864 ; POP ES ;now ES set to DS
1865 ; PUSH SI
1866 ; POP DI ;now DI points to the source filename found.
1867 ;
1868 ; MOV AL, 0
1869 ; CALL STRING_LENGTH ;CX got the length of the string
1870 ;
1871 ; POP ES ;restore ES
1872 ; POP BX ;restore BX
1873 ; POP DI ;restore DI
1874 ; ;;
1875 ; CMP BX, CX ;COMPARE LENGTH
1876 ; JNE CF_EXIT ;IF THEY ARE DIFFERENT, EXIT
1877 ;
1878 ; REPE CMPSB ;compare SI, DI until not equal,
1879 ; CMP CX, 0 ;finish at cx = 0?
1880 ; JE CF_SAME
1881 ; JMP SHORT CF_EXIT
1882 ;CF_SAME:
1883 ; PUSH ES
1884 ; POP DS ;ds = data seg
1885 ;
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
1893 ; JMP MAIN_EXIT
1894 ;CF_EXIT:
1895 ; RET
1896 ;COMP_FILENAME ENDP
1897 ;;
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
1906 INT 21h ;AN000;
1907 JC WAF_ERROR ;AN000;write error
1908 CMP AX, DS:CX_BYTES;AN000;
1909 JNE WAF_DISKFULL;AN000;
1910 JMP WAF_EXIT ;AN000;
1911 WAF_ERROR: ;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
1919
1920 ; Set message parameters
1921 ; Target disk full, critical error
1922
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
1936 WAF_EXIT:;AN000;
1937 RET ;AN000;
1938 WRITE_A_FILE ENDP;AN000;
1939 ;
1940 SET_FILE_DATE_TIME PROC NEAR;AN000;
1941 ;input: BX - target file handle
1942 ;
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;
1947 INT 21h ;AN000;
1948 RET ;AN000;
1949 SET_FILE_DATE_TIME ENDP;AN000;
1950 ;
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?
1954 ; $IF A ;AN005;
1955 JNA $$IF42A ;AN000;
1956 DEC OPEN_FILE_COUNT ;AN005;IF SO, REDUCE THE COUNT BY 1.
1957 ; $ENDIF ;AN005;
1958 $$IF42A: ;AN000;
1959 MOV AH, Close ;AN000; = 3Eh
1960 INT 21H ;AN000;
1961 RET ;AN000;
1962 CLOSE_A_FILE ENDP ;AN000;
1963 ;
1964 DELETE_A_FILE PROC NEAR;AN000;
1965 ;input: DS:DX - points to ASCIIZ string
1966
1967 MOV AH, 41h ;AN000; = 41h
1968 INT 21H ;AN000;
1969 RET ;AN000;
1970 DELETE_A_FILE ENDP;AN000;
1971 ;
1972 ;
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.
1976 ;INPUT: DS - buffer
1977 ; ES - data seg
1978 ; PUSH AX
1979 ; PUSH BX
1980 ; PUSH CX
1981 ; PUSH DX
1982 ; MOV AH, 36h ;GET DISK FREE SPACE
1983 ; MOV DL, ES:T_DRV_NUMBER ;OF TARGET
1984 ; INT 21h
1985 ; CMP BX, 0 ;NO MORE CLUSTER?
1986 ; JE CDF_FULL
1987 ; CLC
1988 ; JMP SHORT CDF_EXIT
1989 ;CDF_FULL:
1990 ; OR ES:COPY_STATUS, DISK_FULL_FLAG ;SET DISK FULL FLAG
1991 ; STC ;SET CARRY
1992 ;CDF_EXIT:
1993 ; POP DX
1994 ; POP CX
1995 ; POP BX
1996 ; POP AX
1997 ; RET
1998 ;
1999 ;CHK_DISK_FULL ENDP
2000 ;;
2001 ;;subttl string_length
2002 ;page
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
2007 ; charater found.
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.!!!
2016 ;
2017 ; DATA INPUT
2018 ; REGISTERS: AL - ASCII CHARACTER
2019 ; ES:DI - POINTER TO THE STRING.
2020 ; DATA OUTPUT
2021 ; REGISTERS: AX,DX,SI etc - PRESERVED.
2022 ; BX - DISTROYED
2023 ; CX - STRING LENGTH UNTIL FOUND THE GIVEN CHARACTER.
2024 ; DI - POINTS TO THE NEXT CHARACTER AFTER THE STRING.
2025 ; DIRECTION FLAG - CLEARED
2026 ; ZERO FLAG - RESET
2027 ;******************************************************************************
2028 ;
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
2038 ; POP DI
2039 ; RET
2040 ;STRING_LENGTH ENDP
2041 ;
2042 ;subttl concat_asciiz
2043 ;page
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
2048 ; ES:DI.
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.
2059 ;DATA INPUT
2060 ; REGISTERS: AL - DELIMETER OR 0FFh
2061 ; ES:DI - POINTER TO THE DESTINATION STRING.
2062 ; DS:SI - POINTER TO THE SOURCE TO BE CONCATENATED.
2063 ;DATA OUTPUT
2064 ; REGISTERS: AL, DX - preserved
2065 ; DI - preserved. POINTER TO THE RESULT STRING
2066 ; SI - DISTROYED
2067 ; CX - RESULT ASCIIZ STRING LENGTH INCLUDE 0
2068 ; DIRECTION FLAG - CLEARED
2069 ;******************************************************************************
2070 ;CONCAT_ASCIIZ PROC NEAR
2071 ;
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.
2080 ; CMP AL, 0FFh
2081 ;; $IF NE ;IF THE USER WANTS TO PUT DIMIMETER,
2082 ; JE $$IF42
2083 ; STOSB ; REPLACE 0 WITH IT.
2084 ;; $ELSE
2085 ; JMP SHORT $$EN42
2086 ;$$IF42:
2087 ; DEC CX ;ELSE DECREASE LENGTH BY 1
2088 ;; $ENDIF
2089 ;$$EN42:
2090 ;; $DO
2091 ;$$DO45:
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
2097 ; JNE $$DO45
2098 ; POP DI
2099 ; RET
2100 ;CONCAT_ASCIIZ ENDP
2101 ;;
2102 ;
2103 ;subttl last_dir_out
2104 ;page
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
2115 ; *** points to 0.)
2116 ;DATA INPUT
2117 ; REGISTERS: DI - points to an ASCIIZ path string.
2118 ; ES - assumed default segment for DI
2119 ;DATA OUTPUT
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 ;******************************************************************************
2126 ;
2127 ;LAST_DIR_OUT PROC NEAR
2128 ;PUBLIC LAST_DIR_OUT
2129 ;
2130 ; PUSH DI
2131 ; PUSH SI ;save current DI, SI
2132 ; CLD ;clear direction
2133 ; MOV SI, 0FFFFh ;used as a not_found flag if unchanged.
2134 ;; $DO
2135 ;$$DO47:
2136 ; MOV AL, 0
2137 ; SCASB
2138 ;; $LEAVE Z ;if [DI] = 0, then end of string. Ends this loop.
2139 ; JZ $$EN47
2140 ; DEC DI ;if [DI] <> 0, then go back and scan char again
2141 ; MOV AL, "\" ;to see it was a back slash.
2142 ; SCASB
2143 ;; $IF Z ;if it was, then save the addr to SI.
2144 ; JNZ $$IF49
2145 ; PUSH DI
2146 ; POP SI
2147 ;
2148 ; DEC SI
2149 ;; $ENDIF ;else do loop again.
2150 ;$$IF49:
2151 ;; $ENDDO
2152 ; JMP SHORT $$DO47
2153 ;$$EN47:
2154 ; CLC ;clear carry flag.
2155 ; CMP SI, 0FFFFh ;Had SI been changed?
2156 ;; $IF E
2157 ; JNE $$IF52
2158 ; STC ;No, set the carry. Not found.
2159 ;; $ELSE
2160 ; JMP SHORT $$EN52
2161 ;$$IF52:
2162 ; MOV BYTE PTR ES:[SI], 0 ;Yes, replace "\" with 0. Seg override to get default DI seg.
2163 ; MOV AX, SI
2164 ; INC AX ;let AX have the last dir offset value.
2165 ; CLC ;clear carry
2166 ;; $ENDIF
2167 ;$$EN52:
2168 ; POP SI ;restore original value
2169 ; POP DI ;original string offset
2170 ; RET
2171 ;LAST_DIR_OUT ENDP
2172 ;;
2173 ;
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
2177 ;goes.)
2178 ;input: DL - drive # (0 = A, 1 = B ...)
2179
2180 MOV AH, Select_Disk ;AN000; = 0Eh
2181 INT 21H ;AN000;
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
2184 RET ;AN000;
2185 SET_DEFAULT_DRV ENDP ;AN000;
2186 ;
2187 ORG_S_DEF PROC NEAR ;AN000;
2188 ;restore the original source directory.
2189 PUSH ES ;AN000;
2190 PUSH DS ;AN000;
2191
2192 PUSH DS ;AN000;
2193 POP ES ;AN000;DS=ES=data seg
2194
2195 TEST SYS_FLAG, DEFAULT_S_DIR_FLAG ;AN000;source default direcotry saved?
2196 ; $IF NZ
2197 JZ $$IF55 ;AN000;
2198 MOV DX, OFFSET SAV_S_DRV ;AN000;saved source drive letter & directory
2199 MOV AH, 3Bh ;AN000;
2200 INT 21h ;AN000;restore source
2201 AND SYS_FLAG, RESET_DEFAULT_S_DIR ;AN000;reset the flag
2202 ; $ENDIF
2203 $$IF55: ;AN000;
2204
2205 POP DS ;AN000;
2206 POP ES ;AN000;
2207
2208 RET ;AN000;
2209 ORG_S_DEF ENDP ;AN000;
2210 ;
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.
2215
2216 TEST SYS_FLAG, TURN_VERIFY_OFF_FLAG ;AN000;turn off verify?
2217 ; $IF NZ ;yes
2218 JZ $$IF57 ;AN000;
2219 MOV AX, 2E00h ;AN000;turn it off
2220 INT 21H ;AN000;
2221 ; $ENDIF
2222 $$IF57: ;AN000;
2223
2224 TEST SYS_FLAG, DEFAULT_DRV_SET_FLAG ;AN000;default drive has been changed?
2225 ; $IF NZ ;yes
2226 JZ $$IF59 ;AN000;
2227 MOV DL, SAV_DEFAULT_DRV ;AN000;
2228 DEC DL ;AN000;
2229 CALL SET_DEFAULT_DRV ;AN000;restore default drv.
2230
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.
2233
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
2237
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;
2242 ; $ENDIF
2243 $$IF59: ;AN000;
2244
2245 TEST SYS_FLAG, DEFAULT_S_DIR_FLAG ;AN000;source default direcotry saved?
2246 ; $IF NZ
2247 JZ $$IF61 ;AN000;
2248 MOV DX, OFFSET SAV_S_DRV ;AN000;saved source drive letter & directory
2249 MOV AH, 3Bh ;AN000;
2250 INT 21h ;AN000;restore source. This is for the case of ERROR exit.
2251 ; $ENDIF
2252 $$IF61: ;AN000;
2253
2254 TEST SYS_FLAG, DEFAULT_T_DIR_FLAG ;AN000;target default directory saved?
2255 ; $IF NZ ;then assume both source, target default saved
2256 JZ $$IF63 ;AN000;
2257 MOV DX, OFFSET SAV_T_DRV ;AN000;saved target drive letter & directory
2258 MOV AH, 3Bh ;AN000;
2259 INT 21h ;AN000;restore target
2260 ; $ENDIF
2261 $$IF63: ;AN000;
2262
2263 RET ;AN000;
2264 ORG_S_T_DEF ENDP ;AN000;
2265 ;
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.
2272 ;If access denied
2273 ; too many open files
2274 ; sharing violation
2275 ; lock violation
2276 ; general failure
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.
2282 ;INPUT:
2283 ; DS - DATA SEG
2284 ;OUTPUT:
2285 ; ALL THE REG PRESERVED
2286
2287 GOTO_MAIN_EXIT: ;AN000;
2288 JMP MAIN_EXIT ;AN000;restore conditions
2289 ;and exit
2290 QUICK_EXIT: ;AN000;
2291 JMP JUST_EXIT ;AN000;immediate exit
2292
2293 RET ;AN000;
2294
2295 EXTENDED_ERROR_HANDLER ENDP;AN000;
2296 ;
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
2301 ; ES - data seg
2302
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
2311 RET ;AN000;
2312 CLOSE_DELETE_FILE ENDP;AN000;
2313 ;
2314 ;
2315
2316 SWITCH_DS_ES PROC NEAR;AN000;
2317 ; switch DS, ES
2318 PUSH DS ;AN000;
2319 PUSH ES ;AN000;
2320 POP DS ;AN000;
2321 POP ES ;AN000;
2322 RET ;AN000;
2323 SWITCH_DS_ES ENDP ;AN000;
2324 ;
2325 ;
2326 INIT PROC NEAR ;AN000;
2327
2328 CALL GET_CUR_DRV ;AN000;save current default drv
2329 MOV DL, SAV_DEFAULT_DRV;AN000;
2330 LEA SI, SAV_DEFAULT_DIR;AN000;
2331
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
2336
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
2342 .ELSE ;AN000; SAR
2343 AND SYS_FLAG, NOT DEFAULT_T_DIR_FLAG ;AN000; SAR
2344 .ENDIF ;AN000; SAR
2345
2346
2347 MOV DL, S_DRV_NUMBER;AN000;
2348 DEC DL ;AN000;
2349 CALL SET_DEFAULT_DRV ;AN000;set source as a default drv
2350 CLC ;AN000;
2351 RET ;AN000;
2352 INIT ENDP ;AN000;
2353 ;
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.
2357
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
2364 ; $ENDIF
2365
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;
2369
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;
2374
2375 .IF < DEST eq 3 > ;AN111;JW
2376 MOV AL,0 ;AN111;JW
2377 .ELSE ;AN111;JW
2378 MOV AL, DEST ;AN000; SAR target drive letter
2379 .ENDIF ;AN111;JW
2380 INC AL ;AN000; SAR
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
2386 ;;;;; $ENDIF
2387 MOV T_DRV_NUMBER, AL ;AN000;save target drv #
2388
2389 ;;;;; CMP S_DRV_NUMBER, AL ;s_drv_number = t_drv_number?
2390 ; ; $IF E
2391 ; ; OR SYS_FLAG, ONE_DISK_COPY_FLAG ;same logical drv copy
2392 ;;;;; $ENDIF
2393
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;
2399 RET ;AN000;
2400 GET_DRIVES ENDP ;AN000;
2401 ;
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
2406 INT 21h ;AN000;
2407 INC AL ;AN000;(1 = A, 2 = B ..)
2408 MOV SAV_DEFAULT_DRV, AL ;AN000;save it
2409 RET ;AN000;
2410 GET_CUR_DRV ENDP ;AN000;
2411 ;
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
2416
2417 MOV AH, Get_Current_Directory;AN000;
2418 INT 21H ;AN000;
2419 RET ;AN000;
2420 GET_CUR_DIR ENDP ;AN000;
2421 ;
2422 TOP_OF_MEM PROC NEAR ;AN000;
2423 ;set Top_of_memory
2424 PUSH ES ;AN000;
2425 MOV BX, PSP_SEG ;AN000;
2426 MOV ES, BX ;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
2430 POP ES ;AN000;
2431 RET ;AN000;
2432 TOP_OF_MEM ENDP ;AN000;
2433
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
2440 ;;;; POP DX ; SAR
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?
2448 JAE IB_CONT ;AN000;
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
2459 IB_CONT: ;AN000;
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 ?
2462 ; $IF B
2463 JNB $$IF65 ;AN000;
2464 MOV CX, 16;AN000;
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
2468 ; $ELSE
2469 JMP SHORT $$EN65 ;AN000;
2470 $$IF65: ;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
2474 $$EN65: ;AN000;
2475 ; which has been decided by BIG_FILE )
2476 RET ;AN000;
2477 INIT_BUFFER ENDP ;AN000;
2478
2479
2480
2481 SELECT ENDS ;AN000;
2482
2483 END ;AN000;
2484