You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
14 KiB
422 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Argument
|
|
|
|
Abstract:
|
|
|
|
Argument processing for the Replace utility
|
|
|
|
Author:
|
|
|
|
Ramon Juan San Andres (ramonsa) 01-May-1991
|
|
|
|
Notes:
|
|
|
|
The arguments accepted by the Replace utility are:
|
|
|
|
Source path.- Source path.
|
|
|
|
Destination path.- Destination path.
|
|
|
|
Add switch.- Adds new files to the target directory instead of
|
|
replacing existing one. Cannot use with Subdir
|
|
switch or CompareTime switch.
|
|
|
|
Prompt switch.- Prompts before adding/replacing a file.
|
|
|
|
ReadOnly switch.- Replaces red-only files as well as regular files.
|
|
|
|
Subdir switch.- Recurses along the destination path.
|
|
|
|
CompareTime switch.-Replaces only thos files on the target path that
|
|
are older than the corresponding file in the
|
|
source path.
|
|
|
|
Wait switch.- Waits for the user to type any key before starting.
|
|
|
|
Help switch.- Displays usage
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "ulib.hxx"
|
|
#include "arg.hxx"
|
|
#include "arrayit.hxx"
|
|
#include "file.hxx"
|
|
#include "system.hxx"
|
|
#include "replace.hxx"
|
|
|
|
|
|
#define MATCH_ALL_PATTERN "*"
|
|
#define CURRENT_DIRECTORY (LPWSTR)L"."
|
|
|
|
|
|
|
|
//
|
|
// Global variables (global to the module)
|
|
//
|
|
|
|
PPATH_ARGUMENT SourcePathArgument = NULL;
|
|
PPATH_ARGUMENT DestinationPathArgument = NULL;
|
|
PFLAG_ARGUMENT AddArgument = NULL;
|
|
PFLAG_ARGUMENT PromptArgument = NULL;
|
|
PFLAG_ARGUMENT ReadOnlyArgument = NULL;
|
|
PFLAG_ARGUMENT SubdirArgument = NULL;
|
|
PFLAG_ARGUMENT CompareTimeArgument = NULL;
|
|
PFLAG_ARGUMENT WaitArgument = NULL;
|
|
PFLAG_ARGUMENT HelpArgument = NULL;
|
|
|
|
BOOLEAN HelpSwitch;
|
|
|
|
|
|
|
|
VOID
|
|
REPLACE::SetArguments(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the arguments for the Replace utility
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Allocate things
|
|
//
|
|
if (//
|
|
// Get the argument patterns
|
|
//
|
|
!_AddPattern.Initialize( (LPWSTR)L"/A" ) ||
|
|
!_PromptPattern.Initialize( (LPWSTR)L"/P" ) ||
|
|
!_ReadOnlyPattern.Initialize( (LPWSTR)L"/R" ) ||
|
|
!_SubdirPattern.Initialize( (LPWSTR)L"/S" ) ||
|
|
!_CompareTimePattern.Initialize( (LPWSTR)L"/U" ) ||
|
|
!_WaitPattern.Initialize( (LPWSTR)L"/W" ) ||
|
|
!_HelpPattern.Initialize( (LPWSTR)L"/?" ) ||
|
|
|
|
//
|
|
// Get our parsing preferences
|
|
//
|
|
!_Switches.Initialize( (LPWSTR)L"/-" ) ||
|
|
!_MultipleSwitch.Initialize( (LPWSTR)L"/APRSUW?" ) ||
|
|
|
|
//
|
|
// Create the arguments
|
|
//
|
|
((SourcePathArgument = NEW PATH_ARGUMENT) == NULL ) ||
|
|
((DestinationPathArgument = NEW PATH_ARGUMENT) == NULL ) ||
|
|
((AddArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((PromptArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((ReadOnlyArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((SubdirArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((CompareTimeArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((WaitArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
|
((HelpArgument = NEW FLAG_ARGUMENT) == NULL )
|
|
) {
|
|
|
|
DisplayMessageAndExit ( REPLACE_ERROR_NO_MEMORY,
|
|
NULL,
|
|
EXIT_NO_MEMORY );
|
|
}
|
|
|
|
|
|
//
|
|
// Parse the arguments
|
|
//
|
|
GetArgumentsCmd();
|
|
|
|
//
|
|
// Verify the arguments
|
|
//
|
|
CheckArgumentConsistency();
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
DELETE( SourcePathArgument );
|
|
DELETE( DestinationPathArgument );
|
|
DELETE( AddArgument );
|
|
DELETE( PromptArgument );
|
|
DELETE( ReadOnlyArgument );
|
|
DELETE( SubdirArgument );
|
|
DELETE( CompareTimeArgument );
|
|
DELETE( WaitArgument );
|
|
DELETE( HelpArgument );
|
|
}
|
|
|
|
VOID
|
|
REPLACE::GetArgumentsCmd(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the arguments from the Command line
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ARRAY ArgArray;
|
|
PATH_ARGUMENT ProgramNameArgument;
|
|
DSTRING CmdLine;
|
|
|
|
//
|
|
// Prepare for parsing
|
|
//
|
|
if (//
|
|
// Initialize the arguments
|
|
//
|
|
!(CmdLine.Initialize( GetCommandLine() )) ||
|
|
!(ArgArray.Initialize( 10, 10 )) ||
|
|
!(ProgramNameArgument.Initialize( MATCH_ALL_PATTERN )) ||
|
|
!(SourcePathArgument->Initialize( MATCH_ALL_PATTERN, FALSE)) ||
|
|
!(DestinationPathArgument->Initialize( MATCH_ALL_PATTERN, TRUE )) ||
|
|
!(AddArgument->Initialize( &_AddPattern )) ||
|
|
!(PromptArgument->Initialize( &_PromptPattern )) ||
|
|
!(ReadOnlyArgument->Initialize( &_ReadOnlyPattern )) ||
|
|
!(SubdirArgument->Initialize( &_SubdirPattern )) ||
|
|
!(CompareTimeArgument->Initialize( &_CompareTimePattern )) ||
|
|
!(WaitArgument->Initialize( &_WaitPattern )) ||
|
|
!(HelpArgument->Initialize( &_HelpPattern )) ||
|
|
|
|
//
|
|
// Put the arguments in the argument array
|
|
//
|
|
!(ArgArray.Put( &ProgramNameArgument )) ||
|
|
!(ArgArray.Put( AddArgument )) ||
|
|
!(ArgArray.Put( PromptArgument )) ||
|
|
!(ArgArray.Put( ReadOnlyArgument )) ||
|
|
!(ArgArray.Put( SubdirArgument )) ||
|
|
!(ArgArray.Put( CompareTimeArgument )) ||
|
|
!(ArgArray.Put( WaitArgument )) ||
|
|
!(ArgArray.Put( HelpArgument )) ||
|
|
!(ArgArray.Put( SourcePathArgument )) ||
|
|
!(ArgArray.Put( DestinationPathArgument ))
|
|
) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
|
NULL,
|
|
EXIT_NO_MEMORY );
|
|
}
|
|
|
|
//
|
|
// Parse the arguments
|
|
//
|
|
ParseArguments( &CmdLine, &ArgArray );
|
|
|
|
//
|
|
// Set the switches
|
|
//
|
|
_AddSwitch = AddArgument->QueryFlag();
|
|
_PromptSwitch = PromptArgument->QueryFlag();
|
|
_ReadOnlySwitch = ReadOnlyArgument->QueryFlag();
|
|
_SubdirSwitch = SubdirArgument->QueryFlag();
|
|
_CompareTimeSwitch = CompareTimeArgument->QueryFlag();
|
|
_WaitSwitch = WaitArgument->QueryFlag();
|
|
HelpSwitch = HelpArgument->QueryFlag();
|
|
|
|
//
|
|
// Set the source and destination paths.
|
|
//
|
|
if ( SourcePathArgument->IsValueSet() ) {
|
|
if ((_SourcePath = SourcePathArgument->GetPath()->QueryPath()) == NULL ) {
|
|
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
|
|
}
|
|
} else {
|
|
_SourcePath = NULL;
|
|
}
|
|
|
|
if ( DestinationPathArgument->IsValueSet() ) {
|
|
if ((_DestinationPath = DestinationPathArgument->GetPath()->QueryFullPath()) == NULL ) {
|
|
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
|
|
}
|
|
} else {
|
|
_DestinationPath = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
REPLACE::ParseArguments(
|
|
IN PWSTRING CmdLine,
|
|
OUT PARRAY ArgArray
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parses a group of arguments
|
|
|
|
Arguments:
|
|
|
|
CmdLine - Supplies pointer to a command line to parse
|
|
ArgArray - Supplies pointer to array of arguments
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
ARGUMENT_LEXEMIZER ArgLex;
|
|
ARRAY LexArray;
|
|
|
|
//
|
|
// Initialize lexeme array and the lexemizer.
|
|
//
|
|
if ( !(LexArray.Initialize( 8, 8 )) ||
|
|
!(ArgLex.Initialize( &LexArray )) ) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
|
NULL,
|
|
EXIT_NO_MEMORY );
|
|
|
|
}
|
|
|
|
//
|
|
// Set our parsing preferences
|
|
//
|
|
ArgLex.PutMultipleSwitch( &_MultipleSwitch );
|
|
ArgLex.PutSwitches( &_Switches );
|
|
ArgLex.SetCaseSensitive( FALSE );
|
|
ArgLex.PutSeparators( " /\t" );
|
|
ArgLex.PutStartQuotes( "\"" );
|
|
ArgLex.PutEndQuotes( "\"" );
|
|
|
|
|
|
//
|
|
// Parse the arguments
|
|
//
|
|
if ( !(ArgLex.PrepareToParse( CmdLine ))) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_PARSE,
|
|
NULL,
|
|
EXIT_COMMAND_LINE_ERROR );
|
|
|
|
}
|
|
|
|
if ( !ArgLex.DoParsing( ArgArray ) ) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_INVALID_SWITCH,
|
|
ArgLex.QueryInvalidArgument(),
|
|
EXIT_COMMAND_LINE_ERROR );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
VOID
|
|
REPLACE::CheckArgumentConsistency (
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks the consistency of the arguments
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PFSN_FILE File = NULL;
|
|
|
|
if ( HelpSwitch ) {
|
|
//
|
|
// Help requested
|
|
//
|
|
Usage();
|
|
}
|
|
|
|
|
|
//
|
|
// Make sure that we have a source path
|
|
//
|
|
if ( _SourcePath == NULL ) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_SOURCE_PATH_REQUIRED,
|
|
NULL,
|
|
EXIT_COMMAND_LINE_ERROR );
|
|
}
|
|
|
|
//
|
|
// The add switch cannot be specified together with the Subdir or the
|
|
// CompareTime switch.
|
|
//
|
|
if ( _AddSwitch && (_SubdirSwitch || _CompareTimeSwitch)) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_INVALID_PARAMETER_COMBINATION,
|
|
NULL,
|
|
EXIT_COMMAND_LINE_ERROR );
|
|
|
|
}
|
|
|
|
//
|
|
// If destination path is null, then the destination path is the
|
|
// current directory
|
|
//
|
|
if ( _DestinationPath == NULL ) {
|
|
|
|
if ( ((_DestinationPath = NEW PATH) == NULL ) ||
|
|
!_DestinationPath->Initialize( CURRENT_DIRECTORY, TRUE ) ) {
|
|
|
|
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
|
NULL,
|
|
EXIT_NO_MEMORY );
|
|
}
|
|
} else if ( (_DestinationPath->HasWildCard()) ||
|
|
((File = SYSTEM::QueryFile( _DestinationPath )) != NULL) ) {
|
|
DisplayMessageAndExit( REPLACE_ERROR_PATH_NOT_FOUND,
|
|
_DestinationPath->GetPathString(),
|
|
EXIT_PATH_NOT_FOUND );
|
|
}
|
|
|
|
DELETE( File );
|
|
}
|