mirror of https://github.com/lianthony/NT4.0
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.
268 lines
7.6 KiB
268 lines
7.6 KiB
|
|
|
|
// These must be included first:
|
|
|
|
#include <windef.h> // LPWSTR, TRUE, etc.
|
|
#include <lmcons.h> // NET_API_STATUS.
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <assert.h> // assert().
|
|
|
|
#include <client.h> // RCGlobalFsTimeResultionMs.
|
|
#undef IF_DEBUG
|
|
|
|
#include <debuglib.h> // NetlibpTrace, NETLIB_DEBUG_ equates.
|
|
#undef IF_DEBUG
|
|
|
|
#include <filefind.h> // LPREPL_FIND_HANDLE, etc.
|
|
#include <netdebug.h> // FORMAT_ equates.
|
|
#include <netlib.h> // NetpMemoryAllocate(), etc
|
|
#include <repldefs.h> // ReplCopyFile(), UNKNOWN_FS_RESOLUTION, etc.
|
|
#include <repltest.h> // FakeFindData(), ShowFileTimes(), ShowTime().
|
|
#include <stdio.h>
|
|
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS, _CRTAPI1.
|
|
#include <tstring.h> // NetpAllocWStrFromStr(), STRCPY(), etc.
|
|
|
|
|
|
enum { UNKNOWN, JUST_FILE, DIR_ITSELF, TREE } WHAT_TO_COPY;
|
|
|
|
|
|
VOID
|
|
Usage(
|
|
IN char * ProgName
|
|
)
|
|
{
|
|
(VOID) printf(
|
|
"This program copies a file or a directory, testing replicator APIs.\n"
|
|
"Author: JR (John Rogers, JohnRo@Microsoft)\n\n"
|
|
"Usage: %s [opts] src dest\n\n"
|
|
"\nWhere opts are:\n"
|
|
" -d copy directory all by itself\n"
|
|
" -f force copy over existing dest\n"
|
|
" -p pretend to copy but don't\n"
|
|
" -r copy recurvely (dirs and files)\n"
|
|
" -v verbose\n", ProgName);
|
|
}
|
|
|
|
int _CRTAPI1
|
|
main(
|
|
IN int argc,
|
|
IN char *argv[]
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
int ArgNumber;
|
|
LPWSTR Dest = NULL;
|
|
LPTSTR DestParent = NULL;
|
|
BOOL FailIfExists = TRUE;
|
|
BOOL GotPermission = FALSE;
|
|
BOOL Pretend = FALSE;
|
|
LPWSTR Source = NULL;
|
|
enum WHAT_TO_COPY CopyType = UNKNOWN;
|
|
BOOL Verbose = FALSE;
|
|
|
|
|
|
//
|
|
// Process command-line arguments.
|
|
//
|
|
for (ArgNumber = 1; ArgNumber < argc; ArgNumber++) {
|
|
if ((*argv[ArgNumber] == '-') || (*argv[ArgNumber] == '/')) {
|
|
switch (tolower(*(argv[ArgNumber]+1))) // Process switches
|
|
{
|
|
|
|
case 'd' : // Copy directory.
|
|
if (CopyType != UNKNOWN) {
|
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
|
Usage( argv[0] );
|
|
goto Cleanup;
|
|
}
|
|
CopyType = DIR_ITSELF;
|
|
break;
|
|
|
|
case 'f' : // Force delete of existing dest.
|
|
FailIfExists = FALSE;
|
|
break;
|
|
|
|
case 'p' : // Pretend to copy but don't (to test other stuff)
|
|
Pretend = TRUE;
|
|
break;
|
|
|
|
case 'r' : // Recursive copy.
|
|
if (CopyType != UNKNOWN) {
|
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
|
Usage( argv[0] );
|
|
goto Cleanup;
|
|
}
|
|
CopyType = TREE;
|
|
break;
|
|
|
|
case 'v' :
|
|
NetlibpTrace = NETLIB_DEBUG_ALL;
|
|
ReplGlobalTrace = REPL_DEBUG_ALL;
|
|
Verbose = TRUE;
|
|
break;
|
|
|
|
default :
|
|
Usage( argv[0] );
|
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
} else { // Must be a file name.
|
|
if (Source == NULL) {
|
|
Source = NetpAllocWStrFromStr(argv[ArgNumber]);
|
|
assert( Source != NULL );
|
|
} else if (Dest == NULL) {
|
|
Dest = NetpAllocWStrFromStr(argv[ArgNumber]);
|
|
assert( Dest != NULL );
|
|
} else {
|
|
Usage( argv[0] ); // Too many file names.
|
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CopyType == UNKNOWN) {
|
|
CopyType = JUST_FILE;
|
|
}
|
|
|
|
if ( (Source==NULL) || (Dest==NULL) || (CopyType==UNKNOWN) ) {
|
|
Usage( argv[0] );
|
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get fs resolution using some absolute directory name on import side.
|
|
//
|
|
DestParent = NetpMemoryAllocate(
|
|
STRSIZE(Dest) + STRSIZE( (LPTSTR) TEXT("\\..") ) );
|
|
assert( DestParent != NULL );
|
|
if (Dest[1] == TCHAR_COLON) {
|
|
DestParent[0] = Dest[0]; // drive letter.
|
|
DestParent[1] = TCHAR_COLON;
|
|
DestParent[2] = TCHAR_BACKSLASH;
|
|
DestParent[3] = TCHAR_EOS;
|
|
} else {
|
|
(VOID) STRCPY(
|
|
DestParent, // dest
|
|
Dest ); // src
|
|
(VOID) STRCAT(
|
|
DestParent, // dest
|
|
(LPTSTR) TEXT("\\..") ); // src
|
|
}
|
|
RCGlobalFsTimeResolutionSecs =
|
|
ReplGetFsTimeResolutionSecs( DestParent );
|
|
|
|
assert( RCGlobalFsTimeResolutionSecs != UNKNOWN_FS_RESOLUTION );
|
|
|
|
//
|
|
// Init and enable the backup/restore permissions in our process token.
|
|
//
|
|
ApiStatus = ReplInitBackupPermission();
|
|
(VOID) printf( "Back from ReplInitBackupPermission, status "
|
|
FORMAT_API_STATUS ".\n", ApiStatus );
|
|
|
|
ApiStatus = ReplEnableBackupPermission();
|
|
(VOID) printf( "Back from ReplEnableBackupPermission, status "
|
|
FORMAT_API_STATUS ".\n", ApiStatus );
|
|
|
|
GotPermission = TRUE;
|
|
|
|
//
|
|
// Copy the file, directory, or tree (unless we're pretending to copy).
|
|
//
|
|
if ( !Pretend ) {
|
|
if (CopyType==JUST_FILE) {
|
|
ApiStatus = ReplCopyFile(
|
|
Source,
|
|
Dest,
|
|
FailIfExists );
|
|
} else if (CopyType==DIR_ITSELF) {
|
|
ApiStatus = ReplCopyDirectoryItself(
|
|
Source,
|
|
Dest,
|
|
FailIfExists );
|
|
} else {
|
|
assert( CopyType==TREE );
|
|
ApiStatus = ReplCopyTree(
|
|
Source,
|
|
Dest );
|
|
}
|
|
|
|
(VOID) printf(
|
|
FORMAT_LPWSTR " => " FORMAT_LPWSTR ": " FORMAT_API_STATUS ".\n",
|
|
Source, Dest, ApiStatus );
|
|
|
|
} else {
|
|
(VOID) printf(
|
|
"PRETENDING TO COPY "
|
|
FORMAT_LPWSTR " => " FORMAT_LPWSTR ".\n",
|
|
Source, Dest );
|
|
|
|
// Pretend to get good status from copy.
|
|
ApiStatus = NO_ERROR;
|
|
}
|
|
|
|
if (CopyType==JUST_FILE) {
|
|
REPL_WIN32_FIND_DATA DestFindData;
|
|
REPL_WIN32_FIND_DATA SourceFindData;
|
|
|
|
//
|
|
// Print resulting times.
|
|
//
|
|
FakeFindData(
|
|
Dest, // file name
|
|
Verbose,
|
|
&DestFindData
|
|
);
|
|
FakeFindData(
|
|
Source, // file name
|
|
Verbose,
|
|
&SourceFindData
|
|
);
|
|
if (Verbose) {
|
|
ShowTime(
|
|
"Source times",
|
|
&( SourceFindData.fdFound.ftLastWriteTime ) );
|
|
|
|
ShowTime(
|
|
"Dest times ",
|
|
&( DestFindData.fdFound.ftLastWriteTime ) );
|
|
}
|
|
|
|
//
|
|
// Make sure file time is close enough.
|
|
//
|
|
if ( !ReplIsFileTimeCloseEnough(
|
|
&SourceFindData.fdFound.ftLastWriteTime,
|
|
&DestFindData.fdFound.ftLastWriteTime) ) {
|
|
|
|
(VOID) printf("***** FILE TIMES (AFTER COPY) NOT CLOSE ENOUGH!\n");
|
|
}
|
|
}
|
|
|
|
// BUGBUG; // make sure checksums match.
|
|
|
|
|
|
Cleanup:
|
|
if (Dest != NULL) {
|
|
NetpMemoryFree( Dest );
|
|
}
|
|
if (DestParent != NULL) {
|
|
NetpMemoryFree( DestParent );
|
|
}
|
|
if (GotPermission) {
|
|
(VOID) ReplDisableBackupPermission();
|
|
}
|
|
if (Source != NULL) {
|
|
NetpMemoryFree( Source );
|
|
}
|
|
|
|
if (ApiStatus == NO_ERROR) {
|
|
return (EXIT_SUCCESS);
|
|
} else {
|
|
return (EXIT_FAILURE);
|
|
}
|
|
}
|