367 lines
8.0 KiB
C++
367 lines
8.0 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "vmpi_filesystem_internal.h"
|
|
#include "tier1/utlbuffer.h"
|
|
|
|
|
|
bool g_bDisableFileAccess = false;
|
|
|
|
|
|
CBaseVMPIFileSystem *g_pBaseVMPIFileSystem = NULL;
|
|
IFileSystem *g_pOriginalPassThruFileSystem = NULL;
|
|
|
|
void* GetVMPIFileSystem()
|
|
{
|
|
return (IBaseFileSystem*)g_pBaseVMPIFileSystem;
|
|
}
|
|
|
|
EXPOSE_INTERFACE_FN( GetVMPIFileSystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION )
|
|
|
|
|
|
IFileSystem* VMPI_FileSystem_Init( int maxMemoryUsage, IFileSystem *pPassThru )
|
|
{
|
|
Assert( g_bUseMPI );
|
|
Assert( !g_pBaseVMPIFileSystem );
|
|
g_pOriginalPassThruFileSystem = pPassThru;
|
|
|
|
if ( g_bMPIMaster )
|
|
{
|
|
extern CBaseVMPIFileSystem* CreateMasterVMPIFileSystem( int maxMemoryUsage, IFileSystem *pPassThru );
|
|
CreateMasterVMPIFileSystem( maxMemoryUsage, pPassThru );
|
|
}
|
|
else
|
|
{
|
|
extern CBaseVMPIFileSystem* CreateWorkerVMPIFileSystem();
|
|
CreateWorkerVMPIFileSystem();
|
|
}
|
|
|
|
// The Create function should have set this. Normally, we'd set g_pBaseVMPIFileSystem right here, but
|
|
// the create functions may want to receive some messages, in which case they need to set g_pBaseVMPIFileSystem
|
|
// so the packets get routed appropriately.
|
|
Assert( g_pBaseVMPIFileSystem );
|
|
return g_pBaseVMPIFileSystem;
|
|
}
|
|
|
|
|
|
IFileSystem* VMPI_FileSystem_Term()
|
|
{
|
|
if ( g_pBaseVMPIFileSystem )
|
|
{
|
|
g_pBaseVMPIFileSystem->Release();
|
|
g_pBaseVMPIFileSystem = NULL;
|
|
|
|
if ( g_iVMPIVerboseLevel >= 1 )
|
|
{
|
|
if ( g_bMPIMaster )
|
|
Msg( "Multicast send: %dk\n", (g_nMulticastBytesSent + 511) / 1024 );
|
|
else
|
|
Msg( "Multicast recv: %dk\n", (g_nMulticastBytesReceived + 511) / 1024 );
|
|
}
|
|
}
|
|
|
|
IFileSystem *pRet = g_pOriginalPassThruFileSystem;
|
|
g_pOriginalPassThruFileSystem = NULL;
|
|
return pRet;
|
|
}
|
|
|
|
|
|
void VMPI_FileSystem_DisableFileAccess()
|
|
{
|
|
g_bDisableFileAccess = true;
|
|
}
|
|
|
|
|
|
CreateInterfaceFn VMPI_FileSystem_GetFactory()
|
|
{
|
|
return Sys_GetFactoryThis();
|
|
}
|
|
|
|
|
|
void VMPI_FileSystem_CreateVirtualFile( const char *pFilename, const void *pData, unsigned long fileLength )
|
|
{
|
|
g_pBaseVMPIFileSystem->CreateVirtualFile( pFilename, pData, fileLength );
|
|
}
|
|
|
|
|
|
// Register our packet ID.
|
|
bool FileSystemRecv( MessageBuffer *pBuf, int iSource, int iPacketID )
|
|
{
|
|
if ( g_pBaseVMPIFileSystem )
|
|
return g_pBaseVMPIFileSystem->HandleFileSystemPacket( pBuf, iSource, iPacketID );
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
CDispatchReg g_DispatchReg_FileSystem( VMPI_PACKETID_FILESYSTEM, FileSystemRecv );
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------ //
|
|
// CVMPIFile_Memory implementation.
|
|
// ------------------------------------------------------------------------------------------------------------------------ //
|
|
|
|
void CVMPIFile_Memory::Init( const char *pData, long len, char chMode /* = 'b' */ )
|
|
{
|
|
m_pData = pData;
|
|
m_DataLen = len;
|
|
m_iCurPos = 0;
|
|
m_chMode = chMode;
|
|
}
|
|
|
|
void CVMPIFile_Memory::Close()
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
void CVMPIFile_Memory::Seek( int pos, FileSystemSeek_t seekType )
|
|
{
|
|
if ( seekType == FILESYSTEM_SEEK_HEAD )
|
|
m_iCurPos = pos;
|
|
else if ( seekType == FILESYSTEM_SEEK_CURRENT )
|
|
m_iCurPos += pos;
|
|
else
|
|
m_iCurPos = m_DataLen - pos;
|
|
}
|
|
|
|
unsigned int CVMPIFile_Memory::Tell()
|
|
{
|
|
return m_iCurPos;
|
|
}
|
|
|
|
unsigned int CVMPIFile_Memory::Size()
|
|
{
|
|
return m_DataLen;
|
|
}
|
|
|
|
void CVMPIFile_Memory::Flush()
|
|
{
|
|
}
|
|
|
|
int CVMPIFile_Memory::Read( void* pOutput, int size )
|
|
{
|
|
Assert( m_iCurPos >= 0 );
|
|
int nToRead = min( (int)(m_DataLen - m_iCurPos), size );
|
|
|
|
if ( m_chMode != 't' )
|
|
{
|
|
memcpy( pOutput, &m_pData[m_iCurPos], nToRead );
|
|
m_iCurPos += nToRead;
|
|
|
|
return nToRead;
|
|
}
|
|
else
|
|
{
|
|
int iRead = 0;
|
|
const char *pData = m_pData + m_iCurPos;
|
|
int len = m_DataLen - m_iCurPos;
|
|
|
|
// Perform crlf translation
|
|
while ( const char *crlf = ( const char * ) memchr( pData, '\r', len ) )
|
|
{
|
|
int canCopy = min( size, crlf - pData );
|
|
memcpy( pOutput, pData, canCopy );
|
|
|
|
m_iCurPos += canCopy;
|
|
pData += canCopy;
|
|
len -= canCopy;
|
|
|
|
iRead += canCopy;
|
|
( char * & ) pOutput += canCopy;
|
|
size -= canCopy;
|
|
|
|
if ( size && len )
|
|
{
|
|
if ( ( len > 1 ) && ( pData[1] == '\n' ) )
|
|
{
|
|
++ m_iCurPos;
|
|
++ pData;
|
|
-- len;
|
|
}
|
|
|
|
* ( char * & ) pOutput = *pData;
|
|
|
|
++ m_iCurPos;
|
|
++ pData;
|
|
-- len;
|
|
|
|
++ iRead;
|
|
++ ( char * & ) pOutput;
|
|
-- size;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if ( size && len )
|
|
{
|
|
// No crlf characters left
|
|
int canCopy = min( size, len );
|
|
memcpy( pOutput, pData, canCopy );
|
|
|
|
m_iCurPos += canCopy;
|
|
pData += canCopy;
|
|
len -= canCopy;
|
|
|
|
iRead += canCopy;
|
|
( char * & ) pOutput += canCopy;
|
|
size -= canCopy;
|
|
}
|
|
|
|
return iRead;
|
|
}
|
|
}
|
|
|
|
int CVMPIFile_Memory::Write( void const* pInput, int size )
|
|
{
|
|
Assert( false ); return 0;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------ //
|
|
// CBaseVMPIFileSystem implementation.
|
|
// ------------------------------------------------------------------------------------------------------------------------ //
|
|
|
|
CBaseVMPIFileSystem::~CBaseVMPIFileSystem()
|
|
{
|
|
}
|
|
|
|
|
|
void CBaseVMPIFileSystem::Release()
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
|
|
void CBaseVMPIFileSystem::Close( FileHandle_t file )
|
|
{
|
|
if ( file )
|
|
((IVMPIFile*)file)->Close();
|
|
}
|
|
|
|
int CBaseVMPIFileSystem::Read( void* pOutput, int size, FileHandle_t file )
|
|
{
|
|
return ((IVMPIFile*)file)->Read( pOutput, size );
|
|
}
|
|
|
|
int CBaseVMPIFileSystem::Write( void const* pInput, int size, FileHandle_t file )
|
|
{
|
|
return ((IVMPIFile*)file)->Write( pInput, size );
|
|
}
|
|
|
|
void CBaseVMPIFileSystem::Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType )
|
|
{
|
|
((IVMPIFile*)file)->Seek( pos, seekType );
|
|
}
|
|
|
|
unsigned int CBaseVMPIFileSystem::Tell( FileHandle_t file )
|
|
{
|
|
return ((IVMPIFile*)file)->Tell();
|
|
}
|
|
|
|
unsigned int CBaseVMPIFileSystem::Size( FileHandle_t file )
|
|
{
|
|
return ((IVMPIFile*)file)->Size();
|
|
}
|
|
|
|
unsigned int CBaseVMPIFileSystem::Size( const char *pFilename, const char *pathID = 0 )
|
|
{
|
|
FileHandle_t hFile = Open( pFilename, "rb", NULL );
|
|
if ( hFile == FILESYSTEM_INVALID_HANDLE )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int ret = Size( hFile );
|
|
Close( hFile );
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
bool CBaseVMPIFileSystem::FileExists( const char *pFileName, const char *pPathID )
|
|
{
|
|
FileHandle_t hFile = Open( pFileName, "rb", NULL );
|
|
if ( hFile )
|
|
{
|
|
Close( hFile );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CBaseVMPIFileSystem::Flush( FileHandle_t file )
|
|
{
|
|
((IVMPIFile*)file)->Flush();
|
|
}
|
|
|
|
bool CBaseVMPIFileSystem::Precache( const char* pFileName, const char *pPathID )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NOTE: This is an exact copy of code in BaseFileSystem.cpp which
|
|
// has to be here because they want to call
|
|
// the implementation of Open/Size/Read/Write in CBaseVMPIFileSystem
|
|
//-----------------------------------------------------------------------------
|
|
bool CBaseVMPIFileSystem::ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes, int nStartingByte, FSAllocFunc_t pfnAlloc )
|
|
{
|
|
const char *pReadFlags = "rb";
|
|
if ( buf.IsText() && !buf.ContainsCRLF() )
|
|
{
|
|
pReadFlags = "rt";
|
|
}
|
|
|
|
FileHandle_t fp = Open( pFileName, buf.IsText() ? "rt" : "rb", pPath );
|
|
if ( !fp )
|
|
return false;
|
|
|
|
int nBytesToRead = Size( fp );
|
|
if ( nMaxBytes > 0 )
|
|
{
|
|
nBytesToRead = min( nMaxBytes, nBytesToRead );
|
|
}
|
|
buf.EnsureCapacity( nBytesToRead + buf.TellPut() );
|
|
|
|
if ( nStartingByte != 0 )
|
|
{
|
|
Seek( fp, nStartingByte, FILESYSTEM_SEEK_HEAD );
|
|
}
|
|
|
|
int nBytesRead = Read( buf.PeekPut(), nBytesToRead, fp );
|
|
buf.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead );
|
|
|
|
Close( fp );
|
|
return (nBytesRead != 0);
|
|
}
|
|
|
|
bool CBaseVMPIFileSystem::WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf )
|
|
{
|
|
const char *pWriteFlags = "wb";
|
|
if ( buf.IsText() && !buf.ContainsCRLF() )
|
|
{
|
|
pWriteFlags = "wt";
|
|
}
|
|
|
|
FileHandle_t fp = Open( pFileName, buf.IsText() ? "wt" : "wb", pPath );
|
|
if ( !fp )
|
|
return false;
|
|
|
|
int nBytesWritten = Write( buf.Base(), buf.TellPut(), fp );
|
|
|
|
Close( fp );
|
|
return (nBytesWritten != 0);
|
|
}
|
|
|