1 static char *SCCSID = "@(#)rtt.c 8.1 86/09/20";
9 #include <comsub.h> /* common subroutine def'n */
12 #include <wrwdefs.h> /* wrw! */
14 unsigned char destddir[MAXPATH+3] = {'\0'};
15 unsigned char srcddir[MAXPATH+3] = {'\0'};
16 unsigned char rtswitch=0;
17 unsigned char control_flag=0;
18 unsigned char control_flag2=0;
19 unsigned char filename[MAXFSPEC] = {"OSO001.MSG"};
20 unsigned char *buf_pointer;
22 /****************************************************************************/
23 /* The following comments are necessary to be here to make msgprof.exe */
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 */
52 /***************** START OF SPECIFICATION *********************************/
54 /* MODULE NAME : RESTORE utility */
56 /* DESCRIPTIVE NAME : Restore one or more backed-up files from a */
57 /* disk to another disk */
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. */
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. */
70 /* This utility has a dependency on the BACKUP utility to */
71 /* perform file backup correctly using the data structure */
75 /* This utility is able to restore the files which are previously */
76 /* backup by IBM BACKUP utility only. */
78 /* ENTRY POINT: Main */
80 /* INPUT: (PARAMETERS) */
83 /* [d:][path]Restore d: [d:][path][filename][.ext] */
84 /* [/S] [/P] [/B:date] [/A:date] [/E:time][/L:time][/M] [/N] */
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 */
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. */
110 /* The following messages will be displayed when the program */
113 /* *** Files were backed up xx/xx/xxxx *** */
114 /* (xx/xx/xxxx will be different in differnt country codes) */
116 /* *** Restoring files from drive d: *** */
118 /* path\filename.ext */
119 /* path\filename.ext */
120 /* path\filename.ext */
121 /* path\filename.ext */
125 /* The restore program sets the ERRORLEVEL in the following manner: */
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 */
135 /* OTHER USER INTERFACES: */
136 /* RESTORE prompts for the user to insert source diskette if */
137 /* the source disk specified is removable: */
139 /* Insert backup diskette 01 in drive d: */
140 /* (d: is the source diskette) */
141 /* Strike any key when ready */
143 /* If the destination disk is a removable drive, the following */
144 /* message is also displayed: */
146 /* Insert restore target in drive d: */
147 /* (d: is the destination disk) */
148 /* Strike any key when ready */
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 */
156 /* When there is any system file restored, the following message */
158 /* System file restored */
159 /* Target disk may not be bootable */
161 /* INTERNAL REFERENCES: */
163 /* Major routines are shown as follows: */
165 /* parse_input_drive_and_file */
166 /* set_input_switches */
167 /* verify_input_switches */
169 /* check_bkdisk_old */
171 /* check_bkdisk_new */
172 /* search_src_disk_old */
173 /* check_flheader_old */
178 /* search_src_disk_new */
182 /* check_flheader_new */
183 /* readonly_or_changed */
185 /* build_path_create_file */
186 /* dos_write_error */
187 /* set_attributes_and_close */
189 /* Minor routines are shown as follows: */
190 /* signal_handler_routine */
200 /* init_control_buf */
201 /* set_reset_test_flag */
202 /* valid_input_date */
203 /* valid_input_time */
205 /***************** END OF SPECIFICATION *********************************/
206 /***************** START OF SPECIFICATION *********************************/
208 /* SUBROUTINE NAME : Main */
210 /* DESCRIPTIVE NAME : Main routine for RESTORE utility */
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. */
219 /* ENTRY POINT: Main */
220 /* Linkage: main((argc,argv) */
222 /* INPUT: (PARAMETERS) */
223 /* argc - number of arguments */
224 /* argv - array of pointers to arguments */
231 /* EFFECTS: rtswitch is changed to reflect the switches passed. */
233 /* INTERNAL REFERENCES: */
237 /* set_input_switches */
238 /* parse_input_drive_and_file */
244 /* set_reset_test_flag */
245 /* set_input_switches */
248 /* EXTERNAL REFERENCES: */
251 /* DSOSETSIGHANDLER */
253 /********************** END OF SPECIFICATIONS *******************************/
254 void main(argc,argv) /* wrw! */
258 /*variables for putmsg */
259 unsigned char *ivtable[2];/*point to the table of bairables to insert*/
260 unsigned char respdata; /*response data area*/
262 unsigned int retcode;
264 unsigned int destdnum; /*the destination disk in the integer form*/
265 unsigned int i; /*loop counter */
266 unsigned int j; /*arrary subcript */
268 unsigned long drive_map;
269 unsigned long prev_address;
270 unsigned int prev_action;
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;
280 void far pascal signal_handler_routine();
281 /************************************************************************/
282 /* set signal handler */
283 /************************************************************************/
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 */
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 */
305 /************************************************************************/
306 /* check dos version */
307 /************************************************************************/
308 retcode = checkdosver();
309 if (retcode != TRUE) {
311 msg_id = INVALID_DOS_VER;
312 putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE);
314 usererror(ERROR_INVALID_DOSVER);
317 /************************************************************************/
318 /*convert the input arguments into upper case */
319 /************************************************************************/
320 for (i=1; i <=argc-1; ++i) {
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);
334 /************************************************************************/
335 /* call subroutine to parse the drive and file name entered */
336 /************************************************************************/
337 parse_input_drive_and_file( argc, argv, &destd, &srcd,
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 */
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 )
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 */
369 /************************************************************************/
370 /* set wildcard flag according to whether there is '*' or/and '?' in */
371 /* file specification */
372 /************************************************************************/
375 if (*c == '*' || *c == '?') {
376 set_reset_test_flag(&control_flag,WILDCARD,SET);
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 */
391 /************************************************************************/
392 /* call dorestore to actually do the restoring */
393 /************************************************************************/
394 dorestore(srcd,destd,inpath,infname,infext,infspec,&td);
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) {
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);
407 exit_routine(NORMAL);