////////////////////////////////////////////////////////////////////////// // low level function, reads directly from the file // TODO: remove all those pOSSaveReader parameter chains and make it a member, passing it along is not needed anymore void CReader::ReadDataFromFileInternal( IPlatformOS::ISaveReaderPtr& pOSSaveReader, void* pDst, uint32 numBytes ) { assert( pOSSaveReader.get() ); if (!m_errorReading) { IPlatformOS::EFileOperationCode code = pOSSaveReader->ReadBytes( pDst, numBytes ); CheckErrorFlag( code ); } }
bool CReader::CheckFileCorruption( IPlatformOS::ISaveReaderPtr& pOSSaveReader, const SFileHeader& fileHeader, uint32 totalSize ) { bool error = false; if (totalSize<=sizeof(fileHeader)) { CryWarning( VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: size check failed. savegame File corrupted! (probably not fully saved)" ); error = true; return error; } uint32 sizeToCheck = totalSize - sizeof(fileHeader); char* pBuf = new char[sizeToCheck]; pOSSaveReader->Seek( 0, IPlatformOS::ISaveReader::ESM_BEGIN ); ReadDataFromFileInternal( pOSSaveReader, pBuf, sizeToCheck ); IZLibCompressor* pZLib = GetISystem()->GetIZLibCompressor(); if (!pZLib) { SAFE_DELETE_ARRAY(pBuf); error = true; return error; } SMD5Context context; char MD5signature[SFileHeader::MD5_SIGNATURE_SIZE]; pZLib->MD5Init(&context); pZLib->MD5Update(&context, pBuf, sizeToCheck); SFileHeader tempFileHeader = fileHeader; for (uint32 i=0; i<SFileHeader::MD5_SIGNATURE_SIZE; ++i) tempFileHeader.m_MD5Signature[i] = 0; // the original signature is always calculated with this zeroed. pZLib->MD5Update(&context, (const char*)(&tempFileHeader), sizeof(tempFileHeader)); pZLib->MD5Final(&context, MD5signature); SAFE_DELETE_ARRAY( pBuf ); for (uint32 i=0; i<SFileHeader::MD5_SIGNATURE_SIZE; ++i) { if (fileHeader.m_MD5Signature[i]!=MD5signature[i]) { CryWarning( VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: md5 check failed. savegame File corrupted!" ); error = true; break; } } return error; }
bool CReader::ReadBinaryFile( const char* pFileName ) { IPlatformOS::ISaveReaderPtr pOSSaveReader = gEnv->pSystem->GetPlatformOS()->SaveGetReader( pFileName, IPlatformOS::Unknown_User ); if (!m_pZLibBuffer) m_pZLibBuffer = new uint8[ XMLCPB_ZLIB_BUFFER_SIZE ]; if (!m_pZLibCompressedBuffer) m_pZLibCompressedBuffer = new uint8[ XMLCPB_ZLIB_BUFFER_SIZE ]; m_errorReading = pOSSaveReader.get()==NULL; if (!m_errorReading) { size_t totalNumBytesInFile = 0; IPlatformOS::EFileOperationCode code = pOSSaveReader->GetNumBytes( totalNumBytesInFile ); m_totalSize = totalNumBytesInFile; CheckErrorFlag( code ); if (!m_errorReading) { SFileHeader fileHeader; pOSSaveReader->Seek( -int(sizeof(fileHeader)), IPlatformOS::ISaveReader::ESM_END ); ReadDataFromFileInternal( pOSSaveReader, &fileHeader, sizeof(fileHeader) ); #ifdef XMLCPB_CHECK_FILE_INTEGRITY m_errorReading = CheckFileCorruption( pOSSaveReader, fileHeader, m_totalSize ); #endif pOSSaveReader->Seek( 0, IPlatformOS::ISaveReader::ESM_BEGIN ); if (fileHeader.m_fileTypeCheck!=fileHeader.FILETYPECHECK) { CryWarning( VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: file type signature not correct. Savegame File corrupted!" ); m_errorReading = true; } if (!m_errorReading) { m_nodesDataSize = fileHeader.m_sizeNodes; m_numNodes = fileHeader.m_numNodes; m_buffer.ReadFromFile( *this, pOSSaveReader, fileHeader.m_sizeNodes ); m_tableTags.ReadFromFile( *this, pOSSaveReader, fileHeader.m_tags ); m_tableAttrNames.ReadFromFile( *this, pOSSaveReader, fileHeader.m_attrNames ); m_tableStrData.ReadFromFile( *this, pOSSaveReader, fileHeader.m_strData ); m_tableAttrSets.ReadFromFile( *this, pOSSaveReader, fileHeader ); CreateNodeAddressTables(); } if (!m_errorReading) { const CNodeLiveReader& root = ActivateLiveNodeFromCompact( m_numNodes - 1 ); // the last node is always the root assert( root.GetLiveId()==XMLCPB_ROOTNODE_ID ); pOSSaveReader->TouchFile(); } } pOSSaveReader->Close(); } CryLog("[LOAD GAME] --Binary saveload: reading done--"); if (m_errorReading) CryWarning( VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: while reading the file: '%s'", pFileName ); return !m_errorReading; }
bool CXmlLoadGame::Init( const char * name ) { #ifdef XML_LOADGAME_USE_COMPRESSION #if defined(XENON) || defined(PS3) CryWarning(VALIDATOR_MODULE_GAME,VALIDATOR_ERROR, "CXmlLoadGame::Init not supported yet, strings cannot grow beyond 32767 chars\n"); return false; #endif const unsigned int nFileSizeBits = GetISystem()->GetCompressedFileSize(name); const unsigned int nFileSizeBytes = nFileSizeBits / 8 + ((nFileSizeBits & 7) + 7) / 8; if (nFileSizeBytes <= 0) { return false; } char* const pXmlData = new char[nFileSizeBytes+16]; GetISystem()->ReadCompressedFile(name, pXmlData,nFileSizeBits); m_pImpl->root = GetISystem()->LoadXmlFromBuffer(pXmlData, nFileSizeBytes); delete []pXmlData; #else if (GetISystem()->GetPlatformOS()->UsePlatformSavingAPI() ) { IPlatformOS::ISaveReaderPtr pSaveReader = GetISystem()->GetPlatformOS()->SaveGetReader(name); if (!pSaveReader) { return false; } size_t nFileSize; if ((pSaveReader->GetNumBytes(nFileSize) == IPlatformOS::eFOC_Failure) || (nFileSize <= 0)) { return false; } std::vector<char> xmlData; xmlData.resize(nFileSize); if (pSaveReader->ReadBytes(&xmlData[0], nFileSize) == IPlatformOS::eFOC_Failure) { return false; } m_pImpl->root = GetISystem()->LoadXmlFromBuffer(&xmlData[0], nFileSize); } else { m_pImpl->root = GetISystem()->LoadXmlFromFile(name); } #endif if (!m_pImpl->root) return false; m_pImpl->inputFile = name; m_pImpl->metadata = m_pImpl->root->findChild("Metadata"); if (!m_pImpl->metadata) return false; return true; }