home *** CD-ROM | disk | FTP | other *** search
- name RESTORE
- title RESTORE.Com 5.1 for MS DOS 2.0 - 4.01
- ; copyright (c) 1989 Canadian Mind Products
- ; - condensed Alps Allegro
- ; - condensed Toshiba P351
- page 60, 132
-
- Comment |
-
- Written in Microsoft Assembler MASM 5.0
- Last Updated: 1989 May 24 by Roedy Green
-
- Authors: Dan Wright and Roedy Green
-
- Canadian Mind Products
- #162 - 1020 Mainland Street
- Vancouver, BC
- Canada V6B 2T4
- (604) 684-6529
-
-
- Purpose
- =======
-
- To restore files backed up under any version of DOS to any other
- version of DOS, Roedy Green wrote the original the Canadian Mind
- Products RESTORE program. Versions 1 through 4.4 handled the
- Backup format used by MS and PC DOS 2.0 through 3.2. CMP
- Restore replaces the RESTORE program that comes with MS DOS or
- IBM PC DOS.
-
- Dan Wright wrote version 5 of Restore to further extend the
- capability to include the new DOS backup format introduced with
- DOS 3.3. With this version, either of the formats will be
- recognized automatically and restored to any version of DOS from
- 2.0 to 4.01
-
- CMP Restore corrects the 20 bugs in the official Restore. This
- will allow people to restore from backups where before they
- could not.
-
- ShareWare
- =========
-
- Though versions 1.0 through 4.4 were in the public domain as
- Charware, starting with Version 5, Restore is ShareWare. To use
- it legally you must send $15 US or $20 Canadian to Canadian Mind
- Products at the address above. When you do so, we will send you
- a diskette. This way you can be sure your version of Restore
- has not been tampered with to include viruses.
-
- Syntax
- ======
-
- RESTORE A: [C:][path\][filespec] [/S] [/P] [/Q]
-
- Where:
-
- A: = source floppy drive, i.e. A:, B:, etc.
- C: = target hard drive, i.e. C:, D:, etc.
- path = the directory where the files will be placed.
- filespec = the specification of files to be restored.
- May include wildcard chars. * and ?.
- /S = restore subdirectories also.
- /P = prompt before restoring each file.
- /Q = quiet, suppress advertising banner.
-
-
- Samples of Use
- ==============
-
- RESTORE A: C:\MySub\MyFile.Ext
- RESTORE A: C:\MySub\*.*/P/S/Q
- RESTORE A: C:\MySub/P
- RESTORE A: C:\MySub
- RESTORE A: \MySub -- presumes default drive
- RESTORE A: C:*.* -- presumes default directory
- RESTORE A: C:\*.BAT/S -- restores all BAT files in all
- subdirectories.
-
-
- It is not as elaborate as the commercial versions, only the /S
- and /P switches are supported.
-
- Version History:
-
- Version 1:
- - not released to the public
- - restored all files ignoring the filespec
-
- Version 2: released Christmas 1986
- - /P /Q /S options.
- - allowed you to select files to be restored.
-
- Version 3: released to Charware subscribers Jan 28 1987
- - fixed bug when restore had to handle 10 or more diskettes.
-
- Version 4: released to BIX March 5 1987
- - fixed bug RESTORE A: C:*.*/S in root directory did not work.
- was treated as RESTORE A: C:\\*.*/S instead of C:\*.*/S
- - fixed bug. Originally all disks in the backup set were
- checked to makes sure they were created on the same day
- to make sure they were part of the same set. Because backups
- can be created with the /A option, it is possible each diskette
- in the set is part of a different set. Thus the check was
- removed.
-
- Version 4.1: released May 8 1987
- - version number now prints as part of the "Screwed up" message
- - RESTORE.TXT documention separated from ASM source code
- - change mailing address
-
- Version 4.2: released July 9 1987
- - beeps when wants disk
-
- Version 4.3: released April 9 1988
- - change of mailing address in banner
-
- Version 4.4: released December 24 1988
- - change of mailing address in banner
-
- Version 5.0: released March 4 1989
- - very limited distribution
- - added support for DOS 3.3 through DOS 4.01
- - this was a major rewrite that took many times
- longer to write than the original. For this
- reason Version 5.0 is not Charware, but rather
- ShareWare.
-
- Version 5.1: released May 24 1989
- - more friendly, simpler, less technical error messages.
- - fancier prompts.
- - tidier source code.
- - bug fixed that restored a file fragment when you inserted
- the wrong diskette.
- - avoid reprompting entire prompt when input bad.
- - Abort Retry Ignore keystrokes no longer echo.
- - / options no longer picky about leading space.
- - warning message if source not A: or B:
- - warning message if target not C: through G:
- - fancier banner, with pause
-
- About the Authors
- =================
-
- Dan Wright is a legally blind programmer seeking work in the
- field either on a contract or full-time basis. He is presenting
- this version of RESTORE as an example of his work. This code
- was written, and parts of it adapted from Canadian Mind Products
- RESTORE version 4.4, using a speech synthesizer and a minimal
- amount of visual feedback from the screen (not enough to read).
- Information on DOS function calls, MASM, etc. was obtained using
- Norton Guides and various reference books which I have had read
- onto cassette tape. The integrity of restored files was
- verified by redirecting the output of DIR commands and the
- output of a CRC utility to files before and after restoring and
- then comparing these using the DOS COMP and FC commands.
-
- Roedy Green is the author of the public domain Abundance
- Database compiler and the 32 bit BBL Forth compiler as well as a
- suite of many small public domain utilities. He also writes for
- The Computer Paper - a Vancouver free advertising paper.
-
- WARNING TO HACKERS
- ==================
-
- If you modify this program to look for existing files on hard
- disk before restoring, beware the APPEND command. It will fool
- you into thinking the file already exists when in fact it does
- not, there is just a similarly named file in one of the APPEND
- directories. The guys who wrote FastBack got fooled by this
- one.
-
- Notes an How BACKUP Works
- =========================
-
- BACKUP uses standard DOS-formatted disks (they must be
- pre-formatted, but not necessarily cleared of all files).
- Backup first erases all files in the root directory of the
- diskette -- even read only files. (I have heard unconfirmed
- reports that some versions of BACKUP have a bug and you have to
- erase the hidden, system and read-only files yourself with QDOS
- II first.) If they were not erased, they could confuse RESTORE
- no end!
-
- In addition BACKUP will not work if there are subdirectories on
- the floppies. Instead of erasing them, it terminates with a
- mysterious stack overflow error.
-
- Notes on DOS 3.2 Backup Format
- ==============================
-
- MS DOS and PC DOS 2.0 through 3.2 use this format. There is a
- slight difference between MS and PC DOS formats -- the \ verses
- the / in file names.
-
- Each backup disk begins with a file called BackupId.@@@,
- followed by one or more of the backed-up files. If two
- identically named files are backed up onto the same physical
- disk, the subsequent file extensions are listed as @01, @02,
- etc. A file may be split across more than one disk, and in this
- case the name of all subsequent chunks are the same as the first
- chunk's (regardless of whether a non-unique name which had to be
- modified on its initial disk is unique on a later disk).
-
- Backup puts a file called \BackupId.@@@ on each diskette. In it
- you can find the diskette sequence number and the date the
- backup was done. There is also an indicator flag to tell if
- this is the last diskette of the set.
-
- offset len
- 01..01 1 -1 if this is last diskette in the set.
- 02..03 2 Sequence no. of diskette. In 8 bit BCD
- 04..05 2 Year e.g. 1986 backup done.
- True 1900 form, not 1980 relative.
- 06..06 1 Day backup done, binary 1..31.
- 07..07 1 Month backup done, binary 1..12.
-
-
- Each file is backed up with a 128 byte preamble. In the
- preamble is the fully qualified name of the file. To make life
- interesting, the subdirectories may be separated with either /
- or \. This goofiness is 90% of the reason my version of RESTORE
- had to be written.
-
- If files are too big to fit on diskette, there are two other
- numbers of interest in the preamble:
-
- 1. The sequence number of this chunk 1, 2 etc
-
- 2. A flag that indicates this is the last chunk.
-
- offset len
- 01 .. 01 1 -1 if last fragment of file, 0 otherwise.
- 02 .. 03 2 Sequence no. of this fragment,
- 04 .. 05 2 Padding.
- 06 .. 69 64 Fully qualified filename on hard disk without drive specifier
- padded on right with nuls. May have / instead \.
- 70 .. 83 14 Padding.
- 84 .. 84 1 Length of fully qualified name including one trailing nul.
- 85 ..129 45 Padding.
-
- Note that the preamble does NOT contain any of the following
- information that you might expect.
-
- 1. attribute byte of the file.
- 2. date and time file was last modified.
- 3. Length in bytes of the chunk.
- 4. offset in file where this chunk fits.
- 5. Length in bytes of the entire file.
- 6. Count of how many chunks there are supposed to be in total.
- 7. Checksum
-
- To glean this information we must examine the date, time and
- attribute bytes of the backup file itself. To figure out where
- the chunk fits in, we simply have to start at the beginning and
- keep track. Thus it is impossible to restore a file unless you
- start at chunk 1 and work sequentially through. Bad news if one
- of the chunks is unreadable.
-
- Following the preamble is the file itself -- absolutely raw --
- no compression of any kind.
-
- When restoring a file we have four versions of the filename:
-
- Fname -- from the floppy directory - part of the floppy file name
- missing A:\ e.g. XXXXXX.XXX
-
- InName -- the actual name of the floppy file
- e.g. A:\XXXXXXXX.XXX
-
- HardName -- the name in the floppy premamble
- missing C:
- e.g. \SUB1\SUB2\XXXXXXXX.XXX
-
- OutName -- the actual name of the file on the hard disk
- e.g. C:\SUB1\SUB2\XXXXXXXX.XXX
-
-
- Notes on DOS 3.3 Backup Format
- ==============================
-
- MS and PC DOS 3.3 through 4.01 (and probably beyond) use the
- following format:
-
- On each backup diskette are two files
- CONTROL.001 - list of files, subdirectories, sizes
-
- BACKUP.001 - actual data files, not compressed, crammed together
- end to end in a single file.
-
- volume id is BACKUP 001
-
- The diskettes are numbered in three places:
- CONTROL.002
- BACKUP.002
- volume id is BACKUP 002
-
- The Control file
- ****************
- The control file begins with a 139 byte header:
-
- offset len
- 00..00 1 8B=139 length of record
- 01..08 8 the word BACKUP signature padded on the right with spaces
- 09..0A 2 diskette number, simple binary starting at 1
- Does not use the goofy BCD format of DOS 3.2
- 0B..89 127 zeroes
- 8A..8A 1 -1 if last diskette in set, 0 otherwise
-
- Then come two types of entries: subdirectories and files. There
- is no special marker for the end of file other than the file size
- recorded in the directory.
-
- Subdirectory entry
- ******************
-
- A 70-byte subdirectory entry looks like this.
- 00..00 1 HEX 46=70 length of record
- 01..3F 63 subdirectory name, no drive, no lead \, with embedded \,
- no trail \, zero padded on right
- 40..41 2 count of files following on this diskette in this subdir
- 42..45 4 offset in the Control file of the next subdirectory
- record. If there is no further subdirectory on this
- diskette, contains -1. The offset is absolute, not
- relative to this record. This way if we are restoring
- only some subdirectories, we can rapidly get on with
- the next one.
-
- The date, time and attribute byte of the subdirectory are NOT
- recorded. Restore builds directories as needed with the current
- date and time with a default attribute byte.
-
- File entry
- **********
-
- Following a subdirectory entry are multiple file entries for the
- files being backed up in that subdirectory.
-
- A 34 byte file entry looks like this:
-
- 00..00 1 HEX 22=34 length of record
- 01..0C 12 file name with embedded dot, padded with 0s.
- no embedded spaces.
- 0D..0D 1 02 = another fragment to come on another diskette after this one.
- 03 = this is the last (possibly only) fragment.
- 0E..11 4 total size of file in bytes
- 12..13 2 Sequence number of this fragment starting at 1.
- 14..17 4 offset into Backup.nnn of start of file.
- 18..1B 4 size of fragment of file in bytes on this diskette
- 1C..1C 1 attribute byte of file in directory format.
- usually the archive bit is on.
- 1D..1D 1 zeroes
- 1E..1F 2 time in DOS directory format
- 20..21 2 date in DOS directory format
-
-
- Note on register conventions
- ============================
-
- Whenever we call a subroutine, the subroutine is permitted to
- trash all registers. Thus the caller must save any registers
- needed. The way the code is written, this is very rarely
- necessary as all high level routines do nothing but calls and
- comparisons of memory resident variables.
-
- Setting the carry flag is often used by a subroutine to inform
- its caller that trouble has occurred.
-
- Callers often cheat when calling very simple routines. They
- fail to save necessary registers knowing that the called routine
- will not mess them up. If you make changes to low level
- routines beware!
-
- | ; End of comment.
-
- ;==============================================================
-
-
- ifdef DEBUG ;; Declared on MASM command line.
- if1
- %out Debug version.
- endif
- .xlist
- .lall
- include restore.dbg ;; PUBLIC declarations for SYMDEB.
- else
- if1
- %out Production version.
- endif
- endif
-
- ;==============================================================
- ; E Q U A T E S
-
- CR equ 0DH
- LF equ 0AH
- BEL equ 7
-
- STD_IN equ 0 ; Handle for standard input device.
- STD_OUT equ 1 ; Handle for standard output device.
- STD_ERR equ 2 ; Handle for standard error device.
-
- STACK_SIZE equ 256 ; Size of program stack in bytes. Used
- ; to check for sufficient memory.
- BUFF_SIZE equ 512*9*10 ; Size of buffer for disk I/O. Size = 10
- ; tracks for 360K floppy.
- HDR_REC_LEN equ 139 ; Length of header record in
- ; CONTROL.XXX.
- SUBDIR_REC_LEN equ 70 ; Length of subdirectory records
- ; in CONTROL.XXX.
- FILE_REC_LEN equ 34 ; Length of file records in
- ; CONTROL.XXX.
-
-
- ;==============================================================
-
- dbln macro Message, Msg_Lbl
- ;; Define Message as one line of a message terminated by CR/LF. If the
- ;; message label Msg_Lbl is supplied, make sure it has been declared and use it
- ;; to calculate the length of the message after the current line is defined.
- ifnb <Msg_Lbl> ;; If the message label has been supplied
- ifndef Msg_Lbl ;; but not declared, declare it.
- even
- Msg_Lbl label byte
- else
- if $+1 eq Msg_Lbl ;; Ensure start address of message is
- even ;; the same on both passes.
- endif
- endif
- endif
-
- ifnb <Message> ;; Define text of message.
- db "&Message"
- endif
- db CR, LF ;; Terminate line.
-
- ifnb <Msg_Lbl> ;; Calculate current length of message.
- Msg_Lbl&_Len = $ - Msg_Lbl
- endif
- endm ;; End of macro dbln.
-
- ;==============================================================
-
- dbpl macro Prompt, Prompt_Lbl
- ;; Define partial line Prompt as a prompt with no terminating CR/LF. If
- ;; the prompt label Prompt_Lbl is supplied, make sure it has been declared and
- ;; use it to calculate the length of the prompt after the current line is
- ;; defined.
- ifnb <Prompt_Lbl> ;; If the label is supplied but not
- ifndef Prompt_Lbl ;; declared, declare it.
- even
- Prompt_Lbl label byte
- else
- if $+1 eq Prompt_Lbl ;; Ensure start address of prompt is
- even ;; the same for both passes.
- endif
- endif
- endif
-
- ifnb <Prompt> ;; Define text of prompt.
- db "&Prompt"
- endif
- ifnb <Prompt_Lbl> ;; Calculate current length of prompt
- ;; if label supplied.
- Prompt_Lbl&_Len = $ - Prompt_Lbl
- endif
- endm ;; End of macro dbpl
-
- ;==============================================================
- dbs Macro Len ;; Len spaces
- DB &Len DUP (" ") ;; define string of spaces
- endm
- ;==============================================================
-
- dbpr macro Prompt, Prompt_Lbl
- ;; Define Prompt as a prompt with no terminating CR/LF and one bell char. If
- ;; the prompt label Prompt_Lbl is supplied, make sure it has been declared and
- ;; use it to calculate the length of the prompt after the current line is
- ;; defined.
- ifnb <Prompt_Lbl> ;; If the label is supplied but not
- ifndef Prompt_Lbl ;; declared, declare it.
- even
- Prompt_Lbl label byte
- else
- if $+1 eq Prompt_Lbl ;; Ensure start address of prompt is
- even ;; the same for both passes.
- endif
- endif
- endif
-
- ifnb <Prompt> ;; Define text of prompt.
- db "&Prompt"
- endif
- db BEL ;; Add one bell char.
- ifnb <Prompt_Lbl> ;; Calculate current length of prompt
- ;; if label supplied.
- Prompt_Lbl&_Len = $ - Prompt_Lbl
- endif
- endm ;; End of macro dbpr.
-
- ;==============================================================
-
- dbzs macro Z_String, Z_String_Lbl
- ;; Define the contents of Z_String as an ASCII Z string with the label
- ;; Z_String_Lbl.
- ifnb <Z_String_Lbl> ;; Declare label for Z string.
- even
- Z_String_Lbl label byte
- else ;; Force error if no label.
- .err
- endif
-
- ifnb <Z_String> ;; Define Z string.
- db "&Z_String"
- endif
- db 0 ;; Add terminating nul.
- endm ;; End of macro dbzs.
-
- ;==============================================================
-
- Patch_Num macro Hex_Num, Num_Start, Num_Width
- local PN_More
- ;; Display the 16 bit quantity Hex_Num as a decimal integer right justified
- ;; in a field Num_Width characters wide with the right most digit at offset
- ;; Num_Start. It generally patches the number into an error message or prompt.
- ifdif <Hex_Num>,<ax>
- mov ax, Hex_Num ;; Value to display in ASCII decimal.
- endif
- lea di, Num_Start ;; Location of right most digit.
- mov cx, Num_Width ;; Width of field in which to place
- ;; Number.
- Call Patch_Sub
- endm ;; End of macro Patch_Num.
-
- ;==============================================================
-
- Say_Err_Msg macro Err_Msg
- ;; Print Err_Msg&_Len characters beginning at the address of Err_Msg
- ;; to the standard error device.
- lea dx, Err_Msg
- mov cx, Err_Msg&_Len
- mov bx, STD_ERR
- mov ah, 40H
- int 21H ;; 40H=Write.
- endm ;; End of macro Say_Err_Msg.
-
- ;==============================================================
-
- Say_Msg macro Msg
- ;; Print Msg&_Len characters beginning at the address of Msg
- ;; to the standard output device. These can be redirected via Pipes.
- lea dx, Msg
- mov cx, Msg&_Len
- mov bx, STD_OUT
- mov ah, 40H
- int 21H ;; 40H=Write.
- endm ;; End of macro Say_Msg.
-
- ;==============================================================
-
- D_Count = 0 ;; Initialize count of dangerous files.
- Test_Count = 0 ;; Used to detect incorrect parameters.
-
- ;==============================================================
-
- Def_D_File macro D_Filename, DC
- ;; Define an ASCII Z string containing the filename passed in D_File and
- ;; calculate its length.
- ;; Keep track of the number of filenames processed in D_Count and use this
- ;; value to generate unique symbols for the address and length of each
- ;; Z string.
- ;; Only the first parameter, the filename of a file which could be dangerous
- ;; to restore to the root directory, should be supplied when calling this
- ;; macro.
- ifb <DC> ;; This part executes on initial call.
- D_Count = D_Count + 1 ;; Increment count of dangerous files.
-
- ;; Now the macro calls itself passing the value of D_Count as a second
- ;; parameter. This enables the generation of symbol names made unique by
- ;; including the current value of D_Count for the address of the string and
- ;; its length.
- Def_D_File <D_Filename>, %D_Count
-
- else ;; This part executes when the macro
- ;; calls itself.
- if Test_Count eq D_Count ;; This occurs if the macro was
- .err ;; erroneously called with a second
- exitm ;; parameter supplied.
- endif
-
- even
- D_File&DC label byte ;; Generate label for string address.
- ifnb <D_Filename> ;; The first parameter can't be blank.
- db "&D_Filename" ;; Define string.
- db 0 ;; Add terminating nul.
- else
- .err
- endif
-
- D_File&DC&_Len = $ - D_File&DC ;; Generate symbol containing string
- ;; length.
-
- ;; Test_Count follows the value of D_Count to prohibit the execution of the
- ;; second part of the macro before the first part which would happen if a
- ;; second parameter was included in the initial call. D_Count is incremented
- ;; on execution of the first part allowing subsequent error free execution of
- ;; the second part. Incrementing Test_Count at the end of the second part
- ;; ensures that the first part must be executed before the second part may
- ;; be executed again.
- Test_Count = Test_Count + 1
- endif
- endm ;; End of macro Def_D_File.
-
- ;==============================================================
-
- Blank_Extension macro Ext_Start
- ;; Patch a filename extension with wild card characters. Ext_Start points
- ;; at the beginning of the file extension.
- lea di, Ext_Start
- mov cx, 3 ;; Length of a file extension.
- mov al, '?'
- cld
- rep stosb
- endm ;; End of macro Blank_Extension.
-
- ;==============================================================
-
- DTA equ 80H ;; Offset in PSP of default DTA.
-
- ; Template for DTa after call to dir. search functions 4EH and 4FH.
- Dir_Search struc
- DS_Reserved db 21 dup (?) ; Reserved for DOS.
- DS_Attr db ? ; File attribute in dir. format.
- DS_Time dw ? ; File time in dir. format.
- DS_Date dw ? ; File date in dir. format.
- DS_Size dd ? ; file size.
- DS_Name db 13 dup (?) ; Filename as ASCII Z string.
- Dir_Search ends
-
-
- ;==============================================================
-
- ; BACKUPID.@@@ file format in DOS 3.2
- Bkp_ID_Rec struc ; 7 bytes of interesting info in
- ; \BACKUPID.@@@.
- BI_Last db ? ; -1 if this is last diskette in the set.
- BI_Seq dw ? ; Sequence no. of diskette. This is
- ; originally in 8 bit BCD form but
- ; will be converted to true binary.
- BI_YYYY dw ? ; Year e.g. 1986 backup done.
- ; True 1900 form, not 1980 relative.
- BI_DD db ? ; Day backup done, binary 1..31.
- BI_MM db ? ; Month backup done, binary 1..12.
- Bkp_ID_Rec ends
-
-
- ;==============================================================
-
- ; 128 byte header at the beginning of every DOS 3.2 backup file.
- Preamble struc
- P_Last db ? ; -1 if last fragment of file, 0
- ; otherwise.
- P_Frag_Seq dw ? ; Sequence no. of this fragment,
- ; 1 = first, 2 = second, etc.
- dw ? ; Padding.
- P_Hard_Name db 64 dup (?) ; Fully qualified filename on hard disk
- ; without drive specifier, padded on
- ; right with nuls. May have / instead
- ; of \.
- db 14 dup (?) ; Padding.
- P_Hard_Len db ? ; Length of fully qualified name
- ; including one trailing nul.
- db 45 dup (?) ; Padding.
- Preamble ends
-
- ;==============================================================
-
- ; Header Record in DOS 3.3 Control.XXX file
- Hdr_Rec struc
- Hdr_Len db ? ; Length of header record.
- Hdr_Sig db "BACKUP " ; Backup signature.
- Hdr_Seq dw ? ; Disk number in set, 1=first, 2=
- ; second, etc.
- db 127 dup (?) ; Padding.
- HDR_Last db ? ; -1 if last diskette in set, 0 otherwise
- Hdr_Rec ends
-
- ;==============================================================
-
- ; Subdir Record in DOS 3.3 Control.XXX file
- Subdir_Rec struc
- Subdir_Len db ? ; Length of subdirectory record.
- Subdir_Name db 61 dup (?) ; Subdirectory name. No leading or
- ; trailing backslash, 0 padded on right.
- dw ? ; Padding.
- Subdir_Count dw ? ; Count of files following in this
- ; subdirectory on this diskette.
- Subdir_Next dd ? ; Absolute offset in CONTROL.XXX of next
- ; subdirectory record. (-1 if no more
- ; subdir entries)
- Subdir_Rec ends
-
- ;==============================================================
-
- ; File Record in DOS 3.3 Control.XXX file
- File_Rec struc
- File_Len db ? ; Length of file record.
- File_Name db 12 dup (?) ; file name with embedded dot, zero
- ; padded, no embedded spaces.
- File_More db ? ; 2=another fragment on next diskette, 3=
- ; last and possibly only fragment.
- File_Size dd ? ; Size of file in bytes.
- File_Frag_Seq dw ? ; Sequence number of this fragment,
- ; 1=first, 2=second, etc.
- File_Frag_Start dd ? ; Offset in BACKUP.XXX where frag.
- ; starts.
- File_Frag_Size dd ? ; Size of fragment of file on this
- ; diskette.
- File_Attr db ? ; File attributes in dir. format.
- db ? ; Padding.
- File_Time dw ? ; File time in dir. format.
- File_Date dw ? ; File date in dir. format.
- File_Rec ends
-
- ;==============================================================
-
- Code segment para
- assume cs : Code, ds : Code, ss : Code, es : Code
- org 100H
-
- Start: jmp Restore_Main
-
- ;==============================================================
- ; V A R I A B L E S
- even
- Rest_Count dw 0 ; count of files restored.
- Want_Seq dw 1 ; Expected disk sequence no.
- Want_Frag_Seq dw 1 ; Expected fragment sequence no.
- Want_Size dd 0 ; Expected file size for multiple
- ; fragment files and for verifying copy.
- Bkp_Seq dw 1 ; Current Diskette sequence no.
-
- Ctl_Hndl dw -1 ; CONTROL.XXX or BACKUPID.@@@ handle.
- Bkp_Hndl dw -1 ; Handle for backup data files.
- Out_Hndl dw -1 ; Output file handle.
-
- Format_Flags db 0 ; Used to indicate format of backup
- ; diskettes being restored.
- DOS32 equ 1 ; Bit 0 set = DOS 3.2 format.
- DOS33 equ 2 ; Bit 1 set = DOS 3.3 format.
-
- Flags db 01H ; If bit set:
- LastFrag EQU 01H ; bit 0 = last file fragment.
- LastDisk EQU 02H ; bit 1 = last diskette in set.
- NewDisk EQU 04H ; Bit 2 = New Diskette.
- WrongOk EQU 08H ; Bit 3 = user OKed diskette out of seq.
- SkipFile EQU 10H ; Bit 4 = Do not restore file.
- FileMatched EQU 20H ; Bit 5 = filename was matched.
- WildCards EQU 40H ; Bit 6 = wild card chars. in command
- ; line pathspec.
- WasPeriod EQU 80H ; Bit 7 = period processed in command
- ; line pathspec.
-
- Cmd_Flags db 0 ; Flags for command line switches.
- Prompt_Needed equ 01h ; Bit 0 set = prompted restore (/p)
- RestoreSubs equ 04h ; Bit 2 set = restore subdirectories (/s)
- Quietly equ 08h ; Bit 3 set = quiet, suppress banner (/Q)
-
- Bkp_Sig db "BACKUP " ; Valid backup control file signature.
- Bkp_Sig_Len equ $ - Bkp_Sig
-
- ; Define filenames used in both backup schemes. X's will be patched later with
- ; correct values.
- dbzs <X:\BACKUPID.@@@> Bkp_ID_Name ; Backup ID filename (DOS 3.2).
- dbzs <X:\*.*> All_Pattern ; Pattern to find files on floppy in
- ; DOS 3.2 backup scheme.
- dbzs <X:\CONTROL.XXX> Ctl_Filename ; Backup control file name (DOS 3.3).
- dbzs <X:\BACKUP.XXX> Bkp_Filename ; Backup data filename (DOS 3.3).
- ; allocate two more bytes so Bkp_Filename can be used to hold floppy filenames
- ; in DOS 3.2 scheme.
- db 2 dup (0)
-
- Rest_Name label byte ; Pathspec to be restored.
- Rest_Drive db 'X:' ; Hard disk drive letter. Patched later.
- db '\' ; Not supplied in subdir records.
- Rest_Path db 75 dup (0)
- Filespec_Ptr dw 0 ; Ptr. to start of filespec in Rest_Path.
- Rest_Name_Len dw 0 ; Length of drive and pathspec to be
- ; restored not including terminating nul.
-
- Match_File db "XXXXXXXX.XXX" ; Name of file proposed to be restored.
- ; Extracted from Rest_Path in format
- ; comparable with command line pattern.
-
- CL_Subdir_Pattern db 64 dup (0) ; Subdirectory pattern from command line
- ; of files to be restored.
- Subdir_Pat_Len dw 0 ; Length of subdirectory pattern
- ; including trailing backslash, but
- ; excluding leading backslash and
- ; trailing nul.
-
- CL_File_Pattern db "????????.???" ; Pattern from command line of files
- ; to be restored.
-
- ; Files dangerous to restore to the root directory.
- Def_D_File <IBMBIO.COM1>
- Def_D_File <IBMDOS.COM>
- Def_D_File <IO.SYS>
- Def_D_File <MSDOS.SYS>
- Def_D_File <COMMAND.COM>
-
- ; Define prompts and informational and error messages.
- Wrong_Ver db "RESTORE requires DOS 2.0 or later.$"
- ; Not done with dbline since handles may not work.
-
- Part_X_Msg db " part "
- Part_X db "XXX"
- Part_X_Msg_Len equ $ - Part_X_Msg
-
- dbpl <X> ,echochar
- DB 08 ; allow keystroke echo
- dbpl ,echochar
- ; Embedded tabs are ok, since DOS will expand them again.
- dbln < ╔════════════════════════════════════════════════════╗>, Banner
- dbln < ║ RESTORE 5.1 for PC DOS and MS DOS 2.0 through 4.01 ║>
- dbln < ╚════════════════════════════════════════════════════╝>
- dbln
- dbln < (c) Copyright 1989 Dan Wright and Roedy Green>
- dbln
- dbln < ░▒▓█ Canadian Mind Products █▓▒░>
- dbln
- dbln < #162 - 1020 Mainland>
- dbln < Vancouver, BC Canada V6B 2T4>
- dbln < (604) 684-6529>
- dbln
- dbln <Restore 5.1 is direct replacement for MS DOS Restore that works across DOS>
- dbln <versions. You can restore files backed up under any level of PC or MS DOS 2.0>
- dbln <though 4.01 to any other level. Restore fixes the many bugs in the official>
- dbln <Restore. Restore can also be used to distribute files on floppy.>
- dbln
- dbln <To continue legally using this Shareware program, you must send a $US 15 or>
- dbln <$CDN 20 registration fee. In return, we will send you the latest version of>
- dbln <Restore. Registration is the only way to completely protect yourself from>
- dbln <viruses. Restore 5.1 is for non-military use only.>
- dbln ,Banner
-
-
- dbln <┌──────────────────────────────────────────────────┐> ,Help_Msg
- dbln <│ RESTORE A: [C:][\path\][filespec] [/S] [/P] [/Q] │>
- dbln <└──────────────────────────────────────────────────┘>
- dbln <A: = source floppy drive, i.e. A:, B:, etc.>
- dbln <C: = target hard drive, i.e. C:, D:, etc.>
- dbln <path = the directory where the files will be placed.>
- dbln <filespec = the specification of files to be restored.>
- dbln < May include wildcard chars. * and ?.>
- dbln </S = restore subdirectories also.>
- dbln </P = prompt before restoring each file.>
- dbln </Q = quiet, suppress advertising banner.>
- dbln
- dbln <e.g. the command line should look something like this:
- dbln
- dbln < Restore A: C:\MySub\MyFile.Ext>
- dbln < Restore A: C:\M???.Bat/P/S/Q>
- dbln < Restore A: C:\*.*/S>
- dbln < Restore A: C:\MySub\>
- dbln < RESTORE A: C:\MySub\MyFile.> ,Help_Msg
-
- dbln ,Insert
- dbln <┌────────────────────────────────────────┐>
- dbpl <│ Insert backup diskette >
- Insert_Seq db "XXX in drive "
- Insert_Drive db "X: │"
- dbln
- dbln <└────────────────────────────────────────┘>
- dbln ,Insert
-
- dbpr ,Strike_Any
- dbln <Strike the space bar to continue... Hit Ctrl-Break to Abort> ,Strike_Any
-
-
- dbln ,Announce_Bkp_Msg
- dbs 3
- dbpl <You inserted diskette number >
- ABM_Seq db "XXX"
- dbpl < into drive >
- ABM_Drive db "X:"
- dbln
- dbs 3
- dbPl <Backed up on >
- ABM_MM db "XX-"
- ABM_DD db "XX-"
- ABM_YYYY db "XXXX"
- dbln ,Announce_Bkp_Msg
-
- dbpl ,Old_Bkp_Format
- dbs 3
- dbln <Diskettes were backed up with DOS 2.0, 2.1, 3.0, 3.1 or 3.2>
- dbln ,Old_Bkp_Format
-
- dbpl ,New_Bkp_Format
- dbs 3
- dbln <Diskettes were backed up with DOS 3.3 or 4.01.>
- dbln ,New_Bkp_Format
-
- dbln <░▒▓█ Usually the source floppy drive is A: or B: Are you sure?█▓▒░> ,Strange_Source
-
- dbln <░▒▓█ Usually the target hard drive is C: D: ... G: Are you sure?█▓▒░> ,Strange_Target
-
- dbln <░▒▓█ Your request to restore was ambiguous.█▓▒░>, Ambiguous
- dbln <Use forms like:>
- dbln <┌──────────────────────┬───────┐>
- dbln <│ Restore A: C:\Mysub\X\ /S /P │ if X is a subirectory>
- dbln <│ Restore A: C:\Mysub\X. /S /P │ if X is a file>
- dbln <└──────────────────────┴───────┘> , Ambiguous
-
-
- dbln <░▒▓█ Diskette is from another backup set. █▓▒░> ,Wrong_Set
-
- dbln <Not to worry, all is forgiven. Now you can either:> ,AR_Msg
- dbln <A. Abort and give up. Any partly restored file will be corrupted.>
- dbln <R. Retry with the proper diskette.>
- dbpr <Abort or Retry (A/R): > ,AR_Msg
-
- dbln ,Out_Of_Seq
- dbln <░▒▓█ Diskette out of sequence. █▓▒░>
- dbln
- dbln <This is not the diskette you were supposed to insert.> ,Out_Of_Seq
-
- dbln <Not to worry, all is forgiven. Now you can either:> ,ARI_Msg
- dbln <A. Abort and give up. No files will be damaged.>
- dbln <R. Retry with the proper diskette.>
- dbln <I. Ignore the sequence error and attempt to restore from this diskette.>
- dbpr <Abort, Retry, or Ignore (A/R/I): > ,ARI_Msg
-
- dbpl ,Prompt_User1
- dbs 9
- dbpl <Restore? > ,Prompt_User1
-
- dbpl < (Y/N): > ,Prompt_User2
-
- dbln < restored> ,Restored
- ; single file msg
- dbln ,Done_Msg
- dbln
- dbpl <Restore completed with >
- DM_Count db "XXXXX file(s) restored."
- dbln ,Done_Msg
-
- dbpr ,None_Restored
- dbln <WARNING: No files were found to restore.> ,None_Restored
-
- dbln <░▒▓█ Insufficient memory. █▓▒░> ,Insufficient
- dbln <Get rid of large TSR programs to free up RAM.> ,Insufficient
-
- dbln <░▒▓█ Invalid parameters. █▓▒░> ,Bad_Params
-
- dbln <░▒▓█ Invalid path. █▓▒░> ,Bad_Path
-
- dbln <░▒▓█ Invalid file specification. █▓▒░> ,Bad_Filespec
-
- dbln <░▒▓█ Invalid source drive specification. █▓▒░> ,Bad_Source
-
- dbln <░▒▓█ Invalid target drive specification. █▓▒░> ,Bad_Target
-
- dbln <░▒▓█ Target drive must not be same as source. █▓▒░> ,Same
-
- dbln <░▒▓█ Wildcard characters not allowed in path. █▓▒░> ,Bad_Wildcards
-
- dbln <░▒▓█ Unrecognized command line switch. █▓▒░> ,Bad_Switch
-
- dbln <░▒▓█ Input error -- possibly you removed the floppy too soon. █▓▒░> ,In_IO_Err
-
- dbln <░▒▓█ Output error -- possibly the hard disk is full. █▓▒░> ,Out_IO_Err
-
- dbln <░▒▓█ Possibly damaged backup diskette. █▓▒░> ,Floppy_Trouble
-
- dbln <░▒▓█ Hard disk trouble. █▓▒░> ,Hard_Disk_Trouble
-
- dbln <░▒▓█ Too many open files. █▓▒░> ,Too_Many_Open
- dbln <Increase FILES=30 parameter in CONFIG.SYS.> ,Too_Many_Open
-
- dbln <░▒▓█ Mysterious error. Diskette possibly damaged. █▓▒░> ,Unknown
-
- dbln ,CRLF
-
- dbpr ,Beep
-
- dbln , Cant_Restore
- dbln <Unable to restore file: > , Cant_Restore
-
- dbln ,Not_Bkp
- dbpl <░▒▓█ Non-backup diskette in drive >
- NB_Drive db "X: █▓▒░"
- dbln ,Not_Bkp
-
-
- dbln ,Special_Attr
- dbln <░▒▓█ This is a Read-only, Hidden, and/or System file. █▓▒░>
- dbln <Do not restore it unless you are absolutely sure of what>
- dbln <you are doing.> ,Special_Attr
-
- dbln ,Aborted
- dbpl <Restore Aborted with >
- Aborted_Count db "XXXXX"
- dbln < files restored.> ,Aborted
-
- ; Define table of valid filename and pathname chars.
- Valid_Chars db 0,"!",0,"#$%&'()",0,0,0,"-",0,0, "0123456789", 6 dup (0)
- db "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]",0,"_"
- db "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{",0,"}",0,0
-
- ;==============================================================
-
- Patch_Sub PROC Near
- ; DOS 3.2 and 3.3
- ; on entry ax=num di=target addr cx=num width
- ; See Patch_Num macro for more details.
- mov bx, 10
- std
- PN_More:
- xor dx, dx ; Zero out high word.
- div bx
- xchg dx, ax ; Get remainder in al.
- add al, '0' ; Convert to ASCII
- stosb ; and store it in the string.
- mov ax, dx
- or ax, ax ; All done?
- loopnz PN_More ; Drop out if so.
-
- mov al, '0' ; Pad on the left with zeros.
- rep stosb
- cld
- Ret
- Patch_Sub ENDP
-
- ;==============================================================
-
- Parse proc near
- ; DOS 3.2 and 3.3
- ; parse the command line tail for the source drive, target drive,
- ; pathspec pattern, and switches specified.
- ;
- ; Returns:
- ;
- ; CL_Subdir_Pattern contains the pattern against which the dirspecs.
- ; of files to be restored are compared. An empty pattern specifies
- ; the root directory; otherwise, the pattern is an absolute dirspec.
- ; stored with a trailing but no leading backslash.
- ;
- ; Subdir_Pat_Len contains the length of the subdir pattern against
- ; which the dirspecs. of files to be restored are matched. If the
- ; pattern specifies the root directory, this value is 0; otherwise,
- ; it contains the length of the pattern including a trailing but not
- ; a leading backslash.
- ;
- ; CL_File_Pattern contains a 12 byte fixed length file pattern which
- ; files to be restored must match. The pattern contains a period at
- ; the 9th position and the filename and extension are padded on the
- ; right to full length with blanks. Any asterisks are expanded to
- ; their question mark equivalents.
- ;
- ; Cmd_Flags bit 0 set if /P switch specified, clear otherwise .
- ;
- ; Cmd_Flags bit 2 set if /S switch specified, clear otherwise.
- ;
- ; Cmd_Flags bit 3 set if /Q switch specified, clear otherwise.
- ;
- xor ch, ch
- mov cl, ds:80H ; Get length of command line tail.
- jcxz P_Help
- mov di, 81H ; Point at command line tail.
- mov al, ' ' ; Skip leading spaces.
- cld
- repe scasb
- jz P_Help
- jcxz P_Err
- cmp byte ptr [di], ':'
- jnz P_Err
- push cx ; Save no. of remaining chars.
- call Get_Source_Drive
- pop cx
- inc di ; Bypass the colon.
- dec cx
- jnz P_Get_Target
- call Default_Drive
- call Default_Subdir
- ret
-
- P_Help: Say_Err_Msg Banner ; Just plain RESTORE no parms
- Call Strike_Any_Key
- call Abort_With_Help
-
- P_Err: Say_Err_Msg Bad_Params
- call Abort_With_Help
-
- P_Get_Target:
- cmp byte ptr [di], '/' ; Is target supplied?
- jz P_Use_Dflts ; No, use default drive and pathspec.
- mov ah, cl ; Should be at least one space
- dec ah ; between source and target.
- mov al, ' ' ; Skip spaces between source and
- repe scasb ; target specifications.
- jz P_Use_Dflts ; Rest of command line was spaces.
- cmp ah, cl ; At least one space?
- jz P_Err ; No, abort.
-
- jcxz P_Use_Dflt_Drv ; Use default drive for target if
- cmp byte ptr [di], ':' ; if none specified.
- jnz P_Use_Dflt_Drv
- push cx
- call Get_Target_Drive
- pop cx
- inc di ; Point to start of pathspec.
- dec cx
- jnz P_Get_Pathspec
- call Default_Subdir ; Use default subdir for pathspec
- ret ; if none specified.
-
- P_Use_Dflt_Drv:
- push cx
- call Default_Drive
- pop cx
- inc cx ; Back up to start of pathspec.
- dec di
-
- P_Get_Pathspec:
- cmp byte ptr [di], '/' ; Switches could be here.
- jz P_Get_Switches ; They are, skip to switch processing.
- cmp byte ptr [di], ' ' ; If space here, switches must follow.
- jz P_Get_Switches ;
- call Get_Pathspec
- jmp short P_Get_Switches
-
- P_Use_Dflts:
- push cx
- push di
- call Default_Drive
- call Default_Subdir
- pop di
- pop cx
-
- ; If any switches were specified, di points at the first slash.
- P_Get_Switches:
- mov al, '/'
- P_More:
- jcxz P_Done
- repne scasb
- jne P_No_More
- jcxz P_Err
- call Get_Switch
- inc di
- dec cx
- jmp short P_More
-
- P_No_More:
- mov al, ' ' ; Ignore trailing spaces on command line.
- cmp [di-1], al
- jnz P_Err
- jcxz P_Done
- repe scasb
- jnz P_Err
- P_Done:
- ret
- ; actual Parse EndP but contains nested procs.
-
- ;==============================================================
-
- Get_Source_Drive proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; Test the validity of the drive letter pointed to by [di-1]. Patch the
- ; names of the backup control and data files with it if it is valid, abort
- ; otherwise. Used by Parse
- and byte ptr [di-1], 0DFH ; Convert drive to upper case.
- mov bl, [di-1]
- sub bl, 'A'-1 ; 1 = drive A, 2 = drive B, etc.
- xor cx, cx ; Read 0 bytes.
- lea dx, Buffer ; Point at a safe place in case something
- ; is returned.
- mov ax, 4404H ; Function = IOCTL Read from block
- int 21H ; device.
- jnc GSD_Check ; Drive is valid.
- cmp ax, 0FH ; Was drive invalid?
- jz GSD_Err ; Yes, abort
- GSD_Check:
- mov al, [di-1] ; get drive letter
- cmp al,'A' ; usually source is A: or B:
- jb GSD_Warn
- cmp al,'B'
- ja GSD_Warn
-
- GSD_OK:
- mov al, [di-1] ; Patch filenames with drive letter.
- mov Ctl_Filename, al
- mov Bkp_Filename, al
- mov Bkp_ID_Name, al
- mov All_Pattern, al
- mov Insert_Drive, al ; Patch insert message.
- mov ABM_Drive, al
- mov NB_Drive, al
- ret
-
- GSD_Warn:
- Say_Err_Msg Strange_Source ; expect A: or B: as source.
- Call Strike_Any_Key
- jmp GSD_OK
-
- GSD_Err:
- Say_Err_Msg Bad_Source
- call Abort_With_Help
-
- Get_Source_Drive endp
-
- ;==============================================================
-
- Get_Target_Drive proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; Get the target drive specification pointed to by [di-1] and make sure that
- ; it is valid and that it is different from the
- ; source drive. If all is OK, use it to patch the restore name drive
- ; letter. Abort otherwise. Used by Parse.
- ;
- and byte ptr [di-1], 0DFH ; Convert drive to upper case.
- mov bl, [di-1]
- sub bl, 'A'-1 ; 1 = drive A, 2 = drive B, etc.
- xor cx, cx ; Read 0 bytes.
- lea dx, Buffer ; Point at a safe place in case something
- ; is returned.
- mov ax, 4404H ; Function = IOCTL Read from block
- int 21H ; device.
- jnc GTD_Check ; Drive is valid.
- cmp ax, 0FH ; Was drive invalid?
- jz GTD_Err1 ; Yes, abort
- GTD_Check:
- mov al, [di-1]
- cmp al, 'C'
- jb GTD_Warn
- cmp al, 'G'
- ja GTD_Warn
-
- GTD_OK:
- mov al, [di-1] ; Make sure source and target drives
- cmp al, Ctl_Filename ; are different.
- jz GTD_Err2 ; Abort if not.
- mov Rest_Drive, al ; Patch restore name with drive letter.
- ret
-
- GTD_Warn:
- Say_Err_Msg Strange_Target ; expect C: or D: as source.
- Call Strike_Any_Key
- jmp GTD_OK
-
- GTD_Err1: Say_Err_Msg Bad_Target
- call Abort_With_Help
-
- GTD_Err2:
- Say_Err_Msg Same
- call Abort_With_Help
- Get_Target_Drive endp
-
- ;==============================================================
-
- Default_Drive proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; Get the default drive to use as the target drive. Make sure it is
- ; different from the source drive. Use it to patch the
- ; pathspec of files to be restored if its OK, abort otherwise.
- ; Used by Parse.
- mov ah, 19H ; Function = Get Current Disk.
- int 21H
- add al, 'A' ; Convert to ASCII. 0=A, 1=B, etc.
- cmp al, Ctl_Filename ; Make sure target is different from
- ; source.
- jz DD_Same
-
- mov Rest_Drive, al ; Patch restore pathspec with drive.
- ret
-
- DD_Same:
- Say_Err_Msg Same
- call Abort_With_Help
- Default_Drive endp
-
- ;==============================================================
-
- Default_Subdir proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; Begin restore pattern with default subdir
- ; Calculate length of default subdir including trailing backslash but not
- ; including leading backslash or trailing nul and return it in Subdir_Pat_Len.
- ; used by Parse
- mov dl, Rest_Drive ; Get target drive letter and convert
- sub dl, 'A'-1 ; to code (1=A, 2=B, etc.).
- lea si, CL_Subdir_Pattern ; si points to buffer for returned
- ; subdir.
- mov ah, 47H ; Function = Get Current Subdir.
- int 21H
- jc DS_Err
-
- ; Calculate length of subdir name with trailing backslash which we will
- ; add, but without leading backslash or trailing nul. The returned subdir
- ; name is nul terminated without leading or trailing backslash.
- lea di, CL_Subdir_Pattern
- mov cx, size CL_Subdir_Pattern
- mov al, 0
- repne scasb
- sub cx, size CL_Subdir_Pattern-1
- neg cx
- cmp di, offset CL_Subdir_Pattern+1 ; Was default subdir root?
- jz DS_Root ; Yes, don't need trailing backslash.
- mov byte ptr [di-1], '\' ; Add trailing backslash.
- inc cx
- DS_Root:
- mov Subdir_Pat_Len, cx
- ret
-
- DS_Err: Say_Err_Msg Unknown
- call Abort_With_Help
- Default_Subdir endp
-
- ;==============================================================
-
- Get_Pathspec proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; Parse the pathspec entered on the command line inserting the current
- ; directory if it is relative. Perform edit checks on the pathspec and abort
- ; if it is invalid. Used by Parse
- ;
- ; Called with:
- ;
- ; di points to the character following the target drive on the
- ; command line or to the first non-blank character following the
- ; source drive if no target drive is specified.
- ;
- ; cx contains the number of characters of the command line tail
- ; remaining to be processed.
- ;
- ; Returns:
- ;
- ; di points to the first switch char (/) on the command line if
- ; there are any, otherwise it points 1 byte past the end of the line.
- ;
- ; cx Contains the number of characters in the command line tail
- ; remaining to be processed.
- ;
- ; CL_Subdir_Pattern contains the full absolute dirspec. against which
- ; files to be restored must be matched. This string includes a
- ; trailing but no leading backslash. If the resultant dirspec.
- ; is the root, its value is empty.
- ;
- ; Subdir_Pat_Len contains the length of the dirspec. contained in
- ; CL_Subdir_Pattern including a trailing but no leading backslash. If
- ; the resultant dirspec. is the root, it contains 0.
- ;
- ; CL_File_Pattern contains a 12 byte fixed length file pattern against
- ; which files to be restored must match. It contains a period in
- ; the 9th position with the filename and extension padded on the right
- ; to full length with blanks and any asterisks expanded to their
- ; question mark equivalent.
- ;
- cmp byte ptr [di], '\' ; absolute path specified?
- jz GP_Absolute ; Yes, don't get current dir.
- push cx
- push di
- call Default_Subdir
- pop di
- pop cx
- jmp short GP_Trailing ; Proceed to check for trailing spaces on
- ; command line.
-
- GP_Absolute:
- inc di ; Bypass leading backslash.
- dec cx
- jnz GP_Trailing
- ret
-
- GP_Trailing:
- cmp byte ptr [di], ' ' ; Check for trailing spaces on command
- ; line.
- jnz GP_Copy ; If none, proceed.
- ; allow optional spaces
- ret
-
- GP_Copy:
- mov si, di ; Save ptr. to start of pathspec.
- mov al, '/' ; Search for switches.
- repne scasb ; Find beginning of switches if any.
- jne GP_No_Switches ; If none, di points one past end of line
- dec di ; otherwise, two past end of pattern.
- inc cx
- ; allow optional space before switches
- GP_No_Switches:
- cmp byte ptr [di-1], ' ' ; Ignore trailing spaces on command line.
- jnz GP_Onward ; No more trailing spaces, proceed.
- dec di ; Skip trailing space.
- inc cx ;
- jmp short GP_No_Switches ; Look for more.
-
- GP_Err0:
- Say_Err_Msg Bad_Wildcards
- call Abort_With_Help
-
-
- GP_Err1:
- Say_Err_Msg Bad_Params
- call Abort_With_Help
-
- ; Now di points 1 past end of pattern.
- GP_Onward: push cx ; Save remaining char count
- push di ; and ptr. to switches.
- mov cx, di ; Get length of pathspec in cx.
- sub cx, si
- lea di, CL_Subdir_Pattern ; Copy pathspec.
- add di, Subdir_Pat_Len ; Move ptr. past default dir. if any.
- lea bx, Valid_Chars ; Table of valid chars for pathspecs.
- inc cx ; compensate for DEC CX inside loop.
-
- GP_More_Zero:
- test Flags, WasPeriod ; Did last path element end with a dot?
- jz GP_No_Dot ; No, proceed.
- dec di ; Yes, get rid of it.
- mov byte ptr [di-1], '\'
- GP_No_Dot: mov Subdir_Pat_Len, di ; Used to get length of subdir pattern.
- xor dx, dx ; Zero path element length counter.
- test Flags, WildCards ; Wild card char in path?
- jnz GP_Err0 ; Yes, abort.
- dec cx ; Decrement count of remaining chars.
- jcxz GP_Copied
- cmp byte ptr [si], '\' ; "\\" not allowed.
- jz GP_Err2
- GP_More:
- cmp di, offset CL_Subdir_Pattern+62 ; Pattern too long?
- jae GP_Err1
- lodsb
- call Edit_Pathspec ; Convert char in al to upper case and
- jc GP_Err2 ; set Carry if char is invalid.
- stosb ; copying.
- inc dx ; Increment counter for this path
- ; element.
- cmp al, '\' ; Is this a path separator?
- jz GP_More_Zero ; Yes, zero dx before re-entering loop.
- cmp dx, 12 ; Is this element too long?
- ja GP_Err2 ; Yes, abort.
- loop GP_More
-
- GP_Copied:
- cmp di, Subdir_Pat_Len ; Is this the nul file pattern?
- jz GP_Nul ; Yes, no need to decode file pattern.
- call Get_File_Pattern
- GP_Nul:
- sub Subdir_Pat_Len, offset CL_Subdir_Pattern
- ; Calculate subdir pattern length.
- pop di ; Retrieve ptr. to switches.
- pop cx ; Retrieve remaining char count.
- GP_Done:
- ret
-
- GP_Err2:
- mov di, si
- mov al, '\' ; Was this part of filespec
- repne scasb
- jnz GP_Err3 ; Yes, use next error message.
- Say_Err_Msg Bad_Path
- call Abort_With_Help
-
- GP_Err3:
- Say_Err_Msg Bad_Filespec
- call Abort_With_Help
- Get_Pathspec endp
-
- ;==============================================================
-
- Edit_Pathspec proc near
- ; DOS 3.2 and 3.3
- ; Determine if the char in al is a valid filename or pathname
- ; char and if it is a wildcard char Used by Get_PathSpec
- ;
- ; Called with:
- ;
- ; al contains char to be validated.
- ;
- ; bx contains ptr. to table of valid filename and pathname chars.
- ;
- ; dx contains number of preceding chars for this pathspec element.
- ;
- ; Returns:
- ;
- ; Carry flag set if char was invalid, clear otherwise.
- ;
- ; Flags bit 6 set if char was a wildcard char, clear otherwise.
- ;
- ; Flags bit 7 set if the char was a period, clear if
- ; no period has been processed or if some character other than a
- ; backslash has been processed since the last period. The calling
- ; routine needs to know if a search pattern contains a period not
- ; followed by an extension in a path element since in this form
- ; the pattern will not match any dirspec's originating in the
- ; backup control file.
- ;
- cmp al, '.'
- jnz EP_Not_Period
- or dx, dx ; Is this the first char in a
- ; path element.
- jz EP_Err ; Yes, abort.
- cmp dx, 8 ; Has this element already got a '.'?
- ja EP_Err ; Yes, abort.
- mov dx, 8 ; Can only have 3 chars. after this.
- or Flags, WasPeriod ; Signal calling routine period
- ; processed.
- jmp short EP_OK
-
- EP_Not_Period:
- cmp al, '\' ; See Flags bit 7 description in
- ; this procedure's description.
- jz EP_OK
- and Flags,0ffh-WasPeriod ; 7fH
-
- cmp dx, 8 ; Should this have been a period?
- jz EP_Err ; Yes, abort.
-
- cmp al, '?' ; Set Flag if wildcard.
- jz EP_Wilds
- cmp al, '*'
- jz EP_Wilds
- sub al, 20H
- jl EP_Err ; al is out of range.
- xlat Valid_Chars ; Return upper case if letter,
- or al, al ; 0 if not a valid char.
- jz EP_Err
-
- EP_OK:
- clc
- ret
-
- EP_Wilds:
- or Flags, Wildcards ; Bit 6 set = wildcards found in
- clc ; command line pathspec.
- ret
-
- EP_Err:
- stc
- ret
- Edit_Pathspec endp
-
- ;==============================================================
-
- Get_File_Pattern proc near
- ; DOS 3.2 and 3.3
- ; Convert the file pattern entered on the command line to a fixed format 12
- ; chars. in length with a period in the 9th position. Pad the filename and
- ; extension on the right with blanks and expand any asterisks to their
- ; question mark equivalent. Used by Get_PathSpec
- ;
- ; Called with:
- ;
- ; di points to the byte following the last char copied from the
- ; command line to CL_Subdir_Pattern. This char is guaranteed to
- ; be either a filespec or part of a filespec.
- ;
- ; Subdir_Pat_Len contains the offset relative to ds of the filespec
- ; copied from the command line into CL_Subdir_Pattern.
- ;
- ; CL_Subdir_Pattern contains the pathspec entered from the command
- ; line. It is guaranteed to contain a filespec.
- ;
- ; CL_File_Pattern is a 12 byte string initialized to the nul file
- ; pattern "????????.???".
- ;
- ; Returns:
- ;
- ; CL_File_Pattern contains the file pattern as described used for
- ; deciding whether or not to restore a given file.
- ;
- ; If DX > 8 then filename contains explicit period.
- ; If BIT 6 in Flags is set we have a wildcard.
- ; Ambiguous case is C:\X
- ; Which should be C:\X\ for subdirectory or C:\X. for file
- cmp dx, 8
- ja Notambiguous
- test flags, Wildcards
- jnz Notambiguous
- Say_Err_Msg Ambiguous
- Call Strike_Any_Key
- Call Abort_With_Help
- Notambiguous:
- mov cx, di ; Get length of file pattern in cx.
- sub cx, Subdir_Pat_Len
- mov si, Subdir_Pat_Len
- lea di, CL_File_Pattern
-
- GFP_More:
- lodsb ; Get a byte.
- cmp al, '*'
- jnz GFP_Not_Star
- cmp di, offset CL_File_Pattern+9
- ; Is this the extension?
- jae GFP_Done ; Yes, all done.
- mov di, si
- mov al, '.' ; Scan for the period if any.
- dec cx
- repnz scasb
- mov si, di ; Point at first char of extension.
- lea di, CL_File_Pattern+9 ; Skip to file extension.
- jcxz GFP_Fill
- jmp short GFP_More
-
- GFP_Not_Star:
- cmp al, '.'
- jnz GFP_Copy
- GFP_Blank:
- cmp byte ptr [di], '.'
- jz GFP_Copy
- mov byte ptr [di], ' '
- inc di
- jmp short GFP_Blank
-
- GFP_Copy:
- stosb ; Copy the char.
- loop GFP_More
- GFP_Fill:
- mov al, ' '
- mov cx, offset CL_File_Pattern+12
- sub cx, di
- rep stosb
- mov CL_File_Pattern+8, '.'
- GFP_Done:
- ret
-
- Get_File_Pattern endp
-
- ;==============================================================
-
- Get_Switch proc near
- ; DOS 3.2 and 3.3
- ; nested in Parse
- ; di points to the letter following a switch char on the command line.
- ; Examine it and set the appropriate bit in Cmd_Flags or abort if it is
- ; not recognizable. Called by Parse.
- and byte ptr [di], 0DFH ; Convert to upper case.
- cmp byte ptr [di], 'P' ; Prompted restore?
- jnz GS_SlashS ; No
- or Cmd_Flags, Prompt_Needed; Bit 0 set = prompted restore.
- ret
-
-
- GS_SlashS:
- cmp byte ptr [di], 'S' ; Restore subdirectories?
- jnz GS_SlashQ ; No.
- or Cmd_Flags, RestoreSubs ; Bit 3 set = restore subdirectories.
- ret
-
- GS_SlashQ:
- cmp byte ptr [di], 'Q' ; Quiet, suppress banner.
- jnz GS_Bad ; No.
- or Cmd_Flags, Quietly ; Bit 3 set = quiet.
- ret
-
- GS_Bad:
- Say_Err_Msg Bad_Switch
- call Abort_With_Help
- Get_Switch endp
-
- ;==============================================================
- Abort_With_Help proc near
- ; called when syntax on command line is bad. We abort.
- ; We also give some help with the syntax.
- ; DOS 3.2 3.3
- ; Print syntax help exit with return code of 4.
- Say_Err_Msg Help_Msg
- mov ax, 4C04H ; Function = exit with return code of 4.
- int 21H
- Abort_With_Help endp
-
- ;==============================================================
- ;==============================================================
-
- Parse endp
-
- ;==============================================================
-
- Get_Next_Disk proc near
- ; DOS 3.2 and 3.3
- ; Prompt the user for the next diskette in the set and continue to prompt until
- ; he inserts a valid backup diskette. If the diskette inserted is not in
- ; sequence prompt him to select either Abort or Retry. In addition if there
- ; is currently no partially restored file on the hard disk allow the option of
- ; Ignore.
- ;
- ; Returns:
- ;
- ; Flags bit 2 set to indicate a new diskette.
- ;
- ; Flags bit 3 set if the user accepted a diskette out of sequence.
- ;
- ; Format_Flags bit 0 set if diskettes were backed up with DOS 3.2
- ; format.
- ;
- ; Format_Flags bit 1 set if diskettes were backed up using DOS 3.3 format.
- ;
- ; Patch insert prompt with sequence number.
- Patch_Num Want_Seq, Insert_Seq+2, 3
-
- GND_Again:
- Say_Err_Msg Insert ; Force the message to the console
- call Strike_Any_Key ; no matter where the output is going.
- call Process_Bkp_ID ; Is diskette in old format?
- jc GND_Again ; Yes, but we were restoring from new.
- jnz GND_OK ; Yes, proceed. Sequence no. is in ax.
- call Process_Ctl_Filename ; Sequence no. returned in ax.
- jc GND_Again ; CY=invalid backup diskette.
-
- GND_OK:
- cmp ax, Want_Seq ; Check returned sequence no.
- jz GND_Done ; Continue if its what we expected.
- push ax
- Say_Err_Msg Out_Of_Seq
- Say_Err_Msg CrLf
- pop ax
-
- comment |
-
- If the user has inserted a valid backup diskette with the wrong sequence
- number, allow him to choose either to abort or to insert a different diskette
- (Retry). In addition if the last file restored from the previous diskette
- is complete allow the user to continue despite the wrong sequence number.
- | ; end of comment.
- test Flags, LastFrag ; Is last file restored complete?
- jnz GND_Can_Ignore ; Yes, ignore is an option.
- test Flags, SkipFile ; Was last file being skipped?
- jnz GND_Can_Ignore ; Yes, Ignore is an option.
- call Abort_Retry
- jmp short GND_Again
-
- GND_Can_Ignore:
- push ax ; Save seq. no.
- call Abort_Retry_Ignore
- pop ax ; Retrieve seq. no. in ax.
- jc GND_Again
- or Flags, WrongOk+SkipFile ; User has accepted a diskette
- ; out of sequence, and
- ; do not restore frag.
-
- GND_Done:
- mov Bkp_Seq, ax ; Save current sequence no.
- inc ax ; Compute and store next sequence no.
- mov Want_Seq, ax
- or Flags, NewDisk ; Set New Disk flag.
- ret
- ; actual Get_Next_Disk endp but contains nested procs
-
- ;==============================================================
-
- Process_Bkp_ID proc near
- ; DOS 3.2
- ; nested in Get_Next_Disk
- ; If the current diskette is in DOS 3.2 backup format, process the backup ID
- ; file and announce the diskette sequence no. and date.
- ;
- ; Returns zero flag set if diskette is not in DOS 3.2 format, clear
- ; otherwise.
- ;
- ; Returns carry flag set if diskette is in DOS 3.2 format but the set
- ; currently being restored is in DOS 3.3 format, clear otherwise.
- ;
- ; Returns with bit 0 of Format_Flags set if the backup diskette is in
- ; DOS 3.2 format and this is acceptable, i.e. either this is the first
- ; diskette to be restored or the previous diskettes were in DOS 3.2 format.
- ;
- call Open_Bkp_ID
- call Get_Bkp_ID
- jnc PBI_Old ; BACKUPID.@@@ was read successfully.
- clc ; Return with ZF and NC meaning
- ret ; unrecognized format.
-
- PBI_Old:
- call Close_Ctl_File ; Close BACKUPID.@@@.
- ; Announce diskette.
- Patch_Num Buffer.BI_Seq, ABM_Seq+2, 3
- Patch_Num Buffer.BI_YYYY, ABM_YYYY+3, 4
- xor ax, AX
- mov al, Buffer.BI_MM
- Patch_Num ax, ABM_MM+1, 2
- xor ax, AX
- mov al, Buffer.BI_DD
- Patch_Num ax, ABM_DD+1, 2
- Say_Msg Announce_Bkp_Msg
-
- test Format_Flags, DOS33 ; Were we already restoring a new
- ; format set?
- jnz PBI_Err ; Yes.
- or Format_Flags, DOS32 ; No, set flag for old format.
-
- and Flags, 0ffh - LastDisk ; 0FDH
- ; Reset flag for last diskette. Could
- ; have been set prematurely if a user
- ; rejected a diskette out of sequence.
- cmp Buffer.BI_Last, -1 ; Is this last diskette in set?
- jne PBI_Done ; No, don't set flag.
- or Flags, LastDisk ; Yes, set flag for last diskette.
-
- PBI_Done:
- mov ax, Buffer.BI_Seq ; Return sequence no. in ax.
- or ax, ax ; Return NZ for valid diskette.
- clc ; Return NC for correct format.
- ret
-
- PBI_Err:
- Say_Err_Msg Wrong_Set
- Say_Err_Msg CrLf
- call Abort_Retry
- stc ; CY = diskette in wrong format.
- ret
- ; actual Process_Bkp_ID EndP but contains nested procs
-
- ;==============================================================
-
- Open_Bkp_ID proc near
- ; DOS 3.3
- ; nested in Get_Next_Disk
- ; nested in Process_Bkp_ID
- ; Open BACKUPID.@@@ on current floppy and return handle in Ctl_Hndl. If file
- ; cannot be found, return with handle of -1. Abort if any other error occurs.
- lea dx, Bkp_ID_Name
- mov ax, 3D00H ; open read-only 3D:00
- int 21H
- jc OBI_Err
- mov Ctl_Hndl, ax
- ret
-
- OBI_Err:
- cmp ax, 2 ; File not found?
- je OBI_Err1
- cmp ax, 3 ; Invalid path or file missing?
- je OBI_Err1
- push ax ; Save error code.
- Say_Err_Msg Floppy_Trouble ; Cant_Open_BC
- pop ax ; Retrieve error code.
- cmp ax, 4 ; Too many files open?
- je OBI_Err2
- Say_Err_Msg Unknown ; Unknown error, abort.
- call Abort
-
- OBI_Err1:
- ret ; Return handle of -1.
-
- OBI_Err2:
- Say_Err_Msg Too_Many_Open
- call Abort ; not enough handles, abort.
-
- Open_Bkp_ID endp
-
- ;==============================================================
-
- Get_Bkp_ID proc near
- ; DOS 3.3
- ; nested in Get_Next_Disk
- ; nested in Process_Bkp_ID
- ; If BACKUPID.@@@ was successfully opened, read its first 7 bytes into the
- ; buffer and convert the sequence no. to true binary form.
- ;
- ; Called with:
- ;
- ; Ctl_Hndl contains the handle of BACKUPID.@@@ if it was successfully
- ; opened, -1 otherwise.
- ;
- ; Returns if successful:
- ;
- ; Buffer contains the first 7 bytes of BACKUP.@@@ with the sequence no.
- ; converted to true binary form.
- ;
- ; Carry Flag = clear.
- ;
- ; Returns carry flag set if BACKUPID.@@@ was not previously successfully opened.
- ;
- mov bx, Ctl_Hndl
- cmp bx, -1
- jz GBI_Not_Bkp
- mov cx, 7 ; Read 7 bytes.
- lea dx, Buffer ; ds:dx points at buffer.
- mov ah, 3FH ; Function = Read.
- int 21H
- jc GBI_Err ; Abort if trouble.
- cmp ax, 7
- jne GBI_Err
-
- ; Convert 8 bit BCD BI_Seq into true binary format.
- mov al, 10
- mul byte ptr Buffer.BI_Seq+1
- add al, byte ptr Buffer.BI_Seq
- adc ah, 0
- mov Buffer.BI_Seq, ax
- clc ; NC means all is in order.
- ret
-
- GBI_Not_Bkp: ; Return CY if diskette is not
- stc ; DOS 3.2 backup.
- ret
-
- GBI_Err:
- Say_Err_Msg Unknown
- call Abort
- Get_Bkp_ID endp
-
- ;==============================================================
-
- Process_Bkp_ID endp
-
- ;==============================================================
-
- Process_Ctl_Filename proc near
- ; DOS 3.3
- ; nested in Get_Next_Disk
- ; Blank out the extension of the previous backup control filename with "?"
- ; wildcard characters and use it to find the backup control file on the new
- ; diskette. If a file is found, convert its sequence number contained in its
- ; extension to a hex value returned to the calling procedure. If no filename
- ; is matched, or if the extension of a matched filename does not contain three
- ; numeric digits, print an error message and signal the calling routine to prompt
- ; for another diskette. If some other error occurs, abort the program with an
- ; error message. Called by Get_Next_Disk
- ;
- ; Called with:
- ;
- ; Ctl_Filename contains the complete nul terminated drive and pathspec
- ; which when the extension is patched with the sequence no. of the
- ; current disk will refer to the backup control file on that disk.
- ;
- ; Bkp_Filename contains the same as Ctl_filename but with respect
- ; to the backup data filename.
- ;
- ; Returns if successful:
- ;
- ; ax contains the hex representation of the sequence no. for the
- ; current diskette.
- ;
- ; Ctl_filename and Bkp_Filename are as when called but patched with
- ; the correct extensions.
- ;
- Blank_Extension Ctl_Filename+11
- lea dx, Ctl_Filename
- xor cx, cx ; Use normal attributes.
- or cx, 10H ; Turn on subdir bit as well. I've
- ; heard that MS DOS 3.2 may not return
- ; all normal files unless subdirs. are
- ; included.
- mov ah, 4EH ; Function = Search for First
- int 21H
- jnc PCF_Found
- cmp ax, 12H ; Matching file not found?
- jz PCF_Err1 ; Yes, not a backup diskette.
- jmp short PCF_Err2 ; No, unknown error.
-
- PCF_Found:
- cmp ds:DTA.DS_Name + 7, '.'
- jnz PCF_Err1
- mov si, DTA.DS_Name+8 ; Point di to beginning of extension.
- mov cx, 3 ; cx = field length.
- call ASCII_Dec_To_Hex
- jc PCF_Err1 ; CY = non-numeric char in field.
- test ds:DTA.DS_Attr, 10H ; Was file a subdir?
- jnz PCF_Err1 ; Yes, non-backup diskette.
-
- ; si points at terminating nul following DTA.DS_Name. di points at terminating
- ; nul following Ctl_Filename.
- call Patch_Filename_Exts
- push ax ; Save sequence no.
- call Patch_Announce_Bkp_Msg
- Say_Msg Announce_Bkp_Msg
- pop ax ; Retrieve seq. no. in ax.
- test Format_Flags, DOS32 ; Were we already restoring files
- ; from a backup set in the old format?
- jnz PCF_Err3 ; Yes.
- or Format_Flags, DOS33 ; No, set flag for DOS 3.3 format.
- clc
- ret
-
- PCF_Err1:
- Say_Err_Msg Not_Bkp
- Say_Err_Msg CrLf
- call Abort_Retry
- stc
- ret
-
- PCF_Err2:
- Say_Err_Msg Unknown
- call Abort
-
- PCF_Err3:
- Say_Err_Msg Wrong_Set
- Say_Err_Msg CrLf
- call Abort_Retry
- stc
- ret
- ; actual Process_Ctl_Filename EndP but contains nested procs.
-
- ;==============================================================
-
- Patch_Filename_Exts proc near
- ; DOS 3.3
- ; nested in Get_Next_Disk
- ; nested in Process_Ctl_Filename
- ; Fill in the extensions for CONTROL.XXX and BACKUP.XXX.
- ;
- ; Called with:
- ;
- ; Offset DTA.DS_Name contains filename returned from function 4EH
- ; Search For First.
- ;
- ; si points at the nul terminating the above name.
- ;
- ; di points at the nul terminating Ctl_Filename.
- ;
- ; Returns:
- ;
- ; Ctl_Filename and Bkp_Filename extensions filled in with the
- ; apparent sequence no. of the diskette according to the directory
- ; search for CONTROL.XXX in the procedure Process_Ctl_Filename.
- ;
- mov cx, 4 ; 3 chars. plus trailing nul.
- std
- rep movsb
- lea di, Bkp_Filename + 9 ; Point to "." before Bkp_filename ext.
- mov cx, 4 ; "." + 3 chars. file ext.
- cld
- rep movsb
- ret
- Patch_Filename_Exts endp
-
- ;==============================================================
-
- Process_Ctl_Filename endp
-
- ;==============================================================
-
- Patch_Announce_Bkp_Msg proc near
- ; DOS 3.3
- ; Patch the message which announces the current diskette with its sequence no.
- ; and date.
- Patch_Num ax, ABM_Seq+2, 3
-
- mov ax, ds:DTA.DS_Date ; Date of CONTROL.XXX file.
- push ax ; Save a copy.
- mov cl, 5 ; Isolate month and patch it into msg.
- shr ax, cl
- and ax, 000FH
- Patch_Num ax, ABM_MM+1, 2
- pop ax
-
- push ax
- and ax, 001FH ; Isolate day and patch it into msg.
- Patch_Num ax, ABM_DD+1, 2
- pop ax
-
- mov cl, 7 ; Isolate year and patch it into msg.
- rol ax, cl
- and ax, 07FH
- add ax, 1980
- Patch_Num ax, ABM_YYYY+3, 4
- ret
- Patch_Announce_Bkp_Msg endp
-
- ;==============================================================
-
- Get_Next_Disk endp
-
- ;==============================================================
-
- ASCII_Dec_To_Hex proc near
- ; DOS 3.3
- ; used by Process_Control_FileName
- ; Convert ASCII string of decimal digits to a 16 bit hex value.
- ;
- ; Called with:
- ;
- ; si points to leftmost digit in string.
- ;
- ; cx contains field width.
- ;
- ; Returns if successful:
- ;
- ; ax contains 16 bit quantity.
- ;
- ; si points to char following last digit.
- ;
- ; carry flag = clear.
- ;
- ; Returns carry flag set if non-numeric char in string.
- ;
- xor ax, ax
- mov bl, 0AH
- ADTH_More:
- mul bl
- mov dl, [si] ; Fetch a digit.
- inc si
- cmp dl, '9'
- ja ADTH_Err
- sub dl, '0' ; Convert from ASCII and make sure
- jb ADTH_Err ; char is numeric.
-
- add al, dl
- adc ah, 0
- loop ADTH_More
- clc
- ret
-
- ADTH_Err:
- stc
- ret
- ASCII_Dec_To_Hex endp
-
- ;==============================================================
-
- Strike_Any_Key proc near
- ; DOS 3.2 and 3.3
- ; Prompt the user to strike spacebar and return to caller when any key detected.
- ; This is better than asking him to strike any key since there are at least
- ; 6 keys which wont be detected.
- Say_Err_Msg Strike_Any ; Force message to print
- ; on console regardless of I/O
- ; redirection.
- mov ax, 0C08H ; Clear typeahead buffer and get one
- int 21H ; filtered char without echo.
- or al, al ; If extended code, get rid of it.
- jnz SAK_Done
- mov ah, 7 ; Function = Get Unfiltered Char.
- int 21H ;w/o echo.
-
- SAK_Done:
- ret
- Strike_Any_Key endp
-
- ;==============================================================
-
- Open_Ctl_File proc near
- ; DOS 3.3
- ; OPEN CONTROL.XXX
- ; Open the current backup control file and store the returned handle in
- ; Ctl_Hndl. print error message and abort if operation failed.
- ;
- ; Returns:
- ;
- ; Ctl_Hndl contains the handle of the successfully opened backup
- ; control file with the file ptr. positioned at the beginning of the file.
- ;
- OCF_Retry:
- lea dx, Ctl_Filename
- mov ax, 3D00H ; Open file with read access.
- int 21H
- jc OCF_Err
- mov Ctl_Hndl, ax ; Save handle.
- ret
-
- ; File could not be opened, process condition.
- OCF_Err:
- push ax ; Would be trashed by Say_Err_Msg
- Say_Err_Msg Floppy_Trouble ; Cant_Open_BC
- pop ax ; Restore error code to ax.
- cmp ax, 4 ; Too many files open?
- je OCF_Err1
- Say_Err_Msg Unknown
- call Abort
-
- OCF_Err1:
- Say_Err_Msg Too_Many_Open
- call Abort ; not enough handles, abort.
-
- Open_Ctl_File endp
-
- ;==============================================================
-
- Open_Bkp_File proc near
- ; DOS 3.2
- ; If restoring files backup up with DOS 3.2 format, copy the filespec of the
- ; backup data file from the DTA into Bkp_Filename.
- ; Open the current backup data file and store the returned handle in
- ; Bkp_Hndl. print error message and abort if operation failed.
- ;
- ; Returns:
- ;
- ; Bkp_Hndl contains the handle of the successfully opened backup
- ; data file with the file ptr. positioned at the beginning of the file.
- ;
- OBF_Retry:
- test Format_Flags, DOS33 ; Is this DOS 3.3 format?
- jnz OBF_New ; Yes, Bkp_Filename already contains
- ; filespec
-
- ; This is DOS 3.2 format. Copy the backup data filename from the DTA.
- mov cx, 13 ; Max. length of filename with nul.
- mov si, DTA.DS_Name
- lea di, Bkp_Filename+3 ; Bypass d:\.
- rep movsb ; Copy filename.
-
- OBF_New:
- lea dx, Bkp_Filename
- mov ax, 3D00H ; Open with read access.
- int 21H
- jc OBF_Err
- mov Bkp_Hndl, ax
- ret
-
- ; File could not be opened, process condition.
- OBF_Err:
- push ax ; Would be trashed by Say_Err_Msg
- Say_Err_Msg Floppy_Trouble ; Bkp_File_Msg
- pop ax ; Restore error code to ax.
- cmp ax, 2 ; File not found?
- je OBF_Err1
- cmp ax, 3 ; Invalid path or file missing?
- je OBF_Err1
- cmp ax, 4 ; Too many files open?
- je OBF_Err2
- Say_Err_Msg Unknown ; Unknown error, abort.
- call Abort
-
- OBF_Err1:
- Say_Err_Msg Floppy_Trouble ; File_Not_Found
- call Abort
-
- OBF_Err2:
- Say_Err_Msg Too_Many_Open
- call Abort ; not enough handles, abort.
-
- Open_Bkp_File endp
-
- ;==============================================================
-
- Process_Hdr proc near
- ; DOS 3.3
- ; in CONTROL.XXX file
- ; Read the header record from the current backup control file and confirm
- ; the validity of the file.
- ; Set a flag if this is the last diskette in the set.
- ;
- ; Called with:
- ;
- ; Ctl_Hndl contains the handle of the currently open control file
- ; with the file ptr. positioned at the beginning of the file.
- ;
- ; Returns:
- ;
- ; Buffer contains the successfully read header record beginning
- ; at offset zero.
- ;
- call Read_Hdr
- call Chk_Sig
- call Chk_Seq
-
- cmp Buffer.HDR_Last, 0ffh ; Is this last diskette in set?
- jnz PH_Done
- or Flags, LastDisk ; Set flag if it is.
- PH_Done:
- ret
-
- ;==============================================================
-
- Read_Hdr proc near
- ; DOS 3.3
- ; nested in Process_Hdr
- ; Read the header record into the buffer from the currently open backup control
- ; file. Print error message and abort if operation failed.
- ;
- ; Called with:
- ;
- ; Ctl_Hndl contains the handle of the currently open backup control
- ; file with the file ptr. positioned at the beginning of the file.
- ;
- ; Returns:
- ;
- ; Buffer contains the successfully read header record beginning
- ; at offset buffer.
- ;
- lea dx, Buffer
- mov bx, Ctl_Hndl
- mov cx, HDR_REC_LEN
- mov ah, 3FH ; Function = Read.
- int 21H
- jc RH_Err
- cmp cx, ax ; Read o.k.?
- jne RH_Err ; Abort if not.
- ret
-
- RH_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- Read_Hdr endp
-
- ;==============================================================
-
- Chk_Seq proc near
- ; DOS 3.3
- ; nested in Process_Hdr
- ; Make sure the sequence number in the control file header agrees with that
- ; of the volume label and file extensions. Abort if it does not.
- ;
- mov ax, Bkp_Seq
- cmp ax, Buffer.Hdr_Seq
- jnz CSeq_Err
- ret
-
- CSeq_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Hdr_Seq
- call Abort
- Chk_Seq endp
-
- ;==============================================================
-
- Chk_Sig proc near
- ; DOS 3.3
- ; nested in Process_Hdr
- ; Verify backup control file signature.
- ;
- lea si, Bkp_Sig
- lea di, Buffer.Hdr_Sig
- mov cx, Bkp_Sig_Len
- repe cmpsb
- jnz CS_Err
- ret
-
- CS_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Sig
- call Abort
- Chk_Sig endp
-
- ;==============================================================
-
- Process_Hdr endp
-
- ;==============================================================
-
- Get_Subdir proc near
- ; DOS 3.3
- ; Process all of the subdir records for the current diskette.
- ;
- GS_More:
- call Get_Subdir_Rec ; Get a subdir record.
- call Get_Dirspec ; Copy out the pathname.
- jc GS_Wrong_Set
-
- ; Save ptr. to next subdir record.
- push word ptr Buffer.Subdir_Next + 2
- push word ptr Buffer.Subdir_Next
-
- call Select_Subdir ; Zero flag set means this dirspec.
- clc ; doesn't match the command line
- jnz GS_Bypass ; pattern, clear otherwise.
- mov cx, Buffer.Subdir_Count ; Pass file record count in cx.
- call Get_Files
- GS_Bypass:
- pop dx ; Pass offset of next subdir record
- ; low word in dx.
- pop cx ; Pass offset of next subdir record
- ; high word in cx.
- jc GS_Wrong_Set ; cy set by Get_Files. Needed to
- ; pop stack before test.
- call Seek_Next_Subdir ; NC = no more subdirs on this diskette.
- jc GS_More ; CY = go back for more.
- ret
-
- GS_Wrong_Set:
- Say_Err_Msg Wrong_Set
- Say_Err_Msg CrLf
- call Abort_Retry
- call Close_Bkp_File ; If Retry, go back for another diskette.
- call Close_Ctl_File ; after closing files on this diskette.
- dec Want_Seq
- stc ; CY signals to prompt for another disk.
- ret
-
- ;==============================================================
-
- Get_Subdir_Rec proc near
- ; DOS 3.3
- ; Read the next subdir record into the buffer and verify it by checking
- ; its length field. Abort with error message if record proves invalid.
- ;
- ; Called with:
- ;
- ; Ctl_Hndl contains the handle of the currently open backup control
- ; file with the file ptr. positioned at the beginning of the next
- ; subdir record.
- ;
- ; Returns:
- ;
- ; Buffer contains the successfully read subdir record beginning
- ; at offset buffer.
- ;
- lea dx, Buffer
- mov cx, SUBDIR_REC_LEN
- mov bx, Ctl_Hndl
- mov ah, 3FH ; Function = Read.
- int 21H
- jc GSR_Err
- cmp ax, cx ; Read o.k.?
- jne GSR_Err ; Abort if not.
- cmp Buffer.Subdir_Len, cl ; If this record is valid, these
- jne GSR_Err ; should be equal.
- ret
-
- GSR_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- Get_Subdir_Rec endp
-
- ;==============================================================
-
- Get_Dirspec proc near
- ; DOS 3.3
- ; If the current diskette is not in sequence and this is the first subdir
- ; record or if the last file was not to be continued, copy the dirspec from
- ; the current subdir record to the pathspec to be restored. Otherwise, make
- ; sure the dirspec in this subdir record is the same as that from the last.
- ; A discrepancy probably indicates the new diskette is from a different set
- ; so alert the user and prompt for the proper diskette.
- ;
- ; Called with:
- ;
- ; Buffer contains the last subdir record read from the backup control
- ; file.
- ;
- ; Flags bit 0 is set if the last file was not to be continued, clear
- ; otherwise.
- ;
- ; Flags bit 3 is set if the newly inserted diskette is out of
- ; sequence, clear otherwise.
- ;
- ; Returns if Successful:
- ;
- ; Filespec_Ptr points to the offset in Rest_Path where the filespec
- ; will begin.
- ;
- ; Rest_Path contains the dirspec. of the current subdir record
- ; left justified with a trailing backslash if required. The
- ; drive and leading backslash have already been filled in immediately
- ; before Rest_Path.
- ;
- ; Carry flag = clear.
- ;
- ; Returns carry flag set if the dirspec. for a continuation of a file did
- ; not match the previous dirspec.
- ;
- lea si, Buffer.Subdir_Name
- lea di, Rest_Path
- cld
-
- test Flags, WrongOk ; Diskette out of sequence?
- jnz GD_Copy ; Yes, copy dirspec.
- test Flags, LastFrag ; Last file continued?
- jnz GD_Copy ; No, copy new dirspec.
-
- mov cx, Filespec_Ptr ; = dirspec. length with trailing
- ; backslash
- jcxz GD_Nul ; or 0 if dirspec. is root.
- dec cx ; Don't count trailing backslash.
- repe cmpsb
- jnz GD_Err ; New dirspec. is different.
-
- GD_Nul:
- mov al, 0 ; Now make sure trailing nul
- cmp [si], al ; comes next.
- jnz GD_Err
- jmp short GD_Done
-
- GD_Copy:
- mov cx, size Subdir_Name
- GD_More:
- lodsb
- or al, al ; Watch for the trailing nul.
- jz GD_Copied ; Add backslash and set up ptr.
- stosb
- loop GD_More
-
- ; If we get this far there's something wrong.
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- GD_Copied:
- cmp di, offset Rest_Path ; If dirspec. is root, don't add
- je GD_Root ; a trailing backslash.
- mov al, '\' ; Add trailing backslash.
- stosb
- dec cx
- GD_Root:
- mov Filespec_Ptr, size Subdir_Name ; Set ptr. to start of
- ; filespec
- sub Filespec_Ptr, cx
-
- GD_Done:
- clc ; All is in order.
- ret
-
- GD_Err:
- stc
- ret
-
- Get_Dirspec endp
-
- ;==============================================================
-
- Seek_Next_Subdir proc near
- ; DOS 3.3
- ; Set the backup control file ptr. to the next subdir record, or set the
- ; carry flag if there is none. Abort if the flags indicate a file with
- ; fragments pending if there are more subdir records on the disk.
- ;
- ; Called with:
- ;
- ; cx contains high word of absolute offset in backup control file of
- ; next subdir record or -1 if there is none.
- ;
- ; dx contains low word of absolute offset in backup control file of
- ; next subdir record or -1 if there is none.
- ;
- ; Ctl_Hndl contains the handle of the open backup control file.
- ;
- ; Flags contains bit 0 set if there are no pending file fragments for
- ; the file just restored, clear if there is.
- ;
- ; Returns:
- ;
- ; If there is another subdir record to process, the carry flag is set
- ; and the file ptr. of the backup control file is positioned at
- ; the beginning of the next subdir record.
- ;
- ; If there are no more subdir records for this diskette the carry flag
- ; is clear.
- ;
- cmp cx, 0ffffh ; Find out if this is the last record.
- jnz SNS_Not_Last ; If it is, cx and dx = -1.
- cmp dx, 0ffffh
- jnz SNS_Not_Last
- clc
- ret
-
- SNS_Not_Last: ; Check for invalid flag.
- test Flags, LastFrag
- jz SNS_Err1
-
- ; Point to next subdir record.
- mov bx, Ctl_Hndl
- mov ax, 4200H ; Function 42 = Move File Ptr.
- int 21H ; al=0 for absolute offset.
- jc SNS_Err2
- stc
- ret
-
- SNS_Err1:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- SNS_Err2:
- Say_Err_Msg Unknown
- call Abort
- Seek_Next_Subdir endp
-
- ;==============================================================
-
- Get_Subdir endp
-
- ;==============================================================
-
- Get_Files proc near
- ; DOS 3.3
- ; Process the file records which follow a subdirectory record in the backup
- ; control file. Return with carry flag clear if all is in order or set if
- ; the current diskette appears to be from the wrong set.
- ;
- ; Called with:
- ;
- ; cx contains the number of file records in the backup control file
- ; remaining to be processed.
- ;
- ; Ctl_Hndl contains the handle of the open backup control file with the
- ; file ptr. positioned at the beginning of the next file record.
- ;
- ; Flags bit 0 set if the previous file fragment was not to be
- ; continued, clear otherwise.
- ;
- ; Flags bit 2 set if this is a new diskette, clear otherwise.
- ;
- GF_More:
- or cx, cx ; Any more file records?
- jz GtF_Done ; No, return to caller.
-
- Comment |
-
- I am assuming that a file record which indicates that there is another file
- fragment coming must always be the last file record in a backup control file.
- The following tests the validity of the backup control file based on this
- assumption.
- | ; End of comment.
- test Flags, LastFrag ; Was previous file to be continued?
- jnz GtF_OK ; No, proceed with next file.
- test Flags, NewDisk ; Yes, is this a new diskette?
- jz GtF_Err ; No, control file is invalid.
-
- GtF_OK:
- push cx ; Save count value.
- call Get_File_Rec
- call Get_Filespec
- jc GtF_Wrong_Set
- call Set_Checks ; Attempt to catch diskettes from
- jc GtF_Wrong_Set ; another set.
- mov dx, Buffer.File_Frag_Seq
- ; Pass file fragment no. in dx.
- call Select_File ; Decide if file should be restored.
- jc GF_Bypass ; CY = don't restore file.
-
- mov dx, Buffer.File_Frag_Seq
- ; Pass file frag. seq. no. in dx.
- mov bl, Buffer.File_Attr ; Pass file attribute in bl.
- call Announce_File
- jc GF_Bypass ; CY = User answered no to restore
- ; prompt.
-
- call Seek_Fragment ; Set backup data file ptr. to beginning
- ; of this fragment.
- ; Copy over one fragment.
- mov bl, Buffer.File_Attr ; Pass file attribute in bl.
- mov cx, Buffer.File_Time ; Pass file time in cx.
- mov dx, Buffer.File_Date ; File date in dx.
- ; Pass file fragment size in bp:si.
- mov si, word ptr Buffer.File_Frag_Size
- mov bp, word ptr Buffer.File_Frag_Size + 2
- call Do_One_Chunk
-
- GF_Bypass:
- pop cx ; Restore remaining file record count
- ; to cx.
- dec cx
- jmp GF_More
-
- GtF_Done:
- clc ; NC means all is well.
- ret
-
- GtF_Wrong_Set:
- pop cx ; Clear the stack.
- ret ; Return to caller with carry flag set.
-
- GtF_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- ;==============================================================
-
- Get_File_Rec proc near
- ; DOS 3.3
- ; Read a file record into the buffer from the backup control file and verify
- ; it by checking its length field. Abort if record is not valid.
- ; Set bit 0 of Flags if record is for last fragment of a file.
- ; Make sure the file fragment sequence number is correct and set the next
- ; expected fragment sequence no. based on whether or not this file is continued.
- ;
- ; Called with:
- ;
- ; Ctl_Hndl contains the handle of the open backup control file with
- ; the file ptr. positioned at the beginning of the file record to
- ; be read.
- ;
- ; Want_Frag_Seq contains the expected file fragment sequence number.
- ;
- ; Returns:
- ;
- ; Buffer contains the successfully read file record beginning at
- ; offset Buffer.
- ;
- ; Flags has bit 0 set if this record is for the last fragment of
- ; a file.
- ;
- ; Want_Frag_Seq contains the next expected fragment sequence number.
- ;
- lea dx, Buffer
- mov bx, Ctl_Hndl
- mov cx, FILE_REC_LEN
- mov ah, 3FH ; Function = Read.
- int 21H
- jc GFR_Err
- cmp cx, ax ; Read successful?
- jne GFR_Err ; Abort if not.
- cmp Buffer.File_Len, cl ; If this record is valid, these
- jne GFR_Err ; should be equal.
- ret
-
- GFR_Err:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- Get_File_Rec endp
-
- ;==============================================================
-
- Get_Filespec proc near
- ; DOS 3.3
- Comment |
- If this is the first file record on a diskette accepted out of sequence, or
- if the previous file was not to be continued:
- > Get filespec in current file record into target pathspec to be restored.
- > Calculate the length of the complete drive and pathspec not including the
- terminating nul.
- Otherwise, if this file record is for the continuation of a previous file:
- > Make sure the previous filespec in the pathspec to be restored matches the
- filespec in the current file record. If they do not match, this probably
- indicates that the new diskette is from another set.
-
- Called with:
-
- Buffer contains the current file record beginning at offset 0.
-
- Filespec_Ptr contains offset into rest_Path where the filespec of
- the file to be restored must begin.
-
- Rest_Path contains the dirspec. of the file to be restored.
-
- Flags bit 3 set if this is the first file record on a diskette
- accepted out of sequence.
-
- Flags bit 0 set if the previous file was to be continued.
-
- Returns:
-
- Rest_Name contains the complete nul terminated pathspec including
- the drive of the file being restored.
-
- Rest_Name_Len contains the length of the drive and pathspec not
- including the terminating nul.
-
- Carry Flag set if filespec comparison failed, clear otherwise.
-
- | ; End of comment.
- lea si, Buffer.File_Name ; Set up indexes to copy or compare.
- lea di, Rest_Path
- add di, Filespec_Ptr ; Point di to start of filespec.
- test Flags, WrongOk ; Is this the first file rec. on a
- ; diskette out of sequence?
- jnz GF_Copy ; Yes, copy the new filespec
- test Flags, LastFrag ; Is this a continuation?
- jnz GF_Copy ; No, copy the new filespec
-
- mov cx, Rest_Name_Len ; Get length of filespec not including
- sub cx, Filespec_Ptr ; nul in cx.
- sub cx, 3 ; Knock off 3 for the C:\
- repe cmpsb
- jnz GF_Err2 ; filespec didn't match.
-
- Comment |
-
- In the case of a full length filespec in the file record there will be
- no trailing nul. A matching full length filespec is shown by si pointing to
- the byte following the filename field in the file record. For the other cases
- the trailing nul may be tested for.
- | ; End of comment.
- cmp si, offset Buffer + 13 ; Does si point past filename field?
- jz GF_Done ; Yes, name was a perfect match.
- cmp byte ptr [si], 0 ; Otherwise check that the next byte
- jz GF_Done ; is 0.
- jmp short GF_Err2 ; Filename did not match.
-
- GF_Copy:
- mov cx, size File_Name
- cld
- rep movsb
- mov byte ptr [di], 0 ; and make sure it's null terminated.
-
- mov cx, 64 ; Maximum length of pathspec.
- lea di, Rest_Path ; Calculate total length of drive
- mov al, 0 ; and pathspec not including trailing
- repne scasb ; nul.
- sub di, offset Rest_Name + 1
- cmp di, 65 ; Abort if length illegal.
- ja GF_Err1
- mov Rest_Name_Len, di
- GF_Done:
- clc ; All is in order.
- ret
-
- GF_Err1:
- Say_Err_Msg Floppy_Trouble ; Bad_Ctl_File
- call Abort
-
- GF_Err2:
- stc ; CY = diskette is from another set.
- ret
- Get_Filespec endp
-
- ;==============================================================
-
- Set_Checks proc near
- ; DOS 3.3
- ; Attempt to catch diskettes from the wrong backup set by checking for
- ; incorrect file fragment sequence numbers and file size fields in file records.
- ; Also keep partial files from being restored when diskettes are inserted out
- ; of sequence.
- ;
- ; Called with:
- ;
- ; Buffer contains the current file record.
- ;
- ; Want_Frag_Seq contains the expected file fragment sequence no.
- ;
- ; Want_Size contains the expected file size for subsequent fragments
- ; of multiple fragment files.
- ;
- ; Flags bit 0 set according to previous file record or to 1 if
- ; there was none.
- ;
- ; Flags bit 3 set if this is the first file on a diskette accepted out
- ; of sequence.
- ;
- ; Returns if no problem detected:
- ;
- ; Carry Flag = clear.
- ;
- ; Want_Frag_Seq contains the next expected file fragment sequence no.
- ;
- ; Want_Size contains the total file size of the current file.
- ;
- ; Flags bit 0 set according to the current file record.
- ;
- ; Flags bit 4 set if the current fragment is a file continuation on
- ; a diskette out of sequence.
- ;
- ; Flags bits 2 and 3 cleared.
- ;
- ; Returns if problem detected:
- ;
- ; Carry Flag = set.
- ;
- test Flags, WrongOk ; Is this the first file rec. from a
- ; diskette accepted out of sequence?
- jz SC_In_Seq ; No, test for validity.
- mov ax, Buffer.File_Frag_Seq
- ; Yes, re-initialize gragment sequence
- ; number from file rec.
- mov Want_Frag_Seq, ax
- cmp ax, 1 ; Signal that this fragment should not
- jz SC_Frag_Seq_OK ; be restored if the fragment seq. no.
- or Flags, SkipFile ; is not 1.
- jmp short SC_Frag_Seq_OK ; Bypass validity check.
-
- SC_In_Seq:
- mov ax, Want_Frag_Seq ; Make sure fragment sequence number
- ; is as expected.
- cmp ax, Buffer.File_Frag_Seq
- jnz SC_Wrong_Set
-
- SC_Frag_Seq_OK: ; Now for the file size check.
- lea si, Buffer.File_Size
- lea di, Want_Size
- cld
- mov cx, 2 ; cx = no. of words to compare or copy.
- test Flags, WrongOk ; Is this first file on diskette
- ; accepted out of sequence?
- jnz SC_Copy ; Yes, copy over new file size.
- test Flags, LastFrag ; Was last file to be continued?
- jnz SC_Copy ; No, copy over new file size.
-
- repe cmpsw ; File sizes for current and previous
- jnz SC_Wrong_Set ; file records should be equal.
- jmp short SC_Size_OK
-
- SC_Copy:
- rep movsw
-
- SC_Size_OK:
- and Flags, 0ffh-(LastFrag+WrongOk+NewDisk)
- ; 0F2H
- ; Clear last fragment, diskette out
- ; of sequence and new diskette
- ; indicators.
- and Buffer.File_More, 1 ; Set bit 0 in Flags if this is
- jz SC_Done ; the record for a file's last fragment.
- or Flags, LastFrag
- mov Want_Frag_Seq, 0 ; Reset fragment sequence no.
-
- SC_Done:
- inc Want_Frag_Seq ; Store next expected frag. seq. no.
- clc
- ret
-
- SC_Wrong_Set:
- stc
- ret
- Set_Checks endp
-
- ;==============================================================
-
- Seek_Fragment proc near
- ; DOS 3.3
- ; Position BACKUP.XXX file ptr. to start of this fragment. The current
- ; file record is still in Buffer beginning at offset zero.
- ;
- mov dx, word ptr Buffer.File_Frag_Start
- mov cx, word ptr Buffer.File_Frag_Start + 2
- mov bx, Bkp_Hndl
- mov ax, 4200H ; Function Move File Ptr.
- int 21H ; al=0 for absolute offset.
- jc SF_Err
- ret
-
- SF_Err:
- Say_Err_Msg Unknown
- call Abort
- Seek_Fragment endp
-
- ;==============================================================
-
- Get_Files endp
-
- ;==============================================================
-
- Select_Subdir proc near
- ; DOS 3.2
- ; Decide whether or not the dirspec. of the file proposed to be restored
- ; matches the pattern from the command line.
- ;
- ; Called with:
- ;
- ; Filespec_Ptr contains the length of the dirspec. portion of the
- ; file(s) proposed to be restored including a trailing but no leading
- ; backslash. If the dirspec. is the root directory its value is 0.
- ;
- ; Rest_Path contains the dirspec. of the file(s) proposed to be
- ; restored including a trailing but no leading backslash. An empty
- ; string indicates the root directory.
- ;
- ; Subdir_Pat_Len contains the length of the directory portion
- ; of the pattern entered on the command line including a trailing but
- ; no leading backslash. A value of zero indicates the root directory.
- ;
- ; CL_Subdir_Pattern contains the directory portion of the pattern
- ; entered from the command line including a trailing but no leading
- ; backslash. An empty string indicates the root directory.
- ;
- ; Cmd_Flags bit 2 set if subdirectories are to be restored, clear
- ; if only files are to be restored.
- ;
- ; Returns:
- ;
- ; Zero Flag set if directory is to be restored, clear if not.
- ;
- mov cx, Subdir_Pat_Len
- cmp cx, Filespec_Ptr ; If the pattern is longer, there
- ja SS_Done ; Cannot be a match.
-
- test Cmd_Flags, RestoreSubs ; /S switch specified?
- jnz SS_Compare ; Yes, proceed with compare.
- cmp cx, Filespec_Ptr ; No, lengths must equal to match.
- jne SS_Done
-
- SS_Compare:
- or cx, cx
- jz SS_Done ; File matched.
- lea si, CL_Subdir_Pattern
- lea di, Rest_Path
- repe cmpsb
- SS_Done:
- ret ; zR = matched, NZ = not matched.
-
- Select_Subdir endp
-
- ;==============================================================
-
- Select_File proc near
- ; DOS 3.2 and 3.3
- ; Decide whether or not the current file should be restored as directed by
- ; the file pattern entered on the command line.
- ;
- ; Called with:
- ;
- ; Rest_Path contains pathspec of file proposed to be restored less
- ; the leading backslash.
- ;
- ; Filespec_ptr contains the offset of the filespec relative to
- ; Rest_Path.
- ;
- ; Rest_Name_Len contains the length of the complete pathspec proposed
- ; to be restored including the "C:\" but not the trailing nul.
- ;
- ; Flags bit 4 set if the previous file fragment was not to be
- ; restored, clear otherwise.
- ;
- ; Flags bit 5 set if the filespec of the previous file fragment
- ; matched the command line pattern and the current pathspec refers
- ; to the same file, clear otherwise.
- ;
- ; dx contains the sequence no. of the current file fragment.
- ;
- ; Returns if file fragment is to be restored:
- ;
- ; Carry Flag clear.
- ;
- ; Flags bit 4 clear.
- ;
- ; Flags bit 5 set.
- ;
- ; Returns if file fragment not to be restored:
- ;
- ; Carry Flag set.
- ;
- ; Flags bit 4 set.
- ;
- cmp dx, 1 ; Release Don't Restore flag and File
- jnz SF_Frag_Pending ; Matched flag for each first fragment.
- and Flags,0ffh-(SkipFile+FileMatched) ; 0CFH
-
- ; Don't restore a fragment for a file whose previous fragments were not
- ; restored.
- SF_Frag_Pending:
- test Flags, SkipFile ; Bit 4 set = Don't Restore File.
- jnz SF_Dont_Restore
-
- test Flags, FileMatched ; Filename matched on previous fragment?
- jnz SF_Restore ; Yes, no need to check again.
- call Match_Filespec ; Restore only files which match
- jc SF_Dont_Restore ; the command line filespec
- call Dangerous_Files ; Don't restore the system files.
- jc SF_Dont_Restore
- or Flags, FileMatched ; Signal for subsequent fragments to
- ; restore this pathspec.
-
- SF_Restore:clc
- ret
-
- SF_Dont_Restore:
- or Flags, SkipFile ; Bit 4 set = Don't Restore.
- stc
- ret
-
- ;==============================================================
-
- Match_Filespec proc near
- ; DOS 3.2 and 3.3
- ; Decide if the filespec of the pathspec proposed to be restored matches that
- ; of the command line pattern.
- ;
- ; Called with:
- ;
- ; CL_File_Pattern contains the command line file pattern to be matched.
- ; It is in the format "MYFILE__.X__" with any '*' wildcard chars.
- ; expanded to the maximum possible number of '?' wildcard chars.
- ;
- ; Returns carry flag clear if a match was made, set if not.
- ;
- cld
- call Extract_Filespec
-
- lea si, CL_File_Pattern
- lea di, Match_File
- mov cx, 12 ; Filename length with embedded '.'.
-
- MF_More:
- jcxz MF_Matched
- repe cmpsb
- je MF_Matched
- cmp byte ptr [si-1], '?'
- je MF_More
- stc
- ret
-
- MF_Matched:clc
- ret
-
- ;==============================================================
-
- Extract_Filespec proc near
- ; DOS 3.2 and 3.3
- ; Extract the filespec from the pathspec. proposed to be restored so that
- ; it is in the form "MYFile__.X__" so that it may be more easily compared
- ; with the pattern specified on the command line.
- lea di, Match_File ; Blank out string with spaces in case
- mov ax, 2020H ; some bytes don't get overwritten.
- mov cx, 6
- rep stosw
-
- lea si, Rest_Path
- add si, Filespec_Ptr ; Point to start of filespec
- lea di, Match_File
- mov cx, Rest_Name_Len ; Get length of filespec in cx.
- sub cx, Filespec_Ptr
- sub cx, 3 ; Allow for "C:\"
- EF_More:
- lodsb
- cmp al, '.' ; Watch for the period.
- jz EF_Ext ; Copy it and the file extension.
- stosb
- loop EF_More
- mov Match_File + 8, '.' ; '.' needed to match string properly.
- ret
-
- EF_Ext:
- lea di, Match_File+8
- stosb
- dec cx
- rep movsb
- ret
- Extract_Filespec endp
-
- ;==============================================================
-
- Match_Filespec endp
-
- ;==============================================================
-
- Dangerous_File macro DC
- local DF_Exit
- ;; Test the filename proposed to be restored against one of the dangerous
- ;; filenames.
- cmp cx, D_File&DC&_Len ;; Filenames can't match if lengths
- jnz DF_Exit ;; aren't equal.
-
- lea si, D_File&DC ;; Compare filenames.
- push cx
- call Dangerous ;; CY = file is dangerous.
- pop cx
- jc DF_Dangerous
- DF_Exit label near
- endm ;; End of macro Dangerous_File.
-
- ;==============================================================
-
- Dangerous_Files proc near
- ; DOS 3.2 and 3.3
- ; Don't allow any files with possible operating system filenames to be
- ; restored to the root directory. Announce the names of any files skipped
- ; over. Return with the carry flag set if the file is to be skipped, clear
- ; otherwise. This rather intimidating code just compares the
- ; file we are about to restore with the names of 5 files known dangerous
- ; to restore, namely IBMBIO.COM IBMDOS.COM IO.SYS MSDOS.SYS and COMMAND.COM
-
- cld
- cmp Filespec_Ptr, 0 ; Is file headed for the root directory?
- jnz DF_OK ; No, File OK to restore.
-
- mov cx, Rest_Name_Len ; Get filename length in cx.
- sub cx, 2 ; Omit "C:\" but add 1 for trailing nul.
- ; Check the filename of the file proposed to be restored to the root directory
- ; to make sure it doesn't have the name of one of the system files. If it
- ; does, return to the calling procedure with carry flag set.
-
- DC = 0 ;; Keep track of which iteration were on.
- rept D_Count ;; D_Count = no. of dangerous files.
- DC = DC + 1 ;; Update iteration counter.
- Dangerous_File %DC
- endm ;; End of repeat block.
-
- DF_OK:
- clc ; File is OK to restore.
- ret
-
- DF_Dangerous:
- stc
- ret
-
- ;==============================================================
-
- Dangerous proc near
- ; DOS 3.2 and 3.3
- ; Compare the filename to which si points with the filename of the file proposed
- ; to be restored. Return to caller with carry flag set if they match, clear
- ; otherwise. The length of the filename to be checked including a trailing nul
- ; is passed to this routine in cx.
- lea di, Rest_Path
- repe cmpsb
- jz D_Dangerous
- clc
- ret
-
- D_Dangerous:stc
- ret
- Dangerous endp
-
- ;==============================================================
-
- Dangerous_Files endp
-
- ;==============================================================
-
- Select_File endp
-
- ;==============================================================
-
- Announce_File proc near
- ; DOS 3.2 and 3.3
- ; If the /P switch is active and the current fragment is the first fragment
- ; in a file, prompt the user whether or not to restore the file. If the current
- ; file fragment is the first fragment in a file containing Read-only, Hidden,
- ; and/or System attributes prompt the user whether or not to
- ; restore the file. If the /P switch is not active and the file has normal
- ; attributes or if the user indicates to restore the file, announce on the
- ; standard output device the drive and full pathspec of the file being
- ; restored. If the file exists in more than one fragment, also announce the
- ; fragment or part number of this fragment.
- ;
- ; Called with:
- ;
- ; Flags bit 0 set if this fragment is the last for the file, clear
- ; otherwise.
- ;
- ; Cmd_Flags bit 0 set if /P switch is active, clear otherwise.
- ;
- ; dx contains the file fragment sequence no. of the current file.
- ;
- ; bl contains the attribute of the file fragment about to be restored.
- ;
- ; Returns:
- ;
- ; Carry Flag and Flags bit 4 set if user indicated not to restore
- ; a file, clear otherwise.
- ;
- push dx ; Save frag. seq. no.
- cmp dx, 1 ; Prompt only on first fragment.
- jnz AF_Restore
- test Cmd_Flags, Prompt_Needed ; Is /P switch in effect?
- jz AF_Attr ; No, skip the prompt.
- push bx ; Save file attribute.
- call Prompt_User ; Get user's decision on restoring file.
- pop bx ; Retrieve file attribute.
- jc AF_No ; NC = yes, CY = no.
-
- AF_Attr:
- test bl, 7 ; Is file Read-only and/or System and/or
- ; hidden?
- jz AF_Restore ; No, skip prompt.
- Say_Err_Msg Special_Attr
- call Prompt_User
- jnc AF_Restore
-
- AF_No:
- pop dx ; Clear stack.
- or Flags, SkipFile ; Bit 4 = Don't restore file.
- stc
- ret
-
- AF_Restore:
- Say_Msg Rest_Name
- pop dx ; Retrieve file frag. seq. no.
- test Flags, LastFrag ; Is this a multi-fragment file?
- jz AF_Part_X ; Yes, announce part no. after name.
- cmp dx, 1 ; Maybe, is frag. no. > 1.
- ja AF_Part_X ; Yes, announce part no.
- clc
- ret
-
- AF_Part_X:
- Patch_Num dx, Part_X+2, 3
- Say_Msg Part_X_Msg
- clc
- ret
-
- ;==============================================================
-
- GetUCChar Proc near
- ; Gets one upper-case char from keyboard
- ; Lower case get converted to upper case
- ; punctuation passed unmolested.
- ; Echos printable chars as letter backspace.
-
- mov ax, 0C08H ; Clear typeahead buffer and get
- int 21H ; filtered no echo
- CMP AL,'a'
- JB FineAsIs
- CMP AL,'z'
- JA FineAsIs
-
- SUB AL,20h ; convert a: to A:
- FineAsIs:
- ; check for displayable char
- CMP AL,32d ; space
- JB NoEcho
- CMP AL,126d ; tilde ~
- JA NoEcho
- MOV EchoChar,AL ; echo upper case chars
- PUSH AX ; save char from destruction
- Say_Err_Msg EchoChar
- POP AX
- NoEcho:
- ret
- GetUCChar ENDP
-
- ;==============================================================
-
- Prompt_User proc near
- ; DOS 3.2 and 3.3
- ; Display on the standard error device the pathspec of the file to be restored
- ; and ask the user to indicate by answering y or n if it should be restored.
- ; Return with carry flag set if he answers N, clear if he answers Y.
- ;
- Say_Err_Msg Prompt_User1
- Say_Err_Msg Rest_Name
- Say_Err_Msg Prompt_User2
- PU_Again:
- Call GetUcChar ; get Y/N
- cmp al, 'Y'
- jne PU1
- Say_Err_Msg CRLF
- clc
- jmp short PU_Done
-
- PU1:
- cmp al, 'N'
- jne PU_Err
- Say_Err_Msg CRLF
- stc
-
- PU_Done:
- ret
-
- PU_Err:
- Say_Err_Msg Beep
- jmp short PU_Again
- Prompt_User endp
-
- ;==============================================================
-
- Announce_File endp
-
- ;==============================================================
-
- Do_One_Chunk proc near
- ; DOS 3.2 and 3.3
- ; Copy the current file fragment to its pathname on the hard disk. If this is
- ; the first fragment of the file, create the pathspec making any needed but
- ; non-existent subdirectories and creating or truncating to zero length the
- ; specified filename. If this is the last fragment for the file, close the
- ; file on the hard disk after copying the fragment.
- ;
- ; Called with:
- ;
- ; Bkp_Hndl contains the handle of the open backup data file with the
- ; file ptr. positioned at the beginning of the file fragment to be
- ; restored, ie at the first byte of data to be copied.
- ;
- ; Out_Hndl contains the handle of the file being restored on the hard
- ; disk if the file has had previous fragments restored, -1 otherwise.
- ;
- ; bl contains the attributes of the file being restored.
- ;
- ; cx contains the file time in DOS dir. format.
- ;
- ; dx contains the file date in DOS directory format.
- ;
- ; bp:si contains the size of the current file fragment.
- ;
- ; Flags bit 0 set if this is the last fragment for the file,
- ; clear if not.
- ;
- ; Returns:
- ;
- ; Out_Hndl contains the handle of the open file being restored on the
- ; hard disk if there are still more fragments to go; otherwise, the
- ; output file has been closed and Out_Hndl contains -1.
- ;
- push cx ; Save file time.
- push dx ; Save file date.
-
- cmp Out_Hndl, -1 ; File will already be open if this is
- ; not a first fragment.
- jnz DOC_Opened
-
- call Open_Out_File ; Create output file on hard disk. bx,
- ; bp, and si may need to be saved if
- ; Open_OUt_File is modified.
- jnc DOC_Opened ; NC = file created successfully.
-
- ; CY = create failed, error code returned in ax.
- cmp ax, 5 ; Access denied?
- jne DOC_Not_RO ; No. bx, bp, and si may need to be
- ; saved if Rid_RO is modified.
- call Rid_RO ; Yes, if file with same pathspec as
- ; Rest_Name exists on hard disk, change
- ; its attributes to normal.
- call Open_Out_File
- jnc DOC_Opened
- call DOC_Unknown ; Unknown error, abort.
-
- DOC_Not_RO:
- cmp ax, 3 ; Path not found?
- jne DOC_Not_Path ; No, path seems OK.
- call Make_Dirs ; Yes, try to create it. May need to
- ; save bx, bp, and si if Make_Dirs
- ; is modified.
- call Open_Out_File
- jnc DOC_Opened
- DOC_Not_Path:
- call DOC_Unknown ; Unknown error, abort.
-
- DOC_Opened:
- call Copy_Fragment
-
- pop dx ; Retrieve file date.
- pop cx ; Retrieve file time.
-
- test Flags, LastFrag ; Only close output file if no more
- jz DOC_Done ; fragments.
- call Close_Out_File
- DOC_Done:
- ret
-
- ;==============================================================
-
- Rid_RO proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; If a file with the same pathspec as the one proposed to be restored already
- ; exists on the hard disk, change its attributes to normal.
- lea dx, Rest_Name
- xor cx, cx ; Use normal attributes.
- mov ax, 4301H ; Function = change file attributes.
- int 21H
- ret
- Rid_RO endp
-
- ;==============================================================
-
- Make_Dirs proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Create the path elements necessary for the pathspec in Rest_Name to exist.
- ; IF a path element cannot be created, assume that a junk file with the same
- ; name as the element exists, attempt to delete it, and try again to create the
- ; path element.
- mov cx, Rest_Name_Len
- sub cx, 4 ; Skip d:\ and first char since first
- ; '\' delimiting a path element can't
- ; occur there.
- lea di, Rest_Name+4 ; Skip over d:\ and first char
- lea dx, Rest_Name ; dx points at path.
- mov al, '\'
- MD_More:
- jcxz MD_Done
- repne scasb ; Scan for a backslash.
- jne MD_Done ; No more path elements to create.
- mov byte ptr [di-1], 0 ; Temporarily change '\' to nul.
- mov ah, 39H ; Function = create subdirectory.
- int 21H ; May fail because of junk file with
- jnc MD_Success ; same name as path. If so, attempt to
- ; delete pathspec and try again.
- mov ah, 41H ; Function = Delete File.
- int 21H
- mov ah, 39H ; Try again.
- int 21H
- MD_Success:
- mov al, '\' ; Replace backslash.
- mov [di-1], al
- jmp short MD_More
- MD_Done:
- ret
- Make_Dirs endp
-
- ;==============================================================
-
- Open_Out_File proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Attempt to open the file to be restored on the hard drive truncating any
- ; existing file to zero length or creating the file if it doesn't exist.
- ; Abort if operation fails because too many files are open.
- ;
- ; Called with:
- ;
- ; Rest_Name contains complete pathspec of file to be restored on
- ; the hard disk.
- ;
- ; bl contains attributes of file to be restored.
- ;
- ; Returns if successful:
- ;
- ; Out_Hndl contains the handle of the successfully opened file on
- ; the hard disk.
- ;
- ; Carry Flag = cleared.
- ;
- ; Returns If Not Successful:
- ;
- ; Carry Flag = set.
- ;
- ; ax contains error code.
- ; 3 = Path not found.
- ; 5 = Access denied.
- ;
- lea dx, Rest_Name ; Point dx to the pathspec of the
- ; file to be restored.
- xor ch, ch ; PUt file attributes in cx.
- mov cl, bl
- or cl, 20H ; Force archive bit on.
- mov ah, 3CH ; Function 3CH=Create or Truncate file.
- int 21H
- jc OOF_Err
- mov Out_Hndl, ax
- ret
-
- OOF_Err:
- cmp ax, 4 ; Too many open files?
- jne OOF_Err1
- Say_Err_Msg Hard_Disk_Trouble ; Cant_Open_OF
- Say_Err_Msg Rest_Name
- Say_Err_Msg Too_Many_Open
- call Abort
-
- OOF_Err1:
- stc
- ret
- Open_Out_File endp
-
- ;==============================================================
-
- Copy_Fragment proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Copy the current file fragment from the backup data file to the hard disk.
- ; If the backup format is DOS 3.3 and this is the last fragment for a file,
- ; make sure the file size is correct.
- ;
- ; Called with:
- ;
- ; Bkp_Hndl contains handle of open backup data file with file ptr.
- ; positioned at the beginning of the data to be restored.
- ;
- ; Out_Hndl contains handle of open file on hard disk with file
- ; ptr. positioned at end-of-file.
- ;
- ; Flags bit 0 set if this is the last fragment for the file, clear
- ; otherwise.
- ;
- ; Format_Flags bit 0 set if the backup is in DOS 3.2 format, clear
- ; otherwise.
- ;
- ; Format_Flags bit 1 set if backup is in DOS 3.3 format, clear
- ; otherwise.
- ;
- ; Want_Size contains the total size of the file in bytes according
- ; to its file record(s) in CONTROL.XXX if the backup is in DOS 3.3
- ; format.
- ;
- ; bp:si contains the size of the file fragment.
- ;
- lea dx, Buffer ; For subsequent reads and writes.
-
- CF_More:
- mov cx, BUFF_SIZE ; Assume at least one buffer full
- clc ; to go.
- cmp si, cx ; Check cx against low word of bytes
- ; remaining to be copied.
- jnc CF_Cpy ; If NC assumption is correct.
- ; Proceed with copy.
-
- or bp, bp ; If Hi byte isn't 0, assumption is
- jnz CF_Cpy ; correct.
-
- mov cx, si ; Otherwise, copy remaining bytes.
- CF_Cpy:
- mov bx, Bkp_Hndl
- mov ah, 3FH ; Function = Read.
- int 21H
- jc CF_Err_Unknown ; Abort if trouble.
- cmp cx, ax ; Read o.k.?
- jne CF_Err_In ; Abort if not.
-
- mov bx, Out_Hndl ; Write this chunk.
- mov ah, 40H ; Function 40H = Write.
- int 21H
- jc CF_Err_Unknown ; Abort if trouble.
- cmp cx, ax ; Write o.k.?
- jne CF_Err_Out ; Abort if not.
-
- sub si, cx ; Subtract bytes read from total
- sbb bp, 0 ; and go back if there's more.
- jnz CF_More
- or si, si
- jnz CF_More
-
- test Format_Flags, DOS32 ; Is backup DOS 3.2 format?
- jnz CF_Done ; Yes, can't check file size.
- test Flags, LastFrag ; Is this the last chunk.
- jz CF_Done ; No, return to caller.
- Comment |
- The file size may be determined by using the Move File Ptr. function (ah=42H)
- to seek an offset of 0 bytes relative to EOF. (al=2). Note that the file
- handle is already in bx.
- | ; End of comment.
- mov ax, 4202H ; Determine if file size is correct.
- xor dx, dx ; Low byte of offset.
- xor cx, cx ; High byte of offset.
- int 21H ; dx:ax = returned offset.
- jc CF_Err_Unknown
-
- cmp ax, word ptr Want_Size ; Correct size returned for low word?
- jnz CF_Wrong_Size ; No.
- cmp dx, word ptr Want_Size+2; Correct size returned for high word?
- jnz CF_Wrong_Size ; No.
-
- CF_Done:
- ret
-
- CF_Wrong_Size:
- call Say_Cant_Restore
- Say_Err_Msg Floppy_Trouble ; Bad_Size
- call Abort
-
- CF_Err_In:
- call Say_Cant_Restore
- Say_Err_Msg In_IO_Err
- call Abort
-
- CF_Err_Out:
- call Say_Cant_Restore
- Say_Err_Msg Out_IO_Err
- call Abort
-
- CF_Err_Unknown:
- call Say_Cant_Restore
- Say_Err_Msg Unknown
- call Abort
-
- ;==============================================================
-
- Say_Cant_Restore proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Print common part of error messages including the pathspec of the
- ; unsuccessfully restored file.
- Say_Err_Msg Cant_Restore
- Say_Err_Msg Rest_Name
- Say_Err_Msg CRLF
- ret
- Say_Cant_Restore endp
-
- ;==============================================================
-
- Copy_Fragment endp
-
- ;==============================================================
-
- Close_Out_File proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Close the file which has been restored on the hard disk. Abort if not
- ; successful. Also set the time and date stamp to that stored in the backup.
- ;
- ; Called with:
- ;
- ; Out_Hndl contains handle of open output file.
- ;
- ; dx contains file date from backup in DOS dir. format.
- ;
- ; cx contains file time from backup in DOS dir. format.
- ;
- ; Returns:
- ;
- ; Out_Hndl contains -1.
- ;
- mov bx, Out_Hndl
- mov ax, 5701H ; Function 57H with al=1 = Set File
- int 21H ; time and date.
-
- mov ah, 3EH ; Function 3EH=Close File.
- int 21H
- jc COF_Err
- mov Out_Hndl, -1 ; Indicates that file is closed.
- Say_Msg Restored
- inc Rest_Count ; UPdate count of files restored.
- ret
-
- COF_Err:
- Say_Err_Msg Hard_Disk_Trouble ; Cant_Close_OF
- Say_Err_Msg Rest_Name
- call Abort
- Close_Out_File endp
-
- ;==============================================================
-
- DOC_Unknown proc near
- ; DOS 3.2 and 3.3
- ; nested in Do_One_Chunk
- ; Restore failed for unknown reason, print error message and abort.
- Say_Err_Msg Hard_Disk_Trouble ; Cant_Open_OF
- Say_Err_Msg Rest_Name
- Say_Err_Msg CRLF
- Say_Err_Msg Unknown
- call Abort
- DOC_Unknown endp
-
- ;==============================================================
-
- Do_One_Chunk endp
-
- ;==============================================================
-
- Close_Bkp_File proc near
- ; DOS 3.3
- ; CLOSE BACKUP.XXX
- ; Close the backup data file and reset its handle to a value of -1. Bkp_Hndl
- ; contains the handle of the open backup data file.
- mov bx, Bkp_Hndl
- mov ah, 3EH ; Function 3EH=Close File.
- int 21H
- jc CBF_Err
- mov Bkp_Hndl, -1 ; Indicates that file is closed.
- ret
-
- CBF_Err:
- Say_Err_Msg Floppy_Trouble ; Cant_Close_BF
- call Abort
- Close_Bkp_File endp
-
- ;==============================================================
-
- Close_Ctl_File proc near
- ; DOS 3.3
- ; CLOSE CONTROL.XXX
- ; Close the backup control or ID file and set its handle to -1. Abort if error.
- ; Ctl_Hndl contains the handle of the open backup control or ID file.
- mov bx, Ctl_Hndl
- mov ah, 3EH ; Function 3EH=Close File.
- int 21H
- jc CCF_Err
- mov Ctl_Hndl, -1 ; Indicates that file is closed.
- ret
-
- CCF_Err:
- Say_Err_Msg Floppy_Trouble ; Cant_Close_CF
- call Abort
- Close_Ctl_File endp
-
- ;==============================================================
-
- Abort_Retry proc near
- ; DOS 3.2 and 3.3
- ; Prompt user to enter A for abort or R for retry. Terminate if abort or
- ; return to caller if retry.
- Say_Err_Msg AR_Msg ; Prompt on standard error device.
- AR_Again:
- Call GetUcChar ; get A/R
- cmp al, 'A'
- jne AR1
- call Abort
-
- AR1:
- cmp al, 'R'
- jne AR_Err
- Say_Err_Msg CRLF
- ret
-
- AR_Err:
- Say_Err_Msg Beep
- jmp short AR_Again
- Abort_Retry endp
-
- ;==============================================================
-
- Abort_Retry_Ignore proc near
- ; DOS 3.2 and 3.3
- ; Prompt user to enter A for abort, R for retry, or I for Ignore. Terminate
- ; if abort or return to caller with carry flag set if retry, clear if ignore.
- Say_Err_Msg ARI_Msg ; Prompt on standard error device.
- ARI_Again:
- Call GetUcChar ; get A/R/I
- cmp al, 'A'
- jne ARI1
- call Abort
-
- ARI1:
- cmp al, 'I'
- jne ARI2
- Say_Err_Msg CRLF
- clc
- jmp short ARI_Done
-
- ARI2:
- cmp al, 'R'
- jne ARI_Err
- Say_Err_Msg CRLF
- stc
-
- ARI_Done:
- ret
-
- ARI_Err:
- Say_Err_Msg Beep
- jmp short ARI_Again
- Abort_Retry_Ignore endp
-
- ;==============================================================
-
- Abort proc near
- ; DOS 3.2 3.3
- ; Print message with count of successfully restored files and exit with return
- ; code of 4.
- Patch_Num Rest_Count, Aborted_Count+4, 5
- Say_Msg Aborted
- mov ax, 4C04H ; Function = exit with return code of 4.
- int 21H
- Abort endp
-
- ;==============================================================
-
- Bye proc near
- ; DOS 3.2 and 3.3
- ; Print sign-off message with count of files restored.
- ; Terminate with return code of 0. If no files were restored, print warning
- ; message and terminate with return code of 1.
- Patch_Num Rest_Count, DM_Count+4, 5
- Say_Msg Done_Msg
- cmp Rest_Count, 0 ; No files restored?
- je B_None ; Yes, print warning and exit.
-
- mov ax, 4C00H ; No, files were restored.
- int 21H ; Function = exit with return code of 0.
-
- B_None:
- Say_Err_Msg None_Restored
- mov ax, 4C01H ; Function = exit with return code of 1.
- int 21H
- Bye endp
-
- ;==============================================================
-
- Restore_File proc near
- ; DOS 3.2
- ; Decide if the file currently described in the DTA is a valid file fragment and
- ; it should be restored. Restore it if it should. Return with carry flag set
- ; if the diskette is determined to have a scrambled directory or to be from
- ; another set, clear otherwise.
- ;
- call Bypass_Bkp_ID ; Don't restore BACKUPID.@@@
- jc RF_Skip ; CY = current file is BACKUPID.@@@.
- call Open_Bkp_File
- call Get_Preamble
- call Copy_Pathspec
- jc RF_Wrong_Set
- call Select_Subdir ; Does subdir match command line?
- jnz RF_Bypass ; NO, skip this pathspec.
- call Scramble_Check
- jc RF_Wrong_Set
-
- mov dx, Buffer.P_Frag_Seq ; Pass file fragment no. in dx.
- call Select_File ; Decide if file should be restored.
- jc RF_Bypass ; CY = don't restore file.
- mov dx, Buffer.P_Frag_Seq ; Pass file frag. seq. no. in dx.
- mov bl, ds:DTA.DS_Attr ; Pass file attribute in bl.
- call Announce_File
- jc RF_Bypass ; CY = User answered no to restore
- ; prompt.
-
- ; Copy over one fragment.
- mov bl, ds:DTA.DS_Attr ; Pass file attribute in bl.
- mov cx, ds:DTA.DS_Time ; Pass file time in cx.
- mov dx, ds:DTA.DS_Date ; File date in dx.
- ; Pass file fragment size in bp:si.
- mov si, word ptr ds:DTA.DS_Size
- mov bp, word ptr ds:DTA.DS_Size+2
- sub si, 128 ; Allow for preamble.
- sbb bp, 0
- call Do_One_Chunk
-
- RF_Bypass:
- call Close_Bkp_File
- RF_Skip:
- clc ; NC = all is in order.
- ret
-
- RF_Wrong_Set:
- ; Diskette is either from another set or its dir. is scrambled.
- call Close_Bkp_File
- Say_Err_Msg Floppy_Trouble ; Scrambled
- call Abort_Retry
- and Flags, 0ffh - LastDisk ; 0FDH
- ; Clear last diskette flag so OM_Main
- ; will prompt for another diskette.
- dec Want_Seq
- stc
- ret
- ; actual Restore_File endp contains nested procs
-
- ;==============================================================
-
- Bypass_Bkp_ID proc near
- ; DOS 3.2
- ; nested in Restore_File
- ; Return CY if file currently in DTA is BACKUPID.@@@ or a subdirectory, NC
- ; otherwise. We don't want to touch a DOS 3.3 diskette in
- ; middle of DOS 3.3 restore.
- test ds:DTA.DS_Attr, 10H ; Is current file a subdir?
- jnz BBI_Bypass ; Yes, skip it.
-
- mov cx, 12 ; Length of BACKUPID.@@@.
- lea si, Bkp_ID_Name+3 ; Bypass d:\.
- lea di, ds:DTA.DS_Name ; Point at filename in DTA.
- repe cmpsb ; Is this BACKUPID.@@@?
- jz BBI_Bypass ; Yes, skip this file.
- clc ; No, return NC.
- ret
-
- BBI_Bypass:
- stc ; Return CY so file will be skipped.
- ret
- Bypass_Bkp_ID endp
-
- ;==============================================================
-
- Get_Preamble proc near
- ; DOS 3.2
- ; Read 128 byte preamble from the open backup file proposed to be restored.
- mov bx, Bkp_Hndl ; Handle of backup file currently
- ; being considered.
- mov cx, 128 ; Length of preamble.
- lea dx, Buffer ; ds:dx points at buffer.
- mov ah, 3FH ; Function = read.
- int 21H
- jc GP_Err
- cmp cx, ax ; Correct no. of bytes read?
- jnz GP_Err
- ret
-
- GP_Err:
- Say_Err_Msg Unknown
- call Abort
- Get_Preamble endp
-
- ;==============================================================
-
- Copy_Pathspec proc near
- ; DOS 3.2
- ; nested in Restore_File
- ; Copy the pathspec proposed to be restored out of the buffer into Rest_Name.
- ; Calculate the total length of the pathspec including the drive but not the
- ; terminating nul and the offset of the filename relative to Rest_Path. If the
- ; new fragment is a continuation of the last file, do not copy its pathspec but
- ; make sure it matches the old one exactly and return CY if not.
- ;
- ; Called with:
- ;
- ; Buffer contains the preamble of the file proposed to be restored.
- ;
- ; Flags bit 1 set if this fragment should be the beginning of a new
- ; file, clear otherwise.
- ;
- ; Flags bit 3 set if this is the first fragment on a diskette accepted
- ; out of sequence, clear otherwise.
- ;
- ; Rest_Name contains the complete nul terminated pathspec including
- ; drive specification of the last fragment processed if any.
- ;
- ; Rest_Name_Len contains the length of the pathspec of the previously
- ; processed fragment if any including the drive but not the trailing
- ; nul.
- ;
- ; Filespec_Ptr contains the offset of the filename of the previously
- ; processed fragment relative to Rest_Path if any.
- ;
- ; Returns if successful:
- ;
- ; Rest_Name contains the complete pathspec of the new fragment
- ; proposed to be restored with any slashes used as path separators
- ; converted to backslashes, i.e. MS DOS 3.2 uses slashes instead of
- ; backslashes for path separators in the BACKUP preambles.
- ;
- ; Rest_Name_Len contains the length of the new pathspec including the
- ; drive but not the trailing nul.
- ;
- ; Filespec_Ptr contains the offset of the filename in the new pathspec
- ; relative to Rest_path.
- ;
- ; Carry Flag = clear.
- ;
- ; Returns if diskette dir. scrambled or diskette from another set:
- ;
- ; Rest_Name, Rest_Name_Len and Filespec_Ptr as on entry.
- ;
- ; Carry Flag = set.
- ;
- lea si, Buffer.P_Hard_Name+1; Skip leading backslash.
- lea di, Rest_Path
- xor ch, ch
- mov cl, Buffer.P_Hard_Len ; Get length of string to process in cx.
- dec cx ; Don't bother with leading backslash.
- jle CP_Err1 ; Nul pathspecs. should never occur.
- cld
-
- test Flags, WrongOk ; Diskette out of sequence?
- jnz CP_Copy ; Yes, copy pathspec
- test Flags, LastFrag ; Last file continued?
- jnz CP_Copy ; No, copy new pathspec
-
- CP_More:
- cmp byte ptr [si], '/' ; Convert slashes to backslashes before
- jnz CP_Compare ; comparison.
- mov byte ptr [si], '\' ; Convert '/' to '\'.
- CP_Compare:
- cmpsb
- jnz CP_Err2 ; New pathspec is different.
- loop CP_More
- clc ; Return NC = all is in order.
- ret
-
- CP_Copy:
- lodsb ; Copy pathspec
- cmp al, '/' ; Convert slashes to backslashes.
- jnz CP_Not_Slash
- mov al, '\'
- CP_Not_Slash:
- stosb
- loop CP_Copy
-
- mov cl, Buffer.P_Hard_Len ; Calculate length of pathspec
- inc cx ; Add 2 for d: and subtract 1 for nul.
- mov Rest_Name_Len, cx
-
- mov al, '\' ; Calculate offset of filespec
- dec di ; Point at trailing nul of Rest_Name.
- std ; Scan backward for first '\'.
- repne scasb
- jcxz CP_Err1 ; Should never get that far.
- dec cx
- mov Filespec_Ptr, cx
- cld
-
- clc ; NC = all is in order.
- ret
-
- CP_Err1:
- Say_Err_Msg Unknown
- call Abort
-
- CP_Err2:
- stc ; Return CY meaning dir. is scrambled or
- ret ; diskette is from another set.
- Copy_Pathspec endp
-
- ;==============================================================
-
- Scramble_Check proc near
- ; DOS 3.2
- ; Nested in Restore_file
- ; Check for file fragments which are out of sequence either because the current
- ; diskette is from another set or because the diskette directory has been
- ; scrambled. Return CY if there's a problem, NC otherwise. If all is well,
- ; this routine also resets the diskette out of sequence and new diskette flags,
- ; calculates the next fragment sequence no., and sets the last fragment flag
- ; according to the current file fragment.
- mov dx, Want_Frag_Seq ; Save Want_Frag_Seq.
- cmp dx, Buffer.P_Frag_Seq ; Is this what was expected?
- je SC_OK ; Yes, return to caller.
-
- test Flags, WrongOk ; Was this diskette accepted out of
- ; sequence?
- jnz SC_OK ; Yes, no problem.
- stc ; CY = dir. is scrambled or
- ret ; diskette is from another set.
-
- SC_OK:
- and Flags, 0ffh-(WrongOk+NewDisk+LastFrag)
- ; 0f2h
- ; Clear diskette out of sequence, new
- ; diskette, and last fragment flags.
- mov ax, Buffer.P_Frag_Seq ; Calculate next sequence no.
- inc ax
- cmp Buffer.P_Last, 0 ; Is this last fragment of current file?
- je SC_More ; No.
- mov ax, 1 ; Yes, reset fragment sequence no.
- or Flags, LastFrag ; and set last fragment flag.
- SC_More:
- mov Want_Frag_Seq, ax
-
- clc ; NC = all is in order.
- ret
-
- Scramble_Check endp
-
- ;==============================================================
-
- Restore_File endp
-
- ;==============================================================
-
- Initial_Checks proc near
-
- ; Make sure DOS version is 2.0 or later and that there is sufficient memory to
- ; run RESTORE.
- mov ah, 30H ; Function = Get DOS Version.
- int 21H
- or ax, ax ; Abort if DOS Version below 2.0.
- jnz RM_Ver_OK
- lea dx, Wrong_Ver
- mov ah, 9 ; Function = Write String to Console.
- int 21H ; Use DOS 1.0 method.
- ret
-
- RM_Ver_OK:
- cmp sp, 100H + offset Buffer + BUFF_SIZE + STACK_SIZE
- ja RM_Enough_Mem ; Abort if insufficient memory.
- Say_Err_Msg Insufficient
- call Abort
-
- RM_Enough_Mem:
- ret
- Initial_Checks EndP
-
- ;==============================================================
-
- Old_Main proc near
- ; DOS 3.2
- ; Perform the restore operation using the DOS 3.2 format.
- Say_Msg Old_Bkp_Format
-
- OM_Next_Disk:
- lea dx, All_Pattern ; Get first file to restore.
- Comment |
- Rumor has it that MS DOS 3.2 might not return all normal files unless subdirs.
- are requested as well. Therefore, subdirs are included in the search here and
- filtered out later by Bypass_Bkp_ID.
- | End of comment.
- mov cx, 16H ; Include system and hidden files. Bits
- ; for RO. and Arc. have no effect, these
- ; bits do not exclude a file from being
- ; "normal".
- mov ah, 4EH ; Function = Search For First.
- OM_Next:
- int 21H ; Get next file.
- jc OM_No_More ; CY = no more files on this diskette.
- call Restore_File
- jc OM_No_More ; This diskette was rejected.
- mov ah, 4FH ; Function = Search For Next.
- jmp short OM_Next ; Get next file to restore.
-
- OM_No_More:
- test Flags, LastDisk ; Is this the last diskette?
- jnz OM_Done ; Yes, exit.
- CALL Get_Next_Disk ; No, get next diskette of set.
- jmp OM_Next_Disk
-
- OM_Done:
- call Bye ; Return to DOS.
- Old_Main endp
-
- ;==============================================================
- ;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
- ; M A I N L I N E R O U T I N E
- ;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
- ;==============================================================
-
- Restore_Main proc near
- ; DOS 3.3 and 3.2 (most of 3.2 handled by Old_Main)
- Call Initial_Checks ; Check DOS version and for sufficient
- ; memory.
- call Parse ; parse command line.
- test Cmd_Flags, Quietly ; /Q switch specified?
- jnz RM_Quiet ; Yes, skip banner.
- Say_Msg Banner
- Call Strike_Any_Key
- RM_Quiet:
- call Get_Next_Disk
- test Format_Flags, DOS32 ; Is this set in old backup format?
- jnz Old_Main ; Yes, do DOS 3.2 restore.
- ; No, proceed with DOS 3.3 restore.
- Say_Msg New_Bkp_Format
-
- RM_More:
- call Open_Ctl_File
- call Open_Bkp_File
- call Process_Hdr
- call Get_Subdir ; CY means that the continuation
- jc RM_Again ; of a file on this diskette had a
- ; different dirspec. than the previous
- ; fragment, probably indicating the
- ; diskette is from another set.
- call Close_Bkp_File
- call Close_Ctl_File
-
- test Flags, LastDisk ; Is this the last diskette?
- jnz RM_Done ; If so, exit to DOS.
- RM_Again:
- call Get_Next_Disk
- jmp RM_More ; Go back for more.
-
- RM_Done:
- call Bye ; Terminate with return code of 0.
-
- Restore_Main endp
-
- ;==============================================================
-
- even
-
- Buffer label byte ; Buffer for disk I/O. Will actually be
- ; Buffer BUFF_SIZE dup (?).
- ; we place buffer here
- ; it won't take space in
- ; load module.
- Code ends
- end Start
-