158 lines
4.2 KiB
C++
158 lines
4.2 KiB
C++
|
|
#include "../../include/kfile/KPackingFileMaker.h"
|
|
#include "../../include/kfile/KFileNameCipher.h"
|
|
#include "../../include/toolkit/XFileUtil.h"
|
|
#include "../../include/compress/XZip.h"
|
|
|
|
|
|
KPackingFileMaker::KPackingFileMaker( KPackingFileSystem* pPackingFS )
|
|
: m_pPackingFS( pPackingFS )
|
|
, m_destDataFileInfo( NULL )
|
|
, m_nDataFileCount( 0 )
|
|
{
|
|
m_destDataFileInfo = new sDataFileInfo[pPackingFS->GetDataFileCount()];
|
|
m_nDataFileCount = pPackingFS->GetDataFileCount();
|
|
}
|
|
|
|
KPackingFileMaker::~KPackingFileMaker()
|
|
{
|
|
close();
|
|
}
|
|
|
|
void KPackingFileMaker::close()
|
|
{
|
|
if( m_destDataFileInfo != NULL )
|
|
{
|
|
for( int i = 0; i < m_nDataFileCount; ++i )
|
|
{
|
|
m_destDataFileInfo[i].close();
|
|
}
|
|
|
|
delete [] m_destDataFileInfo;
|
|
m_destDataFileInfo = NULL;
|
|
|
|
m_nDataFileCount = 0;
|
|
}
|
|
|
|
m_destIndexFileList.clear();
|
|
}
|
|
|
|
KPackingFileMaker::sDataFileInfo* KPackingFileMaker::getDataFileInfo( size_t hash_key )
|
|
{
|
|
if( static_cast< int >( hash_key ) < m_nDataFileCount )
|
|
{
|
|
return &m_destDataFileInfo[hash_key];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool KPackingFileMaker::packingFile( const char *szFileName, const char* pBuffer, size_t size, bool bCompress )
|
|
{
|
|
std::string strEncodedFileName = szFileName;
|
|
std::string strFileName = strEncodedFileName;
|
|
std::string strExtension;
|
|
|
|
if( KFileNameCipher::IsEncodedName( strEncodedFileName ) ) //<= "Win98sUpdateUtil.exe" 제대로 체크 안된다.
|
|
KFileNameCipher::DecodeFileName( strFileName );
|
|
else
|
|
KFileNameCipher::EncodeFileName( strEncodedFileName );
|
|
|
|
XFileUtil::GetFileName( strFileName.c_str(), strFileName );
|
|
XFileUtil::GetFileExtension( strFileName.c_str(), strExtension );
|
|
|
|
//
|
|
size_t hash_key = KPackingFileSystem::getFileHashKey( strEncodedFileName.c_str(), m_nDataFileCount );
|
|
sDataFileInfo* d_info = getDataFileInfo( hash_key );
|
|
if( d_info->m_file == NULL )
|
|
{
|
|
std::string dataFileName = KPackingFileSystem::getDataFileName( m_pPackingFS->GetDataFileName().c_str(), hash_key ) + ".new";
|
|
if( !d_info->create( dataFileName.c_str() ) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
size_t oldOffset = 0;
|
|
if( (size >= KFileSystem::MIN_COMPRESS_FILE_SIZE) && (bCompress == true) )
|
|
{
|
|
size_t xzipBufferSize = XZip::GetBufferSize( size );
|
|
char* xzipBuffer = new char[xzipBufferSize];
|
|
|
|
size_t compressSize = XZip::Compress( pBuffer, size, xzipBuffer, xzipBufferSize );
|
|
|
|
// 압축되지 않고 팩킹된 파일을 여러번 repacking할 때 compressSize < size를 하면 bIsNeedXOR 때문에 문제가 될수 있다
|
|
if( compressSize < size )
|
|
{
|
|
if( d_info->write( xzipBuffer, compressSize, &oldOffset ) == false )
|
|
{
|
|
delete [] xzipBuffer;
|
|
return false;
|
|
}
|
|
|
|
KPackingFileSystem::KFileInfo kFileInfo( strEncodedFileName.c_str(), compressSize, oldOffset, hash_key );
|
|
m_destIndexFileList.push_back( kFileInfo );
|
|
}
|
|
else
|
|
{
|
|
if( d_info->write( pBuffer, size, &oldOffset ) == false )
|
|
{
|
|
delete [] xzipBuffer;
|
|
return false;
|
|
}
|
|
|
|
KPackingFileSystem::KFileInfo kFileInfo( strEncodedFileName.c_str(), size, oldOffset, hash_key );
|
|
m_destIndexFileList.push_back( kFileInfo );
|
|
}
|
|
|
|
delete [] xzipBuffer;
|
|
}
|
|
else
|
|
{
|
|
if( d_info->write( pBuffer, size, &oldOffset ) == false )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
KPackingFileSystem::KFileInfo kFileInfo( strEncodedFileName.c_str(), size, oldOffset, hash_key );
|
|
m_destIndexFileList.push_back( kFileInfo );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool KPackingFileMaker::saveIndexFile()
|
|
{
|
|
std::string strNewIndexFile = std::string( m_pPackingFS->GetIndexFileName() ) + ".new";
|
|
|
|
SetFileAttributes( strNewIndexFile.c_str(), FILE_ATTRIBUTE_NORMAL );
|
|
DeleteFile( strNewIndexFile.c_str() );
|
|
|
|
KHFILE pFile;
|
|
pFile = ::CreateFile( strNewIndexFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
|
|
if ( !IsValidKHFile( pFile) )
|
|
{
|
|
assert( 0 );
|
|
return false;
|
|
}
|
|
|
|
int seed = 0;
|
|
std::vector< KPackingFileSystem::KFileInfo >::const_iterator pos = m_destIndexFileList.begin();
|
|
std::vector< KPackingFileSystem::KFileInfo >::const_iterator end = m_destIndexFileList.end();
|
|
|
|
for( ; pos != end; ++pos )
|
|
{
|
|
const KPackingFileSystem::KFileInfo& info = (*pos);
|
|
if( info.saveFileInfo( pFile, &seed ) == false )
|
|
{
|
|
CloseHandle( pFile );
|
|
DeleteFile( strNewIndexFile.c_str() );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
FlushFileBuffers( pFile );
|
|
CloseHandle( pFile );
|
|
return true;
|
|
}
|