summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/RESTORE
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/RESTORE
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/RESTORE')
-rw-r--r--v4.0/src/CMD/RESTORE/DIRECT.H26
-rw-r--r--v4.0/src/CMD/RESTORE/MAKEFILE108
-rw-r--r--v4.0/src/CMD/RESTORE/MESSAGES.INC1
-rw-r--r--v4.0/src/CMD/RESTORE/RESTORE.C240
-rw-r--r--v4.0/src/CMD/RESTORE/RESTORE.LNK17
-rw-r--r--v4.0/src/CMD/RESTORE/RESTORE.SKL46
-rw-r--r--v4.0/src/CMD/RESTORE/RESTPARS.C1002
-rw-r--r--v4.0/src/CMD/RESTORE/RESTPARS.H119
-rw-r--r--v4.0/src/CMD/RESTORE/RT.H272
-rw-r--r--v4.0/src/CMD/RESTORE/RT1.H273
-rw-r--r--v4.0/src/CMD/RESTORE/RT2.H136
-rw-r--r--v4.0/src/CMD/RESTORE/RTDO.C376
-rw-r--r--v4.0/src/CMD/RESTORE/RTDO1.C420
-rw-r--r--v4.0/src/CMD/RESTORE/RTFILE.C598
-rw-r--r--v4.0/src/CMD/RESTORE/RTFILE1.C456
-rw-r--r--v4.0/src/CMD/RESTORE/RTNEW.C244
-rw-r--r--v4.0/src/CMD/RESTORE/RTNEW1.C627
-rw-r--r--v4.0/src/CMD/RESTORE/RTOLD.C266
-rw-r--r--v4.0/src/CMD/RESTORE/RTOLD1.C657
-rw-r--r--v4.0/src/CMD/RESTORE/RTT.C409
-rw-r--r--v4.0/src/CMD/RESTORE/RTT1.C79
-rw-r--r--v4.0/src/CMD/RESTORE/RTT2.C488
-rw-r--r--v4.0/src/CMD/RESTORE/RTT3.C619
-rw-r--r--v4.0/src/CMD/RESTORE/WRWDEFS.H77
-rw-r--r--v4.0/src/CMD/RESTORE/_MSGRET.ASM242
-rw-r--r--v4.0/src/CMD/RESTORE/_PARSE.ASM115
26 files changed, 7913 insertions, 0 deletions
diff --git a/v4.0/src/CMD/RESTORE/DIRECT.H b/v4.0/src/CMD/RESTORE/DIRECT.H
new file mode 100644
index 0000000..aba9076
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/DIRECT.H
@@ -0,0 +1,26 @@
1/*
2 * direct.h
3 *
4 * This include file contains the function declarations for the library
5 * functions related to directory handling and creation.
6 *
7 * Copyright (C) 1988 Microsoft Corporation
8 *
9 */
10
11/* function declarations for those who want strong type checking
12 * on arguments to library function calls
13 */
14
15#ifdef LINT_ARGS /* arg. checking enabled */
16
17int chdir(char *);
18char *getcwd(char *, int);
19int mkdir(char *);
20int rmdir(char *);
21
22#else
23
24extern char *getcwd();
25
26#endif /* LINT_ARGS */
diff --git a/v4.0/src/CMD/RESTORE/MAKEFILE b/v4.0/src/CMD/RESTORE/MAKEFILE
new file mode 100644
index 0000000..ba67431
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/MAKEFILE
@@ -0,0 +1,108 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12map =..\..\mapper
13here =..\cmd\restore
14
15all: not_file restore.com
16
17#-------BUILD MAPPER ----------------
18not_file : makefile #Always perform these steps!
19 cd $(map)
20 nmake
21 cd $(here)
22
23
24_parse.obj : _parse.asm \
25 makefile \
26 $(inc)\parse.asm \
27 $(inc)\psdata.inc
28
29restore.ctl : restore.skl \
30 makefile \
31 $(msg)\$(COUNTRY).msg
32
33
34_msgret.obj: _msgret.asm \
35 makefile \
36 restore.ctl \
37 restore.cl1 \
38 $(inc)\msgserv.asm \
39 $(inc)\sysmsg.inc
40
41
42restore.obj : restore.c rt.h rt1.h rt2.h restpars.h makefile \
43 $(hinc)\comsub.h $(hinc)\doscalls.h \
44 $(hinc)\error.h
45
46rtt1.obj : rtt1.c rt.h rt1.h rt2.h restpars.h makefile \
47 $(hinc)\comsub.h $(hinc)\doscalls.h \
48 $(hinc)\error.h
49
50rtt3.obj : rtt3.c rt.h rt1.h rt2.h restpars.h makefile \
51 $(hinc)\comsub.h $(hinc)\doscalls.h \
52 $(hinc)\error.h
53
54rtdo.obj : rtdo.c rt.h rt1.h rt2.h restpars.h makefile \
55 $(hinc)\comsub.h $(hinc)\doscalls.h \
56 $(hinc)\error.h
57
58rtdo1.obj : rtdo1.c rt.h rt1.h rt2.h restpars.h makefile \
59 $(hinc)\comsub.h $(hinc)\doscalls.h \
60 $(hinc)\error.h
61
62rtnew.obj : rtnew.c rt.h rt1.h rt2.h restpars.h makefile \
63 $(hinc)\comsub.h $(hinc)\doscalls.h \
64 $(hinc)\error.h
65
66rtnew1.obj : rtnew1.c rt.h rt1.h rt2.h restpars.h makefile \
67 $(hinc)\comsub.h $(hinc)\doscalls.h \
68 $(hinc)\error.h
69
70rtold.obj : rtold.c rt.h rt1.h rt2.h restpars.h makefile \
71 $(hinc)\comsub.h $(hinc)\doscalls.h \
72 $(hinc)\error.h
73
74rtold1.obj : rtold1.c rt.h rt1.h rt2.h restpars.h makefile \
75 $(hinc)\comsub.h $(hinc)\doscalls.h \
76 $(hinc)\error.h
77
78rtfile.obj : rtfile.c rt.h rt1.h rt2.h restpars.h makefile \
79 $(hinc)\comsub.h $(hinc)\doscalls.h \
80 $(hinc)\error.h
81
82rtfile1.obj : rtfile1.c rt.h rt1.h rt2.h restpars.h makefile \
83 $(hinc)\comsub.h $(hinc)\doscalls.h \
84 $(hinc)\error.h
85
86restpars.obj : restpars.c rt.h rt1.h rt2.h restpars.h makefile \
87 $(hinc)\comsub.h $(hinc)\doscalls.h \
88 $(hinc)\error.h
89
90restore.com: restore.obj \
91 restpars.obj \
92 rtdo.obj \
93 rtdo1.obj \
94 rtfile.obj \
95 rtfile1.obj \
96 rtnew.obj \
97 rtnew1.obj \
98 rtold.obj \
99 rtold1.obj \
100 rtt1.obj \
101 rtt3.obj \
102 restore.lnk \
103 _msgret.obj \
104 _parse.obj \
105 $(map)\mapper.lib
106 link @restore.lnk
107 convert restore.exe restore.com
108 erase restore.exe
diff --git a/v4.0/src/CMD/RESTORE/MESSAGES.INC b/v4.0/src/CMD/RESTORE/MESSAGES.INC
new file mode 100644
index 0000000..fbc11bc
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/MESSAGES.INC
@@ -0,0 +1 @@
include restmsg.inc \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RESTORE.C b/v4.0/src/CMD/RESTORE/RESTORE.C
new file mode 100644
index 0000000..e60288f
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RESTORE.C
@@ -0,0 +1,240 @@
1
2/*  0 */
3
4/**************************************************************************/
5/*
6/* MODULE NAME : RESTORE utility
7/*
8/* SOURCE FILE NAME: RESTORE.C
9/*
10/* DESCRIPTIVE NAME : Restore one or more backed-up files from a
11/* disk to another disk
12/*
13/* FUNCTION: Restore files saved by BACKUP utility to their
14/* destination disk. This utility will be able to identify
15/* which of the two backup formats was used and to do the
16/* restore accordingly.
17/*
18/* NOTES: This RESTORE utility recognize two data formats:
19/* 1. The data format used by BACKUP utility of 3.2 and before.
20/* 2. The data format used by BACKUP utility of 3.3 and above,
21/* and also used by CP/DOS 1.0 and above.
22/*
23/* DEPENDENCY:
24/* This utility has a dependency on the BACKUP utility to
25/* perform file backup correctly using the data structure
26/* agreed on.
27/*
28/* RESTRICTION:
29/* This utility is able to restore the files which are previously
30/* backup by the BACKUP utility only.
31/*
32/* ENTRY POINT: Main
33/*
34/* INPUT: (PARAMETERS)
35/*
36/* COMMAND SYNTAX:
37/* [d:][path]Restore d: [d:][path][filename][.ext]
38/* [/S] [/P] [/B:date] [/A:date] [/E:time][/L:time][/M] [/N]
39/*
40/* Parameters:
41/* The first parameter you specify is the drive designator of
42/* the disk containing the backed up files. The second
43/* parameter is the a filespec indicating which files you want
44/* to restore.
45/* Switches:
46/* /S - Restore subdirectories too.
47/* /P - If any hidden or read-only files match the filespec,
48/* prompt the user for permission to restore them.
49/* /B - Only restore those files which were last Revised on or
50/* before the given date.
51/* /A - Only restore those files which were last Revised on or
52/* after the given date.
53/* /E - Only restore those files which were last Revised at or
54/* earlier then the given time.
55/* /L - Only restore those files which were last Revised at or
56/* later then the given time.
57/* /M - Only restore those files which have been Revised since
58/* the last backup.
59/* /N - Only restore those files which no longer exist on the
60/* destination disk.
61/*
62/* EXIT-ERROR:
63/* The restore program sets the ERRORLEVEL in the following manner:
64/*
65/* 0 Normal completion
66/* 1 No files were found to backup
67/* 2 Some files not restored due to sharing conflict
68/* 3 Terminated by user
69/* 4 Terminated due to error
70/*
71/*
72/* SOURCE HISTORY:
73/*
74/* Modification History:
75/*
76/* Code added in DOS 3.3 to allow control file > 64k commented as:
77/* /* !wrw */
78/*
79/* ;AN000; Code added in DOS 4.0
80/* ;AN000;2 Support for APPEND /X deactivation
81/* ;AN000;3 Support for Extended Attributes
82/* ;AN000;4 Support for PARSE service routines
83/* ;AN000;5 Support for code page file tags
84/* ;AN000;6 Support for MESSAGE retriever
85/* ;AN000;8 Eliminate double prompting on single drive systems
86/* ;AN000;9 Fix for termination on "Unable to MKDIR"
87/* ;AN000;10 Fix for p1620
88/* ;AN001; Add CR, LF to end of command line
89/* ;AN002; Make parser errors display the offending parameter
90/* ;AN003; Only disallow restore of system files in ROOT !!
91/* ;AN004; Fix parser
92/* ;AN005; Replace COM_STRRCHR dbcs routine, fixes p5029
93/***************** END OF SPECIFICATION *********************************/
94
95#include "rt.h"
96#include "rt1.h"
97#include "rt2.h"
98#include "restpars.h" /*;AN000;4*/
99#include "dos.h" /*;AN000;2*/
100#include "comsub.h" /* common subroutine def'n */
101#include "doscalls.h"
102#include "error.h"
103
104
105BYTE destddir[MAXPATH+3] = {'\0'};
106BYTE srcddir[MAXPATH+3] = {'\0'};
107BYTE rtswitch=0;
108BYTE control_flag=0;
109BYTE control_flag2=0;
110BYTE *buf_pointer;
111
112/*=============================*/
113BYTE srcd; /*;AN000;4*/
114BYTE destd; /*;AN000;4*/
115BYTE inpath [MAXPATH]; /*;AN000;*/
116BYTE infname [MAXFNAME]; /*;AN000;*/
117BYTE infext [MAXFEXT]; /*;AN000;*/
118BYTE infspec [MAXFSPEC]; /*;AN000;*/
119/*=============================*/
120/*---------------------------------------*/
121/*- */
122/*- Data structures for the PARSER */
123/*- */
124/*---------------------------------------*/
125
126struct subst_list sublist; /*;AN000;6 Message substitution list */
127char response_buff[5]; /*;AN000;6 User response buffer *//*;AN000;6*/
128
129BYTE append_indicator = 0xff; /*;AN000;2 Indicates the support for APPEND /X is active */
130WORD original_append_func; /*;AN000;2 APPEND functions on program entry*/
131struct timedate td;
132
133/***************** START OF SPECIFICATION *********************************/
134/*
135/* SUBROUTINE NAME : Main
136/*
137/* DESCRIPTIVE NAME : Main routine for RESTORE utility
138/*
139/* FUNCTION: Main routine does the following:
140/* 1. Verifies the DOS version
141/* 2. Validate the input command line
142/* 3. Calls dorestore to do the file restore.
143/*
144/* NOTES:
145/*
146/* ENTRY POINT: Main
147/* Linkage: main((argc,argv)
148/*
149/* INPUT: (PARAMETERS)
150/* argc - number of arguments
151/* argv - array of pointers to arguments
152/*
153/* EFFECTS: rtswitch is changed to reflect the switches passed.
154/*
155/********************** END OF SPECIFICATIONS *******************************/
156void main(argc,argv) /* wrw! */
157 int argc;
158 char *argv[];
159{
160 WORD retcode;
161 union REGS inregs,outregs; /*AN000*/
162 WORD i; /*loop counter */
163 WORD j; /*arrary subcript */
164 BYTE *c;
165 DWORD drive_map;
166 DWORD prev_address;
167 WORD prev_action;
168
169/**********************************/
170/** PRELOAD MESSAGES **/
171/**********************************/
172 sysloadmsg(&inregs,&outregs); /*;AN000;6 Preload messages */
173 if (outregs.x.cflag & CARRY) /*;AN000;6 If there was an error */
174 { /*;AN000;6*/
175 sysdispmsg(&outregs,&outregs); /*;AN000;6 Display the error message */
176 exit_routine(UNEXPECTED); /*;AN000;6 and terminate */
177 } /*;AN000;6*/
178
179
180/*********************************************/
181/* Parse the drive and file name entered */
182/*********************************************/
183 parse_command_line /*;AN000;4*/
184 ( /*;AN000;4*/
185 argc, /*;AN000;4*/
186 argv /*;AN000;4*/
187 ); /*;AN000;4*/
188
189/*********************************************/
190/* Make sure APPEND /X is not active */
191/*********************************************/
192 check_appendX(); /*;AN000;2 */
193
194
195/*********************************************/
196/* Take control of Control Break Interrupt */
197/*********************************************/
198 retcode = DOSSETSIGHANDLER
199 (
200 (void far *)signal_handler_routine, /* Signal handler address */
201 (DWORD far *)&prev_address, /* Address of previous handler */
202 (unsigned far *)&prev_action, /* Address of previous action */
203 (unsigned)INSTALL_SIGNAL, /* Indicate request type */
204 (unsigned)CTRL_C /* Signal number */
205 );
206
207 retcode = DOSSETSIGHANDLER
208 (
209 (void far *)signal_handler_routine, /* Signal handler address */
210 (DWORD far *)&prev_address, /* Address of previous handler */
211 (unsigned far *)&prev_action, /* Address of previous action */
212 (unsigned)INSTALL_SIGNAL, /* Indicate request type */
213 (unsigned)CTRL_BREAK /* Signal number */
214 );
215
216/*********************************/
217/* Take control of Hard Errors */
218/*********************************/
219 set_int24_vector(); /*;AN000; Set Critical error vector (int 24h) */
220
221
222 /************************************************************/
223 /* call dorestore (RTDO.C) to actually do the restoring */
224 /************************************************************/
225 dorestore(srcd,destd,inpath,infname,infext,infspec,&td);
226
227 /************************************************************/
228 /* output a msg in the following situations: */
229 /* if flag indicates no file found */
230 /************************************************************/
231 if (set_reset_test_flag(&control_flag,FOUND,TEST)==FALSE)
232 {
233 /*warning! No files were found to restore*/
234 display_it(NO_FILE_TO_RESTORE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
235 exit_routine(NOFILES);
236 }
237
238 exit_routine(NORMAL);
239
240} /* end of main*/
diff --git a/v4.0/src/CMD/RESTORE/RESTORE.LNK b/v4.0/src/CMD/RESTORE/RESTORE.LNK
new file mode 100644
index 0000000..b5c50a3
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RESTORE.LNK
@@ -0,0 +1,17 @@
1/STACK:50000 +
2restore +
3restpars +
4rtt1 +
5rtt3 +
6rtdo +
7rtdo1 +
8rtold +
9rtold1 +
10rtnew +
11rtnew1 +
12rtfile +
13rtfile1 +
14_parse +
15_msgret
16restore.exe,,..\..\mapper\mapper + ..\..\inc\comsubs;
17 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RESTORE.SKL b/v4.0/src/CMD/RESTORE/RESTORE.SKL
new file mode 100644
index 0000000..81bf2cc
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RESTORE.SKL
@@ -0,0 +1,46 @@
1;==========================================================
2
3:util RESTORE ;AN000;
4
5;---------
6:class A
7;--------- ;AN000;
8:use 1 COMMON1 ;AN000; ;For "Incorrect DOS version
9:def 2 CR,LF,"Source and target drives are the same",CR,LF ;AN000;
10:def 3 CR,LF,"Invalid number of parameters",CR,LF ;AN000;
11
12:use 5 COMMON25 ;AN000; ;For "Invalid path
13:def 6 CR,LF,"Invalid drive specification",CR,LF ;AN000;
14:def 7 CR,LF,"Warning! No files were found to restore",CR,LF ;AN000;
15:def 8 CR,LF,"Insert backup diskette %1 in drive %2:",CR,LF ;AN000;
16:def 9 CR,LF,"Insert restore target in drive %1:",CR,LF ;AN000;
17:use 10 COMMON28 ;AN000; ;For "Press any key to continue . . .",CR,LF
18:def 11 CR,LF,"Warning! Diskette is out of sequence",CR,LF ;AN000;
19 "Replace diskette or continue if okay",CR,LF ;AN000;
20
21:def 12 CR,LF,"The last file was not restored",CR,LF ;AN000;
22:def 13 CR,LF,"*** Files were backed up %1 ***",CR,LF ;AN000;
23:def 14 CR,LF,"Source does not contain backup files",CR,LF ;AN000;
24:def 15 CR,LF,"Insufficient memory",CR,LF ;AN000;
25:def 16 CR,LF,"Warning! File %1",CR,LF ;AN000;
26 "is a read-only file",CR,LF ;AN000;
27 "Replace the file (Y/N)?" ;AN000;
28
29:def 17 CR,LF,"Restore file sequence error",CR,LF ;AN000;
30:def 18 CR,LF,"File creation error",CR,LF ;AN000;
31:def 19 CR,LF,"Insufficient disk space",CR,LF ;AN000;
32:def 20 CR,LF,"*** Not able to restore file ***",CR,LF ;AN000;
33:def 21 CR,LF,"*** Restoring files from drive %1: ***",CR,LF ;AN000;
34:def 22 CR,LF,"Warning! File %1",CR,LF ;AN000;
35 "was changed after it was backed up",CR,LF ;AN000;
36 "Replace the file (Y/N)?",CR,LF ;AN000;
37
38:def 23 "Diskette: %1",CR,LF ;AN000;
39
40:use 27 COMMON23 ;AN000; ;For "Invalid date
41:use 28 COMMON24 ;AN000; ;For "Invalid time
42:use 29 COMMON26 ;AN000; ;For "No source drive specified
43:use 30 COMMON27 ;AN000; ;For "No target drive specified
44:def 31 CR,LF ;AN000;
45:end ;AN000;
46;==========================================================
diff --git a/v4.0/src/CMD/RESTORE/RESTPARS.C b/v4.0/src/CMD/RESTORE/RESTPARS.C
new file mode 100644
index 0000000..6299f75
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RESTPARS.C
@@ -0,0 +1,1002 @@
1
2/*-------------------------------
3/* SOURCE FILE NAME: restpars.c
4/*-------------------------------
5/*  0 */
6#include "rt.h"
7#include "rt1.h"
8#include "rt2.h"
9#include "restpars.h" /*;AN000;4*/
10#include "direct.h"
11#include "string.h"
12#include "ctype.h"
13#include "dos.h" /*;AN000;2*/
14#include "comsub.h" /* common subroutine def'n */
15#include "doscalls.h"
16#include "error.h"
17
18/*=============================*/
19extern BYTE srcd; /*;AN000;4*/
20extern BYTE destd; /*;AN000;4*/
21extern BYTE inpath [MAXPATH]; /*;AN000;*/
22extern BYTE infname [MAXFNAME]; /*;AN000;*/
23extern BYTE infext [MAXFEXT]; /*;AN000;*/
24extern BYTE infspec [MAXFSPEC]; /*;AN000;*/
25/*=============================*/
26
27extern BYTE destddir[MAXPATH+3];
28extern BYTE srcddir[MAXPATH+3];
29extern BYTE rtswitch;
30extern BYTE control_flag;
31extern BYTE control_flag2;
32extern BYTE filename[12];
33extern unsigned control_file_handle; /* !wrw */
34extern struct subst_list sublist; /*;AN000;6Message substitution list */
35
36struct p_parms parms; /*;AN000;4 Parser data structure */
37struct p_parmsx parmsx; /*;AN000;4 Parser data structure */
38struct p_pos_blk pos1; /*;AN000;4 Parser data structure */
39struct p_pos_blk pos2; /*;AN000;4 Parser data structure */
40struct p_sw_blk sw1; /*;AN000;4 /S /P /M /N data structure */
41struct p_sw_blk sw2; /*;AN000;4 /E: /L: parser data structure */
42struct p_sw_blk sw3; /*;AN000;4 /B: /A: parser data structure */
43struct p_result_blk pos_buff; /*;AN000;4 Parser data structure */
44struct switchbuff sw_buff; /*;AN000;4 Parser data structure */
45struct timebuff time_buff; /*;AN000;4 Parser data structure */
46struct datebuff date_buff; /*;AN000;4 Parser data structure */
47DWORD noval; /*;AN000;4 Value list for PARSER */
48int parse_count = 1; /*;AN000;4*//*;AC002;*/
49char curr_parm[128]; /*;AN004; Current parameter being parsed*/
50extern struct timedate td;
51
52/* ************************************************/
53/*
54/* SUBROUTINE NAME: parse_command_line
55/*
56/* FUNCTION:
57/*
58/* Parse the RESTORE command line
59/*
60/**************************************************/
61void parse_command_line(argc,argv) /*;AN000;4 */
62int argc; /*;AN000;4 */
63char *argv[]; /*;AN000;4 */
64{ /*;AN000;4 */
65#define EOL -1 /*;AN000;4 */
66 union REGS inregs, outregs; /*;AN000;4 */
67 char cmd_line[128]; /*;AN000;4 */
68 char not_finished = TTRUE; /*;AN000;4 */
69 int x; /*;AN000;4 */
70
71
72 /* Copy command line parameters to local area */
73 cmd_line[0] = NUL; /*;AN000;4*/
74 for (x=1; x<=argc; x++) /*;AN000;4*/
75 { /*;AN000;4*/
76 strcat(cmd_line,argv[x]); /*;AN000;4*/
77 if (x!=argc) strcat(cmd_line," "); /*;AN000;4*/
78 } /*;AN000;4*/
79
80 strcat(cmd_line,"\r"); /* Add CR, LF */ /*;AN004;*/
81
82 if (argc-1 < 1) /*;AN000;4*/
83 { /*;AC000;4*/
84 display_it(NO_SOURCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
85 usererror(INVALIDPARM); /*;AC000;4*/
86 } /*;AC000;4*/
87
88 if (argc-1 < 2) /*;AN000;4*/
89 { /*;AC000;4*/
90 display_it(NO_TARGET,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
91 usererror(INVALIDPARM); /*;AC000;4*/
92 } /*;AC000;4*/
93
94 /* Check for same source and target drive */
95 if (com_toupper(*argv[1]) == com_toupper(*argv[2]) /*;AN000;4*/
96 && (BYTE)*(argv[1]+1) == ':' /*;AN000;4*/
97 && (BYTE)*(argv[1]+2) == NUL /*;AN000;4*/
98 && (BYTE)*(argv[2]+1) == ':' /*;AN000;4*/
99 ) /*;AN000;4*/
100 { /*;AC000;4*/
101 display_it(SOURCE_TARGET_SAME,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
102 usererror(INVALIDPARM); /*;AC000;4*/
103 } /*;AC000;4*/
104
105 /* Initialize parser data structures */
106 parse_init(); /*;AN000;4*/
107
108 inregs.x.si = (WORD)&cmd_line[0]; /*DS:SI*/ /*;AN000;4 make DS:SI point to source */
109 inregs.x.cx = 0; /*;AN000;4*/
110
111 /*********************/
112 /* PARSE LOOP !!!!!! */
113 /*********************/
114 while (not_finished) /*;AN000;4 For all strings in command line */
115 { /*;AN000;4 */
116 inregs.x.dx = 0; /*;AN000;4 RESERVED */
117 inregs.x.di = (WORD)&parms; /*ES:DI*/ /*;AN000;4 address of parm list */
118 parse(&inregs,&outregs); /*;AN000;4 Call DOS PARSE service routines*/
119
120 x=0; /* Save the parsed parameter */ /*;AN004;*/
121 for (inregs.x.si; inregs.x.si<outregs.x.si; inregs.x.si++) /*;AN004;*/
122 { /*;AN004;*/
123 curr_parm[x] = *(char *)inregs.x.si; /*;AN004;*/
124 x++; /*;AN004;*/
125 } /*;AN004;*/
126
127 curr_parm[x] = NUL; /*;AN004;*/
128
129 inregs = outregs; /* Reset registers */ /*;AN000;4 Reset registers*/
130
131 /* Check for PARSE ERROR*/
132 if (outregs.x.ax != (WORD)NOERROR) /*;AN000;4*/
133 { /*;AN000;4*/
134 if (outregs.x.ax==(WORD)EOL) /* Was it End of line? */ /*;AN000;4*/
135 not_finished = FFALSE; /*;AN000;4*/
136 else
137 { /* It was an error */ /*;AN000;4*/
138 not_finished = FFALSE; /*;AN000;4*/
139 parse_error(outregs.x.ax,(BYTE)PARSEERR); /*;AN000;4*//*;AC002;*/
140 } /*;AN000;4*/
141 } /*;AN000;4*/
142
143 if (not_finished) /* Parse was successful !*/ /*;AN000;4*/
144 { /*;AN000;4*/
145 if ( outregs.x.dx == (WORD)&time_buff || /*;AN000;4*/
146 outregs.x.dx == (WORD)&date_buff || /*;AN000;4*/
147 outregs.x.dx == (WORD)&sw_buff /*;AN000;4*/
148 ) /*;AN000;4*/
149 process_switch(outregs.x.dx,argv[parse_count]); /*;AN000;4*//*;AC002;*/
150 } /*;AN000;4*/
151
152 parse_count++; /*;AN000;4*//*;AC002;*/
153 } /* End WHILE Parse loop */ /*;AN000;4*/
154
155 /* Check source and target filespec */
156 if (strlen(argv[2]) >= 5) /*;AN000;p2591*/
157 check_for_device_names(argv); /*;AN000;p2591*/
158
159 check_source_drive(argc,argv); /*;AN000;4*/
160 check_target_filespec(argc,argv); /*;AN000;4*/
161
162 return; /*;AN000;4*/
163} /* end parser */ /*;AN000;4*/
164
165/** ***********************************************/
166/*
167/* SUBROUTINE NAME: parse_error
168/*
169/* FUNCTION:
170/*
171/* There was a parse error. Display message and die
172/*
173/**************************************************/
174void parse_error(msg_num,class) /*;AN000;4*//*;AC002;*/
175WORD msg_num; /*;AN000;4*/
176BYTE class; /*;AN000;4*/
177{ /*;AN000;4*/
178 sublist.value1 = &curr_parm[0]; /*;AN002;*/
179 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN002;*/
180 sublist.one = 0; /*;AN002;*/
181 sublist.max_width1 = (BYTE)strlen(curr_parm); /*;AN002;*/
182 sublist.min_width1 = sublist.max_width1; /*;AN002;*/
183
184
185 if (msg_num == NO_SOURCE || msg_num == NO_TARGET) /*;AN000;6*/
186 display_it(msg_num,STND_ERR_DEV,0,NO_RESPTYPE,class); /*;AN000;6*/
187 else /*;AN000;6*/
188 display_it(msg_num,STND_ERR_DEV,1,NO_RESPTYPE,class); /*;AN000;6*/
189
190
191 usererror(INVALIDPARM); /*;AN000;4*//*;AC002;*/
192 return; /*;AN000;4*/
193} /*;AN000;4*/
194
195/** ***********************************************/
196/*
197/* SUBROUTINE NAME: check_date
198/*
199/* FUNCTION:
200/*
201/* A date parameter was entered. Validate it
202/*
203/**************************************************/
204void check_date(year,month,day) /*;AN000;4*//*;AC002;*/
205WORD year; /*;AN000;4*/
206BYTE month; /*;AN000;4*/
207BYTE day; /*;AN000;4*/
208{ /*;AN000;4*/
209 if (year > 2099 || year < 1980) /*;AC000;4*/
210 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
211
212 if (month > 12 || month < 1) /*;AC000;4*/
213 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
214
215 if (day > 31 || month < 1) /*;AC000;4*/
216 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
217
218 /* Verify day not greater then 30 if Apr,Jun,Sep,Nov */
219 if ((day>30) && (month==4 || month==6 || month==9 || month==11)) /*;AC000;4*/
220 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
221
222 if (month == 2) /* Deal with February */ /*;AC000;4*/
223 { /*;AC000;4*/
224 if (day > 29) /* if Feb 30 or above */ /*;AC000;4*/
225 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
226
227 if ((year % 4) != 0) /* If not a leap year */ /*;AC000;4*/
228 if (day > 28) /* if Feb 29 or above */ /*;AC000;4*/
229 parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
230 } /*;AC000;4*/
231
232 return; /*;AN000;4*/
233} /*;AN000;4*/
234/** ***********************************************/
235/*
236/* SUBROUTINE NAME: check_time
237/*
238/* FUNCTION:
239/*
240/* A time parameter was entered. Validate it
241/*
242/**************************************************/
243void check_time(hours,minutes,seconds,hundreds) /*;AN000;4*//*;AC002;*/
244BYTE hours; /*;AN000;4*/
245BYTE minutes; /*;AN000;4*/
246BYTE seconds; /*;AN000;4*/
247BYTE hundreds; /*;AN000;4*/
248{ /*;AN000;4*/
249
250 if (hours > 23 || hours < 0) /*;AC000;4*/
251 parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
252
253 if (minutes >= 60 || minutes < 0) /*;AC000;4*/
254 parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
255
256 if (seconds >= 60 || seconds < 0) /*;AC000;4*/
257 parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/
258
259 return; /*;AN000;4*/
260} /*;AN000;4*/
261
262/** ***********************************************/
263/*
264/* SUBROUTINE NAME: parse_init
265/*
266/* FUNCTION:
267/*
268/* Initialize the parser data structures
269/*
270/**************************************************/
271#define SSTRING 0x2000 /*;AN000;4*/
272#define FILESPEC 0x0200 /*;AN000;4 */
273#define CAP_FILETABLE 0x0001 /*;AN000;4 */
274#define DRIVELETTER 0x100; /*;AN000;4 */
275#define DATESTRING 0x1000 /*;AN000;4 */
276#define TIMESTRING 0x0800 /*;AN000;4 */
277
278void parse_init() /*;AN000;4 */
279
280{ /* Initialize PARMS data structure */ /*;AN000;4 */
281 parms.parmsx_ptr = (WORD)&parmsx; /*;AN000;4 */
282 parms.p_num_extra = 1; /*;AN000;4 */
283 parms.p_len_extra_delim = 1; /*;AN000;4 */
284 parms.p_extra_delim[0] = ';'; /*;AN000;4 */
285 parms.p_extra_delim[1] = NUL; /*;AN000;4 */
286
287 /* Initialize PARMSX data structure */
288 parmsx.p_minpos= 2; /*;AN000;4 */
289 parmsx.p_maxpos= 2; /*;AN000;4 */
290 parmsx.pos1_ptr= (WORD)&pos1; /*;AN000;4 */
291 parmsx.pos2_ptr= (WORD)&pos2; /*;AN000;4 */
292 parmsx.num_sw = 3; /*;AN000;4 */
293 parmsx.sw1_ptr = (WORD)&sw1; /*;AN000;4 */
294 parmsx.sw2_ptr = (WORD)&sw2; /*;AN000;4 */
295 parmsx.sw3_ptr = (WORD)&sw3; /*;AN000;4 */
296 parmsx.num_keywords = 0; /*;AN000;4 */
297
298 /* Initialize POS1 (Source Drive) data structure */
299 pos1.match_flag = FILESPEC; /*;AN000;4 */
300 pos1.function_flag = 0; /*;AN000;4 */
301 pos1.result_buf = (WORD)&pos_buff; /*;AN000;4 */
302 pos1.value_list = (WORD)&noval; /*;AN000;4 */
303 pos1.nid = 0; /*;AN000;4 */
304
305 /* Initialize POS2 (Target FILESPEC) data structure */
306 pos2.match_flag = SSTRING; /*;AN000;4 */
307 pos2.function_flag = 0; /*;AN000;4 */
308 pos2.result_buf = (WORD)&pos_buff; /*;AN000;4 */
309 pos2.value_list = (WORD)&noval; /*;AN000;4 */
310 pos2.nid = 0; /*;AN000;4 */
311
312 /* Initialize SW1 data structure */
313 sw1.p_match_flag = DATESTRING; /*;AN000;4 */
314 sw1.p_function_flag = 0; /*;AN000;4 */
315 sw1.p_result_buf = (WORD)&date_buff; /*;AN000;4 */
316 sw1.p_value_list = (WORD)&noval; /*;AN000;4 */
317 sw1.p_nid = 2; /*;AN000;4 */
318 strcpy(sw1.switch1,"/B"); /*;AN000;4 */
319 strcpy(sw1.switch2,"/A"); /*;AN000;4 */
320
321 /* Initialize SW2 data structure */
322 sw2.p_match_flag = TIMESTRING; /*;AN000;4 */
323 sw2.p_function_flag = 0; /*;AN000;4 */
324 sw2.p_result_buf = (WORD)&time_buff; /*;AN000;4 */
325 sw2.p_value_list = (WORD)&noval; /*;AN000;4 */
326 sw2.p_nid = 2; /*;AN000;4 */
327 strcpy(sw2.switch1,"/E"); /*;AN000;4 */
328 strcpy(sw2.switch2,"/L"); /*;AN000;4 */
329
330
331 /* Initialize SW3 data structure */
332 sw3.p_match_flag = 0; /*;AN000;4 */
333 sw3.p_function_flag = 0; /*;AN000;4 */
334 sw3.p_result_buf = (WORD)&sw_buff; /*;AN000;4 */
335 sw3.p_value_list = (WORD)&noval; /*;AN000;4 */
336 sw3.p_nid = 4; /*;AN000;4 */
337 strcpy(sw3.switch1,"/S"); /*;AN000;4 */
338 strcpy(sw3.switch2,"/P"); /*;AN000;4 */
339 strcpy(sw3.switch3,"/M"); /*;AN000;4 */
340 strcpy(sw3.switch4,"/N"); /*;AN000;4 */
341
342 /*********************************************/
343 /* Also initialize all time and date values */
344 /*********************************************/
345 td.earlier_hour = 0;
346 td.earlier_minute = 0;
347 td.earlier_second = 0;
348 td.later_hour = 0;
349 td.later_minute = 0;
350 td.later_second = 0;
351 td.before_year = 0;
352 td.before_month = 0;
353 td.before_day = 0;
354 td.after_year = 0;
355 td.after_month = 0;
356 td.after_day = 0;
357
358 /**************************************************/
359 /* Also initialize the message substitution list */
360 /**************************************************/
361 sublist.sl_size1= SUBLIST_SIZE; /*;AN000;6*/
362 sublist.sl_size2= SUBLIST_SIZE; /*;AN000;6*/
363 sublist.one = 1; /*;AN000;6*/
364 sublist.two = 2; /*;AN000;6*/
365 sublist.zero1 = 0; /*;AN000;6*/
366 sublist.zero2 = 0; /*;AN000;6*/
367 sublist.pad_char1 = ' '; /*;AN000;6*/
368 sublist.pad_char2 = ' '; /*;AN000;6*/
369
370 return; /*;AN000;4 */
371} /*;AN000;4 */
372
373
374/** ***********************************************/
375/*
376/* SUBROUTINE NAME: check_for_device_names
377/*
378/* FUNCTION:
379/*
380/* Make sure user not trying to restore a reserved device name
381/*
382/**************************************************/
383void check_for_device_names(argv) /*;AN000;p2591*/
384char *argv[]; /*;AN000;p2591*/
385{ /*;AN000;p2591*/
386 union REGS qregs; /*;AN000;p2591*/
387 char target[128]; /*;AN000;p2591*/
388 char *t; /*;AN000;p2591*/
389
390#define CAPITALIZE_STRING 0x6521 /*;AN000;p2591*/
391
392 qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p2591*/
393 qregs.x.dx = (WORD)argv[2]; /*;AN000;p2591*/
394 strcpy(target,argv[2]); /*;AN000;p2591*/
395 qregs.x.cx = strlen(target); /*;AN000;p2591*/
396 intdos(&qregs,&qregs); /*;AN000;p2591*/
397 strcpy(target,argv[2]); /*;AN000;p2591*/
398
399 for (t=&target[0]; *t!=NUL; t++)
400 if /*;AN000;p2591*/
401 ( strcmp(t,"LPT1")==0 || /*;AN000;p2591*/
402 strcmp(t,"LPT2")==0 || /*;AN000;p2591*/
403 strcmp(t,"PRN")==0 || /*;AN000;p2591*/
404 strcmp(t,"CON")==0 || /*;AN000;p2591*/
405 strcmp(t,"NUL")==0 || /*;AN000;p2591*/
406 strcmp(t,"AUX")==0 || /*;AN000;p2591*/
407 strcmp(t,"LPT1:")==0 || /*;AN000;p2591*/
408 strcmp(t,"LPT2:")==0 || /*;AN000;p2591*/
409 strcmp(t,"PRN:")==0 || /*;AN000;p2591*/
410 strcmp(t,"CON:")==0 || /*;AN000;p2591*/
411 strcmp(t,"NUL:")==0 || /*;AN000;p2591*/
412 strcmp(t,"AUX:")==0 /*;AN000;p2591*/
413 ) /*;AN000;p2591*/
414 { /*;AN000;p2591*/
415 sublist.value1 = (char far *)t; /*;AN000;p2591*/
416 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;p2591*/
417 sublist.one = 0; /*;AN000;p2591*/
418 sublist.max_width1 = (BYTE)strlen(t); /*;AN000;p2591*/
419 sublist.min_width1 = sublist.max_width1; /*;AN000;p2591*/
420
421 display_it(INVPARM,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;p2591*/
422 usererror(INVALIDPARM); /*;AN000;p2591*/
423 } /*;AN000;p2591*/
424
425
426 return; /*;AN000;p2591*/
427} /*;AN000;p2591*/
428
429/** ***********************************************/
430/*
431/* SUBROUTINE NAME: check_source_drive
432/*
433/* FUNCTION:
434/*
435/* Verify drive letter and start building srcddir
436/*
437/**************************************************/
438void check_source_drive(argc,argv) /*;AN000;4*/
439int argc; /*;AN000;4*/
440char *argv[]; /*;AN000;4*/
441{ /*;AN000;4*/
442 WORD retcode; /*;AC000;*/
443 WORD device_handle;
444 WORD action;
445 BYTE parm;
446 BYTE media_type;
447 WORD dnumwant = 1;
448 BYTE temp_array1[4];
449 BYTE temp_array2[4];
450 union REGS qregs; /*;AN000;8*/
451
452 *argv[1]=(BYTE)com_toupper(*argv[1]); /*;AN000;4*/
453
454 if ( /*;AN000;4*/
455 *argv[1] < 'A' || /*;AN000;4*/
456 *argv[1] > 'Z' || /*;AN000;4*/
457 *(argv[1]+1)!=':' || /*;AN000;4*/
458 *(argv[1]+2)!=NUL /*;AN000;4*/
459 ) /*;AN000;4*/
460 { /*;AN000;4*/
461 display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
462 usererror(INVALIDDRIVE); /*;AN000;4*/
463 } /*;AN000;4*/
464
465 srcd = (BYTE)*argv[1]; /*;AN000;4*/
466 srcddir[0] = srcd; /*;AN000;4*/
467 srcddir[1] = ':'; /*;AN000;4*/
468 srcddir[2] = NUL; /*;AN000;4*/
469
470 /***********************************************************************/
471 /* dosopen to find out whether the src drive exist */
472 /* and dosdevioctl to find out whether it is a removable drive */
473 /***********************************************************************/
474 retcode = /*;AC000;4*/
475 DOSOPEN /*;AC000;4*/
476 ( (char far *)&srcddir[0], /*;AC000;4*/
477 (unsigned far *)&device_handle, /*;AC000;4*/
478 (unsigned far *)&action, /*;AC000;4*/
479 (DWORD)0, /*file size*/ /*;AC000;4*/
480 0, /*file attribute*/ /*;AC000;4*/
481 0x01, /*if file exist, open it*/ /*;AC000;4*/
482 /*if file not exist, fail it*//*;AC000;4*/
483 0x80c2, /*deny write, read only*/ /*;AC000;4*/
484 (DWORD)0 /*reserved*/ /*;AC000;4*/
485 ); /*;AC000;4*/
486
487 if (retcode != NOERROR) /*;AC000;4*/
488 { /*;AC000;4*/
489 display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
490 usererror(INVALIDDRIVE); /*;AC000;4*/
491 } /*;AC000;4*/
492
493 /************************************/ /*;AC000;4*/
494 /* See if source drive is removable */ /*;AC000;4*/
495 /************************************/ /*;AC000;4*/
496 retcode = /*;AC000;4*/
497 DOSDEVIOCTL /*;AC000;4*/
498 ( (char far *)&media_type, /*;AC000;4*/
499 (char far *)&parm, /*;AC000;4*/
500 0x20, /*;AC000;4*/
501 0x08, /*;AC000;4*/
502 device_handle /*;AC000;4*/
503 ); /*;AC000;4*/
504
505 if (retcode != NOERROR) /*;AC000;4*/
506 { display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
507 usererror(INVALIDDRIVE); /*;AC000;4*/
508 } /*;AC000;4*/
509
510#define REMOVABLE 0 /*;AC000;4*/
511 if (media_type != REMOVABLE) /*;AC000;4*/
512 set_reset_test_flag(&control_flag2,SRC_HDISK,SET); /*;AC000;4*/
513
514 else /* Source disk is removable */ /*;AC000;4*/
515 { /*;AC000;4*/
516 temp_array1[0] = (BYTE)((dnumwant / 10) + '0'); /*;AC000;4*/
517 temp_array1[1] = (BYTE)((dnumwant % 10) + '0'); /*;AC000;4*/
518 temp_array1[2] = NUL; /*;AC000;4*/
519 temp_array2[0] = srcd; /*;AC000;4*/
520 temp_array2[1] = NUL; /*;AC000;4*/
521
522 sublist.value1 = (char far *)temp_array1; /*;AN000;6*/
523 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
524 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6*/
525 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
526
527 sublist.value2 = (char far *)temp_array2; /*;AN000;6*/
528 sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
529 sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6*/
530 sublist.min_width2 = sublist.max_width2; /*;AN000;6*/
531
532 display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
533 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
534
535 /* If single drive system, eliminates double prompting */
536 /* for user to "Insert diskette for drive %1" */
537 qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/
538 qregs.h.bl = srcddir[0] - 'A' + 1; /*;AN000;8*/
539 intdos(&qregs,&qregs); /*;AN000;8*/
540
541 } /*;AC000;4*/
542 return; /*;AN000;4*/
543} /*;AN000;4*/
544
545/** ***********************************************/
546/*
547/* SUBROUTINE NAME: check_target_filespec
548/*
549/* FUNCTION:
550/*
551/* Verify the target filespec.
552/* 1. Validate destination drive, or use default if none specified
553/* 2. Validate path, or use current dir if not specified
554/* 3. Validate the file name
555/*
556/**************************************************/
557void check_target_filespec(argc,argv) /*;AN000;4*/
558int argc; /*;AN000;4*/
559char *argv[]; /*;AN000;4*/
560{ /*;AN000;4*/
561 WORD retcode; /*;AC000;*/
562 WORD device_handle;
563 WORD action;
564 BYTE parm;
565 BYTE media_type;
566 DWORD drive_map;
567 BYTE temp_destddir[MAXPATH+2];
568 BYTE temp_array1[4];
569 BYTE temp_array2[4];
570 WORD default_drive_num;
571 WORD destd_num;
572 WORD dirlen = MAXPATH;
573 BYTE tdestddir[MAXPATH+3];
574 BYTE ttdestddir[MAXPATH+3];
575 BYTE srcf[MAXPATHF];
576 BYTE argv2_has_switch;
577 BYTE search_string[MAXPATHF+2];
578 BYTE tempp[MAXPATH];
579 WORD j,k,z;
580 BYTE *c;
581 BYTE backdir;
582 WORD dnumwant = 1;
583 union REGS qregs; /*;AN000;8*/
584
585
586 /**************************/
587 /* Uppercase the string */
588 /**************************/
589#define CAPITALIZE_STRING 0x6521 /*;AN000;p????*/
590
591 qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p????*/
592 qregs.x.dx = (WORD)argv[2]; /*;AN000;p????*/
593 strcpy(tempp,argv[2]); /*;AN000;p????*/
594 qregs.x.cx = strlen(tempp); /*;AN000;p????*/
595 intdos(&qregs,&qregs); /*;AN000;p????*/
596
597
598 /***************************************************/
599 /* If no drive letter specified, use current drive */
600 /***************************************************/
601 if ( /*;AC000;4*/
602 *(argv[2]+1)!=':' || /*;AC000;4*/
603 *argv[2] < 'A' || /*;AC000;4*/
604 *argv[2] > 'Z' /*;AC000;4*/
605 ) /*;AC000;4*/
606 { /*;AC000;4*/
607 DOSQCURDISK /*;AC000;4*/
608 ( (unsigned far *)&default_drive_num, /*;AC000;4*/
609 (DWORD far *) &drive_map /*;AC000;4*/
610 ); /*;AC000;4*/
611 destd = (BYTE)(default_drive_num + 'A' - 1); /*;AC000;4*/
612 } /*;AC000;4*/
613 else /*;AC000;4*/
614 { /* User specified the destination drive*/ /*;AC000;4*/
615 destd = (BYTE)*argv[2]; /*;AC000;4*/
616 argv[2] = argv[2] + 2; /*;AC000;4*/
617 } /*;AC000;4*/
618
619 destddir[0] = destd; /*;AC000;4*/
620 destddir[1] = ':'; /*;AC000;4*/
621 destddir[2] = NUL; /*;AC000;4*/
622
623 /***********************************************************************/
624 /* if source drive and destination drive are the same, output error msg*/
625 /***********************************************************************/
626 if (srcd == destd) /*;AC000;4*/
627 { /*;AC000;4*/
628 display_it(SOURCE_TARGET_SAME,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
629 usererror(INVALIDPARM); /*;AC000;4*/
630 } /*;AC000;4*/
631
632 /***********************************************************************/
633 /* dosopen to find out whether the destination drive is exist */
634 /* and dosdevioctl to find out whether it is a removable drive */
635 /***********************************************************************/
636
637 retcode = /*;AC000;4*/
638 DOSOPEN /*;AC000;4*/
639 ( (char far *)&destddir[0], /*;AC000;4*/
640 (unsigned far *)&device_handle, /*;AC000;4*/
641 (unsigned far *)&action, /*;AC000;4*/
642 (DWORD)0, /*file size*/ /*;AC000;4*/
643 0, /*file attribute*/ /*;AC000;4*/
644 0x01, /*if file exist, open it*/ /*;AC000;4*/
645 /*if file not exist, fail it*/ /*;AC000;4*/
646 0x80c2, /*deny write, read only*/ /*;AC000;4*/
647 (DWORD)0 /*reserved*/ /*;AC000;4*/
648 ); /*;AC000;4*/
649
650 if (retcode != NOERROR)/*if open fail*/ /*;AC000;4*/
651 { /*;AC000;4*/
652 display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
653 usererror(INVALIDDRIVE); /*;AC000;4*/
654 } /*;AC000;4*/
655
656 /************************************/ /*;AC000;4*/
657 /* See if target drive is removable */ /*;AC000;4*/
658 /************************************/ /*;AC000;4*/
659 retcode = /*;AC000;4*/
660 DOSDEVIOCTL /*;AC000;4*/
661 ( (char far *)&media_type, /*;AC000;4*/
662 (char far *)&parm, /*;AC000;4*/
663 0x20, /*;AC000;4*/
664 0x08, /*;AC000;4*/
665 device_handle /*;AC000;4*/
666 ); /*;AC000;4*/
667
668 if (retcode != NOERROR) /*;AC000;4*/
669 { display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
670 usererror(INVALIDDRIVE); /*;AC000;4*/
671 } /*;AC000;4*/
672
673 if (media_type == REMOVABLE) /*;AC000;4*/
674 { temp_array1[0] = destd; /*;AC000;4*/
675 temp_array1[1] = NUL; /*;AC000;4*/
676 sublist.value1 = (char far *)temp_array1; /*;AN000;6*/
677 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
678 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6*/
679 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
680
681 display_it(INSERT_TARGET_DISK,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
682 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
683 } /*;AC000;4*/
684
685 /* If single drive system, eliminates double prompting */
686 /* for user to "Insert diskette for drive %1" */
687 qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/
688 qregs.h.bl = destddir[0] - 'A' + 1; /*;AN000;8*/
689 intdos(&qregs,&qregs); /*;AN000;8*/
690
691 /**********************************************************************/
692 /* save current directory of destination disk to be reset back later */
693 /**********************************************************************/
694
695 destd_num = (WORD) (destd - 'A' +1); /*;AC000;4*/
696
697 /* get current directory of destd_num (DosQCurDir) */
698 if ((retcode = /*;AC000;4*/
699 DOSQCURDIR /*;AC000;4*/
700 ( destd_num, /*;AC000;4*/
701 (char far *) tdestddir, /*;AC000;4*/
702 (unsigned far *) &dirlen) /*;AC000;4*/
703 ) != 0) /*;AC000;4*/
704 { /*;AC000;4*/
705 display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
706 usererror(INVALIDDRIVE); /*;AC000;4*/
707 } /*;AC000;4*/
708
709#define BACKSLASH 0x5c
710
711 if (strlen(tdestddir) != 1) /*;AC000;4*/
712 { strcpy(temp_destddir,"\\"); /*;AC000;4*/
713 strcat(temp_destddir,tdestddir); /*;AC000;4*/
714 strcpy(tdestddir,temp_destddir); /*;AC000;4*/
715 } /*;AC000;4*/
716
717
718 /**********************************************************************/
719 /* The next parameter has to be a file name with or without path, */
720 /* or a switch. In the case of there is no path, the current path */
721 /* is used. In the case of there is no file name, the global file */
722 /* name *.* is used */
723 /**********************************************************************/
724 /* argv[2] is a drive spec*/ /*;AC000;4*/
725 if (*(argv[2]+1)==':' && *argv[2] >= 'A' && *argv[2] <= 'Z' && argc!=2) /*;AC000;4*/
726 { /*;AN000;6*/
727 display_it(INVPARM,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/
728 usererror(INVALIDPARM); /*;AC000;4*/
729 } /*;AC000;4*/
730 else /*;AC000;4*/
731 { /*if argv[2] is not a drive spec */ /*;AC000;4*/
732 /*if argv[2] started with '/' (is a switch) or there is no argv[i]*/ /*;AC000;4*/
733 if (*argv[2] == '/' || *argv[2] == NUL || argc ==2) /*;AC000;4*/
734 { strcpy(srcf,tdestddir); /*;AC000;4*/
735 strcat(srcf,"\\*.*"); /*;AC000;4*/
736 } /*;AC000;4*/
737 else /*;AC000;4*/
738 { /*argv[2] does not started with / */ /*;AC000;4*/
739 /* find out whether part of argv[2] is switch specification */ /*;AC000;4*/
740 for (k = 0; argv[2][k] != '/' && argv[2][k] != NUL; ++k);/*;AC000;4*/
741 if (argv[2][k] == '/') /*;AC000;4*/
742 { /*;AC000;4*/
743 argv[2][k] = NUL; /*;AC000;4*/
744 argv2_has_switch = TRUE; /*;AC000;4*/
745 } /*;AC000;4*/
746
747 /*if argv[2] is \\, invalid parm */ /*;AC000;4*/
748 if (argv[2][0] == '\\' && argv[2][1] == '\\' || argv[2][0] == ':') /*;AC000;;4*/
749 { /*;AN000;6*/
750 display_it(INVPARM,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/
751 usererror(INVALIDPARM); /*;AC000;4*/
752 } /*;AC000;4*/
753
754 /*if argv[2] starts with '\' (it is a complete path)*/ /*;AC000;4*/
755 if (*argv[2] == '\\') /*;AC000;4*/
756 strcpy(srcf,argv[2]); /*;AC000;4*/
757 else /*;AC000;4*/
758 /* it is not a complete path, have to put current path in */ /*;AC000;;4*/
759 /* front of the string to build a complete path */ /*;AC000;4*/
760 { strcpy(srcf,tdestddir); /*;AC000;4*/
761 if (strlen(tdestddir) != 1) /*;AC000;4*/
762 strcat(srcf,"\\"); /*;AC000;4*/
763 strcat(srcf,argv[2]); /*;AC000;4*/
764 } /*endif*/ /*;AC000;4*/
765 } /*end of argv[2] does not start with '/' */ /*;AC000;4*/
766
767 j = strlen(srcf); /*;AC000;4*/
768 z = 0; /*;AC000;4*/
769 do /*;AC000;4*/
770 { for (;srcf[z] != '.' && srcf[z] != NUL; ++z); /*;AC000;4*/
771 if (srcf[z] == '.' && srcf[z+1] == '.' && /*;AC000;4*/
772 (srcf[z+2] == '\\' || srcf[z+2] == NUL)) /*;AC000;4*/
773 { backdir = TRUE; /*;AC000;4*/
774 break; /*;AC000;4*/
775 } /*;AC000;4*/
776 z = z+1; /*;AC000;4*/
777 } /*;AC000;4*/
778 while (z < j); /*;AC000;4*/
779
780 /*validate the path*/ /*;AC000;4*/
781 for (z = j; srcf[z] != '\\'; --z); /*;AC000;4*/
782 strcpy(tempp,srcf); /*;AC000;4*/
783 tempp[z] = NUL; /*;AC000;4*/
784
785 for (z = 0; tempp[z] != '*' && tempp[z] != NUL; ++z); /*;AC000;4*/
786 if (tempp[z] == '*' ) /*;AC000;4*/
787 { display_it(PATH_NOT_FOUND,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
788 usererror(INVALIDPARM); /*;AC000;4*/
789 } /*;AC000;4*/
790
791 if (backdir == TRUE) /*;AC000;4*/
792 { search_string[0] = destd; /*;AC000;4*/
793 search_string[1] = ':'; /*;AC000;4*/
794 search_string[2] = NUL; /*;AC000;4*/
795 if (srcf[0] == NUL) /*;AC000;4*/
796 strcat(search_string,"\\"); /*;AC000;4*/
797 else /*;AC000;4*/
798 strcat(search_string, tempp); /*;AC000;4*/
799
800 if(chdir(search_string)!=0) /*;AC000;4*/
801 { sublist.value1 = (char far *)argv[2]; /*;AN000;6*/
802 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
803 sublist.max_width1 = (BYTE)strlen(argv[2]); /*;AN000;6*/
804 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
805 display_it(PATH_NOT_FOUND,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
806 usererror(INVALIDPARM); /*;AC000;4*/
807 } /*;AC000;4*/
808
809 dirlen = MAXPATH; /*;AC000;4*/
810 if ((retcode = DOSQCURDIR(destd_num, /*;AC000;4*/
811 (char far *) ttdestddir, /*;AC000;4*/
812 (unsigned far *) &dirlen)) != NOERROR) /*;AC000;4*/
813 { /*;AC000;4*/
814 com_msg(retcode); /*;AC000;4*/
815 usererror(retcode); /*;AC000;4*/
816 } /*;AC000;4*/
817 /* endif */ /*;AC000;4*/
818
819 temp_destddir[0] = destd; /*;AC000;4*/
820 temp_destddir[1] = ':'; /*;AC000;4*/
821 temp_destddir[2] = NUL; /*;AC000;4*/
822 strcat(temp_destddir,tdestddir); /*;AC000;4*/
823 chdir(temp_destddir); /*;AC000;4*/
824
825 if (strlen(ttdestddir) != 1) /*;AC000;4*/
826 { strcpy(temp_destddir,"\\"); /*;AC000;4*/
827 strcat(temp_destddir,ttdestddir); /*;AC000;4*/
828 strcpy(ttdestddir,temp_destddir); /*;AC000;4*/
829 } /*;AC000;4*/
830
831 strcat(ttdestddir,"\\"); /*;AC000;4*/
832 strcat(ttdestddir,srcf+z+1); /*;AC000;4*/
833 strcpy(srcf,ttdestddir); /*;AC000;4*/
834 } /*end of if backdir is true */ /*;AC000;4*/
835
836 /* The documentation says if path is specified, file name has to */
837 /* be specified also. This logic actually allows user to specify*/
838 /* path without specify filename, as long as the path end with */
839 /* '\'.*/
840 /*If *srcf ends with '\', add "*.*" to the end*/ /*;AC000;4*/
841 j = strlen(srcf); /*;AC000;4*/
842 if (srcf[j-1] == '\\') /*;AC000;4*/
843 strcat(srcf,"*.*"); /*;AC000;4*/
844 if (argv2_has_switch == TRUE) /*;AC000;4*/
845 { *(argv[2]+k) = '/'; /*;AC000;4*/
846 argv[2] = argv[2] + k; /*;AC000;4*/
847 } /* end of if argv[2] started with '/' */ /*;AC000;4*/
848 } /* end of checking for argv[2] */ /*;AC000;4*/
849
850 /**********************************************************************/
851 /* add '\' at the beginning of the current destination directory */
852 /**********************************************************************/
853 temp_destddir[0] = destd; /*;AC000;4*/
854 temp_destddir[1] = ':'; /*;AC000;4*/
855 temp_destddir[2] = NUL; /*;AC000;4*/
856 strcat(temp_destddir,tdestddir); /*;AC000;4*/
857 strcpy(destddir,temp_destddir); /*;AC000;4*/
858
859 /************************************************************************/
860 /* separate the filename for search into prefix(inpath), */
861 /* filename(infname), and file extension (infext) */
862 /* Also take care of the situation that user enter '.' only */
863 /* for file spec. */
864 /************************************************************************/
865 separate(srcf,inpath,infname,infext,infspec); /*;AC000;4*/
866 if (strlen(infname) > MAXFNAME-1 || /*;AC000;4*/
867 strlen(infext) > MAXFEXT-1 || /*;AC000;4*/
868 strlen(inpath) > MAXPATH-1 || /*;AC000;4*/
869 strcmp(infspec,"LPT1")==0 || /*;AC000;4*/
870 strcmp(infspec,"LPT2")==0 || /*;AC000;4*/
871 strcmp(infspec,"PRN")==0 || /*;AC000;4*/
872 strcmp(infspec,"CON")==0 || /*;AC000;4*/
873 strcmp(infspec,"NUL")==0 || /*;AC000;4*/
874 strcmp(infspec,"AUX")==0 || /*;AC000;4*/
875 strcmp(infspec,"LPT1:")==0 || /*;AC000;4*/
876 strcmp(infspec,"LPT2:")==0 || /*;AC000;4*/
877 strcmp(infspec,"PRN:")==0 || /*;AC000;4*/
878 strcmp(infspec,"CON:")==0 || /*;AC000;4*/
879 strcmp(infspec,"NUL:")==0 || /*;AC000;4*/
880 strcmp(infspec,"AUX:")==0 ) /*;AC000;4*/
881 { /*;AC000;4*/
882 sublist.value1 = (char far *)&infspec[0]; /*;AN000;6*/
883 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
884 sublist.one = 0; /* Yes, this is right */ /*;AN000;6*/
885 sublist.max_width1 = (BYTE)strlen(infspec); /*;AN000;6*/
886 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
887
888 display_it(INVPARM,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/
889 usererror(INVALIDPARM); /* invalid parm */ /*;AC000;4*/
890 } /*;AC000;4*/
891
892 /************************************************************************/
893 /* set wildcard flag according to whether there is '*' or/and '?' in */
894 /* file specification */
895 /************************************************************************/
896 c = infspec; /*;AC000;4*/
897 while (*c) /*;AC000;4*/
898 { /*;AC000;4*/
899 if (*c == '*' || *c == '?') /*;AC000;4*/
900 { set_reset_test_flag(&control_flag,WILDCARD,SET); /*;AC000;4*/
901 break; /*;AC000;4*/
902 } /*;AC000;4*/
903 else /*;AC000;4*/
904 c = c+1; /*;AC000;4*/
905 } /*;AC000;4*/
906
907
908 return; /*;AN000;4*/
909} /*;AN000;4*/
910
911/** ***********************************************/
912/*
913/* SUBROUTINE NAME: process_switch
914/*
915/* FUNCTION:
916/*
917/* Identify the switch (/S,/P,/M,/N,/B:,/A:,/E:,/L:)
918/* entered and handle it
919/*
920/**************************************************/
921void process_switch(buff_addr,ptr) /*;AN000;4*//*;AC002;*/
922unsigned buff_addr; /*;AN000;4*/
923char *ptr; /*;AN002;*/
924{ /*;AN000;4*/
925
926 if (buff_addr == (unsigned)&sw_buff) /*;AN000;4*/
927 { /*;AN000;4*/
928 if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch1[0]) /*;AN000;4 /S */
929 {set_reset_test_flag(&rtswitch, SUB, SET); /*;AN000;4*/
930 }
931
932 if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch2[0]) /*;AN000;4 /P */
933 { /*;AN000;4*/
934 set_reset_test_flag(&rtswitch, PROMPT, SET); /*;AN000;4*/
935 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
936 } /*;AN000;4*/
937
938 if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch3[0]) /*;AN000;4 /M */
939 { /*;AN000;4*/
940 set_reset_test_flag(&rtswitch, Revised, SET); /*;AN000;4*/
941 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
942 } /*;AN000;4*/
943
944 if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch4[0]) /*;AN000;4 /N */
945 { /*;AN000;4*/
946 set_reset_test_flag(&rtswitch, NOTEXIST, SET); /*;AN000;4*/
947 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
948 } /*;AN000;4*/
949 } /*;AN000;4*/
950
951
952 if (buff_addr == (unsigned)&time_buff) /*;AN000;4*/
953 { /*;AN000;4*/
954 check_time(time_buff.hours,time_buff.minutes,time_buff.seconds,time_buff.hundreds); /*;AN000;4*//*;AC002;*/
955
956 if (time_buff.tb_synonym_ptr == (WORD)&sw2.switch1[0]) /*;AN000;4 /E */
957 { /*;AN000;4*/
958 td.earlier_hour = time_buff.hours; /*;AN000;4*/
959 td.earlier_minute = time_buff.minutes; /*;AN000;4*/
960 td.earlier_second = time_buff.seconds; /*;AN000;4*/
961 set_reset_test_flag(&rtswitch, EARLIER, SET); /*;AN000;4*/
962 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
963 } /*;AN000;4*/
964
965 if (time_buff.tb_synonym_ptr == (WORD)&sw2.switch2[0]) /*;AN000;4 /L */
966 { /*;AN000;4*/
967 td.later_hour = time_buff.hours; /*;AN000;4*/
968 td.later_minute = time_buff.minutes; /*;AN000;4*/
969 td.later_second = time_buff.seconds; /*;AN000;4*/
970 set_reset_test_flag(&rtswitch, LATER, SET); /*;AN000;4*/
971 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
972 } /*;AN000;4*/
973
974 } /*;AN000;4*/
975
976
977 if (buff_addr == (unsigned)&date_buff) /*;AN000;4*/
978 { /*;AN000;4*/
979 check_date(date_buff.year,date_buff.month,date_buff.day); /*;AN000;4*//*;AC002;*/
980
981 if (date_buff.db_synonym_ptr == (WORD)&sw1.switch1[0]) /*;AN000;4 /B */
982 { /*;AN000;4*/
983 td.before_year = date_buff.year; /*;AN000;4*/
984 td.before_month = date_buff.month; /*;AN000;4*/
985 td.before_day = date_buff.day; /*;AN000;4*/
986 set_reset_test_flag(&rtswitch, BEFORE, SET); /*;AN000;4*/
987 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
988 } /*;AN000;4*/
989
990 if (date_buff.db_synonym_ptr == (WORD)&sw1.switch2[0]) /*;AN000;4 /A */
991 { /*;AN000;4*/
992 td.after_year = date_buff.year; /*;AN000;4*/
993 td.after_month = date_buff.month; /*;AN000;4*/
994 td.after_day = date_buff.day; /*;AN000;4*/
995 set_reset_test_flag(&rtswitch, AFTER, SET); /*;AN000;4*/
996 set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/
997 } /*;AN000;4*/
998
999 } /*;AN000;4*/
1000
1001 return; /*;AN000;4*/
1002} /*;AN000;4*/
diff --git a/v4.0/src/CMD/RESTORE/RESTPARS.H b/v4.0/src/CMD/RESTORE/RESTPARS.H
new file mode 100644
index 0000000..8b9bf95
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RESTPARS.H
@@ -0,0 +1,119 @@
1/* 0 */
2/*-----------------------------------------------------------------------*/
3/*- -*/
4/*- FILE: PARSE.H -*/
5/*- -*/
6/*- PURPOSE: Include file for RESTORE.C and other RESTORE source -*/
7/*- files. Defines structures and DEFINES for the DOS PARSE-*/
8/*- service routines -*/
9/*- -*/
10/*-----------------------------------------------------------------------*/
11
12
13/**********************************************************/
14/* STRUCTURE TO DEFINE ADDITIONAL COMMAND LINE DELIMITERS */
15/**********************************************************/
16struct p_parms /*;AN000;4*/
17 { /*;AN000;4*/
18 WORD parmsx_ptr; /* POINTER TO PARMS STRUCTURE *//*;AN000;4*/
19 BYTE p_num_extra; /* 1 SAYS THAT A DELIMITER LIST FOLLOWS */ /*;AN000;4*/
20 BYTE p_len_extra_delim; /* NUMBER OF ADDITIONAL DELIMITERS */ /*;AN000;4*/
21 BYTE p_extra_delim[2]; /* ADDITIONAL DELIMITERS */ /*;AN000;4*/
22 }; /*;AN000;4*/
23
24/***************************************************/
25/* STRUCTURE TO DEFINE RESTORE SYNTAX REQUIREMENTS */
26/***************************************************/
27struct p_parmsx /*;AN000;4*/
28 { /*;AN000;4*/
29 BYTE p_minpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/
30 BYTE p_maxpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/
31 WORD pos1_ptr; /* POINTER TO SOURCE FILESPEC DEF AREA*/ /*;AN000;4*/
32 WORD pos2_ptr; /* POINTER TO TARGET DRIVE DEF AREA*/ /*;AN000;4*/
33 BYTE num_sw; /* THERE ARE 8 SWITCHES (/S, /P, /M, /N, /E:, /L:, /B:, /A:) */ /*;AN000;4*/
34 WORD sw1_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/
35 WORD sw2_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/
36 WORD sw3_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/
37 WORD num_keywords; /* NUMBER OF KEYWORDS IN RESTORE SYNTAX*/ /*;AN000;4*/
38 }; /*;AN000;4*/
39
40/****************************************/
41/* STRUCTURE TO DEFINE POSITIONAL PARMS */
42/****************************************/
43struct p_pos_blk /*;AN000;4*/
44 { /*;AN000;4*/
45 WORD match_flag; /* Controls type matched */ /*;AN000;4*/
46 WORD function_flag; /* Function to be included */ /*;AN000;4*/
47 WORD result_buf; /* Result buffer address */ /*;AN000;4*/
48 WORD value_list; /* Value list address */ /*;AN000;4*/
49 BYTE nid; /* # of keyword/SW synonyms (0) *//*;AN000;4*/
50 }; /*;AN000;4*/
51
52/********************************/
53/* STRUCTURE TO DEFINE SWITCHES */
54/********************************/
55struct p_sw_blk /*;AN000;4*/
56 { /*;AN000;4*/
57 WORD p_match_flag; /* Controls type matched */ /*;AN000;4*/
58 WORD p_function_flag; /* Function should be taken */ /*;AN000;4*/
59 WORD p_result_buf; /* Result buffer address */ /*;AN000;4*/
60 WORD p_value_list; /* Value list address */ /*;AN000;4*/
61 BYTE p_nid; /* # of switches */ /*;AN000;4*/
62 BYTE switch1[3]; /* Save area for switches */ /*;AN000;4*/
63 BYTE switch2[3]; /* Save area for switches */ /*;AN000;4*/
64 BYTE switch3[3]; /* Save area for switches */ /*;AN000;4*/
65 BYTE switch4[3]; /* Save area for switches */ /*;AN000;4*/
66 }; /*;AN000;4*/
67/* */
68/*---------------------------------------------------------------------------*/
69
70/**************************/
71/* RETURN BUFFER FOR TIME */
72/**************************/
73struct timebuff /*;AN000;4*/
74 { /*;AN000;4*/
75 BYTE tb_type; /* TYPE RETURNED*/ /*;AN000;4*/
76 BYTE tb_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/
77 WORD tb_synonym_ptr; /*;AN000;4*/
78 BYTE hours; /*;AN000;4*/
79 BYTE minutes; /*;AN000;4*/
80 BYTE seconds; /*;AN000;4*/
81 BYTE hundreds; /*;AN000;4*/
82 }; /*;AN000;4*/
83
84/**************************/
85/* RETURN BUFFER FOR DATE */
86/**************************/
87struct datebuff /*;AN000;4*/
88 { /*;AN000;4*/
89 BYTE db_type; /* TYPE RETURNED*/ /*;AN000;4*/
90 BYTE db_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/
91 WORD db_synonym_ptr; /*;AN000;4*/
92 WORD year; /*;AN000;4*/
93 BYTE month; /*;AN000;4*/
94 BYTE day; /*;AN000;4*/
95 }; /*;AN000;4*/
96
97
98/*******************************************/
99/* RETURN BUFFER FOR POSITIONAL PARAMETERS */
100/*******************************************/
101struct p_result_blk /*;AN000;4*/
102 { /*;AN000;4*/
103 BYTE p_type; /* Type returned */ /*;AN000;4*/
104 BYTE p_item_tag; /* Matched item tag */ /*;AN000;4*/
105 WORD p_synonym_ptr; /* pointer to Synonym list returned *//*;AN000;4*/
106 DWORD p_string_ptr; /* Pointer to string */ /*;AN000;4*/
107 }; /* or drive number in 1st byte /*;AN000;4*/
108
109/****************************************/
110/* RETURN BUFFER FOR SWITCH INFORMATION */
111/****************************************/
112struct switchbuff /*;AN000;4*/
113 { /*;AN000;4*/
114 BYTE sw_type; /* TYPE RETURNED*/ /*;AN000;4*/
115 BYTE sw_item_tag; /* Matched item tag */ /*;AN000;4*/
116 WORD sw_synonym_ptr; /* pointer to switch entered */ /*;AN000;4*/
117 DWORD sw_string_ptr; /* Pointer to string */ /*;AN000;4*/
118 }; /*;AN000;4*/
119
diff --git a/v4.0/src/CMD/RESTORE/RT.H b/v4.0/src/CMD/RESTORE/RT.H
new file mode 100644
index 0000000..86a3bec
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RT.H
@@ -0,0 +1,272 @@
1/*  0 */
2/*---------------------------------------------------------
3/*-
4/*- RESTORE Utility include file RT.H
5/*-
6/*---------------------------------------------------------*/
7
8
9/****************************************************************************/
10/* This file contains equates for RESTORE utility */
11/* The equates for messages can be found in rt2.h */
12/****************************************************************************/
13
14#define BYTE unsigned char
15#define WORD unsigned short
16#define DWORD unsigned long
17
18#define NOERROR 0
19#define CARRY 0x0001 /*;AN000;*/
20
21
22/*******************************************/
23/* Lengths of CONTROL.xxx structures */
24/*******************************************/
25#define DHEADLEN 139 /* length of new format disk header */
26#define DIRBLKLEN 70 /* length of new format dir block */
27#define FHEADLEN34 38 /*;AN000;3 Length of new format file header */ /* !wrw */
28#define FHEADLEN33 34 /* length of DOS 3.3 file header */ /* !wrw */
29
30/****************************************************************************/
31/* The following group of definitions are used to set and test the restore */
32/* switch flags. */
33/****************************************************************************/
34
35#define PROMPT 1 /* Prompt user before restoring hidden and */
36 /* read-only files. */
37#define SUB 2 /* Restore all subdirectories too */
38#define BEFORE 4 /* Only restore files written before a date */
39#define AFTER 8 /* Only restore files written after a date */
40#define EARLIER 16 /* Only restore files written earlier then a time*/
41#define LATER 32 /* Only restore files written later than a time */
42#define Revised 64 /* Only restore files that have changed */
43#define NOTEXIST 128 /* Only restore files that no longer exist on */
44 /* the destination drive. */
45
46
47/****************************************************************************/
48/* The following group of definitions are used to set and test the */
49/* restore control flags:control_flag. */
50/****************************************************************************/
51
52#define WILDCARD 1 /* Wildcards in input filespec */
53#define OLDNEW 2 /* indicate old format or new format */
54#define CREATIT 4 /* Restore file does not exist on dest disk */
55#define FOUND 8 /* Found a file to restore */
56#define SPLITFILE 16 /* File was backed up onto 2 or more disks */
57#define SWITCHES 32 /* There are switches set */
58#define SHARERROR 64 /* There is a file not restored due to */
59 /* sharing error */
60#define PARTIAL 128 /* Set if file partially restored */
61
62/****************************************************************************/
63/* The following group of definitions are used to set and test the restore */
64/* control flags:control_flag2 */
65/****************************************************************************/
66
67#define SPLITCTL 1 /* Indicate whether control.xxx is larger */
68 /* then MAXCTRL */
69#define RTSYSTEM 2 /* The file to be restore is system file */
70 /* it has to be restored contiguously */
71#define COUNTRY 4 /*when the bit is on, country info is available */
72#define CPPC 8 /* bit = 1 when CP/DOS, otherwise, PC/DOS */
73#define SRC_HDISK 16 /* bit = 1 when the source disk is harddisk */
74#define TAR_HDISK 32 /* bit = 1 when the target disk is harddisk */
75#define OUTOF_SEQ 64 /* bit = 1 when the disk is out of sequence */
76/****************************************************************************/
77/* Miscelleneous definitions */
78/****************************************************************************/
79#define ON 1 /* the tested bit is on*/
80#define OFF 0 /* the tested bit is off */
81
82#define BACKUPID "BACKUPID.@@@" /* Used to reference that file */
83#define HEADLEN 128 /* Backup file header length */
84#define MAXARGS 11 /* Max # of arguments */
85#define MINARGS 1 /* Minimum # of arguments */
86#define MAXBUF 0xffff /* Max size of buf */
87#define DOWNSIZE 512 /* Amount to decrement memory request size */
88 /* by when doing a series of mallocs. */
89#define MAXPATH 65 /* Length of space allocate for path names */
90#define MAXFNAME 9 /* Max length of file name */
91#define MAXFEXT 4 /* Max length of file extension */
92#define MAXFSPEC 13 /* Max length of file spec. */
93#define MAXPATHF 78 /* Max length of path and file spec */
94#define MAXYEARLEN 4 /* Max length of string that represent year */
95#define MAXMONTHLEN 2 /* Max length of string that represent month */
96#define MAXDAYLEN 2 /* Max length of string that represent day */
97#define MINYEAR 1980 /* Min value of input year */
98#define MAXYEAR 2079 /* Max value of input year */
99#define MAXMONTH 12 /* Max value of input year */
100#define MAXDAY 31 /* Max value of input year */
101#define MAXHOURLEN 2 /* Max length of string that represent hour */
102#define MAXMINUTELEN 2 /* Max length of string that represent minute*/
103#define MAXSECONDLEN 2 /* Max length of string that represent second*/
104#define NUL 0 /* The null character */
105#define NULLC '\000' /* The null character */
106#define MAXCTRL 3072 /* size of buffer to contain control.xxx */
107#define BKIDLENG 7 /* the lenght of old format disk header */
108#define NEWBKIDLENG 139 /* the length of new format disk header */
109#define NOTV 0x16 /* all file attrs except vol id */
110#define ON 1 /* the tested bit is on*/
111#define OFF 0 /* the tested bit is off */
112#define TRUE 0 /* return code, no error */
113#define FALSE 1 /* return code, there is an error */
114#define TTRUE 1 /* return code, no error */
115#define FFALSE 0 /* return code, there is an error */
116#define LAST_PART 0x01 /* the flag in finfo->fflag */
117 /* if on, the file is last part of a file */
118#define COMPLETE_BIT 0x02 /* the complete bit in fheadnew->flag */
119 /* if on, the file was backed up sucessfully */
120#define USA 0
121#define EUR 1
122#define JAP 2
123#define INSTALL_SIGNAL 2 /* active signal handler routine */
124#define DEACTIVE_SIGNAL 1 /* ignor signals */
125#define CTRL_C 1 /* control_c signal */
126#define CTRL_BREAK 4 /* control break signal */
127
128/****************************************************************************/
129/* Defines for common subroutines - comgetarg and computmsg */
130/****************************************************************************/
131
132#define RESPDATA_SIZE 1 /* size of the respdata */
133#define STND_IN_DEV 0 /* standard out device */
134#define STND_OUT_DEV 1 /* standard out device */
135#define STND_ERR_DEV 2 /* standard error device */
136#define NO_RESPTYPE 0 /*response type is no user */
137 /*interaction */
138#define ANY_KEY_RESPTYPE 1 /*response type is ask user to enter*/
139 /*any key. */
140#define ENTER_Y 0 /*user enter yes as response */
141#define ENTER_N 1 /*user enter no as response */
142
143/****************************************************************************/
144/* Defines for convert date format */
145/****************************************************************************/
146
147#define HRSHIFT 11 /* shift 11 bits to get the value of hour */
148#define HRMASK 0x1F /* mask to get the value of hour */
149#define MNSHIFT 5 /* shift 5 bits to get the value of minute */
150#define MNMASK 0x3F /* mask to get the value of minute */
151#define SCMASK 0x1F /* mask to get the value of second */
152#define MOSHIFT 5 /* shift 5 bits to get the value of month */
153#define MOMASK 0x0F /* mask to get the value of month */
154#define DYMASK 0x1F /* shift 9 bits to get the value of day */
155#define YRSHIFT 9 /* mask to get the value of day */
156#define YRMASK 0x7F /* mask to get the value of year */
157#define USA 0
158#define EUR 1
159#define JAP 2
160#define LOYR 1980
161
162/****************************************************************************/
163/* Defines for subroutine set_reset_test_flag */
164/****************************************************************************/
165#define SET 0
166#define RESET 1
167#define TEST 2
168
169/****************************************************************************/
170/* Defines for file attribut byte */
171/****************************************************************************/
172#define READONLY 1 /*the file is marked read only */
173#define HIDDEN 2 /*the file is marked hidden file */
174#define SYSTEM 4 /*the file is marked system file */
175#define VOLUME 8 /*the entry contains a volume label */
176#define SUBDIR 16 /*the entry is a subdirectory name */
177#define ARCHIVE 32 /*the archieve bit of the file */
178
179/****************************************************************************/
180/* Defines for PCDOS return levels */
181/****************************************************************************/
182
183#define PC_NORMAL 0
184 /* Normal completion */
185#define PC_NOFILES 1
186 /* no fl were found to restore */
187#define PC_SHARERR 2
188 /* Some file not restored due to sharing error */
189#define PC_TUSER 3
190 /* Terminated by user */
191#define PC_OTHER 4
192 /* Terminated by user */
193/****************************************************************************/
194/* Defines for CPDOS return codes */
195/****************************************************************************/
196
197#define NORMAL NO_ERROR
198 /* Normal completion */
199#define NOFILES ERROR_FILE_NOT_FOUND
200 /* no fl were found to restore */
201#define SHARERR ERROR_SHARING_VIOLATION
202 /* Some file not restored due to sharing error */
203#define TUSER 1026
204 /* Terminated by user */
205#define INSUFMEM ERROR_NOT_ENOUGH_MEMORY
206 /* insufficient memory */
207#define NOBACKUPFILE 1027
208 /* source does not contain bk file*/
209#define INVALIDPARM ERROR_INVALID_PARAMETER
210 /* invalid parmameter */
211#define INVALIDDRIVE ERROR_INVALID_DRIVE
212 /* invalid drive */
213#define FILESEQERROR 1028
214 /* file seq error */
215#define TARGETFULL ERROR_DISK_FULL
216 /* target disk is full */
217#define UNEXPECTED 999
218 /* unexpected error */
219#define CREATIONERROR 1029
220 /* file creation error */
221 /************************************************/
222 /* Substitution List for Message Retriever */
223 /************************************************/
224/*-----------------------
225; SUBLIST Equates
226;------------------------*/
227#define SUBLIST_SIZE 11 /*;AN000;6 */
228
229#define LEFT_ALIGN 0x0 /*;AN000;6 00xxxxxx */
230#define RIGHT_ALIGN 0x80 /*;AN000;6 10xxxxxx */
231
232#define CHAR_FIELD_CHAR 0x0 /*;AN000;6 a0000000 */
233#define CHAR_FIELD_ASCIIZ 0x10 /*;AN000;6 a0010000 */
234
235#define UNSGN_BIN_BYTE 0x11 /*;AN000;6 a0010001 - Unsigned BINary to Decimal CHARacter */
236#define UNSGN_BIN_WORD 0x21 /*;AN000;6 a0100001 */
237#define UNSGN_BIN_DWORD 0x31 /*;AN000;6 a0110001 */
238
239#define SGN_BIN_BYTE 0x12 /*;AN000;6 a0010010 - Signed BINary to Decimal CHARacter */
240#define SGN_BIN_WORD 0x22 /*;AN000;6 a0100010 */
241#define SGN_BIN_DWORD 0x32 /*;AN000;6 a0110010 */
242
243#define BIN_HEX_BYTE 0x13 /*;AN000;6 a0010011 - Unsigned BINary to Hexidecimal CHARacter */
244#define BIN_HEX_WORD 0x23 /*;AN000;6 a0100011 */
245#define BIN_HEX_DWORD 0x33 /*;AN000;6 a0110011 */
246
247
248#define DATE_MDY_4 0x34 /*;AN000;6 MONTH,DAY AND YEAR (4 DIGITS)*/
249/*------------------------------------*/
250/*- MESSAGE CLASSES -*/
251/*------------------------------------*/
252#define EXTENDED 1 /*;AN000;6*/
253#define PARSEERROR 2 /*;AN000;6*/
254#define UTIL_MSG -1 /*;AN000;6*/
255
256#define CR 0x0d /*;AN000;6*/
257#define LF 0x0a /*;AN000;6*/
258/*-------------------------------
259/*- INT 21h
260/*-------------------------------*/
261#define SETLOGICALDRIVE 0x440f /*;AN000;8*/
262
263#define INSTALL_CHECK 0xB700 /*;AN000;2*/
264#define NOT_INSTALLED 0 /*;AN000;2*/
265#define GET_APPEND_VER 0xB702 /*;AN000;2*/
266#define NET_APPEND 1 /*;AN000;2*/
267#define DOS_APPEND 2 /*;AN000;2*/
268#define GET_STATE 0xB706 /*;AN000;2*/
269#define SET_STATE 0xB707 /*;AN000;2*/
270
271#define APPEND_X_BIT 0x8000 /*;AN000;2*/
272
diff --git a/v4.0/src/CMD/RESTORE/RT1.H b/v4.0/src/CMD/RESTORE/RT1.H
new file mode 100644
index 0000000..e9ab46f
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RT1.H
@@ -0,0 +1,273 @@
1/*  0 */
2/*---------------------------------------------------------
3/*-
4/*- RESTORE Utility include file RT1.H
5/*-
6/*---------------------------------------------------------*/
7
8/****************************************************************************/
9/* This file contains equates for structure definitions used in RESTORE */
10/* utility. */
11/****************************************************************************/
12
13/***************************************************************************/
14/* dheadnew - structure of disk header in CONTROL.xxx, */
15/* used for new format only */
16/***************************************************************************/
17struct disk_header_new
18 {
19 BYTE dhlength; /* length, in byte , of disk header*/
20 BYTE id[8]; /* identifies disk as a backup */
21 BYTE sequence; /* backup diskette sequence num */
22 /* (binary 1-255) */
23 BYTE command[128]; /* save area for command line */
24 /* parameters. */
25 BYTE lastdisk; /* 0ffh if last targert 0 otherwise*/
26 };
27
28
29/***************************************************************************/
30/* dirblk - structure of directory blocks in CONTROL.xxx, */
31/* used for new format only */
32/***************************************************************************/
33struct dir_block
34 {
35 BYTE dblength; /* length, in bytes, of dir block */
36 BYTE path[63];
37 /* ascii path of this directory, */
38 /* drive letter omitted */
39 WORD numentry; /* num of filenames currently in list*/
40 DWORD nextdb; /* offset of next directory block */
41 }; /* =0xffff if last dir block */
42
43
44/***************************************************************************/
45/* fheadnew - structure of file header in CONTROL.xxx, */
46/* used for new format only */
47/***************************************************************************/
48#define EXT_ATTR_FLAG 4 /*;AN000;3*/
49
50struct file_header_new
51 {
52 BYTE fhlength; /* Length, in bytes, of file header */
53 BYTE fname[12]; /* ASCII file name (from directory)*/
54 BYTE flag; /* bit 0=1 if last part of file */
55 /* bit 1=1 if it is backed up successfully */
56 /* ;AN000;3 bit 2=1 if Extended Attributes are backed up (New for DOS4.00) */
57 DWORD flength; /* Total length of the file (from directory) */
58 WORD fsequenc; /* Sequence #, for files that span */
59 DWORD offset; /* Offset in BACKUP.xxx where this segment begins */
60 DWORD partsize; /* Length of part of file on current target */
61 WORD attrib; /* File attribute (from directory) */
62 WORD ftime; /* Time when file was last Revised (from directory)*/
63 WORD fdate; /* Date when file was last Revised (from directory)*/
64 DWORD FH_EA_offset; /*;AN000;3 Offset in BACKUP.xxx where extended attrib begin */
65 };
66
67/*----------------------------------*/
68/*- EXTENDED OPEN PARAMETER LIST -*/
69/*----------------------------------*/
70#define EXTATTBUFLEN 4086 /*;AN000;3*/
71 struct parm_list /*;AN000;3*/
72 { /*;AN000;3*/
73 DWORD ext_attr_addr; /*;AN000;3*/
74 WORD num_additional; /*;AN000;3*/
75 }; /*;AN000;3*/
76
77
78
79
80
81
82
83
84
85
86/**************************************************************************/
87/* Fheadold - structure of file header, used for old format only. */
88/* There are 128 bytes totally in file header of the old */
89/* format backup disk. Only the first 85 bytes contains */
90/* meaningful information. */
91/* This is the structure attached to the beginning of every */
92/* file backed up with DOS 2.0 through 3.2 inclusive. */
93/**************************************************************************/
94struct file_header_old
95 {
96 BYTE headflg; /* 0FFh is last sequence of file, 00h if not last*/
97 BYTE disknum[2]; /* file sequence number */
98 BYTE fill1[2]; /* not used */
99 BYTE wherefrom [78]; /* asciiz path and name without drive letter*/
100 unsigned pathlen; /* length of previous field, not used in this program*/
101 char garbage[50]; /* Filler */
102 };
103
104
105
106
107/***************************************************************************/
108/* dheadold - structure of disk informtion, used by old format only. */
109/* There are 128 bytes totally in disk header of the old */
110/* format backup disk. Only the first 7 bytes contains */
111/* meaningful information. */
112/* This is the BACKUPID.@@@ file */
113/***************************************************************************/
114
115struct disk_header_old
116 {
117 BYTE diskflag; /* 0FFh if last disk, 00h if not last disk. */
118 /* initialize it to 0FFh when BACKUP.@@@ is created,*/
119 /* and zero it out when the disk is full */
120 BYTE disknum[2]; /* Sequence number of the disk. Least significant*/
121 /* byte first. */
122 BYTE diskyear[2]; /* Year, LSB first. */
123 BYTE diskday; /* Month (1 byte) and day (1 byte). */
124 BYTE diskmonth; /* Month (1 byte) and day (1 byte). */
125 };
126
127
128/***************************************************************************/
129/* timedate- structure of buffer to hold time and date data */
130/***************************************************************************/
131struct timedate {
132 unsigned int earlier_hour;
133 unsigned int earlier_minute;
134 unsigned int earlier_second;
135 unsigned int later_hour;
136 unsigned int later_minute;
137 unsigned int later_second;
138 unsigned int before_year;
139 unsigned int before_month;
140 unsigned int before_day;
141 unsigned int after_year;
142 unsigned int after_month;
143 unsigned int after_day;
144};
145/***************************************************************************/
146/* fsinfo - structure of buffer returned from dosqsinfo */
147/***************************************************************************/
148struct fsinfo { /* file system information */
149 unsigned long file_system_id; /* file system ID 4 */
150 unsigned long sectors_per_alloc_unit; /* sectors per allocation unit 4 */
151 unsigned long number_of_alloc_unit; /* number of allocation unit 4 */
152 unsigned long available_alloc_unit; /* available allocatuib unit 4 */
153 unsigned bytes_per_sector; /* number of bytes per sectors 2 */
154}; /* total byte size = 18 */
155
156#define FSINFO_BYTES sizeof(struct fsinfo) /* total # of bytes for BPB */
157
158/***************************************************************************/
159/* internat - structure of buffer returned from get country information */
160/***************************************************************************/
161struct internat {
162unsigned country_code; /* country code */
163unsigned code_page; /* country code page */
164unsigned dtformat; /* time date format */
165 /* 0-usa 1-eur 2-jap */
166BYTE currency_sym, /* Currency Symbol 5 bytes */
167 r1,
168 r2,
169 r3;
170BYTE r4; /* null terminated */
171BYTE thous_sep, /* Thousands separator 2 bytes */
172 r5; /* null terminated */
173BYTE decimal_sep, /* Decimal separator 2 bytes */
174 r6; /* null terminated */
175BYTE datesep, /* Date separator 2 bytes */
176 r7; /* null terminated */
177BYTE timesep, /* Time separator 2 bytes */
178 r8; /* null terminated */
179BYTE bit_field; /* Bit values */
180 /* Bit 0 = 0 if currency symbol first */
181 /* = 1 if currency symbol last */
182 /* Bit 1= 0 if No space after currency symbol*/
183 /* = 1 if space after currency symbol */
184BYTE currency_cents; /* Number of places after currency dec point*/
185BYTE tformat; /* 1 if 24 hour time, 0 if 12 hour time */
186unsigned long map_call; /* Address of case mapping call (DWORD) */
187 /* in real mode compatibility API */
188BYTE data_sep, /* Data list separator character */
189 r9; /* null terminated */
190unsigned ra[ 5 ]; /* reserved */
191} ;
192
193
194/***************************************************************************/
195/* Finfo - structure of file information, used for both old format and */
196/* new format. It contains the information which is common */
197/* between new and old. */
198/***************************************************************************/
199struct file_info
200 {
201 BYTE fname[MAXFSPEC+1]; /* ASCII, filename and file extension.*/
202 BYTE path[MAXPATH+1]; /* ASCII, file path, always started with \ */
203 /* and not end with \ */
204 BYTE fflag; /* last disk in case of file expanded */
205 /* bit 0 = 1 if last part of file */
206 /* In old format file header, its 0ffh if last. */
207 /* The old format has to be converted into bit0=1.*/
208 unsigned dnum; /* sequence number of the file. For file that span */
209 unsigned attrib; /* file attribute */
210 unsigned ftime; /* time when the file was created */
211 unsigned fdate; /* date when the file was created */
212 unsigned long partsize; /* part size of the file */
213 unsigned long offset; /* offset of the file in backup.xxx */
214 BYTE curdir[MAXPATH]; /* current directory of the destination disk.*/
215 /* The current directory usually is maintained to be*/
216 /* the directory that reside the file to be restored*/
217 DWORD ea_offset; /*;AN000;3 Offset in BACKUP.xxx where extended attrib begin */
218};
219
220/****************************************************************************/
221/* dfinfo - destination file information, if the destination file */
222/* is exist. Structure of file information, used for both old */
223/* format and new format. It contains the information which is*/
224/* common between new and old. */
225/****************************************************************************/
226struct dfile_info {
227BYTE fname[12]; /* ASCII, filename and file extension.*/
228BYTE path[64]; /* ASCII, file path, always started with \ and */
229 /* not end with \ */
230BYTE fflag; /* last disk in case of file expanded */
231 /* bit 0 = 1 if last part of file */
232 /* In old format file header, its 0ffh if last. */
233 /* The old format has to be converted into bit0=1.*/
234unsigned short dnum; /* sequence number of the file. For file that span */
235unsigned attrib; /* file attribute */
236unsigned ftime; /* time when the file was created */
237unsigned fdate; /* date when the file was created */
238BYTE *curdir; /* current directory of the destination disk. */
239 /* The current directory usually is maintained to be */
240 /* the directory that reside the file to be restored */
241};
242
243/***************************************************************************/
244/* dinfo - structure of disk information, used for both old format and */
245/* new format. It contains the information which is common */
246/* between new and old. */
247/***************************************************************************/
248struct disk_info {
249BYTE dflag; /* last backup disk or not */
250 /* Its 0ffh if last. 00h otherwise */
251BYTE disknum; /* sequence number of the file. For file that span */
252};
253 struct subst_list /*;AN000;6 */
254 { /*;AN000;6 */
255 BYTE sl_size1; /* Size of List */ /*;AN000;6 */
256 BYTE zero1; /* Reserved */ /*;AN000;6 */
257 char far *value1; /* Time, date, or ptr to data item*/ /*;AN000;6 */
258 BYTE one; /* n of %n */ /*;AN000;6 */
259 BYTE flags1; /* Data Type flags */ /*;AN000;6 */
260 BYTE max_width1; /* Maximum FIELD width */ /*;AN000;6 */
261 BYTE min_width1; /* Minimum FIELD width */ /*;AN000;6 */
262 BYTE pad_char1; /* Character for pad FIELD */ /*;AN000;6 */
263
264 BYTE sl_size2; /* Size of List */ /*;AN000;6 */
265 BYTE zero2; /* Reserved */ /*;AN000;6 */
266 char far *value2; /* Time; date; or ptr to data item*/ /*;AN000;6 */
267 BYTE two; /* n of %n */ /*;AN000;6 */
268 BYTE flags2; /* Data Type flags */ /*;AN000;6 */
269 BYTE max_width2; /* Maximum FIELD width */ /*;AN000;6 */
270 BYTE min_width2; /* Minimum FIELD width */ /*;AN000;6 */
271 BYTE pad_char2; /* Character for pad FIELD */ /*;AN000;6 */
272 }; /*;AN000;6 */
273
diff --git a/v4.0/src/CMD/RESTORE/RT2.H b/v4.0/src/CMD/RESTORE/RT2.H
new file mode 100644
index 0000000..95270b6
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RT2.H
@@ -0,0 +1,136 @@
1/*  0 */
2/*---------------------------------------------------------
3/*-
4/*- RESTORE Utility include file RT2.H
5/*-
6/*---------------------------------------------------------*/
7
8
9
10/*------------------------------------*/
11/* MESSAGE DEFINITIONS */
12/*------------------------------------*/
13#define INVPARM 10 /* Parse class */ /*;AN000;6*/
14
15#define INVALID_DOS_VER 1 /*;AN000;6*/
16#define SOURCE_TARGET_SAME 2 /*;AN000;6*/
17#define INVALID_NUM_PARM 3 /*;AN000;6*/
18#define PATH_NOT_FOUND 5 /*;AN000;6*/
19#define INVALID_DRIVE 6 /*;AN000;6*/
20#define NO_FILE_TO_RESTORE 7 /*;AN000;6*/
21#define INSERT_SOURCE_DISK 8 /*;AN000;6*/
22#define INSERT_TARGET_DISK 9 /*;AN000;6*/
23#define PRESS_ANY_KEY 10 /*;AN000;6*/
24#define DISK_OUT_OF_SEQUENCE 11 /*;AN000;6*/
25#define LAST_FILE_NOT_RESTORED 12 /*;AN000;6*/
26#define FILES_WERE_BACKUP_ON 13 /*;AN000;6*/
27#define SOURCE_NO_BACKUP_FILE 14 /*;AN000;6*/
28#define INSUFFICIENT_MEMORY 15 /*;AN000;6*/
29#define FILE_IS_READONLY 16 /*;AN000;6*/
30#define FILE_SEQUENCE_ERROR 17 /*;AN000;6*/
31#define FILE_CREATION_ERROR 18 /*;AN000;6*/
32#define TARGET_IS_FULL 19 /*;AN000;6*/
33#define NOT_ABLE_TO_RESTORE_FILE 20 /*;AN000;6*/
34#define RESTORE_FILE_FROM_DRIVE 21 /*;AN000;6*/
35#define FILE_WAS_CHANGED 22 /*;AN000;6*/
36#define DISKETTE_NUM 23 /*;AN000;6*/
37
38#define INV_DATE 27 /*;AN000;6*/
39#define INV_TIME 28 /*;AN000;6*/
40#define NO_SOURCE 29 /*;AN000;6*/
41#define NO_TARGET 30 /*;AN000;6*/
42#define CRLF 31 /*;AN000;6*/
43
44#define FILE_TO_BE_RESTORED 99 /*;AN000;6*/
45
46/*------------------------------------*/
47/*- MESSAGE CLASSES -*/
48/*------------------------------------*/
49#define EXTENDED 1 /*;AN000;6*/
50#define PARSEERR 2 /*;AN000;6*/
51#define UTILMSG -1 /*;AN000;6*/
52
53/* 0*/
54/*----------------------------------*/
55/*- SUBROUTINE DECLARATIONS */
56/*----------------------------------*/
57void main(int ,char *[0]);
58void set_input_switches(WORD,BYTE * *,WORD *,struct timedate *);
59void verify_input_switches(BYTE *,struct timedate *);
60int set_reset_test_flag(BYTE *,BYTE ,int );
61void separate(BYTE *,BYTE *,BYTE *,BYTE *,BYTE *);
62void initbuf(DWORD *);
63void init_control_buf(unsigned long ,unsigned int *);
64void usererror(WORD );
65void unexperror(WORD );
66void exit_routine(WORD );
67void pascal far signal_handler_routine(void );
68extern unsigned far pascal set_int24_vector(void); /*;AN000;*/
69void com_msg(WORD );
70int checkdosver(void );
71void dorestore(BYTE ,BYTE ,BYTE *,BYTE *,BYTE *,BYTE *,struct timedate *);
72void check_bkdisk_old(struct disk_header_old *, struct disk_info *,BYTE,unsigned int *);
73void check_bkdisk_new(struct disk_header_new far *,struct disk_info *,BYTE,unsigned int *,unsigned int *);
74void print_info(int ,int ,int);
75WORD pathmatch(BYTE *,BYTE *);
76WORD switchmatch(struct file_info *,BYTE,BYTE,struct timedate *);
77
78int check_flheader_old(struct file_info *,unsigned char *,unsigned int ,
79 unsigned int ,unsigned int ,unsigned long ,unsigned int ,unsigned char ,
80 unsigned char ,unsigned char *,unsigned char *,unsigned int *);
81
82int readonly_or_changed(unsigned int ,unsigned char ,unsigned char *, unsigned char *);
83int fspecmatch(char *,char *);
84WORD open_dest_file(struct file_info *,BYTE );
85void build_path_create_file(BYTE *,BYTE,BYTE,DWORD); /*;AC000;3*/
86int set_attributes_and_close(struct file_info *, BYTE);
87int dos_write_error(DWORD ,BYTE );
88int findfile_new(struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far * *,WORD far * *,unsigned int *,BYTE *);
89int findnew_new(struct file_info *,WORD *,WORD *,BYTE *,BYTE *, WORD far * *,WORD far * *,WORD *,BYTE *);
90
91 void search_src_disk_old(struct disk_info *,struct file_info *,struct disk_header_old *,
92 struct disk_header_new far *,struct file_header_new far *,
93 unsigned char,unsigned char,unsigned long,unsigned int *,unsigned char *,unsigned char *,
94 unsigned char *,unsigned char *,struct timedate *);
95
96 void search_src_disk_new(struct disk_info *,struct file_info *,struct disk_header_old *,
97 struct disk_header_new far *,struct file_header_new far *,
98 unsigned char,unsigned char,unsigned int *,unsigned long,unsigned char *,unsigned char *,
99 unsigned char *,unsigned int *,struct timedate *);
100
101int findfirst_new(struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far**,WORD far**,unsigned int *,BYTE *);
102int findnext_new (struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far**,WORD far**,unsigned int *,BYTE *);
103
104void restore_a_file(struct file_info *,struct disk_info *,unsigned long,unsigned int *,
105 struct file_header_new far *,struct disk_header_old *,struct disk_header_new far *,unsigned char,unsigned char,
106 unsigned char *,unsigned char *,unsigned char *,unsigned int *,unsigned int *);
107
108/*----------------------------------------
109/*- ADDED FOR DOS 4.00
110/*----------------------------------------*/
111int cdecl sprintf(char *,const char *, ...);
112int cdecl printf(const char *,...);
113void check_time(BYTE,BYTE,BYTE,BYTE); /*;AN000;4*//*;AC002;*/
114void check_date(WORD,BYTE,BYTE); /*;AN000;4*//*;AC002;*/
115void parse_error(WORD,BYTE); /*;AN000;4*//*;AC002;*/
116void parse_init(void); /*;AN000;4*/
117void process_switch(unsigned,char *); /*;AN000;4*//*;AC002;*/
118void check_source_drive(int,char * []); /*;AN000;4*/
119void check_target_filespec(int,char * []); /*;AN000;4*/
120void display_it(WORD,WORD,WORD,WORD,BYTE); /*;AN000;6*/
121void parse_command_line(int, char * []); /*;AN000;4*/
122void check_appendX(void); /*;AN000;2*/
123void read_in_first_dirblock(void); /* !wrw */
124void read_in_a_fileheader(void); /* !wrw */
125void read_in_next_dirblock(void); /* !wrw */
126void get_fileheader_length(void); /*;AN000;3*/
127WORD create_the_file(BYTE,DWORD); /*;AN000;3*/
128void read_the_extended_attributes(DWORD); /*;AN000;3*/
129void check_for_device_names(char * []); /*;AN000;p2591*/
130WORD chek_DBCS(char *,WORD,char); /*;AN005;*/
131void Get_DBCS_vector(void); /*;AN005;*/
132
133extern void sysloadmsg(union REGS *, union REGS *); /*_msgret *//*;AN000;6 */
134extern void sysdispmsg(union REGS *, union REGS *); /*_msgret *//*;AN000;6 */
135extern void parse (union REGS *, union REGS *); /* _parse *//*;AN000;4 */
136
diff --git a/v4.0/src/CMD/RESTORE/RTDO.C b/v4.0/src/CMD/RESTORE/RTDO.C
new file mode 100644
index 0000000..bd736b5
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTDO.C
@@ -0,0 +1,376 @@
1
2/*------------------------------------
3/* SOURCE FILE NAME: RTDO.C
4/*------------------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "direct.h"
12#include "stdio.h"
13#include "string.h"
14#include "dos.h" /*;AN000;2*/
15#include "comsub.h" /* common subroutine def'n */
16#include "doscalls.h"
17#include "error.h"
18
19BYTE *buf_pointer;
20unsigned control_file_pointer;
21unsigned src_file_handle;
22struct FileFindBuf filefindbuf;
23struct FileFindBuf dfilefindbuf;
24BYTE far *control_buf_pointer;
25unsigned int control_bufsize; /* !wrw */
26
27extern unsigned char srcddir[MAXPATH+3];
28extern unsigned char rtswitch;
29extern unsigned char control_flag;
30extern unsigned char control_flag2;
31extern unsigned control_file_handle; /* !wrw */
32extern struct subst_list sublist; /*;AN000;6 Message substitution list */
33
34/***************** START OF SPECIFICATION ********************************
35/*
36/* SUBROUTINE NAME : Dorestore
37/*
38/* DESCRIPTIVE NAME : Searching all disks and restore the matching files.
39/*
40/* FUNCTION: This routine does the following:
41/* 1. Initialize the buffer
42/* 2. Change directory to the one which will hold the first
43/* files to be restored.
44/* 3. If the source drive is removable
45/* Ouput the message to the screen for user to insert a
46/* diskette and hit a key when ready.
47/* 4. If the target drive is removable
48/* Ouput the message to the screen for user to insert a
49/* diskette and hit a key when ready.
50/* 5. Check whether the diskette contains old or new data
51/* format.
52/* 6. ouput "file were backup xx-xx-xx"
53/*
54/* For each diskette, do the following:
55/* 5. Call check_bkdisk_old or check_bkdisk_new to check whethe
56/* it is a backup diskette and whether it is in correct
57/* sequence number.
58/* 6. Call search_src_disk_old or search_src_disk_new to search
59/* the entire diskette to find matching files and
60/* restore them.
61/*
62/*
63/********************** END OF SPECIFICATIONS *******************************/
64void dorestore(srcd,destd,inpath,infname,infext,infspec,dt) /* wrw! */
65BYTE srcd;
66BYTE destd;
67BYTE *inpath;
68BYTE *infname;
69BYTE *infext;
70BYTE *infspec;
71struct timedate *dt;
72{
73 BYTE string[MAXPATH+2];
74 struct disk_header_old dheadold;
75 struct disk_header_new dheadnew;
76 struct file_header_new fheadnew;
77 struct disk_info dinfo;
78 struct file_info finfo;
79 unsigned int control_bufsize;
80 unsigned dirlen = MAXPATH;
81 WORD dyear;
82 WORD dmonth;
83 WORD dday;
84
85 BYTE c;
86 BYTE done; /*;AN000;p????*/
87 BYTE path_to_be_chdir[MAXPATH];
88 WORD srcd_num;
89 BYTE temp_srcddir[MAXPATH];
90 unsigned int dnumwant = 1;
91 DWORD bufsize;
92 BYTE temp_array1[4]; /*temparary array to build parameters for substitution list */
93 BYTE temp_array2[4];
94
95 /*declaration for dosfindfirst */
96 unsigned dirhandle = 1;
97 unsigned attribute = NOTV;
98 unsigned search_cnt = 1; /* # of entries to find */
99 unsigned buf_len = sizeof(struct FileFindBuf);
100 BYTE search_string[MAXPATHF+2];
101 WORD retcode;
102 /*end decleration for ffirst and fnext*/
103
104 union REGS qregs; /*;AN000;8*/
105 DWORD date; /*;AN000;6*/
106
107 /****************************************************************/
108 /* change dest drive directory to the one which will hold the */
109 /* first file to be restored */
110 /****************************************************************/
111 string[0] = destd;
112 string[1] = ':';
113 string[2] = NULLC;
114 strcat(string,inpath);
115 /*if chdir sucessful, save the directory in finfo->curdir*/
116 /*if fail, the path is not exist, and needs to be rebuild*/
117 if(chdir(string)==0)
118 strcpy(finfo.curdir,inpath);
119
120 /*****************************************************************/
121 /*if the source disk is hard disk get the current dir of the srcd*/
122 /* chdir the source disk to be in \backup directory */
123 /*****************************************************************/
124 /**************************************/
125 /* if the source disk is a hard disk */
126 /**************************************/
127 /* save current directory of source disk to be reset back later */
128 /* convert character srcd into integer form */
129 /**************************************/
130
131 srcd_num = (WORD)(srcd - 'A' +1);
132
133 /**************************************/
134 /* get current directory of srcd (DosQCurDir) */
135 /**************************************/
136 if ((retcode = DOSQCURDIR(srcd_num,(char far *) srcddir,(unsigned far *)&dirlen)) != 0)
137 {
138 display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
139 usererror(INVALIDDRIVE);
140 }
141
142 temp_srcddir[0] = srcd;
143 temp_srcddir[1] = ':';
144 temp_srcddir[2] = NULLC;
145 if (strlen(srcddir) != 1)
146 strcat(temp_srcddir,"\\");
147 strcat(temp_srcddir,srcddir);
148 strcpy(srcddir,temp_srcddir);
149
150 path_to_be_chdir[0] = srcd;
151 path_to_be_chdir[1] = ':';
152 path_to_be_chdir[2] = NULLC;
153 if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == TRUE)
154 strcat(path_to_be_chdir,"\\BACKUP");
155 else
156 strcat(path_to_be_chdir,"\\");
157
158 if(chdir(path_to_be_chdir)!=0)
159 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
160 usererror(NOBACKUPFILE);
161 }
162
163 /*****************************************************************/
164 /* Identify whether the inserted diskette is a old format backup */
165 /* diskette or a new format backup diskette */
166 /* BACKUP.@@@ or BACKUP.xxx with xxx numeric characters has */
167 /* to be on the diskette */
168 /*****************************************************************/
169 search_string[0] = srcd;
170 search_string[1] = ':';
171 search_string[2] = NULLC;
172 strcat(search_string, "BACKUP*.???");
173
174 /***********************/
175 /* Find the first file */
176 /***********************/
177 done = FFALSE; /*;AN000;p????*/
178
179 retcode = /*;AN000;p????*/
180 DOSFINDFIRST /*;AN000;p????*/
181 ( /*;AN000;p????*/
182 (char far *)search_string, /*;AN000;p????*/
183 (unsigned far *)&dirhandle, /*;AN000;p????*/
184 attribute, /*;AN000;p????*/
185 (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/
186 buf_len, /*;AN000;p????*/
187 (unsigned far *)&search_cnt, /*;AN000;p????*/
188 (DWORD) 0 /*;AN000;p????*/
189 ); /*;AN000;p????*/
190
191 if (retcode != NOERROR) /*;AN000;p????*/
192 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/
193 usererror(NOBACKUPFILE); /*;AN000;p????*/
194 } /*;AN000;p????*/
195
196 /*****************************/
197 /* Skip over subdirectories */
198 while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR) /*;AN000;p????*/
199 { /*;AN000;p????*/
200 search_cnt = 1; /*;AN000;p????*/
201
202 retcode = /*;AN000;p????*/
203 DOSFINDNEXT /*;AN000;p????*/
204 ( dirhandle, /*;AN000;p????*/
205 (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/
206 buf_len, /*;AN000;p????*/
207 (unsigned far *)&search_cnt /*;AN000;p????*/
208 ); /*;AN000;p????*/
209
210 if (retcode != NOERROR) /*;AN000;p????*/
211 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/
212 usererror(NOBACKUPFILE); /*;AN000;p????*/
213 } /*;AN000;p????*/
214 } /*;AN000;p????*/
215
216 /****************************************/
217 /* Loop through looking at file names */
218 /****************************************/
219 do /*;AN000;p????*/
220 { /* Is it old BACKUP ??? */ /*;AN000;p????*/
221 if (strcmp(filefindbuf.file_name,BACKUPID)==0) /*;AN000;p????*/
222 { /*;AN000;p????*/
223 set_reset_test_flag(&control_flag,OLDNEW,SET); /*;AN000;p????*/
224 done = TTRUE; /*;AN000;p????*/
225 } /*;AN000;p????*/
226 else /*;AN000;p????*/
227 { /* Is it new BACKUP ??? */ /*;AN000;p????*/
228 if ((filefindbuf.file_name[6] == '.') && /*;AN000;p????*/
229 (filefindbuf.file_name[7] >= '0') && /*;AN000;p????*/
230 (filefindbuf.file_name[7] <= '9') && /*;AN000;p????*/
231 (filefindbuf.file_name[8] >= '0') && /*;AN000;p????*/
232 (filefindbuf.file_name[8] <= '9') && /*;AN000;p????*/
233 (filefindbuf.file_name[9] >= '0') && /*;AN000;p????*/
234 (filefindbuf.file_name[9] <= '9') && /*;AN000;p????*/
235 (filefindbuf.file_name[10] == NULLC) ) /*;AN000;p????*/
236 { /*;AN000;p????*/
237 set_reset_test_flag(&control_flag,OLDNEW,RESET); /*;AN000;p????*/
238 init_control_buf((unsigned long)0,&control_bufsize);/*;AN000;p????*/
239 done = TTRUE; /*;AN000;p????*/
240 } /*;AN000;p????*/
241 }
242
243 if (!done)
244 do
245 { /*;AN000;p????*/
246 search_cnt = 1; /*;AN000;p????*/
247 retcode = /*;AN000;p????*/
248 DOSFINDNEXT /*;AN000;p????*/
249 ( dirhandle, /*;AN000;p????*/
250 (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/
251 buf_len, /*;AN000;p????*/
252 (unsigned far *)&search_cnt /*;AN000;p????*/
253 ); /*;AN000;p????*/
254
255 if (retcode != NOERROR) /*;AN000;p????*/
256 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/
257 usererror(NOBACKUPFILE); /*;AN000;p????*/
258 } /*;AN000;p????*/
259
260 } /* end while */ /*;AN000;p????*/
261 while(filefindbuf.attributes & SUBDIR == SUBDIR);
262
263 } /* end DO loop */ /*;AN000;p????*/
264 while (!done); /*;AN000;p????*/
265
266
267 retcode = DOSFINDCLOSE(dirhandle);
268
269 /***************************************/
270 /* Display the date of the backup disk */
271 /***************************************/
272 dyear = (filefindbuf.write_date >> YRSHIFT & YRMASK) + LOYR;
273 dmonth = filefindbuf.write_date >> MOSHIFT & MOMASK;
274 dday = filefindbuf.write_date & DYMASK;
275 date = dyear + (dday*16777216) + (dmonth*65536); /*;AN000;6*/
276
277 sublist.value1 = (char far *)date; /*;AN000;6*/
278 sublist.flags1 = LEFT_ALIGN + DATE_MDY_4; /*;AN000;6*/
279 sublist.max_width1 = (BYTE)10; /*;AN000;6*/
280 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
281 display_it(FILES_WERE_BACKUP_ON,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
282
283 /*****************************************************************/
284 /*start a loop to check and restore each diskette */
285 /*****************************************************************/
286 initbuf(&bufsize); /* !wrw */
287
288 for (;;)
289 {
290
291 /*****************************************************************/
292 /* check whether the inserted diskette is a backup diskette */
293 /*****************************************************************/
294 /*if old, check_bkdisk_old else check_bkdisk_new*/
295
296 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
297 check_bkdisk_old(&dheadold, &dinfo, srcd, &dnumwant);
298 else
299 check_bkdisk_new((struct disk_header_new far *)&dheadnew, &dinfo, srcd, &dnumwant,&control_bufsize);
300
301 /*****************************************************************/
302 /* At this point a real backup diskette which is in correct sequence number */
303 /* has been found. In the case of new format, the file CONTROL.xxx is open.*/
304 /*****************************************************************/
305 /* restored the diskette */
306 /*****************************************************************/
307
308 /*if old*/
309 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
310 search_src_disk_old(&dinfo,&finfo,&dheadold,(struct disk_header_new far *)&dheadnew,
311 (struct file_header_new far *)&fheadnew,srcd,destd,bufsize,&dnumwant,
312 inpath,infname,infext,infspec,dt);
313 else
314 search_src_disk_new(&dinfo,&finfo,&dheadold,(struct disk_header_new far *)&dheadnew,
315 (struct file_header_new far *)&fheadnew,srcd,destd,&dnumwant,bufsize,
316 inpath,infname,infspec,&control_bufsize,dt);
317
318 printf("\n");
319 set_reset_test_flag(&control_flag2,OUTOF_SEQ,RESET);
320 /************************************************************************/
321 /*if ( bk disk is not the last one && (the file spec is WILDCARD or file*/
322 /*not found yet or SUB flag in rtswitches is on)), then prompt for user */
323 /*to insert another diskette and loop again. */
324 /************************************************************************/
325 if ((dinfo.dflag!=0xff) &&
326 ((set_reset_test_flag(&control_flag,WILDCARD,TEST) == TRUE) ||
327 (set_reset_test_flag(&control_flag,FOUND,TEST) == FALSE) ||
328 (set_reset_test_flag(&rtswitch,SUB,TEST) == TRUE)))
329 {
330 /**********************************************************/
331 /* output message for user to insert another diskette and */
332 /* "strike any key when ready" */
333 /* with response type 4 (wait for a key to be hit) */
334 /**********************************************************/
335
336 if (control_file_handle != 0xffff) /* !wrw */
337 { /* !wrw */
338 DOSCLOSE(control_file_handle); /* !wrw */
339 control_file_handle = 0xffff; /* !wrw */
340 } /* !wrw */
341
342 temp_array1[0] = (char)((dnumwant / 10) + '0');
343 temp_array1[1] = (char)((dnumwant % 10) + '0');
344 temp_array1[2] = NULLC;
345 temp_array2[0] = srcd;
346 temp_array2[1] = NULLC;
347
348 sublist.value1 = (char far *)temp_array1; /*;AN000;6 */
349 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
350 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */
351 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
352
353 sublist.value2 = (char far *)temp_array2; /*;AN000;6 */
354 sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
355 sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6 */
356 sublist.min_width2 = sublist.max_width2; /*;AN000;6 */
357
358 display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
359 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
360
361 /* If single drive system, eliminates double prompting */
362 /* for user to "Insert diskette for drive %1" */
363 qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/
364 qregs.h.bl = srcddir[0] - 'A' + 1; /*;AN000;8*/
365 intdos(&qregs,&qregs); /*;AN000;8*/
366
367 continue;
368 }
369 else
370 break;
371
372 } /*end of for loop*/
373
374
375 return;
376} /*;AN000;*/
diff --git a/v4.0/src/CMD/RESTORE/RTDO1.C b/v4.0/src/CMD/RESTORE/RTDO1.C
new file mode 100644
index 0000000..29bc973
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTDO1.C
@@ -0,0 +1,420 @@
1
2/*-----------------------------
3/* SOURCE FILE NAME: RTDO1.C
4/*-----------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "string.h"
12#include "dos.h" /*;AN000;2*/
13#include "comsub.h" /* common subroutine def'n */
14#include "doscalls.h"
15#include "error.h"
16
17struct disk_header_new russ_disk_header; /* !wrw */
18unsigned control_file_handle = 0xffff; /* !wrw */
19
20extern BYTE control_flag2;
21extern BYTE far *control_buf_pointer;
22extern unsigned control_selector;
23extern struct FileFindBuf filefindbuf;
24extern struct internat ctry; /* data area for get country info */
25extern struct subst_list sublist; /*;AN000;6 Message substitution list */
26/***************** START OF SPECIFICATION ********************************
27/*
28/* SUBROUTINE NAME : check_bkdisk_new
29/*
30/* DESCRIPTIVE NAME : For new format only, check to see whether the disk
31/* is a backup disk, and whether the disk is in right
32/* sequence.
33/*
34/* FUNCTION: The routine does the following:
35/* 1. Find the file CONTROL.xxx. If the file is not there
36/* the disk is not a backup disk.
37/* 2. validate the extension of control.xxx
38/* 3. Check the sequence number of the disk to make sure
39/* its in sequence.
40/* 4. Open the file CONTROL.xxx.
41/* 5. Read the file CONTROL.xxx in.
42/* 6. Fill dinfo with correct information.
43/* 7. Output a message to the screen to confirm that
44/* the disk is going to be restored.
45/*
46/* NOTES: This subroutine also take care of situation that user
47/* insert a old format diskette while the RESTORE started with
48/* new format diskettes.
49/*
50/* When the inserted disk does not contain the file CONTROL.xxx,
51/* a message "source file does not contains backup files" is
52/* output to the user. If the user wants to change diskette
53/* and try again, next diskette will be read.
54/*
55/* When disk is out of sequence, a 'warning' is given to user,
56/* if the user still wants to proceed the restoring by doing
57/* nothing but hit a key, the same diskette will be read again.
58/* In case of expanded file, another check for dnum of the expand
59/* file will guarantee the disk in sequence.
60/*
61/*
62/********************** END OF SPECIFICATIONS *******************************/
63void check_bkdisk_new(dheadnew, dinfo, srcd, dnumwant,control_bufsize) /* wrw! */
64
65struct disk_header_new far *dheadnew;
66struct disk_info *dinfo;
67BYTE srcd;
68unsigned int *dnumwant;
69unsigned int *control_bufsize;
70{
71 WORD dnumok = FALSE;
72 WORD disknum; /*disk number carried by the file name backup.xxx*/
73 BYTE fname_to_be_opened[13];
74 WORD numread;
75 BYTE temp_array1[4];
76 BYTE temp_array2[4];
77 BYTE c;
78 WORD read_count;
79 WORD action;
80
81
82 /*declaration for dosfindfirst */
83 unsigned dirhandle = 0xffff;
84 unsigned attribute = NOTV;
85 unsigned search_cnt = 1;
86 unsigned buf_len = sizeof(struct FileFindBuf);
87 BYTE search_string[MAXPATHF+2];
88 WORD retcode;
89 /*end decleration for ffirst and fnext*/
90 /*****************************/
91 /*search for control.xxx */
92 /*****************************/
93 for (;;)
94 {
95 /*DosFindFirst, using the filename CONTROL.???*/
96 search_string[0] = srcd;
97 search_string[1] = ':';
98 search_string[2] = NULLC;
99 strcat(search_string, "CONTROL.???");
100 dirhandle = 0xffff;
101 search_cnt = 1;
102
103 retcode = /* Find the 1st filename that */
104 DOSFINDFIRST( /* matches specified fspec*/
105 (char far *)search_string, /* File path name*/
106 (unsigned far *)&dirhandle, /* Directory search handle */
107 attribute, /* Search attribute */
108 (struct FileFindBuf far *)&filefindbuf,
109 buf_len, /* Result buffer length */
110 (unsigned far *)&search_cnt, /* Number of entries to find */
111 (DWORD) 0
112 );
113
114 if (retcode != NOERROR)
115 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
116 usererror(NOBACKUPFILE);
117 }
118 else
119 {
120 /*if the directory found is a subdirectory, find next one*/
121 while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR)
122 {
123 search_cnt = 1;
124 retcode = DOSFINDNEXT(dirhandle,
125 (struct FileFindBuf far *)&filefindbuf,
126 buf_len,
127 (unsigned far *)&search_cnt);
128 if (retcode != 0)
129 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
130 usererror(NOBACKUPFILE);
131 }
132 } /*end while */
133 } /*end of file control.xxx not found*/
134
135 retcode = DOSFINDCLOSE(dirhandle);
136
137 /********************************************************************/
138 /* validate the file extension of control.xxx to make sure they are */
139 /* three numeric characters */
140 /********************************************************************/
141 if ((filefindbuf.file_name[7] != '.') || (filefindbuf.file_name[8] < '0') ||
142 (filefindbuf.file_name[8] > '9') || (filefindbuf.file_name[9] < '0') ||
143 (filefindbuf.file_name[9] > '9') || (filefindbuf.file_name[10] < '0') ||
144 (filefindbuf.file_name[10] > '9') || (filefindbuf.file_name[11] != NULLC) )
145 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
146 usererror(NOBACKUPFILE);
147 }
148
149 /********************************************************************/
150 /* check the disk sequence number of the disk */
151 /********************************************************************/
152 if (dnumok == TRUE)
153 {
154 if (disknum != *dnumwant)
155 set_reset_test_flag(&control_flag2,OUTOF_SEQ,SET);
156 dnumok = FALSE;
157 }
158 else
159 {
160 disknum = (filefindbuf.file_name[8]-'0')*100 +
161 (filefindbuf.file_name[9]-'0')*10
162 +filefindbuf.file_name[10]-'0';
163 if (disknum != *dnumwant)
164 {
165 display_it(DISK_OUT_OF_SEQUENCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
166 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
167
168 /* When disk is out of sequence, a 'warning' is given to user. */
169 /* If the user still wants to proceed the restoring by doing */
170 /* nothing but hit a key, the same diskette will be read again.*/
171 dnumok = TRUE;
172
173 continue;
174 } /*endif*/
175 } /*endif of dnumok = FALSE*/
176
177 /********************************************************************/
178 /* open control.xxx */
179 /********************************************************************/
180 fname_to_be_opened[0] = srcd;
181 fname_to_be_opened[1] = ':';
182 fname_to_be_opened[2] = NULLC;
183 strcat(fname_to_be_opened,filefindbuf.file_name);
184
185 retcode =
186 DOSOPEN
187 ( (char far *)&fname_to_be_opened[0],
188 (unsigned far *)&control_file_handle, /* !wrw */
189 (unsigned far *)&action,
190 (DWORD)0,
191 0,
192 0x01,
193 0x00c0,
194 (DWORD)0
195 );
196
197 if (retcode != NOERROR)
198 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
199 usererror(NOBACKUPFILE);
200 }
201
202 /********************************************************************/
203 /* READ DISK_HEADER INTO STATIC DISKHEADER STRUCTURE wrw */
204 /********************************************************************/
205
206 retcode =
207 DOSREAD
208 ( /* !wrw */
209 control_file_handle, /* !wrw */
210 (char far *)&russ_disk_header, /* !wrw */
211 (unsigned short)DHEADLEN, /* !wrw */
212 (unsigned far *)&read_count /* !wrw */
213 ); /* !wrw */
214
215 if (retcode != NOERROR || (DWORD)read_count != (DWORD)DHEADLEN) /* !wrw */
216 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
217 unexperror(NOBACKUPFILE);
218 }
219
220 /********************************************************************/
221 /* get and store dheadnew information into dinfo */
222 /********************************************************************/
223 dheadnew = (struct disk_header_new far *)&russ_disk_header; /* !wrw */
224
225 dinfo->disknum = dheadnew->sequence;
226 dinfo->dflag = dheadnew->lastdisk;
227
228 /* At this point, the diskette has passed all the checking, and */
229 /* should be a ok diskette. break out of the loop.*/
230 break;
231
232 } /*end of "for (;;)" loop */
233
234 /********************************************************************/
235 /* output confirm msg "restore file from drive d:" */
236 /********************************************************************/
237 temp_array1[0] = srcd;
238 temp_array1[1] = NULLC;
239
240 sublist.value1 = (char far *)temp_array1; /*;AN000;6 */
241 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
242 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */
243 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
244
245 display_it(RESTORE_FILE_FROM_DRIVE,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
246
247 /********************************************************************/
248 /* if the source disk is removable, output diskette number also */
249 /********************************************************************/
250 if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == FALSE)
251 {
252 temp_array2[0] = (dinfo->disknum / 10) + '0';
253 temp_array2[1] = (dinfo->disknum % 10) + '0';
254 temp_array2[2] = NULLC;
255
256 sublist.value1 = (char far *)temp_array2; /*;AN000;6*/
257 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/
258 sublist.max_width1 = (BYTE)strlen(temp_array2); /*;AN000;6*/
259 sublist.min_width1 = sublist.max_width1; /*;AN000;6*/
260
261 display_it(DISKETTE_NUM,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
262 }
263
264 *dnumwant = dinfo->disknum + 1;
265
266 return; /*;AN000;*/
267} /*end of subroutine */
268
269/***************** START OF SPECIFICATION ********************************
270/*
271/* SUBROUTINE NAME : check_bkdisk_old
272/*
273/* DESCRIPTIVE NAME : For old format only, check to see whether the disk
274/* is a backup disk, and whether the disk is in right
275/* sequence.
276/*
277/* FUNCTION: The routine does the following:
278/* 1. Open the file BACKUPID.@@@. If the file is not there,
279/* the disk is not a backup disk.
280/* 3. Check the sequence number of the disk to make sure
281/* its in sequence.
282/* 4. Fill dinfo with correct information.
283/* 5. Output a message to the screen to confirm that
284/* the disk is going to be restored.
285/*
286/* NOTES: This subroutine also take care of situation that user
287/* insert a new format diskette while the RESTORE started with
288/* old format diskettes.
289/*
290/* When the inserted disk does not contain the file BACKUP.@@@,
291/* a message "source file does not contains backup files" is
292/* output to the user. If the user wants to change diskette
293/* and try again, next diskette will be read.
294/*
295/* When disk is out of sequence, a 'warning' is given to user,
296/* if the user still wants to proceed the restoring by doing
297/* nothing but hit a key, the same diskette will be read again.
298/* In case of expanded file, another check for dnum of the expand
299/* file will guarantee the disk in sequence.
300/*
301/*
302/********************** END OF SPECIFICATIONS *******************************/
303void check_bkdisk_old(dheadold, dinfo, srcd, dnumwant) /* wrw! */
304 struct disk_header_old *dheadold;
305 struct disk_info *dinfo;
306 BYTE srcd;
307 unsigned int *dnumwant;
308{
309 WORD retcode;
310 WORD action;
311
312 int dnumok = FALSE;
313 unsigned file_pointer;
314 char fname_to_be_opened[13];
315 int numread;
316 int dyear;
317 int dmonth;
318 int dday;
319 char temp_array1[4];
320 char temp_array2[4];
321 BYTE c;
322
323 /********************************************************************/
324 /* open and read backupid.@@@. Store information in backupid.@@@ */
325 /* into dinfo */
326 /********************************************************************/
327
328 for (;;)
329 {
330 fname_to_be_opened[0] = srcd;
331 fname_to_be_opened[1] = ':';
332 fname_to_be_opened[2] = NULLC;
333 strcat(fname_to_be_opened,BACKUPID);
334 retcode =
335 DOSOPEN(
336 (char far *)&fname_to_be_opened[0],(unsigned far *)&file_pointer,
337 (unsigned far *)&action,(DWORD)0,0,0x01,0x00c0,(DWORD)0
338 );
339
340 if (retcode != NOERROR)
341 { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
342 usererror(NOBACKUPFILE);
343 }
344
345 /*read BKIDLENG (7) bytes from the file and store into dheadold*/
346 retcode = DOSREAD( file_pointer,
347 (char far *)dheadold,
348 BKIDLENG,
349 (unsigned far *)&numread);
350 /*if return code of read indicate less than 11 bytes been read*/
351 if (retcode != 0 || numread < BKIDLENG) {
352 /*unexperror "source file does not contains backup files"*/
353 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
354 unexperror(NOBACKUPFILE);
355 } /*endif */
356 dinfo->disknum = dheadold->disknum[0] + dheadold->disknum[1] * 10;
357 dyear = dheadold->diskyear[0] + dheadold->diskyear[1]*256;
358 dinfo->dflag = dheadold->diskflag;
359
360 /*close the file*/
361 DOSCLOSE(file_pointer);
362
363 /********************************************************************/
364 /* check disk sequence number */
365 /********************************************************************/
366 if (dnumok == TRUE) {
367 if ((WORD)dinfo->disknum != *dnumwant) {
368 set_reset_test_flag(&control_flag2,OUTOF_SEQ,SET);
369 }
370 dnumok = FALSE;
371 }
372 else {
373 if ((WORD)dinfo->disknum != *dnumwant) {
374 /*When disk is out of sequence, a 'warning' is given to user,
375 if the user still wants to proceed the restoring by doing
376 nothing but hit a key, the same diskette will be read again.*/
377 display_it(DISK_OUT_OF_SEQUENCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
378 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
379 dnumok = TRUE;
380 continue;
381 } /*endif*/
382 } /*endif*/
383
384 /*at this point, the diskette has passed all the checking, and
385 should be a ok diskette. break out of the loop.*/
386 break;
387 } /*end of loop*/
388
389 /********************************************************************/
390 /* output a confirm msg "restoring files from drive d:" */
391 /********************************************************************/
392 temp_array1[0] = srcd;
393 temp_array1[1] = NULLC;
394 sublist.value1 = (char far *)temp_array1; /*;AN000;6 */
395 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
396 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */
397 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
398 display_it(RESTORE_FILE_FROM_DRIVE,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
399
400 /********************************************************************/
401 /* if the source disk is removable, output msg "diskette xx" */
402 /********************************************************************/
403 if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == FALSE)
404 {
405 temp_array2[0] = (dinfo->disknum / 10) + '0';
406 temp_array2[1] = (dinfo->disknum % 10) + '0';
407 temp_array2[2] = NULLC;
408
409 sublist.value1 = (char far *)temp_array2; /*;AN000;6 */
410 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
411 sublist.max_width1 = (BYTE)strlen(temp_array2); /*;AN000;6 */
412 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
413 display_it(DISKETTE_NUM,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
414 }
415
416 *dnumwant = dinfo->disknum + 1;
417 return; /*;AN000;*/
418} /*end of subroutine */
419
420 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RTFILE.C b/v4.0/src/CMD/RESTORE/RTFILE.C
new file mode 100644
index 0000000..d853f52
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTFILE.C
@@ -0,0 +1,598 @@
1
2/*----------------------------
3/* SOURCE FILE NAME: rtfile.c
4/*----------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "string.h"
12#include "stdio.h"
13#include "dos.h" /*;AN000;2*/
14#include "comsub.h" /* common subroutine def'n */
15#include "doscalls.h"
16#include "error.h"
17
18extern BYTE rtswitch;
19extern BYTE control_flag;
20extern BYTE control_flag2;
21extern BYTE filename[12];
22extern BYTE far *buf_pointer;
23extern char far *control_buf_pointer;
24extern unsigned int done_searching; /* !wrw */
25extern unsigned int numentry;
26
27unsigned dest_file_handle;
28extern unsigned src_file_handle;
29extern unsigned control_file_handle; /* !wrw */
30BYTE dest_file_spec[MAXFSPEC+3];
31extern struct FileFindBuf filefindbuf;
32extern BYTE src_fname[MAXFNAME];
33extern struct subst_list sublist; /*;AN000;6 Message substitution list */
34
35/***************** START OF SPECIFICATION *********************************/
36/* */
37/* SUBROUTINE NAME : restore_a_file */
38/* */
39/* DESCRIPTIVE NAME : restore a file found onto the destination disk. */
40/* */
41/* FUNCTION: This subroutine call open_dest_file to open the destination */
42/* file under the proper path. If the path is not found, build */
43/* the path. */
44/* It then enter a loop to do reading the source disk and */
45/* writing the destination disk until end of file. If the file */
46/* is so large that it is backed up on more than one disk, */
47/* the user is prompt to insert next diskette. In this */
48/* situation, the disk is checked for correct sequence number, */
49/* and then searched for the file to be continue restoring. */
50/* after the file is completely restored, the time, date, and */
51/* attributes of the restored file is set to be the same as */
52/* its original value. */
53/* */
54/********************** END OF SPECIFICATIONS *******************************/
55
56void restore_a_file(finfo,dinfo,bufsize,control_bufsize, /* wrw! */
57 fheadnew,dheadold,dheadnew,
58 srcd,destd,inpath,infname,infspec,dnumwant,dirhandle)
59
60 struct file_info *finfo;
61 struct disk_info *dinfo;
62 unsigned long bufsize;
63 unsigned int *control_bufsize;
64 struct file_header_new far *fheadnew;
65 struct disk_header_old *dheadold;
66 struct disk_header_new far *dheadnew;
67 BYTE srcd;
68 BYTE destd;
69 unsigned char *inpath;
70 unsigned char *infname;
71 unsigned char *infspec;
72 unsigned int *dnumwant;
73 unsigned int *dirhandle;
74{
75 BYTE c;
76 BYTE temp_array1[4];
77 BYTE temp_array2[4];
78 BYTE temp_fname[MAXFSPEC];
79 WORD action;
80 WORD first_time=TRUE;
81
82 /*declaration for dosfindfirst */
83 WORD temp_dirhandle;
84 WORD next_dirhandle;
85 unsigned attribute = NOTV; /* */
86 unsigned search_cnt = 1; /* # of entries to find */
87 unsigned buf_len = sizeof(struct FileFindBuf);
88 BYTE search_string[MAXPATHF+2];
89 /*end decleration for ffirst and fnext*/
90
91 BYTE outstring[MAXPATHF+2];
92 WORD retcode;
93 DWORD iterate_num;
94 DWORD i; /* wrw! */
95 WORD numread;
96 WORD numwrite;
97 DWORD int remainder;
98 DWORD part_size;
99 WORD file_seq_num = 1; /*when this routine is called, the first
100 part of the file already get check against the
101 file sequence number */
102 BYTE file_tobe_opened[MAXFSPEC+2];
103 WORD found = FALSE;
104 WORD *dirptr;
105 WORD *flptr;
106 WORD read_count;
107 DWORD newptr;
108 WORD next_file_pointer;
109 unsigned int dnum;
110 DWORD temp_offset;
111
112 BYTE my_own_dirpath[MAXPATH];
113 int x; /*;AN000;8*/
114 union REGS qregs; /*;AN000;8*/
115
116 /*build a string of destination file specification*/
117 dest_file_spec[0] = destd;
118 dest_file_spec[1] = ':';
119 dest_file_spec[2] = NULLC;
120 strcat(dest_file_spec,finfo->fname);
121
122 /*********************************************************************/
123 /* Open destination file, and chdir the the path where the dest file */
124 /* going to reside. If the path is not there, then create the path. */
125 /* If file sharing error, exit this routine */
126 /*********************************************************************/
127 /*open_dest_file*/
128 retcode=open_dest_file(finfo,destd);
129
130 /*if file sharring error, exit this subroutine*/
131 if (retcode == FALSE)
132 display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
133 else
134 {
135 /*setflag PARTIAL*/
136 set_reset_test_flag(&control_flag,PARTIAL,SET);
137
138 /*********************************************************************/
139 /* This loop will be processed once for each part of the source file */
140 /*********************************************************************/
141 for ( ; ; )
142 {
143
144 /*********************************************************************/
145 /* compare source file size and buf size to determine the */
146 /* iteration of reading and writing */
147 /*********************************************************************/
148 part_size = finfo->partsize;
149 /*if old*/
150 if (set_reset_test_flag(&control_flag,OLDNEW,TEST)==TRUE)
151 part_size = part_size - HEADLEN;
152
153 iterate_num = part_size / bufsize;
154 /*if remain of of filesize/bufsize != 0, add 1 to iterate_num*/
155 remainder = part_size % bufsize;
156 if (remainder > 0)
157 ++iterate_num;
158
159 /*********************************************************************/
160 /*loop through each of the iteration */
161 /*********************************************************************/
162 for (i = 1; i <= iterate_num; ++i)
163 {
164 /***************************************************************/
165 /* if old format, read from the beginning of the source file */
166 /***************************************************************/
167 /*read source file (new and old have different pointer)*/
168 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
169 {
170 retcode = DOSREAD( src_file_handle,
171 (char far *)&buf_pointer[0],
172 (unsigned)bufsize,
173 (unsigned far *)&numread);
174
175 if (retcode != 0)
176 {
177 com_msg(retcode);
178 unexperror(retcode);
179 }
180 }
181 else
182 { /*new format*/
183 /***************************************************************/
184 /* if new format, search backup.xxx for the file to be restored*/
185 /* and read it. */
186 /***************************************************************/
187 temp_offset = finfo->offset + bufsize * (i - 1);
188 retcode =
189 DOSCHGFILEPTR
190 (src_file_handle,
191 (DWORD) temp_offset,
192 (unsigned) 0,
193 (DWORD far *) &newptr
194 );
195
196 if (i == iterate_num)
197 {
198 part_size = part_size - bufsize * (iterate_num -1);
199 retcode =
200 DOSREAD
201 ( src_file_handle,
202 (char far *)&buf_pointer[0],
203 (unsigned)part_size,
204 (unsigned far *)&numread
205 );
206 }
207 else
208 {
209 retcode =
210 DOSREAD
211 (src_file_handle,
212 (char far *)&buf_pointer[0],
213 (unsigned)bufsize,
214 (unsigned far *)&numread
215 );
216
217 } /*end of i == iterate_num */
218 } /*end of new format */
219
220 /*************************************************************/
221 /* write to dest file */
222 /*************************************************************/
223 retcode =
224 DOSWRITE
225 (dest_file_handle,
226 (char far *)&buf_pointer[0],
227 (unsigned) numread,
228 (unsigned far *) &numwrite
229 );
230
231 /*************************************************************/
232 /*if the num of bytes read != num of bytes write */
233 /* call dos_write_error to find out why */
234 /*************************************************************/
235 if (numread != numwrite)
236 dos_write_error(bufsize,destd);
237 }
238 /*end iteration loop*/
239
240 /*****************************************************************/
241 /*if the file is system file, turn RTSYSTEM on */
242 /*****************************************************************/
243 if (strcmp(finfo->fname,"IBMBIO.COM")==0 ||
244 strcmp(finfo->fname,"IBMDOS.COM")==0 ||
245 strcmp(finfo->fname,"COMMAND.COM")==0 )
246 set_reset_test_flag(&control_flag2,RTSYSTEM,SET);
247
248
249 /*****************************************************************/
250 /*if the source file header indicate that this is the last disk, */
251 /* that is,it is completely copied, then exit the for loop */
252 /*****************************************************************/
253 if (set_reset_test_flag(&finfo->fflag,LAST_PART,TEST) == TRUE)
254 break; /* exit the loop */
255
256 /*****************************************************************/
257 /*The logic flow come here when the file expanded into next disk.*/
258 /* if old format, close the file handle and find handle */
259 /* if new format, close src file */
260 /*****************************************************************/
261 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
262 { /*close source file*/
263 DOSCLOSE(src_file_handle);
264
265 if (first_time == TRUE)
266 { temp_dirhandle = *dirhandle;
267 first_time = FALSE;
268 retcode = DOSFINDCLOSE(temp_dirhandle);
269 }
270 }
271 else
272 {
273 DOSCLOSE(src_file_handle);
274 DOSCLOSE(control_file_handle); /* !wrw */
275 control_file_handle = 0xffff; /* !wrw */
276 }
277
278 /*****************************************************************/
279 /* output message for user to insert another diskette */
280 /* "strike any key when ready" */
281 /* with response type 4 (wait for a key to be hit) */
282 /*****************************************************************/
283
284 if (control_file_handle != 0xffff) /* !wrw */
285 { /* !wrw */
286 DOSCLOSE(control_file_handle); /* !wrw */
287 control_file_handle = 0xffff; /* !wrw */
288 } /* !wrw */
289
290 printf("\n");
291 temp_array1[0] = (char) (*dnumwant / 10) + '0';
292 temp_array1[1] = (char) (*dnumwant % 10) + '0';
293 temp_array1[2] = NULLC;
294 temp_array2[0] = srcd;
295 temp_array2[1] = NULLC;
296
297 sublist.value1 = (char far *)temp_array1; /*;AN000;6 */
298 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
299 sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */
300 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
301
302 sublist.value2 = (char far *)temp_array2; /*;AN000;6 */
303 sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
304 sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6 */
305 sublist.min_width2 = sublist.max_width2; /*;AN000;6 */
306
307 display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
308 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
309
310 /* If single drive system, eliminates double prompting */
311 /* for user to "Insert diskette for drive %1" */
312 qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/
313 qregs.h.bl = srcd; /*;AN000;8*/
314 intdos(&qregs,&qregs); /*;AN000;8*/
315
316 /**************************************************/
317 /**************************************************/
318 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
319 check_bkdisk_old(dheadold,dinfo,srcd,dnumwant);
320 else
321 check_bkdisk_new(dheadnew,dinfo,srcd,dnumwant,control_bufsize);
322
323 /*at this point a real backup diskette which is in correct sequence
324 number has been found. In the case of new format, the file
325 CONTROL.xxx is opened.*/
326
327 /*****************************************************************/
328 /*increament file sequence number */
329 /*****************************************************************/
330 file_seq_num = file_seq_num + 1;
331
332 /*****************************************************************/
333 /* search the new disk for next part of the file */
334 /*****************************************************************/
335 if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
336 { /**************************************************************/
337 /* if old format, */
338 /*DosFindFirst:find the first file on the diskette (non-vol id*/
339 /*entry) */
340 /**************************************************************/
341 search_string[0] = srcd;
342 search_string[1] = ':';
343 search_string[2] = NULLC;
344 strcat(search_string, src_fname);
345
346 next_dirhandle = 0xffff; /* directory handle */
347
348 retcode = /* Find the 1st filename that */
349 DOSFINDFIRST( /* matches specified file spec*/
350 (char far * ) search_string, /* File path name */
351 (unsigned far * ) &next_dirhandle, /* Directory search */
352 attribute, /* Search attribute */
353 (struct FileFindBuf far *) &filefindbuf,
354 buf_len, /* Result buffer length */
355 (unsigned far * ) &search_cnt, /* Number of entries to find*/
356 (DWORD) 0
357 );
358
359 if (retcode != 0)
360 {
361 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
362 unexperror(retcode);
363 }
364
365
366 /*if the directory found is a subdirectory, find next one*/
367 while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR)
368 {
369 search_cnt = 1;
370 retcode = DOSFINDNEXT(next_dirhandle,
371 (struct FileFindBuf far *)&filefindbuf,
372 buf_len,
373 (unsigned far *)&search_cnt);
374
375 if (retcode != 0)
376 {
377 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
378 unexperror(retcode);
379 }
380
381 } /*end while */
382
383 retcode = DOSFINDCLOSE(next_dirhandle);
384
385 /*****************************************************************/
386 /* check_flheader_old: open and read file header, check dnum */
387 /* of the file, and fill fheadold and finfo with correct info*/
388 /*****************************************************************/
389 strcpy(temp_fname,filefindbuf.file_name);
390 retcode =
391 check_flheader_old
392 ( finfo, temp_fname,
393 filefindbuf.write_date, filefindbuf.write_time,
394 filefindbuf.attributes, filefindbuf.file_size,
395 file_seq_num, srcd, destd, infspec, inpath, dnumwant
396 );
397
398 if (retcode != 0)
399 {
400 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
401 unexperror(retcode);
402 }
403
404 /*****************************************************************/
405 /* check file sequence number. */
406 /*****************************************************************/
407 if (finfo->dnum != file_seq_num)
408 { display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
409 unexperror(FILESEQERROR);
410 }
411
412 }
413 else
414 { /*new format*/
415 /**********************************************/
416 /* Find the file on the CONTROL.xxx first */
417 /**********************************************/
418
419 /* findfirst_new on the new diskette using the filename.??? */
420 retcode =
421 findfirst_new
422 ( finfo, &found, &done_searching,
423 finfo->path, finfo->fname, (WORD far **) &dirptr, /* wrw! */
424 (WORD far **) &flptr, &numentry, my_own_dirpath
425 ); /* wrw! */
426
427 while (retcode != 0 )
428 {
429 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
430 unexperror(CREATIONERROR);
431 }
432
433 if (finfo->dnum != file_seq_num)
434 { display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
435 unexperror(FILESEQERROR);
436 }
437
438 /**************************************************************/
439 /* open file backup.xxx */
440 /**************************************************************/
441 /*the current disk is one less than the disk num wanted*/
442 dnum = *dnumwant -1;
443 /*make the file name to be opened*/
444 file_tobe_opened[0] = srcd;
445 file_tobe_opened[1] = ':';
446 file_tobe_opened[2] = NULLC;
447 strcat(file_tobe_opened,"BACKUP.");
448 file_tobe_opened[9] = (char)((dnum / 100) + '0');
449 dnum = dnum % 100;
450 file_tobe_opened[10] = (char)((dnum / 10) + '0');
451 dnum = dnum % 10;
452 file_tobe_opened[11] = (char)(dnum + '0');
453 file_tobe_opened[12] = NULLC;
454
455 retcode =
456 DOSOPEN
457 ( (char far *)&file_tobe_opened[0],
458 (unsigned far *)&src_file_handle,
459 (unsigned far *)&action,
460 (DWORD)0, /*file size*/
461 0, /*file attribute*/
462 0x01, /*if file exist, open it*/
463 /*if file not exist, fail it*/
464 0x00c0, /*deny write, read only*/
465 (DWORD)0
466 ); /*reserved*/
467
468 if (retcode != 0)
469 { display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
470 unexperror(retcode);
471 }
472
473 }
474 /*end of if new format*/
475
476 /*assume the file to be continue definatly will be found on the
477 second diskette because the dnum of the file already gets checked
478 in check_bkdisk_old or check_bkdisk_new*/
479
480 /*set flag to be SPLITFILE*/
481 set_reset_test_flag(&control_flag,SPLITFILE,SET);
482
483 /*******************************************/
484 /* Display name of file is to be restored */
485 /*******************************************/
486 /*outstring = inpath\infspec*/
487 strcpy(outstring,finfo->path);
488 if (strlen(finfo->path) != 1 )
489 strcat(outstring,"\\");
490
491 strcat(outstring,finfo->fname);
492 x = strlen(outstring);
493 outstring[x] = CR; /*;AN000;6*/
494 outstring[x+1] = LF; /*;AN000;6*/
495 outstring[x+2] = NUL; /*;AN000;6*/
496 qregs.x.ax = 0x4000; /*;AN000;6*/
497 qregs.x.bx = 0x0001; /*;AN000;6*/
498 qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/
499 qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/
500 intdos(&qregs,&qregs); /*;AN000;6*/
501
502 /*loop back to do the read source and write dest until finfo->fflag
503 indicate that this is the last part of file*/
504 } /*end of for loop*/
505
506 /************************************************************************/
507 /*set_attributes_and_close: set the attributes and last write date/time */
508 /*of the file just restore to be like those of the backup file */
509 /************************************************************************/
510 set_attributes_and_close(finfo,destd);
511
512 /************************************************************************/
513 /* If old format and the file split, then find next matching file */
514 /************************************************************************/
515 if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE &&
516 set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE)
517 {
518 /*search string used for DisFindFirst = srcd:infname.**/
519 /*DosFindFirst:find the first file on the diskette (non-vol id entry)
520 using the search string*/
521 search_string[0] = srcd;
522 search_string[1] = ':';
523 search_string[2] = NULLC;
524 strcat(search_string, infname);
525 strcat(search_string, ".*");
526
527 temp_dirhandle = 0xffff;
528 retcode = /* Find the 1st filename that */
529 DOSFINDFIRST( /* matches specified file spec*/
530 ( char far * ) search_string, /* File path name */
531 ( unsigned far * ) &temp_dirhandle, /* Directory search handle*/
532 (unsigned) NOTV, /* Search attribute */
533 (struct FileFindBuf far *) &filefindbuf,
534 buf_len, /* Result buffer length */
535 ( unsigned far * ) &search_cnt, /* Number of entries to find */
536 ( DWORD) 0
537 );
538
539 /*if not found return*/
540 if (retcode != 0)
541 temp_dirhandle = 0xffff;
542 else
543 {
544
545 /*if the directory found is a subdirectory, find next one*/
546 while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR)
547 {
548 search_cnt = 1;
549 retcode = DOSFINDNEXT(temp_dirhandle,
550 (struct FileFindBuf far *)&filefindbuf,
551 buf_len,
552 (unsigned far *)&search_cnt);
553 if (retcode != 0)
554 temp_dirhandle = 0xffff;
555 } /*end while */
556
557 if(strcmp(filefindbuf.file_name,BACKUPID)==0 ||
558 strcmp(filefindbuf.file_name,src_fname)==0 )
559 {
560 retcode =DOSFINDNEXT(temp_dirhandle,
561 (struct FileFindBuf far *)&filefindbuf,
562 buf_len,
563 (unsigned far *)&search_cnt);
564
565 if (retcode != 0)
566 temp_dirhandle = 0xffff;
567
568 else
569 {
570 if(strcmp(filefindbuf.file_name,BACKUPID)==0 ||
571 strcmp(filefindbuf.file_name,src_fname)==0 )
572 {
573 retcode =DOSFINDNEXT(temp_dirhandle,
574 (struct FileFindBuf far *)&filefindbuf,
575 buf_len,
576 (unsigned far *)&search_cnt);
577
578 if (retcode != 0)
579 temp_dirhandle = 0xffff;
580 }
581
582 } /*end of the rc is 0 */
583 } /*end of if strcomp is sucessful*/
584
585 }
586 *dirhandle = temp_dirhandle;
587
588 } /*end of if the file was splitted */
589
590
591 /****************************************************************/
592 /*set FOUNDFILE flag */
593 /****************************************************************/
594 set_reset_test_flag(&control_flag,FOUND,SET);
595 } /* end of if open destination file get file sharing error */
596
597} /*end of restore_a_file subroutine*/
598 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RTFILE1.C b/v4.0/src/CMD/RESTORE/RTFILE1.C
new file mode 100644
index 0000000..722cd6c
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTFILE1.C
@@ -0,0 +1,456 @@
1
2/*------------------------------
3/* SOURCE FILE NAME: rtfile1.c
4/*------------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "direct.h"
12#include "string.h"
13#include "dos.h" /*;AN000;2*/
14#include "comsub.h" /* common subroutine def'n */
15#include "doscalls.h"
16#include "error.h"
17
18char ext_attrib_buff[4086]; /*;AN000;3*/
19
20extern BYTE rtswitch;
21extern BYTE control_flag;
22extern BYTE control_flag2;
23extern unsigned dest_file_handle;
24extern unsigned src_file_handle;
25extern BYTE far *buf_pointer;
26extern BYTE dest_file_spec[MAXFSPEC+3];
27extern struct FileFindBuf filefindbuf;
28
29extern struct file_header_new far *fheadnew; /*;AN000;3 */
30
31/* *************** START OF SPECIFICATION ********************************
32/*
33/* SUBROUTINE NAME : open_dest_file
34/*
35/* DESCRIPTIVE NAME : open the destination file and build a path to it
36/* if necessary.
37/*
38/* FUNCTION: Try to change the current directory of the destination disk
39/* to be the one the file is to be restored. If not able to
40/* do it because the directory does not exist, call
41/* build_path_create_file subroutine to build path,
42/* create the destination file and return a handle on it.
43/* If file can not be created, find out whether it is caused
44/* by file sharing error, or caused by disk full.
45/*
46/*
47/********************** END OF SPECIFICATIONS ******************************/
48WORD open_dest_file(finfo,destd)
49struct file_info *finfo;
50BYTE destd;
51{
52 BYTE fname[MAXFSPEC+2];
53 BYTE path_to_be_chdir[MAXPATH+2];
54 WORD rc;
55
56 WORD retcode;
57
58 /*declaration for dosfindfirst */
59 unsigned dirhandle = 0xffff;
60 unsigned attribute = NOTV;
61 unsigned search_cnt = 1;
62 unsigned buf_len = sizeof(struct FileFindBuf);
63 BYTE search_string[MAXPATHF+2];
64 /*end decleration for ffirst and fnext*/
65
66 /*************************************************************************
67 /*if current directory is not where the file wants to be restored and
68 /* (the file is not to be restored in root or the current directory is
69 /* not root). This is to avoid building path if the the current
70 /* directory already got updated to be the right directory (in dorestore),
71 /* or both current directory and the requested directory are root
72 /* directory
73 /**************************************************************************/
74
75 if (strcmp(finfo->path,finfo->curdir)!=0)
76 {
77 /* Change to finfo->path. If error, create the directory */
78 strcpy(finfo->curdir,finfo->path);
79 path_to_be_chdir[0] = destd;
80 path_to_be_chdir[1] = ':';
81 path_to_be_chdir[2] = NULLC;
82 strcat(path_to_be_chdir,finfo->curdir);
83 if(chdir(path_to_be_chdir)!=0)
84 {
85 build_path_create_file(finfo->path,destd,finfo->fflag,finfo->ea_offset); /*;AC000;3*/
86 if (dest_file_handle != NULLC)
87 return(TRUE);
88 }
89 }
90
91 /* Current directory is the one where files are to be restored to*/
92
93 retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/
94
95 if (retcode == NOERROR)
96 return(TRUE);
97
98 /*----------------------------------------*/
99 /*- There was an error creating target -*/
100 /*- file. Reset attribute and try again -*/
101 /*----------------------------------------*/
102 retcode =
103 DOSSETFILEMODE
104 (
105 (char far *)&dest_file_spec[0],
106 (unsigned) 0x00,
107 (DWORD) 0
108 );
109
110 retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/
111
112 if (retcode == NOERROR)
113 return(TRUE);
114 else
115 return(FALSE); /*;AC000;p1102*/
116
117
118} /*end of subroutine*/
119/* *************** START OF SPECIFICATION ********************************
120/*
121/* SUBROUTINE NAME : build_path_create_file
122/*
123/* DESCRIPTIVE NAME : Build path for the destination file, and create
124/* the file in the current direactory.
125/*
126/* FUNCTION: Rebuild the path of the file about to be restored by
127/* recreating all subdirectories needed to complete the path.
128/* Then chdir to the one which is to reside and create the
129/* file.
130/*
131/********************* END OF SPECIFICATIONS ********************************/
132void build_path_create_file(in_path,destd,fflag,ea_offset)
133BYTE *in_path;
134BYTE destd;
135BYTE fflag; /*;AN000;3*/
136DWORD ea_offset; /*;AN000;3*/
137{
138 WORD array[20];
139 int i,j;
140 BYTE path[MAXPATH+2];
141 WORD retcode;
142 BYTE cant_make = FFALSE; /*;AN000;10*/
143
144 path[0] = destd;
145 path[1] = ':';
146 path[2] = NULLC;
147 strcat(path,in_path);
148 i = strlen(path);
149 j = -1;
150
151 /* Create the path for destination file */
152 /*Loop until mkdir(path) is successful*/
153
154 while (mkdir(path) && !cant_make) /*;AC000;10*/
155 {
156 /*scan path backward until find a \ */
157 for (; path[i] != '\\'; i--)
158 if (i < 0)
159 { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
160 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/
161 cant_make = TTRUE; /*;AN000;10*/
162 break; /*;AN000;10*/
163 }
164
165 /*obtain the last subdir from the path */
166 path[i] = NULLC;
167 j++;
168 /*save the location of the last \ in an array of \ locations */
169 array[j] = i;
170 }
171
172 /*loop through the array of \ locations*/
173 i = j;
174 for (;;)
175 {
176 if (i >= 0 && !cant_make) /*;AC000;10*/
177 {
178 path[array[i]] = '\\';
179 if (mkdir(path))
180 { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
181 display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/
182 cant_make = TTRUE; /*;AN000;10*/
183 break; /*;AN000;10*/
184 }
185 --i;
186 }
187 else
188 break;
189 } /*end for loop */
190
191 chdir(path); /*;AN000;3*/
192 retcode = create_the_file(fflag,ea_offset); /*;AN000;3*/
193
194 return; /* wrw! */
195
196}
197
198/********************************************************/
199/*
200/* SUBROUTINE NAME: create_the_file
201/*
202/* DESCRIPTIVE NAME : Create the target file.
203/* Use DOS 4.00 Extended Create Function 6C00h
204/* Remember to handle Extended Attributes!
205/*
206/********************************************************/
207#define EXTENDEDOPEN 0x6c00 /*;AN000;3*/
208WORD create_the_file(fflag,ea_offset) /*;AN000;3*/
209BYTE fflag; /*;AN000;3*/
210DWORD ea_offset; /*;AN000;3*/
211{ /*;AN000;3*/
212 WORD action; /*;AN000;3*/
213 WORD retcode; /*;AN000;3*/
214 union REGS reg; /*;AN000;3*/
215 struct parm_list ea_parmlist; /*;AN000;3 Parameter list for extended open*/
216
217 if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/
218 read_the_extended_attributes(ea_offset); /*;AN000;3*/
219
220 ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/
221 ea_parmlist.num_additional = 0; /*;AN000;3*/
222
223 retcode = NOERROR; /*;AN000;3*/
224 reg.x.ax = EXTENDEDOPEN; /* Function */ /*;AN000;3*/
225 reg.x.bx = 0x2011; /* Mode */ /*;AN000;3*/
226 reg.x.bx = 0x0081; /* Mode */ /*;AN000;3*/
227 reg.x.cx = 0; /* Attribute */ /*;AN000;3*/
228 reg.x.dx = 0x112; /* Flag */ /*;AN000;3*/
229
230 reg.x.si = (WORD)&dest_file_spec[0]; /* Filename */ /*;AN000;3*/
231
232 if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/
233 reg.x.di = (WORD)&ea_parmlist; /* Parmlist */ /*;AN000;3*/
234 else
235 reg.x.di = 0xffff; /* No parmlist */ /*;AN000;3*/
236
237 intdos(&reg,&reg); /*;AN000;3*/
238 if (reg.x.cflag & CARRY) /* If there was an error /*;AN000;3*/
239 retcode = reg.x.ax; /* then set return code /*;AN000;3*/
240
241 dest_file_handle = reg.x.ax; /*;AN000;3*/
242
243 return(retcode); /*;AN000;3*/
244} /*;AN000;3*/
245/********************************************************/
246/*
247/* SUBROUTINE NAME: read_the_extended_attributes
248/*
249/* DESCRIPTIVE NAME : reads in the extended attributes
250/*
251/********************************************************/
252void read_the_extended_attributes(ea_offset) /*;AN000;3*/
253DWORD ea_offset; /*;AN000;3*/
254{ /*;AN000;3*/
255 WORD ea_len; /*;AN000;3*/
256 DWORD file_position; /*;AN000;3*/
257 WORD read_count; /*;AN000;3*/
258 WORD retcode; /*;AN000;3*/
259 /*******************************/
260 /* Seek to Extended Attributes */
261 retcode = /*;AN000;3*/
262 DOSCHGFILEPTR /*;AN000;3*/
263 ( /*;AN000;3*/
264 src_file_handle, /* Handle */ /*;AN000;3*/
265 ea_offset, /* New location */ /*;AN000;3*/
266 (BYTE)0, /* MOVE METHOD */ /*;AN000;3*/
267 (DWORD far *)&file_position /*;AN000;3*/
268 ); /*;AN000;3*/
269
270 /*************************************/
271 /* Read in Extended Attribute length */
272 retcode = /*;AN000;3*/
273 DOSREAD /*;AN000;3*/
274 ( /*;AN000;3*/
275 src_file_handle, /*;AN000;3*/
276 (char far *)&ea_len, /*;AN000;3*/
277 (unsigned short)2, /*;AN000;3*/
278 (unsigned far *)&read_count /*;AN000;3*/
279 ); /*;AN000;3*/
280
281 /***********************************/
282 /* Read in the Extended Attributes */
283 retcode = /*;AN000;3*/
284 DOSREAD /*;AN000;3*/
285 ( /*;AN000;3*/
286 src_file_handle, /*;AN000;3*/
287 (char far *)&ext_attrib_buff[0], /*;AN000;3*/
288 (unsigned short)ea_len, /*;AN000;3*/
289 (unsigned far *)&read_count /*;AN000;3*/
290 ); /*;AN000;3*/
291
292 return; /*;AN000;3*/
293} /*;AN000;3*/
294
295/* *************** START OF SPECIFICATION ********************************
296/*
297/* SUBROUTINE NAME : set_attributes_and_close
298/*
299/* DESCRIPTIVE NAME : Set the file attributes and close the file
300/*
301/* FUNCTION: Set the attributes and last write date/time of the file just
302/* restored to be like those of the backup file.
303/*
304/********************* END OF SPECIFICATIONS ********************************/
305int set_attributes_and_close(finfo,destd)
306struct file_info *finfo;
307BYTE destd;
308{
309 struct FileStatus fileinfo_buf;
310 WORD destdnum;
311 WORD buflen = sizeof(struct FileStatus);
312
313 WORD retcode;
314
315 destdnum = destd - 'A' + 1;
316
317 /************************************************************************/
318 /* call DosQFileInfo: Request date and time of the dest file */
319 /************************************************************************/
320 retcode = DOSQFILEINFO (
321 (unsigned)dest_file_handle, /* File handle */
322 (unsigned)1, /* File info data required */
323 (char far *)&fileinfo_buf, /* File info buffer */
324 (unsigned)buflen); /* File info buffer size */
325
326 /*if fail, unexperror "file creation error"*/
327 if (retcode != NOERROR)
328 { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
329 usererror(retcode);
330 }
331 /************************************************************************/
332 /* call DosSetFileInfo: Set date and time in dest file as the same date */
333 /* and time in finfo */
334 /************************************************************************/
335 fileinfo_buf.write_date = finfo->fdate;
336 fileinfo_buf.write_time = finfo->ftime;
337 retcode = DOSSETFILEINFO (
338 (unsigned)dest_file_handle, /* File handle */
339 (unsigned)1, /* File info data required */
340 (char far *)&fileinfo_buf, /* File info buffer */
341 (unsigned)buflen); /* File info buffer size */
342
343 /*if fail, unexperror "file creation error"*/
344 if (retcode != NOERROR)
345 { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
346 usererror(retcode);
347 }
348
349 /******************************************************************/
350 /*close dest file */
351 /******************************************************************/
352 DOSCLOSE(dest_file_handle);
353
354 /******************************************************************/
355 /*DosSetFileMode to set file attrib of d:infspec(from input line) */
356 /*to be the attrib in finfo structure */
357 /******************************************************************/
358 finfo->attrib = finfo->attrib & 0xffdf;
359 retcode =
360 DOSSETFILEMODE
361 (
362 (char far *)dest_file_spec,
363 (unsigned) finfo->attrib, (DWORD) 0
364 );
365
366
367 /******************************************************************/
368 /*reset flag PARTIAL */
369 /******************************************************************/
370 set_reset_test_flag(&control_flag,PARTIAL,RESET);
371
372return(0); /* wrw! */
373
374} /*end of subroutine*/
375
376/* *************** START OF SPECIFICATION ********************************
377/*
378/* SUBROUTINE NAME : dos_write_error
379/*
380/* DESCRIPTIVE NAME : Determine the cause of the error during
381/* DOS write, and output message according to it.
382/*
383/* FUNCTION: If error returned from get free space of the disk
384/* is caused by disk full, a message "target disk is
385/* full" is output to the user.
386/* Otherwise, the error is caused by other reason, and
387/* a message "file creation error" is output to the user.
388/*
389/*
390/********************** END OF SPECIFICATIONS *******************************/
391int dos_write_error(buf_size,destd)
392DWORD buf_size;
393BYTE destd;
394{
395 DWORD free_space;
396 WORD drive_num;
397 struct fsinfo *fsinfo_buf;
398
399 WORD retcode;
400
401 /******************************************************************/
402 /*DosQFsinfo: get free space in the hard disk */
403 /******************************************************************/
404 drive_num = destd - 'A' + 1;
405 retcode = DOSQFSINFO
406 ((unsigned)drive_num, /* Drive number - 0=default, 1=A, etc */
407 (unsigned)1, /* File system info required */
408 (char far *)fsinfo_buf, /* File system info buffer */
409 (unsigned)FSINFO_BYTES /* File system info buffer size */
410 );
411
412
413 free_space = fsinfo_buf->sectors_per_alloc_unit *
414 fsinfo_buf->available_alloc_unit *
415 fsinfo_buf->bytes_per_sector;
416
417
418 /******************************************************************/
419 /*if the free space left is less than buffer size for file read */
420 /* and write, output msg "target is full", and "file creation */
421 /* error", otherwise, output "file creation error". */
422 /******************************************************************/
423 if ( free_space < buf_size)
424 { display_it(TARGET_IS_FULL,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
425
426 /*close dest file*/
427 DOSCLOSE(dest_file_handle);
428
429 if ((retcode = DOSDELETE((char far *)&dest_file_spec[0],
430 (DWORD)0)) != 0)
431 {
432 /*set file mode to 0*/
433 retcode =
434 DOSSETFILEMODE
435 (
436 (char far *)&dest_file_spec[0],
437 (unsigned) 0x00,
438 (DWORD)0
439 );
440
441 /* delete the partially completed destination file*/
442 retcode = DOSDELETE((char far *) dest_file_spec,(DWORD)0);
443 }
444
445 display_it(LAST_FILE_NOT_RESTORED,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
446 usererror(TARGETFULL);
447 }
448 else
449 { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
450 usererror(CREATIONERROR);
451 }
452 /*endif*/
453
454 return(0); /* wrw! */
455
456}/*end of subroutine*/
diff --git a/v4.0/src/CMD/RESTORE/RTNEW.C b/v4.0/src/CMD/RESTORE/RTNEW.C
new file mode 100644
index 0000000..c4c9cb6
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTNEW.C
@@ -0,0 +1,244 @@
1
2/*------------------------------
3/* SOURCE FILE NAME: RTNEW.C
4/*------------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "string.h"
12#include "dos.h" /*;AN000;2*/
13#include "comsub.h" /* common subroutine def'n */
14#include "doscalls.h"
15#include "error.h"
16
17extern BYTE control_flag;
18extern BYTE control_flag2;
19extern unsigned far *control_buf_pointer;
20extern unsigned control_file_handle; /* !wrw */
21extern unsigned src_file_handle;
22unsigned int done_searching; /* !wrw */
23unsigned int numentry;
24extern struct subst_list sublist; /*;AN000;6 Message substitution list */
25
26/***************** START OF SPECIFICATION ********************************
27/*
28/* SUBROUTINE NAME : search_src_disk_new
29/*
30/* DESCRIPTIVE NAME : For new format only, search the entire disk for
31/* matching files.
32/*
33/* FUNCTION: Call subroutine findfirst_new and fnext_new to find all the
34/* files which match the filename and file extension specified
35/* in the command line.
36/*
37/* Whenever there is a file found, subroutine filematch
38/* is called to match the file path, and file extension.
39/* If file path and file extension match the specification,
40/* subroutine switchmatch is called to match the file
41/* attributes, file modes, time, and date, then file sequence
42/* is checked.
43/*
44/* If the file matches all the specification, subroutine
45/* restore_a_file is called to actually restore the file.
46/*
47/*
48/********************* END OF SPECIFICATIONS ********************************/
49void search_src_disk_new(dinfo,finfo,dheadold,dheadnew,fheadnew, /* wrw! */
50 srcd,destd,dnumwant,buf_size,
51 inpath,infname,infspec,control_buf_size,td)
52
53 struct disk_info *dinfo;
54 struct file_info *finfo;
55 struct disk_header_new far *dheadnew;
56 struct file_header_new far *fheadnew;
57 struct disk_header_old *dheadold;
58 BYTE srcd;
59 BYTE destd;
60 unsigned int *dnumwant; /*num of next disk*/
61 unsigned long buf_size;
62 unsigned *control_buf_size;
63 unsigned char *inpath;
64 unsigned char *infname;
65 unsigned char *infspec;
66 struct timedate *td;
67
68{
69 BYTE outstring[MAXPATH+MAXFSPEC];
70 WORD file_seq_num = 1;
71 WORD first_file_on_diskette = TRUE;
72 BYTE file_tobe_opened[MAXFSPEC+2];
73 WORD dnum;
74 WORD found = FALSE;
75 WORD far *dirptr;
76 WORD far *flptr;
77 WORD retcode;
78 WORD action;
79 BYTE dir_path[MAXPATH];
80 unsigned int my_own_little_dirhandle = 0; /* !wrw */
81 union REGS qregs; /*;AN000;8*/
82 int x; /*;AN000;8*/
83
84 done_searching = FALSE; /* !wrw */
85
86 /***********************************************************************/
87 /*search the file control.xxx and try to find the file with match file */
88 /*name and file path */
89 /***********************************************************************/
90
91 retcode = findfirst_new(finfo,&found,&done_searching,inpath,
92 infspec,&dirptr,&flptr,&numentry,dir_path);
93
94 if (retcode != TRUE)
95 return;
96
97 /***********************************************************************/
98 /*open file backup.xxx */
99 /***********************************************************************/
100 /*the current disk is one less than the disk num wanted*/
101 dnum = *dnumwant -1;
102 /*make the file name to be opened*/
103 file_tobe_opened[0] = srcd;
104 file_tobe_opened[1] = ':';
105 file_tobe_opened[2] = NULLC;
106 strcat(file_tobe_opened,"BACKUP.");
107 file_tobe_opened[9] = (char)((dnum / 100) + '0');
108 dnum = dnum % 100;
109 file_tobe_opened[10] = (char)((dnum / 10) + '0');
110 dnum = dnum % 10;
111 file_tobe_opened[11] = (char)(dnum + '0');
112 file_tobe_opened[12] = NULLC;
113
114 retcode =
115 DOSOPEN
116 ((char far *)&file_tobe_opened[0],
117 (unsigned far *)&src_file_handle,
118 (unsigned far *)&action,
119 (DWORD)0,
120 0,
121 0x01,
122 0x00c0,
123 (DWORD)0
124 );
125
126
127 if (retcode != NOERROR)
128 {
129 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
130 unexperror(retcode);
131 }
132
133 /***********************************************************************/
134 /*start loop to find next until no more file found */
135 /***********************************************************************/
136 do
137 {
138 /******************************************/
139 /* if it is system file, find next one */
140 /******************************************/
141 if
142 (
143 (strcmp(finfo->fname,"IBMBIO.COM")==0 ||
144 strcmp(finfo->fname,"IBMDOS.COM")==0 ||
145 strcmp(finfo->fname,"CMD.EXE")==0 ||
146 strcmp(finfo->fname,"COMMAND.COM")==0
147 ) /*;AN003;*/
148 && strcmp(finfo->path,"\\")==0 /*;AN003;*/
149 )
150 { /* Do not RESTORE the file */
151 }
152 else
153 {
154
155 /***********************************************************************/
156 /*if there are any switches set in the input line, call switch match. */
157 /* if switchmatch returns FALSE, then find next file */
158 /***********************************************************************/
159 if ((set_reset_test_flag(&control_flag,SWITCHES,TEST) == FALSE) ||
160 (set_reset_test_flag(&control_flag,SWITCHES,TEST) == TRUE &&
161 ((retcode = switchmatch(finfo, srcd, destd, td)) == TRUE) ))
162 {
163
164 /***********************************************************************/
165 /* if the diskette is out of sequence, then do not check the sequence */
166 /* number of the 1st file. Otherwise, check sequence number */
167 /***********************************************************************/
168 if (set_reset_test_flag(&control_flag2,OUTOF_SEQ,TEST) == TRUE &&
169 first_file_on_diskette == TRUE && finfo->dnum != file_seq_num)
170 {
171 }
172 else
173 {
174 if (finfo->dnum != file_seq_num)
175 {
176 display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
177 unexperror(FILESEQERROR);
178 }
179
180 /***********************************************************************/
181 /* msg: output one line of outstring on the screen */
182 /* to confirm that a file has been restored sucessfully */
183 /***********************************************************************/
184 strcpy(outstring,finfo->path);
185 if (strlen(finfo->path) != 1 )
186 strcat(outstring,"\\");
187
188 strcat(outstring,finfo->fname);
189 x = strlen(outstring);
190 outstring[x] = CR; /*;AN000;6*/
191 outstring[x+1] = LF; /*;AN000;6*/
192 outstring[x+2] = NUL; /*;AN000;6*/
193 qregs.x.ax = 0x4000; /*;AN000;6*/
194 qregs.x.bx = 0x0001; /*;AN000;6*/
195 qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/
196 qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/
197 intdos(&qregs,&qregs); /*;AN000;6*/
198
199 /***********************************************************************/
200 /* restore the file */
201 /***********************************************************************/
202 restore_a_file(finfo,dinfo,buf_size,control_buf_size,
203 fheadnew,dheadold,dheadnew,
204 srcd,destd,inpath,infname,infspec,dnumwant,&my_own_little_dirhandle); /* wrw! */
205
206 first_file_on_diskette = FALSE;
207
208 if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE)
209 {
210 set_reset_test_flag(&control_flag,SPLITFILE,RESET);
211 /*do findfirst, the file found should be the splitted file*/
212
213 /* retcode= findfirst_new( finfo, &found, &done_searching, inpath, */
214 /* infspec, &dirptr, &flptr,&numentry,dir_path ); */
215 }
216
217 } /*end of if disk and file out of sequence*/
218
219 } /*end of if switch match is ok */
220
221 } /*end of if root directory and DOS system files */
222
223 /***********************************************************************/
224 /* if has not search to the end of the diskette, find next file */
225 /***********************************************************************/
226 if (done_searching == FALSE)
227 {
228 found = FALSE;
229 retcode= findnext_new(finfo,&found,&done_searching,inpath,infspec,
230 &dirptr,&flptr,&numentry,dir_path );
231
232 }
233 else
234 break;
235
236 } /* end do while loop */
237 while( retcode == TRUE);
238
239 DOSCLOSE(src_file_handle);
240
241return; /* !wrw */
242
243} /*end of subroutine*/
244
diff --git a/v4.0/src/CMD/RESTORE/RTNEW1.C b/v4.0/src/CMD/RESTORE/RTNEW1.C
new file mode 100644
index 0000000..c449192
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTNEW1.C
@@ -0,0 +1,627 @@
1
2/*------------------------------
3/* SOURCE FILE NAME: RTNEW1.C
4/*------------------------------
5/*  0 */
6#include "rt.h"
7#include "rt1.h"
8#include "rt2.h"
9#include "restpars.h" /*;AN000;4*/
10#include "string.h"
11#include "dos.h" /*;AN000;2*/
12#include "comsub.h" /* common subroutine def'n */
13#include "doscalls.h"
14#include "error.h"
15
16
17#define LAST_DIRBLOCK 0xffffffff /* !wrw */
18BYTE got_first_fh; /* !wrw */
19
20struct dir_block russ_dir_block; /* Current directory block /* !wrw */
21extern BYTE backup_level; /* Tells which DOS version made the BACKUP*/ /*;AN000;3*/
22
23struct file_header_new russ_file_header;/* Current file_header /* !wrw */
24unsigned short tot_num_fh_read_in; /* Num FH read in so far /* !wrw */
25unsigned short num_fh_in_buffer; /* Num FH currently in buff /* !wrw */
26unsigned short num_fh_in_buf_processed; /* Number of FH in the buffer that have been processed /* !wrw */
27struct file_header_new far *fheadnew; /* Global pointer to FH /* !wrw */
28
29
30BYTE fileheader_length; /*;AN000;3 Length of a file header */
31
32extern BYTE rtswitch;
33extern BYTE control_flag;
34extern BYTE control_flag2;
35extern char far *control_buf_pointer;
36extern unsigned control_file_handle;
37extern WORD control_bufsize; /* !wrw */
38
39
40/*  0 */
41/***************** START OF SPECIFICATION ********************************
42/*
43/* SUBROUTINE NAME : findfile_new
44/*
45/* DESCRIPTIVE NAME : Find a file with matching file name from
46/* the file CONTROL.xxx.
47/*
48/* FUNCTION: For new format only, search through all directory blocks
49/* and all file headers until a file header with matched file
50/* path, name and extension is found. also store information
51/* into fhead and finfo if file is found which match the
52/* filename and file extension specified in the command line.
53/*
54/* NOTES: Path name for comparison has to started with \ and end with \.
55/*
56/********************** END OF SPECIFICATIONS *******************************/
57int findfile_new( finfo, found, done_searching, inpath,
58 infspec, dirptr, flptr, numentry, dir_path)
59
60struct file_info *finfo;
61WORD *found;
62unsigned int *done_searching;
63BYTE *inpath;
64BYTE *infspec;
65WORD far **dirptr;
66WORD far **flptr;
67unsigned int *numentry;
68BYTE *dir_path;
69{
70 struct dir_block far *dirblk;
71 char temp_path[MAXPATH];
72 char temp_fname[MAXFSPEC];
73 WORD i;
74 WORD rc;
75
76
77 dirblk = (struct dir_block far *)&russ_dir_block; /* !wrw */
78 fheadnew = (struct file_header_new far *)&russ_file_header; /* !wrw */
79
80 /******************************************************************/
81 /* search the directory block for the one that has the right path */
82 /*******************************************************************/
83 while ((*done_searching == FALSE) && (*found == FALSE))
84 {
85 temp_path[0] = '\\';
86 for (i = 0; i <= (MAXPATH-2); ++i)
87 temp_path[i+1] = dirblk->path[i];
88
89 temp_path[MAXPATH-1] = NULLC;
90
91 /*****************************/
92 /* While path does not match */
93 /*****************************/
94
95 while (pathmatch(inpath,temp_path) == FALSE)
96 {
97 if (dirblk->nextdb == LAST_DIRBLOCK) /* !wrw */
98 {
99 *found = FALSE;
100 *done_searching = TRUE;
101 break;
102 }
103 else
104 {
105 read_in_next_dirblock(); /* !wrw */
106 temp_path[0] = '\\';
107 for (i = 0; i <= (MAXPATH-2); ++i)
108 temp_path[i+1] = dirblk->path[i];
109 temp_path[MAXPATH-1] = NULLC;
110 continue;
111 }
112 /*end of if not last dirblk*/
113
114 } /*end while loop, searching for the right path in directory block*/
115 /*if done searching, break out of the big loop to exit*/
116
117 if (*done_searching == TRUE)
118 break;
119
120 /***************************************************/
121 /* directory block with correct path has been found*/
122 /***************************************************/
123
124 /*get the total number of file headers in the directory block*/
125 *numentry = (unsigned int)russ_dir_block.numentry; /* !wrw */
126
127 if (got_first_fh == FALSE) /* !wrw */
128 read_in_a_fileheader(); /*#### /* !wrw */
129
130 /****************************************************/
131 /* search all the file headers under this directory */
132 /* block to find the one with right file name */
133 /****************************************************/
134 for (;;)
135 {
136
137 if ((rc = fheadnew->flag & COMPLETE_BIT) != COMPLETE_BIT)
138 {
139 if (*numentry)
140 --(*numentry);
141 if (*numentry==0)
142 {
143 if (dirblk->nextdb == LAST_DIRBLOCK) /* !wrw */
144 {
145 *found = FALSE;
146 *done_searching = TRUE;
147 break; /*exit FOR loop, go back to WHILE loop*/
148 }
149 else
150 {
151 read_in_next_dirblock(); /* !wrw */
152 break; /*exit FOR loop, go back to WHILE loop*/
153 }
154 }
155 else
156 {
157 read_in_a_fileheader(); /* !wrw */
158 continue;
159 }
160 }
161
162 for (i = 0; i <= (MAXFSPEC-2); ++i)
163 temp_fname[i] = fheadnew->fname[i];
164 temp_fname[MAXFSPEC-1] = NULLC;
165
166 if (fspecmatch(infspec,temp_fname)==TRUE)
167 {
168 *found = TRUE;
169 break;
170 }
171 else /* This file header is not the right one*/
172 {
173 if (*numentry)
174 --(*numentry);
175 if (*numentry == 0)
176 {
177 if (dirblk->nextdb == LAST_DIRBLOCK)
178 {
179 *found = FALSE;
180 *done_searching = TRUE;
181 break; /*exit FOR loop, go back to WHILE loop*/
182 }
183 else
184 {
185 read_in_next_dirblock(); /* !wrw */
186 break;
187 } /*end of if not last dir block */
188 }
189 else /*point to the next file header and loop again*/
190 read_in_a_fileheader(); /* !wrw */
191
192 }
193
194 } /* end for (;;) loop to search all file headers in a directory block */
195
196 } /*end of while loop*/
197
198
199
200 /*******************************************************************/
201 /* if a file is found, save the information in the disk header and */
202 /* file header */
203 /*******************************************************************/
204 if (*found == TRUE)
205 {
206 /* Store information from dir blk into finfo */
207 if (strcmp(dir_path,"no path from fnext") == 0)
208 strcpy(finfo->path,temp_path);
209 else
210 {
211 finfo->path[0] = '\\';
212 finfo->path[1] = NULLC;
213 strcat(finfo->path,dir_path);
214 }
215
216 /*store information from file header into finfo*/
217 for (i = 0; i <= (MAXFSPEC-2); ++i)
218 finfo->fname[i] = fheadnew->fname[i];
219 finfo->fname[MAXFSPEC-1] = NULLC;
220 finfo->fflag = fheadnew->flag;
221 finfo->dnum = fheadnew->fsequenc;
222 finfo->ftime = fheadnew->ftime;
223 finfo->fdate = fheadnew->fdate;
224 finfo->attrib = fheadnew->attrib;
225 finfo->partsize = fheadnew->partsize;
226 finfo->offset = fheadnew->offset;
227
228 if ((fheadnew->flag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/
229 finfo->ea_offset = fheadnew->FH_EA_offset; /*;AN000;3*/
230
231 if (*numentry)
232 --(*numentry);
233
234 if (*numentry == 0)
235 {
236 if (dirblk->nextdb == LAST_DIRBLOCK)
237 *done_searching = TRUE;
238 else
239 {
240 read_in_next_dirblock(); /* !wrw */
241 read_in_a_fileheader(); /* !wrw */
242 *numentry = dirblk->numentry;
243 }
244 }
245 else
246 read_in_a_fileheader(); /* !wrw */
247
248 *dirptr=(WORD far *)dirblk;
249 *flptr=(WORD far *)fheadnew;
250
251 return (TRUE);
252 } /*end of if found */
253 else
254 return (FALSE);
255
256 return(TRUE); /*;AN000;*/
257} /*end of subroutine */
258
259/*  0 */
260/***************** START OF SPECIFICATION ********************************
261/*
262/* SUBROUTINE NAME : findnext_new
263/*
264/* DESCRIPTIVE NAME : For new format only, continue at the point
265/* findfirst_new or previous findnext_new exit, search
266/* the entire file of CONTROL.xxx to find matching file
267/* names.
268/*
269/* FUNCTION: Continue at where findfirst_new or previous findnext_new
270/* stop, search the current directory blocks for the matching
271/* file path, if fail to find a file, then call findfile to
272/* search all directory block.
273/*
274/*
275/********************** END OF SPECIFICATIONS *******************************/
276int findnext_new(finfo, found, done_searching, in_path,
277 infspec, dirptr, flptr, numentry, dir_path)
278
279struct file_info *finfo;
280WORD *found;
281unsigned int *done_searching;
282BYTE *in_path;
283BYTE *infspec;
284WORD far **dirptr;
285WORD far **flptr;
286unsigned int *numentry;
287BYTE *dir_path;
288{
289 struct dir_block far *dirblk;
290 WORD retcode;
291 WORD i;
292 BYTE temp_fname[MAXFSPEC];
293 WORD rc;
294 char temp_path[MAXPATH];
295
296 dirblk=(struct dir_block far *)*dirptr;
297 fheadnew=(struct file_header_new far *)*flptr;
298 strcpy(dir_path,"no path from fnext");
299
300 temp_path[0] = '\\';
301 for (i = 0; i <= (MAXPATH-2); ++i)
302 temp_path[i+1] = dirblk->path[i];
303
304 temp_path[MAXPATH-1] = NULLC;
305
306 /****************************************/
307 /* Should we process this subdirectory ?*/
308 /****************************************/
309 if (pathmatch(in_path,temp_path) == TRUE)
310 {
311
312 /*************************************************/
313 /*complete the scanning current db to find a file*/
314 /*************************************************/
315 for (;;)
316 {
317 if ((rc = fheadnew->flag & COMPLETE_BIT) != COMPLETE_BIT)
318 {
319 if (*numentry)
320 --(*numentry);
321
322 if (*numentry==0)
323 {
324 if (dirblk->nextdb == LAST_DIRBLOCK)
325 {
326 *found = FALSE;
327 *done_searching = TRUE;
328 break;
329 }
330 else
331 {
332 read_in_next_dirblock(); /* !wrw */
333 break; /* !wrw */
334 }
335 } /* !wrw */
336 else /* There are more files from current dirblock. Get them */
337 { /* !wrw */
338 read_in_a_fileheader(); /* !wrw */
339 continue; /* !wrw */
340 }
341 }
342 /*endif*/
343
344 /* If this file header is the right one)*/
345 for (i = 0; i <= (MAXFSPEC-2); ++i)
346 temp_fname[i] = fheadnew->fname[i];
347
348 temp_fname[MAXFSPEC-1] = NULLC;
349
350 if (fspecmatch(infspec,temp_fname)==TRUE)
351 {
352 *found = TRUE;
353 for (i = 0; i <= (MAXPATH-2); ++i)
354 dir_path[i] = dirblk->path[i];
355 break;
356 }
357 else /*if this file header is not the right one*/
358 {
359 if (*numentry)
360 --(*numentry);
361 if (*numentry == 0) /* If no more files in this directory block */
362 {
363 if (dirblk->nextdb == LAST_DIRBLOCK) /* If this is the last dirblock on current source disk */
364 {
365 *found = FALSE;
366 *done_searching = TRUE;
367 break;
368 }
369 else
370 {
371 read_in_next_dirblock(); /* !wrw */
372 break; /* !wrw */
373 } /*end of if not last dir block */ /* !wrw */
374 } /* !wrw */
375 else /* !wrw */
376 read_in_a_fileheader(); /* !wrw */
377 }
378 } /*end loop searching all file headers in dir block */
379 } /*end of if the path match inpath*/
380
381 else
382 *found = FALSE;
383
384
385 /********************************************************************/
386 /* If fail to find a file in the current directory block, call */
387 /* filefind_new to find next. */
388 /* If already found or done searching, call findfile_new to store */
389 /* information in finfo and dinfo */
390 /********************************************************************/
391
392 *dirptr=(WORD far *)dirblk;
393 *flptr=(WORD far *)fheadnew;
394
395 retcode = findfile_new(finfo,found,done_searching,in_path,infspec,dirptr,
396 flptr,numentry, dir_path);
397
398 return(retcode);
399}
400
401/*  0 */
402/***************** START OF SPECIFICATION ********************************
403/*
404/* SUBROUTINE NAME : findfirst_new
405/*
406/* DESCRIPTIVE NAME : For new format only, search the entire file
407/* of CONTROL.xxx to find matching file names.
408/*
409/* FUNCTION: search directory blocks one after the other to find the
410/* directory block with the matching file path, then search
411/* the entire directory block to find the file with matching
412/* file name.
413/*
414/*
415/********************** END OF SPECIFICATIONS *******************************/
416int findfirst_new(finfo,found,done_searching,in_path,infspec,dirptr,flptr,numentry,dir_path)
417
418struct file_info *finfo;
419WORD *found;
420unsigned int *done_searching;
421BYTE *in_path;
422BYTE *infspec;
423WORD far **dirptr;
424WORD far **flptr;
425unsigned int *numentry;
426BYTE *dir_path;
427{
428 struct dir_block far *dirblk;
429 WORD retcode;
430
431 strcpy(dir_path,"no path from fnext");
432 dirblk = (struct dir_block far *)&russ_dir_block; /* !wrw */
433 read_in_first_dirblock(); /* !wrw */
434
435 if (got_first_fh == FALSE) /* !wrw */
436 read_in_a_fileheader(); /*### /* !wrw */
437
438 *found = FALSE;
439 *done_searching = FALSE;
440 *dirptr=(WORD far *)dirblk;
441 *flptr=(WORD far *)fheadnew;
442
443 retcode = findfile_new(finfo,found,done_searching,in_path,
444 infspec,dirptr,flptr,numentry,dir_path);
445
446 return(retcode);
447} /*end of findfirst_new */
448
449
450
451
452/*  0 */
453/*********************************************************************/
454/*
455/* SUBROUTINE NAME: read_in_next_dirblock
456/*
457/* FUNCTION:
458/* Reads in a directory block
459/* Figures out if it was put there by DOS 3.3 or 4.0
460/*********************************************************************/
461void read_in_next_dirblock() /* !wrw */
462{
463
464 WORD retcode; /* return code save area */ /* !wrw */
465 WORD read_count; /* num bytes read in */ /* !wrw */
466 DWORD file_pointer; /* current file pointer, returned by lseek !wrw */
467
468 retcode = /* !wrw */
469 DOSCHGFILEPTR /* !wrw */
470 ( /* !wrw */
471 control_file_handle, /* Handle */ /* !wrw */
472 russ_dir_block.nextdb, /* New location */ /* !wrw */
473 (BYTE)0, /* MOVE METHOD */ /* !wrw */
474 (DWORD far *)&file_pointer /* !wrw */
475 ); /* !wrw */
476
477 retcode =
478 DOSREAD
479 ( /* !wrw */
480 control_file_handle, /* !wrw */
481 (char far *)&russ_dir_block, /* !wrw */
482 (unsigned short)DIRBLKLEN, /* !wrw */
483 (unsigned far *)&read_count /* !wrw */
484 ); /* !wrw */
485 /* !wrw */
486 if (retcode != NOERROR) /* !wrw */
487 { /* !wrw */
488 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
489 unexperror(NOBACKUPFILE); /* !wrw */
490 }
491
492 got_first_fh = FALSE; /* !wrw */
493 get_fileheader_length(); /*;AN000;3*/
494
495 return; /* !wrw */
496} /* !wrw */
497
498
499/*********************************************************************/
500/*
501/* SUBROUTINE NAME: read_in_first_dirblock
502/*
503/* FUNCTION:
504/* Reads in the first directory block
505/* Figures out if it was put there by DOS 3.3 or 4.0
506/*********************************************************************/
507
508void read_in_first_dirblock() /* !wrw */
509{
510
511WORD retcode; /* return code save area */ /* !wrw */
512WORD read_count; /* num bytes read in */ /* !wrw */
513
514 /********************************************************************/
515 /* READ DIRECTORY_BLOCK INTO STATIC DATA AREA */
516 /********************************************************************/
517
518 retcode = DOSREAD( /* !wrw */
519 control_file_handle, /* !wrw */
520 (char far *)&russ_dir_block, /* !wrw */
521 (unsigned short)DIRBLKLEN, /* !wrw */
522 (unsigned far *)&read_count /* !wrw */
523 ); /* !wrw */
524
525 if (retcode != 0) /* !wrw */
526 { /* !wrw */
527 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
528 unexperror(NOBACKUPFILE); /* !wrw */
529 }
530
531 got_first_fh = FALSE; /* !wrw */
532 get_fileheader_length(); /*;AN000;3*/
533
534 return; /* end subroutine */ /* !wrw */
535} /* !wrw */
536
537/**************************************************************/
538/*
539/* SUBROUTINE: get_fileheader_length
540/*
541/* FUNCTION: Gets the length of a file header
542/* Sets BACKUP_LEVEL to indicate which
543/**************************************************************/
544void get_fileheader_length()
545{
546 WORD retcode; /*;AN000;3*/
547 WORD read_count; /*;AN000;3*/
548 DWORD file_position; /*;AN000;3*/
549
550 /* Save current file pointer */
551 retcode = /*;AN000;3*/
552 DOSCHGFILEPTR /*;AN000;3*/
553 ( /*;AN000;3*/
554 control_file_handle, /* Handle */ /*;AN000;3*/
555 (DWORD)0, /* New location *//*;AN000;3*/
556 (BYTE)1, /* MOVE METHOD *//*;AN000;3*/
557 (DWORD far *)&file_position /*;AN000;3*/
558 ); /*;AN000;3*/
559
560 if (retcode != 0) /*;AN000;3*/
561 { /*;AN000;3*/
562 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
563 unexperror(NOBACKUPFILE); /*;AN000;3*/
564 }
565
566 /* Read in file header length*/
567 retcode = /*;AN000;3*/
568 DOSREAD /*;AN000;3*/
569 ( /*;AN000;3*/
570 control_file_handle, /*;AN000;3*/
571 (char far *)&fileheader_length, /*;AN000;3*/
572 (unsigned short)2, /*;AN000;3*/
573 (unsigned far *)&read_count /*;AN000;3*/
574 ); /*;AN000;3*/
575
576 if (retcode != 0 || read_count != 2) /*;AN000;3*/
577 { /*;AN000;3*/
578 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
579 unexperror(NOBACKUPFILE); /*;AN000;3*/
580 }
581
582 /* Reset file pointer */
583 retcode = /*;AN000;3*/
584 DOSCHGFILEPTR /*;AN000;3*/
585 ( /*;AN000;3*/
586 control_file_handle, /* Handle */ /*;AN000;3*/
587 file_position, /* New location *//*;AN000;3*/
588 (BYTE)0, /* MOVE METHOD *//*;AN000;3*/
589 (DWORD far *)&file_position /*;AN000;3*/
590 ); /*;AN000;3*/
591
592 return;
593} /* end get_fileheader_length() */
594
595
596/*  0 */
597/**************************************************************/
598/*
599/* SUBROUTINE: read_in_a_fileheader
600/*
601/* FUNCTION: Reads in a file header
602/*
603/**************************************************************/
604void read_in_a_fileheader() /* !wrw */
605{ /* !wrw */
606WORD retcode; /* return code save area */ /* !wrw */
607WORD read_count; /* num bytes read in */ /* !wrw */
608
609 retcode = DOSREAD /* !wrw */
610 ( /* !wrw */
611 control_file_handle, /* !wrw */
612 (char far *)&russ_file_header, /* !wrw */
613 fileheader_length, /* !wrw */
614 (unsigned far *)&read_count /* !wrw */
615 ); /* !wrw */
616
617 if (retcode != NOERROR) /* !wrw */
618 { /* !wrw */
619 display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
620 unexperror(NOBACKUPFILE); /* !wrw */
621 } /* !wrw */
622
623 got_first_fh = TRUE; /* !wrw */
624 fheadnew = (struct file_header_new far *)&russ_file_header; /* !wrw */
625
626return; /* !wrw */
627} /* !wrw */
diff --git a/v4.0/src/CMD/RESTORE/RTOLD.C b/v4.0/src/CMD/RESTORE/RTOLD.C
new file mode 100644
index 0000000..a345d76
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTOLD.C
@@ -0,0 +1,266 @@
1
2/*----------------------------
3/* SOURCE FILE NAME: RTOLD.C
4/*----------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "string.h"
12#include "dos.h" /*;AN000;2*/
13#include "comsub.h" /* common subroutine def'n */
14#include "doscalls.h"
15#include "error.h"
16
17extern BYTE rtswitch;
18extern BYTE control_flag;
19extern BYTE control_flag2;
20extern BYTE far *buf_pointer;
21extern unsigned src_file_handle;
22extern struct FileFindBuf filefindbuf;
23extern struct subst_list sublist; /*;AN000;6 Message substitution list */
24
25/***************** START OF SPECIFICATION *********************************/
26/* */
27/* SUBROUTINE NAME : search_src_disk_old */
28/* */
29/* DESCRIPTIVE NAME : For old format only, search the entire disk for */
30/* matching files. */
31/* */
32/* FUNCTION: Using find first and find next to find all the files */
33/* which match the filename specified in the input */
34/* cammand line. */
35/* */
36/* Whenever there is a file found, subroutine filespecmatch */
37/* is called to match the file path, and file extension. */
38/* If file path and file extension match the specification, */
39/* subroutine switchmatch is called to match the file */
40/* attributes, file modes, time, and date, then file sequence */
41/* number is checked. */
42/* */
43/* If the file matches all the specification, subroutine */
44/* restore_a_file is called to actually restore the file. */
45/* */
46/* */
47/********************** END OF SPECIFICATIONS *******************************/
48void search_src_disk_old(dinfo,finfo,dheadold,dheadnew,fheadnew, /* wrw! */
49 srcd,destd,buf_size,dnumwant,
50 inpath,infname,infext,infspec,td)
51
52 struct disk_info *dinfo;
53 struct file_info *finfo;
54 struct disk_header_old *dheadold;
55 struct file_header_new far *fheadnew;
56 struct disk_header_new far *dheadnew;
57 BYTE srcd;
58 BYTE destd;
59 unsigned long buf_size;
60 unsigned int *dnumwant;
61 unsigned char *inpath;
62 unsigned char *infname;
63 unsigned char *infext;
64 unsigned char *infspec;
65 struct timedate *td;
66
67{
68 BYTE outstring[MAXPATH+MAXFSPEC];
69 WORD file_seq_num=1;
70 WORD first_file_on_diskette = TRUE;
71 WORD first_time_in_loop = TRUE;
72 WORD return_code;
73 DWORD partsize;
74 unsigned int control_bufsize;
75 BYTE temp_fname[MAXFNAME];
76 BYTE temp_path[MAXPATH];
77 WORD temp_dirhandle;
78
79
80 /*declaration for dosfindfirst */
81 unsigned dirhandle = 0xffff; /* directory handle */
82 unsigned search_cnt = 1; /* # of entries to find */
83 unsigned buf_len = sizeof(struct FileFindBuf);
84 BYTE search_string[MAXPATHF+2];
85 WORD retcode;
86 /*end decleration for ffirst and fnext*/
87 union REGS qregs; /*;AN000;8*/
88 int x; /*;AN000;8*/
89
90/*************************************************************************/
91/* FIND THE FIRST FILE ON SOURCE */
92/*************************************************************************/
93 search_string[0] = srcd;
94 search_string[1] = ':';
95 search_string[2] = NULLC;
96 strcat(search_string, infname);
97 strcat(search_string, ".*");
98
99retcode = /* Find the 1st filename that */
100 DOSFINDFIRST( /* matches specified file spec*/
101 ( char far * ) search_string, /* File path name */
102 ( unsigned far * ) &dirhandle, /* Directory search handle */
103 (unsigned) NOTV, /* Search attribute */
104 (struct FileFindBuf far *) &filefindbuf,
105 buf_len, /* Result buffer length */
106 ( unsigned far * ) &search_cnt, /* Number of entries to find */
107 ( DWORD) 0
108 );
109
110
111/*************************************************************************/
112/* IF CANNOT FIND ANY FILES ON SOURCE, RETURN */
113/*************************************************************************/
114 if (retcode != 0)
115 return;
116
117
118
119
120/*************************************************************************/
121/* start DO loop to find next until no more file found */
122/*************************************************************************/
123do
124{
125 /*if the directory found is a subdirectory, find next one*/
126 if((retcode = filefindbuf.attributes & 0x0010) != 0x0010)
127 {
128 /* SKIP BACKUPID */
129 if (strcmp(filefindbuf.file_name,BACKUPID) != 0)
130 {
131 if (first_time_in_loop == FALSE)
132 DOSCLOSE(src_file_handle);
133 else
134 first_time_in_loop = FALSE;
135
136 /*************************************************************************/
137 /*check_flheader_old: open and read file header, */
138 /*************************************************************************/
139 strcpy(temp_fname,filefindbuf.file_name);
140 retcode = check_flheader_old( finfo, temp_fname,
141 filefindbuf.write_date, filefindbuf.write_time,
142 filefindbuf.attributes, filefindbuf.file_size,
143 file_seq_num, srcd, destd, infspec, inpath, dnumwant);
144
145 if (retcode == 0) {
146
147 /*************************/
148 /* SKIP SYSTEM FILES */
149 if ((set_reset_test_flag(&control_flag2,CPPC,TEST) == FALSE) &&
150 (strcmp(finfo->fname,"IBMBIO.COM")==0 ||
151 strcmp(finfo->fname,"IBMDOS.COM")==0 ||
152 strcmp(finfo->fname,"COMMAND.COM")==0 ))
153 {}
154 else {
155
156 /*************************************************************************/
157 /*if there is any switches set in the input line */
158 /*switchmatch (this subroutine search the hard disk for the dest */
159 /*************************************************************************/
160 if ((set_reset_test_flag(&control_flag,SWITCHES,TEST) == FALSE) ||
161 (set_reset_test_flag(&control_flag,SWITCHES,TEST) == TRUE &&
162 ((retcode = switchmatch(finfo, srcd, destd, td)) == TRUE) )) {
163
164 /*************************************************************************/
165 /*if dnum in fheadold.disknum is not 1 and is not in sequence, error */
166 /*************************************************************************/
167 if (set_reset_test_flag(&control_flag2,OUTOF_SEQ,TEST) == TRUE &&
168 first_file_on_diskette == TRUE && finfo->dnum != 1)
169 {}
170 else
171 {
172 if (finfo->dnum != 1 || finfo->dnum != file_seq_num)
173 {
174 display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
175 unexperror(FILESEQERROR);
176 }
177 /*endif*/
178 /*************************************************************************/
179 /* output msg to indicate which file is to be restored */
180 /*************************************************************************/
181 /*outstring = inpath\infspec*/
182 strcpy(outstring,finfo->path);
183 if (strlen(finfo->path) != 1 )
184 strcat(outstring,"\\");
185
186 strcat(outstring,finfo->fname);
187 x = strlen(outstring);
188 outstring[x] = CR; /*;AN000;6*/
189 outstring[x+1] = LF; /*;AN000;6*/
190 outstring[x+2] = NUL; /*;AN000;6*/
191 qregs.x.ax = 0x4000; /*;AN000;6*/
192 qregs.x.bx = 0x0001; /*;AN000;6*/
193 qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/
194 qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/
195 intdos(&qregs,&qregs); /*;AN000;6*/
196
197
198 /*************************************************************************/
199 /* call restore_a_file to restore the file */
200 /*************************************************************************/
201 restore_a_file(finfo,dinfo,buf_size,&control_bufsize,
202 fheadnew,dheadold,dheadnew,
203 srcd,destd,inpath,infname,infspec,dnumwant,&dirhandle);
204
205 first_file_on_diskette = FALSE;
206
207 /*************************************************************************/
208 /* if the file just restored is a split file, and last file, exit loop */
209 /*************************************************************************/
210 if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE)
211 {
212 set_reset_test_flag(&control_flag,SPLITFILE,RESET);
213
214 if (dirhandle == 0xffff)
215 break;
216 else
217 {
218 retcode = 0;
219 continue;
220 }
221 } /*end of if file splitted*/
222
223
224 } /*end of if disk and file out of sequence*/
225 } /*end of switch match fail*/
226 } /*end of PC/DOS and it is system files*/
227 } /*end of if check file header is ok */
228 } /*end of if file name is not BACKUPID*/
229 } /*end of if the directory found is a subdirectory*/
230
231 search_cnt = 1;
232
233 retcode =
234 DOSFINDNEXT
235 (dirhandle,
236 (struct FileFindBuf far *)&filefindbuf,
237 buf_len,
238 (unsigned far *)&search_cnt
239 );
240
241}
242while(retcode == 0); /* END MAIN DO LOOP */
243
244DOSCLOSE(src_file_handle);
245/*************************************************************************/
246/* if error during findnext, error exit */
247/*************************************************************************/
248 if (retcode != ERROR_NO_MORE_FILES && retcode != 0)
249 {
250 com_msg(retcode);
251 unexperror(retcode);
252 }
253
254
255 if (dirhandle != 0xffff)
256 {
257 if ((retcode = DOSFINDCLOSE(dirhandle)) != 0)
258 {
259 com_msg(retcode);
260 unexperror(retcode);
261 }
262 }
263
264
265return;
266} /*end of subroutine*/
diff --git a/v4.0/src/CMD/RESTORE/RTOLD1.C b/v4.0/src/CMD/RESTORE/RTOLD1.C
new file mode 100644
index 0000000..25df45c
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTOLD1.C
@@ -0,0 +1,657 @@
1
2/*-------------------------------
3/* SOURCE FILE NAME: RTOLD1.C
4/*-------------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "string.h"
12#include "dos.h" /*;AN000;2*/
13#include "comsub.h" /* common subroutine def'n */
14#include "doscalls.h"
15#include "error.h"
16#include "stdio.h"
17
18extern BYTE rtswitch;
19extern BYTE control_flag;
20extern BYTE control_flag2;
21extern char far *buf_pointer;
22extern unsigned src_file_handle;
23extern struct FileFindBuf filefindbuf;
24extern struct FileFindBuf dfilefindbuf;
25BYTE src_fname[MAXFNAME];
26extern struct subst_list sublist; /*;AN000;6 Message substitution list */
27extern char response_buff[5]; /*;AN000;6*/
28struct file_header_old fheadold; /*;AN000;*/
29
30/***************** START OF SPECIFICATION ********************************
31/*
32/* SUBROUTINE NAME : pathmatch
33/*
34/* DESCRIPTIVE NAME : Compare two paths and return TRUE or FALSE
35/* according to whether they match or not.
36/*
37/* NOTES: Global characters * and ? are meaningless in the file path name
38/* Assume both path pattern and path subject are not end with \
39/*
40/* INPUT: (PARAMETERS)
41/* subject - the file path to be compared.
42/* pattern - the file path to be compared against.
43/*
44/********************** END OF SPECIFICATIONS *******************************/
45WORD pathmatch(patterns,subjects)
46
47BYTE *patterns; /* the string to be matched with */
48BYTE *subjects; /* the string to be matched */
49{
50 BYTE *pattern; /* the working pointer to point to the pattern */
51 BYTE *subject; /* the working pointer to point to the subject */
52 int z;
53
54 /*save the pointers to both strings*/
55 pattern = patterns;
56 subject = subjects;
57
58 /* loop until matched or unmatched is determined */
59 for (;;)
60 {
61 if (*pattern == *subject)
62 {
63 if (*pattern != NULLC) /* not finish scanning yet*/
64 {
65 pattern+=1; /* advance the pointer by 1 */
66 subject+=1; /* advance the pointer by 1 */
67 continue; /* continue on comparing again */
68 }
69 else
70 return(TRUE);
71 }
72 else
73 { /* if subject is longer than pattern and SUB flag in rtswitches is on */
74 if (set_reset_test_flag(&rtswitch, SUB, TEST)==TRUE)
75 {
76 if ((*pattern == NULLC && *subject == '\\') ||
77 (patterns[0] == '\\' && patterns[1] == NULLC))
78 return(TRUE);
79 else
80 return(FALSE);
81 }
82 else
83 return(FALSE);
84 }
85 }
86 return(TRUE); /*;AN000;*/
87}
88
89/***************** START OF SPECIFICATION ********************************
90/*
91/* SUBROUTINE NAME : fspecmatch
92/*
93/* DESCRIPTIVE NAME : Compare two file spec. and return TRUE or FALSE
94/* according to whether they match or not.
95/*
96/* FUNCTION: This subroutine compare the file names and file extensions
97/* to determine whether they are match or not.
98/* TRUE is returned if they are match, otherwise, FALSE
99/* is returned.
100/*
101/* NOTES: * and ? are acceptable in the file name and file extension.
102/*
103/********************** END OF SPECIFICATIONS *******************************/
104fspecmatch(patterns, subjects)
105char *patterns;
106char *subjects;
107{
108 char *pattern;
109 char *subject;
110 int z;
111
112 pattern = patterns;
113 subject = subjects;
114
115 for (;;)
116 {
117 if (*pattern == '*')
118 {
119 /*advance pointer in pattern until find '.' or nullc*/
120 for (;*pattern != '.' && *pattern != NULLC; ++pattern);
121 if (*pattern == NULLC)
122 {
123
124 /* pattern has no extension, so make sure subject doesn't either */
125 /* find end or '.' in subject */
126
127 for (;*subject != '.' && *subject != NULLC; ++subject);
128
129 if (*subject == NULLC || *(subject+1) == '.')
130 return(TRUE);
131 else /* subject has extension, so return FALSE */
132 return(FALSE);
133 }
134 else
135 {
136 if ( *(pattern+1) == '*')
137 return(TRUE);
138 else
139 {
140 /*advance pointer in subject until find '.' or nullc*/
141 for (;*subject != '.' && *subject != NULLC; ++subject);
142 if (*subject == NULLC )
143 {
144 if (*(pattern+1) != NULLC)
145 return(FALSE);
146 else
147 return(TRUE);
148 }
149 else
150 {
151 pattern+=1;
152 subject+=1;
153 continue;
154 } /*end of if *subject is not NULL*/
155 } /*end of if *(pattern+1) is not '*' */
156 } /*end of if *pattern == NULLC */
157 }
158 else
159 {
160 if (*pattern == *subject || *pattern == '?')
161 {
162 if (*pattern != NULLC)
163 {
164 pattern+=1;
165 subject+=1;
166 continue;
167 }
168 else
169 return(TRUE);
170 }
171 else
172 if (*pattern == '.' && *(pattern+1) == '*' && *subject == NULLC)
173 return(TRUE);
174 else
175 return(FALSE);
176 }
177
178 } /*end of for loop*/
179
180} /*end of subroutine */
181
182/***************** START OF SPECIFICATION ********************************
183/*
184/* SUBROUTINE NAME : switchmatch
185/*
186/* DESCRIPTIVE NAME : Check the file attributes, and/or file modes
187/* against the switches set in the input command
188/* line.
189/*
190/* FUNCTION: this subroutine search the hard disk for the dest
191/* file first. If dest file is found, the attributs of the
192/* destination file will be used for checking.
193/*
194/* Check the switches set in the input command line one by
195/* one, whenever a switch not match is found, FALSE is returne
196/* In the case a switch is match, TRUE is not returned until al
197/* switches is checked.
198/*
199/*
200/********************** END OF SPECIFICATIONS *******************************/
201WORD switchmatch(finfo, srcd, destd, td)
202struct file_info *finfo;
203BYTE srcd;
204BYTE destd;
205struct timedate *td;
206{
207 WORD yy;
208 WORD mm;
209 WORD dd;
210 WORD hh;
211 WORD mn;
212 WORD ss;
213 WORD action;
214 unsigned file_pointer;
215 WORD retcode;
216 int z;
217
218 /*declaration for dosqfileinfo*/
219 struct FileStatus fileinfo_buf;
220 WORD destdnum;
221 WORD buflen = sizeof(struct FileStatus);
222 unsigned attributes;
223
224 /*declaration for dosfindfirst */
225 unsigned ddirhandle = 0xffff;
226 unsigned attribute = NOTV;
227 unsigned search_cnt = 1;
228 unsigned buf_len = sizeof(struct FileFindBuf);
229 BYTE search_string[MAXPATHF+2];
230 /*end decleration for ffirst and fnext*/
231
232 /***********************************************************************/
233 /* Search hard file for the path and name of file about to be restored */
234 /* and get the file information of the file on the hard disk */
235 /***********************************************************************/
236 search_string[0] = destd;
237 search_string[1] = ':';
238 search_string[2] = NULLC;
239 strcat(search_string, finfo->path);
240 if (strlen(finfo->path) != 1)
241 strcat(search_string, "\\");
242 strcat(search_string, finfo->fname);
243
244 retcode = DOSOPEN( (char far *)&search_string[0],
245 (unsigned far *)&file_pointer,
246 (unsigned far *)&action,
247 (DWORD)0, /*file size*/
248 0, /*file attribute*/
249 0x01, /*if file exist, open*/
250 /*if file not exist, fail*/
251 0x00c0, /*deny write, read write access*/
252 (DWORD)0 ); /*reserved*/
253 /***********************************************************************/
254 /*if open fail (means the file does not exist on the hard disk), then */
255 /* return true */
256 /***********************************************************************/
257 if (retcode != NOERROR) {
258 /*set flag CREATIT*/
259 set_reset_test_flag(&control_flag,CREATIT,SET);
260 /*return TRUE*/
261 return (TRUE);
262 }
263 /*********************************************************************/
264 /* call DosQFileInfo: Request date and time of the dest file */
265 /*********************************************************************/
266 retcode = DOSQFILEINFO (
267 (unsigned)file_pointer, /* File handle */
268 (unsigned)1, /* File info data required */
269 (char far *)&fileinfo_buf, /* File info buffer */
270 (unsigned)buflen); /* File info buffer size */
271
272
273 if (retcode != NOERROR) {
274 com_msg(retcode);
275 unexperror(retcode);
276 }
277
278 if ((retcode = DOSQFILEMODE((char far *)&search_string[0],
279 (unsigned far *) &attributes,
280 (DWORD) 0)) !=0) {
281 com_msg(retcode);
282 unexperror(retcode);
283 }
284
285
286 DOSCLOSE(file_pointer);
287 /***********************************************************************/
288 /*if NOTEXIST flag is on */
289 /***********************************************************************/
290 if (set_reset_test_flag(&rtswitch,NOTEXIST,TEST) == TRUE) {
291 return(FALSE);
292 }
293
294 /***********************************************************************/
295 /*if BEFORE or AFTER is on, convert date into integer form */
296 /***********************************************************************/
297 if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE ||
298 set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE ) {
299 /*convert the input date into correct numbers.*/
300 /*Both new and old format have date in the form of date returned from*/
301 /*ffirst*/
302 /*the input date is in the form of: yyyyyyymmmmddddd*/
303 yy = (fileinfo_buf.write_date >> YRSHIFT & YRMASK) + LOYR;
304 mm = fileinfo_buf.write_date >> MOSHIFT & MOMASK;
305 dd = fileinfo_buf.write_date & DYMASK;
306 }
307 /*endif*/
308
309 /***********************************************************************/
310 /*if BEFORE flag is on */
311 /***********************************************************************/
312 if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE) {
313 if ( yy > td->before_year ) {
314 return(FALSE);
315 }
316
317 if (yy == td->before_year && mm > td->before_month) {
318 return(FALSE);
319 }
320
321 if (yy == td->before_year && mm == td->before_month &&
322 dd > td->before_day) {
323 return(FALSE);
324 }
325 }
326 /*endif*/
327
328 /***********************************************************************/
329 /*if AFTER flag is on */
330 /***********************************************************************/
331 if (set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE) {
332 if (yy < td->after_year ) {
333 return(FALSE);
334 }
335
336 if (yy == td->after_year && mm < td->after_month) {
337 return(FALSE);
338 }
339
340 if (yy == td->after_year && mm == td->after_month && dd < td->after_day) {
341 return(FALSE);
342 }
343 }
344 /*endif*/
345
346 /***********************************************************************/
347 /*if EARLIER or LATER is on, convert date time into integer form */
348 /***********************************************************************/
349 if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE ||
350 set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) {
351 /* convert the input time into correct numbers. */
352 /* Both new and old format have time in the form of date returned */
353 /* from ffirst. */
354 /* the input time is in the form of: hhhhhmmmmmmsssss */
355 hh = fileinfo_buf.write_time >> HRSHIFT & HRMASK;
356 mn = fileinfo_buf.write_time >> MNSHIFT & MNMASK;
357 ss = fileinfo_buf.write_time & SCMASK;
358 }
359 /*endif*/
360
361 /***********************************************************************/
362 /*if EARLIER flag is on */
363 /***********************************************************************/
364 if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE) {
365 if (hh > td->earlier_hour) {
366 return(FALSE);
367 }
368
369 if (hh == td->earlier_hour && mn > td->earlier_minute) {
370 return(FALSE);
371 }
372
373 if (hh == td->earlier_hour && mn == td->earlier_minute &&
374 ss > td->earlier_second) {
375 return(FALSE);
376 }
377 }
378 /*endif*/
379
380 /***********************************************************************/
381 /*if LATER flag is on */
382 /***********************************************************************/
383 if (set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) {
384 if (hh < td->later_hour) {
385 return(FALSE);
386 }
387
388 if (hh == td->later_hour && mn < td->later_minute) {
389 return(FALSE);
390 }
391
392 if (hh == td->later_hour && mn == td->later_minute &&
393 ss < td->later_second) {
394 return(FALSE);
395 }
396 }
397 /*endif*/
398
399 /*************************************************************************/
400 /* if Revised flag is on and fileinfo->attrib indicate file has not */
401 /* been Revised, return FALSE */
402 /*************************************************************************/
403 if (set_reset_test_flag(&rtswitch,Revised,TEST) == TRUE) {
404 if((retcode = attributes & 0x0020) != 0x0020) {
405 return(FALSE);
406 }
407 }
408 /*endif*/
409
410 /***********************************************************************/
411 /* if PROMPT and fileinfo->file_attrib indicate READONLY, or CHANGED*/
412 /***********************************************************************/
413 if ((set_reset_test_flag(&rtswitch,PROMPT,TEST) == TRUE) &&
414 (((retcode = attributes & 0x0001) == 0x0001) ||
415 ((retcode = attributes & 0x0020) == 0x0020) ))
416 {
417 /*call subroutine to ask whether the user really wants to restore */
418 retcode = readonly_or_changed(attributes,destd,finfo->fname,finfo->path);
419 if (retcode == FALSE) {
420 return(FALSE);
421 }
422 /*endif*/
423 }
424 /*endif*/
425
426 /***********************************************************************/
427 /* if pass all the switch testing, return TRUE */
428 /***********************************************************************/
429 return(TRUE);
430
431} /*end of subroutine switch_match */
432
433/***************** START OF SPECIFICATION ********************************
434/*
435/* SUBROUTINE NAME : check_flheader_old
436/*
437/* DESCRIPTIVE NAME : Check the information in the file header of
438/* the file to be restored.
439/*
440/* FUNCTION: For old format only, Open the file to be restored, get
441/* header informtion
442/*
443/*
444/********************** END OF SPECIFICATIONS *******************************/
445int check_flheader_old
446 ( finfo,f_name,f_date,f_time,f_attrib,f_len,
447 file_seq_num,srcd,destd,infspec,inpath,dnumwant
448 )
449
450 struct file_info *finfo;
451 unsigned char *f_name; /* name string */
452 unsigned f_date; /* file's date */
453 unsigned f_time; /* file's time */
454 unsigned f_attrib; /* file's attribute */
455 unsigned long f_len; /* file length */
456 unsigned int file_seq_num;
457 BYTE srcd;
458 BYTE destd;
459 BYTE *infspec;
460 BYTE *inpath;
461 unsigned int *dnumwant;
462{
463 WORD temp_dnumwant;
464 WORD numread;
465 WORD action;
466 BYTE file_to_be_opened[15];
467 BYTE string_to_be_separate[79];
468 BYTE path[65];
469 BYTE name[9];
470 BYTE ext[4];
471 BYTE spec[13];
472 WORD i; /*loop counter*/
473 WORD retcode;
474 int z;
475
476 temp_dnumwant = *dnumwant; /*to fix a bug that dosread change the
477 value of dnumwant */
478
479
480 /***********************************************************************/
481 /*open the file to be restored as deny write and read access */
482 /***********************************************************************/
483 strcpy(src_fname,f_name);
484 file_to_be_opened[0] = srcd;
485 file_to_be_opened[1] = ':';
486 file_to_be_opened[2] = NULLC;
487 strcat(file_to_be_opened,f_name);
488 retcode = DOSOPEN( (char far *)&file_to_be_opened[0],
489 (unsigned far *)&src_file_handle,
490 (unsigned far *)&action,
491 (DWORD)0, /*file size*/
492 0, /*file attribute*/
493 0x01, /*if file exist, open it*/
494 /*if file not exist, fail it*/
495 0x00c0, /*deny write, read only*/
496 (DWORD)0 ); /*reserved*/
497
498 /*if open fail*/
499 if (retcode != 0) {
500 /****not able to restore the file****/
501 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
502 unexperror(retcode);
503 }
504 /*endif*/
505
506 /***********************************************************************/
507 /*read 128 bytes header information from the file into fheadold */
508 /***********************************************************************/
509 retcode = DOSREAD( src_file_handle,
510 (char far *)&fheadold,
511 HEADLEN,
512 (unsigned far *)&numread);
513 /*if read fail*/
514 if (retcode != 0 )
515 {
516 display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
517 unexperror(retcode);
518 }
519 /*end of if read fail */
520
521 /*if the number of read is less than HEADLEN, return FALSE */
522 if (numread != HEADLEN)
523 return(FALSE);
524
525 /* save disk number */
526 finfo->dnum = fheadold.disknum[1]* 10 + fheadold.disknum[0];
527
528 if (fheadold.wherefrom[0] != '\\')
529 return(FALSE);
530 strcpy(string_to_be_separate,fheadold.wherefrom);
531 separate(string_to_be_separate,path,name,ext,spec);
532
533 /***********************************************************************/
534 /* match the path and file spec. */
535 /***********************************************************************/
536 if
537 ( pathmatch(inpath,path) == FALSE ||
538 fspecmatch(infspec,spec) == FALSE
539 )
540 {
541 *dnumwant = temp_dnumwant;
542 return(FALSE);
543 }
544
545 /***********************************************************************/
546 /*Store some information from filefindbuf into finfo */
547 /***********************************************************************/
548 finfo->ftime = f_time;
549 finfo->fdate = f_date;
550 finfo->attrib = f_attrib;
551 finfo->partsize = f_len;
552
553 /***********************************************************************/
554 /*Store filename and path information from fheadold into finfo */
555 /***********************************************************************/
556 strcpy(finfo->fname,spec);
557 strcpy(finfo->path,path);
558
559 /***********************************************************************/
560 /* store some other information from fheadold to finfo */
561 /***********************************************************************/
562 if (fheadold.headflg == 0xff)
563 finfo->fflag= LAST_PART;
564 else
565 finfo->fflag= 0;
566
567 *dnumwant = temp_dnumwant;
568 return(TRUE);
569
570 /*return nothing*/
571
572} /*end of subroutine*/
573
574
575/***************** START OF SPECIFICATION ********************************
576/*
577/* SUBROUTINE NAME : readonly_or_changed
578/*
579/* DESCRIPTIVE NAME : handle the situration that a read only file
580/* or is found, or the file has been Revised.
581/*
582/* FUNCTION: In the case that a readonly file is found, or the file
583/* on the destination disk has been Revised since last backup,
584/* this subroutine output a warning message to the user, and
585/* prompt for user to enter yes or no depending on whether
586/* the user wants to proceed restoring the file.
587/*
588/*
589/********************* END OF SPECIFICATIONS ********************************/
590#define CHECK_YES_NO 0x6523 /*;AN000;6*/
591#define YES_NO_RESPTYPE 0xc1 /*;AN000;6*/
592#define YES 1 /*;AN000;6*/
593
594int readonly_or_changed(attrib,destd,fspec,fpath)
595
596 unsigned attrib;
597 unsigned char destd;
598 unsigned char *fspec;
599 unsigned char *fpath;
600{
601
602 union REGS inregs, outregs; /*;AN000;6 Register set */
603 WORD retcode;
604
605 char file_to_be_chmode[MAXPATHF+2];
606 DWORD dw = 0L;
607 int z;
608
609 sublist.value1 = (char far *)fspec; /*;AN000;6 */
610 sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */
611 sublist.max_width1 = (BYTE)strlen(fspec); /*;AN000;6 */
612 sublist.min_width1 = sublist.max_width1; /*;AN000;6 */
613
614 /***********************************************************************/
615 /* if readonly, output msg and wait for user's prompt */
616 /***********************************************************************/
617 do /*;AN000;6*/
618 { /*;AN000;6*/
619 if((retcode = attrib & 0x0001) == 0x0001)
620 display_it(FILE_IS_READONLY,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
621 else
622 display_it(FILE_WAS_CHANGED,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
623
624
625 inregs.x.ax = (unsigned)CHECK_YES_NO; /*;AN000;6*/
626 inregs.h.dl = response_buff[0]; /*;AN000;6*/
627 int86(0x21,&inregs,&outregs); /*;AN000;6*/
628 display_it(CRLF,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
629 } /*;AN000;6*/
630 while (outregs.h.al > 1); /*;AN000;6*/
631
632 /***********************************************************************/
633 /* if user's input is 'Y', return TRUE, else return FALSE */
634 /***********************************************************************/
635 if (outregs.x.ax == YES) /*;AN000;6*/
636 { file_to_be_chmode[0] = destd;
637 file_to_be_chmode[1] = ':';
638 file_to_be_chmode[2] = NULLC;
639 strcat(file_to_be_chmode,fpath);
640 if (strlen(fpath) != 1) {
641 strcat(file_to_be_chmode,"\\");
642 }
643 strcat(file_to_be_chmode,fspec);
644 /* change the file attribute to be 0, that is, reset it */
645 if ((retcode = DOSSETFILEMODE((char far *)file_to_be_chmode,(unsigned) 0x00, dw)) != 0)
646 {
647 com_msg(retcode);
648 unexperror(retcode);
649 }
650 return(TRUE);
651 }
652 else {
653 return(FALSE);
654 }
655 /* endif */
656} /* end of subroutine readonly_or_changed */
657
diff --git a/v4.0/src/CMD/RESTORE/RTT.C b/v4.0/src/CMD/RESTORE/RTT.C
new file mode 100644
index 0000000..d581d30
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTT.C
@@ -0,0 +1,409 @@
1static char *SCCSID = "@(#)rtt.c 8.1 86/09/20";
2
3/*  0 */
4
5#include <stdio.h>
6#include "rt.h"
7#include "rt1.h"
8#include "rt2.h"
9#include <comsub.h> /* common subroutine def'n */
10#include <doscalls.h>
11#include <basemid.h>
12#include <wrwdefs.h> /* wrw! */
13
14unsigned char destddir[MAXPATH+3] = {'\0'};
15unsigned char srcddir[MAXPATH+3] = {'\0'};
16unsigned char rtswitch=0;
17unsigned char control_flag=0;
18unsigned char control_flag2=0;
19unsigned char filename[MAXFSPEC] = {"OSO001.MSG"};
20unsigned char *buf_pointer;
21
22/****************************************************************************/
23/* The following comments are necessary to be here to make msgprof.exe */
24/* correctly. */
25/****************************************************************************/
26/* #define INSERT_SOURCE_DISK MSG_INS_BACKUP_DISK */
27/* #define SOURCE_TARGET_SAME MSG_REST_SOUR_TARG_SAME */
28/* #define INVALID_NUM_PARM MSG_REST_NUM_INVAL_PARA */
29/* #define INVALID_DRIVE MSG_REST_INVAL_SPEC */
30/* #define NO_FILE_TO_RESTORE MSG_REST_NO_FILE_FOUND */
31/* #define INVALID_PARM MSG_REST_INVAL_PARA */
32/* #define LAST_FILE_NOT_RESTORED MSG_REST_LAST_FILE_NOT */
33/* #define SOURCE_NO_BACKUP_FILE MSG_REST_SOURCE_NO_BACK */
34/* #define INSUFFICIENT_MEMORY MSG_REST_INSUF_MEM */
35/* #define FILE_SEQUENCE_ERROR MSG_REST_FILE_SEQ_ERROR */
36/* #define FILE_CREATION_ERROR MSG_REST_FILE_CREAT_ERROR */
37/* #define TARGET_IS_FULL MSG_REST_TARG_FULL */
38/* #define NOT_ABLE_TO_RESTORE_FILE MSG_REST_CANNOT_REST_FILE */
39/* #define INVALID_DOS_VER MSG_REST_INVAL_VERS */
40/* #define FILE_SHARING_ERROR MSG_REST_FILE_SHAR */
41/* #define FILE_WAS_CHANGED MSG_REST_CHNG_REPL */
42/* #define DISK_OUT_OF_SEQUENCE MSG_REST_DISK_OUT_SEQ */
43/* #define FILE_IS_READONLY MSG_REST_FILE_READ */
44/* #define SYSTEM_FILE_RESTORED MSG_REST_SYS */
45/* #define FILES_WERE_BACKUP_ON MSG_REST_FILE_BACKUP */
46/* #define RESTORE_FILE_FROM_DRIVE MSG_REST_FILE_FROM */
47/* #define INSERT_TARGET_DISK MSG_REST_TARG_DISK */
48/* #define FILE_TO_BE_RESTORED MSG_REST_FILENAME */
49/* #define DISKETTE_NUM MSG_REST_DISKETTE */
50/* #define PATH_NOT_FOUND MSG_BACK_INVAL_PATH */
51
52/***************** START OF SPECIFICATION *********************************/
53/* */
54/* MODULE NAME : RESTORE utility */
55/* */
56/* DESCRIPTIVE NAME : Restore one or more backed-up files from a */
57/* disk to another disk */
58/* */
59/* FUNCTION: Restore files saved by BACKUP utility to their */
60/* destination disk. This utility will be able to identify */
61/* which of the two backup formats was used and to do the */
62/* restore accordingly. */
63/* */
64/* NOTES: This RESTORE utility recognize two data formats: */
65/* 1. The data format used by BACKUP utility of 3.2 and before. */
66/* 2. The data format used by BACKUP utility of 3.3 and above, */
67/* and also used by CP/DOS 1.0 and above. */
68/* */
69/* DEPENDENCY: */
70/* This utility has a dependency on the BACKUP utility to */
71/* perform file backup correctly using the data structure */
72/* agreed on. */
73/* */
74/* RESTRICTION: */
75/* This utility is able to restore the files which are previously */
76/* backup by IBM BACKUP utility only. */
77/* */
78/* ENTRY POINT: Main */
79/* */
80/* INPUT: (PARAMETERS) */
81/* */
82/* COMMAND SYNTAX: */
83/* [d:][path]Restore d: [d:][path][filename][.ext] */
84/* [/S] [/P] [/B:date] [/A:date] [/E:time][/L:time][/M] [/N] */
85/* */
86/* Parameters: */
87/* The first parameter you specify is the drive designator of */
88/* the disk containing the backed up files. The second */
89/* parameter is the a filespec indicating which files you want */
90/* to restore. */
91/* Switches: */
92/* /S - Restore subdirectories too. */
93/* /P - If any hidden or read-only files match the filespec, */
94/* prompt the user for permission to restore them. */
95/* /B - Only restore those files which were last Revised on or */
96/* before the given date. */
97/* /A - Only restore those files which were last Revised on or */
98/* after the given date. */
99/* /E - Only restore those files which were last Revised at or */
100/* earlier then the given time. */
101/* /L - Only restore those files which were last Revised at or */
102/* later then the given time. */
103/* /M - Only restore those files which have been Revised since */
104/* the last backup. */
105/* /N - Only restore those files which no longer exist on the */
106/* destination disk. */
107/* */
108/* EXIT-NORMAL: */
109/* */
110/* The following messages will be displayed when the program */
111/* exit normally. */
112/* */
113/* *** Files were backed up xx/xx/xxxx *** */
114/* (xx/xx/xxxx will be different in differnt country codes) */
115/* */
116/* *** Restoring files from drive d: *** */
117/* Diskette: xx */
118/* path\filename.ext */
119/* path\filename.ext */
120/* path\filename.ext */
121/* path\filename.ext */
122/* ..... */
123/* */
124/* EXIT-ERROR: */
125/* The restore program sets the ERRORLEVEL in the following manner: */
126/* */
127/* 0 Normal completion */
128/* 1 No files were found to backup */
129/* 2 Some files not restored due to sharing conflict */
130/* 3 Terminated by user */
131/* 4 Terminated due to error */
132/* */
133/* EFFECTS: None */
134/* */
135/* OTHER USER INTERFACES: */
136/* RESTORE prompts for the user to insert source diskette if */
137/* the source disk specified is removable: */
138/* */
139/* Insert backup diskette 01 in drive d: */
140/* (d: is the source diskette) */
141/* Strike any key when ready */
142/* */
143/* If the destination disk is a removable drive, the following */
144/* message is also displayed: */
145/* */
146/* Insert restore target in drive d: */
147/* (d: is the destination disk) */
148/* Strike any key when ready */
149/* */
150/* No matter whether the destination disk is a removable drive */
151/* or a non_removable drive, when the destination disk is full, */
152/* RESTORE output a message "Target is full" and exit. RESTORE */
153/* does not prompt for user to change destination disk when it */
154/* is full. */
155/* */
156/* When there is any system file restored, the following message */
157/* is displayed: */
158/* System file restored */
159/* Target disk may not be bootable */
160/* */
161/* INTERNAL REFERENCES: */
162/* ROUTINES: */
163/* Major routines are shown as follows: */
164/* main */
165/* parse_input_drive_and_file */
166/* set_input_switches */
167/* verify_input_switches */
168/* dorestore */
169/* check_bkdisk_old */
170/* printinfo */
171/* check_bkdisk_new */
172/* search_src_disk_old */
173/* check_flheader_old */
174/* pathmatch */
175/* fspecmatch */
176/* switchmatch */
177/* restore_a_file */
178/* search_src_disk_new */
179/* findfirst_new */
180/* findfile_new */
181/* findnext_new */
182/* check_flheader_new */
183/* readonly_or_changed */
184/* open_dest_file */
185/* build_path_create_file */
186/* dos_write_error */
187/* set_attributes_and_close */
188/* */
189/* Minor routines are shown as follows: */
190/* signal_handler_routine */
191/* usererror */
192/* unexperror */
193/* exit_routine */
194/* putmsg */
195/* com_msg */
196/* beep */
197/* checkdosver */
198/* separate */
199/* initbuf */
200/* init_control_buf */
201/* set_reset_test_flag */
202/* valid_input_date */
203/* valid_input_time */
204/* */
205/***************** END OF SPECIFICATION *********************************/
206/***************** START OF SPECIFICATION *********************************/
207/* */
208/* SUBROUTINE NAME : Main */
209/* */
210/* DESCRIPTIVE NAME : Main routine for RESTORE utility */
211/* */
212/* FUNCTION: Main routine does the following: */
213/* 1. Verifies the DOS version */
214/* 2. Validate the input command line */
215/* 3. Calls dorestore to do the file restore. */
216/* */
217/* NOTES: */
218/* */
219/* ENTRY POINT: Main */
220/* Linkage: main((argc,argv) */
221/* */
222/* INPUT: (PARAMETERS) */
223/* argc - number of arguments */
224/* argv - array of pointers to arguments */
225/* */
226/* */
227/* EXIT-NORMAL: */
228/* */
229/* EXIT-ERROR: */
230/* */
231/* EFFECTS: rtswitch is changed to reflect the switches passed. */
232/* */
233/* INTERNAL REFERENCES: */
234/* ROUTINES: */
235/* dorestore */
236/* checkdosver */
237/* set_input_switches */
238/* parse_input_drive_and_file */
239/* separate */
240/* beep */
241/* putmsg */
242/* usererror */
243/* exit_routine */
244/* set_reset_test_flag */
245/* set_input_switches */
246/* exit_routine */
247/* */
248/* EXTERNAL REFERENCES: */
249/* ROUTINES: */
250/* com_strupr */
251/* DSOSETSIGHANDLER */
252/* */
253/********************** END OF SPECIFICATIONS *******************************/
254void main(argc,argv) /* wrw! */
255 int argc;
256 char *argv[];
257{
258 /*variables for putmsg */
259 unsigned char *ivtable[2];/*point to the table of bairables to insert*/
260 unsigned char respdata; /*response data area*/
261 unsigned int msg_id;
262 unsigned int retcode;
263
264 unsigned int destdnum; /*the destination disk in the integer form*/
265 unsigned int i; /*loop counter */
266 unsigned int j; /*arrary subcript */
267 unsigned char *c;
268 unsigned long drive_map;
269 unsigned long prev_address;
270 unsigned int prev_action;
271 unsigned char srcd;
272 unsigned char destd;
273 unsigned char srcf[MAXPATHF];
274 unsigned char inpath[MAXPATH];
275 unsigned char infname[MAXFNAME];
276 unsigned char infext[MAXFEXT];
277 unsigned char infspec[MAXFSPEC];
278 unsigned int next_arg;
279 struct timedate td;
280 void far pascal signal_handler_routine();
281 /************************************************************************/
282 /* set signal handler */
283 /************************************************************************/
284
285 retcode = DOSSETSIGHANDLER(
286 (void (far *)() )signal_handler_routine, /* Signal handler address */
287 (unsigned long far *)&prev_address, /* Address of previous handler */
288 (unsigned far *)&prev_action, /* Address of previous action */
289 (unsigned)INSTALL_SIGNAL, /* Indicate request type */
290 (unsigned)CTRL_C); /* Signal number */
291
292 if (retcode != 0)
293 com_msg(retcode);
294
295 retcode = DOSSETSIGHANDLER(
296 (void (far *)() )signal_handler_routine, /* Signal handler address */
297 (unsigned long far *)&prev_address, /* Address of previous handler */
298 (unsigned far *)&prev_action, /* Address of previous action */
299 (unsigned)INSTALL_SIGNAL, /* Indicate request type */
300 (unsigned)CTRL_BREAK); /* Signal number */
301
302 if (retcode != 0)
303 com_msg(retcode);
304
305 /************************************************************************/
306 /* check dos version */
307 /************************************************************************/
308 retcode = checkdosver();
309 if (retcode != TRUE) {
310
311 msg_id = INVALID_DOS_VER;
312 putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE);
313
314 usererror(ERROR_INVALID_DOSVER);
315 }
316
317 /************************************************************************/
318 /*convert the input arguments into upper case */
319 /************************************************************************/
320 for (i=1; i <=argc-1; ++i) {
321 com_strupr(argv[i]);
322 }
323
324 /************************************************************************/
325 /* verify the number of parameters */
326 /************************************************************************/
327 if (argc-1 < MINARGS || argc-1 > MAXARGS) {
328 msg_id = INVALID_NUM_PARM; /*invalid number of parameters*/
329 putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE);
330 usererror(INVALIDPARM);
331 }
332 /* endif*/
333
334 /************************************************************************/
335 /* call subroutine to parse the drive and file name entered */
336 /************************************************************************/
337 parse_input_drive_and_file( argc, argv, &destd, &srcd,
338 srcf, &next_arg) ;
339
340 /************************************************************************/
341 /* separate the filename for search into prefix(inpath), */
342 /* filename(infname), and file extension (infext) */
343 /* Also take care of the situation that user enter '.' only */
344 /* for file spec. */
345 /************************************************************************/
346 separate(srcf,inpath,infname,infext,infspec);
347 if (strlen(infname) > MAXFNAME-1 ||
348 strlen(infext) > MAXFEXT-1 ||
349 strlen(inpath) > MAXPATH-1 ||
350 strcmp(infspec,"LPT1")==0 ||
351 strcmp(infspec,"LPT2")==0 ||
352 strcmp(infspec,"PRN")==0 ||
353 strcmp(infspec,"CON")==0 ||
354 strcmp(infspec,"NUL")==0 ||
355 strcmp(infspec,"AUX")==0 ||
356 strcmp(infspec,"LPT1:")==0 ||
357 strcmp(infspec,"LPT2:")==0 ||
358 strcmp(infspec,"PRN:")==0 ||
359 strcmp(infspec,"CON:")==0 ||
360 strcmp(infspec,"NUL:")==0 ||
361 strcmp(infspec,"AUX:")==0 )
362 {
363 msg_id = INVALID_PARM;
364 ivtable[0] = infspec;
365 putmsg (ivtable,1,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE);
366 usererror(INVALIDPARM); /* invalid parm */
367 }
368
369 /************************************************************************/
370 /* set wildcard flag according to whether there is '*' or/and '?' in */
371 /* file specification */
372 /************************************************************************/
373 c = infspec;
374 while (*c) {
375 if (*c == '*' || *c == '?') {
376 set_reset_test_flag(&control_flag,WILDCARD,SET);
377 break;
378 }
379 else
380 c = c+1;
381 } /*end while*/
382
383 /************************************************************************/
384 /* if there is any more parameters to be parsed, call set_input_switches*/
385 /* to parse them started from argv[next_arg] */
386 /************************************************************************/
387 if (next_arg != 0 && argc > next_arg) {
388 set_input_switches( argc, argv, &next_arg, &td);
389 } /* started from argv[next_arg] should be switches */
390
391 /************************************************************************/
392 /* call dorestore to actually do the restoring */
393 /************************************************************************/
394 dorestore(srcd,destd,inpath,infname,infext,infspec,&td);
395
396 /************************************************************************/
397 /* output a msg in the following situations: */
398 /* if flag indicates no file found */
399 /************************************************************************/
400 if (set_reset_test_flag(&control_flag,FOUND,TEST)==FALSE) {
401 beep();
402 msg_id = NO_FILE_TO_RESTORE; /*warning! No files were found to restore*/
403 putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE);
404 exit_routine(NOFILES);
405 }
406
407 exit_routine(NORMAL);
408
409} /* end of main*/
diff --git a/v4.0/src/CMD/RESTORE/RTT1.C b/v4.0/src/CMD/RESTORE/RTT1.C
new file mode 100644
index 0000000..7b75f75
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTT1.C
@@ -0,0 +1,79 @@
1
2/*----------------------------
3/* SOURCE FILE NAME: RTT1.C
4/*----------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "restpars.h" /*;AN000;4*/
11#include "dos.h" /*;AN000;2*/
12#include "comsub.h" /* common subroutine def'n */
13#include "doscalls.h"
14#include "error.h"
15
16extern BYTE destddir[MAXPATH+3];
17extern BYTE srcddir[MAXPATH+3];
18extern BYTE rtswitch;
19extern BYTE control_flag;
20extern BYTE control_flag2;
21extern BYTE filename[12];
22extern unsigned control_file_handle; /* !wrw */
23extern BYTE append_indicator; /*;AN000;2*/
24extern WORD original_append_func; /*;AN000;2*/
25
26/** ***********************************************/
27/*
28/* SUBROUTINE NAME: check_appendX
29/*
30/* FUNCTION:
31/* Check APPEND /X status. If it is not active,
32/* do nothing. If it is active, then turn it off
33/* and set flag indicating that we must reset it later.
34/*
35/***************************************************/
36void check_appendX() /*;AN000;2*/
37{ /*;AN000;2*/
38 union REGS gregs; /*;AN000;2 Register set */
39
40 gregs.x.ax = INSTALL_CHECK; /*;AN000;2 Get installed state*/
41 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
42
43 /*****************************************************/
44 /* 1) See if append is active
45 /* 2) If so, figure out if PCDOS or PCNET version
46 /*****************************************************/
47 if (gregs.h.al == 0) /*;AN000;2 Zero if not installed*/
48 append_indicator = NOT_INSTALLED; /*;AN000;2 */
49 else /*;AN000;2 See which APPEND it is*/
50 { /*;AN000;2*/
51 gregs.x.ax = GET_APPEND_VER; /*;AN000;2*/
52 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
53
54 if (gregs.h.al == (BYTE)-1) /*;AN000;2 -1 if PCDOS version*/
55 append_indicator = DOS_APPEND; /*;AN000;2*/
56 else /*;AN000;2*/
57 append_indicator = NET_APPEND; /*;AN000;2*/
58 } /*;AN000;2*/
59
60 /*****************************************************/
61 /* If it is the PCDOS append
62 /* 1) Get the current append functions (returned in BX)
63 /* 2) Reset append with /X support off
64 /*****************************************************/
65 if (append_indicator == DOS_APPEND) /*;AN000;2*/
66 { /*;AN000;2*/
67 gregs.x.ax = GET_STATE; /*;AN000;2 Get active APPEND functions*/
68 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
69 original_append_func = gregs.x.bx; /*;AN000;2*/
70
71 gregs.x.ax = SET_STATE; /*;AN000;2*/
72 gregs.x.bx = gregs.x.bx & (!APPEND_X_BIT); /*;AN000;2*/
73 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
74
75 } /*;AN000;2*/
76
77 return; /*;AN000;2*/
78} /*;AN000;2*/
79 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RTT2.C b/v4.0/src/CMD/RESTORE/RTT2.C
new file mode 100644
index 0000000..92d50de
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTT2.C
@@ -0,0 +1,488 @@
1static char *SCCSID = "@(#)rtt2.c 8.4 86/10/19";
2/*  0 */
3#include <direct.h>
4#include "rt.h"
5#include "rt1.h"
6#include "rt2.h"
7#include <comsub.h> /* common subroutine def'n */
8#include <doscalls.h>
9#include <wrwdefs.h> /* wrw! */
10
11extern unsigned char rtswitch;
12extern unsigned char control_flag;
13extern unsigned char control_flag2;
14extern struct internat ctry; /* data area for country info*/
15
16/***************** START OF SPECIFICATION *********************************/
17/* */
18/* SUBROUTINE NAME : valid_input_time */
19/* */
20/* DESCRIPTIVE NAME : to validate and convert the time input from the */
21/* command line. */
22/* */
23/* FUNCTION: This subroutine validate the time input from the command lin */
24/* against the country dependent information, and convert */
25/* the deta into three integers which are hour, minute, and */
26/* second. */
27/* NOTES: */
28/* */
29/* INPUT: (PARAMETERS) */
30/* in_string - the string from command line which contains date */
31/* information. */
32/* OUTPUT: */
33/* inhour - the input hour after converted */
34/* inminute - the input minute after converted */
35/* insecond - the input second after converted */
36/* */
37/* EXIT-NORMAL: returns TRUE if the time is valid */
38/* */
39/* EXIT-ERROR: returns FALSE if the time is invalid */
40/* */
41/* EFFECTS: */
42/* */
43/* INTERNAL REFERENCES: */
44/* ROUTINES: */
45/* usererror */
46/* unexperror */
47/* putmsg */
48/* set_reset_test_flag */
49/* */
50/* EXTERNAL REFERENCES: */
51/* ROUTINES: */
52/* */
53/********************** END OF SPECIFICATIONS *******************************/
54int valid_input_time(in_string, inhour, inminute, insecond)
55 unsigned char *in_string; /*the input string */
56 unsigned int *inhour; /*the input hour */
57 unsigned int *inminute; /*the input minute */
58 unsigned int *insecond; /*the input second */
59{
60 unsigned char chour[10];
61 unsigned char cminute[10];
62 unsigned char csecond[10];
63 unsigned int i,j,z; /*working pointer*/
64 unsigned int no_second = FALSE;
65 unsigned char string[20];
66
67 /*declaration for get country information*/
68 unsigned int byte_len;
69 unsigned buflen = sizeof( struct internat ); /* length of data area */
70 unsigned int retcode;
71 long country = 0L;
72
73 /************************************************/
74 /* find the string for hour */
75 /************************************************/
76 #ifdef DEBUG
77 printf("\ntime to be validate %s",in_string);
78 #endif
79 /*save the pointer of input string*/
80 strcpy(string,in_string);
81
82 /* search the first occurance of country->timesep */
83 for (i = 0; (string[i] != NULLC) && (string[i] != ctry.timesep &&
84 string[i] != ':' && string[i] != '.'); ++i);
85
86 if (string[i] == NULLC) { /*if not found*/
87 #ifdef DEBUG
88 printf("\nno time seperator");
89 #endif
90 return(FALSE);
91 }
92
93 string[i] = NULLC; /*replace it with NULLC*/
94
95 /*get the string which represent hour*/
96 strcpy(chour,string);
97 /*put the rest of the string into cminute*/
98 strcpy(cminute,string+i+1);
99
100 /************************************************/
101 /* validate hour */
102 /************************************************/
103 if (strlen(chour) > MAXHOURLEN || strlen(chour)<1 ) {
104 #ifdef DEBUG
105 printf("\ninvalid hour length");
106 #endif
107 return(FALSE);
108 }
109
110 /* convert the string into integer form*/
111 *inhour = 0;
112 for (j=0; chour[j] != NULLC ; ++j) {
113 if (chour[j] < '0' || chour[j] > '9') {
114 #ifdef DEBUG
115 printf("\nhour value not 0-9");
116 #endif
117 return(FALSE);
118 }
119 *inhour = *inhour*10 + chour[j]-'0';
120 }
121
122 if (*inhour > 23 || *inhour < 0) {
123 #ifdef DEBUG
124 printf("\ninvalid hour value");
125 #endif
126 return(FALSE);
127 }
128
129 /************************************************/
130 /* find the string for minute */
131 /************************************************/
132 /*search the next occurance of country->timesep*/
133 for (i = 0; (cminute[i] != NULLC) && (cminute[i] != ctry.timesep &&
134 cminute[i] != ':' && cminute[i] != '.'); ++i);
135
136 if (cminute[i] == NULLC) { /*if not found*/
137 no_second = TRUE;
138 }
139
140 /*put NULLC at the end of string which represent minute*/
141 cminute[i] = NULLC; /*replace it with NULLC*/
142 strcpy(csecond,cminute+i+1);
143
144 /************************************************/
145 /* validate minute */
146 /************************************************/
147 if (strlen(cminute) > MAXMINUTELEN || strlen(cminute)<1 ) {
148 #ifdef DEBUG
149 printf("\ninvalid min length");
150 #endif
151 return(FALSE);
152 }
153
154 /*convert the string into integer*/
155 *inminute = 0;
156 for (j=0; cminute[j] != NULLC ; ++j) {
157 if (cminute[j] < '0' || cminute[j] > '9') {
158 #ifdef DEBUG
159 printf("\ninvalid min value, not 0-9");
160 #endif
161 return(FALSE);
162 }
163 *inminute = *inminute*10 + cminute[j]-'0';
164 }
165
166 if (*inminute > 59 || *inminute < 0) {
167 #ifdef DEBUG
168 printf("\ninvalid min value");
169 #endif
170 return(FALSE);
171 }
172
173 /***************************************************/
174 /* if user input second, get the string for second */
175 /***************************************************/
176 if (no_second == TRUE)
177 return(TRUE);
178 else {
179
180 /************************************************/
181 /* validate second */
182 /************************************************/
183 if (strlen(csecond) > MAXSECONDLEN || strlen(csecond) < 1 ) {
184 #ifdef DEBUG
185 printf("\ninvalid second length");
186 #endif
187 return(FALSE);
188 }
189
190 /*convert the rest of the string into integer*/
191 *insecond = 0;
192 for (j=0; csecond[j] != NULLC; ++j)
193 {
194 if (csecond[j] < '0' || csecond[j] > '9') {
195 #ifdef DEBUG
196 printf("\ninvalid second, 0-9");
197 #endif
198 return(FALSE);
199 }
200 *insecond = *insecond*10 + csecond[j]-'0';
201 }
202
203 if (*insecond > 59 || *insecond < 0) {
204 #ifdef DEBUG
205 printf("\ninvalid second value");
206 #endif
207 return(FALSE);
208 }
209 } /*end of if no_second is true */
210 return(TRUE);
211
212} /*end of subroutine*/
213/***************** START OF SPECIFICATION *********************************/
214/* */
215/* SUBROUTINE NAME : valid_input_date */
216/* */
217/* DESCRIPTIVE NAME : to validate and convert the date input from the */
218/* command line. */
219/* */
220/* FUNCTION: This subroutine validate the date input from the command lin */
221/* against the country dependent information, and convert */
222/* the deta into three integers which are year, month, and day. */
223/* NOTES: */
224/* */
225/* INPUT: (PARAMETERS) */
226/* in_string - the string from command line which contains date */
227/* information. */
228/* OUTPUT: */
229/* inyear - the input year after converted */
230/* inmonth - the input month after converted */
231/* inday - the input day after converted */
232/* */
233/* EXIT-NORMAL: returns TRUE if the date is valid */
234/* */
235/* EXIT-ERROR: returns FALSE if the date is invalid */
236/* */
237/* EFFECTS: */
238/* */
239/* INTERNAL REFERENCES: */
240/* ROUTINES: */
241/* usererror */
242/* unexperror */
243/* putmsg */
244/* set_reset_test_flag */
245/* */
246/* EXTERNAL REFERENCES: */
247/* ROUTINES: */
248/* */
249/********************** END OF SPECIFICATIONS *******************************/
250int valid_input_date(in_string,inyear,inmonth,inday)
251
252 unsigned char *in_string;
253 unsigned int *inyear;
254 unsigned int *inmonth;
255 unsigned int *inday;
256{
257 unsigned char c1[10];
258 unsigned char c2[10];
259 unsigned char c3[10];
260 unsigned char cyear[10];
261 unsigned char cmonth[10];
262 unsigned char cday[10];
263 unsigned int in1;
264 unsigned int in2;
265 unsigned int in3;
266 unsigned int i,j,z; /*working pointer*/
267 unsigned char string[30];
268 unsigned int remainder;
269
270 #ifdef DEBUG
271 printf("\ndate to be validate %s",in_string);
272 #endif
273 /************************************************/
274 /* separate the input date string into 3 parts */
275 /************************************************/
276 /*save the pointer to the input string*/
277 strcpy(string,in_string);
278
279 /* search the first occurance of country->datesep */
280 for (i = 0; (string[i] != NULLC) && (string[i] != ctry.datesep &&
281 string[i] != '/' && string[i] != '-' && string[i] != '.'); ++i);
282
283 if (string[i] == NULLC) { /*if not found*/
284 #ifdef DEBUG
285 printf("\ninvalid date sep");
286 #endif
287 return(FALSE);
288 }
289
290 string[i] = NULLC; /*replace it with NULLC*/
291
292 /*get the string which represent year*/
293 strcpy(c1,string);
294 /*put the rest of the string into c2*/
295 strcpy(c2,string+i+1);
296
297 /*search the next occurance of country->datesep*/
298 for (i = 0; (c2[i] != NULLC) && (c2[i] != ctry.datesep &&
299 c2[i] != '/' && c2[i] != '-' && c2[i] != '.'); ++i);
300
301 if (c2[i] == NULLC) { /*if not found*/
302 #ifdef DEBUG
303 printf("\nno 2nd date sep");
304 #endif
305 return(FALSE);
306 }
307
308 /*put NULLC at the end of string which represent month*/
309 c2[i] = NULLC; /*replace it with NULLC*/
310 strcpy(c3,c2+i+1);
311
312 /************************************************/
313 /* convert all 3 strings to integers */
314 /************************************************/
315 in1 = 0;
316 for (j=0; c1[j] != NULLC ; ++j) {
317 if (c1[j] < '0' || c1[j] > '9') {
318 #ifdef DEBUG
319 printf("\ninvalid 1st in date not 0-9");
320 #endif
321 return(FALSE);
322 }
323 in1 = in1*10 + c1[j]-'0';
324 }
325
326 in2 = 0;
327 for (j=0; c2[j] != NULLC ; ++j) {
328 if (c2[j] < '0' || c2[j] > '9') {
329 #ifdef DEBUG
330 printf("\ninvalid 2nd in date not 0-9");
331 #endif
332 return(FALSE);
333 }
334 in2 = in2*10 + c2[j]-'0';
335 }
336
337 in3 = 0;
338 for (j=0; c3[j] != NULLC ; ++j) {
339 if (c3[j] < '0' || c3[j] > '9') {
340 #ifdef DEBUG
341 printf("\ninvalid 3rd in date not 0-9");
342 #endif
343 return(FALSE);
344 }
345 in3 = in3*10 + c3[j]-'0';
346 }
347 /************************************************/
348 /* identify what these 3 integers are stand for */
349 /************************************************/
350 switch (ctry.dtformat) {
351 case USA:
352 *inmonth = in1;
353 *inday = in2;
354 *inyear = in3;
355 strcpy(cmonth,c1);
356 strcpy(cday,c2);
357 strcpy(cyear,c3);
358 break;
359 case EUR:
360 *inday = in1;
361 *inmonth = in2;
362 *inyear = in3;
363 strcpy(cday,c1);
364 strcpy(cmonth,c2);
365 strcpy(cyear,c3);
366 break;
367 case JAP:
368 *inyear = in1;
369 *inmonth = in2;
370 *inday = in3;
371 strcpy(cyear,c1);
372 strcpy(cmonth,c2);
373 strcpy(cday,c3);
374 break;
375 default:
376 #ifdef DEBUG
377 printf("\ninvalid country code %d",ctry.dtformat);
378 #endif
379 unexperror(UNEXPECTED);
380 break;
381 }
382 /************************************************/
383 /* validate the value of year */
384 /************************************************/
385 if (strlen(cyear) > MAXYEARLEN || strlen(cyear)<1 ) {
386 #ifdef DEBUG
387 printf("\ninvalid year len");
388 #endif
389 return(FALSE);
390 }
391
392 if (*inyear <= 99 && *inyear >= 80)
393 *inyear = *inyear + 1900;
394 if (*inyear <= 79 && *inyear >= 00)
395 *inyear = *inyear + 2000;
396
397 /*validate the value of year */
398 if (*inyear > MAXYEAR || *inyear < MINYEAR) {
399 #ifdef DEBUG
400 printf("\ninvalid year value");
401 #endif
402 return(FALSE);
403 }
404
405 /************************************************/
406 /* validate the value of month */
407 /************************************************/
408 if (strlen(cmonth) > MAXMONTHLEN || strlen(cmonth)<1 ) {
409 #ifdef DEBUG
410 printf("\ninvalid month length");
411 #endif
412 return(FALSE);
413 }
414
415 /*validate the value of year */
416 if (*inmonth > MAXMONTH || *inmonth <= 0) {
417 #ifdef DEBUG
418 printf("\ninvalid month value");
419 #endif
420 return(FALSE);
421 }
422
423 /************************************************/
424 /* validate the value of day */
425 /************************************************/
426 if (strlen(cday) > MAXDAYLEN || strlen(cday)<1 ) {
427 #ifdef DEBUG
428 printf("\ninvalid day len");
429 #endif
430 return(FALSE);
431 }
432
433 /*validate the value of year */
434 if (*inday > MAXDAY || *inday <= 0 ) {
435 #ifdef DEBUG
436 printf("\ninvalid day value");
437 #endif
438 return(FALSE);
439 }
440 if ((*inmonth == 1 || *inmonth == 3 || *inmonth == 5 ||
441 *inmonth == 7 || *inmonth == 8 || *inmonth == 10 ||
442 *inmonth == 12 ) && (*inday > 31 || *inday < 1)) {
443 #ifdef DEBUG
444 printf("\ninvalid day value");
445 #endif
446 return(FALSE);
447 }
448 else {
449 if ((*inmonth == 4 || *inmonth == 6 || *inmonth == 9 ||
450 *inmonth == 11 ) && (*inday > 30 || *inday < 1)) {
451 #ifdef DEBUG
452 printf("\ninvalid day value");
453 #endif
454 return(FALSE);
455 }
456 else {
457 if (*inmonth == 2) {
458 /*check for leap year */
459 remainder = *inyear % 4;
460 if (remainder == 0) {
461 if (*inday > 29 || *inday < 1) {
462 #ifdef DEBUG
463 printf("\ninvalid day value");
464 #endif
465 return(FALSE);
466 }
467 }
468 else {
469 if (*inday > 28 || *inday < 1) {
470 #ifdef DEBUG
471 printf("\ninvalid day value");
472 #endif
473 return(FALSE);
474 }
475 }
476 }
477 }
478 }
479
480 /************************************************/
481 /* if there is no error found, return TRUE */
482 /************************************************/
483 return(TRUE);
484
485} /*end of subroutine valid_input_date*/
486
487/**************************/
488 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/RTT3.C b/v4.0/src/CMD/RESTORE/RTT3.C
new file mode 100644
index 0000000..e3edd0c
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/RTT3.C
@@ -0,0 +1,619 @@
1
2/*---------------------------------
3/* SOURCE FILE NAME: RTT3.C
4/*---------------------------------
5/*  0 */
6
7#include "rt.h"
8#include "rt1.h"
9#include "rt2.h"
10#include "direct.h"
11#include "string.h"
12#include "dos.h" /*;AN000;2*/
13#include "comsub.h" /* common subroutine def'n */
14#include "doscalls.h"
15#include "error.h"
16#include "process.h" /*;AN000;p972*/
17
18extern BYTE filename[12];
19extern BYTE destddir[MAXPATH+3];
20extern BYTE srcddir[MAXPATH+3];
21extern BYTE rtswitch;
22extern BYTE control_flag;
23extern BYTE control_flag2;
24char far *buf_pointer;
25char far *control_buf_pointer;
26unsigned control_selector;
27extern BYTE dest_file_spec[MAXFSPEC];
28extern unsigned dest_file_handle;
29extern BYTE append_indicator; /*;AN000;2*/
30extern WORD original_append_func; /*;AN000;2*/
31extern struct subst_list sublist; /*;AN000;6 Message substitution list */
32extern char response_buff[5]; /*;AN000;6*/
33BYTE far *DBCS_ptr; /*;AN005;*/
34char got_dbcs_vector = FFALSE; /*;AN005;*/
35
36/***************** START OF SPECIFICATION ********************************
37/*
38/* SUBROUTINE NAME : set_reset_test_flag
39/*
40/* DESCRIPTIVE NAME : to set a flag, reset a flag, or test a flag.
41/*
42/* FUNCTION: This subroutine is called when there is a need to set
43/* a flag, reset a flag, or test a flag.
44/* NOTES:
45/*
46/* INPUT: (PARAMETERS)
47/* flag - the flag to be set, reset, or tested.
48/* targetbt - the target bit to be set, reset, or tested.
49/* choice - = 1 if want to set
50/* = 2 if want to reset
51/* = 3 if want to test
52/*
53/********************* END OF SPECIFICATIONS ********************************/
54int set_reset_test_flag(flag,targetbt,choice)
55
56 BYTE *flag; /*the flag to be tested against*/
57 BYTE targetbt; /*the byte to be tested */
58 int choice;
59{
60 BYTE temp;
61
62
63switch (choice) {
64case SET:
65 *flag = *flag | targetbt;
66 break;
67
68case RESET:
69 *flag = *flag & ~targetbt;
70 break;
71
72case TEST:
73 temp = *flag & targetbt;
74 if (temp == 0) {
75 return(FALSE); /*the tested bit is off*/
76 }
77 else {
78 return(TRUE); /*the tested bit is on */
79 }
80 break;
81
82default:
83 unexperror(UNEXPECTED);
84 break;
85} /*end of switch */
86
87 return(FALSE); /* wrw! */
88
89}
90/***************** START OF SPECIFICATION ********************************
91/*
92/* SUBROUTINE NAME : separate
93/*
94/* DESCRIPTIVE NAME : Separate the given input string into 3 parts;
95/* which is the path, filename, file extension, and
96/* file specification.
97/*
98/* FUNCTION: The subroutine searches the input string for the last '\',
99/* which separates the path and file specification, and then
100/* searches the file specification for '.', which separates
101/* the filename and file extension. Also take care the
102/* situation of the user enter '.' for file specification.
103/* This subroutine also validate the file specification
104/* and each path entered by the user by calling common
105/* subroutine Comverflnm.
106/*
107/* NOTE: The input string must start with '\'
108/* All the output string are terminated by 00h
109/*
110/* INPUT: (PARAMETERS)
111/* instring - input string to be separated into path, filename,
112/* and file extension.
113/*
114/* OUTPUT:
115/* path - output path name, always starts with '\' and not end
116/* with '\'
117/* filename - output file name
118/* fileext - output file extension
119/* filespec - output file name and file extension
120/*
121/********************** END OF SPECIFICATIONS *******************************/
122void separate(instring,path,filename,fileext,filespec)
123BYTE *instring; /* point to beginning of input string */
124BYTE *path; /* point to beginning of path string */
125BYTE *filename; /* point to beginning of file name */
126BYTE *fileext; /* point to beginning of file ext. */
127BYTE *filespec; /* point to beginning of file spec */
128{
129 BYTE *iptr; /* working pointer */
130 BYTE *fptr; /* working pointer */
131 WORD i; /*;AN005;*/
132
133/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
134 /* Find last non-DBCS backslash character */
135/* fptr = com_strrchr(instring,'\\'); /*;AN000;p2532*/
136
137 for ( /*;AN005;*/
138 i=strlen(instring); /*;AN005;*/
139 (i>=0) && (!chek_DBCS(instring,i,'\\')); /*;AN005;*/
140 i-- /*;AN005;*/
141 ) /*;AN005;*/
142 {}; /*;AN005;*/
143
144 fptr = instring + i; /*;AN005;*/
145/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
146
147 if (fptr!=instring || instring[0] == '\\')
148 {
149 *fptr = NULLC; /*;AC000;*/
150 strcpy(path, instring);
151 if (path[0] == NULLC)
152 strcpy(path,"\\");
153 *fptr = '\\';
154 ++fptr;
155 strcpy(filespec, fptr);
156
157 if (filespec[0] == '.' && filespec[1] == NULLC)
158 {
159 strcpy(filename, "*");
160 strcpy(fileext, "*");
161 strcpy(filespec, "*.*");
162 }
163 else
164 { /*else if filespec is not '.'*/
165 for (iptr = fptr; *iptr!='.' && *iptr != NULLC; ++iptr);
166
167 if (*iptr == '.')
168 {
169 *iptr = NULLC;
170 strcpy(filename, fptr);
171 *iptr = '.';
172
173 iptr = iptr+1;
174 strcpy(fileext, iptr);
175 }
176 else
177 {
178 strcpy(filename, filespec);
179 *fileext = NULLC;
180 }
181
182 }
183
184 }
185 else
186 {}
187
188 return;
189}
190
191
192
193
194
195/***************** START OF SPECIFICATION ********************************
196/*
197/* SUBROUTINE NAME : initbuf
198/*
199/* DESCRIPTIVE NAME : Initialize buffer for reading and writting.
200/*
201/* FUNCTION: Allocate up to 64 K bytes buffer for reading and writing
202/* data, and make sure its size is divisible by the sector
203/* size of the restore drive.
204/*
205/* NOTES:
206/*
207/********************** END OF SPECIFICATIONS *******************************/
208
209void initbuf(bufsize_long)
210 DWORD *bufsize_long;
211{
212 unsigned bufsize;
213 WORD selector;
214 WORD retcode;
215
216 bufsize = MAXBUF; /*64K-1 */
217 /*do while allocate bufsize fail, bufsize = bufsize - DOWNSIZE*/
218 for (;;) {
219 retcode = DOSALLOCSEG( (unsigned ) bufsize, /*buf length */
220 ( unsigned far * ) &selector, /* buf pointer*/
221 ( unsigned) 0 ); /* no sharing */
222 if ( retcode != 0)
223 {
224 if (bufsize > DOWNSIZE)
225 bufsize = bufsize - DOWNSIZE;
226 else
227 break;
228 }
229 else
230 break;
231 }
232 if (bufsize != 0 && bufsize <= DOWNSIZE ) {
233 display_it(INSUFFICIENT_MEMORY,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
234 usererror(INSUFMEM);
235 }
236
237 FP_SEG( buf_pointer ) = selector;
238 FP_OFF( buf_pointer ) = 0 ;
239
240 if (bufsize == 0)
241 *bufsize_long = (DWORD)MAXBUF;
242 else
243 *bufsize_long = (DWORD)bufsize;
244} /*end of subroutine*/
245
246/***************** START OF SPECIFICATION ********************************
247/*
248/* SUBROUTINE NAME : init_control_buf
249/*
250/* DESCRIPTIVE NAME : Initialize buffer for control.XXX.
251/*
252/* FUNCTION: Allocate buffer for reading in control.xxx
253/*
254/* OUTPUT:
255/* control_bufsize - the size of buffer
256/*
257/*
258/********************** END OF SPECIFICATIONS *******************************/
259void init_control_buf(control_file_len,control_bufsize) /* !wrw */
260 DWORD control_file_len; /* !wrw */
261 unsigned int *control_bufsize; /* !wrw */
262{ /* !wrw */
263 unsigned bufsize; /* !wrw */
264 WORD retcode; /* !wrw */
265
266 bufsize = 3072; /* !wrw */
267
268
269 retcode = DOSALLOCSEG( (unsigned ) bufsize, /* !wrw */
270 ( unsigned far * ) &control_selector, /* !wrw */
271 ( unsigned) 0 ); /* !wrw */
272
273
274 if ( retcode != 0) /* If there is insufficient memory /* !wrw */
275 { /* !wrw */
276 display_it(INSUFFICIENT_MEMORY,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
277 usererror(INSUFMEM);
278 } /* !wrw */
279
280 FP_SEG( control_buf_pointer ) = control_selector; /* !wrw */
281 FP_OFF( control_buf_pointer ) = 0 ; /* !wrw */
282
283 *control_bufsize = bufsize; /* !wrw */
284
285} /*end of subroutine*/ /* !wrw */
286
287/***************** START OF SPECIFICATION ********************************
288/*
289/* SUBROUTINE NAME : unexperror
290/*
291/* DESCRIPTIVE NAME : exit the program because of something really bad
292/* occures
293/*
294/* FUNCTION: Exit the program because of unexpected error
295/*
296/*
297/********************** END OF SPECIFICATIONS *******************************/
298void unexperror(retcode)
299WORD retcode;
300{
301 exit_routine(retcode);
302 return;
303}
304
305/***************** START OF SPECIFICATION ********************************
306/*
307/* SUBROUTINE NAME : usererror
308/*
309/* DESCRIPTIVE NAME : exit the program because of a user error
310/*
311/********************** END OF SPECIFICATIONS *******************************/
312void usererror(retcode)
313WORD retcode;
314{
315 unexperror(retcode);
316 return;
317}
318
319/***************** START OF SPECIFICATION ********************************
320/*
321/* SUBROUTINE NAME : exit_routine
322/*
323/* DESCRIPTIVE NAME : exit the program
324/*
325/* FUNCTION: 1. output msg if there is a sharing error.
326/* 2. if PCDOS, convert return codes to error levels
327/* 3. exit the program
328/*
329/* NOTES:
330/*
331/* INPUT: (PARAMETERS)
332/* retcode - the reason of error
333/*
334/*
335/********************** END OF SPECIFICATIONS *******************************/
336void exit_routine(retcode)
337WORD retcode;
338{
339 union REGS regs; /*;AN000;2*/
340
341 chdir (destddir);
342
343 chdir (srcddir);
344
345 /* if flag indicates there is a SHAREERROR */
346 if (retcode == NORMAL &&
347 set_reset_test_flag(&control_flag,SHARERROR,TEST)==TRUE)
348 retcode = SHARERR;
349
350 switch(retcode)
351 {
352 case NORMAL: retcode = PC_NORMAL;
353 break;
354 case NOFILES: retcode = PC_NOFILES;
355 break;
356 case SHARERR: retcode = PC_SHARERR;
357 break;
358 case TUSER: retcode = PC_TUSER;
359 break;
360 default: retcode = PC_OTHER;
361 break;
362 } /* end switch */
363
364
365 if (append_indicator == DOS_APPEND) /*;AN000;2 If append /x was reset*/
366 { /*;AN000;2*/
367 regs.x.ax = SET_STATE; /*;AN000;2*/
368 regs.x.bx = original_append_func; /*;AN000;2*/
369 int86(0x2f,&regs,&regs); /*;AN000;2*/
370 } /*;AN000;2*/
371
372 exit(retcode); /*;AN000;p972*/
373
374}
375/***************** START OF SPECIFICATION ********************************
376/*
377/* SUBROUTINE NAME : signal_handler_routine
378/*
379/* DESCRIPTIVE NAME : handle the situation that the user terminate
380/* the program by Control-break.
381/*
382/* FUNCTION: This subroutine change the directory of the
383/* destination disk back to the original directory.
384/* If there is a file in the middle of restoring, close
385/* the file, deleted the partially restored file, and
386/* output a message.
387/* Then exit with error level TUSER.
388/*
389/*
390/********************** END OF SPECIFICATIONS *******************************/
391void pascal far signal_handler_routine()
392{
393 WORD retcode;
394
395 DWORD dw = 0L; /* reserved double word*/
396
397 /*change dir to the original directory of the destination disk*/
398
399 /**************************************************************/
400 /*if PARTIAL flag is on, close and delete the destination file*/
401 /**************************************************************/
402 if (set_reset_test_flag(&control_flag,PARTIAL,TEST) == TRUE) {
403 /* close the partially completed destination file*/
404 DOSCLOSE(dest_file_handle);
405 /* delete the partially completed destination file*/
406 if ((retcode = DOSDELETE((char far *) dest_file_spec, dw)) != 0) {
407 /*set file mode to 0*/
408 if ((retcode = DOSSETFILEMODE((char far *)dest_file_spec,
409 (unsigned) 0x00, dw)) != 0)
410 {
411 com_msg(retcode);
412 unexperror(retcode);
413 }
414 /* delete the partially completed destination file*/
415 if ((retcode = DOSDELETE((char far *) dest_file_spec, dw)) != 0) {
416 com_msg(retcode);
417 unexperror(retcode);
418 }
419 }
420 display_it(LAST_FILE_NOT_RESTORED,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
421 }
422 exit_routine(TUSER);
423
424} /* end of signal_handler*/
425
426/************************************************************/
427/*
428/* SUBROUTINE NAME: display_it (added for DOS 4.00)
429/*
430/* SUBROUTINE FUNCTION:
431/* Display the requested message to the standard output device.
432/*
433/* INPUT:
434/* 1) (WORD) Number of the message to be displayed.
435/* 2) (WORD) Handle to be written to.
436/* 3) (WORD) Substitution Count
437/* 4) (WORD) Flag indicating user should "Strike any key..."
438/*
439/* OUTPUT:
440/* The message corresponding to the requested msg number will
441/* be written to the requested handle. If requested, substitution
442/* text will be inserted as required. The Substitution List
443/* is global and, if used, will be initialized by DISPLAY_MSG
444/* before calling this routine.
445/*
446/* NORMAL EXIT:
447/* Message will be successfully written to requested handle.
448/*
449/* ERROR EXIT:
450/* None. Note that theoretically an error can be returned from
451/* SYSDISPMSG, but there is nothing that the application can do.
452/*
453/*
454/************************************************************/
455#define CLASS -1 /* Goes in DH register */ /*;AN000;6*/
456#define NUL_POINTER 0 /* Pointer to nothing */ /*;AN000;6*/
457
458void display_it(msg_number,handle,subst_count,waitflag,class) /*;AN000;6*/
459
460WORD msg_number; /*;AN000;6*/
461WORD handle; /*;AN000;6*/
462WORD subst_count; /*;AN000;6*/
463WORD waitflag; /*;AN000;6*/
464BYTE class; /*;AN000;6*/
465{ /*;AN000;6*/
466 union REGS reg; /*;AN000;6*/
467
468 reg.x.ax = msg_number; /*;AN000;6*/
469 reg.x.bx = handle; /*;AN000;6*/
470 reg.x.cx = subst_count; /*;AN000;6*/
471 reg.h.dh = class; /*;AN000;6*/
472 reg.h.dl = (BYTE)waitflag; /*;AN000;6*/
473 reg.x.di = (BYTE)&response_buff[0]; /*;AN000;6*/
474 reg.x.si = (WORD)(char far *)&sublist; /*;AN000;6*/
475
476 sysdispmsg(&reg,&reg); /*;AN000;6*/
477 response_buff[0] = reg.h.al; /* User input */ /*;AN000;6*/
478
479 return; /*;AN000;6 */
480} /*;AN000;6 */
481/***************** START OF SPECIFICATION ********************************
482/*
483/* SUBROUTINE NAME : com_msg
484/*
485/* DESCRIPTIVE NAME : the routine to output a message according to
486/* the return codes returned from API calls.
487/*
488/* FUNCTION: 1. if CP/DOS, then call rctomid
489/*
490/* NOTES:
491/*
492/* INPUT: (PARAMETERS)
493/* retcode - return code used to call rctomid
494/*
495/*
496/********************** END OF SPECIFICATIONS *******************************/
497void com_msg(retcode)
498WORD retcode;
499{
500 /* Was IF CPDOS */
501 display_it(rctomid(retcode),STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
502
503 return;
504
505}
506/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
507/* */
508/* Subroutine Name: chek_DBCS() */
509/* */
510/* (Ripped off and Revised from ATTRIB.C) */
511/* */
512/* Subroutine Function: */
513/* Given an array and a position in the array, check if the character */
514/* is a non-DBCS character. */
515/* */
516/* Input: array, character position, character */
517/* */
518/* Output: TRUE - if array[position-1] != DBCS character AND */
519/* array[position] == character. */
520/* FALSE - otherwise */
521/* */
522/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
523WORD chek_DBCS(array,position,character) /*;AN005;*/
524char *array; /*;AN005;*/
525WORD position; /*;AN005;*/
526char character; /*;AN005;*/
527{ /*;AN005;*/
528 BYTE far *ptr; /*;AN005;*/
529 WORD i; /*;AN005;*/
530 char c; /*;AN005;*/
531 char darray[128]; /* DBCS array, put "D" in every position*/ /*;AN005;*/
532 /* that corresponds to the first byte */
533 /* of a DBCS character. */
534 if (!got_dbcs_vector) /*;AN005;*/
535 Get_DBCS_vector(); /*;AN005;*/
536
537 for (i=0;i<128;i++) /*;AN005;*/
538 darray[i] = ' '; /*;AN005;*/
539
540 /* Check each character, starting with the first in string, for DBCS */
541 /* characters and mark each with a "D" in the corresponding darray. */
542 for (i=0;i<position;i++) /*;AN005;*/
543 { /*;AN005;*/
544 c = array[i]; /*;AN005;*/
545
546 /* look thru DBCS table to determine if character is first byte */
547 /* of a double byte character */
548 for (ptr=DBCS_ptr; (WORD)*(WORD far *)ptr != 0; ptr += 2) /*;AN005;*/
549 { /*;AN005;*/
550
551 /* check if byte is within range values of DOS DBCS table */
552 if (c >= *ptr && c <= *(ptr+1)) /*;AN005;*/
553 { /*;AN005;*/
554 darray[i] = 'D'; /*;AN005;*/
555 i++; /* skip over second byte of DBCS */ /*;AN005;*/
556 break; /*;AN005;*/
557 } /*;AN005;*/
558 } /*;AN005;*/
559 } /*;AN005;*/
560
561 /* if character is not DBCS then check to see if it is == to character */
562 if (darray[position-1] != 'D' && character == array[position]) /*;AN005;*/
563 return (TTRUE); /*;AN005;*/
564 else /*;AN005;*/
565 return (FFALSE); /*;AN005;*/
566} /*;AN005;*/
567
568/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
569/* */
570/* Subroutine Name: Get_DBCS_vector() */
571/* */
572/* Subroutine Function: */
573/* Gets the double-byte table vector. */
574/* Puts it in global variable DBCS_ptr */
575/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
576void Get_DBCS_vector() /*;AN005;*/
577{ /*;AN005;*/
578 union REGS inregs,outregs; /*;AN005;*/
579 struct SREGS segregs; /*;AN005;*/
580 char fix_es_reg[2]; /*;AN005;*/
581 WORD *ptr; /*;AN005;*/
582 DWORD far *addr_ptr; /*;AN005;*/
583 WORD *buffer; /*;AN005;*/
584
585 /***********************************/
586 /* Allocate a buffer */
587 /***********************************/
588 inregs.x.ax = 0x4800; /* Allocate */ /*;AN005;*/
589 inregs.x.bx = 1; /* Num paragraphs */ /*;AN005;*/
590 intdos(&inregs,&outregs); /* Int 21h */ /*;AN005;*/
591 buffer = (WORD *)outregs.x.ax; /* Segment of buffer */ /*;AN005;*/
592
593 inregs.x.ax = 0x6507; /* get extended country info */ /*;AN005;*/
594 inregs.x.bx = 0xffff; /* use active code page */ /*;AN005;*/
595 inregs.x.cx = 5; /* 5 bytes of return data */ /*;AN005;*/
596 inregs.x.dx = 0xffff; /* use default country */ /*;AN005;*/
597 inregs.x.di = 0; /* buffer offset */ /*;AN005;*/
598 segregs.es = (WORD)buffer; /* buffer segment */ /*;AN005;*/
599 segregs.ds = (WORD)buffer; /* buffer segment */ /*;AN005;*/
600 intdosx(&inregs,&outregs,&segregs); /*;AN005;*/
601 strcpy(fix_es_reg,NUL); /*;AN005;*/
602
603 outregs.x.di++; /* skip over id byte */ /*;AN005;*/
604
605 /* make a far ptr from ES:[DI] */
606 addr_ptr = 0; /*;AN005;*/
607 ptr = (WORD *)&addr_ptr; /*;AN005;*/
608 *ptr = (WORD)outregs.x.di; /* get offset */ /*;AN005;*/
609 ptr++; /*;AN005;*/
610 *ptr = (WORD)segregs.es; /* get segment */ /*;AN005;*/
611 DBCS_ptr = (BYTE far *)*addr_ptr; /*;AN005;*/
612 DBCS_ptr += 2; /* skip over table length */ /*;AN005;*/
613
614 /* DBCS_ptr points to DBCS table */
615 strcpy(fix_es_reg,NUL); /*;AN005;*/
616 got_dbcs_vector = TTRUE; /*;AN005;*/
617 return; /*;AN005;*/
618} /*;AN005;*/
619
diff --git a/v4.0/src/CMD/RESTORE/WRWDEFS.H b/v4.0/src/CMD/RESTORE/WRWDEFS.H
new file mode 100644
index 0000000..b8cfb13
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/WRWDEFS.H
@@ -0,0 +1,77 @@
1
2
3 /* built in 'c' functions */
4
5 int sprintf();
6 int printf();
7 char *strcat(char *,char *);
8 int strlen(char *);
9 char *strcpy(char *, char *);
10 int strncmp(char *,char *,unsigned int);
11 int strcmp(char *,char *);
12
13 /* li functions */
14 int chdir(char *);
15 int mkdir(char *);
16
17 void search_src_disk_old(struct disk_info *,
18 struct file_info *,
19 struct disk_header_old *,
20 struct disk_header_new far *,
21 struct file_header_old *,
22 struct file_header_new far *,
23 unsigned char,
24 unsigned char,
25 unsigned long,
26 unsigned int *,
27 unsigned char *,
28 unsigned char *,
29 unsigned char *,
30 unsigned char *,
31 struct timedate *);
32
33 void search_src_disk_new(struct disk_info *,
34 struct file_info *,
35 struct disk_header_old *,
36 struct disk_header_new far *,
37 struct file_header_old *,
38 struct file_header_new far *,
39 unsigned char,
40 unsigned char,
41 unsigned int *,
42 unsigned long,
43 unsigned char *,
44 unsigned char *,
45 unsigned char *,
46 unsigned int *,
47 struct timedate *);
48
49
50 int findfirst_new( struct file_info *,
51 unsigned int *,
52 unsigned int *,
53 unsigned char *,
54 unsigned char *,
55 unsigned int far**,
56 unsigned int far**,
57 unsigned int *,
58 unsigned char *);
59
60
61 void restore_a_file(struct file_info *,
62 struct disk_info *,
63 unsigned long,
64 unsigned int *,
65 struct file_header_old *,
66 struct file_header_new far *,
67 struct disk_header_old *,
68 struct disk_header_new far *,
69 unsigned char,
70 unsigned char,
71 unsigned char *,
72 unsigned char *,
73 unsigned char *,
74 unsigned int *,
75 unsigned int *);
76
77 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/_MSGRET.ASM b/v4.0/src/CMD/RESTORE/_MSGRET.ASM
new file mode 100644
index 0000000..92597f6
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/_MSGRET.ASM
@@ -0,0 +1,242 @@
1page 60,132
2name _msgret
3title C to Message Retriever
4;-------------------------------------------------------------------
5;
6; MODULE: _msgret
7;
8; PURPOSE: Supplies an interface between C programs and
9; the DOS 3.3 message retriever
10;
11; CALLING FORMAT:
12; sysloadmsg(&inregs,&outregs);
13; sysdispmsg(&inregs,&outregs);
14;
15; DATE: 5-21-87
16;
17;-------------------------------------------------------------------
18
19 INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000;
20
21 MSG_UTILNAME <RESTORE> ;IDENTIFY THE COMPONENT ;AN000;
22
23 .8087
24_TEXT SEGMENT BYTE PUBLIC 'CODE'
25_TEXT ENDS
26_DATA SEGMENT WORD PUBLIC 'DATA'
27_DATA ENDS
28CONST SEGMENT WORD PUBLIC 'CONST'
29CONST ENDS
30_BSS SEGMENT WORD PUBLIC 'BSS'
31_BSS ENDS
32DGROUP GROUP CONST, _BSS, _DATA
33 ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP
34
35
36 public _sysloadmsg
37 public _sysdispmsg
38
39;-------------------------------------------------------------------
40;-------------------------------------------------------------------
41
42_DATA segment
43.XLIST
44.XCREF
45 MSG_SERVICES <MSGDATA> ;DATA AREA FOR THE MESSAGE HANDLER ;AN000;
46.LIST
47.CREF
48_DATA ends
49
50
51_TEXT segment
52
53;-------------------------------------------------------------------
54 ;DEFAULT=CHECK DOS VERSION
55 ;DEFAULT=NEARmsg
56 ;DEFAULT=INPUTmsg
57 ;DEFAULT=NUMmsg
58 ;DEFAULT=NO TIMEmsg
59 ;DEFAULT=NO DATEmsg
60.XLIST
61.XCREF
62 MSG_SERVICES <LOADmsg,INPUTmsg,DISPLAYmsg,CHARmsg,NUMmsg,DATEmsg,FARmsg> ;AN000;6
63 MSG_SERVICES <RESTORE.CTL,RESTORE.CLA,RESTORE.CL1,RESTORE.CL2> ;AN000;6
64.LIST
65.CREF
66;-------------------------------------------------------------------
67
68_sysloadmsg proc near
69
70 push bp ; save user's base pointer
71 mov bp,sp ; set bp to current sp
72 push di ; save some registers
73 push si
74
75; copy C inregs into proper registers
76
77 mov di,[bp+4] ; fix di (arg 0)
78
79;-------------------------------------------------------------------
80
81 mov ax,[di+0ah] ; load di
82 push ax ; the di value from inregs is now on stack
83
84 mov ax,[di+00] ; get inregs.x.ax
85 mov bx,[di+02] ; get inregs.x.bx
86 mov cx,[di+04] ; get inregs.x.cx
87 mov dx,[di+06] ; get inregs.x.dx
88 mov si,[di+08] ; get inregs.x.si
89 pop di ; get inregs.x.di from stack
90
91 push bp ; save base pointer
92
93;-------------------------------------------------------------------
94 call sysloadmsg ; call the message retriever
95;-------------------------------------------------------------------
96
97 pop bp ; restore base pointer
98 push di ; the di value from call is now on stack
99 mov di,[bp+6] ; fix di (arg 1)
100
101 mov [di+00],ax ; load outregs.x.ax
102 mov [di+02],bx ; load outregs.x.bx
103 mov [di+04],cx ; load outregs.x.cx
104 mov [di+06],dx ; load outregs.x.dx
105 mov [di+08],si ; load outregs.x.si
106
107 lahf ; get flags into ax
108 mov al,ah ; move into low byte
109 mov [di+0ch],ax ; load outregs.x.cflag
110
111 pop ax ; get di from stack
112 mov [di+0ah],ax ; load outregs.x.di
113
114;-------------------------------------------------------------------
115
116 pop si ; restore registers
117 pop di
118 mov sp,bp ; restore sp
119 pop bp ; restore user's bp
120 ret
121
122_sysloadmsg endp
123
124
125;_sysgetmsg proc near
126;
127; push bp ; save user's base pointer
128; mov bp,sp ; set bp to current sp
129; push di ; save some registers
130; push si
131;
132;; copy C inregs into proper registers
133;
134; mov di,[bp+4] ; fix di (arg 0)
135;
136;;-------------------------------------------------------------------
137;
138; mov ax,[di+0ah] ; load di
139; push ax ; the di value from inregs is now on stack
140;
141; mov ax,[di+00] ; get inregs.x.ax
142; mov bx,[di+02] ; get inregs.x.bx
143; mov cx,[di+04] ; get inregs.x.cx
144; mov dx,[di+06] ; get inregs.x.dx
145; mov si,[di+08] ; get inregs.x.si
146; pop di ; get inregs.x.di from stack
147;
148; push bp ; save base pointer
149;
150;;-------------------------------------------------------------------
151; call sysgetmsg ; call the message retriever
152;;-------------------------------------------------------------------
153;
154; pop bp ; restore base pointer
155; push di ; the di value from call is now on stack
156; mov di,[bp+6] ; fix di (arg 1)
157;
158; mov [di+00],ax ; load outregs.x.ax
159; mov [di+02],bx ; load outregs.x.bx
160; mov [di+04],cx ; load outregs.x.cx
161; mov [di+06],dx ; load outregs.x.dx
162; mov [di+08],si ; load outregs.x.si
163;
164; lahf ; get flags into ax
165; mov al,ah ; move into low byte
166; mov [di+0ch],ax ; load outregs.x.cflag
167;
168; pop ax ; get di from stack
169; mov [di+0ah],ax ; load outregs.x.di
170;
171;;-------------------------------------------------------------------
172;
173; pop si ; restore registers
174; pop di
175; mov sp,bp ; restore sp
176; pop bp ; restore user's bp
177; ret
178;
179;_sysgetmsg endp
180
181_sysdispmsg proc near
182
183 push bp ; save user's base pointer
184 mov bp,sp ; set bp to current sp
185 push di ; save some registers
186 push si
187
188; copy C inregs into proper registers
189
190 mov di,[bp+4] ; fix di (arg 0)
191
192;-------------------------------------------------------------------
193
194 mov ax,[di+0ah] ; load di
195 push ax ; the di value from inregs is now on stack
196
197 mov ax,[di+00] ; get inregs.x.ax
198 mov bx,[di+02] ; get inregs.x.bx
199 mov cx,[di+04] ; get inregs.x.cx
200 mov dx,[di+06] ; get inregs.x.dx
201 mov si,[di+08] ; get inregs.x.si
202 pop di ; get inregs.x.di from stack
203
204 push bp ; save base pointer
205
206;-------------------------------------------------------------------
207 call sysdispmsg ; call the message retriever
208;-------------------------------------------------------------------
209
210 pop bp ; restore base pointer
211 push di ; the di value from call is now on stack
212 mov di,[bp+6] ; fix di (arg 1)
213
214 mov [di+00],ax ; load outregs.x.ax
215 mov [di+02],bx ; load outregs.x.bx
216 mov [di+04],cx ; load outregs.x.cx
217 mov [di+06],dx ; load outregs.x.dx
218 mov [di+08],si ; load outregs.x.si
219
220 lahf ; get flags into ax
221 mov al,ah ; move into low byte
222 mov [di+0ch],ax ; load outregs.x.cflag
223
224 pop ax ; get di from stack
225 mov [di+0ah],ax ; load outregs.x.di
226
227;-------------------------------------------------------------------
228
229 pop si ; restore registers
230 pop di
231 mov sp,bp ; restore sp
232 pop bp ; restore user's bp
233 ret
234
235_sysdispmsg endp
236
237include msgdcl.inc
238
239_TEXT ends ; end code segment
240 end
241
242 \ No newline at end of file
diff --git a/v4.0/src/CMD/RESTORE/_PARSE.ASM b/v4.0/src/CMD/RESTORE/_PARSE.ASM
new file mode 100644
index 0000000..9685fe6
--- /dev/null
+++ b/v4.0/src/CMD/RESTORE/_PARSE.ASM
@@ -0,0 +1,115 @@
1page 60,132
2name _parse
3title C to PARSER interface
4;-------------------------------------------------------------------
5;
6; MODULE: _parse
7;
8; PURPOSE: Supplies an interface between C programs and
9; the DOS 3.3 parser
10;
11; CALLING FORMAT:
12; parse(&inregs,&outregs);
13;
14; DATE: 5-21-87
15;
16;-------------------------------------------------------------------
17
18; extrn sysparse:far
19
20 public _parse
21
22;-------------------------------------------------------------------
23FarSW equ 0 ; make sysparse be a NEAR proc
24TimeSW equ 1 ; Check time format
25FileSW equ 1 ; Check file specification
26CAPSW equ 1 ; Perform CAPS if specified
27CmpxSW equ 0 ; Check complex list
28NumSW equ 0 ; Check numeric value
29KeySW equ 0 ; Support keywords
30SwSW equ 1 ; Support switches
31Val1SW equ 0 ; Support value definition 1
32Val2SW equ 0 ; Support value definition 2
33Val3SW equ 0 ; Support value definition 3
34DrvSW equ 1 ; Support drive only format
35QusSW equ 0 ; Support quoted string format
36IncSW equ 0 ; Dont include PSDATA, I just did it
37BaseSW equ 1 ; DS points to data
38;-------------------------------------------------------------------
39
40DGROUP GROUP _DATA
41PGROUP GROUP _TEXT
42
43_DATA segment byte public 'DATA'
44include psdata.inc
45_DATA ends
46
47_TEXT segment byte public 'CODE'
48
49 ASSUME CS: PGROUP
50 ASSUME DS: DGROUP
51
52;-------------------------------------------------------------------
53.xlist
54include parse.asm ; include the parser
55.list
56;-------------------------------------------------------------------
57
58_parse proc near
59
60 push bp ; save user's base pointer
61 mov bp,sp ; set bp to current sp
62 push di ; save some registers
63 push si
64
65; copy C inregs into proper registers
66
67 mov di,[bp+4] ; fix di (arg 0)
68
69;-------------------------------------------------------------------
70
71 mov ax,[di+0ah] ; load di
72 push ax ; the di value from inregs is now on stack
73
74 mov ax,[di+00] ; get inregs.x.ax
75 mov bx,[di+02] ; get inregs.x.bx
76 mov cx,[di+04] ; get inregs.x.cx
77 mov dx,[di+06] ; get inregs.x.dx
78 mov si,[di+08] ; get inregs.x.si
79 pop di ; get inregs.x.di from stack
80
81 push bp ; save base pointer
82;-------------------------------------------------------------------
83 call sysparse ; call the parser
84;-------------------------------------------------------------------
85 pop bp ; restore base pointer
86 push di ; the di value from call is now on stack
87 mov di,[bp+6] ; fix di (arg 1)
88
89 mov [di+00],ax ; load outregs.x.ax
90 mov [di+02],bx ; load outregs.x.bx
91 mov [di+04],cx ; load outregs.x.cx
92 mov [di+06],dx ; load outregs.x.dx
93 mov [di+08],si ; load outregs.x.si
94
95 lahf ; get flags into ax
96 mov al,ah ; move into low byte
97 mov [di+0ch],ax ; load outregs.x.cflag
98
99 pop ax ; get di from stack
100 mov [di+0ah],ax ; load outregs.x.di
101
102;-------------------------------------------------------------------
103
104 pop si ; restore registers
105 pop di
106 mov sp,bp ; restore sp
107 pop bp ; restore user's bp
108 ret
109
110_parse endp
111
112_TEXT ends ; end code segment
113 end
114
115 \ No newline at end of file