summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/RESTORE/RTT3.C
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/RESTORE/RTT3.C')
-rw-r--r--v4.0/src/CMD/RESTORE/RTT3.C619
1 files changed, 619 insertions, 0 deletions
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