Team Fortress 2 Source Code as on 22/4/2020
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.

366 lines
8.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "vmpi_filesystem_internal.h"
  9. #include "tier1/utlbuffer.h"
  10. bool g_bDisableFileAccess = false;
  11. CBaseVMPIFileSystem *g_pBaseVMPIFileSystem = NULL;
  12. IFileSystem *g_pOriginalPassThruFileSystem = NULL;
  13. void* GetVMPIFileSystem()
  14. {
  15. return (IBaseFileSystem*)g_pBaseVMPIFileSystem;
  16. }
  17. EXPOSE_INTERFACE_FN( GetVMPIFileSystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION )
  18. IFileSystem* VMPI_FileSystem_Init( int maxMemoryUsage, IFileSystem *pPassThru )
  19. {
  20. Assert( g_bUseMPI );
  21. Assert( !g_pBaseVMPIFileSystem );
  22. g_pOriginalPassThruFileSystem = pPassThru;
  23. if ( g_bMPIMaster )
  24. {
  25. extern CBaseVMPIFileSystem* CreateMasterVMPIFileSystem( int maxMemoryUsage, IFileSystem *pPassThru );
  26. CreateMasterVMPIFileSystem( maxMemoryUsage, pPassThru );
  27. }
  28. else
  29. {
  30. extern CBaseVMPIFileSystem* CreateWorkerVMPIFileSystem();
  31. CreateWorkerVMPIFileSystem();
  32. }
  33. // The Create function should have set this. Normally, we'd set g_pBaseVMPIFileSystem right here, but
  34. // the create functions may want to receive some messages, in which case they need to set g_pBaseVMPIFileSystem
  35. // so the packets get routed appropriately.
  36. Assert( g_pBaseVMPIFileSystem );
  37. return g_pBaseVMPIFileSystem;
  38. }
  39. IFileSystem* VMPI_FileSystem_Term()
  40. {
  41. if ( g_pBaseVMPIFileSystem )
  42. {
  43. g_pBaseVMPIFileSystem->Release();
  44. g_pBaseVMPIFileSystem = NULL;
  45. if ( g_iVMPIVerboseLevel >= 1 )
  46. {
  47. if ( g_bMPIMaster )
  48. Msg( "Multicast send: %dk\n", (g_nMulticastBytesSent + 511) / 1024 );
  49. else
  50. Msg( "Multicast recv: %dk\n", (g_nMulticastBytesReceived + 511) / 1024 );
  51. }
  52. }
  53. IFileSystem *pRet = g_pOriginalPassThruFileSystem;
  54. g_pOriginalPassThruFileSystem = NULL;
  55. return pRet;
  56. }
  57. void VMPI_FileSystem_DisableFileAccess()
  58. {
  59. g_bDisableFileAccess = true;
  60. }
  61. CreateInterfaceFn VMPI_FileSystem_GetFactory()
  62. {
  63. return Sys_GetFactoryThis();
  64. }
  65. void VMPI_FileSystem_CreateVirtualFile( const char *pFilename, const void *pData, unsigned long fileLength )
  66. {
  67. g_pBaseVMPIFileSystem->CreateVirtualFile( pFilename, pData, fileLength );
  68. }
  69. // Register our packet ID.
  70. bool FileSystemRecv( MessageBuffer *pBuf, int iSource, int iPacketID )
  71. {
  72. if ( g_pBaseVMPIFileSystem )
  73. return g_pBaseVMPIFileSystem->HandleFileSystemPacket( pBuf, iSource, iPacketID );
  74. else
  75. return false;
  76. }
  77. CDispatchReg g_DispatchReg_FileSystem( VMPI_PACKETID_FILESYSTEM, FileSystemRecv );
  78. // ------------------------------------------------------------------------------------------------------------------------ //
  79. // CVMPIFile_Memory implementation.
  80. // ------------------------------------------------------------------------------------------------------------------------ //
  81. void CVMPIFile_Memory::Init( const char *pData, long len, char chMode /* = 'b' */ )
  82. {
  83. m_pData = pData;
  84. m_DataLen = len;
  85. m_iCurPos = 0;
  86. m_chMode = chMode;
  87. }
  88. void CVMPIFile_Memory::Close()
  89. {
  90. delete this;
  91. }
  92. void CVMPIFile_Memory::Seek( int pos, FileSystemSeek_t seekType )
  93. {
  94. if ( seekType == FILESYSTEM_SEEK_HEAD )
  95. m_iCurPos = pos;
  96. else if ( seekType == FILESYSTEM_SEEK_CURRENT )
  97. m_iCurPos += pos;
  98. else
  99. m_iCurPos = m_DataLen - pos;
  100. }
  101. unsigned int CVMPIFile_Memory::Tell()
  102. {
  103. return m_iCurPos;
  104. }
  105. unsigned int CVMPIFile_Memory::Size()
  106. {
  107. return m_DataLen;
  108. }
  109. void CVMPIFile_Memory::Flush()
  110. {
  111. }
  112. int CVMPIFile_Memory::Read( void* pOutput, int size )
  113. {
  114. Assert( m_iCurPos >= 0 );
  115. int nToRead = min( (int)(m_DataLen - m_iCurPos), size );
  116. if ( m_chMode != 't' )
  117. {
  118. memcpy( pOutput, &m_pData[m_iCurPos], nToRead );
  119. m_iCurPos += nToRead;
  120. return nToRead;
  121. }
  122. else
  123. {
  124. int iRead = 0;
  125. const char *pData = m_pData + m_iCurPos;
  126. int len = m_DataLen - m_iCurPos;
  127. // Perform crlf translation
  128. while ( const char *crlf = ( const char * ) memchr( pData, '\r', len ) )
  129. {
  130. int canCopy = min( size, crlf - pData );
  131. memcpy( pOutput, pData, canCopy );
  132. m_iCurPos += canCopy;
  133. pData += canCopy;
  134. len -= canCopy;
  135. iRead += canCopy;
  136. ( char * & ) pOutput += canCopy;
  137. size -= canCopy;
  138. if ( size && len )
  139. {
  140. if ( ( len > 1 ) && ( pData[1] == '\n' ) )
  141. {
  142. ++ m_iCurPos;
  143. ++ pData;
  144. -- len;
  145. }
  146. * ( char * & ) pOutput = *pData;
  147. ++ m_iCurPos;
  148. ++ pData;
  149. -- len;
  150. ++ iRead;
  151. ++ ( char * & ) pOutput;
  152. -- size;
  153. }
  154. else
  155. break;
  156. }
  157. if ( size && len )
  158. {
  159. // No crlf characters left
  160. int canCopy = min( size, len );
  161. memcpy( pOutput, pData, canCopy );
  162. m_iCurPos += canCopy;
  163. pData += canCopy;
  164. len -= canCopy;
  165. iRead += canCopy;
  166. ( char * & ) pOutput += canCopy;
  167. size -= canCopy;
  168. }
  169. return iRead;
  170. }
  171. }
  172. int CVMPIFile_Memory::Write( void const* pInput, int size )
  173. {
  174. Assert( false ); return 0;
  175. }
  176. // ------------------------------------------------------------------------------------------------------------------------ //
  177. // CBaseVMPIFileSystem implementation.
  178. // ------------------------------------------------------------------------------------------------------------------------ //
  179. CBaseVMPIFileSystem::~CBaseVMPIFileSystem()
  180. {
  181. }
  182. void CBaseVMPIFileSystem::Release()
  183. {
  184. delete this;
  185. }
  186. void CBaseVMPIFileSystem::Close( FileHandle_t file )
  187. {
  188. if ( file )
  189. ((IVMPIFile*)file)->Close();
  190. }
  191. int CBaseVMPIFileSystem::Read( void* pOutput, int size, FileHandle_t file )
  192. {
  193. return ((IVMPIFile*)file)->Read( pOutput, size );
  194. }
  195. int CBaseVMPIFileSystem::Write( void const* pInput, int size, FileHandle_t file )
  196. {
  197. return ((IVMPIFile*)file)->Write( pInput, size );
  198. }
  199. void CBaseVMPIFileSystem::Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType )
  200. {
  201. ((IVMPIFile*)file)->Seek( pos, seekType );
  202. }
  203. unsigned int CBaseVMPIFileSystem::Tell( FileHandle_t file )
  204. {
  205. return ((IVMPIFile*)file)->Tell();
  206. }
  207. unsigned int CBaseVMPIFileSystem::Size( FileHandle_t file )
  208. {
  209. return ((IVMPIFile*)file)->Size();
  210. }
  211. unsigned int CBaseVMPIFileSystem::Size( const char *pFilename, const char *pathID = 0 )
  212. {
  213. FileHandle_t hFile = Open( pFilename, "rb", NULL );
  214. if ( hFile == FILESYSTEM_INVALID_HANDLE )
  215. {
  216. return 0;
  217. }
  218. else
  219. {
  220. unsigned int ret = Size( hFile );
  221. Close( hFile );
  222. return ret;
  223. }
  224. }
  225. bool CBaseVMPIFileSystem::FileExists( const char *pFileName, const char *pPathID )
  226. {
  227. FileHandle_t hFile = Open( pFileName, "rb", NULL );
  228. if ( hFile )
  229. {
  230. Close( hFile );
  231. return true;
  232. }
  233. else
  234. {
  235. return false;
  236. }
  237. }
  238. void CBaseVMPIFileSystem::Flush( FileHandle_t file )
  239. {
  240. ((IVMPIFile*)file)->Flush();
  241. }
  242. bool CBaseVMPIFileSystem::Precache( const char* pFileName, const char *pPathID )
  243. {
  244. return false;
  245. }
  246. //-----------------------------------------------------------------------------
  247. // NOTE: This is an exact copy of code in BaseFileSystem.cpp which
  248. // has to be here because they want to call
  249. // the implementation of Open/Size/Read/Write in CBaseVMPIFileSystem
  250. //-----------------------------------------------------------------------------
  251. bool CBaseVMPIFileSystem::ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes, int nStartingByte, FSAllocFunc_t pfnAlloc )
  252. {
  253. const char *pReadFlags = "rb";
  254. if ( buf.IsText() && !buf.ContainsCRLF() )
  255. {
  256. pReadFlags = "rt";
  257. }
  258. FileHandle_t fp = Open( pFileName, buf.IsText() ? "rt" : "rb", pPath );
  259. if ( !fp )
  260. return false;
  261. int nBytesToRead = Size( fp );
  262. if ( nMaxBytes > 0 )
  263. {
  264. nBytesToRead = min( nMaxBytes, nBytesToRead );
  265. }
  266. buf.EnsureCapacity( nBytesToRead + buf.TellPut() );
  267. if ( nStartingByte != 0 )
  268. {
  269. Seek( fp, nStartingByte, FILESYSTEM_SEEK_HEAD );
  270. }
  271. int nBytesRead = Read( buf.PeekPut(), nBytesToRead, fp );
  272. buf.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead );
  273. Close( fp );
  274. return (nBytesRead != 0);
  275. }
  276. bool CBaseVMPIFileSystem::WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf )
  277. {
  278. const char *pWriteFlags = "wb";
  279. if ( buf.IsText() && !buf.ContainsCRLF() )
  280. {
  281. pWriteFlags = "wt";
  282. }
  283. FileHandle_t fp = Open( pFileName, buf.IsText() ? "wt" : "wb", pPath );
  284. if ( !fp )
  285. return false;
  286. int nBytesWritten = Write( buf.Base(), buf.TellPut(), fp );
  287. Close( fp );
  288. return (nBytesWritten != 0);
  289. }