mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,416 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// FILEIO.CPP
|
||||
//
|
||||
// File I/O Service Routines
|
||||
//=====================================================================================//
|
||||
#include "vxconsole.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SystemTimeToString
|
||||
//
|
||||
// mm/dd/yyyy hh:mm:ss am
|
||||
//-----------------------------------------------------------------------------
|
||||
char *SystemTimeToString( SYSTEMTIME *systemTime, char *buffer, int bufferSize )
|
||||
{
|
||||
char timeString[256];
|
||||
char dateString[256];
|
||||
int length;
|
||||
|
||||
GetDateFormat( LOCALE_SYSTEM_DEFAULT, 0, systemTime, "MM'/'dd'/'yyyy", dateString, sizeof( dateString ) );
|
||||
GetTimeFormat( LOCALE_SYSTEM_DEFAULT, 0, systemTime, "hh':'mm':'ss tt", timeString, sizeof( timeString ) );
|
||||
length = _snprintf( buffer, bufferSize, "%s %s", dateString, timeString );
|
||||
if ( length == -1 )
|
||||
buffer[bufferSize-1] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CompareFileTimes_NTFStoFATX
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int CompareFileTimes_NTFStoFATX( FILETIME* ntfsFileTime, char *ntfsTimeString, int ntfsStringSize, FILETIME* fatxFileTime, char *fatxTimeString, int fatxStringSize )
|
||||
{
|
||||
SYSTEMTIME ntfsSystemTime;
|
||||
SYSTEMTIME fatxSystemTime;
|
||||
int diff;
|
||||
int ntfsSeconds;
|
||||
int fatxSeconds;
|
||||
|
||||
TIME_ZONE_INFORMATION tzInfo;
|
||||
GetTimeZoneInformation( &tzInfo );
|
||||
|
||||
// cannot compare UTC file times directly
|
||||
// disjoint filesystems - xbox has a +/- 2s error
|
||||
// daylight savings time handling on each file system may cause problems
|
||||
FileTimeToSystemTime( ntfsFileTime, &ntfsSystemTime );
|
||||
FileTimeToSystemTime( fatxFileTime, &fatxSystemTime );
|
||||
|
||||
// operate on local times, assumes xbox and pc are both set for same time zone and daylight saving
|
||||
SYSTEMTIME ntfsLocalTime;
|
||||
SYSTEMTIME fatxLocalTime;
|
||||
SystemTimeToTzSpecificLocalTime( &tzInfo, &ntfsSystemTime, &ntfsLocalTime );
|
||||
SystemTimeToTzSpecificLocalTime( &tzInfo, &fatxSystemTime, &fatxLocalTime );
|
||||
|
||||
if ( ntfsTimeString )
|
||||
{
|
||||
SystemTimeToString( &ntfsLocalTime, ntfsTimeString, ntfsStringSize );
|
||||
}
|
||||
|
||||
if ( fatxTimeString )
|
||||
{
|
||||
SystemTimeToString( &fatxLocalTime, fatxTimeString, fatxStringSize );
|
||||
}
|
||||
|
||||
diff = ntfsLocalTime.wYear-fatxLocalTime.wYear;
|
||||
if ( diff )
|
||||
return diff;
|
||||
|
||||
diff = ntfsLocalTime.wMonth-fatxLocalTime.wMonth;
|
||||
if ( diff )
|
||||
return diff;
|
||||
|
||||
diff = ntfsLocalTime.wDay-fatxLocalTime.wDay;
|
||||
if ( diff )
|
||||
return diff;
|
||||
|
||||
diff = ntfsLocalTime.wHour-fatxLocalTime.wHour;
|
||||
if ( diff )
|
||||
return diff;
|
||||
|
||||
// allow for +/- 3s error
|
||||
ntfsSeconds = ntfsLocalTime.wHour*60*60 + ntfsLocalTime.wMinute*60 + ntfsLocalTime.wSecond;
|
||||
fatxSeconds = fatxLocalTime.wHour*60*60 + fatxLocalTime.wMinute*60 + fatxLocalTime.wSecond;
|
||||
|
||||
diff = ntfsSeconds-fatxSeconds;
|
||||
if ( diff > 3 || diff < -3 )
|
||||
return diff;
|
||||
|
||||
// times are considered equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FreeTargetFileList
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void FreeTargetFileList( fileNode_t* pFileList )
|
||||
{
|
||||
fileNode_t *nodePtr;
|
||||
fileNode_t *nextPtr;
|
||||
|
||||
if ( !pFileList )
|
||||
return;
|
||||
|
||||
nodePtr = pFileList;
|
||||
while ( nodePtr )
|
||||
{
|
||||
nextPtr = nodePtr->nextPtr;
|
||||
|
||||
Sys_Free( nodePtr->filename );
|
||||
Sys_Free( nodePtr );
|
||||
|
||||
nodePtr = nextPtr;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetTargetFileList_r
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GetTargetFileList_r( char* targetPath, bool recurse, int attributes, int level, fileNode_t** pFileList )
|
||||
{
|
||||
HRESULT hr;
|
||||
PDM_WALK_DIR pWalkDir = NULL;
|
||||
DM_FILE_ATTRIBUTES fileAttr;
|
||||
bool valid;
|
||||
char filename[MAX_PATH];
|
||||
fileNode_t* nodePtr;
|
||||
bool bGetNormal;
|
||||
int fixedAttributes;
|
||||
|
||||
if ( !level )
|
||||
*pFileList = NULL;
|
||||
|
||||
fixedAttributes = attributes;
|
||||
if ( fixedAttributes & FILE_ATTRIBUTE_NORMAL )
|
||||
{
|
||||
fixedAttributes &= ~FILE_ATTRIBUTE_NORMAL;
|
||||
bGetNormal = true;
|
||||
}
|
||||
else
|
||||
bGetNormal = false;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
hr = DmWalkDir( &pWalkDir, targetPath, &fileAttr );
|
||||
if ( hr != XBDM_NOERR )
|
||||
break;
|
||||
|
||||
strcpy( filename, targetPath );
|
||||
Sys_AddFileSeperator( filename, sizeof( filename ) );
|
||||
strcat( filename, fileAttr.Name );
|
||||
|
||||
// restrict to desired attributes
|
||||
if ( ( bGetNormal && !fileAttr.Attributes ) || ( fileAttr.Attributes & fixedAttributes ) )
|
||||
{
|
||||
Sys_NormalizePath( filename, false );
|
||||
|
||||
// create a new file node
|
||||
nodePtr = ( fileNode_t* )Sys_Alloc( sizeof( fileNode_t ) );
|
||||
|
||||
// link it in
|
||||
nodePtr->filename = Sys_CopyString( filename );
|
||||
nodePtr->changeTime = fileAttr.ChangeTime;
|
||||
nodePtr->creationTime = fileAttr.CreationTime;
|
||||
nodePtr->sizeHigh = fileAttr.SizeHigh;
|
||||
nodePtr->sizeLow = fileAttr.SizeLow;
|
||||
nodePtr->attributes = fileAttr.Attributes;
|
||||
nodePtr->level = level;
|
||||
nodePtr->nextPtr = *pFileList;
|
||||
*pFileList = nodePtr;
|
||||
}
|
||||
|
||||
if ( fileAttr.Attributes & FILE_ATTRIBUTE_DIRECTORY )
|
||||
{
|
||||
if ( recurse )
|
||||
{
|
||||
// descend into directory
|
||||
valid = GetTargetFileList_r( filename, recurse, attributes, level+1, pFileList );
|
||||
if ( !valid )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
DmCloseDir( pWalkDir );
|
||||
|
||||
if ( hr != XBDM_ENDOFLIST )
|
||||
{
|
||||
// failure
|
||||
return false;
|
||||
}
|
||||
|
||||
// ok
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileSyncEx
|
||||
//
|
||||
// -1: failure, 0: nothing, 1: synced
|
||||
//-----------------------------------------------------------------------------
|
||||
int FileSyncEx( const char* localFilename, const char* targetFilename, int fileSyncMode, bool bVerbose, bool bNoWrite )
|
||||
{
|
||||
bool copy;
|
||||
bool pathExist;
|
||||
WIN32_FILE_ATTRIBUTE_DATA localAttributes;
|
||||
DM_FILE_ATTRIBUTES targetAttributes;
|
||||
HRESULT hr;
|
||||
int errCode;
|
||||
int deltaTime;
|
||||
char localTimeString[256];
|
||||
char targetTimeString[256];
|
||||
|
||||
if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_OFF )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !GetFileAttributesEx( localFilename, GetFileExInfoStandard, &localAttributes ) )
|
||||
{
|
||||
// failed to get the local file's attributes
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_RED, "Sync Failure: Local file %s not available\n", localFilename );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( localAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
||||
{
|
||||
// ignore directory
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( fileSyncMode & FSYNC_ANDEXISTSONTARGET )
|
||||
{
|
||||
hr = DmGetFileAttributes( targetFilename, &targetAttributes );
|
||||
if ( hr != XBDM_NOERR )
|
||||
{
|
||||
// target doesn't exist, no sync operation should commence
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, Target file %s not available\n", targetFilename );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// default success, no operation
|
||||
errCode = 0;
|
||||
|
||||
// default, create path and copy
|
||||
copy = true;
|
||||
pathExist = false;
|
||||
|
||||
if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_IFNEWER )
|
||||
{
|
||||
hr = DmGetFileAttributes( targetFilename, &targetAttributes );
|
||||
if ( hr == XBDM_NOERR )
|
||||
{
|
||||
// target path to file exists
|
||||
pathExist = true;
|
||||
|
||||
// compare times
|
||||
deltaTime = CompareFileTimes_NTFStoFATX( &localAttributes.ftLastWriteTime, localTimeString, sizeof( localTimeString), &targetAttributes.ChangeTime, targetTimeString, sizeof( targetTimeString ) );
|
||||
if ( deltaTime < 0 )
|
||||
{
|
||||
// ntfs is older, fatx is newer, no update
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, %s [%s] is newer than %s [%s]\n", targetFilename, targetTimeString, localFilename, localTimeString );
|
||||
}
|
||||
copy = false;
|
||||
}
|
||||
else if ( !deltaTime )
|
||||
{
|
||||
// equal times, compare sizes
|
||||
if ( localAttributes.nFileSizeLow == targetAttributes.SizeLow &&
|
||||
localAttributes.nFileSizeHigh == targetAttributes.SizeHigh )
|
||||
{
|
||||
// file appears synced
|
||||
copy = false;
|
||||
}
|
||||
if ( bVerbose )
|
||||
{
|
||||
if ( copy )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Update, %s [%s] [%d] has different size than %s [%s] [%d]\n", targetFilename, targetTimeString, targetAttributes.SizeLow, localFilename, localTimeString, localAttributes.nFileSizeLow );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, %s [%s] [%d] has same time and file size as %s [%s] [%d]\n", targetFilename, targetTimeString, targetAttributes.SizeLow, localFilename, localTimeString, localAttributes.nFileSizeLow );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ntfs is newer, fatx is older, update
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Update, %s [%s] is older than %s [%s]\n", targetFilename, targetTimeString, localFilename, localTimeString );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_ALWAYS )
|
||||
{
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Force Update, %s\n", targetFilename );
|
||||
}
|
||||
}
|
||||
|
||||
if ( copy && !bNoWrite )
|
||||
{
|
||||
if ( !pathExist )
|
||||
{
|
||||
CreateTargetPath( targetFilename );
|
||||
}
|
||||
|
||||
hr = DmSendFile( localFilename, targetFilename );
|
||||
if ( hr == XBDM_NOERR )
|
||||
{
|
||||
// force the target to match the local attributes
|
||||
// to ensure sync
|
||||
memset( &targetAttributes, 0, sizeof( targetAttributes ) );
|
||||
targetAttributes.SizeHigh = localAttributes.nFileSizeHigh;
|
||||
targetAttributes.SizeLow = localAttributes.nFileSizeLow;
|
||||
targetAttributes.CreationTime = localAttributes.ftCreationTime;
|
||||
targetAttributes.ChangeTime = localAttributes.ftLastWriteTime;
|
||||
DmSetFileAttributes( targetFilename, &targetAttributes );
|
||||
|
||||
// success, file copied
|
||||
errCode = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failure
|
||||
if ( bVerbose )
|
||||
{
|
||||
ConsoleWindowPrintf( XBX_CLR_RED, "Sync Failed!\n" );
|
||||
}
|
||||
errCode = -1;
|
||||
}
|
||||
|
||||
DebugCommand( "0x%8.8x = FileSyncEx( %s, %s )\n", hr, localFilename, targetFilename );
|
||||
}
|
||||
|
||||
return errCode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LoadTargetFile
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool LoadTargetFile( const char *pTargetPath, int *pFileSize, void **pData )
|
||||
{
|
||||
DM_FILE_ATTRIBUTES fileAttributes;
|
||||
HRESULT hr;
|
||||
DWORD bytesRead;
|
||||
char *pBuffer;
|
||||
|
||||
*pFileSize = 0;
|
||||
*pData = (void *)NULL;
|
||||
|
||||
hr = DmGetFileAttributes( pTargetPath, &fileAttributes );
|
||||
if ( hr != XBDM_NOERR || !fileAttributes.SizeLow )
|
||||
return false;
|
||||
|
||||
// allocate for size and terminating null
|
||||
pBuffer = (char *)Sys_Alloc( fileAttributes.SizeLow+1 );
|
||||
|
||||
hr = DmReadFilePartial( pTargetPath, 0, (LPBYTE)pBuffer, fileAttributes.SizeLow, &bytesRead );
|
||||
if ( hr != XBDM_NOERR || ( bytesRead != fileAttributes.SizeLow ) )
|
||||
{
|
||||
Sys_Free( pBuffer );
|
||||
return false;
|
||||
}
|
||||
|
||||
// add a terminating null
|
||||
pBuffer[fileAttributes.SizeLow] = '\0';
|
||||
|
||||
*pFileSize = fileAttributes.SizeLow;
|
||||
*pData = pBuffer;
|
||||
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CreateTargetPath
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CreateTargetPath( const char *pTargetFilename )
|
||||
{
|
||||
// create path chain
|
||||
char *pPath;
|
||||
char dirPath[MAX_PATH];
|
||||
|
||||
// prime and skip to first seperator
|
||||
strcpy( dirPath, pTargetFilename );
|
||||
pPath = strchr( dirPath, '\\' );
|
||||
while ( pPath )
|
||||
{
|
||||
pPath = strchr( pPath+1, '\\' );
|
||||
if ( pPath )
|
||||
{
|
||||
*pPath = '\0';
|
||||
DmMkdir( dirPath );
|
||||
*pPath = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user