Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

560 lines
12 KiB

/*
* 10.25.94 Joe Holman TC-like program changed to perform
* logging ERRORs for media.
* 01.17.95 Joe Holman Every file that is copied gets NORMAL attrs.
* 02.01.95 Joe Holman Revamped algorithm and allow empty dirs
* to be copied.
*
*/
#include <direct.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <conio.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <process.h>
#include <ctype.h>
#include <windows.h>
#include <time.h>
// Forward Function Declartions...
BOOL CopyNode( char * );
void __cdecl main( int, char ** );
void MyMakeDir ( char * );
void MyCopyFile ( const char * , const char * );
ULONG numFilesCopied=0;
char gSource[MAX_PATH];
char gDest[MAX_PATH];
char realDest[MAX_PATH];
char tempdir[MAX_PATH];
char tempfile[MAX_PATH];
//int drv;
int srclen, dstlen;
FILE * logFile;
void Msg ( const char * szFormat, ... ) {
va_list vaArgs;
va_start ( vaArgs, szFormat );
vprintf ( szFormat, vaArgs );
vfprintf ( logFile, szFormat, vaArgs );
va_end ( vaArgs );
}
void Usage( void ) {
printf ( "Usage: mTC logFile src-tree dst-tree" );
exit (1);
}
char fPathChr ( int c ) {
return (char) ( c == '\\' || c == '/' );
}
void Header(argv)
char* argv[];
{
time_t t;
Msg ("\n=========== MTC =============\n");
Msg ("LogFile : %s\n",argv[1]);
Msg ("Source : %s\n",argv[2]);
Msg ("Destination: %s\n",argv[3]);
time(&t);
Msg ("Time : %s",ctime(&t));
Msg ("================================\n\n");
}
/* ExpandPath - construct a path from the root to the specified file
* correctly handling ., .. and current directory/drive references.
*
* src source path for input
* dst destination buffer
* returns TRUE if error detected
*/
ExpandPath (src, dst)
char *src, *dst;
{
LPSTR FilePart;
LPSTR p;
BOOL Ok;
Ok = (!GetFullPathName( (LPSTR) src,
(DWORD) MAX_PATH,
(LPSTR) dst,
&FilePart ));
if ( !Ok ) {
p = src + strlen( src ) - 1;
if ( *p == '.' ) {
if ( p > src ) {
p--;
if ( *p != '.' && *p != ':' && !fPathChr(*p) ) {
strcat( dst, "." );
}
}
}
}
return Ok;
}
BOOL RecurseSrcDir ( const char * gSource, const char * gDest ) {
WIN32_FIND_DATA wfd;
HANDLE fHandle;
BOOL bRC=TRUE;
ULONG gle;
char szSrc[MAX_PATH];
char szDst[MAX_PATH];
char szPath[MAX_PATH];
char szDest[MAX_PATH];
char szFind[MAX_PATH];
char szSrcFile[MAX_PATH];
char szDstFile[MAX_PATH];
// Get rid of any trailing forward slashes.
//
strcpy ( szSrc, gSource );
strcpy ( szDst, gDest );
if ( szSrc[strlen(szSrc)-1] == '\\' ) {
szSrc[strlen(szSrc)-1] = '\0';
}
if ( szDst[strlen(szDst)-1] == '\\' ) {
szDst[strlen(szDst)-1] = '\0';
}
//Msg ( "entered: szSrc = %s, szDst = %s\n", szSrc, szDst );
sprintf ( szFind, "%s\\*.*", szSrc );
fHandle = FindFirstFile ( szFind, &wfd );
if ( fHandle == INVALID_HANDLE_VALUE ) {
// An error occurred finding a directory.
//
Msg ( "ERROR R FindFirstFile FAILED, szFind = %s, GLE = %ld\n",
szFind, GetLastError() );
return (FALSE);
}
else {
// Since this is the first time finding a directory,
// go to the loops code that makes the same directory on the
// destination.
//
goto DIR_LOOP_ENTRY;
}
do {
DIR_CONTINUE:;
bRC = FindNextFile ( fHandle, &wfd );
if ( !bRC ) {
// An error occurred with FindNextFile.
//
gle = GetLastError();
if ( gle == ERROR_NO_MORE_FILES ) {
//Msg ( "ERROR_NO_MORE_FILES...\n" );
FindClose ( fHandle );
return (TRUE);
}
else {
Msg ( "ERROR R FindNextFile FAILED, GLE = %ld\n",
GetLastError() );
FindClose ( fHandle );
exit ( 1 );
}
}
else {
DIR_LOOP_ENTRY:;
// Msg ( "wfd.cFileName = %s\n", wfd.cFileName );
// If not directory, don't just continue.
//
if ( (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
sprintf ( szSrcFile, "%s\\%s", szSrc, wfd.cFileName );
sprintf ( szDstFile, "%s\\%s", szDst, wfd.cFileName );
MyCopyFile ( szSrcFile, szDstFile );
goto DIR_CONTINUE;
}
// Don't do anything with . and .. directory entries.
//
if (!strcmp ( wfd.cFileName, "." ) ||
!strcmp ( wfd.cFileName, "..") ) {
//Msg ( "Don't do anything with . or .. dirs.\n" );
goto DIR_CONTINUE;
}
// Don't do anything with HIDDEN directory entries.
//
if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
//Msg ( "Don't do anything with HIDDEN dirs.\n" );
goto DIR_CONTINUE;
}
sprintf ( szPath, "%s\\%s", szSrc, wfd.cFileName );
sprintf ( szDest, "%s\\%s", szDst, wfd.cFileName );
//Msg ( "szPath = %s\n", szPath );
//Msg ( "md szDest = %s\n", szDest );
MyMakeDir ( szDest );
// Keep recursing down the directories.
//
RecurseSrcDir ( szPath, szDest );
}
} while ( bRC );
return ( TRUE );
}
BOOL MakeCommandDir ( const char * dest ) {
char szDest[MAX_PATH];
char szLast[MAX_PATH]; // contains last directory made
char * blah;
int i;
strcpy ( szLast, dest );
// Exception case - if the specified directory is just the root, then
// just ignore this code, since the root directory exists by default.
if ( szLast[1] == ':' &&
szLast[2] == '\\' &&
szLast[3] == '\0' ) {
return ( TRUE );
}
// Clean-up any trailing slashes.
//
if ( szLast[strlen(szLast)-1] == '\\' ) {
szLast[strlen(szLast)-1] = '\0';
}
//Msg ( "MakeCommandDir, %s\n", szLast );
// Copy and skip the D:\ chars.
//
szDest[0] = szLast[0];
szDest[1] = szLast[1];
szDest[2] = szLast[2];
blah = szLast;
blah += 3;
i = 3;
while ( 1 ) {
if ( *blah == '\0' ) {
szDest[i] = *blah;
MyMakeDir ( szDest ); // make the directory...
break;
}
else if ( *blah == '\\' ) {
szDest[i] = '\0';
MyMakeDir ( szDest ); // make the directory...
szDest[i] = *blah; // now, since the dir exists, put the slash
// back in.
}
else {
szDest[i] = *blah;
}
++blah; ++i;
}
return ( TRUE );
}
void __cdecl main ( int argc, char * argv[] ) {
if ( argc != 4) {
Usage();
exit(1);
}
if ((logFile=fopen(argv[1],"a"))==NULL) {
printf("ERROR Couldn't open logFile: %s\n",argv[1]);
exit(1);
}
Header(argv);
Msg ( "%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3] );
if ( ExpandPath (argv[2], gSource) ) {
Msg ( "ERROR Invalid source: %s\n", argv[2] );
exit(1);
}
if ( ExpandPath (argv[3], gDest) ) {
Msg ( "ERROR Invalid destination: %s\n", argv[3] );
exit(1);
}
Msg ( "gSource = %s\n", gSource );
Msg ( "gDest = %s\n", gDest );
srclen = strlen (gSource);
dstlen = strlen (gDest);
if (!strcmp(gSource, gDest)) {
Msg ("ERROR gSource == gDest\n" );
exit(1);
}
// Make any destination directories specified on the command line.
//
MakeCommandDir ( gDest );
// Make the src directory structure on the destination.
//
RecurseSrcDir ( gSource, gDest );
Msg ( "\nnumFilesCopied: %ld\n", numFilesCopied );
exit(0);
}
/***************************************************************************\
MEMBER: strbscan
SYNOPSIS: Returns pointer to first character from string in set
ALGORITHM:
ARGUMENTS: const LPSTR - search string
const LPSTR - set of characters
RETURNS: LPSTR - pointer to first matching character
NOTES:
HISTORY: davegi 28-Jul-90
Rewritten from 286 MASM
KEYWORDS:
SEEALSO:
\***************************************************************************/
#include <assert.h>
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
LPSTR
strbscan (
const LPSTR pszStr,
const LPSTR pszSet
) {
assert( pszStr );
assert( pszSet );
return pszStr + strcspn( pszStr, pszSet );
}
static char szDot[] = ".";
static char szDotDot[] = "..";
static char szColon[] = ":";
static char szPathSep[] = "\\/:";
/** FindFilename - find filename in string
*
* Find last /\:-separated component in string
*
* psz pointer to string to search
*
* returns pointer to filename
*/
static char *FindFilename (char *psz)
{
char *p;
while (TRUE) {
p = strbscan (psz, szPathSep);
if (*p == 0) {
return psz;
}
psz = p + 1;
}
}
void MyCopyFile ( const char * src, const char * dst ) {
BOOL fCopy = TRUE;
BOOL bRC;
// Copy the file if the src is newer than the dst.
//
// See if the dst exists first.
//
if (_access (dst, 00) != -1 ) {
struct _stat srcbuf;
struct _stat dstbuf;
int irc;
// The dst exists, see if we need to copy the src (newer).
//
irc = _stat (src, &srcbuf);
if ( irc == -1 ) {
Msg ( "MyCopyFile ERROR stat src FAILed: %s\n", src );
}
irc = _stat (dst, &dstbuf);
if ( irc == -1 ) {
Msg ( "MyCopyFile ERROR stat dst FAILed: %s\n", dst );
}
if ( srcbuf.st_mtime <= dstbuf.st_mtime) {
// The src is NOT newer than the dst, don't copy.
fCopy = FALSE;
}
}
else {
// Dst doesn't exist. Copy the file over.
//
//Msg ( "Dst doesn't exist, so copy over: %s\n", dst );
fCopy = TRUE;
}
if ( fCopy ) {
bRC = CopyFile ( src, dst, FALSE );
if ( !bRC ) {
Msg ( "CopyFile ERROR, gle = %ld: %s >>> %s\n",
GetLastError(), src, dst );
exit ( 1 );
}
else {
BOOL b;
Msg ( "CopyFile: %s >>> %s [OK]\n", src, dst );
b = SetFileAttributes ( dst, FILE_ATTRIBUTE_NORMAL );
if ( !b ) {
Msg ( "ERROR SetFileAttributes: %s, gle() = %ld\n",
dst, GetLastError() );
}
++numFilesCopied;
}
}
}
void MyMakeDir ( char * szPath ) {
char szDirToMake[MAX_PATH];
int numChars = strlen ( szPath );
struct _stat dbuf;
// szPath is the string of the destination path.
// Currently, this assumes a local drive on the machine.
// We could change the below code to skip the first \\server\share
// names in a UNC specified path, if ever needed.
//
strcpy ( szDirToMake, szPath );
//Msg ( "szDirToMake = %s\n", szDirToMake );
if ( _stat ( szDirToMake, &dbuf) == 0 ) {
if ( dbuf.st_mode & S_IFDIR ) {
// Wanted directory exists already.
//
}
if ( dbuf.st_mode & S_IFREG ) {
// Wanted directory to make already exists as a FILE !
//
Msg ("ERROR MyMakeDir(%s) is a file already.", szDirToMake);
exit ( 1 );
}
}
else {
if ( errno == ENOENT ) {
BOOL b;
b = CreateDirectory ( szDirToMake, NULL );
if ( !b ) {
Msg ("ERROR Unable to CreateDirectory(%s), gle = %ld\n",
szDirToMake, GetLastError() );
exit(1);
}
else {
Msg ( "md %s [OK]\n", szDirToMake );
}
}
else {
Msg ( "MyMakeDir ERROR (%s) stat FAILED...\n", szDirToMake );
exit(1);
}
}
}