diff options
Diffstat (limited to 'utils/xbox/vxconsole/fileio.cpp')
| -rw-r--r-- | utils/xbox/vxconsole/fileio.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/utils/xbox/vxconsole/fileio.cpp b/utils/xbox/vxconsole/fileio.cpp new file mode 100644 index 0000000..9b9ca25 --- /dev/null +++ b/utils/xbox/vxconsole/fileio.cpp @@ -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; +} |