From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/RESTORE/DIRECT.H | 26 + v4.0/src/CMD/RESTORE/MAKEFILE | 108 ++++ v4.0/src/CMD/RESTORE/MESSAGES.INC | 1 + v4.0/src/CMD/RESTORE/RESTORE.C | 240 +++++++++ v4.0/src/CMD/RESTORE/RESTORE.LNK | 17 + v4.0/src/CMD/RESTORE/RESTORE.SKL | 46 ++ v4.0/src/CMD/RESTORE/RESTPARS.C | 1002 +++++++++++++++++++++++++++++++++++++ v4.0/src/CMD/RESTORE/RESTPARS.H | 119 +++++ v4.0/src/CMD/RESTORE/RT.H | 272 ++++++++++ v4.0/src/CMD/RESTORE/RT1.H | 273 ++++++++++ v4.0/src/CMD/RESTORE/RT2.H | 136 +++++ v4.0/src/CMD/RESTORE/RTDO.C | 376 ++++++++++++++ v4.0/src/CMD/RESTORE/RTDO1.C | 420 ++++++++++++++++ v4.0/src/CMD/RESTORE/RTFILE.C | 598 ++++++++++++++++++++++ v4.0/src/CMD/RESTORE/RTFILE1.C | 456 +++++++++++++++++ v4.0/src/CMD/RESTORE/RTNEW.C | 244 +++++++++ v4.0/src/CMD/RESTORE/RTNEW1.C | 627 +++++++++++++++++++++++ v4.0/src/CMD/RESTORE/RTOLD.C | 266 ++++++++++ v4.0/src/CMD/RESTORE/RTOLD1.C | 657 ++++++++++++++++++++++++ v4.0/src/CMD/RESTORE/RTT.C | 409 +++++++++++++++ v4.0/src/CMD/RESTORE/RTT1.C | 79 +++ v4.0/src/CMD/RESTORE/RTT2.C | 488 ++++++++++++++++++ v4.0/src/CMD/RESTORE/RTT3.C | 619 +++++++++++++++++++++++ v4.0/src/CMD/RESTORE/WRWDEFS.H | 77 +++ v4.0/src/CMD/RESTORE/_MSGRET.ASM | 242 +++++++++ v4.0/src/CMD/RESTORE/_PARSE.ASM | 115 +++++ 26 files changed, 7913 insertions(+) create mode 100644 v4.0/src/CMD/RESTORE/DIRECT.H create mode 100644 v4.0/src/CMD/RESTORE/MAKEFILE create mode 100644 v4.0/src/CMD/RESTORE/MESSAGES.INC create mode 100644 v4.0/src/CMD/RESTORE/RESTORE.C create mode 100644 v4.0/src/CMD/RESTORE/RESTORE.LNK create mode 100644 v4.0/src/CMD/RESTORE/RESTORE.SKL create mode 100644 v4.0/src/CMD/RESTORE/RESTPARS.C create mode 100644 v4.0/src/CMD/RESTORE/RESTPARS.H create mode 100644 v4.0/src/CMD/RESTORE/RT.H create mode 100644 v4.0/src/CMD/RESTORE/RT1.H create mode 100644 v4.0/src/CMD/RESTORE/RT2.H create mode 100644 v4.0/src/CMD/RESTORE/RTDO.C create mode 100644 v4.0/src/CMD/RESTORE/RTDO1.C create mode 100644 v4.0/src/CMD/RESTORE/RTFILE.C create mode 100644 v4.0/src/CMD/RESTORE/RTFILE1.C create mode 100644 v4.0/src/CMD/RESTORE/RTNEW.C create mode 100644 v4.0/src/CMD/RESTORE/RTNEW1.C create mode 100644 v4.0/src/CMD/RESTORE/RTOLD.C create mode 100644 v4.0/src/CMD/RESTORE/RTOLD1.C create mode 100644 v4.0/src/CMD/RESTORE/RTT.C create mode 100644 v4.0/src/CMD/RESTORE/RTT1.C create mode 100644 v4.0/src/CMD/RESTORE/RTT2.C create mode 100644 v4.0/src/CMD/RESTORE/RTT3.C create mode 100644 v4.0/src/CMD/RESTORE/WRWDEFS.H create mode 100644 v4.0/src/CMD/RESTORE/_MSGRET.ASM create mode 100644 v4.0/src/CMD/RESTORE/_PARSE.ASM (limited to 'v4.0/src/CMD/RESTORE') 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 @@ +/* + * direct.h + * + * This include file contains the function declarations for the library + * functions related to directory handling and creation. + * + * Copyright (C) 1988 Microsoft Corporation + * + */ + +/* function declarations for those who want strong type checking + * on arguments to library function calls + */ + +#ifdef LINT_ARGS /* arg. checking enabled */ + +int chdir(char *); +char *getcwd(char *, int); +int mkdir(char *); +int rmdir(char *); + +#else + +extern char *getcwd(); + +#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 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +map =..\..\mapper +here =..\cmd\restore + +all: not_file restore.com + +#-------BUILD MAPPER ---------------- +not_file : makefile #Always perform these steps! + cd $(map) + nmake + cd $(here) + + +_parse.obj : _parse.asm \ + makefile \ + $(inc)\parse.asm \ + $(inc)\psdata.inc + +restore.ctl : restore.skl \ + makefile \ + $(msg)\$(COUNTRY).msg + + +_msgret.obj: _msgret.asm \ + makefile \ + restore.ctl \ + restore.cl1 \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc + + +restore.obj : restore.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtt1.obj : rtt1.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtt3.obj : rtt3.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtdo.obj : rtdo.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtdo1.obj : rtdo1.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtnew.obj : rtnew.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtnew1.obj : rtnew1.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtold.obj : rtold.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtold1.obj : rtold1.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtfile.obj : rtfile.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +rtfile1.obj : rtfile1.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +restpars.obj : restpars.c rt.h rt1.h rt2.h restpars.h makefile \ + $(hinc)\comsub.h $(hinc)\doscalls.h \ + $(hinc)\error.h + +restore.com: restore.obj \ + restpars.obj \ + rtdo.obj \ + rtdo1.obj \ + rtfile.obj \ + rtfile1.obj \ + rtnew.obj \ + rtnew1.obj \ + rtold.obj \ + rtold1.obj \ + rtt1.obj \ + rtt3.obj \ + restore.lnk \ + _msgret.obj \ + _parse.obj \ + $(map)\mapper.lib + link @restore.lnk + convert restore.exe restore.com + 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 @@ + +/*  0 */ + +/**************************************************************************/ +/* +/* MODULE NAME : RESTORE utility +/* +/* SOURCE FILE NAME: RESTORE.C +/* +/* DESCRIPTIVE NAME : Restore one or more backed-up files from a +/* disk to another disk +/* +/* FUNCTION: Restore files saved by BACKUP utility to their +/* destination disk. This utility will be able to identify +/* which of the two backup formats was used and to do the +/* restore accordingly. +/* +/* NOTES: This RESTORE utility recognize two data formats: +/* 1. The data format used by BACKUP utility of 3.2 and before. +/* 2. The data format used by BACKUP utility of 3.3 and above, +/* and also used by CP/DOS 1.0 and above. +/* +/* DEPENDENCY: +/* This utility has a dependency on the BACKUP utility to +/* perform file backup correctly using the data structure +/* agreed on. +/* +/* RESTRICTION: +/* This utility is able to restore the files which are previously +/* backup by the BACKUP utility only. +/* +/* ENTRY POINT: Main +/* +/* INPUT: (PARAMETERS) +/* +/* COMMAND SYNTAX: +/* [d:][path]Restore d: [d:][path][filename][.ext] +/* [/S] [/P] [/B:date] [/A:date] [/E:time][/L:time][/M] [/N] +/* +/* Parameters: +/* The first parameter you specify is the drive designator of +/* the disk containing the backed up files. The second +/* parameter is the a filespec indicating which files you want +/* to restore. +/* Switches: +/* /S - Restore subdirectories too. +/* /P - If any hidden or read-only files match the filespec, +/* prompt the user for permission to restore them. +/* /B - Only restore those files which were last Revised on or +/* before the given date. +/* /A - Only restore those files which were last Revised on or +/* after the given date. +/* /E - Only restore those files which were last Revised at or +/* earlier then the given time. +/* /L - Only restore those files which were last Revised at or +/* later then the given time. +/* /M - Only restore those files which have been Revised since +/* the last backup. +/* /N - Only restore those files which no longer exist on the +/* destination disk. +/* +/* EXIT-ERROR: +/* The restore program sets the ERRORLEVEL in the following manner: +/* +/* 0 Normal completion +/* 1 No files were found to backup +/* 2 Some files not restored due to sharing conflict +/* 3 Terminated by user +/* 4 Terminated due to error +/* +/* +/* SOURCE HISTORY: +/* +/* Modification History: +/* +/* Code added in DOS 3.3 to allow control file > 64k commented as: +/* /* !wrw */ +/* +/* ;AN000; Code added in DOS 4.0 +/* ;AN000;2 Support for APPEND /X deactivation +/* ;AN000;3 Support for Extended Attributes +/* ;AN000;4 Support for PARSE service routines +/* ;AN000;5 Support for code page file tags +/* ;AN000;6 Support for MESSAGE retriever +/* ;AN000;8 Eliminate double prompting on single drive systems +/* ;AN000;9 Fix for termination on "Unable to MKDIR" +/* ;AN000;10 Fix for p1620 +/* ;AN001; Add CR, LF to end of command line +/* ;AN002; Make parser errors display the offending parameter +/* ;AN003; Only disallow restore of system files in ROOT !! +/* ;AN004; Fix parser +/* ;AN005; Replace COM_STRRCHR dbcs routine, fixes p5029 +/***************** END OF SPECIFICATION *********************************/ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + + +BYTE destddir[MAXPATH+3] = {'\0'}; +BYTE srcddir[MAXPATH+3] = {'\0'}; +BYTE rtswitch=0; +BYTE control_flag=0; +BYTE control_flag2=0; +BYTE *buf_pointer; + +/*=============================*/ +BYTE srcd; /*;AN000;4*/ +BYTE destd; /*;AN000;4*/ +BYTE inpath [MAXPATH]; /*;AN000;*/ +BYTE infname [MAXFNAME]; /*;AN000;*/ +BYTE infext [MAXFEXT]; /*;AN000;*/ +BYTE infspec [MAXFSPEC]; /*;AN000;*/ +/*=============================*/ +/*---------------------------------------*/ +/*- */ +/*- Data structures for the PARSER */ +/*- */ +/*---------------------------------------*/ + +struct subst_list sublist; /*;AN000;6 Message substitution list */ +char response_buff[5]; /*;AN000;6 User response buffer *//*;AN000;6*/ + +BYTE append_indicator = 0xff; /*;AN000;2 Indicates the support for APPEND /X is active */ +WORD original_append_func; /*;AN000;2 APPEND functions on program entry*/ +struct timedate td; + +/***************** START OF SPECIFICATION *********************************/ +/* +/* SUBROUTINE NAME : Main +/* +/* DESCRIPTIVE NAME : Main routine for RESTORE utility +/* +/* FUNCTION: Main routine does the following: +/* 1. Verifies the DOS version +/* 2. Validate the input command line +/* 3. Calls dorestore to do the file restore. +/* +/* NOTES: +/* +/* ENTRY POINT: Main +/* Linkage: main((argc,argv) +/* +/* INPUT: (PARAMETERS) +/* argc - number of arguments +/* argv - array of pointers to arguments +/* +/* EFFECTS: rtswitch is changed to reflect the switches passed. +/* +/********************** END OF SPECIFICATIONS *******************************/ +void main(argc,argv) /* wrw! */ + int argc; + char *argv[]; +{ + WORD retcode; + union REGS inregs,outregs; /*AN000*/ + WORD i; /*loop counter */ + WORD j; /*arrary subcript */ + BYTE *c; + DWORD drive_map; + DWORD prev_address; + WORD prev_action; + +/**********************************/ +/** PRELOAD MESSAGES **/ +/**********************************/ + sysloadmsg(&inregs,&outregs); /*;AN000;6 Preload messages */ + if (outregs.x.cflag & CARRY) /*;AN000;6 If there was an error */ + { /*;AN000;6*/ + sysdispmsg(&outregs,&outregs); /*;AN000;6 Display the error message */ + exit_routine(UNEXPECTED); /*;AN000;6 and terminate */ + } /*;AN000;6*/ + + +/*********************************************/ +/* Parse the drive and file name entered */ +/*********************************************/ + parse_command_line /*;AN000;4*/ + ( /*;AN000;4*/ + argc, /*;AN000;4*/ + argv /*;AN000;4*/ + ); /*;AN000;4*/ + +/*********************************************/ +/* Make sure APPEND /X is not active */ +/*********************************************/ + check_appendX(); /*;AN000;2 */ + + +/*********************************************/ +/* Take control of Control Break Interrupt */ +/*********************************************/ + retcode = DOSSETSIGHANDLER + ( + (void far *)signal_handler_routine, /* Signal handler address */ + (DWORD far *)&prev_address, /* Address of previous handler */ + (unsigned far *)&prev_action, /* Address of previous action */ + (unsigned)INSTALL_SIGNAL, /* Indicate request type */ + (unsigned)CTRL_C /* Signal number */ + ); + + retcode = DOSSETSIGHANDLER + ( + (void far *)signal_handler_routine, /* Signal handler address */ + (DWORD far *)&prev_address, /* Address of previous handler */ + (unsigned far *)&prev_action, /* Address of previous action */ + (unsigned)INSTALL_SIGNAL, /* Indicate request type */ + (unsigned)CTRL_BREAK /* Signal number */ + ); + +/*********************************/ +/* Take control of Hard Errors */ +/*********************************/ + set_int24_vector(); /*;AN000; Set Critical error vector (int 24h) */ + + + /************************************************************/ + /* call dorestore (RTDO.C) to actually do the restoring */ + /************************************************************/ + dorestore(srcd,destd,inpath,infname,infext,infspec,&td); + + /************************************************************/ + /* output a msg in the following situations: */ + /* if flag indicates no file found */ + /************************************************************/ + if (set_reset_test_flag(&control_flag,FOUND,TEST)==FALSE) + { + /*warning! No files were found to restore*/ + display_it(NO_FILE_TO_RESTORE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + exit_routine(NOFILES); + } + + exit_routine(NORMAL); + +} /* 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 @@ +/STACK:50000 + +restore + +restpars + +rtt1 + +rtt3 + +rtdo + +rtdo1 + +rtold + +rtold1 + +rtnew + +rtnew1 + +rtfile + +rtfile1 + +_parse + +_msgret +restore.exe,,..\..\mapper\mapper + ..\..\inc\comsubs; + \ 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 @@ +;========================================================== + +:util RESTORE ;AN000; + +;--------- +:class A +;--------- ;AN000; +:use 1 COMMON1 ;AN000; ;For "Incorrect DOS version +:def 2 CR,LF,"Source and target drives are the same",CR,LF ;AN000; +:def 3 CR,LF,"Invalid number of parameters",CR,LF ;AN000; + +:use 5 COMMON25 ;AN000; ;For "Invalid path +:def 6 CR,LF,"Invalid drive specification",CR,LF ;AN000; +:def 7 CR,LF,"Warning! No files were found to restore",CR,LF ;AN000; +:def 8 CR,LF,"Insert backup diskette %1 in drive %2:",CR,LF ;AN000; +:def 9 CR,LF,"Insert restore target in drive %1:",CR,LF ;AN000; +:use 10 COMMON28 ;AN000; ;For "Press any key to continue . . .",CR,LF +:def 11 CR,LF,"Warning! Diskette is out of sequence",CR,LF ;AN000; + "Replace diskette or continue if okay",CR,LF ;AN000; + +:def 12 CR,LF,"The last file was not restored",CR,LF ;AN000; +:def 13 CR,LF,"*** Files were backed up %1 ***",CR,LF ;AN000; +:def 14 CR,LF,"Source does not contain backup files",CR,LF ;AN000; +:def 15 CR,LF,"Insufficient memory",CR,LF ;AN000; +:def 16 CR,LF,"Warning! File %1",CR,LF ;AN000; + "is a read-only file",CR,LF ;AN000; + "Replace the file (Y/N)?" ;AN000; + +:def 17 CR,LF,"Restore file sequence error",CR,LF ;AN000; +:def 18 CR,LF,"File creation error",CR,LF ;AN000; +:def 19 CR,LF,"Insufficient disk space",CR,LF ;AN000; +:def 20 CR,LF,"*** Not able to restore file ***",CR,LF ;AN000; +:def 21 CR,LF,"*** Restoring files from drive %1: ***",CR,LF ;AN000; +:def 22 CR,LF,"Warning! File %1",CR,LF ;AN000; + "was changed after it was backed up",CR,LF ;AN000; + "Replace the file (Y/N)?",CR,LF ;AN000; + +:def 23 "Diskette: %1",CR,LF ;AN000; + +:use 27 COMMON23 ;AN000; ;For "Invalid date +:use 28 COMMON24 ;AN000; ;For "Invalid time +:use 29 COMMON26 ;AN000; ;For "No source drive specified +:use 30 COMMON27 ;AN000; ;For "No target drive specified +:def 31 CR,LF ;AN000; +:end ;AN000; +;========================================================== 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 @@ + +/*------------------------------- +/* SOURCE FILE NAME: restpars.c +/*------------------------------- +/*  0 */ +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "direct.h" +#include "string.h" +#include "ctype.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +/*=============================*/ +extern BYTE srcd; /*;AN000;4*/ +extern BYTE destd; /*;AN000;4*/ +extern BYTE inpath [MAXPATH]; /*;AN000;*/ +extern BYTE infname [MAXFNAME]; /*;AN000;*/ +extern BYTE infext [MAXFEXT]; /*;AN000;*/ +extern BYTE infspec [MAXFSPEC]; /*;AN000;*/ +/*=============================*/ + +extern BYTE destddir[MAXPATH+3]; +extern BYTE srcddir[MAXPATH+3]; +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern BYTE filename[12]; +extern unsigned control_file_handle; /* !wrw */ +extern struct subst_list sublist; /*;AN000;6Message substitution list */ + +struct p_parms parms; /*;AN000;4 Parser data structure */ +struct p_parmsx parmsx; /*;AN000;4 Parser data structure */ +struct p_pos_blk pos1; /*;AN000;4 Parser data structure */ +struct p_pos_blk pos2; /*;AN000;4 Parser data structure */ +struct p_sw_blk sw1; /*;AN000;4 /S /P /M /N data structure */ +struct p_sw_blk sw2; /*;AN000;4 /E: /L: parser data structure */ +struct p_sw_blk sw3; /*;AN000;4 /B: /A: parser data structure */ +struct p_result_blk pos_buff; /*;AN000;4 Parser data structure */ +struct switchbuff sw_buff; /*;AN000;4 Parser data structure */ +struct timebuff time_buff; /*;AN000;4 Parser data structure */ +struct datebuff date_buff; /*;AN000;4 Parser data structure */ +DWORD noval; /*;AN000;4 Value list for PARSER */ +int parse_count = 1; /*;AN000;4*//*;AC002;*/ +char curr_parm[128]; /*;AN004; Current parameter being parsed*/ +extern struct timedate td; + +/* ************************************************/ +/* +/* SUBROUTINE NAME: parse_command_line +/* +/* FUNCTION: +/* +/* Parse the RESTORE command line +/* +/**************************************************/ +void parse_command_line(argc,argv) /*;AN000;4 */ +int argc; /*;AN000;4 */ +char *argv[]; /*;AN000;4 */ +{ /*;AN000;4 */ +#define EOL -1 /*;AN000;4 */ + union REGS inregs, outregs; /*;AN000;4 */ + char cmd_line[128]; /*;AN000;4 */ + char not_finished = TTRUE; /*;AN000;4 */ + int x; /*;AN000;4 */ + + + /* Copy command line parameters to local area */ + cmd_line[0] = NUL; /*;AN000;4*/ + for (x=1; x<=argc; x++) /*;AN000;4*/ + { /*;AN000;4*/ + strcat(cmd_line,argv[x]); /*;AN000;4*/ + if (x!=argc) strcat(cmd_line," "); /*;AN000;4*/ + } /*;AN000;4*/ + + strcat(cmd_line,"\r"); /* Add CR, LF */ /*;AN004;*/ + + if (argc-1 < 1) /*;AN000;4*/ + { /*;AC000;4*/ + display_it(NO_SOURCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + if (argc-1 < 2) /*;AN000;4*/ + { /*;AC000;4*/ + display_it(NO_TARGET,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + /* Check for same source and target drive */ + if (com_toupper(*argv[1]) == com_toupper(*argv[2]) /*;AN000;4*/ + && (BYTE)*(argv[1]+1) == ':' /*;AN000;4*/ + && (BYTE)*(argv[1]+2) == NUL /*;AN000;4*/ + && (BYTE)*(argv[2]+1) == ':' /*;AN000;4*/ + ) /*;AN000;4*/ + { /*;AC000;4*/ + display_it(SOURCE_TARGET_SAME,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + /* Initialize parser data structures */ + parse_init(); /*;AN000;4*/ + + inregs.x.si = (WORD)&cmd_line[0]; /*DS:SI*/ /*;AN000;4 make DS:SI point to source */ + inregs.x.cx = 0; /*;AN000;4*/ + + /*********************/ + /* PARSE LOOP !!!!!! */ + /*********************/ + while (not_finished) /*;AN000;4 For all strings in command line */ + { /*;AN000;4 */ + inregs.x.dx = 0; /*;AN000;4 RESERVED */ + inregs.x.di = (WORD)&parms; /*ES:DI*/ /*;AN000;4 address of parm list */ + parse(&inregs,&outregs); /*;AN000;4 Call DOS PARSE service routines*/ + + x=0; /* Save the parsed parameter */ /*;AN004;*/ + for (inregs.x.si; inregs.x.si= 5) /*;AN000;p2591*/ + check_for_device_names(argv); /*;AN000;p2591*/ + + check_source_drive(argc,argv); /*;AN000;4*/ + check_target_filespec(argc,argv); /*;AN000;4*/ + + return; /*;AN000;4*/ +} /* end parser */ /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: parse_error +/* +/* FUNCTION: +/* +/* There was a parse error. Display message and die +/* +/**************************************************/ +void parse_error(msg_num,class) /*;AN000;4*//*;AC002;*/ +WORD msg_num; /*;AN000;4*/ +BYTE class; /*;AN000;4*/ +{ /*;AN000;4*/ + sublist.value1 = &curr_parm[0]; /*;AN002;*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN002;*/ + sublist.one = 0; /*;AN002;*/ + sublist.max_width1 = (BYTE)strlen(curr_parm); /*;AN002;*/ + sublist.min_width1 = sublist.max_width1; /*;AN002;*/ + + + if (msg_num == NO_SOURCE || msg_num == NO_TARGET) /*;AN000;6*/ + display_it(msg_num,STND_ERR_DEV,0,NO_RESPTYPE,class); /*;AN000;6*/ + else /*;AN000;6*/ + display_it(msg_num,STND_ERR_DEV,1,NO_RESPTYPE,class); /*;AN000;6*/ + + + usererror(INVALIDPARM); /*;AN000;4*//*;AC002;*/ + return; /*;AN000;4*/ +} /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_date +/* +/* FUNCTION: +/* +/* A date parameter was entered. Validate it +/* +/**************************************************/ +void check_date(year,month,day) /*;AN000;4*//*;AC002;*/ +WORD year; /*;AN000;4*/ +BYTE month; /*;AN000;4*/ +BYTE day; /*;AN000;4*/ +{ /*;AN000;4*/ + if (year > 2099 || year < 1980) /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if (month > 12 || month < 1) /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if (day > 31 || month < 1) /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + /* Verify day not greater then 30 if Apr,Jun,Sep,Nov */ + if ((day>30) && (month==4 || month==6 || month==9 || month==11)) /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if (month == 2) /* Deal with February */ /*;AC000;4*/ + { /*;AC000;4*/ + if (day > 29) /* if Feb 30 or above */ /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if ((year % 4) != 0) /* If not a leap year */ /*;AC000;4*/ + if (day > 28) /* if Feb 29 or above */ /*;AC000;4*/ + parse_error(INV_DATE,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + } /*;AC000;4*/ + + return; /*;AN000;4*/ +} /*;AN000;4*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_time +/* +/* FUNCTION: +/* +/* A time parameter was entered. Validate it +/* +/**************************************************/ +void check_time(hours,minutes,seconds,hundreds) /*;AN000;4*//*;AC002;*/ +BYTE hours; /*;AN000;4*/ +BYTE minutes; /*;AN000;4*/ +BYTE seconds; /*;AN000;4*/ +BYTE hundreds; /*;AN000;4*/ +{ /*;AN000;4*/ + + if (hours > 23 || hours < 0) /*;AC000;4*/ + parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if (minutes >= 60 || minutes < 0) /*;AC000;4*/ + parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + if (seconds >= 60 || seconds < 0) /*;AC000;4*/ + parse_error(INV_TIME,(BYTE)UTILMSG); /*;AC000;4*//*;AC002;*/ + + return; /*;AN000;4*/ +} /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: parse_init +/* +/* FUNCTION: +/* +/* Initialize the parser data structures +/* +/**************************************************/ +#define SSTRING 0x2000 /*;AN000;4*/ +#define FILESPEC 0x0200 /*;AN000;4 */ +#define CAP_FILETABLE 0x0001 /*;AN000;4 */ +#define DRIVELETTER 0x100; /*;AN000;4 */ +#define DATESTRING 0x1000 /*;AN000;4 */ +#define TIMESTRING 0x0800 /*;AN000;4 */ + +void parse_init() /*;AN000;4 */ + +{ /* Initialize PARMS data structure */ /*;AN000;4 */ + parms.parmsx_ptr = (WORD)&parmsx; /*;AN000;4 */ + parms.p_num_extra = 1; /*;AN000;4 */ + parms.p_len_extra_delim = 1; /*;AN000;4 */ + parms.p_extra_delim[0] = ';'; /*;AN000;4 */ + parms.p_extra_delim[1] = NUL; /*;AN000;4 */ + + /* Initialize PARMSX data structure */ + parmsx.p_minpos= 2; /*;AN000;4 */ + parmsx.p_maxpos= 2; /*;AN000;4 */ + parmsx.pos1_ptr= (WORD)&pos1; /*;AN000;4 */ + parmsx.pos2_ptr= (WORD)&pos2; /*;AN000;4 */ + parmsx.num_sw = 3; /*;AN000;4 */ + parmsx.sw1_ptr = (WORD)&sw1; /*;AN000;4 */ + parmsx.sw2_ptr = (WORD)&sw2; /*;AN000;4 */ + parmsx.sw3_ptr = (WORD)&sw3; /*;AN000;4 */ + parmsx.num_keywords = 0; /*;AN000;4 */ + + /* Initialize POS1 (Source Drive) data structure */ + pos1.match_flag = FILESPEC; /*;AN000;4 */ + pos1.function_flag = 0; /*;AN000;4 */ + pos1.result_buf = (WORD)&pos_buff; /*;AN000;4 */ + pos1.value_list = (WORD)&noval; /*;AN000;4 */ + pos1.nid = 0; /*;AN000;4 */ + + /* Initialize POS2 (Target FILESPEC) data structure */ + pos2.match_flag = SSTRING; /*;AN000;4 */ + pos2.function_flag = 0; /*;AN000;4 */ + pos2.result_buf = (WORD)&pos_buff; /*;AN000;4 */ + pos2.value_list = (WORD)&noval; /*;AN000;4 */ + pos2.nid = 0; /*;AN000;4 */ + + /* Initialize SW1 data structure */ + sw1.p_match_flag = DATESTRING; /*;AN000;4 */ + sw1.p_function_flag = 0; /*;AN000;4 */ + sw1.p_result_buf = (WORD)&date_buff; /*;AN000;4 */ + sw1.p_value_list = (WORD)&noval; /*;AN000;4 */ + sw1.p_nid = 2; /*;AN000;4 */ + strcpy(sw1.switch1,"/B"); /*;AN000;4 */ + strcpy(sw1.switch2,"/A"); /*;AN000;4 */ + + /* Initialize SW2 data structure */ + sw2.p_match_flag = TIMESTRING; /*;AN000;4 */ + sw2.p_function_flag = 0; /*;AN000;4 */ + sw2.p_result_buf = (WORD)&time_buff; /*;AN000;4 */ + sw2.p_value_list = (WORD)&noval; /*;AN000;4 */ + sw2.p_nid = 2; /*;AN000;4 */ + strcpy(sw2.switch1,"/E"); /*;AN000;4 */ + strcpy(sw2.switch2,"/L"); /*;AN000;4 */ + + + /* Initialize SW3 data structure */ + sw3.p_match_flag = 0; /*;AN000;4 */ + sw3.p_function_flag = 0; /*;AN000;4 */ + sw3.p_result_buf = (WORD)&sw_buff; /*;AN000;4 */ + sw3.p_value_list = (WORD)&noval; /*;AN000;4 */ + sw3.p_nid = 4; /*;AN000;4 */ + strcpy(sw3.switch1,"/S"); /*;AN000;4 */ + strcpy(sw3.switch2,"/P"); /*;AN000;4 */ + strcpy(sw3.switch3,"/M"); /*;AN000;4 */ + strcpy(sw3.switch4,"/N"); /*;AN000;4 */ + + /*********************************************/ + /* Also initialize all time and date values */ + /*********************************************/ + td.earlier_hour = 0; + td.earlier_minute = 0; + td.earlier_second = 0; + td.later_hour = 0; + td.later_minute = 0; + td.later_second = 0; + td.before_year = 0; + td.before_month = 0; + td.before_day = 0; + td.after_year = 0; + td.after_month = 0; + td.after_day = 0; + + /**************************************************/ + /* Also initialize the message substitution list */ + /**************************************************/ + sublist.sl_size1= SUBLIST_SIZE; /*;AN000;6*/ + sublist.sl_size2= SUBLIST_SIZE; /*;AN000;6*/ + sublist.one = 1; /*;AN000;6*/ + sublist.two = 2; /*;AN000;6*/ + sublist.zero1 = 0; /*;AN000;6*/ + sublist.zero2 = 0; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.pad_char2 = ' '; /*;AN000;6*/ + + return; /*;AN000;4 */ +} /*;AN000;4 */ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_for_device_names +/* +/* FUNCTION: +/* +/* Make sure user not trying to restore a reserved device name +/* +/**************************************************/ +void check_for_device_names(argv) /*;AN000;p2591*/ +char *argv[]; /*;AN000;p2591*/ +{ /*;AN000;p2591*/ + union REGS qregs; /*;AN000;p2591*/ + char target[128]; /*;AN000;p2591*/ + char *t; /*;AN000;p2591*/ + +#define CAPITALIZE_STRING 0x6521 /*;AN000;p2591*/ + + qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p2591*/ + qregs.x.dx = (WORD)argv[2]; /*;AN000;p2591*/ + strcpy(target,argv[2]); /*;AN000;p2591*/ + qregs.x.cx = strlen(target); /*;AN000;p2591*/ + intdos(&qregs,&qregs); /*;AN000;p2591*/ + strcpy(target,argv[2]); /*;AN000;p2591*/ + + for (t=&target[0]; *t!=NUL; t++) + if /*;AN000;p2591*/ + ( strcmp(t,"LPT1")==0 || /*;AN000;p2591*/ + strcmp(t,"LPT2")==0 || /*;AN000;p2591*/ + strcmp(t,"PRN")==0 || /*;AN000;p2591*/ + strcmp(t,"CON")==0 || /*;AN000;p2591*/ + strcmp(t,"NUL")==0 || /*;AN000;p2591*/ + strcmp(t,"AUX")==0 || /*;AN000;p2591*/ + strcmp(t,"LPT1:")==0 || /*;AN000;p2591*/ + strcmp(t,"LPT2:")==0 || /*;AN000;p2591*/ + strcmp(t,"PRN:")==0 || /*;AN000;p2591*/ + strcmp(t,"CON:")==0 || /*;AN000;p2591*/ + strcmp(t,"NUL:")==0 || /*;AN000;p2591*/ + strcmp(t,"AUX:")==0 /*;AN000;p2591*/ + ) /*;AN000;p2591*/ + { /*;AN000;p2591*/ + sublist.value1 = (char far *)t; /*;AN000;p2591*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;p2591*/ + sublist.one = 0; /*;AN000;p2591*/ + sublist.max_width1 = (BYTE)strlen(t); /*;AN000;p2591*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;p2591*/ + + display_it(INVPARM,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;p2591*/ + usererror(INVALIDPARM); /*;AN000;p2591*/ + } /*;AN000;p2591*/ + + + return; /*;AN000;p2591*/ +} /*;AN000;p2591*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_source_drive +/* +/* FUNCTION: +/* +/* Verify drive letter and start building srcddir +/* +/**************************************************/ +void check_source_drive(argc,argv) /*;AN000;4*/ +int argc; /*;AN000;4*/ +char *argv[]; /*;AN000;4*/ +{ /*;AN000;4*/ + WORD retcode; /*;AC000;*/ + WORD device_handle; + WORD action; + BYTE parm; + BYTE media_type; + WORD dnumwant = 1; + BYTE temp_array1[4]; + BYTE temp_array2[4]; + union REGS qregs; /*;AN000;8*/ + + *argv[1]=(BYTE)com_toupper(*argv[1]); /*;AN000;4*/ + + if ( /*;AN000;4*/ + *argv[1] < 'A' || /*;AN000;4*/ + *argv[1] > 'Z' || /*;AN000;4*/ + *(argv[1]+1)!=':' || /*;AN000;4*/ + *(argv[1]+2)!=NUL /*;AN000;4*/ + ) /*;AN000;4*/ + { /*;AN000;4*/ + display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AN000;4*/ + } /*;AN000;4*/ + + srcd = (BYTE)*argv[1]; /*;AN000;4*/ + srcddir[0] = srcd; /*;AN000;4*/ + srcddir[1] = ':'; /*;AN000;4*/ + srcddir[2] = NUL; /*;AN000;4*/ + + /***********************************************************************/ + /* dosopen to find out whether the src drive exist */ + /* and dosdevioctl to find out whether it is a removable drive */ + /***********************************************************************/ + retcode = /*;AC000;4*/ + DOSOPEN /*;AC000;4*/ + ( (char far *)&srcddir[0], /*;AC000;4*/ + (unsigned far *)&device_handle, /*;AC000;4*/ + (unsigned far *)&action, /*;AC000;4*/ + (DWORD)0, /*file size*/ /*;AC000;4*/ + 0, /*file attribute*/ /*;AC000;4*/ + 0x01, /*if file exist, open it*/ /*;AC000;4*/ + /*if file not exist, fail it*//*;AC000;4*/ + 0x80c2, /*deny write, read only*/ /*;AC000;4*/ + (DWORD)0 /*reserved*/ /*;AC000;4*/ + ); /*;AC000;4*/ + + if (retcode != NOERROR) /*;AC000;4*/ + { /*;AC000;4*/ + display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AC000;4*/ + } /*;AC000;4*/ + + /************************************/ /*;AC000;4*/ + /* See if source drive is removable */ /*;AC000;4*/ + /************************************/ /*;AC000;4*/ + retcode = /*;AC000;4*/ + DOSDEVIOCTL /*;AC000;4*/ + ( (char far *)&media_type, /*;AC000;4*/ + (char far *)&parm, /*;AC000;4*/ + 0x20, /*;AC000;4*/ + 0x08, /*;AC000;4*/ + device_handle /*;AC000;4*/ + ); /*;AC000;4*/ + + if (retcode != NOERROR) /*;AC000;4*/ + { display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AC000;4*/ + } /*;AC000;4*/ + +#define REMOVABLE 0 /*;AC000;4*/ + if (media_type != REMOVABLE) /*;AC000;4*/ + set_reset_test_flag(&control_flag2,SRC_HDISK,SET); /*;AC000;4*/ + + else /* Source disk is removable */ /*;AC000;4*/ + { /*;AC000;4*/ + temp_array1[0] = (BYTE)((dnumwant / 10) + '0'); /*;AC000;4*/ + temp_array1[1] = (BYTE)((dnumwant % 10) + '0'); /*;AC000;4*/ + temp_array1[2] = NUL; /*;AC000;4*/ + temp_array2[0] = srcd; /*;AC000;4*/ + temp_array2[1] = NUL; /*;AC000;4*/ + + sublist.value1 = (char far *)temp_array1; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + + sublist.value2 = (char far *)temp_array2; /*;AN000;6*/ + sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6*/ + sublist.min_width2 = sublist.max_width2; /*;AN000;6*/ + + display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /* If single drive system, eliminates double prompting */ + /* for user to "Insert diskette for drive %1" */ + qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ + qregs.h.bl = srcddir[0] - 'A' + 1; /*;AN000;8*/ + intdos(&qregs,&qregs); /*;AN000;8*/ + + } /*;AC000;4*/ + return; /*;AN000;4*/ +} /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_target_filespec +/* +/* FUNCTION: +/* +/* Verify the target filespec. +/* 1. Validate destination drive, or use default if none specified +/* 2. Validate path, or use current dir if not specified +/* 3. Validate the file name +/* +/**************************************************/ +void check_target_filespec(argc,argv) /*;AN000;4*/ +int argc; /*;AN000;4*/ +char *argv[]; /*;AN000;4*/ +{ /*;AN000;4*/ + WORD retcode; /*;AC000;*/ + WORD device_handle; + WORD action; + BYTE parm; + BYTE media_type; + DWORD drive_map; + BYTE temp_destddir[MAXPATH+2]; + BYTE temp_array1[4]; + BYTE temp_array2[4]; + WORD default_drive_num; + WORD destd_num; + WORD dirlen = MAXPATH; + BYTE tdestddir[MAXPATH+3]; + BYTE ttdestddir[MAXPATH+3]; + BYTE srcf[MAXPATHF]; + BYTE argv2_has_switch; + BYTE search_string[MAXPATHF+2]; + BYTE tempp[MAXPATH]; + WORD j,k,z; + BYTE *c; + BYTE backdir; + WORD dnumwant = 1; + union REGS qregs; /*;AN000;8*/ + + + /**************************/ + /* Uppercase the string */ + /**************************/ +#define CAPITALIZE_STRING 0x6521 /*;AN000;p????*/ + + qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p????*/ + qregs.x.dx = (WORD)argv[2]; /*;AN000;p????*/ + strcpy(tempp,argv[2]); /*;AN000;p????*/ + qregs.x.cx = strlen(tempp); /*;AN000;p????*/ + intdos(&qregs,&qregs); /*;AN000;p????*/ + + + /***************************************************/ + /* If no drive letter specified, use current drive */ + /***************************************************/ + if ( /*;AC000;4*/ + *(argv[2]+1)!=':' || /*;AC000;4*/ + *argv[2] < 'A' || /*;AC000;4*/ + *argv[2] > 'Z' /*;AC000;4*/ + ) /*;AC000;4*/ + { /*;AC000;4*/ + DOSQCURDISK /*;AC000;4*/ + ( (unsigned far *)&default_drive_num, /*;AC000;4*/ + (DWORD far *) &drive_map /*;AC000;4*/ + ); /*;AC000;4*/ + destd = (BYTE)(default_drive_num + 'A' - 1); /*;AC000;4*/ + } /*;AC000;4*/ + else /*;AC000;4*/ + { /* User specified the destination drive*/ /*;AC000;4*/ + destd = (BYTE)*argv[2]; /*;AC000;4*/ + argv[2] = argv[2] + 2; /*;AC000;4*/ + } /*;AC000;4*/ + + destddir[0] = destd; /*;AC000;4*/ + destddir[1] = ':'; /*;AC000;4*/ + destddir[2] = NUL; /*;AC000;4*/ + + /***********************************************************************/ + /* if source drive and destination drive are the same, output error msg*/ + /***********************************************************************/ + if (srcd == destd) /*;AC000;4*/ + { /*;AC000;4*/ + display_it(SOURCE_TARGET_SAME,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + /***********************************************************************/ + /* dosopen to find out whether the destination drive is exist */ + /* and dosdevioctl to find out whether it is a removable drive */ + /***********************************************************************/ + + retcode = /*;AC000;4*/ + DOSOPEN /*;AC000;4*/ + ( (char far *)&destddir[0], /*;AC000;4*/ + (unsigned far *)&device_handle, /*;AC000;4*/ + (unsigned far *)&action, /*;AC000;4*/ + (DWORD)0, /*file size*/ /*;AC000;4*/ + 0, /*file attribute*/ /*;AC000;4*/ + 0x01, /*if file exist, open it*/ /*;AC000;4*/ + /*if file not exist, fail it*/ /*;AC000;4*/ + 0x80c2, /*deny write, read only*/ /*;AC000;4*/ + (DWORD)0 /*reserved*/ /*;AC000;4*/ + ); /*;AC000;4*/ + + if (retcode != NOERROR)/*if open fail*/ /*;AC000;4*/ + { /*;AC000;4*/ + display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AC000;4*/ + } /*;AC000;4*/ + + /************************************/ /*;AC000;4*/ + /* See if target drive is removable */ /*;AC000;4*/ + /************************************/ /*;AC000;4*/ + retcode = /*;AC000;4*/ + DOSDEVIOCTL /*;AC000;4*/ + ( (char far *)&media_type, /*;AC000;4*/ + (char far *)&parm, /*;AC000;4*/ + 0x20, /*;AC000;4*/ + 0x08, /*;AC000;4*/ + device_handle /*;AC000;4*/ + ); /*;AC000;4*/ + + if (retcode != NOERROR) /*;AC000;4*/ + { display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AC000;4*/ + } /*;AC000;4*/ + + if (media_type == REMOVABLE) /*;AC000;4*/ + { temp_array1[0] = destd; /*;AC000;4*/ + temp_array1[1] = NUL; /*;AC000;4*/ + sublist.value1 = (char far *)temp_array1; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + + display_it(INSERT_TARGET_DISK,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + } /*;AC000;4*/ + + /* If single drive system, eliminates double prompting */ + /* for user to "Insert diskette for drive %1" */ + qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ + qregs.h.bl = destddir[0] - 'A' + 1; /*;AN000;8*/ + intdos(&qregs,&qregs); /*;AN000;8*/ + + /**********************************************************************/ + /* save current directory of destination disk to be reset back later */ + /**********************************************************************/ + + destd_num = (WORD) (destd - 'A' +1); /*;AC000;4*/ + + /* get current directory of destd_num (DosQCurDir) */ + if ((retcode = /*;AC000;4*/ + DOSQCURDIR /*;AC000;4*/ + ( destd_num, /*;AC000;4*/ + (char far *) tdestddir, /*;AC000;4*/ + (unsigned far *) &dirlen) /*;AC000;4*/ + ) != 0) /*;AC000;4*/ + { /*;AC000;4*/ + display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); /*;AC000;4*/ + } /*;AC000;4*/ + +#define BACKSLASH 0x5c + + if (strlen(tdestddir) != 1) /*;AC000;4*/ + { strcpy(temp_destddir,"\\"); /*;AC000;4*/ + strcat(temp_destddir,tdestddir); /*;AC000;4*/ + strcpy(tdestddir,temp_destddir); /*;AC000;4*/ + } /*;AC000;4*/ + + + /**********************************************************************/ + /* The next parameter has to be a file name with or without path, */ + /* or a switch. In the case of there is no path, the current path */ + /* is used. In the case of there is no file name, the global file */ + /* name *.* is used */ + /**********************************************************************/ + /* argv[2] is a drive spec*/ /*;AC000;4*/ + if (*(argv[2]+1)==':' && *argv[2] >= 'A' && *argv[2] <= 'Z' && argc!=2) /*;AC000;4*/ + { /*;AN000;6*/ + display_it(INVPARM,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + else /*;AC000;4*/ + { /*if argv[2] is not a drive spec */ /*;AC000;4*/ + /*if argv[2] started with '/' (is a switch) or there is no argv[i]*/ /*;AC000;4*/ + if (*argv[2] == '/' || *argv[2] == NUL || argc ==2) /*;AC000;4*/ + { strcpy(srcf,tdestddir); /*;AC000;4*/ + strcat(srcf,"\\*.*"); /*;AC000;4*/ + } /*;AC000;4*/ + else /*;AC000;4*/ + { /*argv[2] does not started with / */ /*;AC000;4*/ + /* find out whether part of argv[2] is switch specification */ /*;AC000;4*/ + for (k = 0; argv[2][k] != '/' && argv[2][k] != NUL; ++k);/*;AC000;4*/ + if (argv[2][k] == '/') /*;AC000;4*/ + { /*;AC000;4*/ + argv[2][k] = NUL; /*;AC000;4*/ + argv2_has_switch = TRUE; /*;AC000;4*/ + } /*;AC000;4*/ + + /*if argv[2] is \\, invalid parm */ /*;AC000;4*/ + if (argv[2][0] == '\\' && argv[2][1] == '\\' || argv[2][0] == ':') /*;AC000;;4*/ + { /*;AN000;6*/ + display_it(INVPARM,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + /*if argv[2] starts with '\' (it is a complete path)*/ /*;AC000;4*/ + if (*argv[2] == '\\') /*;AC000;4*/ + strcpy(srcf,argv[2]); /*;AC000;4*/ + else /*;AC000;4*/ + /* it is not a complete path, have to put current path in */ /*;AC000;;4*/ + /* front of the string to build a complete path */ /*;AC000;4*/ + { strcpy(srcf,tdestddir); /*;AC000;4*/ + if (strlen(tdestddir) != 1) /*;AC000;4*/ + strcat(srcf,"\\"); /*;AC000;4*/ + strcat(srcf,argv[2]); /*;AC000;4*/ + } /*endif*/ /*;AC000;4*/ + } /*end of argv[2] does not start with '/' */ /*;AC000;4*/ + + j = strlen(srcf); /*;AC000;4*/ + z = 0; /*;AC000;4*/ + do /*;AC000;4*/ + { for (;srcf[z] != '.' && srcf[z] != NUL; ++z); /*;AC000;4*/ + if (srcf[z] == '.' && srcf[z+1] == '.' && /*;AC000;4*/ + (srcf[z+2] == '\\' || srcf[z+2] == NUL)) /*;AC000;4*/ + { backdir = TRUE; /*;AC000;4*/ + break; /*;AC000;4*/ + } /*;AC000;4*/ + z = z+1; /*;AC000;4*/ + } /*;AC000;4*/ + while (z < j); /*;AC000;4*/ + + /*validate the path*/ /*;AC000;4*/ + for (z = j; srcf[z] != '\\'; --z); /*;AC000;4*/ + strcpy(tempp,srcf); /*;AC000;4*/ + tempp[z] = NUL; /*;AC000;4*/ + + for (z = 0; tempp[z] != '*' && tempp[z] != NUL; ++z); /*;AC000;4*/ + if (tempp[z] == '*' ) /*;AC000;4*/ + { display_it(PATH_NOT_FOUND,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + if (backdir == TRUE) /*;AC000;4*/ + { search_string[0] = destd; /*;AC000;4*/ + search_string[1] = ':'; /*;AC000;4*/ + search_string[2] = NUL; /*;AC000;4*/ + if (srcf[0] == NUL) /*;AC000;4*/ + strcat(search_string,"\\"); /*;AC000;4*/ + else /*;AC000;4*/ + strcat(search_string, tempp); /*;AC000;4*/ + + if(chdir(search_string)!=0) /*;AC000;4*/ + { sublist.value1 = (char far *)argv[2]; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(argv[2]); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + display_it(PATH_NOT_FOUND,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(INVALIDPARM); /*;AC000;4*/ + } /*;AC000;4*/ + + dirlen = MAXPATH; /*;AC000;4*/ + if ((retcode = DOSQCURDIR(destd_num, /*;AC000;4*/ + (char far *) ttdestddir, /*;AC000;4*/ + (unsigned far *) &dirlen)) != NOERROR) /*;AC000;4*/ + { /*;AC000;4*/ + com_msg(retcode); /*;AC000;4*/ + usererror(retcode); /*;AC000;4*/ + } /*;AC000;4*/ + /* endif */ /*;AC000;4*/ + + temp_destddir[0] = destd; /*;AC000;4*/ + temp_destddir[1] = ':'; /*;AC000;4*/ + temp_destddir[2] = NUL; /*;AC000;4*/ + strcat(temp_destddir,tdestddir); /*;AC000;4*/ + chdir(temp_destddir); /*;AC000;4*/ + + if (strlen(ttdestddir) != 1) /*;AC000;4*/ + { strcpy(temp_destddir,"\\"); /*;AC000;4*/ + strcat(temp_destddir,ttdestddir); /*;AC000;4*/ + strcpy(ttdestddir,temp_destddir); /*;AC000;4*/ + } /*;AC000;4*/ + + strcat(ttdestddir,"\\"); /*;AC000;4*/ + strcat(ttdestddir,srcf+z+1); /*;AC000;4*/ + strcpy(srcf,ttdestddir); /*;AC000;4*/ + } /*end of if backdir is true */ /*;AC000;4*/ + + /* The documentation says if path is specified, file name has to */ + /* be specified also. This logic actually allows user to specify*/ + /* path without specify filename, as long as the path end with */ + /* '\'.*/ + /*If *srcf ends with '\', add "*.*" to the end*/ /*;AC000;4*/ + j = strlen(srcf); /*;AC000;4*/ + if (srcf[j-1] == '\\') /*;AC000;4*/ + strcat(srcf,"*.*"); /*;AC000;4*/ + if (argv2_has_switch == TRUE) /*;AC000;4*/ + { *(argv[2]+k) = '/'; /*;AC000;4*/ + argv[2] = argv[2] + k; /*;AC000;4*/ + } /* end of if argv[2] started with '/' */ /*;AC000;4*/ + } /* end of checking for argv[2] */ /*;AC000;4*/ + + /**********************************************************************/ + /* add '\' at the beginning of the current destination directory */ + /**********************************************************************/ + temp_destddir[0] = destd; /*;AC000;4*/ + temp_destddir[1] = ':'; /*;AC000;4*/ + temp_destddir[2] = NUL; /*;AC000;4*/ + strcat(temp_destddir,tdestddir); /*;AC000;4*/ + strcpy(destddir,temp_destddir); /*;AC000;4*/ + + /************************************************************************/ + /* separate the filename for search into prefix(inpath), */ + /* filename(infname), and file extension (infext) */ + /* Also take care of the situation that user enter '.' only */ + /* for file spec. */ + /************************************************************************/ + separate(srcf,inpath,infname,infext,infspec); /*;AC000;4*/ + if (strlen(infname) > MAXFNAME-1 || /*;AC000;4*/ + strlen(infext) > MAXFEXT-1 || /*;AC000;4*/ + strlen(inpath) > MAXPATH-1 || /*;AC000;4*/ + strcmp(infspec,"LPT1")==0 || /*;AC000;4*/ + strcmp(infspec,"LPT2")==0 || /*;AC000;4*/ + strcmp(infspec,"PRN")==0 || /*;AC000;4*/ + strcmp(infspec,"CON")==0 || /*;AC000;4*/ + strcmp(infspec,"NUL")==0 || /*;AC000;4*/ + strcmp(infspec,"AUX")==0 || /*;AC000;4*/ + strcmp(infspec,"LPT1:")==0 || /*;AC000;4*/ + strcmp(infspec,"LPT2:")==0 || /*;AC000;4*/ + strcmp(infspec,"PRN:")==0 || /*;AC000;4*/ + strcmp(infspec,"CON:")==0 || /*;AC000;4*/ + strcmp(infspec,"NUL:")==0 || /*;AC000;4*/ + strcmp(infspec,"AUX:")==0 ) /*;AC000;4*/ + { /*;AC000;4*/ + sublist.value1 = (char far *)&infspec[0]; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.one = 0; /* Yes, this is right */ /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(infspec); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + + display_it(INVPARM,STND_ERR_DEV,1,NO_RESPTYPE,(BYTE)PARSEERROR);/*;AN000;6*/ + usererror(INVALIDPARM); /* invalid parm */ /*;AC000;4*/ + } /*;AC000;4*/ + + /************************************************************************/ + /* set wildcard flag according to whether there is '*' or/and '?' in */ + /* file specification */ + /************************************************************************/ + c = infspec; /*;AC000;4*/ + while (*c) /*;AC000;4*/ + { /*;AC000;4*/ + if (*c == '*' || *c == '?') /*;AC000;4*/ + { set_reset_test_flag(&control_flag,WILDCARD,SET); /*;AC000;4*/ + break; /*;AC000;4*/ + } /*;AC000;4*/ + else /*;AC000;4*/ + c = c+1; /*;AC000;4*/ + } /*;AC000;4*/ + + + return; /*;AN000;4*/ +} /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: process_switch +/* +/* FUNCTION: +/* +/* Identify the switch (/S,/P,/M,/N,/B:,/A:,/E:,/L:) +/* entered and handle it +/* +/**************************************************/ +void process_switch(buff_addr,ptr) /*;AN000;4*//*;AC002;*/ +unsigned buff_addr; /*;AN000;4*/ +char *ptr; /*;AN002;*/ +{ /*;AN000;4*/ + + if (buff_addr == (unsigned)&sw_buff) /*;AN000;4*/ + { /*;AN000;4*/ + if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch1[0]) /*;AN000;4 /S */ + {set_reset_test_flag(&rtswitch, SUB, SET); /*;AN000;4*/ + } + + if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch2[0]) /*;AN000;4 /P */ + { /*;AN000;4*/ + set_reset_test_flag(&rtswitch, PROMPT, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch3[0]) /*;AN000;4 /M */ + { /*;AN000;4*/ + set_reset_test_flag(&rtswitch, Revised, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw3.switch4[0]) /*;AN000;4 /N */ + { /*;AN000;4*/ + set_reset_test_flag(&rtswitch, NOTEXIST, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + } /*;AN000;4*/ + + + if (buff_addr == (unsigned)&time_buff) /*;AN000;4*/ + { /*;AN000;4*/ + check_time(time_buff.hours,time_buff.minutes,time_buff.seconds,time_buff.hundreds); /*;AN000;4*//*;AC002;*/ + + if (time_buff.tb_synonym_ptr == (WORD)&sw2.switch1[0]) /*;AN000;4 /E */ + { /*;AN000;4*/ + td.earlier_hour = time_buff.hours; /*;AN000;4*/ + td.earlier_minute = time_buff.minutes; /*;AN000;4*/ + td.earlier_second = time_buff.seconds; /*;AN000;4*/ + set_reset_test_flag(&rtswitch, EARLIER, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + if (time_buff.tb_synonym_ptr == (WORD)&sw2.switch2[0]) /*;AN000;4 /L */ + { /*;AN000;4*/ + td.later_hour = time_buff.hours; /*;AN000;4*/ + td.later_minute = time_buff.minutes; /*;AN000;4*/ + td.later_second = time_buff.seconds; /*;AN000;4*/ + set_reset_test_flag(&rtswitch, LATER, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + } /*;AN000;4*/ + + + if (buff_addr == (unsigned)&date_buff) /*;AN000;4*/ + { /*;AN000;4*/ + check_date(date_buff.year,date_buff.month,date_buff.day); /*;AN000;4*//*;AC002;*/ + + if (date_buff.db_synonym_ptr == (WORD)&sw1.switch1[0]) /*;AN000;4 /B */ + { /*;AN000;4*/ + td.before_year = date_buff.year; /*;AN000;4*/ + td.before_month = date_buff.month; /*;AN000;4*/ + td.before_day = date_buff.day; /*;AN000;4*/ + set_reset_test_flag(&rtswitch, BEFORE, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + if (date_buff.db_synonym_ptr == (WORD)&sw1.switch2[0]) /*;AN000;4 /A */ + { /*;AN000;4*/ + td.after_year = date_buff.year; /*;AN000;4*/ + td.after_month = date_buff.month; /*;AN000;4*/ + td.after_day = date_buff.day; /*;AN000;4*/ + set_reset_test_flag(&rtswitch, AFTER, SET); /*;AN000;4*/ + set_reset_test_flag(&control_flag, SWITCHES, SET); /*;AN000;4*/ + } /*;AN000;4*/ + + } /*;AN000;4*/ + + return; /*;AN000;4*/ +} /*;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 @@ +/* 0 */ +/*-----------------------------------------------------------------------*/ +/*- -*/ +/*- FILE: PARSE.H -*/ +/*- -*/ +/*- PURPOSE: Include file for RESTORE.C and other RESTORE source -*/ +/*- files. Defines structures and DEFINES for the DOS PARSE-*/ +/*- service routines -*/ +/*- -*/ +/*-----------------------------------------------------------------------*/ + + +/**********************************************************/ +/* STRUCTURE TO DEFINE ADDITIONAL COMMAND LINE DELIMITERS */ +/**********************************************************/ +struct p_parms /*;AN000;4*/ + { /*;AN000;4*/ + WORD parmsx_ptr; /* POINTER TO PARMS STRUCTURE *//*;AN000;4*/ + BYTE p_num_extra; /* 1 SAYS THAT A DELIMITER LIST FOLLOWS */ /*;AN000;4*/ + BYTE p_len_extra_delim; /* NUMBER OF ADDITIONAL DELIMITERS */ /*;AN000;4*/ + BYTE p_extra_delim[2]; /* ADDITIONAL DELIMITERS */ /*;AN000;4*/ + }; /*;AN000;4*/ + +/***************************************************/ +/* STRUCTURE TO DEFINE RESTORE SYNTAX REQUIREMENTS */ +/***************************************************/ +struct p_parmsx /*;AN000;4*/ + { /*;AN000;4*/ + BYTE p_minpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/ + BYTE p_maxpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/ + WORD pos1_ptr; /* POINTER TO SOURCE FILESPEC DEF AREA*/ /*;AN000;4*/ + WORD pos2_ptr; /* POINTER TO TARGET DRIVE DEF AREA*/ /*;AN000;4*/ + BYTE num_sw; /* THERE ARE 8 SWITCHES (/S, /P, /M, /N, /E:, /L:, /B:, /A:) */ /*;AN000;4*/ + WORD sw1_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/ + WORD sw2_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/ + WORD sw3_ptr; /* POINTER TO SWITCH DEFINITION AREA*/ /*;AN000;4*/ + WORD num_keywords; /* NUMBER OF KEYWORDS IN RESTORE SYNTAX*/ /*;AN000;4*/ + }; /*;AN000;4*/ + +/****************************************/ +/* STRUCTURE TO DEFINE POSITIONAL PARMS */ +/****************************************/ +struct p_pos_blk /*;AN000;4*/ + { /*;AN000;4*/ + WORD match_flag; /* Controls type matched */ /*;AN000;4*/ + WORD function_flag; /* Function to be included */ /*;AN000;4*/ + WORD result_buf; /* Result buffer address */ /*;AN000;4*/ + WORD value_list; /* Value list address */ /*;AN000;4*/ + BYTE nid; /* # of keyword/SW synonyms (0) *//*;AN000;4*/ + }; /*;AN000;4*/ + +/********************************/ +/* STRUCTURE TO DEFINE SWITCHES */ +/********************************/ +struct p_sw_blk /*;AN000;4*/ + { /*;AN000;4*/ + WORD p_match_flag; /* Controls type matched */ /*;AN000;4*/ + WORD p_function_flag; /* Function should be taken */ /*;AN000;4*/ + WORD p_result_buf; /* Result buffer address */ /*;AN000;4*/ + WORD p_value_list; /* Value list address */ /*;AN000;4*/ + BYTE p_nid; /* # of switches */ /*;AN000;4*/ + BYTE switch1[3]; /* Save area for switches */ /*;AN000;4*/ + BYTE switch2[3]; /* Save area for switches */ /*;AN000;4*/ + BYTE switch3[3]; /* Save area for switches */ /*;AN000;4*/ + BYTE switch4[3]; /* Save area for switches */ /*;AN000;4*/ + }; /*;AN000;4*/ +/* */ +/*---------------------------------------------------------------------------*/ + +/**************************/ +/* RETURN BUFFER FOR TIME */ +/**************************/ +struct timebuff /*;AN000;4*/ + { /*;AN000;4*/ + BYTE tb_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE tb_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/ + WORD tb_synonym_ptr; /*;AN000;4*/ + BYTE hours; /*;AN000;4*/ + BYTE minutes; /*;AN000;4*/ + BYTE seconds; /*;AN000;4*/ + BYTE hundreds; /*;AN000;4*/ + }; /*;AN000;4*/ + +/**************************/ +/* RETURN BUFFER FOR DATE */ +/**************************/ +struct datebuff /*;AN000;4*/ + { /*;AN000;4*/ + BYTE db_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE db_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/ + WORD db_synonym_ptr; /*;AN000;4*/ + WORD year; /*;AN000;4*/ + BYTE month; /*;AN000;4*/ + BYTE day; /*;AN000;4*/ + }; /*;AN000;4*/ + + +/*******************************************/ +/* RETURN BUFFER FOR POSITIONAL PARAMETERS */ +/*******************************************/ +struct p_result_blk /*;AN000;4*/ + { /*;AN000;4*/ + BYTE p_type; /* Type returned */ /*;AN000;4*/ + BYTE p_item_tag; /* Matched item tag */ /*;AN000;4*/ + WORD p_synonym_ptr; /* pointer to Synonym list returned *//*;AN000;4*/ + DWORD p_string_ptr; /* Pointer to string */ /*;AN000;4*/ + }; /* or drive number in 1st byte /*;AN000;4*/ + +/****************************************/ +/* RETURN BUFFER FOR SWITCH INFORMATION */ +/****************************************/ +struct switchbuff /*;AN000;4*/ + { /*;AN000;4*/ + BYTE sw_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE sw_item_tag; /* Matched item tag */ /*;AN000;4*/ + WORD sw_synonym_ptr; /* pointer to switch entered */ /*;AN000;4*/ + DWORD sw_string_ptr; /* Pointer to string */ /*;AN000;4*/ + }; /*;AN000;4*/ + 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 @@ +/*  0 */ +/*--------------------------------------------------------- +/*- +/*- RESTORE Utility include file RT.H +/*- +/*---------------------------------------------------------*/ + + +/****************************************************************************/ +/* This file contains equates for RESTORE utility */ +/* The equates for messages can be found in rt2.h */ +/****************************************************************************/ + +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long + +#define NOERROR 0 +#define CARRY 0x0001 /*;AN000;*/ + + +/*******************************************/ +/* Lengths of CONTROL.xxx structures */ +/*******************************************/ +#define DHEADLEN 139 /* length of new format disk header */ +#define DIRBLKLEN 70 /* length of new format dir block */ +#define FHEADLEN34 38 /*;AN000;3 Length of new format file header */ /* !wrw */ +#define FHEADLEN33 34 /* length of DOS 3.3 file header */ /* !wrw */ + +/****************************************************************************/ +/* The following group of definitions are used to set and test the restore */ +/* switch flags. */ +/****************************************************************************/ + +#define PROMPT 1 /* Prompt user before restoring hidden and */ + /* read-only files. */ +#define SUB 2 /* Restore all subdirectories too */ +#define BEFORE 4 /* Only restore files written before a date */ +#define AFTER 8 /* Only restore files written after a date */ +#define EARLIER 16 /* Only restore files written earlier then a time*/ +#define LATER 32 /* Only restore files written later than a time */ +#define Revised 64 /* Only restore files that have changed */ +#define NOTEXIST 128 /* Only restore files that no longer exist on */ + /* the destination drive. */ + + +/****************************************************************************/ +/* The following group of definitions are used to set and test the */ +/* restore control flags:control_flag. */ +/****************************************************************************/ + +#define WILDCARD 1 /* Wildcards in input filespec */ +#define OLDNEW 2 /* indicate old format or new format */ +#define CREATIT 4 /* Restore file does not exist on dest disk */ +#define FOUND 8 /* Found a file to restore */ +#define SPLITFILE 16 /* File was backed up onto 2 or more disks */ +#define SWITCHES 32 /* There are switches set */ +#define SHARERROR 64 /* There is a file not restored due to */ + /* sharing error */ +#define PARTIAL 128 /* Set if file partially restored */ + +/****************************************************************************/ +/* The following group of definitions are used to set and test the restore */ +/* control flags:control_flag2 */ +/****************************************************************************/ + +#define SPLITCTL 1 /* Indicate whether control.xxx is larger */ + /* then MAXCTRL */ +#define RTSYSTEM 2 /* The file to be restore is system file */ + /* it has to be restored contiguously */ +#define COUNTRY 4 /*when the bit is on, country info is available */ +#define CPPC 8 /* bit = 1 when CP/DOS, otherwise, PC/DOS */ +#define SRC_HDISK 16 /* bit = 1 when the source disk is harddisk */ +#define TAR_HDISK 32 /* bit = 1 when the target disk is harddisk */ +#define OUTOF_SEQ 64 /* bit = 1 when the disk is out of sequence */ +/****************************************************************************/ +/* Miscelleneous definitions */ +/****************************************************************************/ +#define ON 1 /* the tested bit is on*/ +#define OFF 0 /* the tested bit is off */ + +#define BACKUPID "BACKUPID.@@@" /* Used to reference that file */ +#define HEADLEN 128 /* Backup file header length */ +#define MAXARGS 11 /* Max # of arguments */ +#define MINARGS 1 /* Minimum # of arguments */ +#define MAXBUF 0xffff /* Max size of buf */ +#define DOWNSIZE 512 /* Amount to decrement memory request size */ + /* by when doing a series of mallocs. */ +#define MAXPATH 65 /* Length of space allocate for path names */ +#define MAXFNAME 9 /* Max length of file name */ +#define MAXFEXT 4 /* Max length of file extension */ +#define MAXFSPEC 13 /* Max length of file spec. */ +#define MAXPATHF 78 /* Max length of path and file spec */ +#define MAXYEARLEN 4 /* Max length of string that represent year */ +#define MAXMONTHLEN 2 /* Max length of string that represent month */ +#define MAXDAYLEN 2 /* Max length of string that represent day */ +#define MINYEAR 1980 /* Min value of input year */ +#define MAXYEAR 2079 /* Max value of input year */ +#define MAXMONTH 12 /* Max value of input year */ +#define MAXDAY 31 /* Max value of input year */ +#define MAXHOURLEN 2 /* Max length of string that represent hour */ +#define MAXMINUTELEN 2 /* Max length of string that represent minute*/ +#define MAXSECONDLEN 2 /* Max length of string that represent second*/ +#define NUL 0 /* The null character */ +#define NULLC '\000' /* The null character */ +#define MAXCTRL 3072 /* size of buffer to contain control.xxx */ +#define BKIDLENG 7 /* the lenght of old format disk header */ +#define NEWBKIDLENG 139 /* the length of new format disk header */ +#define NOTV 0x16 /* all file attrs except vol id */ +#define ON 1 /* the tested bit is on*/ +#define OFF 0 /* the tested bit is off */ +#define TRUE 0 /* return code, no error */ +#define FALSE 1 /* return code, there is an error */ +#define TTRUE 1 /* return code, no error */ +#define FFALSE 0 /* return code, there is an error */ +#define LAST_PART 0x01 /* the flag in finfo->fflag */ + /* if on, the file is last part of a file */ +#define COMPLETE_BIT 0x02 /* the complete bit in fheadnew->flag */ + /* if on, the file was backed up sucessfully */ +#define USA 0 +#define EUR 1 +#define JAP 2 +#define INSTALL_SIGNAL 2 /* active signal handler routine */ +#define DEACTIVE_SIGNAL 1 /* ignor signals */ +#define CTRL_C 1 /* control_c signal */ +#define CTRL_BREAK 4 /* control break signal */ + +/****************************************************************************/ +/* Defines for common subroutines - comgetarg and computmsg */ +/****************************************************************************/ + +#define RESPDATA_SIZE 1 /* size of the respdata */ +#define STND_IN_DEV 0 /* standard out device */ +#define STND_OUT_DEV 1 /* standard out device */ +#define STND_ERR_DEV 2 /* standard error device */ +#define NO_RESPTYPE 0 /*response type is no user */ + /*interaction */ +#define ANY_KEY_RESPTYPE 1 /*response type is ask user to enter*/ + /*any key. */ +#define ENTER_Y 0 /*user enter yes as response */ +#define ENTER_N 1 /*user enter no as response */ + +/****************************************************************************/ +/* Defines for convert date format */ +/****************************************************************************/ + +#define HRSHIFT 11 /* shift 11 bits to get the value of hour */ +#define HRMASK 0x1F /* mask to get the value of hour */ +#define MNSHIFT 5 /* shift 5 bits to get the value of minute */ +#define MNMASK 0x3F /* mask to get the value of minute */ +#define SCMASK 0x1F /* mask to get the value of second */ +#define MOSHIFT 5 /* shift 5 bits to get the value of month */ +#define MOMASK 0x0F /* mask to get the value of month */ +#define DYMASK 0x1F /* shift 9 bits to get the value of day */ +#define YRSHIFT 9 /* mask to get the value of day */ +#define YRMASK 0x7F /* mask to get the value of year */ +#define USA 0 +#define EUR 1 +#define JAP 2 +#define LOYR 1980 + +/****************************************************************************/ +/* Defines for subroutine set_reset_test_flag */ +/****************************************************************************/ +#define SET 0 +#define RESET 1 +#define TEST 2 + +/****************************************************************************/ +/* Defines for file attribut byte */ +/****************************************************************************/ +#define READONLY 1 /*the file is marked read only */ +#define HIDDEN 2 /*the file is marked hidden file */ +#define SYSTEM 4 /*the file is marked system file */ +#define VOLUME 8 /*the entry contains a volume label */ +#define SUBDIR 16 /*the entry is a subdirectory name */ +#define ARCHIVE 32 /*the archieve bit of the file */ + +/****************************************************************************/ +/* Defines for PCDOS return levels */ +/****************************************************************************/ + +#define PC_NORMAL 0 + /* Normal completion */ +#define PC_NOFILES 1 + /* no fl were found to restore */ +#define PC_SHARERR 2 + /* Some file not restored due to sharing error */ +#define PC_TUSER 3 + /* Terminated by user */ +#define PC_OTHER 4 + /* Terminated by user */ +/****************************************************************************/ +/* Defines for CPDOS return codes */ +/****************************************************************************/ + +#define NORMAL NO_ERROR + /* Normal completion */ +#define NOFILES ERROR_FILE_NOT_FOUND + /* no fl were found to restore */ +#define SHARERR ERROR_SHARING_VIOLATION + /* Some file not restored due to sharing error */ +#define TUSER 1026 + /* Terminated by user */ +#define INSUFMEM ERROR_NOT_ENOUGH_MEMORY + /* insufficient memory */ +#define NOBACKUPFILE 1027 + /* source does not contain bk file*/ +#define INVALIDPARM ERROR_INVALID_PARAMETER + /* invalid parmameter */ +#define INVALIDDRIVE ERROR_INVALID_DRIVE + /* invalid drive */ +#define FILESEQERROR 1028 + /* file seq error */ +#define TARGETFULL ERROR_DISK_FULL + /* target disk is full */ +#define UNEXPECTED 999 + /* unexpected error */ +#define CREATIONERROR 1029 + /* file creation error */ + /************************************************/ + /* Substitution List for Message Retriever */ + /************************************************/ +/*----------------------- +; SUBLIST Equates +;------------------------*/ +#define SUBLIST_SIZE 11 /*;AN000;6 */ + +#define LEFT_ALIGN 0x0 /*;AN000;6 00xxxxxx */ +#define RIGHT_ALIGN 0x80 /*;AN000;6 10xxxxxx */ + +#define CHAR_FIELD_CHAR 0x0 /*;AN000;6 a0000000 */ +#define CHAR_FIELD_ASCIIZ 0x10 /*;AN000;6 a0010000 */ + +#define UNSGN_BIN_BYTE 0x11 /*;AN000;6 a0010001 - Unsigned BINary to Decimal CHARacter */ +#define UNSGN_BIN_WORD 0x21 /*;AN000;6 a0100001 */ +#define UNSGN_BIN_DWORD 0x31 /*;AN000;6 a0110001 */ + +#define SGN_BIN_BYTE 0x12 /*;AN000;6 a0010010 - Signed BINary to Decimal CHARacter */ +#define SGN_BIN_WORD 0x22 /*;AN000;6 a0100010 */ +#define SGN_BIN_DWORD 0x32 /*;AN000;6 a0110010 */ + +#define BIN_HEX_BYTE 0x13 /*;AN000;6 a0010011 - Unsigned BINary to Hexidecimal CHARacter */ +#define BIN_HEX_WORD 0x23 /*;AN000;6 a0100011 */ +#define BIN_HEX_DWORD 0x33 /*;AN000;6 a0110011 */ + + +#define DATE_MDY_4 0x34 /*;AN000;6 MONTH,DAY AND YEAR (4 DIGITS)*/ +/*------------------------------------*/ +/*- MESSAGE CLASSES -*/ +/*------------------------------------*/ +#define EXTENDED 1 /*;AN000;6*/ +#define PARSEERROR 2 /*;AN000;6*/ +#define UTIL_MSG -1 /*;AN000;6*/ + +#define CR 0x0d /*;AN000;6*/ +#define LF 0x0a /*;AN000;6*/ +/*------------------------------- +/*- INT 21h +/*-------------------------------*/ +#define SETLOGICALDRIVE 0x440f /*;AN000;8*/ + +#define INSTALL_CHECK 0xB700 /*;AN000;2*/ +#define NOT_INSTALLED 0 /*;AN000;2*/ +#define GET_APPEND_VER 0xB702 /*;AN000;2*/ +#define NET_APPEND 1 /*;AN000;2*/ +#define DOS_APPEND 2 /*;AN000;2*/ +#define GET_STATE 0xB706 /*;AN000;2*/ +#define SET_STATE 0xB707 /*;AN000;2*/ + +#define APPEND_X_BIT 0x8000 /*;AN000;2*/ + 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 @@ +/*  0 */ +/*--------------------------------------------------------- +/*- +/*- RESTORE Utility include file RT1.H +/*- +/*---------------------------------------------------------*/ + +/****************************************************************************/ +/* This file contains equates for structure definitions used in RESTORE */ +/* utility. */ +/****************************************************************************/ + +/***************************************************************************/ +/* dheadnew - structure of disk header in CONTROL.xxx, */ +/* used for new format only */ +/***************************************************************************/ +struct disk_header_new + { + BYTE dhlength; /* length, in byte , of disk header*/ + BYTE id[8]; /* identifies disk as a backup */ + BYTE sequence; /* backup diskette sequence num */ + /* (binary 1-255) */ + BYTE command[128]; /* save area for command line */ + /* parameters. */ + BYTE lastdisk; /* 0ffh if last targert 0 otherwise*/ + }; + + +/***************************************************************************/ +/* dirblk - structure of directory blocks in CONTROL.xxx, */ +/* used for new format only */ +/***************************************************************************/ +struct dir_block + { + BYTE dblength; /* length, in bytes, of dir block */ + BYTE path[63]; + /* ascii path of this directory, */ + /* drive letter omitted */ + WORD numentry; /* num of filenames currently in list*/ + DWORD nextdb; /* offset of next directory block */ + }; /* =0xffff if last dir block */ + + +/***************************************************************************/ +/* fheadnew - structure of file header in CONTROL.xxx, */ +/* used for new format only */ +/***************************************************************************/ +#define EXT_ATTR_FLAG 4 /*;AN000;3*/ + +struct file_header_new + { + BYTE fhlength; /* Length, in bytes, of file header */ + BYTE fname[12]; /* ASCII file name (from directory)*/ + BYTE flag; /* bit 0=1 if last part of file */ + /* bit 1=1 if it is backed up successfully */ + /* ;AN000;3 bit 2=1 if Extended Attributes are backed up (New for DOS4.00) */ + DWORD flength; /* Total length of the file (from directory) */ + WORD fsequenc; /* Sequence #, for files that span */ + DWORD offset; /* Offset in BACKUP.xxx where this segment begins */ + DWORD partsize; /* Length of part of file on current target */ + WORD attrib; /* File attribute (from directory) */ + WORD ftime; /* Time when file was last Revised (from directory)*/ + WORD fdate; /* Date when file was last Revised (from directory)*/ + DWORD FH_EA_offset; /*;AN000;3 Offset in BACKUP.xxx where extended attrib begin */ + }; + +/*----------------------------------*/ +/*- EXTENDED OPEN PARAMETER LIST -*/ +/*----------------------------------*/ +#define EXTATTBUFLEN 4086 /*;AN000;3*/ + struct parm_list /*;AN000;3*/ + { /*;AN000;3*/ + DWORD ext_attr_addr; /*;AN000;3*/ + WORD num_additional; /*;AN000;3*/ + }; /*;AN000;3*/ + + + + + + + + + + +/**************************************************************************/ +/* Fheadold - structure of file header, used for old format only. */ +/* There are 128 bytes totally in file header of the old */ +/* format backup disk. Only the first 85 bytes contains */ +/* meaningful information. */ +/* This is the structure attached to the beginning of every */ +/* file backed up with DOS 2.0 through 3.2 inclusive. */ +/**************************************************************************/ +struct file_header_old + { + BYTE headflg; /* 0FFh is last sequence of file, 00h if not last*/ + BYTE disknum[2]; /* file sequence number */ + BYTE fill1[2]; /* not used */ + BYTE wherefrom [78]; /* asciiz path and name without drive letter*/ + unsigned pathlen; /* length of previous field, not used in this program*/ + char garbage[50]; /* Filler */ + }; + + + + +/***************************************************************************/ +/* dheadold - structure of disk informtion, used by old format only. */ +/* There are 128 bytes totally in disk header of the old */ +/* format backup disk. Only the first 7 bytes contains */ +/* meaningful information. */ +/* This is the BACKUPID.@@@ file */ +/***************************************************************************/ + +struct disk_header_old + { + BYTE diskflag; /* 0FFh if last disk, 00h if not last disk. */ + /* initialize it to 0FFh when BACKUP.@@@ is created,*/ + /* and zero it out when the disk is full */ + BYTE disknum[2]; /* Sequence number of the disk. Least significant*/ + /* byte first. */ + BYTE diskyear[2]; /* Year, LSB first. */ + BYTE diskday; /* Month (1 byte) and day (1 byte). */ + BYTE diskmonth; /* Month (1 byte) and day (1 byte). */ + }; + + +/***************************************************************************/ +/* timedate- structure of buffer to hold time and date data */ +/***************************************************************************/ +struct timedate { + unsigned int earlier_hour; + unsigned int earlier_minute; + unsigned int earlier_second; + unsigned int later_hour; + unsigned int later_minute; + unsigned int later_second; + unsigned int before_year; + unsigned int before_month; + unsigned int before_day; + unsigned int after_year; + unsigned int after_month; + unsigned int after_day; +}; +/***************************************************************************/ +/* fsinfo - structure of buffer returned from dosqsinfo */ +/***************************************************************************/ +struct fsinfo { /* file system information */ + unsigned long file_system_id; /* file system ID 4 */ + unsigned long sectors_per_alloc_unit; /* sectors per allocation unit 4 */ + unsigned long number_of_alloc_unit; /* number of allocation unit 4 */ + unsigned long available_alloc_unit; /* available allocatuib unit 4 */ + unsigned bytes_per_sector; /* number of bytes per sectors 2 */ +}; /* total byte size = 18 */ + +#define FSINFO_BYTES sizeof(struct fsinfo) /* total # of bytes for BPB */ + +/***************************************************************************/ +/* internat - structure of buffer returned from get country information */ +/***************************************************************************/ +struct internat { +unsigned country_code; /* country code */ +unsigned code_page; /* country code page */ +unsigned dtformat; /* time date format */ + /* 0-usa 1-eur 2-jap */ +BYTE currency_sym, /* Currency Symbol 5 bytes */ + r1, + r2, + r3; +BYTE r4; /* null terminated */ +BYTE thous_sep, /* Thousands separator 2 bytes */ + r5; /* null terminated */ +BYTE decimal_sep, /* Decimal separator 2 bytes */ + r6; /* null terminated */ +BYTE datesep, /* Date separator 2 bytes */ + r7; /* null terminated */ +BYTE timesep, /* Time separator 2 bytes */ + r8; /* null terminated */ +BYTE bit_field; /* Bit values */ + /* Bit 0 = 0 if currency symbol first */ + /* = 1 if currency symbol last */ + /* Bit 1= 0 if No space after currency symbol*/ + /* = 1 if space after currency symbol */ +BYTE currency_cents; /* Number of places after currency dec point*/ +BYTE tformat; /* 1 if 24 hour time, 0 if 12 hour time */ +unsigned long map_call; /* Address of case mapping call (DWORD) */ + /* in real mode compatibility API */ +BYTE data_sep, /* Data list separator character */ + r9; /* null terminated */ +unsigned ra[ 5 ]; /* reserved */ +} ; + + +/***************************************************************************/ +/* Finfo - structure of file information, used for both old format and */ +/* new format. It contains the information which is common */ +/* between new and old. */ +/***************************************************************************/ +struct file_info + { + BYTE fname[MAXFSPEC+1]; /* ASCII, filename and file extension.*/ + BYTE path[MAXPATH+1]; /* ASCII, file path, always started with \ */ + /* and not end with \ */ + BYTE fflag; /* last disk in case of file expanded */ + /* bit 0 = 1 if last part of file */ + /* In old format file header, its 0ffh if last. */ + /* The old format has to be converted into bit0=1.*/ + unsigned dnum; /* sequence number of the file. For file that span */ + unsigned attrib; /* file attribute */ + unsigned ftime; /* time when the file was created */ + unsigned fdate; /* date when the file was created */ + unsigned long partsize; /* part size of the file */ + unsigned long offset; /* offset of the file in backup.xxx */ + BYTE curdir[MAXPATH]; /* current directory of the destination disk.*/ + /* The current directory usually is maintained to be*/ + /* the directory that reside the file to be restored*/ + DWORD ea_offset; /*;AN000;3 Offset in BACKUP.xxx where extended attrib begin */ +}; + +/****************************************************************************/ +/* dfinfo - destination file information, if the destination file */ +/* is exist. Structure of file information, used for both old */ +/* format and new format. It contains the information which is*/ +/* common between new and old. */ +/****************************************************************************/ +struct dfile_info { +BYTE fname[12]; /* ASCII, filename and file extension.*/ +BYTE path[64]; /* ASCII, file path, always started with \ and */ + /* not end with \ */ +BYTE fflag; /* last disk in case of file expanded */ + /* bit 0 = 1 if last part of file */ + /* In old format file header, its 0ffh if last. */ + /* The old format has to be converted into bit0=1.*/ +unsigned short dnum; /* sequence number of the file. For file that span */ +unsigned attrib; /* file attribute */ +unsigned ftime; /* time when the file was created */ +unsigned fdate; /* date when the file was created */ +BYTE *curdir; /* current directory of the destination disk. */ + /* The current directory usually is maintained to be */ + /* the directory that reside the file to be restored */ +}; + +/***************************************************************************/ +/* dinfo - structure of disk information, used for both old format and */ +/* new format. It contains the information which is common */ +/* between new and old. */ +/***************************************************************************/ +struct disk_info { +BYTE dflag; /* last backup disk or not */ + /* Its 0ffh if last. 00h otherwise */ +BYTE disknum; /* sequence number of the file. For file that span */ +}; + struct subst_list /*;AN000;6 */ + { /*;AN000;6 */ + BYTE sl_size1; /* Size of List */ /*;AN000;6 */ + BYTE zero1; /* Reserved */ /*;AN000;6 */ + char far *value1; /* Time, date, or ptr to data item*/ /*;AN000;6 */ + BYTE one; /* n of %n */ /*;AN000;6 */ + BYTE flags1; /* Data Type flags */ /*;AN000;6 */ + BYTE max_width1; /* Maximum FIELD width */ /*;AN000;6 */ + BYTE min_width1; /* Minimum FIELD width */ /*;AN000;6 */ + BYTE pad_char1; /* Character for pad FIELD */ /*;AN000;6 */ + + BYTE sl_size2; /* Size of List */ /*;AN000;6 */ + BYTE zero2; /* Reserved */ /*;AN000;6 */ + char far *value2; /* Time; date; or ptr to data item*/ /*;AN000;6 */ + BYTE two; /* n of %n */ /*;AN000;6 */ + BYTE flags2; /* Data Type flags */ /*;AN000;6 */ + BYTE max_width2; /* Maximum FIELD width */ /*;AN000;6 */ + BYTE min_width2; /* Minimum FIELD width */ /*;AN000;6 */ + BYTE pad_char2; /* Character for pad FIELD */ /*;AN000;6 */ + }; /*;AN000;6 */ + 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 @@ +/*  0 */ +/*--------------------------------------------------------- +/*- +/*- RESTORE Utility include file RT2.H +/*- +/*---------------------------------------------------------*/ + + + +/*------------------------------------*/ +/* MESSAGE DEFINITIONS */ +/*------------------------------------*/ +#define INVPARM 10 /* Parse class */ /*;AN000;6*/ + +#define INVALID_DOS_VER 1 /*;AN000;6*/ +#define SOURCE_TARGET_SAME 2 /*;AN000;6*/ +#define INVALID_NUM_PARM 3 /*;AN000;6*/ +#define PATH_NOT_FOUND 5 /*;AN000;6*/ +#define INVALID_DRIVE 6 /*;AN000;6*/ +#define NO_FILE_TO_RESTORE 7 /*;AN000;6*/ +#define INSERT_SOURCE_DISK 8 /*;AN000;6*/ +#define INSERT_TARGET_DISK 9 /*;AN000;6*/ +#define PRESS_ANY_KEY 10 /*;AN000;6*/ +#define DISK_OUT_OF_SEQUENCE 11 /*;AN000;6*/ +#define LAST_FILE_NOT_RESTORED 12 /*;AN000;6*/ +#define FILES_WERE_BACKUP_ON 13 /*;AN000;6*/ +#define SOURCE_NO_BACKUP_FILE 14 /*;AN000;6*/ +#define INSUFFICIENT_MEMORY 15 /*;AN000;6*/ +#define FILE_IS_READONLY 16 /*;AN000;6*/ +#define FILE_SEQUENCE_ERROR 17 /*;AN000;6*/ +#define FILE_CREATION_ERROR 18 /*;AN000;6*/ +#define TARGET_IS_FULL 19 /*;AN000;6*/ +#define NOT_ABLE_TO_RESTORE_FILE 20 /*;AN000;6*/ +#define RESTORE_FILE_FROM_DRIVE 21 /*;AN000;6*/ +#define FILE_WAS_CHANGED 22 /*;AN000;6*/ +#define DISKETTE_NUM 23 /*;AN000;6*/ + +#define INV_DATE 27 /*;AN000;6*/ +#define INV_TIME 28 /*;AN000;6*/ +#define NO_SOURCE 29 /*;AN000;6*/ +#define NO_TARGET 30 /*;AN000;6*/ +#define CRLF 31 /*;AN000;6*/ + +#define FILE_TO_BE_RESTORED 99 /*;AN000;6*/ + +/*------------------------------------*/ +/*- MESSAGE CLASSES -*/ +/*------------------------------------*/ +#define EXTENDED 1 /*;AN000;6*/ +#define PARSEERR 2 /*;AN000;6*/ +#define UTILMSG -1 /*;AN000;6*/ + +/* 0*/ +/*----------------------------------*/ +/*- SUBROUTINE DECLARATIONS */ +/*----------------------------------*/ +void main(int ,char *[0]); +void set_input_switches(WORD,BYTE * *,WORD *,struct timedate *); +void verify_input_switches(BYTE *,struct timedate *); +int set_reset_test_flag(BYTE *,BYTE ,int ); +void separate(BYTE *,BYTE *,BYTE *,BYTE *,BYTE *); +void initbuf(DWORD *); +void init_control_buf(unsigned long ,unsigned int *); +void usererror(WORD ); +void unexperror(WORD ); +void exit_routine(WORD ); +void pascal far signal_handler_routine(void ); +extern unsigned far pascal set_int24_vector(void); /*;AN000;*/ +void com_msg(WORD ); +int checkdosver(void ); +void dorestore(BYTE ,BYTE ,BYTE *,BYTE *,BYTE *,BYTE *,struct timedate *); +void check_bkdisk_old(struct disk_header_old *, struct disk_info *,BYTE,unsigned int *); +void check_bkdisk_new(struct disk_header_new far *,struct disk_info *,BYTE,unsigned int *,unsigned int *); +void print_info(int ,int ,int); +WORD pathmatch(BYTE *,BYTE *); +WORD switchmatch(struct file_info *,BYTE,BYTE,struct timedate *); + +int check_flheader_old(struct file_info *,unsigned char *,unsigned int , + unsigned int ,unsigned int ,unsigned long ,unsigned int ,unsigned char , + unsigned char ,unsigned char *,unsigned char *,unsigned int *); + +int readonly_or_changed(unsigned int ,unsigned char ,unsigned char *, unsigned char *); +int fspecmatch(char *,char *); +WORD open_dest_file(struct file_info *,BYTE ); +void build_path_create_file(BYTE *,BYTE,BYTE,DWORD); /*;AC000;3*/ +int set_attributes_and_close(struct file_info *, BYTE); +int dos_write_error(DWORD ,BYTE ); +int findfile_new(struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far * *,WORD far * *,unsigned int *,BYTE *); +int findnew_new(struct file_info *,WORD *,WORD *,BYTE *,BYTE *, WORD far * *,WORD far * *,WORD *,BYTE *); + + void search_src_disk_old(struct disk_info *,struct file_info *,struct disk_header_old *, + struct disk_header_new far *,struct file_header_new far *, + unsigned char,unsigned char,unsigned long,unsigned int *,unsigned char *,unsigned char *, + unsigned char *,unsigned char *,struct timedate *); + + void search_src_disk_new(struct disk_info *,struct file_info *,struct disk_header_old *, + struct disk_header_new far *,struct file_header_new far *, + unsigned char,unsigned char,unsigned int *,unsigned long,unsigned char *,unsigned char *, + unsigned char *,unsigned int *,struct timedate *); + +int findfirst_new(struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far**,WORD far**,unsigned int *,BYTE *); +int findnext_new (struct file_info *,WORD *,unsigned int *,BYTE *,BYTE *,WORD far**,WORD far**,unsigned int *,BYTE *); + +void restore_a_file(struct file_info *,struct disk_info *,unsigned long,unsigned int *, + struct file_header_new far *,struct disk_header_old *,struct disk_header_new far *,unsigned char,unsigned char, + unsigned char *,unsigned char *,unsigned char *,unsigned int *,unsigned int *); + +/*---------------------------------------- +/*- ADDED FOR DOS 4.00 +/*----------------------------------------*/ +int cdecl sprintf(char *,const char *, ...); +int cdecl printf(const char *,...); +void check_time(BYTE,BYTE,BYTE,BYTE); /*;AN000;4*//*;AC002;*/ +void check_date(WORD,BYTE,BYTE); /*;AN000;4*//*;AC002;*/ +void parse_error(WORD,BYTE); /*;AN000;4*//*;AC002;*/ +void parse_init(void); /*;AN000;4*/ +void process_switch(unsigned,char *); /*;AN000;4*//*;AC002;*/ +void check_source_drive(int,char * []); /*;AN000;4*/ +void check_target_filespec(int,char * []); /*;AN000;4*/ +void display_it(WORD,WORD,WORD,WORD,BYTE); /*;AN000;6*/ +void parse_command_line(int, char * []); /*;AN000;4*/ +void check_appendX(void); /*;AN000;2*/ +void read_in_first_dirblock(void); /* !wrw */ +void read_in_a_fileheader(void); /* !wrw */ +void read_in_next_dirblock(void); /* !wrw */ +void get_fileheader_length(void); /*;AN000;3*/ +WORD create_the_file(BYTE,DWORD); /*;AN000;3*/ +void read_the_extended_attributes(DWORD); /*;AN000;3*/ +void check_for_device_names(char * []); /*;AN000;p2591*/ +WORD chek_DBCS(char *,WORD,char); /*;AN005;*/ +void Get_DBCS_vector(void); /*;AN005;*/ + +extern void sysloadmsg(union REGS *, union REGS *); /*_msgret *//*;AN000;6 */ +extern void sysdispmsg(union REGS *, union REGS *); /*_msgret *//*;AN000;6 */ +extern void parse (union REGS *, union REGS *); /* _parse *//*;AN000;4 */ + 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 @@ + +/*------------------------------------ +/* SOURCE FILE NAME: RTDO.C +/*------------------------------------ +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "direct.h" +#include "stdio.h" +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +BYTE *buf_pointer; +unsigned control_file_pointer; +unsigned src_file_handle; +struct FileFindBuf filefindbuf; +struct FileFindBuf dfilefindbuf; +BYTE far *control_buf_pointer; +unsigned int control_bufsize; /* !wrw */ + +extern unsigned char srcddir[MAXPATH+3]; +extern unsigned char rtswitch; +extern unsigned char control_flag; +extern unsigned char control_flag2; +extern unsigned control_file_handle; /* !wrw */ +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : Dorestore +/* +/* DESCRIPTIVE NAME : Searching all disks and restore the matching files. +/* +/* FUNCTION: This routine does the following: +/* 1. Initialize the buffer +/* 2. Change directory to the one which will hold the first +/* files to be restored. +/* 3. If the source drive is removable +/* Ouput the message to the screen for user to insert a +/* diskette and hit a key when ready. +/* 4. If the target drive is removable +/* Ouput the message to the screen for user to insert a +/* diskette and hit a key when ready. +/* 5. Check whether the diskette contains old or new data +/* format. +/* 6. ouput "file were backup xx-xx-xx" +/* +/* For each diskette, do the following: +/* 5. Call check_bkdisk_old or check_bkdisk_new to check whethe +/* it is a backup diskette and whether it is in correct +/* sequence number. +/* 6. Call search_src_disk_old or search_src_disk_new to search +/* the entire diskette to find matching files and +/* restore them. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void dorestore(srcd,destd,inpath,infname,infext,infspec,dt) /* wrw! */ +BYTE srcd; +BYTE destd; +BYTE *inpath; +BYTE *infname; +BYTE *infext; +BYTE *infspec; +struct timedate *dt; +{ + BYTE string[MAXPATH+2]; + struct disk_header_old dheadold; + struct disk_header_new dheadnew; + struct file_header_new fheadnew; + struct disk_info dinfo; + struct file_info finfo; + unsigned int control_bufsize; + unsigned dirlen = MAXPATH; + WORD dyear; + WORD dmonth; + WORD dday; + + BYTE c; + BYTE done; /*;AN000;p????*/ + BYTE path_to_be_chdir[MAXPATH]; + WORD srcd_num; + BYTE temp_srcddir[MAXPATH]; + unsigned int dnumwant = 1; + DWORD bufsize; + BYTE temp_array1[4]; /*temparary array to build parameters for substitution list */ + BYTE temp_array2[4]; + + /*declaration for dosfindfirst */ + unsigned dirhandle = 1; + unsigned attribute = NOTV; + unsigned search_cnt = 1; /* # of entries to find */ + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + WORD retcode; + /*end decleration for ffirst and fnext*/ + + union REGS qregs; /*;AN000;8*/ + DWORD date; /*;AN000;6*/ + + /****************************************************************/ + /* change dest drive directory to the one which will hold the */ + /* first file to be restored */ + /****************************************************************/ + string[0] = destd; + string[1] = ':'; + string[2] = NULLC; + strcat(string,inpath); + /*if chdir sucessful, save the directory in finfo->curdir*/ + /*if fail, the path is not exist, and needs to be rebuild*/ + if(chdir(string)==0) + strcpy(finfo.curdir,inpath); + + /*****************************************************************/ + /*if the source disk is hard disk get the current dir of the srcd*/ + /* chdir the source disk to be in \backup directory */ + /*****************************************************************/ + /**************************************/ + /* if the source disk is a hard disk */ + /**************************************/ + /* save current directory of source disk to be reset back later */ + /* convert character srcd into integer form */ + /**************************************/ + + srcd_num = (WORD)(srcd - 'A' +1); + + /**************************************/ + /* get current directory of srcd (DosQCurDir) */ + /**************************************/ + if ((retcode = DOSQCURDIR(srcd_num,(char far *) srcddir,(unsigned far *)&dirlen)) != 0) + { + display_it(INVALID_DRIVE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INVALIDDRIVE); + } + + temp_srcddir[0] = srcd; + temp_srcddir[1] = ':'; + temp_srcddir[2] = NULLC; + if (strlen(srcddir) != 1) + strcat(temp_srcddir,"\\"); + strcat(temp_srcddir,srcddir); + strcpy(srcddir,temp_srcddir); + + path_to_be_chdir[0] = srcd; + path_to_be_chdir[1] = ':'; + path_to_be_chdir[2] = NULLC; + if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == TRUE) + strcat(path_to_be_chdir,"\\BACKUP"); + else + strcat(path_to_be_chdir,"\\"); + + if(chdir(path_to_be_chdir)!=0) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(NOBACKUPFILE); + } + + /*****************************************************************/ + /* Identify whether the inserted diskette is a old format backup */ + /* diskette or a new format backup diskette */ + /* BACKUP.@@@ or BACKUP.xxx with xxx numeric characters has */ + /* to be on the diskette */ + /*****************************************************************/ + search_string[0] = srcd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, "BACKUP*.???"); + + /***********************/ + /* Find the first file */ + /***********************/ + done = FFALSE; /*;AN000;p????*/ + + retcode = /*;AN000;p????*/ + DOSFINDFIRST /*;AN000;p????*/ + ( /*;AN000;p????*/ + (char far *)search_string, /*;AN000;p????*/ + (unsigned far *)&dirhandle, /*;AN000;p????*/ + attribute, /*;AN000;p????*/ + (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/ + buf_len, /*;AN000;p????*/ + (unsigned far *)&search_cnt, /*;AN000;p????*/ + (DWORD) 0 /*;AN000;p????*/ + ); /*;AN000;p????*/ + + if (retcode != NOERROR) /*;AN000;p????*/ + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/ + usererror(NOBACKUPFILE); /*;AN000;p????*/ + } /*;AN000;p????*/ + + /*****************************/ + /* Skip over subdirectories */ + while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR) /*;AN000;p????*/ + { /*;AN000;p????*/ + search_cnt = 1; /*;AN000;p????*/ + + retcode = /*;AN000;p????*/ + DOSFINDNEXT /*;AN000;p????*/ + ( dirhandle, /*;AN000;p????*/ + (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/ + buf_len, /*;AN000;p????*/ + (unsigned far *)&search_cnt /*;AN000;p????*/ + ); /*;AN000;p????*/ + + if (retcode != NOERROR) /*;AN000;p????*/ + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/ + usererror(NOBACKUPFILE); /*;AN000;p????*/ + } /*;AN000;p????*/ + } /*;AN000;p????*/ + + /****************************************/ + /* Loop through looking at file names */ + /****************************************/ + do /*;AN000;p????*/ + { /* Is it old BACKUP ??? */ /*;AN000;p????*/ + if (strcmp(filefindbuf.file_name,BACKUPID)==0) /*;AN000;p????*/ + { /*;AN000;p????*/ + set_reset_test_flag(&control_flag,OLDNEW,SET); /*;AN000;p????*/ + done = TTRUE; /*;AN000;p????*/ + } /*;AN000;p????*/ + else /*;AN000;p????*/ + { /* Is it new BACKUP ??? */ /*;AN000;p????*/ + if ((filefindbuf.file_name[6] == '.') && /*;AN000;p????*/ + (filefindbuf.file_name[7] >= '0') && /*;AN000;p????*/ + (filefindbuf.file_name[7] <= '9') && /*;AN000;p????*/ + (filefindbuf.file_name[8] >= '0') && /*;AN000;p????*/ + (filefindbuf.file_name[8] <= '9') && /*;AN000;p????*/ + (filefindbuf.file_name[9] >= '0') && /*;AN000;p????*/ + (filefindbuf.file_name[9] <= '9') && /*;AN000;p????*/ + (filefindbuf.file_name[10] == NULLC) ) /*;AN000;p????*/ + { /*;AN000;p????*/ + set_reset_test_flag(&control_flag,OLDNEW,RESET); /*;AN000;p????*/ + init_control_buf((unsigned long)0,&control_bufsize);/*;AN000;p????*/ + done = TTRUE; /*;AN000;p????*/ + } /*;AN000;p????*/ + } + + if (!done) + do + { /*;AN000;p????*/ + search_cnt = 1; /*;AN000;p????*/ + retcode = /*;AN000;p????*/ + DOSFINDNEXT /*;AN000;p????*/ + ( dirhandle, /*;AN000;p????*/ + (struct FileFindBuf far *)&filefindbuf, /*;AN000;p????*/ + buf_len, /*;AN000;p????*/ + (unsigned far *)&search_cnt /*;AN000;p????*/ + ); /*;AN000;p????*/ + + if (retcode != NOERROR) /*;AN000;p????*/ + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;p????*/ + usererror(NOBACKUPFILE); /*;AN000;p????*/ + } /*;AN000;p????*/ + + } /* end while */ /*;AN000;p????*/ + while(filefindbuf.attributes & SUBDIR == SUBDIR); + + } /* end DO loop */ /*;AN000;p????*/ + while (!done); /*;AN000;p????*/ + + + retcode = DOSFINDCLOSE(dirhandle); + + /***************************************/ + /* Display the date of the backup disk */ + /***************************************/ + dyear = (filefindbuf.write_date >> YRSHIFT & YRMASK) + LOYR; + dmonth = filefindbuf.write_date >> MOSHIFT & MOMASK; + dday = filefindbuf.write_date & DYMASK; + date = dyear + (dday*16777216) + (dmonth*65536); /*;AN000;6*/ + + sublist.value1 = (char far *)date; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + DATE_MDY_4; /*;AN000;6*/ + sublist.max_width1 = (BYTE)10; /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + display_it(FILES_WERE_BACKUP_ON,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + + /*****************************************************************/ + /*start a loop to check and restore each diskette */ + /*****************************************************************/ + initbuf(&bufsize); /* !wrw */ + + for (;;) + { + + /*****************************************************************/ + /* check whether the inserted diskette is a backup diskette */ + /*****************************************************************/ + /*if old, check_bkdisk_old else check_bkdisk_new*/ + + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + check_bkdisk_old(&dheadold, &dinfo, srcd, &dnumwant); + else + check_bkdisk_new((struct disk_header_new far *)&dheadnew, &dinfo, srcd, &dnumwant,&control_bufsize); + + /*****************************************************************/ + /* At this point a real backup diskette which is in correct sequence number */ + /* has been found. In the case of new format, the file CONTROL.xxx is open.*/ + /*****************************************************************/ + /* restored the diskette */ + /*****************************************************************/ + + /*if old*/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + search_src_disk_old(&dinfo,&finfo,&dheadold,(struct disk_header_new far *)&dheadnew, + (struct file_header_new far *)&fheadnew,srcd,destd,bufsize,&dnumwant, + inpath,infname,infext,infspec,dt); + else + search_src_disk_new(&dinfo,&finfo,&dheadold,(struct disk_header_new far *)&dheadnew, + (struct file_header_new far *)&fheadnew,srcd,destd,&dnumwant,bufsize, + inpath,infname,infspec,&control_bufsize,dt); + + printf("\n"); + set_reset_test_flag(&control_flag2,OUTOF_SEQ,RESET); + /************************************************************************/ + /*if ( bk disk is not the last one && (the file spec is WILDCARD or file*/ + /*not found yet or SUB flag in rtswitches is on)), then prompt for user */ + /*to insert another diskette and loop again. */ + /************************************************************************/ + if ((dinfo.dflag!=0xff) && + ((set_reset_test_flag(&control_flag,WILDCARD,TEST) == TRUE) || + (set_reset_test_flag(&control_flag,FOUND,TEST) == FALSE) || + (set_reset_test_flag(&rtswitch,SUB,TEST) == TRUE))) + { + /**********************************************************/ + /* output message for user to insert another diskette and */ + /* "strike any key when ready" */ + /* with response type 4 (wait for a key to be hit) */ + /**********************************************************/ + + if (control_file_handle != 0xffff) /* !wrw */ + { /* !wrw */ + DOSCLOSE(control_file_handle); /* !wrw */ + control_file_handle = 0xffff; /* !wrw */ + } /* !wrw */ + + temp_array1[0] = (char)((dnumwant / 10) + '0'); + temp_array1[1] = (char)((dnumwant % 10) + '0'); + temp_array1[2] = NULLC; + temp_array2[0] = srcd; + temp_array2[1] = NULLC; + + sublist.value1 = (char far *)temp_array1; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + + sublist.value2 = (char far *)temp_array2; /*;AN000;6 */ + sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6 */ + sublist.min_width2 = sublist.max_width2; /*;AN000;6 */ + + display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /* If single drive system, eliminates double prompting */ + /* for user to "Insert diskette for drive %1" */ + qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ + qregs.h.bl = srcddir[0] - 'A' + 1; /*;AN000;8*/ + intdos(&qregs,&qregs); /*;AN000;8*/ + + continue; + } + else + break; + + } /*end of for loop*/ + + + return; +} /*;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 @@ + +/*----------------------------- +/* SOURCE FILE NAME: RTDO1.C +/*----------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +struct disk_header_new russ_disk_header; /* !wrw */ +unsigned control_file_handle = 0xffff; /* !wrw */ + +extern BYTE control_flag2; +extern BYTE far *control_buf_pointer; +extern unsigned control_selector; +extern struct FileFindBuf filefindbuf; +extern struct internat ctry; /* data area for get country info */ +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : check_bkdisk_new +/* +/* DESCRIPTIVE NAME : For new format only, check to see whether the disk +/* is a backup disk, and whether the disk is in right +/* sequence. +/* +/* FUNCTION: The routine does the following: +/* 1. Find the file CONTROL.xxx. If the file is not there +/* the disk is not a backup disk. +/* 2. validate the extension of control.xxx +/* 3. Check the sequence number of the disk to make sure +/* its in sequence. +/* 4. Open the file CONTROL.xxx. +/* 5. Read the file CONTROL.xxx in. +/* 6. Fill dinfo with correct information. +/* 7. Output a message to the screen to confirm that +/* the disk is going to be restored. +/* +/* NOTES: This subroutine also take care of situation that user +/* insert a old format diskette while the RESTORE started with +/* new format diskettes. +/* +/* When the inserted disk does not contain the file CONTROL.xxx, +/* a message "source file does not contains backup files" is +/* output to the user. If the user wants to change diskette +/* and try again, next diskette will be read. +/* +/* When disk is out of sequence, a 'warning' is given to user, +/* if the user still wants to proceed the restoring by doing +/* nothing but hit a key, the same diskette will be read again. +/* In case of expanded file, another check for dnum of the expand +/* file will guarantee the disk in sequence. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void check_bkdisk_new(dheadnew, dinfo, srcd, dnumwant,control_bufsize) /* wrw! */ + +struct disk_header_new far *dheadnew; +struct disk_info *dinfo; +BYTE srcd; +unsigned int *dnumwant; +unsigned int *control_bufsize; +{ + WORD dnumok = FALSE; + WORD disknum; /*disk number carried by the file name backup.xxx*/ + BYTE fname_to_be_opened[13]; + WORD numread; + BYTE temp_array1[4]; + BYTE temp_array2[4]; + BYTE c; + WORD read_count; + WORD action; + + + /*declaration for dosfindfirst */ + unsigned dirhandle = 0xffff; + unsigned attribute = NOTV; + unsigned search_cnt = 1; + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + WORD retcode; + /*end decleration for ffirst and fnext*/ + /*****************************/ + /*search for control.xxx */ + /*****************************/ + for (;;) + { + /*DosFindFirst, using the filename CONTROL.???*/ + search_string[0] = srcd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, "CONTROL.???"); + dirhandle = 0xffff; + search_cnt = 1; + + retcode = /* Find the 1st filename that */ + DOSFINDFIRST( /* matches specified fspec*/ + (char far *)search_string, /* File path name*/ + (unsigned far *)&dirhandle, /* Directory search handle */ + attribute, /* Search attribute */ + (struct FileFindBuf far *)&filefindbuf, + buf_len, /* Result buffer length */ + (unsigned far *)&search_cnt, /* Number of entries to find */ + (DWORD) 0 + ); + + if (retcode != NOERROR) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(NOBACKUPFILE); + } + else + { + /*if the directory found is a subdirectory, find next one*/ + while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR) + { + search_cnt = 1; + retcode = DOSFINDNEXT(dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt); + if (retcode != 0) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(NOBACKUPFILE); + } + } /*end while */ + } /*end of file control.xxx not found*/ + + retcode = DOSFINDCLOSE(dirhandle); + + /********************************************************************/ + /* validate the file extension of control.xxx to make sure they are */ + /* three numeric characters */ + /********************************************************************/ + if ((filefindbuf.file_name[7] != '.') || (filefindbuf.file_name[8] < '0') || + (filefindbuf.file_name[8] > '9') || (filefindbuf.file_name[9] < '0') || + (filefindbuf.file_name[9] > '9') || (filefindbuf.file_name[10] < '0') || + (filefindbuf.file_name[10] > '9') || (filefindbuf.file_name[11] != NULLC) ) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(NOBACKUPFILE); + } + + /********************************************************************/ + /* check the disk sequence number of the disk */ + /********************************************************************/ + if (dnumok == TRUE) + { + if (disknum != *dnumwant) + set_reset_test_flag(&control_flag2,OUTOF_SEQ,SET); + dnumok = FALSE; + } + else + { + disknum = (filefindbuf.file_name[8]-'0')*100 + + (filefindbuf.file_name[9]-'0')*10 + +filefindbuf.file_name[10]-'0'; + if (disknum != *dnumwant) + { + display_it(DISK_OUT_OF_SEQUENCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /* When disk is out of sequence, a 'warning' is given to user. */ + /* If the user still wants to proceed the restoring by doing */ + /* nothing but hit a key, the same diskette will be read again.*/ + dnumok = TRUE; + + continue; + } /*endif*/ + } /*endif of dnumok = FALSE*/ + + /********************************************************************/ + /* open control.xxx */ + /********************************************************************/ + fname_to_be_opened[0] = srcd; + fname_to_be_opened[1] = ':'; + fname_to_be_opened[2] = NULLC; + strcat(fname_to_be_opened,filefindbuf.file_name); + + retcode = + DOSOPEN + ( (char far *)&fname_to_be_opened[0], + (unsigned far *)&control_file_handle, /* !wrw */ + (unsigned far *)&action, + (DWORD)0, + 0, + 0x01, + 0x00c0, + (DWORD)0 + ); + + if (retcode != NOERROR) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(NOBACKUPFILE); + } + + /********************************************************************/ + /* READ DISK_HEADER INTO STATIC DISKHEADER STRUCTURE wrw */ + /********************************************************************/ + + retcode = + DOSREAD + ( /* !wrw */ + control_file_handle, /* !wrw */ + (char far *)&russ_disk_header, /* !wrw */ + (unsigned short)DHEADLEN, /* !wrw */ + (unsigned far *)&read_count /* !wrw */ + ); /* !wrw */ + + if (retcode != NOERROR || (DWORD)read_count != (DWORD)DHEADLEN) /* !wrw */ + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + unexperror(NOBACKUPFILE); + } + + /********************************************************************/ + /* get and store dheadnew information into dinfo */ + /********************************************************************/ + dheadnew = (struct disk_header_new far *)&russ_disk_header; /* !wrw */ + + dinfo->disknum = dheadnew->sequence; + dinfo->dflag = dheadnew->lastdisk; + + /* At this point, the diskette has passed all the checking, and */ + /* should be a ok diskette. break out of the loop.*/ + break; + + } /*end of "for (;;)" loop */ + + /********************************************************************/ + /* output confirm msg "restore file from drive d:" */ + /********************************************************************/ + temp_array1[0] = srcd; + temp_array1[1] = NULLC; + + sublist.value1 = (char far *)temp_array1; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + + display_it(RESTORE_FILE_FROM_DRIVE,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + + /********************************************************************/ + /* if the source disk is removable, output diskette number also */ + /********************************************************************/ + if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == FALSE) + { + temp_array2[0] = (dinfo->disknum / 10) + '0'; + temp_array2[1] = (dinfo->disknum % 10) + '0'; + temp_array2[2] = NULLC; + + sublist.value1 = (char far *)temp_array2; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(temp_array2); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + + display_it(DISKETTE_NUM,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + } + + *dnumwant = dinfo->disknum + 1; + + return; /*;AN000;*/ +} /*end of subroutine */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : check_bkdisk_old +/* +/* DESCRIPTIVE NAME : For old format only, check to see whether the disk +/* is a backup disk, and whether the disk is in right +/* sequence. +/* +/* FUNCTION: The routine does the following: +/* 1. Open the file BACKUPID.@@@. If the file is not there, +/* the disk is not a backup disk. +/* 3. Check the sequence number of the disk to make sure +/* its in sequence. +/* 4. Fill dinfo with correct information. +/* 5. Output a message to the screen to confirm that +/* the disk is going to be restored. +/* +/* NOTES: This subroutine also take care of situation that user +/* insert a new format diskette while the RESTORE started with +/* old format diskettes. +/* +/* When the inserted disk does not contain the file BACKUP.@@@, +/* a message "source file does not contains backup files" is +/* output to the user. If the user wants to change diskette +/* and try again, next diskette will be read. +/* +/* When disk is out of sequence, a 'warning' is given to user, +/* if the user still wants to proceed the restoring by doing +/* nothing but hit a key, the same diskette will be read again. +/* In case of expanded file, another check for dnum of the expand +/* file will guarantee the disk in sequence. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void check_bkdisk_old(dheadold, dinfo, srcd, dnumwant) /* wrw! */ + struct disk_header_old *dheadold; + struct disk_info *dinfo; + BYTE srcd; + unsigned int *dnumwant; +{ + WORD retcode; + WORD action; + + int dnumok = FALSE; + unsigned file_pointer; + char fname_to_be_opened[13]; + int numread; + int dyear; + int dmonth; + int dday; + char temp_array1[4]; + char temp_array2[4]; + BYTE c; + + /********************************************************************/ + /* open and read backupid.@@@. Store information in backupid.@@@ */ + /* into dinfo */ + /********************************************************************/ + + for (;;) + { + fname_to_be_opened[0] = srcd; + fname_to_be_opened[1] = ':'; + fname_to_be_opened[2] = NULLC; + strcat(fname_to_be_opened,BACKUPID); + retcode = + DOSOPEN( + (char far *)&fname_to_be_opened[0],(unsigned far *)&file_pointer, + (unsigned far *)&action,(DWORD)0,0,0x01,0x00c0,(DWORD)0 + ); + + if (retcode != NOERROR) + { display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(NOBACKUPFILE); + } + + /*read BKIDLENG (7) bytes from the file and store into dheadold*/ + retcode = DOSREAD( file_pointer, + (char far *)dheadold, + BKIDLENG, + (unsigned far *)&numread); + /*if return code of read indicate less than 11 bytes been read*/ + if (retcode != 0 || numread < BKIDLENG) { + /*unexperror "source file does not contains backup files"*/ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + unexperror(NOBACKUPFILE); + } /*endif */ + dinfo->disknum = dheadold->disknum[0] + dheadold->disknum[1] * 10; + dyear = dheadold->diskyear[0] + dheadold->diskyear[1]*256; + dinfo->dflag = dheadold->diskflag; + + /*close the file*/ + DOSCLOSE(file_pointer); + + /********************************************************************/ + /* check disk sequence number */ + /********************************************************************/ + if (dnumok == TRUE) { + if ((WORD)dinfo->disknum != *dnumwant) { + set_reset_test_flag(&control_flag2,OUTOF_SEQ,SET); + } + dnumok = FALSE; + } + else { + if ((WORD)dinfo->disknum != *dnumwant) { + /*When disk is out of sequence, a 'warning' is given to user, + if the user still wants to proceed the restoring by doing + nothing but hit a key, the same diskette will be read again.*/ + display_it(DISK_OUT_OF_SEQUENCE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + dnumok = TRUE; + continue; + } /*endif*/ + } /*endif*/ + + /*at this point, the diskette has passed all the checking, and + should be a ok diskette. break out of the loop.*/ + break; + } /*end of loop*/ + + /********************************************************************/ + /* output a confirm msg "restoring files from drive d:" */ + /********************************************************************/ + temp_array1[0] = srcd; + temp_array1[1] = NULLC; + sublist.value1 = (char far *)temp_array1; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + display_it(RESTORE_FILE_FROM_DRIVE,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /********************************************************************/ + /* if the source disk is removable, output msg "diskette xx" */ + /********************************************************************/ + if (set_reset_test_flag(&control_flag2,SRC_HDISK,TEST) == FALSE) + { + temp_array2[0] = (dinfo->disknum / 10) + '0'; + temp_array2[1] = (dinfo->disknum % 10) + '0'; + temp_array2[2] = NULLC; + + sublist.value1 = (char far *)temp_array2; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(temp_array2); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + display_it(DISKETTE_NUM,STND_OUT_DEV,1,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + } + + *dnumwant = dinfo->disknum + 1; + return; /*;AN000;*/ +} /*end of subroutine */ + + \ 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 @@ + +/*---------------------------- +/* SOURCE FILE NAME: rtfile.c +/*---------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "stdio.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern BYTE filename[12]; +extern BYTE far *buf_pointer; +extern char far *control_buf_pointer; +extern unsigned int done_searching; /* !wrw */ +extern unsigned int numentry; + +unsigned dest_file_handle; +extern unsigned src_file_handle; +extern unsigned control_file_handle; /* !wrw */ +BYTE dest_file_spec[MAXFSPEC+3]; +extern struct FileFindBuf filefindbuf; +extern BYTE src_fname[MAXFNAME]; +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ + +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* SUBROUTINE NAME : restore_a_file */ +/* */ +/* DESCRIPTIVE NAME : restore a file found onto the destination disk. */ +/* */ +/* FUNCTION: This subroutine call open_dest_file to open the destination */ +/* file under the proper path. If the path is not found, build */ +/* the path. */ +/* It then enter a loop to do reading the source disk and */ +/* writing the destination disk until end of file. If the file */ +/* is so large that it is backed up on more than one disk, */ +/* the user is prompt to insert next diskette. In this */ +/* situation, the disk is checked for correct sequence number, */ +/* and then searched for the file to be continue restoring. */ +/* after the file is completely restored, the time, date, and */ +/* attributes of the restored file is set to be the same as */ +/* its original value. */ +/* */ +/********************** END OF SPECIFICATIONS *******************************/ + +void restore_a_file(finfo,dinfo,bufsize,control_bufsize, /* wrw! */ + fheadnew,dheadold,dheadnew, + srcd,destd,inpath,infname,infspec,dnumwant,dirhandle) + + struct file_info *finfo; + struct disk_info *dinfo; + unsigned long bufsize; + unsigned int *control_bufsize; + struct file_header_new far *fheadnew; + struct disk_header_old *dheadold; + struct disk_header_new far *dheadnew; + BYTE srcd; + BYTE destd; + unsigned char *inpath; + unsigned char *infname; + unsigned char *infspec; + unsigned int *dnumwant; + unsigned int *dirhandle; +{ + BYTE c; + BYTE temp_array1[4]; + BYTE temp_array2[4]; + BYTE temp_fname[MAXFSPEC]; + WORD action; + WORD first_time=TRUE; + + /*declaration for dosfindfirst */ + WORD temp_dirhandle; + WORD next_dirhandle; + unsigned attribute = NOTV; /* */ + unsigned search_cnt = 1; /* # of entries to find */ + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + /*end decleration for ffirst and fnext*/ + + BYTE outstring[MAXPATHF+2]; + WORD retcode; + DWORD iterate_num; + DWORD i; /* wrw! */ + WORD numread; + WORD numwrite; + DWORD int remainder; + DWORD part_size; + WORD file_seq_num = 1; /*when this routine is called, the first + part of the file already get check against the + file sequence number */ + BYTE file_tobe_opened[MAXFSPEC+2]; + WORD found = FALSE; + WORD *dirptr; + WORD *flptr; + WORD read_count; + DWORD newptr; + WORD next_file_pointer; + unsigned int dnum; + DWORD temp_offset; + + BYTE my_own_dirpath[MAXPATH]; + int x; /*;AN000;8*/ + union REGS qregs; /*;AN000;8*/ + + /*build a string of destination file specification*/ + dest_file_spec[0] = destd; + dest_file_spec[1] = ':'; + dest_file_spec[2] = NULLC; + strcat(dest_file_spec,finfo->fname); + + /*********************************************************************/ + /* Open destination file, and chdir the the path where the dest file */ + /* going to reside. If the path is not there, then create the path. */ + /* If file sharing error, exit this routine */ + /*********************************************************************/ + /*open_dest_file*/ + retcode=open_dest_file(finfo,destd); + + /*if file sharring error, exit this subroutine*/ + if (retcode == FALSE) + display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + else + { + /*setflag PARTIAL*/ + set_reset_test_flag(&control_flag,PARTIAL,SET); + + /*********************************************************************/ + /* This loop will be processed once for each part of the source file */ + /*********************************************************************/ + for ( ; ; ) + { + + /*********************************************************************/ + /* compare source file size and buf size to determine the */ + /* iteration of reading and writing */ + /*********************************************************************/ + part_size = finfo->partsize; + /*if old*/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST)==TRUE) + part_size = part_size - HEADLEN; + + iterate_num = part_size / bufsize; + /*if remain of of filesize/bufsize != 0, add 1 to iterate_num*/ + remainder = part_size % bufsize; + if (remainder > 0) + ++iterate_num; + + /*********************************************************************/ + /*loop through each of the iteration */ + /*********************************************************************/ + for (i = 1; i <= iterate_num; ++i) + { + /***************************************************************/ + /* if old format, read from the beginning of the source file */ + /***************************************************************/ + /*read source file (new and old have different pointer)*/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + { + retcode = DOSREAD( src_file_handle, + (char far *)&buf_pointer[0], + (unsigned)bufsize, + (unsigned far *)&numread); + + if (retcode != 0) + { + com_msg(retcode); + unexperror(retcode); + } + } + else + { /*new format*/ + /***************************************************************/ + /* if new format, search backup.xxx for the file to be restored*/ + /* and read it. */ + /***************************************************************/ + temp_offset = finfo->offset + bufsize * (i - 1); + retcode = + DOSCHGFILEPTR + (src_file_handle, + (DWORD) temp_offset, + (unsigned) 0, + (DWORD far *) &newptr + ); + + if (i == iterate_num) + { + part_size = part_size - bufsize * (iterate_num -1); + retcode = + DOSREAD + ( src_file_handle, + (char far *)&buf_pointer[0], + (unsigned)part_size, + (unsigned far *)&numread + ); + } + else + { + retcode = + DOSREAD + (src_file_handle, + (char far *)&buf_pointer[0], + (unsigned)bufsize, + (unsigned far *)&numread + ); + + } /*end of i == iterate_num */ + } /*end of new format */ + + /*************************************************************/ + /* write to dest file */ + /*************************************************************/ + retcode = + DOSWRITE + (dest_file_handle, + (char far *)&buf_pointer[0], + (unsigned) numread, + (unsigned far *) &numwrite + ); + + /*************************************************************/ + /*if the num of bytes read != num of bytes write */ + /* call dos_write_error to find out why */ + /*************************************************************/ + if (numread != numwrite) + dos_write_error(bufsize,destd); + } + /*end iteration loop*/ + + /*****************************************************************/ + /*if the file is system file, turn RTSYSTEM on */ + /*****************************************************************/ + if (strcmp(finfo->fname,"IBMBIO.COM")==0 || + strcmp(finfo->fname,"IBMDOS.COM")==0 || + strcmp(finfo->fname,"COMMAND.COM")==0 ) + set_reset_test_flag(&control_flag2,RTSYSTEM,SET); + + + /*****************************************************************/ + /*if the source file header indicate that this is the last disk, */ + /* that is,it is completely copied, then exit the for loop */ + /*****************************************************************/ + if (set_reset_test_flag(&finfo->fflag,LAST_PART,TEST) == TRUE) + break; /* exit the loop */ + + /*****************************************************************/ + /*The logic flow come here when the file expanded into next disk.*/ + /* if old format, close the file handle and find handle */ + /* if new format, close src file */ + /*****************************************************************/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + { /*close source file*/ + DOSCLOSE(src_file_handle); + + if (first_time == TRUE) + { temp_dirhandle = *dirhandle; + first_time = FALSE; + retcode = DOSFINDCLOSE(temp_dirhandle); + } + } + else + { + DOSCLOSE(src_file_handle); + DOSCLOSE(control_file_handle); /* !wrw */ + control_file_handle = 0xffff; /* !wrw */ + } + + /*****************************************************************/ + /* output message for user to insert another diskette */ + /* "strike any key when ready" */ + /* with response type 4 (wait for a key to be hit) */ + /*****************************************************************/ + + if (control_file_handle != 0xffff) /* !wrw */ + { /* !wrw */ + DOSCLOSE(control_file_handle); /* !wrw */ + control_file_handle = 0xffff; /* !wrw */ + } /* !wrw */ + + printf("\n"); + temp_array1[0] = (char) (*dnumwant / 10) + '0'; + temp_array1[1] = (char) (*dnumwant % 10) + '0'; + temp_array1[2] = NULLC; + temp_array2[0] = srcd; + temp_array2[1] = NULLC; + + sublist.value1 = (char far *)temp_array1; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(temp_array1); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + + sublist.value2 = (char far *)temp_array2; /*;AN000;6 */ + sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width2 = (BYTE)strlen(temp_array2); /*;AN000;6 */ + sublist.min_width2 = sublist.max_width2; /*;AN000;6 */ + + display_it(INSERT_SOURCE_DISK,STND_ERR_DEV,2,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /* If single drive system, eliminates double prompting */ + /* for user to "Insert diskette for drive %1" */ + qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ + qregs.h.bl = srcd; /*;AN000;8*/ + intdos(&qregs,&qregs); /*;AN000;8*/ + + /**************************************************/ + /**************************************************/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + check_bkdisk_old(dheadold,dinfo,srcd,dnumwant); + else + check_bkdisk_new(dheadnew,dinfo,srcd,dnumwant,control_bufsize); + + /*at this point a real backup diskette which is in correct sequence + number has been found. In the case of new format, the file + CONTROL.xxx is opened.*/ + + /*****************************************************************/ + /*increament file sequence number */ + /*****************************************************************/ + file_seq_num = file_seq_num + 1; + + /*****************************************************************/ + /* search the new disk for next part of the file */ + /*****************************************************************/ + if (set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + { /**************************************************************/ + /* if old format, */ + /*DosFindFirst:find the first file on the diskette (non-vol id*/ + /*entry) */ + /**************************************************************/ + search_string[0] = srcd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, src_fname); + + next_dirhandle = 0xffff; /* directory handle */ + + retcode = /* Find the 1st filename that */ + DOSFINDFIRST( /* matches specified file spec*/ + (char far * ) search_string, /* File path name */ + (unsigned far * ) &next_dirhandle, /* Directory search */ + attribute, /* Search attribute */ + (struct FileFindBuf far *) &filefindbuf, + buf_len, /* Result buffer length */ + (unsigned far * ) &search_cnt, /* Number of entries to find*/ + (DWORD) 0 + ); + + if (retcode != 0) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + + + /*if the directory found is a subdirectory, find next one*/ + while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR) + { + search_cnt = 1; + retcode = DOSFINDNEXT(next_dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt); + + if (retcode != 0) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + + } /*end while */ + + retcode = DOSFINDCLOSE(next_dirhandle); + + /*****************************************************************/ + /* check_flheader_old: open and read file header, check dnum */ + /* of the file, and fill fheadold and finfo with correct info*/ + /*****************************************************************/ + strcpy(temp_fname,filefindbuf.file_name); + retcode = + check_flheader_old + ( finfo, temp_fname, + filefindbuf.write_date, filefindbuf.write_time, + filefindbuf.attributes, filefindbuf.file_size, + file_seq_num, srcd, destd, infspec, inpath, dnumwant + ); + + if (retcode != 0) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + + /*****************************************************************/ + /* check file sequence number. */ + /*****************************************************************/ + if (finfo->dnum != file_seq_num) + { display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(FILESEQERROR); + } + + } + else + { /*new format*/ + /**********************************************/ + /* Find the file on the CONTROL.xxx first */ + /**********************************************/ + + /* findfirst_new on the new diskette using the filename.??? */ + retcode = + findfirst_new + ( finfo, &found, &done_searching, + finfo->path, finfo->fname, (WORD far **) &dirptr, /* wrw! */ + (WORD far **) &flptr, &numentry, my_own_dirpath + ); /* wrw! */ + + while (retcode != 0 ) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(CREATIONERROR); + } + + if (finfo->dnum != file_seq_num) + { display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(FILESEQERROR); + } + + /**************************************************************/ + /* open file backup.xxx */ + /**************************************************************/ + /*the current disk is one less than the disk num wanted*/ + dnum = *dnumwant -1; + /*make the file name to be opened*/ + file_tobe_opened[0] = srcd; + file_tobe_opened[1] = ':'; + file_tobe_opened[2] = NULLC; + strcat(file_tobe_opened,"BACKUP."); + file_tobe_opened[9] = (char)((dnum / 100) + '0'); + dnum = dnum % 100; + file_tobe_opened[10] = (char)((dnum / 10) + '0'); + dnum = dnum % 10; + file_tobe_opened[11] = (char)(dnum + '0'); + file_tobe_opened[12] = NULLC; + + retcode = + DOSOPEN + ( (char far *)&file_tobe_opened[0], + (unsigned far *)&src_file_handle, + (unsigned far *)&action, + (DWORD)0, /*file size*/ + 0, /*file attribute*/ + 0x01, /*if file exist, open it*/ + /*if file not exist, fail it*/ + 0x00c0, /*deny write, read only*/ + (DWORD)0 + ); /*reserved*/ + + if (retcode != 0) + { display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + + } + /*end of if new format*/ + + /*assume the file to be continue definatly will be found on the + second diskette because the dnum of the file already gets checked + in check_bkdisk_old or check_bkdisk_new*/ + + /*set flag to be SPLITFILE*/ + set_reset_test_flag(&control_flag,SPLITFILE,SET); + + /*******************************************/ + /* Display name of file is to be restored */ + /*******************************************/ + /*outstring = inpath\infspec*/ + strcpy(outstring,finfo->path); + if (strlen(finfo->path) != 1 ) + strcat(outstring,"\\"); + + strcat(outstring,finfo->fname); + x = strlen(outstring); + outstring[x] = CR; /*;AN000;6*/ + outstring[x+1] = LF; /*;AN000;6*/ + outstring[x+2] = NUL; /*;AN000;6*/ + qregs.x.ax = 0x4000; /*;AN000;6*/ + qregs.x.bx = 0x0001; /*;AN000;6*/ + qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/ + qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/ + intdos(&qregs,&qregs); /*;AN000;6*/ + + /*loop back to do the read source and write dest until finfo->fflag + indicate that this is the last part of file*/ + } /*end of for loop*/ + + /************************************************************************/ + /*set_attributes_and_close: set the attributes and last write date/time */ + /*of the file just restore to be like those of the backup file */ + /************************************************************************/ + set_attributes_and_close(finfo,destd); + + /************************************************************************/ + /* If old format and the file split, then find next matching file */ + /************************************************************************/ + if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE && + set_reset_test_flag(&control_flag,OLDNEW,TEST) == TRUE) + { + /*search string used for DisFindFirst = srcd:infname.**/ + /*DosFindFirst:find the first file on the diskette (non-vol id entry) + using the search string*/ + search_string[0] = srcd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, infname); + strcat(search_string, ".*"); + + temp_dirhandle = 0xffff; + retcode = /* Find the 1st filename that */ + DOSFINDFIRST( /* matches specified file spec*/ + ( char far * ) search_string, /* File path name */ + ( unsigned far * ) &temp_dirhandle, /* Directory search handle*/ + (unsigned) NOTV, /* Search attribute */ + (struct FileFindBuf far *) &filefindbuf, + buf_len, /* Result buffer length */ + ( unsigned far * ) &search_cnt, /* Number of entries to find */ + ( DWORD) 0 + ); + + /*if not found return*/ + if (retcode != 0) + temp_dirhandle = 0xffff; + else + { + + /*if the directory found is a subdirectory, find next one*/ + while((retcode = filefindbuf.attributes & SUBDIR) == SUBDIR) + { + search_cnt = 1; + retcode = DOSFINDNEXT(temp_dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt); + if (retcode != 0) + temp_dirhandle = 0xffff; + } /*end while */ + + if(strcmp(filefindbuf.file_name,BACKUPID)==0 || + strcmp(filefindbuf.file_name,src_fname)==0 ) + { + retcode =DOSFINDNEXT(temp_dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt); + + if (retcode != 0) + temp_dirhandle = 0xffff; + + else + { + if(strcmp(filefindbuf.file_name,BACKUPID)==0 || + strcmp(filefindbuf.file_name,src_fname)==0 ) + { + retcode =DOSFINDNEXT(temp_dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt); + + if (retcode != 0) + temp_dirhandle = 0xffff; + } + + } /*end of the rc is 0 */ + } /*end of if strcomp is sucessful*/ + + } + *dirhandle = temp_dirhandle; + + } /*end of if the file was splitted */ + + + /****************************************************************/ + /*set FOUNDFILE flag */ + /****************************************************************/ + set_reset_test_flag(&control_flag,FOUND,SET); + } /* end of if open destination file get file sharing error */ + +} /*end of restore_a_file subroutine*/ + \ 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 @@ + +/*------------------------------ +/* SOURCE FILE NAME: rtfile1.c +/*------------------------------ +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "direct.h" +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +char ext_attrib_buff[4086]; /*;AN000;3*/ + +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern unsigned dest_file_handle; +extern unsigned src_file_handle; +extern BYTE far *buf_pointer; +extern BYTE dest_file_spec[MAXFSPEC+3]; +extern struct FileFindBuf filefindbuf; + +extern struct file_header_new far *fheadnew; /*;AN000;3 */ + +/* *************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : open_dest_file +/* +/* DESCRIPTIVE NAME : open the destination file and build a path to it +/* if necessary. +/* +/* FUNCTION: Try to change the current directory of the destination disk +/* to be the one the file is to be restored. If not able to +/* do it because the directory does not exist, call +/* build_path_create_file subroutine to build path, +/* create the destination file and return a handle on it. +/* If file can not be created, find out whether it is caused +/* by file sharing error, or caused by disk full. +/* +/* +/********************** END OF SPECIFICATIONS ******************************/ +WORD open_dest_file(finfo,destd) +struct file_info *finfo; +BYTE destd; +{ + BYTE fname[MAXFSPEC+2]; + BYTE path_to_be_chdir[MAXPATH+2]; + WORD rc; + + WORD retcode; + + /*declaration for dosfindfirst */ + unsigned dirhandle = 0xffff; + unsigned attribute = NOTV; + unsigned search_cnt = 1; + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + /*end decleration for ffirst and fnext*/ + + /************************************************************************* + /*if current directory is not where the file wants to be restored and + /* (the file is not to be restored in root or the current directory is + /* not root). This is to avoid building path if the the current + /* directory already got updated to be the right directory (in dorestore), + /* or both current directory and the requested directory are root + /* directory + /**************************************************************************/ + + if (strcmp(finfo->path,finfo->curdir)!=0) + { + /* Change to finfo->path. If error, create the directory */ + strcpy(finfo->curdir,finfo->path); + path_to_be_chdir[0] = destd; + path_to_be_chdir[1] = ':'; + path_to_be_chdir[2] = NULLC; + strcat(path_to_be_chdir,finfo->curdir); + if(chdir(path_to_be_chdir)!=0) + { + build_path_create_file(finfo->path,destd,finfo->fflag,finfo->ea_offset); /*;AC000;3*/ + if (dest_file_handle != NULLC) + return(TRUE); + } + } + + /* Current directory is the one where files are to be restored to*/ + + retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/ + + if (retcode == NOERROR) + return(TRUE); + + /*----------------------------------------*/ + /*- There was an error creating target -*/ + /*- file. Reset attribute and try again -*/ + /*----------------------------------------*/ + retcode = + DOSSETFILEMODE + ( + (char far *)&dest_file_spec[0], + (unsigned) 0x00, + (DWORD) 0 + ); + + retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/ + + if (retcode == NOERROR) + return(TRUE); + else + return(FALSE); /*;AC000;p1102*/ + + +} /*end of subroutine*/ +/* *************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : build_path_create_file +/* +/* DESCRIPTIVE NAME : Build path for the destination file, and create +/* the file in the current direactory. +/* +/* FUNCTION: Rebuild the path of the file about to be restored by +/* recreating all subdirectories needed to complete the path. +/* Then chdir to the one which is to reside and create the +/* file. +/* +/********************* END OF SPECIFICATIONS ********************************/ +void build_path_create_file(in_path,destd,fflag,ea_offset) +BYTE *in_path; +BYTE destd; +BYTE fflag; /*;AN000;3*/ +DWORD ea_offset; /*;AN000;3*/ +{ + WORD array[20]; + int i,j; + BYTE path[MAXPATH+2]; + WORD retcode; + BYTE cant_make = FFALSE; /*;AN000;10*/ + + path[0] = destd; + path[1] = ':'; + path[2] = NULLC; + strcat(path,in_path); + i = strlen(path); + j = -1; + + /* Create the path for destination file */ + /*Loop until mkdir(path) is successful*/ + + while (mkdir(path) && !cant_make) /*;AC000;10*/ + { + /*scan path backward until find a \ */ + for (; path[i] != '\\'; i--) + if (i < 0) + { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/ + cant_make = TTRUE; /*;AN000;10*/ + break; /*;AN000;10*/ + } + + /*obtain the last subdir from the path */ + path[i] = NULLC; + j++; + /*save the location of the last \ in an array of \ locations */ + array[j] = i; + } + + /*loop through the array of \ locations*/ + i = j; + for (;;) + { + if (i >= 0 && !cant_make) /*;AC000;10*/ + { + path[array[i]] = '\\'; + if (mkdir(path)) + { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/ + cant_make = TTRUE; /*;AN000;10*/ + break; /*;AN000;10*/ + } + --i; + } + else + break; + } /*end for loop */ + + chdir(path); /*;AN000;3*/ + retcode = create_the_file(fflag,ea_offset); /*;AN000;3*/ + + return; /* wrw! */ + +} + +/********************************************************/ +/* +/* SUBROUTINE NAME: create_the_file +/* +/* DESCRIPTIVE NAME : Create the target file. +/* Use DOS 4.00 Extended Create Function 6C00h +/* Remember to handle Extended Attributes! +/* +/********************************************************/ +#define EXTENDEDOPEN 0x6c00 /*;AN000;3*/ +WORD create_the_file(fflag,ea_offset) /*;AN000;3*/ +BYTE fflag; /*;AN000;3*/ +DWORD ea_offset; /*;AN000;3*/ +{ /*;AN000;3*/ + WORD action; /*;AN000;3*/ + WORD retcode; /*;AN000;3*/ + union REGS reg; /*;AN000;3*/ + struct parm_list ea_parmlist; /*;AN000;3 Parameter list for extended open*/ + + if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/ + read_the_extended_attributes(ea_offset); /*;AN000;3*/ + + ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/ + ea_parmlist.num_additional = 0; /*;AN000;3*/ + + retcode = NOERROR; /*;AN000;3*/ + reg.x.ax = EXTENDEDOPEN; /* Function */ /*;AN000;3*/ + reg.x.bx = 0x2011; /* Mode */ /*;AN000;3*/ + reg.x.bx = 0x0081; /* Mode */ /*;AN000;3*/ + reg.x.cx = 0; /* Attribute */ /*;AN000;3*/ + reg.x.dx = 0x112; /* Flag */ /*;AN000;3*/ + + reg.x.si = (WORD)&dest_file_spec[0]; /* Filename */ /*;AN000;3*/ + + if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/ + reg.x.di = (WORD)&ea_parmlist; /* Parmlist */ /*;AN000;3*/ + else + reg.x.di = 0xffff; /* No parmlist */ /*;AN000;3*/ + + intdos(®,®); /*;AN000;3*/ + if (reg.x.cflag & CARRY) /* If there was an error /*;AN000;3*/ + retcode = reg.x.ax; /* then set return code /*;AN000;3*/ + + dest_file_handle = reg.x.ax; /*;AN000;3*/ + + return(retcode); /*;AN000;3*/ +} /*;AN000;3*/ +/********************************************************/ +/* +/* SUBROUTINE NAME: read_the_extended_attributes +/* +/* DESCRIPTIVE NAME : reads in the extended attributes +/* +/********************************************************/ +void read_the_extended_attributes(ea_offset) /*;AN000;3*/ +DWORD ea_offset; /*;AN000;3*/ +{ /*;AN000;3*/ + WORD ea_len; /*;AN000;3*/ + DWORD file_position; /*;AN000;3*/ + WORD read_count; /*;AN000;3*/ + WORD retcode; /*;AN000;3*/ + /*******************************/ + /* Seek to Extended Attributes */ + retcode = /*;AN000;3*/ + DOSCHGFILEPTR /*;AN000;3*/ + ( /*;AN000;3*/ + src_file_handle, /* Handle */ /*;AN000;3*/ + ea_offset, /* New location */ /*;AN000;3*/ + (BYTE)0, /* MOVE METHOD */ /*;AN000;3*/ + (DWORD far *)&file_position /*;AN000;3*/ + ); /*;AN000;3*/ + + /*************************************/ + /* Read in Extended Attribute length */ + retcode = /*;AN000;3*/ + DOSREAD /*;AN000;3*/ + ( /*;AN000;3*/ + src_file_handle, /*;AN000;3*/ + (char far *)&ea_len, /*;AN000;3*/ + (unsigned short)2, /*;AN000;3*/ + (unsigned far *)&read_count /*;AN000;3*/ + ); /*;AN000;3*/ + + /***********************************/ + /* Read in the Extended Attributes */ + retcode = /*;AN000;3*/ + DOSREAD /*;AN000;3*/ + ( /*;AN000;3*/ + src_file_handle, /*;AN000;3*/ + (char far *)&ext_attrib_buff[0], /*;AN000;3*/ + (unsigned short)ea_len, /*;AN000;3*/ + (unsigned far *)&read_count /*;AN000;3*/ + ); /*;AN000;3*/ + + return; /*;AN000;3*/ +} /*;AN000;3*/ + +/* *************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : set_attributes_and_close +/* +/* DESCRIPTIVE NAME : Set the file attributes and close the file +/* +/* FUNCTION: Set the attributes and last write date/time of the file just +/* restored to be like those of the backup file. +/* +/********************* END OF SPECIFICATIONS ********************************/ +int set_attributes_and_close(finfo,destd) +struct file_info *finfo; +BYTE destd; +{ + struct FileStatus fileinfo_buf; + WORD destdnum; + WORD buflen = sizeof(struct FileStatus); + + WORD retcode; + + destdnum = destd - 'A' + 1; + + /************************************************************************/ + /* call DosQFileInfo: Request date and time of the dest file */ + /************************************************************************/ + retcode = DOSQFILEINFO ( + (unsigned)dest_file_handle, /* File handle */ + (unsigned)1, /* File info data required */ + (char far *)&fileinfo_buf, /* File info buffer */ + (unsigned)buflen); /* File info buffer size */ + + /*if fail, unexperror "file creation error"*/ + if (retcode != NOERROR) + { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(retcode); + } + /************************************************************************/ + /* call DosSetFileInfo: Set date and time in dest file as the same date */ + /* and time in finfo */ + /************************************************************************/ + fileinfo_buf.write_date = finfo->fdate; + fileinfo_buf.write_time = finfo->ftime; + retcode = DOSSETFILEINFO ( + (unsigned)dest_file_handle, /* File handle */ + (unsigned)1, /* File info data required */ + (char far *)&fileinfo_buf, /* File info buffer */ + (unsigned)buflen); /* File info buffer size */ + + /*if fail, unexperror "file creation error"*/ + if (retcode != NOERROR) + { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(retcode); + } + + /******************************************************************/ + /*close dest file */ + /******************************************************************/ + DOSCLOSE(dest_file_handle); + + /******************************************************************/ + /*DosSetFileMode to set file attrib of d:infspec(from input line) */ + /*to be the attrib in finfo structure */ + /******************************************************************/ + finfo->attrib = finfo->attrib & 0xffdf; + retcode = + DOSSETFILEMODE + ( + (char far *)dest_file_spec, + (unsigned) finfo->attrib, (DWORD) 0 + ); + + + /******************************************************************/ + /*reset flag PARTIAL */ + /******************************************************************/ + set_reset_test_flag(&control_flag,PARTIAL,RESET); + +return(0); /* wrw! */ + +} /*end of subroutine*/ + +/* *************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : dos_write_error +/* +/* DESCRIPTIVE NAME : Determine the cause of the error during +/* DOS write, and output message according to it. +/* +/* FUNCTION: If error returned from get free space of the disk +/* is caused by disk full, a message "target disk is +/* full" is output to the user. +/* Otherwise, the error is caused by other reason, and +/* a message "file creation error" is output to the user. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +int dos_write_error(buf_size,destd) +DWORD buf_size; +BYTE destd; +{ + DWORD free_space; + WORD drive_num; + struct fsinfo *fsinfo_buf; + + WORD retcode; + + /******************************************************************/ + /*DosQFsinfo: get free space in the hard disk */ + /******************************************************************/ + drive_num = destd - 'A' + 1; + retcode = DOSQFSINFO + ((unsigned)drive_num, /* Drive number - 0=default, 1=A, etc */ + (unsigned)1, /* File system info required */ + (char far *)fsinfo_buf, /* File system info buffer */ + (unsigned)FSINFO_BYTES /* File system info buffer size */ + ); + + + free_space = fsinfo_buf->sectors_per_alloc_unit * + fsinfo_buf->available_alloc_unit * + fsinfo_buf->bytes_per_sector; + + + /******************************************************************/ + /*if the free space left is less than buffer size for file read */ + /* and write, output msg "target is full", and "file creation */ + /* error", otherwise, output "file creation error". */ + /******************************************************************/ + if ( free_space < buf_size) + { display_it(TARGET_IS_FULL,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + /*close dest file*/ + DOSCLOSE(dest_file_handle); + + if ((retcode = DOSDELETE((char far *)&dest_file_spec[0], + (DWORD)0)) != 0) + { + /*set file mode to 0*/ + retcode = + DOSSETFILEMODE + ( + (char far *)&dest_file_spec[0], + (unsigned) 0x00, + (DWORD)0 + ); + + /* delete the partially completed destination file*/ + retcode = DOSDELETE((char far *) dest_file_spec,(DWORD)0); + } + + display_it(LAST_FILE_NOT_RESTORED,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(TARGETFULL); + } + else + { display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(CREATIONERROR); + } + /*endif*/ + + return(0); /* wrw! */ + +}/*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 @@ + +/*------------------------------ +/* SOURCE FILE NAME: RTNEW.C +/*------------------------------ +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +extern BYTE control_flag; +extern BYTE control_flag2; +extern unsigned far *control_buf_pointer; +extern unsigned control_file_handle; /* !wrw */ +extern unsigned src_file_handle; +unsigned int done_searching; /* !wrw */ +unsigned int numentry; +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : search_src_disk_new +/* +/* DESCRIPTIVE NAME : For new format only, search the entire disk for +/* matching files. +/* +/* FUNCTION: Call subroutine findfirst_new and fnext_new to find all the +/* files which match the filename and file extension specified +/* in the command line. +/* +/* Whenever there is a file found, subroutine filematch +/* is called to match the file path, and file extension. +/* If file path and file extension match the specification, +/* subroutine switchmatch is called to match the file +/* attributes, file modes, time, and date, then file sequence +/* is checked. +/* +/* If the file matches all the specification, subroutine +/* restore_a_file is called to actually restore the file. +/* +/* +/********************* END OF SPECIFICATIONS ********************************/ +void search_src_disk_new(dinfo,finfo,dheadold,dheadnew,fheadnew, /* wrw! */ + srcd,destd,dnumwant,buf_size, + inpath,infname,infspec,control_buf_size,td) + + struct disk_info *dinfo; + struct file_info *finfo; + struct disk_header_new far *dheadnew; + struct file_header_new far *fheadnew; + struct disk_header_old *dheadold; + BYTE srcd; + BYTE destd; + unsigned int *dnumwant; /*num of next disk*/ + unsigned long buf_size; + unsigned *control_buf_size; + unsigned char *inpath; + unsigned char *infname; + unsigned char *infspec; + struct timedate *td; + +{ + BYTE outstring[MAXPATH+MAXFSPEC]; + WORD file_seq_num = 1; + WORD first_file_on_diskette = TRUE; + BYTE file_tobe_opened[MAXFSPEC+2]; + WORD dnum; + WORD found = FALSE; + WORD far *dirptr; + WORD far *flptr; + WORD retcode; + WORD action; + BYTE dir_path[MAXPATH]; + unsigned int my_own_little_dirhandle = 0; /* !wrw */ + union REGS qregs; /*;AN000;8*/ + int x; /*;AN000;8*/ + + done_searching = FALSE; /* !wrw */ + + /***********************************************************************/ + /*search the file control.xxx and try to find the file with match file */ + /*name and file path */ + /***********************************************************************/ + + retcode = findfirst_new(finfo,&found,&done_searching,inpath, + infspec,&dirptr,&flptr,&numentry,dir_path); + + if (retcode != TRUE) + return; + + /***********************************************************************/ + /*open file backup.xxx */ + /***********************************************************************/ + /*the current disk is one less than the disk num wanted*/ + dnum = *dnumwant -1; + /*make the file name to be opened*/ + file_tobe_opened[0] = srcd; + file_tobe_opened[1] = ':'; + file_tobe_opened[2] = NULLC; + strcat(file_tobe_opened,"BACKUP."); + file_tobe_opened[9] = (char)((dnum / 100) + '0'); + dnum = dnum % 100; + file_tobe_opened[10] = (char)((dnum / 10) + '0'); + dnum = dnum % 10; + file_tobe_opened[11] = (char)(dnum + '0'); + file_tobe_opened[12] = NULLC; + + retcode = + DOSOPEN + ((char far *)&file_tobe_opened[0], + (unsigned far *)&src_file_handle, + (unsigned far *)&action, + (DWORD)0, + 0, + 0x01, + 0x00c0, + (DWORD)0 + ); + + + if (retcode != NOERROR) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + + /***********************************************************************/ + /*start loop to find next until no more file found */ + /***********************************************************************/ + do + { + /******************************************/ + /* if it is system file, find next one */ + /******************************************/ + if + ( + (strcmp(finfo->fname,"IBMBIO.COM")==0 || + strcmp(finfo->fname,"IBMDOS.COM")==0 || + strcmp(finfo->fname,"CMD.EXE")==0 || + strcmp(finfo->fname,"COMMAND.COM")==0 + ) /*;AN003;*/ + && strcmp(finfo->path,"\\")==0 /*;AN003;*/ + ) + { /* Do not RESTORE the file */ + } + else + { + + /***********************************************************************/ + /*if there are any switches set in the input line, call switch match. */ + /* if switchmatch returns FALSE, then find next file */ + /***********************************************************************/ + if ((set_reset_test_flag(&control_flag,SWITCHES,TEST) == FALSE) || + (set_reset_test_flag(&control_flag,SWITCHES,TEST) == TRUE && + ((retcode = switchmatch(finfo, srcd, destd, td)) == TRUE) )) + { + + /***********************************************************************/ + /* if the diskette is out of sequence, then do not check the sequence */ + /* number of the 1st file. Otherwise, check sequence number */ + /***********************************************************************/ + if (set_reset_test_flag(&control_flag2,OUTOF_SEQ,TEST) == TRUE && + first_file_on_diskette == TRUE && finfo->dnum != file_seq_num) + { + } + else + { + if (finfo->dnum != file_seq_num) + { + display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(FILESEQERROR); + } + + /***********************************************************************/ + /* msg: output one line of outstring on the screen */ + /* to confirm that a file has been restored sucessfully */ + /***********************************************************************/ + strcpy(outstring,finfo->path); + if (strlen(finfo->path) != 1 ) + strcat(outstring,"\\"); + + strcat(outstring,finfo->fname); + x = strlen(outstring); + outstring[x] = CR; /*;AN000;6*/ + outstring[x+1] = LF; /*;AN000;6*/ + outstring[x+2] = NUL; /*;AN000;6*/ + qregs.x.ax = 0x4000; /*;AN000;6*/ + qregs.x.bx = 0x0001; /*;AN000;6*/ + qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/ + qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/ + intdos(&qregs,&qregs); /*;AN000;6*/ + + /***********************************************************************/ + /* restore the file */ + /***********************************************************************/ + restore_a_file(finfo,dinfo,buf_size,control_buf_size, + fheadnew,dheadold,dheadnew, + srcd,destd,inpath,infname,infspec,dnumwant,&my_own_little_dirhandle); /* wrw! */ + + first_file_on_diskette = FALSE; + + if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE) + { + set_reset_test_flag(&control_flag,SPLITFILE,RESET); + /*do findfirst, the file found should be the splitted file*/ + + /* retcode= findfirst_new( finfo, &found, &done_searching, inpath, */ + /* infspec, &dirptr, &flptr,&numentry,dir_path ); */ + } + + } /*end of if disk and file out of sequence*/ + + } /*end of if switch match is ok */ + + } /*end of if root directory and DOS system files */ + + /***********************************************************************/ + /* if has not search to the end of the diskette, find next file */ + /***********************************************************************/ + if (done_searching == FALSE) + { + found = FALSE; + retcode= findnext_new(finfo,&found,&done_searching,inpath,infspec, + &dirptr,&flptr,&numentry,dir_path ); + + } + else + break; + + } /* end do while loop */ + while( retcode == TRUE); + + DOSCLOSE(src_file_handle); + +return; /* !wrw */ + +} /*end of subroutine*/ + 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 @@ + +/*------------------------------ +/* SOURCE FILE NAME: RTNEW1.C +/*------------------------------ +/*  0 */ +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + + +#define LAST_DIRBLOCK 0xffffffff /* !wrw */ +BYTE got_first_fh; /* !wrw */ + +struct dir_block russ_dir_block; /* Current directory block /* !wrw */ +extern BYTE backup_level; /* Tells which DOS version made the BACKUP*/ /*;AN000;3*/ + +struct file_header_new russ_file_header;/* Current file_header /* !wrw */ +unsigned short tot_num_fh_read_in; /* Num FH read in so far /* !wrw */ +unsigned short num_fh_in_buffer; /* Num FH currently in buff /* !wrw */ +unsigned short num_fh_in_buf_processed; /* Number of FH in the buffer that have been processed /* !wrw */ +struct file_header_new far *fheadnew; /* Global pointer to FH /* !wrw */ + + +BYTE fileheader_length; /*;AN000;3 Length of a file header */ + +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern char far *control_buf_pointer; +extern unsigned control_file_handle; +extern WORD control_bufsize; /* !wrw */ + + +/*  0 */ +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : findfile_new +/* +/* DESCRIPTIVE NAME : Find a file with matching file name from +/* the file CONTROL.xxx. +/* +/* FUNCTION: For new format only, search through all directory blocks +/* and all file headers until a file header with matched file +/* path, name and extension is found. also store information +/* into fhead and finfo if file is found which match the +/* filename and file extension specified in the command line. +/* +/* NOTES: Path name for comparison has to started with \ and end with \. +/* +/********************** END OF SPECIFICATIONS *******************************/ +int findfile_new( finfo, found, done_searching, inpath, + infspec, dirptr, flptr, numentry, dir_path) + +struct file_info *finfo; +WORD *found; +unsigned int *done_searching; +BYTE *inpath; +BYTE *infspec; +WORD far **dirptr; +WORD far **flptr; +unsigned int *numentry; +BYTE *dir_path; +{ + struct dir_block far *dirblk; + char temp_path[MAXPATH]; + char temp_fname[MAXFSPEC]; + WORD i; + WORD rc; + + + dirblk = (struct dir_block far *)&russ_dir_block; /* !wrw */ + fheadnew = (struct file_header_new far *)&russ_file_header; /* !wrw */ + + /******************************************************************/ + /* search the directory block for the one that has the right path */ + /*******************************************************************/ + while ((*done_searching == FALSE) && (*found == FALSE)) + { + temp_path[0] = '\\'; + for (i = 0; i <= (MAXPATH-2); ++i) + temp_path[i+1] = dirblk->path[i]; + + temp_path[MAXPATH-1] = NULLC; + + /*****************************/ + /* While path does not match */ + /*****************************/ + + while (pathmatch(inpath,temp_path) == FALSE) + { + if (dirblk->nextdb == LAST_DIRBLOCK) /* !wrw */ + { + *found = FALSE; + *done_searching = TRUE; + break; + } + else + { + read_in_next_dirblock(); /* !wrw */ + temp_path[0] = '\\'; + for (i = 0; i <= (MAXPATH-2); ++i) + temp_path[i+1] = dirblk->path[i]; + temp_path[MAXPATH-1] = NULLC; + continue; + } + /*end of if not last dirblk*/ + + } /*end while loop, searching for the right path in directory block*/ + /*if done searching, break out of the big loop to exit*/ + + if (*done_searching == TRUE) + break; + + /***************************************************/ + /* directory block with correct path has been found*/ + /***************************************************/ + + /*get the total number of file headers in the directory block*/ + *numentry = (unsigned int)russ_dir_block.numentry; /* !wrw */ + + if (got_first_fh == FALSE) /* !wrw */ + read_in_a_fileheader(); /*#### /* !wrw */ + + /****************************************************/ + /* search all the file headers under this directory */ + /* block to find the one with right file name */ + /****************************************************/ + for (;;) + { + + if ((rc = fheadnew->flag & COMPLETE_BIT) != COMPLETE_BIT) + { + if (*numentry) + --(*numentry); + if (*numentry==0) + { + if (dirblk->nextdb == LAST_DIRBLOCK) /* !wrw */ + { + *found = FALSE; + *done_searching = TRUE; + break; /*exit FOR loop, go back to WHILE loop*/ + } + else + { + read_in_next_dirblock(); /* !wrw */ + break; /*exit FOR loop, go back to WHILE loop*/ + } + } + else + { + read_in_a_fileheader(); /* !wrw */ + continue; + } + } + + for (i = 0; i <= (MAXFSPEC-2); ++i) + temp_fname[i] = fheadnew->fname[i]; + temp_fname[MAXFSPEC-1] = NULLC; + + if (fspecmatch(infspec,temp_fname)==TRUE) + { + *found = TRUE; + break; + } + else /* This file header is not the right one*/ + { + if (*numentry) + --(*numentry); + if (*numentry == 0) + { + if (dirblk->nextdb == LAST_DIRBLOCK) + { + *found = FALSE; + *done_searching = TRUE; + break; /*exit FOR loop, go back to WHILE loop*/ + } + else + { + read_in_next_dirblock(); /* !wrw */ + break; + } /*end of if not last dir block */ + } + else /*point to the next file header and loop again*/ + read_in_a_fileheader(); /* !wrw */ + + } + + } /* end for (;;) loop to search all file headers in a directory block */ + + } /*end of while loop*/ + + + + /*******************************************************************/ + /* if a file is found, save the information in the disk header and */ + /* file header */ + /*******************************************************************/ + if (*found == TRUE) + { + /* Store information from dir blk into finfo */ + if (strcmp(dir_path,"no path from fnext") == 0) + strcpy(finfo->path,temp_path); + else + { + finfo->path[0] = '\\'; + finfo->path[1] = NULLC; + strcat(finfo->path,dir_path); + } + + /*store information from file header into finfo*/ + for (i = 0; i <= (MAXFSPEC-2); ++i) + finfo->fname[i] = fheadnew->fname[i]; + finfo->fname[MAXFSPEC-1] = NULLC; + finfo->fflag = fheadnew->flag; + finfo->dnum = fheadnew->fsequenc; + finfo->ftime = fheadnew->ftime; + finfo->fdate = fheadnew->fdate; + finfo->attrib = fheadnew->attrib; + finfo->partsize = fheadnew->partsize; + finfo->offset = fheadnew->offset; + + if ((fheadnew->flag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/ + finfo->ea_offset = fheadnew->FH_EA_offset; /*;AN000;3*/ + + if (*numentry) + --(*numentry); + + if (*numentry == 0) + { + if (dirblk->nextdb == LAST_DIRBLOCK) + *done_searching = TRUE; + else + { + read_in_next_dirblock(); /* !wrw */ + read_in_a_fileheader(); /* !wrw */ + *numentry = dirblk->numentry; + } + } + else + read_in_a_fileheader(); /* !wrw */ + + *dirptr=(WORD far *)dirblk; + *flptr=(WORD far *)fheadnew; + + return (TRUE); + } /*end of if found */ + else + return (FALSE); + + return(TRUE); /*;AN000;*/ +} /*end of subroutine */ + +/*  0 */ +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : findnext_new +/* +/* DESCRIPTIVE NAME : For new format only, continue at the point +/* findfirst_new or previous findnext_new exit, search +/* the entire file of CONTROL.xxx to find matching file +/* names. +/* +/* FUNCTION: Continue at where findfirst_new or previous findnext_new +/* stop, search the current directory blocks for the matching +/* file path, if fail to find a file, then call findfile to +/* search all directory block. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +int findnext_new(finfo, found, done_searching, in_path, + infspec, dirptr, flptr, numentry, dir_path) + +struct file_info *finfo; +WORD *found; +unsigned int *done_searching; +BYTE *in_path; +BYTE *infspec; +WORD far **dirptr; +WORD far **flptr; +unsigned int *numentry; +BYTE *dir_path; +{ + struct dir_block far *dirblk; + WORD retcode; + WORD i; + BYTE temp_fname[MAXFSPEC]; + WORD rc; + char temp_path[MAXPATH]; + + dirblk=(struct dir_block far *)*dirptr; + fheadnew=(struct file_header_new far *)*flptr; + strcpy(dir_path,"no path from fnext"); + + temp_path[0] = '\\'; + for (i = 0; i <= (MAXPATH-2); ++i) + temp_path[i+1] = dirblk->path[i]; + + temp_path[MAXPATH-1] = NULLC; + + /****************************************/ + /* Should we process this subdirectory ?*/ + /****************************************/ + if (pathmatch(in_path,temp_path) == TRUE) + { + + /*************************************************/ + /*complete the scanning current db to find a file*/ + /*************************************************/ + for (;;) + { + if ((rc = fheadnew->flag & COMPLETE_BIT) != COMPLETE_BIT) + { + if (*numentry) + --(*numentry); + + if (*numentry==0) + { + if (dirblk->nextdb == LAST_DIRBLOCK) + { + *found = FALSE; + *done_searching = TRUE; + break; + } + else + { + read_in_next_dirblock(); /* !wrw */ + break; /* !wrw */ + } + } /* !wrw */ + else /* There are more files from current dirblock. Get them */ + { /* !wrw */ + read_in_a_fileheader(); /* !wrw */ + continue; /* !wrw */ + } + } + /*endif*/ + + /* If this file header is the right one)*/ + for (i = 0; i <= (MAXFSPEC-2); ++i) + temp_fname[i] = fheadnew->fname[i]; + + temp_fname[MAXFSPEC-1] = NULLC; + + if (fspecmatch(infspec,temp_fname)==TRUE) + { + *found = TRUE; + for (i = 0; i <= (MAXPATH-2); ++i) + dir_path[i] = dirblk->path[i]; + break; + } + else /*if this file header is not the right one*/ + { + if (*numentry) + --(*numentry); + if (*numentry == 0) /* If no more files in this directory block */ + { + if (dirblk->nextdb == LAST_DIRBLOCK) /* If this is the last dirblock on current source disk */ + { + *found = FALSE; + *done_searching = TRUE; + break; + } + else + { + read_in_next_dirblock(); /* !wrw */ + break; /* !wrw */ + } /*end of if not last dir block */ /* !wrw */ + } /* !wrw */ + else /* !wrw */ + read_in_a_fileheader(); /* !wrw */ + } + } /*end loop searching all file headers in dir block */ + } /*end of if the path match inpath*/ + + else + *found = FALSE; + + + /********************************************************************/ + /* If fail to find a file in the current directory block, call */ + /* filefind_new to find next. */ + /* If already found or done searching, call findfile_new to store */ + /* information in finfo and dinfo */ + /********************************************************************/ + + *dirptr=(WORD far *)dirblk; + *flptr=(WORD far *)fheadnew; + + retcode = findfile_new(finfo,found,done_searching,in_path,infspec,dirptr, + flptr,numentry, dir_path); + + return(retcode); +} + +/*  0 */ +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : findfirst_new +/* +/* DESCRIPTIVE NAME : For new format only, search the entire file +/* of CONTROL.xxx to find matching file names. +/* +/* FUNCTION: search directory blocks one after the other to find the +/* directory block with the matching file path, then search +/* the entire directory block to find the file with matching +/* file name. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +int findfirst_new(finfo,found,done_searching,in_path,infspec,dirptr,flptr,numentry,dir_path) + +struct file_info *finfo; +WORD *found; +unsigned int *done_searching; +BYTE *in_path; +BYTE *infspec; +WORD far **dirptr; +WORD far **flptr; +unsigned int *numentry; +BYTE *dir_path; +{ + struct dir_block far *dirblk; + WORD retcode; + + strcpy(dir_path,"no path from fnext"); + dirblk = (struct dir_block far *)&russ_dir_block; /* !wrw */ + read_in_first_dirblock(); /* !wrw */ + + if (got_first_fh == FALSE) /* !wrw */ + read_in_a_fileheader(); /*### /* !wrw */ + + *found = FALSE; + *done_searching = FALSE; + *dirptr=(WORD far *)dirblk; + *flptr=(WORD far *)fheadnew; + + retcode = findfile_new(finfo,found,done_searching,in_path, + infspec,dirptr,flptr,numentry,dir_path); + + return(retcode); +} /*end of findfirst_new */ + + + + +/*  0 */ +/*********************************************************************/ +/* +/* SUBROUTINE NAME: read_in_next_dirblock +/* +/* FUNCTION: +/* Reads in a directory block +/* Figures out if it was put there by DOS 3.3 or 4.0 +/*********************************************************************/ +void read_in_next_dirblock() /* !wrw */ +{ + + WORD retcode; /* return code save area */ /* !wrw */ + WORD read_count; /* num bytes read in */ /* !wrw */ + DWORD file_pointer; /* current file pointer, returned by lseek !wrw */ + + retcode = /* !wrw */ + DOSCHGFILEPTR /* !wrw */ + ( /* !wrw */ + control_file_handle, /* Handle */ /* !wrw */ + russ_dir_block.nextdb, /* New location */ /* !wrw */ + (BYTE)0, /* MOVE METHOD */ /* !wrw */ + (DWORD far *)&file_pointer /* !wrw */ + ); /* !wrw */ + + retcode = + DOSREAD + ( /* !wrw */ + control_file_handle, /* !wrw */ + (char far *)&russ_dir_block, /* !wrw */ + (unsigned short)DIRBLKLEN, /* !wrw */ + (unsigned far *)&read_count /* !wrw */ + ); /* !wrw */ + /* !wrw */ + if (retcode != NOERROR) /* !wrw */ + { /* !wrw */ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(NOBACKUPFILE); /* !wrw */ + } + + got_first_fh = FALSE; /* !wrw */ + get_fileheader_length(); /*;AN000;3*/ + + return; /* !wrw */ +} /* !wrw */ + + +/*********************************************************************/ +/* +/* SUBROUTINE NAME: read_in_first_dirblock +/* +/* FUNCTION: +/* Reads in the first directory block +/* Figures out if it was put there by DOS 3.3 or 4.0 +/*********************************************************************/ + +void read_in_first_dirblock() /* !wrw */ +{ + +WORD retcode; /* return code save area */ /* !wrw */ +WORD read_count; /* num bytes read in */ /* !wrw */ + + /********************************************************************/ + /* READ DIRECTORY_BLOCK INTO STATIC DATA AREA */ + /********************************************************************/ + + retcode = DOSREAD( /* !wrw */ + control_file_handle, /* !wrw */ + (char far *)&russ_dir_block, /* !wrw */ + (unsigned short)DIRBLKLEN, /* !wrw */ + (unsigned far *)&read_count /* !wrw */ + ); /* !wrw */ + + if (retcode != 0) /* !wrw */ + { /* !wrw */ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(NOBACKUPFILE); /* !wrw */ + } + + got_first_fh = FALSE; /* !wrw */ + get_fileheader_length(); /*;AN000;3*/ + + return; /* end subroutine */ /* !wrw */ +} /* !wrw */ + +/**************************************************************/ +/* +/* SUBROUTINE: get_fileheader_length +/* +/* FUNCTION: Gets the length of a file header +/* Sets BACKUP_LEVEL to indicate which +/**************************************************************/ +void get_fileheader_length() +{ + WORD retcode; /*;AN000;3*/ + WORD read_count; /*;AN000;3*/ + DWORD file_position; /*;AN000;3*/ + + /* Save current file pointer */ + retcode = /*;AN000;3*/ + DOSCHGFILEPTR /*;AN000;3*/ + ( /*;AN000;3*/ + control_file_handle, /* Handle */ /*;AN000;3*/ + (DWORD)0, /* New location *//*;AN000;3*/ + (BYTE)1, /* MOVE METHOD *//*;AN000;3*/ + (DWORD far *)&file_position /*;AN000;3*/ + ); /*;AN000;3*/ + + if (retcode != 0) /*;AN000;3*/ + { /*;AN000;3*/ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(NOBACKUPFILE); /*;AN000;3*/ + } + + /* Read in file header length*/ + retcode = /*;AN000;3*/ + DOSREAD /*;AN000;3*/ + ( /*;AN000;3*/ + control_file_handle, /*;AN000;3*/ + (char far *)&fileheader_length, /*;AN000;3*/ + (unsigned short)2, /*;AN000;3*/ + (unsigned far *)&read_count /*;AN000;3*/ + ); /*;AN000;3*/ + + if (retcode != 0 || read_count != 2) /*;AN000;3*/ + { /*;AN000;3*/ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(NOBACKUPFILE); /*;AN000;3*/ + } + + /* Reset file pointer */ + retcode = /*;AN000;3*/ + DOSCHGFILEPTR /*;AN000;3*/ + ( /*;AN000;3*/ + control_file_handle, /* Handle */ /*;AN000;3*/ + file_position, /* New location *//*;AN000;3*/ + (BYTE)0, /* MOVE METHOD *//*;AN000;3*/ + (DWORD far *)&file_position /*;AN000;3*/ + ); /*;AN000;3*/ + + return; +} /* end get_fileheader_length() */ + + +/*  0 */ +/**************************************************************/ +/* +/* SUBROUTINE: read_in_a_fileheader +/* +/* FUNCTION: Reads in a file header +/* +/**************************************************************/ +void read_in_a_fileheader() /* !wrw */ +{ /* !wrw */ +WORD retcode; /* return code save area */ /* !wrw */ +WORD read_count; /* num bytes read in */ /* !wrw */ + + retcode = DOSREAD /* !wrw */ + ( /* !wrw */ + control_file_handle, /* !wrw */ + (char far *)&russ_file_header, /* !wrw */ + fileheader_length, /* !wrw */ + (unsigned far *)&read_count /* !wrw */ + ); /* !wrw */ + + if (retcode != NOERROR) /* !wrw */ + { /* !wrw */ + display_it(SOURCE_NO_BACKUP_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(NOBACKUPFILE); /* !wrw */ + } /* !wrw */ + + got_first_fh = TRUE; /* !wrw */ + fheadnew = (struct file_header_new far *)&russ_file_header; /* !wrw */ + +return; /* !wrw */ +} /* !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 @@ + +/*---------------------------- +/* SOURCE FILE NAME: RTOLD.C +/*---------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern BYTE far *buf_pointer; +extern unsigned src_file_handle; +extern struct FileFindBuf filefindbuf; +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ + +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* SUBROUTINE NAME : search_src_disk_old */ +/* */ +/* DESCRIPTIVE NAME : For old format only, search the entire disk for */ +/* matching files. */ +/* */ +/* FUNCTION: Using find first and find next to find all the files */ +/* which match the filename specified in the input */ +/* cammand line. */ +/* */ +/* Whenever there is a file found, subroutine filespecmatch */ +/* is called to match the file path, and file extension. */ +/* If file path and file extension match the specification, */ +/* subroutine switchmatch is called to match the file */ +/* attributes, file modes, time, and date, then file sequence */ +/* number is checked. */ +/* */ +/* If the file matches all the specification, subroutine */ +/* restore_a_file is called to actually restore the file. */ +/* */ +/* */ +/********************** END OF SPECIFICATIONS *******************************/ +void search_src_disk_old(dinfo,finfo,dheadold,dheadnew,fheadnew, /* wrw! */ + srcd,destd,buf_size,dnumwant, + inpath,infname,infext,infspec,td) + + struct disk_info *dinfo; + struct file_info *finfo; + struct disk_header_old *dheadold; + struct file_header_new far *fheadnew; + struct disk_header_new far *dheadnew; + BYTE srcd; + BYTE destd; + unsigned long buf_size; + unsigned int *dnumwant; + unsigned char *inpath; + unsigned char *infname; + unsigned char *infext; + unsigned char *infspec; + struct timedate *td; + +{ + BYTE outstring[MAXPATH+MAXFSPEC]; + WORD file_seq_num=1; + WORD first_file_on_diskette = TRUE; + WORD first_time_in_loop = TRUE; + WORD return_code; + DWORD partsize; + unsigned int control_bufsize; + BYTE temp_fname[MAXFNAME]; + BYTE temp_path[MAXPATH]; + WORD temp_dirhandle; + + + /*declaration for dosfindfirst */ + unsigned dirhandle = 0xffff; /* directory handle */ + unsigned search_cnt = 1; /* # of entries to find */ + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + WORD retcode; + /*end decleration for ffirst and fnext*/ + union REGS qregs; /*;AN000;8*/ + int x; /*;AN000;8*/ + +/*************************************************************************/ +/* FIND THE FIRST FILE ON SOURCE */ +/*************************************************************************/ + search_string[0] = srcd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, infname); + strcat(search_string, ".*"); + +retcode = /* Find the 1st filename that */ + DOSFINDFIRST( /* matches specified file spec*/ + ( char far * ) search_string, /* File path name */ + ( unsigned far * ) &dirhandle, /* Directory search handle */ + (unsigned) NOTV, /* Search attribute */ + (struct FileFindBuf far *) &filefindbuf, + buf_len, /* Result buffer length */ + ( unsigned far * ) &search_cnt, /* Number of entries to find */ + ( DWORD) 0 + ); + + +/*************************************************************************/ +/* IF CANNOT FIND ANY FILES ON SOURCE, RETURN */ +/*************************************************************************/ + if (retcode != 0) + return; + + + + +/*************************************************************************/ +/* start DO loop to find next until no more file found */ +/*************************************************************************/ +do +{ + /*if the directory found is a subdirectory, find next one*/ + if((retcode = filefindbuf.attributes & 0x0010) != 0x0010) + { + /* SKIP BACKUPID */ + if (strcmp(filefindbuf.file_name,BACKUPID) != 0) + { + if (first_time_in_loop == FALSE) + DOSCLOSE(src_file_handle); + else + first_time_in_loop = FALSE; + + /*************************************************************************/ + /*check_flheader_old: open and read file header, */ + /*************************************************************************/ + strcpy(temp_fname,filefindbuf.file_name); + retcode = check_flheader_old( finfo, temp_fname, + filefindbuf.write_date, filefindbuf.write_time, + filefindbuf.attributes, filefindbuf.file_size, + file_seq_num, srcd, destd, infspec, inpath, dnumwant); + + if (retcode == 0) { + + /*************************/ + /* SKIP SYSTEM FILES */ + if ((set_reset_test_flag(&control_flag2,CPPC,TEST) == FALSE) && + (strcmp(finfo->fname,"IBMBIO.COM")==0 || + strcmp(finfo->fname,"IBMDOS.COM")==0 || + strcmp(finfo->fname,"COMMAND.COM")==0 )) + {} + else { + + /*************************************************************************/ + /*if there is any switches set in the input line */ + /*switchmatch (this subroutine search the hard disk for the dest */ + /*************************************************************************/ + if ((set_reset_test_flag(&control_flag,SWITCHES,TEST) == FALSE) || + (set_reset_test_flag(&control_flag,SWITCHES,TEST) == TRUE && + ((retcode = switchmatch(finfo, srcd, destd, td)) == TRUE) )) { + + /*************************************************************************/ + /*if dnum in fheadold.disknum is not 1 and is not in sequence, error */ + /*************************************************************************/ + if (set_reset_test_flag(&control_flag2,OUTOF_SEQ,TEST) == TRUE && + first_file_on_diskette == TRUE && finfo->dnum != 1) + {} + else + { + if (finfo->dnum != 1 || finfo->dnum != file_seq_num) + { + display_it(FILE_SEQUENCE_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(FILESEQERROR); + } + /*endif*/ + /*************************************************************************/ + /* output msg to indicate which file is to be restored */ + /*************************************************************************/ + /*outstring = inpath\infspec*/ + strcpy(outstring,finfo->path); + if (strlen(finfo->path) != 1 ) + strcat(outstring,"\\"); + + strcat(outstring,finfo->fname); + x = strlen(outstring); + outstring[x] = CR; /*;AN000;6*/ + outstring[x+1] = LF; /*;AN000;6*/ + outstring[x+2] = NUL; /*;AN000;6*/ + qregs.x.ax = 0x4000; /*;AN000;6*/ + qregs.x.bx = 0x0001; /*;AN000;6*/ + qregs.x.cx = (WORD)strlen(outstring); /*;AN000;6*/ + qregs.x.dx = (unsigned int)&outstring[0]; /*;AN000;6*/ + intdos(&qregs,&qregs); /*;AN000;6*/ + + + /*************************************************************************/ + /* call restore_a_file to restore the file */ + /*************************************************************************/ + restore_a_file(finfo,dinfo,buf_size,&control_bufsize, + fheadnew,dheadold,dheadnew, + srcd,destd,inpath,infname,infspec,dnumwant,&dirhandle); + + first_file_on_diskette = FALSE; + + /*************************************************************************/ + /* if the file just restored is a split file, and last file, exit loop */ + /*************************************************************************/ + if (set_reset_test_flag(&control_flag,SPLITFILE,TEST)==TRUE) + { + set_reset_test_flag(&control_flag,SPLITFILE,RESET); + + if (dirhandle == 0xffff) + break; + else + { + retcode = 0; + continue; + } + } /*end of if file splitted*/ + + + } /*end of if disk and file out of sequence*/ + } /*end of switch match fail*/ + } /*end of PC/DOS and it is system files*/ + } /*end of if check file header is ok */ + } /*end of if file name is not BACKUPID*/ + } /*end of if the directory found is a subdirectory*/ + + search_cnt = 1; + + retcode = + DOSFINDNEXT + (dirhandle, + (struct FileFindBuf far *)&filefindbuf, + buf_len, + (unsigned far *)&search_cnt + ); + +} +while(retcode == 0); /* END MAIN DO LOOP */ + +DOSCLOSE(src_file_handle); +/*************************************************************************/ +/* if error during findnext, error exit */ +/*************************************************************************/ + if (retcode != ERROR_NO_MORE_FILES && retcode != 0) + { + com_msg(retcode); + unexperror(retcode); + } + + + if (dirhandle != 0xffff) + { + if ((retcode = DOSFINDCLOSE(dirhandle)) != 0) + { + com_msg(retcode); + unexperror(retcode); + } + } + + +return; +} /*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 @@ + +/*------------------------------- +/* SOURCE FILE NAME: RTOLD1.C +/*------------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" +#include "stdio.h" + +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern char far *buf_pointer; +extern unsigned src_file_handle; +extern struct FileFindBuf filefindbuf; +extern struct FileFindBuf dfilefindbuf; +BYTE src_fname[MAXFNAME]; +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ +extern char response_buff[5]; /*;AN000;6*/ +struct file_header_old fheadold; /*;AN000;*/ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : pathmatch +/* +/* DESCRIPTIVE NAME : Compare two paths and return TRUE or FALSE +/* according to whether they match or not. +/* +/* NOTES: Global characters * and ? are meaningless in the file path name +/* Assume both path pattern and path subject are not end with \ +/* +/* INPUT: (PARAMETERS) +/* subject - the file path to be compared. +/* pattern - the file path to be compared against. +/* +/********************** END OF SPECIFICATIONS *******************************/ +WORD pathmatch(patterns,subjects) + +BYTE *patterns; /* the string to be matched with */ +BYTE *subjects; /* the string to be matched */ +{ + BYTE *pattern; /* the working pointer to point to the pattern */ + BYTE *subject; /* the working pointer to point to the subject */ + int z; + + /*save the pointers to both strings*/ + pattern = patterns; + subject = subjects; + + /* loop until matched or unmatched is determined */ + for (;;) + { + if (*pattern == *subject) + { + if (*pattern != NULLC) /* not finish scanning yet*/ + { + pattern+=1; /* advance the pointer by 1 */ + subject+=1; /* advance the pointer by 1 */ + continue; /* continue on comparing again */ + } + else + return(TRUE); + } + else + { /* if subject is longer than pattern and SUB flag in rtswitches is on */ + if (set_reset_test_flag(&rtswitch, SUB, TEST)==TRUE) + { + if ((*pattern == NULLC && *subject == '\\') || + (patterns[0] == '\\' && patterns[1] == NULLC)) + return(TRUE); + else + return(FALSE); + } + else + return(FALSE); + } + } + return(TRUE); /*;AN000;*/ +} + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : fspecmatch +/* +/* DESCRIPTIVE NAME : Compare two file spec. and return TRUE or FALSE +/* according to whether they match or not. +/* +/* FUNCTION: This subroutine compare the file names and file extensions +/* to determine whether they are match or not. +/* TRUE is returned if they are match, otherwise, FALSE +/* is returned. +/* +/* NOTES: * and ? are acceptable in the file name and file extension. +/* +/********************** END OF SPECIFICATIONS *******************************/ +fspecmatch(patterns, subjects) +char *patterns; +char *subjects; +{ + char *pattern; + char *subject; + int z; + + pattern = patterns; + subject = subjects; + + for (;;) + { + if (*pattern == '*') + { + /*advance pointer in pattern until find '.' or nullc*/ + for (;*pattern != '.' && *pattern != NULLC; ++pattern); + if (*pattern == NULLC) + { + + /* pattern has no extension, so make sure subject doesn't either */ + /* find end or '.' in subject */ + + for (;*subject != '.' && *subject != NULLC; ++subject); + + if (*subject == NULLC || *(subject+1) == '.') + return(TRUE); + else /* subject has extension, so return FALSE */ + return(FALSE); + } + else + { + if ( *(pattern+1) == '*') + return(TRUE); + else + { + /*advance pointer in subject until find '.' or nullc*/ + for (;*subject != '.' && *subject != NULLC; ++subject); + if (*subject == NULLC ) + { + if (*(pattern+1) != NULLC) + return(FALSE); + else + return(TRUE); + } + else + { + pattern+=1; + subject+=1; + continue; + } /*end of if *subject is not NULL*/ + } /*end of if *(pattern+1) is not '*' */ + } /*end of if *pattern == NULLC */ + } + else + { + if (*pattern == *subject || *pattern == '?') + { + if (*pattern != NULLC) + { + pattern+=1; + subject+=1; + continue; + } + else + return(TRUE); + } + else + if (*pattern == '.' && *(pattern+1) == '*' && *subject == NULLC) + return(TRUE); + else + return(FALSE); + } + + } /*end of for loop*/ + +} /*end of subroutine */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : switchmatch +/* +/* DESCRIPTIVE NAME : Check the file attributes, and/or file modes +/* against the switches set in the input command +/* line. +/* +/* FUNCTION: this subroutine search the hard disk for the dest +/* file first. If dest file is found, the attributs of the +/* destination file will be used for checking. +/* +/* Check the switches set in the input command line one by +/* one, whenever a switch not match is found, FALSE is returne +/* In the case a switch is match, TRUE is not returned until al +/* switches is checked. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +WORD switchmatch(finfo, srcd, destd, td) +struct file_info *finfo; +BYTE srcd; +BYTE destd; +struct timedate *td; +{ + WORD yy; + WORD mm; + WORD dd; + WORD hh; + WORD mn; + WORD ss; + WORD action; + unsigned file_pointer; + WORD retcode; + int z; + + /*declaration for dosqfileinfo*/ + struct FileStatus fileinfo_buf; + WORD destdnum; + WORD buflen = sizeof(struct FileStatus); + unsigned attributes; + + /*declaration for dosfindfirst */ + unsigned ddirhandle = 0xffff; + unsigned attribute = NOTV; + unsigned search_cnt = 1; + unsigned buf_len = sizeof(struct FileFindBuf); + BYTE search_string[MAXPATHF+2]; + /*end decleration for ffirst and fnext*/ + + /***********************************************************************/ + /* Search hard file for the path and name of file about to be restored */ + /* and get the file information of the file on the hard disk */ + /***********************************************************************/ + search_string[0] = destd; + search_string[1] = ':'; + search_string[2] = NULLC; + strcat(search_string, finfo->path); + if (strlen(finfo->path) != 1) + strcat(search_string, "\\"); + strcat(search_string, finfo->fname); + + retcode = DOSOPEN( (char far *)&search_string[0], + (unsigned far *)&file_pointer, + (unsigned far *)&action, + (DWORD)0, /*file size*/ + 0, /*file attribute*/ + 0x01, /*if file exist, open*/ + /*if file not exist, fail*/ + 0x00c0, /*deny write, read write access*/ + (DWORD)0 ); /*reserved*/ + /***********************************************************************/ + /*if open fail (means the file does not exist on the hard disk), then */ + /* return true */ + /***********************************************************************/ + if (retcode != NOERROR) { + /*set flag CREATIT*/ + set_reset_test_flag(&control_flag,CREATIT,SET); + /*return TRUE*/ + return (TRUE); + } + /*********************************************************************/ + /* call DosQFileInfo: Request date and time of the dest file */ + /*********************************************************************/ + retcode = DOSQFILEINFO ( + (unsigned)file_pointer, /* File handle */ + (unsigned)1, /* File info data required */ + (char far *)&fileinfo_buf, /* File info buffer */ + (unsigned)buflen); /* File info buffer size */ + + + if (retcode != NOERROR) { + com_msg(retcode); + unexperror(retcode); + } + + if ((retcode = DOSQFILEMODE((char far *)&search_string[0], + (unsigned far *) &attributes, + (DWORD) 0)) !=0) { + com_msg(retcode); + unexperror(retcode); + } + + + DOSCLOSE(file_pointer); + /***********************************************************************/ + /*if NOTEXIST flag is on */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,NOTEXIST,TEST) == TRUE) { + return(FALSE); + } + + /***********************************************************************/ + /*if BEFORE or AFTER is on, convert date into integer form */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE || + set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE ) { + /*convert the input date into correct numbers.*/ + /*Both new and old format have date in the form of date returned from*/ + /*ffirst*/ + /*the input date is in the form of: yyyyyyymmmmddddd*/ + yy = (fileinfo_buf.write_date >> YRSHIFT & YRMASK) + LOYR; + mm = fileinfo_buf.write_date >> MOSHIFT & MOMASK; + dd = fileinfo_buf.write_date & DYMASK; + } + /*endif*/ + + /***********************************************************************/ + /*if BEFORE flag is on */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE) { + if ( yy > td->before_year ) { + return(FALSE); + } + + if (yy == td->before_year && mm > td->before_month) { + return(FALSE); + } + + if (yy == td->before_year && mm == td->before_month && + dd > td->before_day) { + return(FALSE); + } + } + /*endif*/ + + /***********************************************************************/ + /*if AFTER flag is on */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE) { + if (yy < td->after_year ) { + return(FALSE); + } + + if (yy == td->after_year && mm < td->after_month) { + return(FALSE); + } + + if (yy == td->after_year && mm == td->after_month && dd < td->after_day) { + return(FALSE); + } + } + /*endif*/ + + /***********************************************************************/ + /*if EARLIER or LATER is on, convert date time into integer form */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE || + set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) { + /* convert the input time into correct numbers. */ + /* Both new and old format have time in the form of date returned */ + /* from ffirst. */ + /* the input time is in the form of: hhhhhmmmmmmsssss */ + hh = fileinfo_buf.write_time >> HRSHIFT & HRMASK; + mn = fileinfo_buf.write_time >> MNSHIFT & MNMASK; + ss = fileinfo_buf.write_time & SCMASK; + } + /*endif*/ + + /***********************************************************************/ + /*if EARLIER flag is on */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE) { + if (hh > td->earlier_hour) { + return(FALSE); + } + + if (hh == td->earlier_hour && mn > td->earlier_minute) { + return(FALSE); + } + + if (hh == td->earlier_hour && mn == td->earlier_minute && + ss > td->earlier_second) { + return(FALSE); + } + } + /*endif*/ + + /***********************************************************************/ + /*if LATER flag is on */ + /***********************************************************************/ + if (set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) { + if (hh < td->later_hour) { + return(FALSE); + } + + if (hh == td->later_hour && mn < td->later_minute) { + return(FALSE); + } + + if (hh == td->later_hour && mn == td->later_minute && + ss < td->later_second) { + return(FALSE); + } + } + /*endif*/ + + /*************************************************************************/ + /* if Revised flag is on and fileinfo->attrib indicate file has not */ + /* been Revised, return FALSE */ + /*************************************************************************/ + if (set_reset_test_flag(&rtswitch,Revised,TEST) == TRUE) { + if((retcode = attributes & 0x0020) != 0x0020) { + return(FALSE); + } + } + /*endif*/ + + /***********************************************************************/ + /* if PROMPT and fileinfo->file_attrib indicate READONLY, or CHANGED*/ + /***********************************************************************/ + if ((set_reset_test_flag(&rtswitch,PROMPT,TEST) == TRUE) && + (((retcode = attributes & 0x0001) == 0x0001) || + ((retcode = attributes & 0x0020) == 0x0020) )) + { + /*call subroutine to ask whether the user really wants to restore */ + retcode = readonly_or_changed(attributes,destd,finfo->fname,finfo->path); + if (retcode == FALSE) { + return(FALSE); + } + /*endif*/ + } + /*endif*/ + + /***********************************************************************/ + /* if pass all the switch testing, return TRUE */ + /***********************************************************************/ + return(TRUE); + +} /*end of subroutine switch_match */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : check_flheader_old +/* +/* DESCRIPTIVE NAME : Check the information in the file header of +/* the file to be restored. +/* +/* FUNCTION: For old format only, Open the file to be restored, get +/* header informtion +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +int check_flheader_old + ( finfo,f_name,f_date,f_time,f_attrib,f_len, + file_seq_num,srcd,destd,infspec,inpath,dnumwant + ) + + struct file_info *finfo; + unsigned char *f_name; /* name string */ + unsigned f_date; /* file's date */ + unsigned f_time; /* file's time */ + unsigned f_attrib; /* file's attribute */ + unsigned long f_len; /* file length */ + unsigned int file_seq_num; + BYTE srcd; + BYTE destd; + BYTE *infspec; + BYTE *inpath; + unsigned int *dnumwant; +{ + WORD temp_dnumwant; + WORD numread; + WORD action; + BYTE file_to_be_opened[15]; + BYTE string_to_be_separate[79]; + BYTE path[65]; + BYTE name[9]; + BYTE ext[4]; + BYTE spec[13]; + WORD i; /*loop counter*/ + WORD retcode; + int z; + + temp_dnumwant = *dnumwant; /*to fix a bug that dosread change the + value of dnumwant */ + + + /***********************************************************************/ + /*open the file to be restored as deny write and read access */ + /***********************************************************************/ + strcpy(src_fname,f_name); + file_to_be_opened[0] = srcd; + file_to_be_opened[1] = ':'; + file_to_be_opened[2] = NULLC; + strcat(file_to_be_opened,f_name); + retcode = DOSOPEN( (char far *)&file_to_be_opened[0], + (unsigned far *)&src_file_handle, + (unsigned far *)&action, + (DWORD)0, /*file size*/ + 0, /*file attribute*/ + 0x01, /*if file exist, open it*/ + /*if file not exist, fail it*/ + 0x00c0, /*deny write, read only*/ + (DWORD)0 ); /*reserved*/ + + /*if open fail*/ + if (retcode != 0) { + /****not able to restore the file****/ + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + /*endif*/ + + /***********************************************************************/ + /*read 128 bytes header information from the file into fheadold */ + /***********************************************************************/ + retcode = DOSREAD( src_file_handle, + (char far *)&fheadold, + HEADLEN, + (unsigned far *)&numread); + /*if read fail*/ + if (retcode != 0 ) + { + display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + unexperror(retcode); + } + /*end of if read fail */ + + /*if the number of read is less than HEADLEN, return FALSE */ + if (numread != HEADLEN) + return(FALSE); + + /* save disk number */ + finfo->dnum = fheadold.disknum[1]* 10 + fheadold.disknum[0]; + + if (fheadold.wherefrom[0] != '\\') + return(FALSE); + strcpy(string_to_be_separate,fheadold.wherefrom); + separate(string_to_be_separate,path,name,ext,spec); + + /***********************************************************************/ + /* match the path and file spec. */ + /***********************************************************************/ + if + ( pathmatch(inpath,path) == FALSE || + fspecmatch(infspec,spec) == FALSE + ) + { + *dnumwant = temp_dnumwant; + return(FALSE); + } + + /***********************************************************************/ + /*Store some information from filefindbuf into finfo */ + /***********************************************************************/ + finfo->ftime = f_time; + finfo->fdate = f_date; + finfo->attrib = f_attrib; + finfo->partsize = f_len; + + /***********************************************************************/ + /*Store filename and path information from fheadold into finfo */ + /***********************************************************************/ + strcpy(finfo->fname,spec); + strcpy(finfo->path,path); + + /***********************************************************************/ + /* store some other information from fheadold to finfo */ + /***********************************************************************/ + if (fheadold.headflg == 0xff) + finfo->fflag= LAST_PART; + else + finfo->fflag= 0; + + *dnumwant = temp_dnumwant; + return(TRUE); + + /*return nothing*/ + +} /*end of subroutine*/ + + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : readonly_or_changed +/* +/* DESCRIPTIVE NAME : handle the situration that a read only file +/* or is found, or the file has been Revised. +/* +/* FUNCTION: In the case that a readonly file is found, or the file +/* on the destination disk has been Revised since last backup, +/* this subroutine output a warning message to the user, and +/* prompt for user to enter yes or no depending on whether +/* the user wants to proceed restoring the file. +/* +/* +/********************* END OF SPECIFICATIONS ********************************/ +#define CHECK_YES_NO 0x6523 /*;AN000;6*/ +#define YES_NO_RESPTYPE 0xc1 /*;AN000;6*/ +#define YES 1 /*;AN000;6*/ + +int readonly_or_changed(attrib,destd,fspec,fpath) + + unsigned attrib; + unsigned char destd; + unsigned char *fspec; + unsigned char *fpath; +{ + + union REGS inregs, outregs; /*;AN000;6 Register set */ + WORD retcode; + + char file_to_be_chmode[MAXPATHF+2]; + DWORD dw = 0L; + int z; + + sublist.value1 = (char far *)fspec; /*;AN000;6 */ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ + sublist.max_width1 = (BYTE)strlen(fspec); /*;AN000;6 */ + sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ + + /***********************************************************************/ + /* if readonly, output msg and wait for user's prompt */ + /***********************************************************************/ + do /*;AN000;6*/ + { /*;AN000;6*/ + if((retcode = attrib & 0x0001) == 0x0001) + display_it(FILE_IS_READONLY,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + else + display_it(FILE_WAS_CHANGED,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + + inregs.x.ax = (unsigned)CHECK_YES_NO; /*;AN000;6*/ + inregs.h.dl = response_buff[0]; /*;AN000;6*/ + int86(0x21,&inregs,&outregs); /*;AN000;6*/ + display_it(CRLF,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + } /*;AN000;6*/ + while (outregs.h.al > 1); /*;AN000;6*/ + + /***********************************************************************/ + /* if user's input is 'Y', return TRUE, else return FALSE */ + /***********************************************************************/ + if (outregs.x.ax == YES) /*;AN000;6*/ + { file_to_be_chmode[0] = destd; + file_to_be_chmode[1] = ':'; + file_to_be_chmode[2] = NULLC; + strcat(file_to_be_chmode,fpath); + if (strlen(fpath) != 1) { + strcat(file_to_be_chmode,"\\"); + } + strcat(file_to_be_chmode,fspec); + /* change the file attribute to be 0, that is, reset it */ + if ((retcode = DOSSETFILEMODE((char far *)file_to_be_chmode,(unsigned) 0x00, dw)) != 0) + { + com_msg(retcode); + unexperror(retcode); + } + return(TRUE); + } + else { + return(FALSE); + } + /* endif */ +} /* end of subroutine readonly_or_changed */ + 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 @@ +static char *SCCSID = "@(#)rtt.c 8.1 86/09/20"; + +/*  0 */ + +#include +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include /* common subroutine def'n */ +#include +#include +#include /* wrw! */ + +unsigned char destddir[MAXPATH+3] = {'\0'}; +unsigned char srcddir[MAXPATH+3] = {'\0'}; +unsigned char rtswitch=0; +unsigned char control_flag=0; +unsigned char control_flag2=0; +unsigned char filename[MAXFSPEC] = {"OSO001.MSG"}; +unsigned char *buf_pointer; + +/****************************************************************************/ +/* The following comments are necessary to be here to make msgprof.exe */ +/* correctly. */ +/****************************************************************************/ +/* #define INSERT_SOURCE_DISK MSG_INS_BACKUP_DISK */ +/* #define SOURCE_TARGET_SAME MSG_REST_SOUR_TARG_SAME */ +/* #define INVALID_NUM_PARM MSG_REST_NUM_INVAL_PARA */ +/* #define INVALID_DRIVE MSG_REST_INVAL_SPEC */ +/* #define NO_FILE_TO_RESTORE MSG_REST_NO_FILE_FOUND */ +/* #define INVALID_PARM MSG_REST_INVAL_PARA */ +/* #define LAST_FILE_NOT_RESTORED MSG_REST_LAST_FILE_NOT */ +/* #define SOURCE_NO_BACKUP_FILE MSG_REST_SOURCE_NO_BACK */ +/* #define INSUFFICIENT_MEMORY MSG_REST_INSUF_MEM */ +/* #define FILE_SEQUENCE_ERROR MSG_REST_FILE_SEQ_ERROR */ +/* #define FILE_CREATION_ERROR MSG_REST_FILE_CREAT_ERROR */ +/* #define TARGET_IS_FULL MSG_REST_TARG_FULL */ +/* #define NOT_ABLE_TO_RESTORE_FILE MSG_REST_CANNOT_REST_FILE */ +/* #define INVALID_DOS_VER MSG_REST_INVAL_VERS */ +/* #define FILE_SHARING_ERROR MSG_REST_FILE_SHAR */ +/* #define FILE_WAS_CHANGED MSG_REST_CHNG_REPL */ +/* #define DISK_OUT_OF_SEQUENCE MSG_REST_DISK_OUT_SEQ */ +/* #define FILE_IS_READONLY MSG_REST_FILE_READ */ +/* #define SYSTEM_FILE_RESTORED MSG_REST_SYS */ +/* #define FILES_WERE_BACKUP_ON MSG_REST_FILE_BACKUP */ +/* #define RESTORE_FILE_FROM_DRIVE MSG_REST_FILE_FROM */ +/* #define INSERT_TARGET_DISK MSG_REST_TARG_DISK */ +/* #define FILE_TO_BE_RESTORED MSG_REST_FILENAME */ +/* #define DISKETTE_NUM MSG_REST_DISKETTE */ +/* #define PATH_NOT_FOUND MSG_BACK_INVAL_PATH */ + +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* MODULE NAME : RESTORE utility */ +/* */ +/* DESCRIPTIVE NAME : Restore one or more backed-up files from a */ +/* disk to another disk */ +/* */ +/* FUNCTION: Restore files saved by BACKUP utility to their */ +/* destination disk. This utility will be able to identify */ +/* which of the two backup formats was used and to do the */ +/* restore accordingly. */ +/* */ +/* NOTES: This RESTORE utility recognize two data formats: */ +/* 1. The data format used by BACKUP utility of 3.2 and before. */ +/* 2. The data format used by BACKUP utility of 3.3 and above, */ +/* and also used by CP/DOS 1.0 and above. */ +/* */ +/* DEPENDENCY: */ +/* This utility has a dependency on the BACKUP utility to */ +/* perform file backup correctly using the data structure */ +/* agreed on. */ +/* */ +/* RESTRICTION: */ +/* This utility is able to restore the files which are previously */ +/* backup by IBM BACKUP utility only. */ +/* */ +/* ENTRY POINT: Main */ +/* */ +/* INPUT: (PARAMETERS) */ +/* */ +/* COMMAND SYNTAX: */ +/* [d:][path]Restore d: [d:][path][filename][.ext] */ +/* [/S] [/P] [/B:date] [/A:date] [/E:time][/L:time][/M] [/N] */ +/* */ +/* Parameters: */ +/* The first parameter you specify is the drive designator of */ +/* the disk containing the backed up files. The second */ +/* parameter is the a filespec indicating which files you want */ +/* to restore. */ +/* Switches: */ +/* /S - Restore subdirectories too. */ +/* /P - If any hidden or read-only files match the filespec, */ +/* prompt the user for permission to restore them. */ +/* /B - Only restore those files which were last Revised on or */ +/* before the given date. */ +/* /A - Only restore those files which were last Revised on or */ +/* after the given date. */ +/* /E - Only restore those files which were last Revised at or */ +/* earlier then the given time. */ +/* /L - Only restore those files which were last Revised at or */ +/* later then the given time. */ +/* /M - Only restore those files which have been Revised since */ +/* the last backup. */ +/* /N - Only restore those files which no longer exist on the */ +/* destination disk. */ +/* */ +/* EXIT-NORMAL: */ +/* */ +/* The following messages will be displayed when the program */ +/* exit normally. */ +/* */ +/* *** Files were backed up xx/xx/xxxx *** */ +/* (xx/xx/xxxx will be different in differnt country codes) */ +/* */ +/* *** Restoring files from drive d: *** */ +/* Diskette: xx */ +/* path\filename.ext */ +/* path\filename.ext */ +/* path\filename.ext */ +/* path\filename.ext */ +/* ..... */ +/* */ +/* EXIT-ERROR: */ +/* The restore program sets the ERRORLEVEL in the following manner: */ +/* */ +/* 0 Normal completion */ +/* 1 No files were found to backup */ +/* 2 Some files not restored due to sharing conflict */ +/* 3 Terminated by user */ +/* 4 Terminated due to error */ +/* */ +/* EFFECTS: None */ +/* */ +/* OTHER USER INTERFACES: */ +/* RESTORE prompts for the user to insert source diskette if */ +/* the source disk specified is removable: */ +/* */ +/* Insert backup diskette 01 in drive d: */ +/* (d: is the source diskette) */ +/* Strike any key when ready */ +/* */ +/* If the destination disk is a removable drive, the following */ +/* message is also displayed: */ +/* */ +/* Insert restore target in drive d: */ +/* (d: is the destination disk) */ +/* Strike any key when ready */ +/* */ +/* No matter whether the destination disk is a removable drive */ +/* or a non_removable drive, when the destination disk is full, */ +/* RESTORE output a message "Target is full" and exit. RESTORE */ +/* does not prompt for user to change destination disk when it */ +/* is full. */ +/* */ +/* When there is any system file restored, the following message */ +/* is displayed: */ +/* System file restored */ +/* Target disk may not be bootable */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* Major routines are shown as follows: */ +/* main */ +/* parse_input_drive_and_file */ +/* set_input_switches */ +/* verify_input_switches */ +/* dorestore */ +/* check_bkdisk_old */ +/* printinfo */ +/* check_bkdisk_new */ +/* search_src_disk_old */ +/* check_flheader_old */ +/* pathmatch */ +/* fspecmatch */ +/* switchmatch */ +/* restore_a_file */ +/* search_src_disk_new */ +/* findfirst_new */ +/* findfile_new */ +/* findnext_new */ +/* check_flheader_new */ +/* readonly_or_changed */ +/* open_dest_file */ +/* build_path_create_file */ +/* dos_write_error */ +/* set_attributes_and_close */ +/* */ +/* Minor routines are shown as follows: */ +/* signal_handler_routine */ +/* usererror */ +/* unexperror */ +/* exit_routine */ +/* putmsg */ +/* com_msg */ +/* beep */ +/* checkdosver */ +/* separate */ +/* initbuf */ +/* init_control_buf */ +/* set_reset_test_flag */ +/* valid_input_date */ +/* valid_input_time */ +/* */ +/***************** END OF SPECIFICATION *********************************/ +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* SUBROUTINE NAME : Main */ +/* */ +/* DESCRIPTIVE NAME : Main routine for RESTORE utility */ +/* */ +/* FUNCTION: Main routine does the following: */ +/* 1. Verifies the DOS version */ +/* 2. Validate the input command line */ +/* 3. Calls dorestore to do the file restore. */ +/* */ +/* NOTES: */ +/* */ +/* ENTRY POINT: Main */ +/* Linkage: main((argc,argv) */ +/* */ +/* INPUT: (PARAMETERS) */ +/* argc - number of arguments */ +/* argv - array of pointers to arguments */ +/* */ +/* */ +/* EXIT-NORMAL: */ +/* */ +/* EXIT-ERROR: */ +/* */ +/* EFFECTS: rtswitch is changed to reflect the switches passed. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* dorestore */ +/* checkdosver */ +/* set_input_switches */ +/* parse_input_drive_and_file */ +/* separate */ +/* beep */ +/* putmsg */ +/* usererror */ +/* exit_routine */ +/* set_reset_test_flag */ +/* set_input_switches */ +/* exit_routine */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* com_strupr */ +/* DSOSETSIGHANDLER */ +/* */ +/********************** END OF SPECIFICATIONS *******************************/ +void main(argc,argv) /* wrw! */ + int argc; + char *argv[]; +{ + /*variables for putmsg */ + unsigned char *ivtable[2];/*point to the table of bairables to insert*/ + unsigned char respdata; /*response data area*/ + unsigned int msg_id; + unsigned int retcode; + + unsigned int destdnum; /*the destination disk in the integer form*/ + unsigned int i; /*loop counter */ + unsigned int j; /*arrary subcript */ + unsigned char *c; + unsigned long drive_map; + unsigned long prev_address; + unsigned int prev_action; + unsigned char srcd; + unsigned char destd; + unsigned char srcf[MAXPATHF]; + unsigned char inpath[MAXPATH]; + unsigned char infname[MAXFNAME]; + unsigned char infext[MAXFEXT]; + unsigned char infspec[MAXFSPEC]; + unsigned int next_arg; + struct timedate td; + void far pascal signal_handler_routine(); + /************************************************************************/ + /* set signal handler */ + /************************************************************************/ + + retcode = DOSSETSIGHANDLER( + (void (far *)() )signal_handler_routine, /* Signal handler address */ + (unsigned long far *)&prev_address, /* Address of previous handler */ + (unsigned far *)&prev_action, /* Address of previous action */ + (unsigned)INSTALL_SIGNAL, /* Indicate request type */ + (unsigned)CTRL_C); /* Signal number */ + + if (retcode != 0) + com_msg(retcode); + + retcode = DOSSETSIGHANDLER( + (void (far *)() )signal_handler_routine, /* Signal handler address */ + (unsigned long far *)&prev_address, /* Address of previous handler */ + (unsigned far *)&prev_action, /* Address of previous action */ + (unsigned)INSTALL_SIGNAL, /* Indicate request type */ + (unsigned)CTRL_BREAK); /* Signal number */ + + if (retcode != 0) + com_msg(retcode); + + /************************************************************************/ + /* check dos version */ + /************************************************************************/ + retcode = checkdosver(); + if (retcode != TRUE) { + + msg_id = INVALID_DOS_VER; + putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE); + + usererror(ERROR_INVALID_DOSVER); + } + + /************************************************************************/ + /*convert the input arguments into upper case */ + /************************************************************************/ + for (i=1; i <=argc-1; ++i) { + com_strupr(argv[i]); + } + + /************************************************************************/ + /* verify the number of parameters */ + /************************************************************************/ + if (argc-1 < MINARGS || argc-1 > MAXARGS) { + msg_id = INVALID_NUM_PARM; /*invalid number of parameters*/ + putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE); + usererror(INVALIDPARM); + } + /* endif*/ + + /************************************************************************/ + /* call subroutine to parse the drive and file name entered */ + /************************************************************************/ + parse_input_drive_and_file( argc, argv, &destd, &srcd, + srcf, &next_arg) ; + + /************************************************************************/ + /* separate the filename for search into prefix(inpath), */ + /* filename(infname), and file extension (infext) */ + /* Also take care of the situation that user enter '.' only */ + /* for file spec. */ + /************************************************************************/ + separate(srcf,inpath,infname,infext,infspec); + if (strlen(infname) > MAXFNAME-1 || + strlen(infext) > MAXFEXT-1 || + strlen(inpath) > MAXPATH-1 || + strcmp(infspec,"LPT1")==0 || + strcmp(infspec,"LPT2")==0 || + strcmp(infspec,"PRN")==0 || + strcmp(infspec,"CON")==0 || + strcmp(infspec,"NUL")==0 || + strcmp(infspec,"AUX")==0 || + strcmp(infspec,"LPT1:")==0 || + strcmp(infspec,"LPT2:")==0 || + strcmp(infspec,"PRN:")==0 || + strcmp(infspec,"CON:")==0 || + strcmp(infspec,"NUL:")==0 || + strcmp(infspec,"AUX:")==0 ) + { + msg_id = INVALID_PARM; + ivtable[0] = infspec; + putmsg (ivtable,1,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE); + usererror(INVALIDPARM); /* invalid parm */ + } + + /************************************************************************/ + /* set wildcard flag according to whether there is '*' or/and '?' in */ + /* file specification */ + /************************************************************************/ + c = infspec; + while (*c) { + if (*c == '*' || *c == '?') { + set_reset_test_flag(&control_flag,WILDCARD,SET); + break; + } + else + c = c+1; + } /*end while*/ + + /************************************************************************/ + /* if there is any more parameters to be parsed, call set_input_switches*/ + /* to parse them started from argv[next_arg] */ + /************************************************************************/ + if (next_arg != 0 && argc > next_arg) { + set_input_switches( argc, argv, &next_arg, &td); + } /* started from argv[next_arg] should be switches */ + + /************************************************************************/ + /* call dorestore to actually do the restoring */ + /************************************************************************/ + dorestore(srcd,destd,inpath,infname,infext,infspec,&td); + + /************************************************************************/ + /* output a msg in the following situations: */ + /* if flag indicates no file found */ + /************************************************************************/ + if (set_reset_test_flag(&control_flag,FOUND,TEST)==FALSE) { + beep(); + msg_id = NO_FILE_TO_RESTORE; /*warning! No files were found to restore*/ + putmsg (ivtable,0,msg_id,NO_RESPTYPE,&respdata,RESPDATA_SIZE); + exit_routine(NOFILES); + } + + exit_routine(NORMAL); + +} /* 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 @@ + +/*---------------------------- +/* SOURCE FILE NAME: RTT1.C +/*---------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "restpars.h" /*;AN000;4*/ +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" + +extern BYTE destddir[MAXPATH+3]; +extern BYTE srcddir[MAXPATH+3]; +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +extern BYTE filename[12]; +extern unsigned control_file_handle; /* !wrw */ +extern BYTE append_indicator; /*;AN000;2*/ +extern WORD original_append_func; /*;AN000;2*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_appendX +/* +/* FUNCTION: +/* Check APPEND /X status. If it is not active, +/* do nothing. If it is active, then turn it off +/* and set flag indicating that we must reset it later. +/* +/***************************************************/ +void check_appendX() /*;AN000;2*/ +{ /*;AN000;2*/ + union REGS gregs; /*;AN000;2 Register set */ + + gregs.x.ax = INSTALL_CHECK; /*;AN000;2 Get installed state*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + /*****************************************************/ + /* 1) See if append is active + /* 2) If so, figure out if PCDOS or PCNET version + /*****************************************************/ + if (gregs.h.al == 0) /*;AN000;2 Zero if not installed*/ + append_indicator = NOT_INSTALLED; /*;AN000;2 */ + else /*;AN000;2 See which APPEND it is*/ + { /*;AN000;2*/ + gregs.x.ax = GET_APPEND_VER; /*;AN000;2*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + if (gregs.h.al == (BYTE)-1) /*;AN000;2 -1 if PCDOS version*/ + append_indicator = DOS_APPEND; /*;AN000;2*/ + else /*;AN000;2*/ + append_indicator = NET_APPEND; /*;AN000;2*/ + } /*;AN000;2*/ + + /*****************************************************/ + /* If it is the PCDOS append + /* 1) Get the current append functions (returned in BX) + /* 2) Reset append with /X support off + /*****************************************************/ + if (append_indicator == DOS_APPEND) /*;AN000;2*/ + { /*;AN000;2*/ + gregs.x.ax = GET_STATE; /*;AN000;2 Get active APPEND functions*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + original_append_func = gregs.x.bx; /*;AN000;2*/ + + gregs.x.ax = SET_STATE; /*;AN000;2*/ + gregs.x.bx = gregs.x.bx & (!APPEND_X_BIT); /*;AN000;2*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + } /*;AN000;2*/ + + return; /*;AN000;2*/ +} /*;AN000;2*/ + \ 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 @@ +static char *SCCSID = "@(#)rtt2.c 8.4 86/10/19"; +/*  0 */ +#include +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include /* common subroutine def'n */ +#include +#include /* wrw! */ + +extern unsigned char rtswitch; +extern unsigned char control_flag; +extern unsigned char control_flag2; +extern struct internat ctry; /* data area for country info*/ + +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* SUBROUTINE NAME : valid_input_time */ +/* */ +/* DESCRIPTIVE NAME : to validate and convert the time input from the */ +/* command line. */ +/* */ +/* FUNCTION: This subroutine validate the time input from the command lin */ +/* against the country dependent information, and convert */ +/* the deta into three integers which are hour, minute, and */ +/* second. */ +/* NOTES: */ +/* */ +/* INPUT: (PARAMETERS) */ +/* in_string - the string from command line which contains date */ +/* information. */ +/* OUTPUT: */ +/* inhour - the input hour after converted */ +/* inminute - the input minute after converted */ +/* insecond - the input second after converted */ +/* */ +/* EXIT-NORMAL: returns TRUE if the time is valid */ +/* */ +/* EXIT-ERROR: returns FALSE if the time is invalid */ +/* */ +/* EFFECTS: */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* usererror */ +/* unexperror */ +/* putmsg */ +/* set_reset_test_flag */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/********************** END OF SPECIFICATIONS *******************************/ +int valid_input_time(in_string, inhour, inminute, insecond) + unsigned char *in_string; /*the input string */ + unsigned int *inhour; /*the input hour */ + unsigned int *inminute; /*the input minute */ + unsigned int *insecond; /*the input second */ +{ + unsigned char chour[10]; + unsigned char cminute[10]; + unsigned char csecond[10]; + unsigned int i,j,z; /*working pointer*/ + unsigned int no_second = FALSE; + unsigned char string[20]; + + /*declaration for get country information*/ + unsigned int byte_len; + unsigned buflen = sizeof( struct internat ); /* length of data area */ + unsigned int retcode; + long country = 0L; + + /************************************************/ + /* find the string for hour */ + /************************************************/ + #ifdef DEBUG + printf("\ntime to be validate %s",in_string); + #endif + /*save the pointer of input string*/ + strcpy(string,in_string); + + /* search the first occurance of country->timesep */ + for (i = 0; (string[i] != NULLC) && (string[i] != ctry.timesep && + string[i] != ':' && string[i] != '.'); ++i); + + if (string[i] == NULLC) { /*if not found*/ + #ifdef DEBUG + printf("\nno time seperator"); + #endif + return(FALSE); + } + + string[i] = NULLC; /*replace it with NULLC*/ + + /*get the string which represent hour*/ + strcpy(chour,string); + /*put the rest of the string into cminute*/ + strcpy(cminute,string+i+1); + + /************************************************/ + /* validate hour */ + /************************************************/ + if (strlen(chour) > MAXHOURLEN || strlen(chour)<1 ) { + #ifdef DEBUG + printf("\ninvalid hour length"); + #endif + return(FALSE); + } + + /* convert the string into integer form*/ + *inhour = 0; + for (j=0; chour[j] != NULLC ; ++j) { + if (chour[j] < '0' || chour[j] > '9') { + #ifdef DEBUG + printf("\nhour value not 0-9"); + #endif + return(FALSE); + } + *inhour = *inhour*10 + chour[j]-'0'; + } + + if (*inhour > 23 || *inhour < 0) { + #ifdef DEBUG + printf("\ninvalid hour value"); + #endif + return(FALSE); + } + + /************************************************/ + /* find the string for minute */ + /************************************************/ + /*search the next occurance of country->timesep*/ + for (i = 0; (cminute[i] != NULLC) && (cminute[i] != ctry.timesep && + cminute[i] != ':' && cminute[i] != '.'); ++i); + + if (cminute[i] == NULLC) { /*if not found*/ + no_second = TRUE; + } + + /*put NULLC at the end of string which represent minute*/ + cminute[i] = NULLC; /*replace it with NULLC*/ + strcpy(csecond,cminute+i+1); + + /************************************************/ + /* validate minute */ + /************************************************/ + if (strlen(cminute) > MAXMINUTELEN || strlen(cminute)<1 ) { + #ifdef DEBUG + printf("\ninvalid min length"); + #endif + return(FALSE); + } + + /*convert the string into integer*/ + *inminute = 0; + for (j=0; cminute[j] != NULLC ; ++j) { + if (cminute[j] < '0' || cminute[j] > '9') { + #ifdef DEBUG + printf("\ninvalid min value, not 0-9"); + #endif + return(FALSE); + } + *inminute = *inminute*10 + cminute[j]-'0'; + } + + if (*inminute > 59 || *inminute < 0) { + #ifdef DEBUG + printf("\ninvalid min value"); + #endif + return(FALSE); + } + + /***************************************************/ + /* if user input second, get the string for second */ + /***************************************************/ + if (no_second == TRUE) + return(TRUE); + else { + + /************************************************/ + /* validate second */ + /************************************************/ + if (strlen(csecond) > MAXSECONDLEN || strlen(csecond) < 1 ) { + #ifdef DEBUG + printf("\ninvalid second length"); + #endif + return(FALSE); + } + + /*convert the rest of the string into integer*/ + *insecond = 0; + for (j=0; csecond[j] != NULLC; ++j) + { + if (csecond[j] < '0' || csecond[j] > '9') { + #ifdef DEBUG + printf("\ninvalid second, 0-9"); + #endif + return(FALSE); + } + *insecond = *insecond*10 + csecond[j]-'0'; + } + + if (*insecond > 59 || *insecond < 0) { + #ifdef DEBUG + printf("\ninvalid second value"); + #endif + return(FALSE); + } + } /*end of if no_second is true */ + return(TRUE); + +} /*end of subroutine*/ +/***************** START OF SPECIFICATION *********************************/ +/* */ +/* SUBROUTINE NAME : valid_input_date */ +/* */ +/* DESCRIPTIVE NAME : to validate and convert the date input from the */ +/* command line. */ +/* */ +/* FUNCTION: This subroutine validate the date input from the command lin */ +/* against the country dependent information, and convert */ +/* the deta into three integers which are year, month, and day. */ +/* NOTES: */ +/* */ +/* INPUT: (PARAMETERS) */ +/* in_string - the string from command line which contains date */ +/* information. */ +/* OUTPUT: */ +/* inyear - the input year after converted */ +/* inmonth - the input month after converted */ +/* inday - the input day after converted */ +/* */ +/* EXIT-NORMAL: returns TRUE if the date is valid */ +/* */ +/* EXIT-ERROR: returns FALSE if the date is invalid */ +/* */ +/* EFFECTS: */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* usererror */ +/* unexperror */ +/* putmsg */ +/* set_reset_test_flag */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/********************** END OF SPECIFICATIONS *******************************/ +int valid_input_date(in_string,inyear,inmonth,inday) + + unsigned char *in_string; + unsigned int *inyear; + unsigned int *inmonth; + unsigned int *inday; +{ + unsigned char c1[10]; + unsigned char c2[10]; + unsigned char c3[10]; + unsigned char cyear[10]; + unsigned char cmonth[10]; + unsigned char cday[10]; + unsigned int in1; + unsigned int in2; + unsigned int in3; + unsigned int i,j,z; /*working pointer*/ + unsigned char string[30]; + unsigned int remainder; + + #ifdef DEBUG + printf("\ndate to be validate %s",in_string); + #endif + /************************************************/ + /* separate the input date string into 3 parts */ + /************************************************/ + /*save the pointer to the input string*/ + strcpy(string,in_string); + + /* search the first occurance of country->datesep */ + for (i = 0; (string[i] != NULLC) && (string[i] != ctry.datesep && + string[i] != '/' && string[i] != '-' && string[i] != '.'); ++i); + + if (string[i] == NULLC) { /*if not found*/ + #ifdef DEBUG + printf("\ninvalid date sep"); + #endif + return(FALSE); + } + + string[i] = NULLC; /*replace it with NULLC*/ + + /*get the string which represent year*/ + strcpy(c1,string); + /*put the rest of the string into c2*/ + strcpy(c2,string+i+1); + + /*search the next occurance of country->datesep*/ + for (i = 0; (c2[i] != NULLC) && (c2[i] != ctry.datesep && + c2[i] != '/' && c2[i] != '-' && c2[i] != '.'); ++i); + + if (c2[i] == NULLC) { /*if not found*/ + #ifdef DEBUG + printf("\nno 2nd date sep"); + #endif + return(FALSE); + } + + /*put NULLC at the end of string which represent month*/ + c2[i] = NULLC; /*replace it with NULLC*/ + strcpy(c3,c2+i+1); + + /************************************************/ + /* convert all 3 strings to integers */ + /************************************************/ + in1 = 0; + for (j=0; c1[j] != NULLC ; ++j) { + if (c1[j] < '0' || c1[j] > '9') { + #ifdef DEBUG + printf("\ninvalid 1st in date not 0-9"); + #endif + return(FALSE); + } + in1 = in1*10 + c1[j]-'0'; + } + + in2 = 0; + for (j=0; c2[j] != NULLC ; ++j) { + if (c2[j] < '0' || c2[j] > '9') { + #ifdef DEBUG + printf("\ninvalid 2nd in date not 0-9"); + #endif + return(FALSE); + } + in2 = in2*10 + c2[j]-'0'; + } + + in3 = 0; + for (j=0; c3[j] != NULLC ; ++j) { + if (c3[j] < '0' || c3[j] > '9') { + #ifdef DEBUG + printf("\ninvalid 3rd in date not 0-9"); + #endif + return(FALSE); + } + in3 = in3*10 + c3[j]-'0'; + } + /************************************************/ + /* identify what these 3 integers are stand for */ + /************************************************/ + switch (ctry.dtformat) { + case USA: + *inmonth = in1; + *inday = in2; + *inyear = in3; + strcpy(cmonth,c1); + strcpy(cday,c2); + strcpy(cyear,c3); + break; + case EUR: + *inday = in1; + *inmonth = in2; + *inyear = in3; + strcpy(cday,c1); + strcpy(cmonth,c2); + strcpy(cyear,c3); + break; + case JAP: + *inyear = in1; + *inmonth = in2; + *inday = in3; + strcpy(cyear,c1); + strcpy(cmonth,c2); + strcpy(cday,c3); + break; + default: + #ifdef DEBUG + printf("\ninvalid country code %d",ctry.dtformat); + #endif + unexperror(UNEXPECTED); + break; + } + /************************************************/ + /* validate the value of year */ + /************************************************/ + if (strlen(cyear) > MAXYEARLEN || strlen(cyear)<1 ) { + #ifdef DEBUG + printf("\ninvalid year len"); + #endif + return(FALSE); + } + + if (*inyear <= 99 && *inyear >= 80) + *inyear = *inyear + 1900; + if (*inyear <= 79 && *inyear >= 00) + *inyear = *inyear + 2000; + + /*validate the value of year */ + if (*inyear > MAXYEAR || *inyear < MINYEAR) { + #ifdef DEBUG + printf("\ninvalid year value"); + #endif + return(FALSE); + } + + /************************************************/ + /* validate the value of month */ + /************************************************/ + if (strlen(cmonth) > MAXMONTHLEN || strlen(cmonth)<1 ) { + #ifdef DEBUG + printf("\ninvalid month length"); + #endif + return(FALSE); + } + + /*validate the value of year */ + if (*inmonth > MAXMONTH || *inmonth <= 0) { + #ifdef DEBUG + printf("\ninvalid month value"); + #endif + return(FALSE); + } + + /************************************************/ + /* validate the value of day */ + /************************************************/ + if (strlen(cday) > MAXDAYLEN || strlen(cday)<1 ) { + #ifdef DEBUG + printf("\ninvalid day len"); + #endif + return(FALSE); + } + + /*validate the value of year */ + if (*inday > MAXDAY || *inday <= 0 ) { + #ifdef DEBUG + printf("\ninvalid day value"); + #endif + return(FALSE); + } + if ((*inmonth == 1 || *inmonth == 3 || *inmonth == 5 || + *inmonth == 7 || *inmonth == 8 || *inmonth == 10 || + *inmonth == 12 ) && (*inday > 31 || *inday < 1)) { + #ifdef DEBUG + printf("\ninvalid day value"); + #endif + return(FALSE); + } + else { + if ((*inmonth == 4 || *inmonth == 6 || *inmonth == 9 || + *inmonth == 11 ) && (*inday > 30 || *inday < 1)) { + #ifdef DEBUG + printf("\ninvalid day value"); + #endif + return(FALSE); + } + else { + if (*inmonth == 2) { + /*check for leap year */ + remainder = *inyear % 4; + if (remainder == 0) { + if (*inday > 29 || *inday < 1) { + #ifdef DEBUG + printf("\ninvalid day value"); + #endif + return(FALSE); + } + } + else { + if (*inday > 28 || *inday < 1) { + #ifdef DEBUG + printf("\ninvalid day value"); + #endif + return(FALSE); + } + } + } + } + } + + /************************************************/ + /* if there is no error found, return TRUE */ + /************************************************/ + return(TRUE); + +} /*end of subroutine valid_input_date*/ + +/**************************/ + \ 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 @@ + +/*--------------------------------- +/* SOURCE FILE NAME: RTT3.C +/*--------------------------------- +/*  0 */ + +#include "rt.h" +#include "rt1.h" +#include "rt2.h" +#include "direct.h" +#include "string.h" +#include "dos.h" /*;AN000;2*/ +#include "comsub.h" /* common subroutine def'n */ +#include "doscalls.h" +#include "error.h" +#include "process.h" /*;AN000;p972*/ + +extern BYTE filename[12]; +extern BYTE destddir[MAXPATH+3]; +extern BYTE srcddir[MAXPATH+3]; +extern BYTE rtswitch; +extern BYTE control_flag; +extern BYTE control_flag2; +char far *buf_pointer; +char far *control_buf_pointer; +unsigned control_selector; +extern BYTE dest_file_spec[MAXFSPEC]; +extern unsigned dest_file_handle; +extern BYTE append_indicator; /*;AN000;2*/ +extern WORD original_append_func; /*;AN000;2*/ +extern struct subst_list sublist; /*;AN000;6 Message substitution list */ +extern char response_buff[5]; /*;AN000;6*/ +BYTE far *DBCS_ptr; /*;AN005;*/ +char got_dbcs_vector = FFALSE; /*;AN005;*/ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : set_reset_test_flag +/* +/* DESCRIPTIVE NAME : to set a flag, reset a flag, or test a flag. +/* +/* FUNCTION: This subroutine is called when there is a need to set +/* a flag, reset a flag, or test a flag. +/* NOTES: +/* +/* INPUT: (PARAMETERS) +/* flag - the flag to be set, reset, or tested. +/* targetbt - the target bit to be set, reset, or tested. +/* choice - = 1 if want to set +/* = 2 if want to reset +/* = 3 if want to test +/* +/********************* END OF SPECIFICATIONS ********************************/ +int set_reset_test_flag(flag,targetbt,choice) + + BYTE *flag; /*the flag to be tested against*/ + BYTE targetbt; /*the byte to be tested */ + int choice; +{ + BYTE temp; + + +switch (choice) { +case SET: + *flag = *flag | targetbt; + break; + +case RESET: + *flag = *flag & ~targetbt; + break; + +case TEST: + temp = *flag & targetbt; + if (temp == 0) { + return(FALSE); /*the tested bit is off*/ + } + else { + return(TRUE); /*the tested bit is on */ + } + break; + +default: + unexperror(UNEXPECTED); + break; +} /*end of switch */ + + return(FALSE); /* wrw! */ + +} +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : separate +/* +/* DESCRIPTIVE NAME : Separate the given input string into 3 parts; +/* which is the path, filename, file extension, and +/* file specification. +/* +/* FUNCTION: The subroutine searches the input string for the last '\', +/* which separates the path and file specification, and then +/* searches the file specification for '.', which separates +/* the filename and file extension. Also take care the +/* situation of the user enter '.' for file specification. +/* This subroutine also validate the file specification +/* and each path entered by the user by calling common +/* subroutine Comverflnm. +/* +/* NOTE: The input string must start with '\' +/* All the output string are terminated by 00h +/* +/* INPUT: (PARAMETERS) +/* instring - input string to be separated into path, filename, +/* and file extension. +/* +/* OUTPUT: +/* path - output path name, always starts with '\' and not end +/* with '\' +/* filename - output file name +/* fileext - output file extension +/* filespec - output file name and file extension +/* +/********************** END OF SPECIFICATIONS *******************************/ +void separate(instring,path,filename,fileext,filespec) +BYTE *instring; /* point to beginning of input string */ +BYTE *path; /* point to beginning of path string */ +BYTE *filename; /* point to beginning of file name */ +BYTE *fileext; /* point to beginning of file ext. */ +BYTE *filespec; /* point to beginning of file spec */ +{ + BYTE *iptr; /* working pointer */ + BYTE *fptr; /* working pointer */ + WORD i; /*;AN005;*/ + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Find last non-DBCS backslash character */ +/* fptr = com_strrchr(instring,'\\'); /*;AN000;p2532*/ + + for ( /*;AN005;*/ + i=strlen(instring); /*;AN005;*/ + (i>=0) && (!chek_DBCS(instring,i,'\\')); /*;AN005;*/ + i-- /*;AN005;*/ + ) /*;AN005;*/ + {}; /*;AN005;*/ + + fptr = instring + i; /*;AN005;*/ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + if (fptr!=instring || instring[0] == '\\') + { + *fptr = NULLC; /*;AC000;*/ + strcpy(path, instring); + if (path[0] == NULLC) + strcpy(path,"\\"); + *fptr = '\\'; + ++fptr; + strcpy(filespec, fptr); + + if (filespec[0] == '.' && filespec[1] == NULLC) + { + strcpy(filename, "*"); + strcpy(fileext, "*"); + strcpy(filespec, "*.*"); + } + else + { /*else if filespec is not '.'*/ + for (iptr = fptr; *iptr!='.' && *iptr != NULLC; ++iptr); + + if (*iptr == '.') + { + *iptr = NULLC; + strcpy(filename, fptr); + *iptr = '.'; + + iptr = iptr+1; + strcpy(fileext, iptr); + } + else + { + strcpy(filename, filespec); + *fileext = NULLC; + } + + } + + } + else + {} + + return; +} + + + + + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : initbuf +/* +/* DESCRIPTIVE NAME : Initialize buffer for reading and writting. +/* +/* FUNCTION: Allocate up to 64 K bytes buffer for reading and writing +/* data, and make sure its size is divisible by the sector +/* size of the restore drive. +/* +/* NOTES: +/* +/********************** END OF SPECIFICATIONS *******************************/ + +void initbuf(bufsize_long) + DWORD *bufsize_long; +{ + unsigned bufsize; + WORD selector; + WORD retcode; + + bufsize = MAXBUF; /*64K-1 */ + /*do while allocate bufsize fail, bufsize = bufsize - DOWNSIZE*/ + for (;;) { + retcode = DOSALLOCSEG( (unsigned ) bufsize, /*buf length */ + ( unsigned far * ) &selector, /* buf pointer*/ + ( unsigned) 0 ); /* no sharing */ + if ( retcode != 0) + { + if (bufsize > DOWNSIZE) + bufsize = bufsize - DOWNSIZE; + else + break; + } + else + break; + } + if (bufsize != 0 && bufsize <= DOWNSIZE ) { + display_it(INSUFFICIENT_MEMORY,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/ + usererror(INSUFMEM); + } + + FP_SEG( buf_pointer ) = selector; + FP_OFF( buf_pointer ) = 0 ; + + if (bufsize == 0) + *bufsize_long = (DWORD)MAXBUF; + else + *bufsize_long = (DWORD)bufsize; +} /*end of subroutine*/ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : init_control_buf +/* +/* DESCRIPTIVE NAME : Initialize buffer for control.XXX. +/* +/* FUNCTION: Allocate buffer for reading in control.xxx +/* +/* OUTPUT: +/* control_bufsize - the size of buffer +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void init_control_buf(control_file_len,control_bufsize) /* !wrw */ + DWORD control_file_len; /* !wrw */ + unsigned int *control_bufsize; /* !wrw */ +{ /* !wrw */ + unsigned bufsize; /* !wrw */ + WORD retcode; /* !wrw */ + + bufsize = 3072; /* !wrw */ + + + retcode = DOSALLOCSEG( (unsigned ) bufsize, /* !wrw */ + ( unsigned far * ) &control_selector, /* !wrw */ + ( unsigned) 0 ); /* !wrw */ + + + if ( retcode != 0) /* If there is insufficient memory /* !wrw */ + { /* !wrw */ + display_it(INSUFFICIENT_MEMORY,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + usererror(INSUFMEM); + } /* !wrw */ + + FP_SEG( control_buf_pointer ) = control_selector; /* !wrw */ + FP_OFF( control_buf_pointer ) = 0 ; /* !wrw */ + + *control_bufsize = bufsize; /* !wrw */ + +} /*end of subroutine*/ /* !wrw */ + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : unexperror +/* +/* DESCRIPTIVE NAME : exit the program because of something really bad +/* occures +/* +/* FUNCTION: Exit the program because of unexpected error +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void unexperror(retcode) +WORD retcode; +{ + exit_routine(retcode); + return; +} + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : usererror +/* +/* DESCRIPTIVE NAME : exit the program because of a user error +/* +/********************** END OF SPECIFICATIONS *******************************/ +void usererror(retcode) +WORD retcode; +{ + unexperror(retcode); + return; +} + +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : exit_routine +/* +/* DESCRIPTIVE NAME : exit the program +/* +/* FUNCTION: 1. output msg if there is a sharing error. +/* 2. if PCDOS, convert return codes to error levels +/* 3. exit the program +/* +/* NOTES: +/* +/* INPUT: (PARAMETERS) +/* retcode - the reason of error +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void exit_routine(retcode) +WORD retcode; +{ + union REGS regs; /*;AN000;2*/ + + chdir (destddir); + + chdir (srcddir); + + /* if flag indicates there is a SHAREERROR */ + if (retcode == NORMAL && + set_reset_test_flag(&control_flag,SHARERROR,TEST)==TRUE) + retcode = SHARERR; + + switch(retcode) + { + case NORMAL: retcode = PC_NORMAL; + break; + case NOFILES: retcode = PC_NOFILES; + break; + case SHARERR: retcode = PC_SHARERR; + break; + case TUSER: retcode = PC_TUSER; + break; + default: retcode = PC_OTHER; + break; + } /* end switch */ + + + if (append_indicator == DOS_APPEND) /*;AN000;2 If append /x was reset*/ + { /*;AN000;2*/ + regs.x.ax = SET_STATE; /*;AN000;2*/ + regs.x.bx = original_append_func; /*;AN000;2*/ + int86(0x2f,®s,®s); /*;AN000;2*/ + } /*;AN000;2*/ + + exit(retcode); /*;AN000;p972*/ + +} +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : signal_handler_routine +/* +/* DESCRIPTIVE NAME : handle the situation that the user terminate +/* the program by Control-break. +/* +/* FUNCTION: This subroutine change the directory of the +/* destination disk back to the original directory. +/* If there is a file in the middle of restoring, close +/* the file, deleted the partially restored file, and +/* output a message. +/* Then exit with error level TUSER. +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void pascal far signal_handler_routine() +{ + WORD retcode; + + DWORD dw = 0L; /* reserved double word*/ + + /*change dir to the original directory of the destination disk*/ + + /**************************************************************/ + /*if PARTIAL flag is on, close and delete the destination file*/ + /**************************************************************/ + if (set_reset_test_flag(&control_flag,PARTIAL,TEST) == TRUE) { + /* close the partially completed destination file*/ + DOSCLOSE(dest_file_handle); + /* delete the partially completed destination file*/ + if ((retcode = DOSDELETE((char far *) dest_file_spec, dw)) != 0) { + /*set file mode to 0*/ + if ((retcode = DOSSETFILEMODE((char far *)dest_file_spec, + (unsigned) 0x00, dw)) != 0) + { + com_msg(retcode); + unexperror(retcode); + } + /* delete the partially completed destination file*/ + if ((retcode = DOSDELETE((char far *) dest_file_spec, dw)) != 0) { + com_msg(retcode); + unexperror(retcode); + } + } + display_it(LAST_FILE_NOT_RESTORED,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + } + exit_routine(TUSER); + +} /* end of signal_handler*/ + +/************************************************************/ +/* +/* SUBROUTINE NAME: display_it (added for DOS 4.00) +/* +/* SUBROUTINE FUNCTION: +/* Display the requested message to the standard output device. +/* +/* INPUT: +/* 1) (WORD) Number of the message to be displayed. +/* 2) (WORD) Handle to be written to. +/* 3) (WORD) Substitution Count +/* 4) (WORD) Flag indicating user should "Strike any key..." +/* +/* OUTPUT: +/* The message corresponding to the requested msg number will +/* be written to the requested handle. If requested, substitution +/* text will be inserted as required. The Substitution List +/* is global and, if used, will be initialized by DISPLAY_MSG +/* before calling this routine. +/* +/* NORMAL EXIT: +/* Message will be successfully written to requested handle. +/* +/* ERROR EXIT: +/* None. Note that theoretically an error can be returned from +/* SYSDISPMSG, but there is nothing that the application can do. +/* +/* +/************************************************************/ +#define CLASS -1 /* Goes in DH register */ /*;AN000;6*/ +#define NUL_POINTER 0 /* Pointer to nothing */ /*;AN000;6*/ + +void display_it(msg_number,handle,subst_count,waitflag,class) /*;AN000;6*/ + +WORD msg_number; /*;AN000;6*/ +WORD handle; /*;AN000;6*/ +WORD subst_count; /*;AN000;6*/ +WORD waitflag; /*;AN000;6*/ +BYTE class; /*;AN000;6*/ +{ /*;AN000;6*/ + union REGS reg; /*;AN000;6*/ + + reg.x.ax = msg_number; /*;AN000;6*/ + reg.x.bx = handle; /*;AN000;6*/ + reg.x.cx = subst_count; /*;AN000;6*/ + reg.h.dh = class; /*;AN000;6*/ + reg.h.dl = (BYTE)waitflag; /*;AN000;6*/ + reg.x.di = (BYTE)&response_buff[0]; /*;AN000;6*/ + reg.x.si = (WORD)(char far *)&sublist; /*;AN000;6*/ + + sysdispmsg(®,®); /*;AN000;6*/ + response_buff[0] = reg.h.al; /* User input */ /*;AN000;6*/ + + return; /*;AN000;6 */ +} /*;AN000;6 */ +/***************** START OF SPECIFICATION ******************************** +/* +/* SUBROUTINE NAME : com_msg +/* +/* DESCRIPTIVE NAME : the routine to output a message according to +/* the return codes returned from API calls. +/* +/* FUNCTION: 1. if CP/DOS, then call rctomid +/* +/* NOTES: +/* +/* INPUT: (PARAMETERS) +/* retcode - return code used to call rctomid +/* +/* +/********************** END OF SPECIFICATIONS *******************************/ +void com_msg(retcode) +WORD retcode; +{ + /* Was IF CPDOS */ + display_it(rctomid(retcode),STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ + + return; + +} +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: chek_DBCS() */ +/* */ +/* (Ripped off and Revised from ATTRIB.C) */ +/* */ +/* Subroutine Function: */ +/* Given an array and a position in the array, check if the character */ +/* is a non-DBCS character. */ +/* */ +/* Input: array, character position, character */ +/* */ +/* Output: TRUE - if array[position-1] != DBCS character AND */ +/* array[position] == character. */ +/* FALSE - otherwise */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +WORD chek_DBCS(array,position,character) /*;AN005;*/ +char *array; /*;AN005;*/ +WORD position; /*;AN005;*/ +char character; /*;AN005;*/ +{ /*;AN005;*/ + BYTE far *ptr; /*;AN005;*/ + WORD i; /*;AN005;*/ + char c; /*;AN005;*/ + char darray[128]; /* DBCS array, put "D" in every position*/ /*;AN005;*/ + /* that corresponds to the first byte */ + /* of a DBCS character. */ + if (!got_dbcs_vector) /*;AN005;*/ + Get_DBCS_vector(); /*;AN005;*/ + + for (i=0;i<128;i++) /*;AN005;*/ + darray[i] = ' '; /*;AN005;*/ + + /* Check each character, starting with the first in string, for DBCS */ + /* characters and mark each with a "D" in the corresponding darray. */ + for (i=0;i= *ptr && c <= *(ptr+1)) /*;AN005;*/ + { /*;AN005;*/ + darray[i] = 'D'; /*;AN005;*/ + i++; /* skip over second byte of DBCS */ /*;AN005;*/ + break; /*;AN005;*/ + } /*;AN005;*/ + } /*;AN005;*/ + } /*;AN005;*/ + + /* if character is not DBCS then check to see if it is == to character */ + if (darray[position-1] != 'D' && character == array[position]) /*;AN005;*/ + return (TTRUE); /*;AN005;*/ + else /*;AN005;*/ + return (FFALSE); /*;AN005;*/ +} /*;AN005;*/ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_DBCS_vector() */ +/* */ +/* Subroutine Function: */ +/* Gets the double-byte table vector. */ +/* Puts it in global variable DBCS_ptr */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +void Get_DBCS_vector() /*;AN005;*/ +{ /*;AN005;*/ + union REGS inregs,outregs; /*;AN005;*/ + struct SREGS segregs; /*;AN005;*/ + char fix_es_reg[2]; /*;AN005;*/ + WORD *ptr; /*;AN005;*/ + DWORD far *addr_ptr; /*;AN005;*/ + WORD *buffer; /*;AN005;*/ + + /***********************************/ + /* Allocate a buffer */ + /***********************************/ + inregs.x.ax = 0x4800; /* Allocate */ /*;AN005;*/ + inregs.x.bx = 1; /* Num paragraphs */ /*;AN005;*/ + intdos(&inregs,&outregs); /* Int 21h */ /*;AN005;*/ + buffer = (WORD *)outregs.x.ax; /* Segment of buffer */ /*;AN005;*/ + + inregs.x.ax = 0x6507; /* get extended country info */ /*;AN005;*/ + inregs.x.bx = 0xffff; /* use active code page */ /*;AN005;*/ + inregs.x.cx = 5; /* 5 bytes of return data */ /*;AN005;*/ + inregs.x.dx = 0xffff; /* use default country */ /*;AN005;*/ + inregs.x.di = 0; /* buffer offset */ /*;AN005;*/ + segregs.es = (WORD)buffer; /* buffer segment */ /*;AN005;*/ + segregs.ds = (WORD)buffer; /* buffer segment */ /*;AN005;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN005;*/ + strcpy(fix_es_reg,NUL); /*;AN005;*/ + + outregs.x.di++; /* skip over id byte */ /*;AN005;*/ + + /* make a far ptr from ES:[DI] */ + addr_ptr = 0; /*;AN005;*/ + ptr = (WORD *)&addr_ptr; /*;AN005;*/ + *ptr = (WORD)outregs.x.di; /* get offset */ /*;AN005;*/ + ptr++; /*;AN005;*/ + *ptr = (WORD)segregs.es; /* get segment */ /*;AN005;*/ + DBCS_ptr = (BYTE far *)*addr_ptr; /*;AN005;*/ + DBCS_ptr += 2; /* skip over table length */ /*;AN005;*/ + + /* DBCS_ptr points to DBCS table */ + strcpy(fix_es_reg,NUL); /*;AN005;*/ + got_dbcs_vector = TTRUE; /*;AN005;*/ + return; /*;AN005;*/ +} /*;AN005;*/ + 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 @@ + + + /* built in 'c' functions */ + + int sprintf(); + int printf(); + char *strcat(char *,char *); + int strlen(char *); + char *strcpy(char *, char *); + int strncmp(char *,char *,unsigned int); + int strcmp(char *,char *); + + /* li functions */ + int chdir(char *); + int mkdir(char *); + + void search_src_disk_old(struct disk_info *, + struct file_info *, + struct disk_header_old *, + struct disk_header_new far *, + struct file_header_old *, + struct file_header_new far *, + unsigned char, + unsigned char, + unsigned long, + unsigned int *, + unsigned char *, + unsigned char *, + unsigned char *, + unsigned char *, + struct timedate *); + + void search_src_disk_new(struct disk_info *, + struct file_info *, + struct disk_header_old *, + struct disk_header_new far *, + struct file_header_old *, + struct file_header_new far *, + unsigned char, + unsigned char, + unsigned int *, + unsigned long, + unsigned char *, + unsigned char *, + unsigned char *, + unsigned int *, + struct timedate *); + + + int findfirst_new( struct file_info *, + unsigned int *, + unsigned int *, + unsigned char *, + unsigned char *, + unsigned int far**, + unsigned int far**, + unsigned int *, + unsigned char *); + + + void restore_a_file(struct file_info *, + struct disk_info *, + unsigned long, + unsigned int *, + struct file_header_old *, + struct file_header_new far *, + struct disk_header_old *, + struct disk_header_new far *, + unsigned char, + unsigned char, + unsigned char *, + unsigned char *, + unsigned char *, + unsigned int *, + unsigned int *); + + \ 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 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 message retriever +; +; CALLING FORMAT: +; sysloadmsg(&inregs,&outregs); +; sysdispmsg(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; + + .8087 +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS +DGROUP GROUP CONST, _BSS, _DATA + ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP + + + public _sysloadmsg + public _sysdispmsg + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + +_DATA segment +.XLIST +.XCREF + MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; +.LIST +.CREF +_DATA ends + + +_TEXT segment + +;------------------------------------------------------------------- + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg +.XLIST +.XCREF + MSG_SERVICES ;AN000;6 + MSG_SERVICES ;AN000;6 +.LIST +.CREF +;------------------------------------------------------------------- + +_sysloadmsg proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + call sysloadmsg ; call the message retriever +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_sysloadmsg endp + + +;_sysgetmsg proc near +; +; push bp ; save user's base pointer +; mov bp,sp ; set bp to current sp +; push di ; save some registers +; push si +; +;; copy C inregs into proper registers +; +; mov di,[bp+4] ; fix di (arg 0) +; +;;------------------------------------------------------------------- +; +; mov ax,[di+0ah] ; load di +; push ax ; the di value from inregs is now on stack +; +; mov ax,[di+00] ; get inregs.x.ax +; mov bx,[di+02] ; get inregs.x.bx +; mov cx,[di+04] ; get inregs.x.cx +; mov dx,[di+06] ; get inregs.x.dx +; mov si,[di+08] ; get inregs.x.si +; pop di ; get inregs.x.di from stack +; +; push bp ; save base pointer +; +;;------------------------------------------------------------------- +; call sysgetmsg ; call the message retriever +;;------------------------------------------------------------------- +; +; pop bp ; restore base pointer +; push di ; the di value from call is now on stack +; mov di,[bp+6] ; fix di (arg 1) +; +; mov [di+00],ax ; load outregs.x.ax +; mov [di+02],bx ; load outregs.x.bx +; mov [di+04],cx ; load outregs.x.cx +; mov [di+06],dx ; load outregs.x.dx +; mov [di+08],si ; load outregs.x.si +; +; lahf ; get flags into ax +; mov al,ah ; move into low byte +; mov [di+0ch],ax ; load outregs.x.cflag +; +; pop ax ; get di from stack +; mov [di+0ah],ax ; load outregs.x.di +; +;;------------------------------------------------------------------- +; +; pop si ; restore registers +; pop di +; mov sp,bp ; restore sp +; pop bp ; restore user's bp +; ret +; +;_sysgetmsg endp + +_sysdispmsg proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + call sysdispmsg ; call the message retriever +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_sysdispmsg endp + +include msgdcl.inc + +_TEXT ends ; end code segment + end + + \ 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 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 parser +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse + +;------------------------------------------------------------------- +FarSW equ 0 ; make sysparse be a NEAR proc +TimeSW equ 1 ; Check time format +FileSW equ 1 ; Check file specification +CAPSW equ 1 ; Perform CAPS if specified +CmpxSW equ 0 ; Check complex list +NumSW equ 0 ; Check numeric value +KeySW equ 0 ; Support keywords +SwSW equ 1 ; Support switches +Val1SW equ 0 ; Support value definition 1 +Val2SW equ 0 ; Support value definition 2 +Val3SW equ 0 ; Support value definition 3 +DrvSW equ 1 ; Support drive only format +QusSW equ 0 ; Support quoted string format +IncSW equ 0 ; Dont include PSDATA, I just did it +BaseSW equ 1 ; DS points to data +;------------------------------------------------------------------- + +DGROUP GROUP _DATA +PGROUP GROUP _TEXT + +_DATA segment byte public 'DATA' +include psdata.inc +_DATA ends + +_TEXT segment byte public 'CODE' + + ASSUME CS: PGROUP + ASSUME DS: DGROUP + +;------------------------------------------------------------------- +.xlist +include parse.asm ; include the parser +.list +;------------------------------------------------------------------- + +_parse proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer +;------------------------------------------------------------------- + call sysparse ; call the parser +;------------------------------------------------------------------- + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_parse endp + +_TEXT ends ; end code segment + end + + \ No newline at end of file -- cgit v1.2.3