Counter Strike : Global Offensive Source Code
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.

304 lines
9.4 KiB

  1. //===== Copyright � 1996-2006, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Filesystem abstraction for CSaveRestore - allows for storing temp save files
  4. // either in memory or on disk.
  5. //
  6. //===========================================================================//
  7. #ifdef _WIN32
  8. #include "winerror.h"
  9. #endif
  10. #include "filesystem_engine.h"
  11. #include "saverestore_filesystem.h"
  12. #include "saverestore_filesystem_passthrough.h"
  13. #include "host_saverestore.h"
  14. #include "host.h"
  15. #include "sys.h"
  16. #include "tier1/utlbuffer.h"
  17. #include "tier1/lzss.h"
  18. #include "tier1/convar.h"
  19. #include "ixboxsystem.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. #define MOD_DIR "DEFAULT_WRITE_PATH"
  23. //-----------------------------------------------------------------------------
  24. // Purpose: Implementation to execute traditional save to disk behavior
  25. //-----------------------------------------------------------------------------
  26. CSaveRestoreFileSystemPassthrough::CSaveRestoreFileSystemPassthrough() : m_iContainerOpens( 0 ) {}
  27. bool CSaveRestoreFileSystemPassthrough::FileExists( const char *pFileName, const char *pPathID )
  28. {
  29. return g_pFileSystem->FileExists( pFileName, pPathID );
  30. }
  31. void CSaveRestoreFileSystemPassthrough::RemoveFile( char const* pRelativePath, const char *pathID )
  32. {
  33. g_pFileSystem->RemoveFile( pRelativePath, pathID );
  34. }
  35. void CSaveRestoreFileSystemPassthrough::RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID )
  36. {
  37. g_pFileSystem->RenameFile( pOldPath, pNewPath, pathID );
  38. }
  39. void CSaveRestoreFileSystemPassthrough::AsyncFinishAllWrites( void )
  40. {
  41. g_pFileSystem->AsyncFinishAllWrites();
  42. }
  43. FileHandle_t CSaveRestoreFileSystemPassthrough::Open( const char *pFullName, const char *pOptions, const char *pathID )
  44. {
  45. return g_pFileSystem->OpenEx( pFullName, pOptions, FSOPEN_NEVERINPACK, pathID );
  46. }
  47. void CSaveRestoreFileSystemPassthrough::Close( FileHandle_t hSaveFile )
  48. {
  49. g_pFileSystem->Close( hSaveFile );
  50. }
  51. int CSaveRestoreFileSystemPassthrough::Read( void *pOutput, int size, FileHandle_t hFile )
  52. {
  53. return g_pFileSystem->Read( pOutput, size, hFile );
  54. }
  55. int CSaveRestoreFileSystemPassthrough::Write( void const* pInput, int size, FileHandle_t hFile )
  56. {
  57. return g_pFileSystem->Write( pInput, size, hFile );
  58. }
  59. FSAsyncStatus_t CSaveRestoreFileSystemPassthrough::AsyncWrite( const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl )
  60. {
  61. SaveMsg( "AsyncWrite (%s/%d)...\n", pFileName, nSrcBytes );
  62. return g_pFileSystem->AsyncWrite( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl );
  63. }
  64. void CSaveRestoreFileSystemPassthrough::Seek( FileHandle_t hFile, int pos, FileSystemSeek_t method )
  65. {
  66. g_pFileSystem->Seek( hFile, pos, method );
  67. }
  68. unsigned int CSaveRestoreFileSystemPassthrough::Tell( FileHandle_t hFile )
  69. {
  70. return g_pFileSystem->Tell( hFile );
  71. }
  72. unsigned int CSaveRestoreFileSystemPassthrough::Size( FileHandle_t hFile )
  73. {
  74. return g_pFileSystem->Size( hFile );
  75. }
  76. unsigned int CSaveRestoreFileSystemPassthrough::Size( const char *pFileName, const char *pPathID )
  77. {
  78. return g_pFileSystem->Size( pFileName, pPathID );
  79. }
  80. FSAsyncStatus_t CSaveRestoreFileSystemPassthrough::AsyncFinish( FSAsyncControl_t hControl, bool wait )
  81. {
  82. return g_pFileSystem->AsyncFinish( hControl, wait );
  83. }
  84. void CSaveRestoreFileSystemPassthrough::AsyncRelease( FSAsyncControl_t hControl )
  85. {
  86. g_pFileSystem->AsyncRelease( hControl );
  87. }
  88. FSAsyncStatus_t CSaveRestoreFileSystemPassthrough::AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl )
  89. {
  90. return g_pFileSystem->AsyncAppend( pFileName, pSrc, nSrcBytes, bFreeMemory, pControl );
  91. }
  92. FSAsyncStatus_t CSaveRestoreFileSystemPassthrough::AsyncAppendFile(const char *pDestFileName, const char *pSrcFileName, FSAsyncControl_t *pControl )
  93. {
  94. return g_pFileSystem->AsyncAppendFile( pDestFileName, pSrcFileName, pControl );
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Copies the contents of the save directory into a single file
  98. //-----------------------------------------------------------------------------
  99. void CSaveRestoreFileSystemPassthrough::DirectoryCopy( const char *pPath, const char *pDestFileName, bool bIsXSave )
  100. {
  101. SaveMsg( "DirectoryCopy....\n");
  102. CUtlVector<filelistelem_t> list;
  103. // force the writes to finish before trying to get the size/existence of a file
  104. // @TODO: don't need this if retain sizes for files written earlier in process
  105. SaveMsg( "DirectoryCopy: AsyncFinishAllWrites\n");
  106. g_pFileSystem->AsyncFinishAllWrites();
  107. // build the directory list
  108. char basefindfn[ MAX_PATH ];
  109. const char *findfn = Sys_FindFirstEx(pPath, MOD_DIR, basefindfn, sizeof( basefindfn ) );
  110. while ( findfn )
  111. {
  112. int index = list.AddToTail();
  113. memset( list[index].szFileName, 0, sizeof(list[index].szFileName) );
  114. Q_strncpy( list[index].szFileName, findfn, sizeof(list[index].szFileName) );
  115. findfn = Sys_FindNext( basefindfn, sizeof( basefindfn ) );
  116. }
  117. Sys_FindClose();
  118. // write the list of files to the save file
  119. char szName[MAX_PATH];
  120. for ( int i = 0; i < list.Count(); i++ )
  121. {
  122. if ( !bIsXSave )
  123. {
  124. Q_snprintf( szName, sizeof( szName ), "%s%s", saverestore->GetSaveDir(), list[i].szFileName );
  125. }
  126. else
  127. {
  128. PREPARE_XSAVE_FILENAME( XBX_GetPrimaryUserId(), szName ) "%s", list[i].szFileName );
  129. }
  130. Q_FixSlashes( szName );
  131. int fileSize = g_pFileSystem->Size( szName );
  132. if ( fileSize )
  133. {
  134. Assert( sizeof(list[i].szFileName) == MAX_PATH );
  135. SaveMsg( "DirectoryCopy: AsyncAppend %s, %s\n", szName, pDestFileName );
  136. g_pFileSystem->AsyncAppend( pDestFileName, memcpy( new char[MAX_PATH], list[i].szFileName, MAX_PATH), MAX_PATH, true ); // Filename can only be as long as a map name + extension
  137. g_pFileSystem->AsyncAppend( pDestFileName, new int(fileSize), sizeof(int), true );
  138. g_pFileSystem->AsyncAppendFile( pDestFileName, szName );
  139. }
  140. }
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose: Extracts all the files contained within pFile
  144. //-----------------------------------------------------------------------------
  145. bool CSaveRestoreFileSystemPassthrough::DirectoryExtract( FileHandle_t pFile, int fileCount, bool bIsXSave )
  146. {
  147. int fileSize;
  148. FileHandle_t pCopy;
  149. char szName[ MAX_PATH ], fileName[ MAX_PATH ];
  150. bool success = true;
  151. for ( int i = 0; i < fileCount && success; i++ )
  152. {
  153. // Filename can only be as long as a map name + extension
  154. if ( g_pSaveRestoreFileSystem->Read( fileName, MAX_PATH, pFile ) != MAX_PATH )
  155. return false;
  156. if ( g_pSaveRestoreFileSystem->Read( &fileSize, sizeof(int), pFile ) != sizeof(int) )
  157. return false;
  158. if ( !fileSize )
  159. return false;
  160. if ( !bIsXSave )
  161. {
  162. Q_snprintf( szName, sizeof( szName ), "%s%s", saverestore->GetSaveDir(), fileName );
  163. }
  164. else
  165. {
  166. PREPARE_XSAVE_FILENAME( XBX_GetPrimaryUserId(), szName ) "%s", fileName );
  167. }
  168. Q_FixSlashes( szName );
  169. pCopy = g_pSaveRestoreFileSystem->Open( szName, "wb", MOD_DIR );
  170. if ( !pCopy )
  171. return false;
  172. success = FileCopy( pCopy, pFile, fileSize );
  173. g_pSaveRestoreFileSystem->Close( pCopy );
  174. }
  175. return success;
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose: returns the number of files in the specified filter
  179. //-----------------------------------------------------------------------------
  180. int CSaveRestoreFileSystemPassthrough::DirectoryCount( const char *pPath )
  181. {
  182. int count = 0;
  183. const char *findfn = Sys_FindFirstEx( pPath, MOD_DIR, NULL, 0 );
  184. while ( findfn != NULL )
  185. {
  186. count++;
  187. findfn = Sys_FindNext(NULL, 0 );
  188. }
  189. Sys_FindClose();
  190. return count;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: Clears the save directory of all temporary files (*.hl)
  194. //-----------------------------------------------------------------------------
  195. void CSaveRestoreFileSystemPassthrough::DirectoryClear( const char *pPath, bool bIsXSave )
  196. {
  197. char const *findfn;
  198. char szPath[ MAX_PATH ];
  199. findfn = Sys_FindFirstEx( pPath, MOD_DIR, NULL, 0 );
  200. while ( findfn != NULL )
  201. {
  202. if ( !bIsXSave )
  203. {
  204. Q_snprintf( szPath, sizeof( szPath ), "%s%s", saverestore->GetSaveDir(), findfn );
  205. }
  206. else
  207. {
  208. PREPARE_XSAVE_FILENAME( XBX_GetPrimaryUserId(), szPath ) "%s", findfn );
  209. }
  210. // Delete the temporary save file
  211. g_pFileSystem->RemoveFile( szPath, MOD_DIR );
  212. // Any more save files
  213. findfn = Sys_FindNext( NULL, 0 );
  214. }
  215. Sys_FindClose();
  216. }
  217. void CSaveRestoreFileSystemPassthrough::AuditFiles( void )
  218. {
  219. Msg("Not using save-in-memory path!\n" );
  220. }
  221. bool CSaveRestoreFileSystemPassthrough::LoadFileFromDisk( const char *pFilename )
  222. {
  223. Msg("Not using save-in-memory path!\n" );
  224. return true;
  225. }
  226. bool CSaveRestoreFileSystemPassthrough::FileCopy( FileHandle_t pOutput, FileHandle_t pInput, int fileSize )
  227. {
  228. // allocate a reasonably large file copy buffer, since otherwise write performance under steam suffers
  229. char *buf = (char *)malloc(FILECOPYBUFSIZE);
  230. int size;
  231. int readSize;
  232. bool success = true;
  233. while ( fileSize > 0 )
  234. {
  235. if ( fileSize > FILECOPYBUFSIZE )
  236. size = FILECOPYBUFSIZE;
  237. else
  238. size = fileSize;
  239. if ( ( readSize = g_pSaveRestoreFileSystem->Read( buf, size, pInput ) ) < size )
  240. {
  241. Warning( "Unexpected end of file expanding save game\n" );
  242. fileSize = 0;
  243. success = false;
  244. break;
  245. }
  246. g_pSaveRestoreFileSystem->Write( buf, readSize, pOutput );
  247. fileSize -= size;
  248. }
  249. free(buf);
  250. return success;
  251. }