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.

298 lines
10 KiB

  1. //===== Copyright � 1996-2011, Valve Corporation, All rights reserved. ======//
  2. #include "ps3_saveutil_v2.h"
  3. #include "memdbgon.h"
  4. #include <vjobs/jobparams_shared.h>
  5. #include <vjobs/root.h>
  6. #include <ps3/vjobutils.h>
  7. class CSaveUtilV2Job_Load : public ISaveUtilV2Job
  8. {
  9. public: // Job entry point
  10. virtual JobStatus_t DoExecute();
  11. public: // Data passed from main thread
  12. char m_chFileName[VALVE_CONTAINER_FILENAME_LEN];
  13. char m_chFullPathOut[MAX_PATH];
  14. bool m_bForCloud;
  15. public: // Data resolved from the main thread
  16. CSaveUtilV2ContainerTOC::TocEntry_t *m_pTocEntry;
  17. int m_nSubFileIndex;
  18. job_zlibinflate::JobDescriptor_t * m_pJobInflate;
  19. protected: // Data used for loading file contents
  20. CUtlBuffer m_bufScratch;
  21. int WriteFile( char const *szFile );
  22. protected: // Stat callback
  23. virtual void DoDataStatCallback( SONY_SAVEUTIL_STAT_PARAMS );
  24. protected: // Load and write to disk
  25. void DoDataFile_LoadToBuffer( SONY_SAVEUTIL_FILE_PARAMS );
  26. void DoDataFile_WriteToDisk( SONY_SAVEUTIL_FILE_PARAMS );
  27. };
  28. //////////////////////////////////////////////////////////////////////////
  29. void SaveUtilV2_Load( CPS3SaveRestoreAsyncStatus *pAsync, const char *pFilename, const char *pDestFullPath )
  30. {
  31. if ( !SaveUtilV2_CanStartJob() )
  32. return;
  33. // Find the file that the caller wants
  34. int nSubFileIndex = -1;
  35. int k = g_SaveUtilV2TOC.FindByEmbeddedFileName( pFilename, &nSubFileIndex );
  36. if ( ( nSubFileIndex < 0 ) || ( k < 0 ) || ( k >= g_SaveUtilV2TOC.m_arrEntries.Count() ) )
  37. {
  38. pAsync->m_nSonyRetValue = CELL_SAVEDATA_ERROR_FAILURE;
  39. pAsync->m_bDone = 1;
  40. Warning( "ERROR: SaveUtilV2_Load: attempted to load file '%s' which doesn't exist in container!\n", pFilename );
  41. return;
  42. }
  43. // Start the job
  44. CSaveUtilV2Job_Load *pJob = new CSaveUtilV2Job_Load;
  45. V_strncpy( pJob->m_chFileName, pFilename, sizeof( pJob->m_chFileName ) );
  46. pJob->m_bForCloud = false;
  47. switch ( pDestFullPath[0] )
  48. {
  49. case '@':
  50. pJob->m_bForCloud = true;
  51. ++ pDestFullPath;
  52. break;
  53. }
  54. V_strncpy( pJob->m_chFullPathOut, pDestFullPath, sizeof( pJob->m_chFullPathOut ) );
  55. pJob->m_pTocEntry = &g_SaveUtilV2TOC.m_arrEntries[k].m_entry;
  56. pJob->m_nSubFileIndex = nSubFileIndex;
  57. SaveUtilV2_EnqueueJob( pAsync, pJob );
  58. }
  59. //////////////////////////////////////////////////////////////////////////
  60. JobStatus_t CSaveUtilV2Job_Load::DoExecute()
  61. {
  62. float flTimeStamp = Plat_FloatTime();
  63. Msg( "CSaveUtilV2Job_Load @%.3f\n", flTimeStamp );
  64. // Allocate required buffer
  65. if ( m_bForCloud )
  66. {
  67. int numBytesRequired = sizeof( CSaveUtilV2ContainerTOC::TocStorageReserved_t );
  68. for ( int iPart = 0; iPart < VALVE_CONTAINER_FPARTS; ++ iPart )
  69. numBytesRequired += m_pTocEntry->m_numBytesFile[iPart];
  70. m_bufScratch.EnsureCapacity( numBytesRequired );
  71. }
  72. else
  73. {
  74. m_bufScratch.EnsureCapacity( m_pTocEntry->m_numBytesFile[m_nSubFileIndex] + m_pTocEntry->m_numBytesDecompressedFile[m_nSubFileIndex] );
  75. }
  76. m_pJobInflate = NewJob128( *g_saveUtilVjobInstance.m_pRoot->m_pJobZlibInflate );
  77. m_pJobInflate->header.sizeScratch = ( 16 * 1024 ) / 16 ;
  78. // Call saveutil
  79. int retv = cellSaveDataAutoSave2(
  80. CELL_SAVEDATA_VERSION_CURRENT,
  81. g_pszSaveUtilContainerName,
  82. CELL_SAVEDATA_ERRDIALOG_NONE,
  83. &m_SaveDirInfo,
  84. csDataStatCallback,
  85. csDataFileCallback,
  86. SYS_MEMORY_CONTAINER_ID_INVALID,
  87. this );
  88. DeleteJob( m_pJobInflate );
  89. float flEndTimeStamp = Plat_FloatTime();
  90. Msg( "CSaveUtilV2Job_Load: cellSaveDataAutoSave2 returned %x @%.3f ( total time = %.3f sec )\n", retv, flEndTimeStamp, flEndTimeStamp - flTimeStamp );
  91. return SaveUtilV2_JobDone( retv );
  92. }
  93. void CSaveUtilV2Job_Load::DoDataStatCallback( SONY_SAVEUTIL_STAT_PARAMS )
  94. {
  95. Msg( "CSaveUtilV2Job_Load::DoDataStatCallback @%.3f\n", Plat_FloatTime() );
  96. SetDataFileCallback( &CSaveUtilV2Job_Load::DoDataFile_LoadToBuffer );
  97. cbResult->result = CELL_SAVEDATA_CBRESULT_OK_NEXT;
  98. }
  99. void CSaveUtilV2Job_Load::DoDataFile_LoadToBuffer( SONY_SAVEUTIL_FILE_PARAMS )
  100. {
  101. Msg( "CSaveUtilV2Job_Load::DoDataFile_LoadToBuffer @%.3f\n", Plat_FloatTime() );
  102. // Load the file contents
  103. set->fileOperation = CELL_SAVEDATA_FILEOP_READ;
  104. set->fileName = m_pTocEntry->m_chContainerName;
  105. set->fileType = CELL_SAVEDATA_FILETYPE_SECUREFILE;
  106. memcpy( set->secureFileId, g_pszSaveUtilSecureFileId, CELL_SAVEDATA_SECUREFILEID_SIZE );
  107. set->reserved = NULL;
  108. set->fileOffset = CSaveUtilV2ContainerTOC::kStorageCapacity;
  109. if ( m_bForCloud )
  110. {
  111. set->fileSize = 0;
  112. for ( int iPart = 0; iPart < VALVE_CONTAINER_FPARTS; ++ iPart )
  113. set->fileSize += m_pTocEntry->m_numBytesFile[iPart];
  114. m_bufScratch.SeekPut( CUtlBuffer::SEEK_HEAD, sizeof( CSaveUtilV2ContainerTOC::TocStorageReserved_t ) + set->fileSize );
  115. set->fileBuf = ( ( uint8 * ) m_bufScratch.Base() ) + sizeof( CSaveUtilV2ContainerTOC::TocStorageReserved_t );
  116. set->fileBufSize = m_bufScratch.Size() - sizeof( CSaveUtilV2ContainerTOC::TocStorageReserved_t );
  117. }
  118. else
  119. {
  120. for ( int k = 0; k < m_nSubFileIndex; ++ k )
  121. set->fileOffset += m_pTocEntry->m_numBytesFile[k];
  122. set->fileSize = m_pTocEntry->m_numBytesFile[m_nSubFileIndex];
  123. m_bufScratch.SeekPut( CUtlBuffer::SEEK_HEAD, set->fileSize );
  124. set->fileBuf = m_bufScratch.Base();
  125. set->fileBufSize = m_bufScratch.Size();
  126. }
  127. // keep reading
  128. SetDataFileCallback( &CSaveUtilV2Job_Load::DoDataFile_WriteToDisk );
  129. cbResult->result = CELL_SAVEDATA_CBRESULT_OK_NEXT;
  130. Msg( "CSaveUtilV2Job_Load::DoDataFile_LoadToBuffer will load %u bytes of '%s' from '%s'...\n", set->fileSize, m_chFileName, set->fileName );
  131. }
  132. void CSaveUtilV2Job_Load::DoDataFile_WriteToDisk( SONY_SAVEUTIL_FILE_PARAMS )
  133. {
  134. Msg( "CSaveUtilV2Job_Load::DoDataFile_WriteToDisk '%s' @%.3f\n", m_chFileName, Plat_FloatTime() );
  135. int ret = WriteFile( m_chFullPathOut );
  136. if ( ret < 0 )
  137. {
  138. Msg( "ERROR: CSaveUtilV2Job_Load::DoDataFile_WriteToDisk failed to write file to disk!\n" );
  139. g_pSaveUtilAsyncStatus->m_nSonyRetValue = CELL_SAVEDATA_ERROR_FAILURE;
  140. cbResult->result = CELL_SAVEDATA_CBRESULT_ERR_FAILURE;
  141. return;
  142. }
  143. cbResult->result = CELL_SAVEDATA_CBRESULT_OK_LAST;
  144. }
  145. int CSaveUtilV2Job_Load::WriteFile( char const *szFile )
  146. {
  147. if ( !szFile || !*szFile )
  148. return 0;
  149. float flTimeStamp = Plat_FloatTime();
  150. Msg( "CSaveUtilV2Job_Load::WriteFile : %s @%.3f\n", szFile, flTimeStamp );
  151. unsigned char *pWriteData = ( unsigned char * ) m_bufScratch.Base();
  152. unsigned int numBytesWrite = m_pTocEntry->m_numBytesFile[m_nSubFileIndex]; // the compressed size
  153. if ( m_bForCloud )
  154. {
  155. numBytesWrite = m_bufScratch.TellPut();
  156. V_memcpy( pWriteData, m_pTocEntry, sizeof( CSaveUtilV2ContainerTOC::TocStorageReserved_t ) );
  157. //
  158. // Signature
  159. //
  160. // Generate sult into filename field
  161. CSaveUtilV2ContainerTOC::TocEntry_t *pSignature = ( CSaveUtilV2ContainerTOC::TocEntry_t * ) pWriteData;
  162. for ( int isult = 0; isult < sizeof( pSignature->m_chFile[0] ); ++ isult )
  163. pSignature->m_chFile[0][isult] = ( 1 + rand() ) % 220;
  164. // Put the version of our save header
  165. V_memset( pSignature->m_chContainerName, 0, sizeof( pSignature->m_chContainerName ) );
  166. pSignature->m_chContainerName[0] = 'S';
  167. pSignature->m_chContainerName[1] = 'A';
  168. pSignature->m_chContainerName[2] = 'V';
  169. pSignature->m_chContainerName[3] = '1';
  170. // Temporarily put our cryptokey in place of hash
  171. V_memcpy( pWriteData + 8, &g_uiSteamCloudCryptoKey, sizeof( g_uiSteamCloudCryptoKey ) );
  172. uint32 uiHash = SaveUtilV2_ComputeBufferHash( pWriteData, numBytesWrite );
  173. // Store the hash
  174. for ( int isult = 0; isult < sizeof( g_uiSteamCloudCryptoKey ) - sizeof( uiHash ); ++ isult )
  175. pWriteData[8 + isult] = ( 1 + rand() ) % 220;
  176. V_memcpy( pWriteData + 8 + sizeof( g_uiSteamCloudCryptoKey ) - sizeof( uiHash ), &uiHash, sizeof( uiHash ) );
  177. }
  178. else if ( m_pTocEntry->m_numBytesDecompressedFile[m_nSubFileIndex] )
  179. {
  180. // The file is actually compressed
  181. if( g_saveUtilVjobInstance.m_pRoot )
  182. {
  183. double flStartInflateJob = Plat_FloatTime();
  184. job_zlibinflate::JobParams_t * pJobParams = job_zlibinflate::GetJobParams( m_pJobInflate );
  185. pJobParams->m_eaUncompressedOutput = pWriteData + numBytesWrite;
  186. pJobParams->m_eaCompressed = pWriteData;
  187. pJobParams->m_nCompressedSize = numBytesWrite;
  188. pJobParams->m_nExpectedUncompressedSize = m_pTocEntry->m_numBytesDecompressedFile[m_nSubFileIndex];
  189. int nError = g_saveUtilVjobInstance.m_pRoot->m_queuePortSound.pushJob( &m_pJobInflate->header, sizeof( *m_pJobInflate ), 0, CELL_SPURS_JOBQUEUE_FLAG_SYNC_JOB );
  190. if( nError != CELL_OK )
  191. {
  192. Warning("job_zlibinflate failed to push through port, error 0x%X\n", nError );
  193. return -1;
  194. }
  195. while( !pJobParams->IsDone() )
  196. {
  197. ThreadSleep( 1 );
  198. }
  199. double flEndInflateJob = Plat_FloatTime();
  200. if( pJobParams->m_nError != 0 )
  201. {
  202. Warning( "CSaveUtilV2Job_Load::WriteFile failed to uncompress!\n" );
  203. return -1;
  204. }
  205. else
  206. {
  207. Msg( "job_zlibInflate took %.3f sec : %u -> %u KiB (%.2f MiB/s)\n", flEndInflateJob - flStartInflateJob, pJobParams->m_nCompressedSize/1024, pJobParams->m_nExpectedUncompressedSize/1024, pJobParams->m_nExpectedUncompressedSize / ( 1024 * 1024 * ( flEndInflateJob - flStartInflateJob ) ) );
  208. pWriteData += numBytesWrite;
  209. numBytesWrite = m_pTocEntry->m_numBytesDecompressedFile[m_nSubFileIndex];
  210. }
  211. }
  212. else
  213. {
  214. return -1;
  215. }
  216. }
  217. int ret;
  218. int fd;
  219. ret = cellFsOpen( szFile, CELL_FS_O_CREAT | CELL_FS_O_TRUNC | CELL_FS_O_WRONLY, &fd, NULL, 0 );
  220. if ( ret < 0 )
  221. {
  222. Msg( "ERROR: CSaveUtilV2Job_Load::DoDataFile_WriteToDisk : %s : cellFsOpen failed : %d\n", szFile, ret );
  223. return ret;
  224. }
  225. uint64_t numBytesActuallyWritten = 0;
  226. ret = cellFsWrite( fd, pWriteData, numBytesWrite, &numBytesActuallyWritten );
  227. cellFsClose( fd );
  228. if ( ret < 0 )
  229. {
  230. Msg( "ERROR: CSaveUtilV2Job_Load::DoDataFile_WriteToDisk : %s : cellFsWrite failed : %d\n", szFile, ret );
  231. return ret;
  232. }
  233. if ( numBytesActuallyWritten != numBytesWrite )
  234. {
  235. Msg( "ERROR: CSaveUtilV2Job_Load::DoDataFile_WriteToDisk : %s : cellFsWrite wrote incorrect file : %ull bytes written, %d bytes expected\n",
  236. szFile, numBytesActuallyWritten, numBytesWrite );
  237. return -1;
  238. }
  239. float flEndTimeStamp = Plat_FloatTime();
  240. Msg( "CSaveUtilV2Job_Load::WriteFile finished writing %s @%.3f (%.3f sec)\n", szFile, flEndTimeStamp, flEndTimeStamp - flTimeStamp );
  241. return 0;
  242. }