From b3309951c44265ff19bb769ea7edbabe50f9dfc0 Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 2 Feb 2016 10:21:42 +0100 Subject: [PATCH] Changed: Moved LZMA and 7z functions/methods in seven_zip Changed: Removed old 7z/lzma code since the library has been updated Fixed: Implemented packLZMA function to compress a file with LZMA --HG-- branch : develop --- code/ryzom/client/src/login_patch.cpp | 7 +- code/ryzom/client/src/login_patch.h | 4 - .../client/src/login_patch_seven_zip.cpp | 468 ------------------ code/ryzom/client/src/seven_zip/seven_zip.cpp | 357 +++++++++++++ code/ryzom/client/src/seven_zip/seven_zip.h | 31 ++ 5 files changed, 392 insertions(+), 475 deletions(-) delete mode 100644 code/ryzom/client/src/login_patch_seven_zip.cpp create mode 100644 code/ryzom/client/src/seven_zip/seven_zip.cpp create mode 100644 code/ryzom/client/src/seven_zip/seven_zip.h diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index c942071d0..37cbddcbd 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -54,6 +54,7 @@ #include "login.h" #include "user_agent.h" +#include "seven_zip/seven_zip.h" #ifndef RY_BG_DOWNLOADER #include "client_cfg.h" @@ -2625,7 +2626,7 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) // try to unpack the file try { - if (!CPatchManager::unpackLZMA(pPM->ClientPatchPath+lzmaFile, OutFilename+".tmp")) + if (!unpackLZMA(pPM->ClientPatchPath+lzmaFile, OutFilename+".tmp")) { // fallback to standard patch method usePatchFile = true; @@ -3087,7 +3088,7 @@ bool CPatchManager::download(const std::string& patchFullname, const std::string && patchName.substr(patchName.size() - zsStrLength) == zsStr) { std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength); - CPatchManager::unpack7Zip(patchName, outFilename); + unpack7Zip(patchName, outFilename); pPM->deleteFile(patchName); pPM->renameFile(outFilename, sourceFullname); } @@ -3449,7 +3450,7 @@ void CInstallThread::run() std::string outFilename = patchName.substr(0, patchName.size() - zsStrLength); std::string localOutFilename = CPath::standardizeDosPath(outFilename); - if ( CPatchManager::unpackLZMA(patchName, localOutFilename) ) + if ( unpackLZMA(patchName, localOutFilename) ) { pPM->deleteFile(patchName); pPM->renameFile(outFilename, sourceName); diff --git a/code/ryzom/client/src/login_patch.h b/code/ryzom/client/src/login_patch.h index 9fdf907e8..c7f0f4509 100644 --- a/code/ryzom/client/src/login_patch.h +++ b/code/ryzom/client/src/login_patch.h @@ -331,10 +331,6 @@ private: void clearDataScanLog(); static void getCorruptedFileInfo(const SFileToPatch &ftp, ucstring &sTranslate); - // utility func to decompress a monofile 7zip archive - static bool unpack7Zip(const std::string &sevenZipFile, const std::string &destFileName); - // utility func to decompress a single LZMA packed file - static bool unpackLZMA(const std::string &sevenZipFile, const std::string &destFileName); static bool downloadAndUnpack(const std::string& patchPath, const std::string& sourceFilename, const std::string& extractPath, const std::string& tmpDirectory, uint32 timestamp); // Forward message to Installation Software void onFileInstallFinished(); diff --git a/code/ryzom/client/src/login_patch_seven_zip.cpp b/code/ryzom/client/src/login_patch_seven_zip.cpp deleted file mode 100644 index 306c0607f..000000000 --- a/code/ryzom/client/src/login_patch_seven_zip.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include "stdpch.h" -#include "login_patch.h" - -#define RZ_USE_SEVENZIP 1 -#define RZ_USE_NEW_LZMA - -#ifdef RZ_USE_SEVENZIP - -#ifdef RZ_USE_NEW_LZMA - -#include "seven_zip/7z.h" -#include "seven_zip/7zAlloc.h" -#include "seven_zip/7zBuf.h" -#include "seven_zip/7zCrc.h" -#include "seven_zip/7zFile.h" -#include "seven_zip/7zVersion.h" -#include "seven_zip/LzmaDec.h" - -#else - -#include "seven_zip/7zCrc.h" -#include "seven_zip/7zIn.h" -#include "seven_zip/7zExtract.h" -#include "seven_zip/LzmaDecode.h" - -#endif - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; - - -#ifdef RZ_USE_NEW_LZMA - -/// Input stream class for 7zip archive -class CNel7ZipInStream : public ISeekInStream -{ - NLMISC::IStream *_Stream; - -public: - /// Constructor, only allow file stream because 7zip will 'seek' in the stream - CNel7ZipInStream(NLMISC::IStream *s) - : _Stream(s) - { - Read = readFunc; - Seek = seekFunc; - } - - // the read function called by 7zip to read data - static SRes readFunc(void *object, void *buffer, size_t *size) - { - try - { - CNel7ZipInStream *me = (CNel7ZipInStream*)object; - uint len = (uint)*size; - me->_Stream->serialBuffer((uint8*)buffer, len); - return SZ_OK; - } - catch (...) - { - return SZ_ERROR_READ; - } - } - - // the seek function called by seven zip to seek inside stream - static SRes seekFunc(void *object, Int64 *pos, ESzSeek origin) - { - try - { - CNel7ZipInStream *me = (CNel7ZipInStream*)object; - sint32 offset = (sint32)*pos; - bool ret = me->_Stream->seek(offset, (NLMISC::IStream::TSeekOrigin)origin); - - if (ret) - { - *pos = (Int64)me->_Stream->getPos(); - return SZ_OK; - } - } - catch (...) - { - } - - return SZ_ERROR_READ; - } -}; - -#else - -/// Input stream class for 7zip archive -class CNel7ZipInStream : public _ISzInStream -{ - NLMISC::IStream *_Stream; - -public: - /// Constructor, only allow file stream because 7zip will 'seek' in the stream - CNel7ZipInStream(NLMISC::IStream *s) - : _Stream(s) - { - Read = readFunc; - Seek = seekFunc; - } - - // the read function called by 7zip to read data - static SZ_RESULT readFunc(void *object, void *buffer, size_t size, size_t *processedSize) - { - try - { - CNel7ZipInStream *me = (CNel7ZipInStream*)object; - me->_Stream->serialBuffer((uint8*)buffer, (uint)size); - *processedSize = size; - return SZ_OK; - } - catch (...) - { - return SZE_FAIL; - } - } - - // the seek function called by seven zip to seek inside stream - static SZ_RESULT seekFunc(void *object, CFileSize pos) - { - try - { - CNel7ZipInStream *me = (CNel7ZipInStream*)object; - bool ret= me->_Stream->seek(pos, NLMISC::IStream::begin); - if (ret) - return SZ_OK; - else - return SZE_FAIL; - } - catch (...) - { - return SZE_FAIL; - } - } -}; - -#endif - -#endif - -bool CPatchManager::unpack7Zip(const std::string &sevenZipFile, const std::string &destFileName) -{ -#ifdef RZ_USE_SEVENZIP - nlinfo("Uncompressing 7zip archive '%s' to '%s'", sevenZipFile.c_str(), destFileName.c_str()); - - // init seven zip - ISzAlloc allocImp; - allocImp.Alloc = SzAlloc; - allocImp.Free = SzFree; - - ISzAlloc allocTempImp; - allocTempImp.Alloc = SzAllocTemp; - allocTempImp.Free = SzFreeTemp; - - // wrap file in a CIFile - CIFile input(sevenZipFile); - CNel7ZipInStream inStr(&input); - -#ifdef RZ_USE_NEW_LZMA - - CLookToRead lookStream; - lookStream.realStream = &inStr; - LookToRead_CreateVTable(&lookStream, False); - LookToRead_Init(&lookStream); - - CrcGenerateTable(); - - CSzArEx db; - SzArEx_Init(&db); - - // unpack the file using the 7zip API - SRes res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); - - if (res != SZ_OK) - { - nlerror("Failed to open archive file %s", sevenZipFile.c_str()); - return false; - } - - if (db.NumFiles != 1) - { - nlerror("Seven zip archive with more than 1 file are unsupported"); - return false; - } - - UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ - Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ - size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ - - size_t offset; - size_t outSizeProcessed = 0; - - // get the first file - res = SzArEx_Extract(&db, &lookStream.s, 0, - &blockIndex, &outBuffer, &outBufferSize, - &offset, &outSizeProcessed, - &allocImp, &allocTempImp); - - // get the length of first file - size_t nameLen = SzArEx_GetFileNameUtf16(&db, 0, NULL); - - ucstring filename; - filename.resize(nameLen); - - // write filename into ucstring - SzArEx_GetFileNameUtf16(&db, 0, &filename[0]); - - // write the extracted file - FILE *outputHandle = fopen(destFileName.c_str(), "wb+"); - - if (outputHandle == 0) - { - nlerror("Can not open output file '%s'", destFileName.c_str()); - return false; - } - - UInt32 processedSize = (UInt32)fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); - - if (processedSize != outSizeProcessed) - { - nlerror("Failed to write %u char to output file '%s'", outSizeProcessed-processedSize, destFileName.c_str()); - return false; - } - - fclose(outputHandle); - - IAlloc_Free(&allocImp, outBuffer); - - // free 7z context - SzArEx_Free(&db, &allocImp); - -#else - - InitCrcTable(); - - CArchiveDatabaseEx db; - SzArDbExInit(&db); - - // unpack the file using the 7zip API - SZ_RESULT res = SzArchiveOpen(&inStr, &db, &allocImp, &allocTempImp); - - if (res != SZ_OK) - { - nlerror("Failed to open archive file %s", sevenZipFile.c_str()); - return false; - } - - if (db.Database.NumFiles != 1) - { - nlerror("Seven zip archive with more than 1 file are unsupported"); - return false; - } - - UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ - Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ - size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ - - size_t offset = 0; - size_t outSizeProcessed = 0; - - // get the first file - res = SzExtract(&inStr, &db, 0, - &blockIndex, &outBuffer, &outBufferSize, - &offset, &outSizeProcessed, - &allocImp, &allocTempImp); - - // write the extracted file - FILE *outputHandle = fopen(destFileName.c_str(), "wb+"); - - if (outputHandle == 0) - { - nlerror("Can not open output file '%s'", destFileName.c_str()); - return false; - } - - UInt32 processedSize = (UInt32)fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); - - if (processedSize != outSizeProcessed) - { - nlerror("Failed to write %u char to output file '%s'", outSizeProcessed-processedSize, destFileName.c_str()); - return false; - } - - fclose(outputHandle); - allocImp.Free(outBuffer); - - // free 7z context - SzArDbExFree(&db, allocImp.Free); - -#endif - - // ok, all is fine, file is unpacked - return true; -#else - return false; -#endif -} - -bool CPatchManager::unpackLZMA(const std::string &lzmaFile, const std::string &destFileName) -{ -#ifdef RZ_USE_SEVENZIP - nldebug("unpackLZMA : decompression the lzma file '%s' into output file '%s", lzmaFile.c_str(), destFileName.c_str()); - - CIFile inStream(lzmaFile); - uint32 inSize = inStream.getFileSize(); - -#ifdef RZ_USE_NEW_LZMA - - if (inSize < LZMA_PROPS_SIZE + 8) - { - nlwarning("Invalid file size, too small file '%s'", lzmaFile.c_str()); - return false; - } - - // read the compressed file in buffer - auto_ptr inBuffer = auto_ptr(new uint8[inSize]); - inStream.serialBuffer(inBuffer.get(), inSize); - - uint8 *pos = inBuffer.get(); - - pos += LZMA_PROPS_SIZE; - - // read the output file size - size_t fileSize = 0; - - for (int i = 0; i < 8; ++i) - { - if (pos >= inBuffer.get()+inSize) - { - nlassert(false); - return false; - } - - fileSize |= ((UInt64)*pos++) << (8 * i); - } - - // allocators - ISzAlloc allocImp; - allocImp.Alloc = SzAlloc; - allocImp.Free = SzFree; - - CLzmaDec state; - LzmaDec_Construct(&state); - - // allocate and decode props and probs - SRes res = LzmaDec_Allocate(&state, inBuffer.get(), LZMA_PROPS_SIZE, &allocImp); - - if (res != 0) - { - nlwarning("Failed to decode lzma properies in file '%s'!", lzmaFile.c_str()); - return false; - } - - // allocate the output buffer - auto_ptr outBuffer = auto_ptr(new uint8[fileSize]); - - // in and out file sizes - SizeT outProcessed = fileSize; - SizeT inProcessed = (SizeT)(inSize-(pos-inBuffer.get())); - - LzmaDec_Init(&state); - - // decompress the file in memory - ELzmaStatus status; - res = LzmaDec_DecodeToBuf(&state, (Byte*)outBuffer.get(), &outProcessed, (Byte*)pos, &inProcessed, LZMA_FINISH_ANY, &status); - - // free memory - LzmaDec_Free(&state, &allocImp); - - if (res != 0 || outProcessed != fileSize) - { - nlwarning("Failed to decode lzma file '%s' with status %d", lzmaFile.c_str(), (sint)status); - return false; - } - -#else - - auto_ptr inBuffer = auto_ptr(new uint8[inSize]); - inStream.serialBuffer(inBuffer.get(), inSize); - - CLzmaDecoderState state; - - uint8 *pos = inBuffer.get(); - - // read the lzma properties - int res = LzmaDecodeProperties(&state.Properties, (unsigned char*) pos, LZMA_PROPERTIES_SIZE); - if (res != 0) - { - nlwarning("Failed to decode lzma properies in file '%s'!", lzmaFile.c_str()); - return false; - } - - if (inSize < LZMA_PROPERTIES_SIZE + 8) - { - nlwarning("Invalid file size, too small file '%s'", lzmaFile.c_str()); - return false; - } - - // alloc the probs, making sure they are deleted in function exit - size_t nbProb = LzmaGetNumProbs(&state.Properties); - auto_ptr probs = auto_ptr(new CProb[nbProb]); - state.Probs = probs.get(); - - pos += LZMA_PROPERTIES_SIZE; - - // read the output file size - size_t fileSize = 0; - for (int i = 0; i < 8; i++) - { - if (pos >= inBuffer.get()+inSize) - { - nlassert(false); - return false; - } - fileSize |= ((UInt64)*pos++) << (8 * i); - } - - SizeT outProcessed = 0; - SizeT inProcessed = 0; - - // allocate the output buffer - auto_ptr outBuffer = auto_ptr(new uint8[fileSize]); - - // decompress the file in memory - res = LzmaDecode(&state, (unsigned char*) pos, (SizeT)(inSize-(pos-inBuffer.get())), &inProcessed, (unsigned char*)outBuffer.get(), (SizeT)fileSize, &outProcessed); - - if (res != 0 || outProcessed != fileSize) - { - nlwarning("Failed to decode lzma file '%s'", lzmaFile.c_str()); - return false; - } - -#endif - - // store on output buffer - COFile outStream(destFileName); - outStream.serialBuffer(outBuffer.get(), (uint)fileSize); - - return true; -#else - return false; -#endif -} diff --git a/code/ryzom/client/src/seven_zip/seven_zip.cpp b/code/ryzom/client/src/seven_zip/seven_zip.cpp new file mode 100644 index 000000000..84a7eaace --- /dev/null +++ b/code/ryzom/client/src/seven_zip/seven_zip.cpp @@ -0,0 +1,357 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "seven_zip.h" + +#include "nel/misc/types_nl.h" +#include "nel/misc/file.h" +#include "nel/misc/path.h" + +#include "7z.h" +#include "7zAlloc.h" +#include "7zCrc.h" +#include "7zVersion.h" +#include "LzmaLib.h" + +#include + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; + + +/// Input stream class for 7zip archive +class CNel7ZipInStream : public ISeekInStream +{ + NLMISC::IStream *_Stream; + +public: + /// Constructor, only allow file stream because 7zip will 'seek' in the stream + CNel7ZipInStream(NLMISC::IStream *s) + : _Stream(s) + { + Read = readFunc; + Seek = seekFunc; + } + + // the read function called by 7zip to read data + static SRes readFunc(void *object, void *buffer, size_t *size) + { + try + { + CNel7ZipInStream *me = (CNel7ZipInStream*)object; + uint len = (uint)*size; + me->_Stream->serialBuffer((uint8*)buffer, len); + return SZ_OK; + } + catch (...) + { + return SZ_ERROR_READ; + } + } + + // the seek function called by seven zip to seek inside stream + static SRes seekFunc(void *object, Int64 *pos, ESzSeek origin) + { + try + { + CNel7ZipInStream *me = (CNel7ZipInStream*)object; + sint32 offset = (sint32)*pos; + bool ret = me->_Stream->seek(offset, (NLMISC::IStream::TSeekOrigin)origin); + + if (ret) + { + *pos = (Int64)me->_Stream->getPos(); + return SZ_OK; + } + } + catch (...) + { + } + + return SZ_ERROR_READ; + } +}; + +bool unpack7Zip(const std::string &sevenZipFile, const std::string &destFileName) +{ + nlinfo("Uncompressing 7zip archive '%s' to '%s'", sevenZipFile.c_str(), destFileName.c_str()); + + // init seven zip + ISzAlloc allocImp; + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + ISzAlloc allocTempImp; + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + // wrap file in a CIFile + CIFile input(sevenZipFile); + CNel7ZipInStream inStr(&input); + + CLookToRead lookStream; + lookStream.realStream = &inStr; + LookToRead_CreateVTable(&lookStream, False); + LookToRead_Init(&lookStream); + + CrcGenerateTable(); + + CSzArEx db; + SzArEx_Init(&db); + + // unpack the file using the 7zip API + SRes res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + + if (res != SZ_OK) + { + nlerror("Failed to open archive file %s", sevenZipFile.c_str()); + return false; + } + + if (db.NumFiles != 1) + { + nlerror("Seven zip archive with more than 1 file are unsupported"); + return false; + } + + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + size_t offset; + size_t outSizeProcessed = 0; + + // get the first file + res = SzArEx_Extract(&db, &lookStream.s, 0, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + + // get the length of first file + size_t nameLen = SzArEx_GetFileNameUtf16(&db, 0, NULL); + + ucstring filename; + filename.resize(nameLen); + + // write filename into ucstring + SzArEx_GetFileNameUtf16(&db, 0, &filename[0]); + + // write the extracted file + FILE *outputHandle = fopen(destFileName.c_str(), "wb+"); + + if (outputHandle == 0) + { + nlerror("Can not open output file '%s'", destFileName.c_str()); + return false; + } + + UInt32 processedSize = (UInt32)fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); + + if (processedSize != outSizeProcessed) + { + nlerror("Failed to write %u char to output file '%s'", outSizeProcessed-processedSize, destFileName.c_str()); + return false; + } + + fclose(outputHandle); + + IAlloc_Free(&allocImp, outBuffer); + + // free 7z context + SzArEx_Free(&db, &allocImp); + + // ok, all is fine, file is unpacked + return true; +} + +bool unpackLZMA(const std::string &lzmaFile, const std::string &destFileName) +{ + nldebug("unpackLZMA: decompress LZMA file '%s' to '%s", lzmaFile.c_str(), destFileName.c_str()); + + // open input file + CIFile inStream(lzmaFile); + uint32 inSize = inStream.getFileSize(); + + if (inSize < LZMA_PROPS_SIZE + 8) + { + nlwarning("unpackLZMA: Invalid file size, too small file '%s'", lzmaFile.c_str()); + return false; + } + + // allocate input buffer for props + auto_ptr propsBuffer = auto_ptr(new uint8[LZMA_PROPS_SIZE]); + + // size of LZMA content + inSize -= LZMA_PROPS_SIZE + 8; + + // allocate input buffer for lzma data + auto_ptr inBuffer = auto_ptr(new uint8[inSize]); + + uint64 fileSize = 0; + + try + { + // read props + inStream.serialBuffer(propsBuffer.get(), LZMA_PROPS_SIZE); + + // read uncompressed size + inStream.serial(fileSize); + + // read lzma content + inStream.serialBuffer(inBuffer.get(), inSize); + } + catch(const EReadError &e) + { + nlwarning("unpackLZMA: Error while reading '%s': %s", lzmaFile.c_str(), e.what()); + return false; + } + + // allocate the output buffer + auto_ptr outBuffer = auto_ptr(new uint8[fileSize]); + + // in and out file sizes + SizeT outProcessed = (SizeT)fileSize; + SizeT inProcessed = (SizeT)inSize; + + // decompress the file in memory + sint res = LzmaUncompress(outBuffer.get(), &outProcessed, inBuffer.get(), &inProcessed, propsBuffer.get(), LZMA_PROPS_SIZE); + + if (res != 0 || outProcessed != fileSize) + { + nlwarning("unpackLZMA: Failed to decode lzma file '%s' with status %d", lzmaFile.c_str(), res); + return false; + } + + // store on output buffer + COFile outStream(destFileName); + + try + { + // write content + outStream.serialBuffer(outBuffer.get(), (uint)fileSize); + } + catch(const EFile &e) + { + nlwarning("unpackLZMA: Error while writing '%s': %s", destFileName.c_str(), e.what()); + CFile::deleteFile(destFileName); + return false; + } + + return true; +} + +bool packLZMA(const std::string &srcFileName, const std::string &lzmaFileName) +{ + nldebug("unpackLZMA: compress '%s' to LZMA file '%s", srcFileName.c_str(), lzmaFileName.c_str()); + + // open file + CIFile inStream(srcFileName); + size_t inSize = inStream.getFileSize(); + + // file empty + if (!inSize) + { + nlwarning("packLZMA: File '%s' not found or empty", srcFileName.c_str()); + return false; + } + + // allocate input buffer + auto_ptr inBuffer = auto_ptr(new uint8[inSize]); + + try + { + // read file in buffer + inStream.serialBuffer(inBuffer.get(), inSize); + } + catch(const EReadError &e) + { + nlwarning("packLZMA: Error while reading '%s': %s", srcFileName.c_str(), e.what()); + return false; + } + + // allocate output buffer + size_t outSize = (11 * inSize / 10) + 65536; // worst case = 1.1 * size + 64K + auto_ptr outBuffer = auto_ptr(new uint8[outSize]); + + // allocate buffer for props + size_t outPropsSize = LZMA_PROPS_SIZE; + auto_ptr outProps = auto_ptr(new uint8[outPropsSize]); + + // compress with best compression and other default settings + sint res = LzmaCompress(outBuffer.get(), &outSize, inBuffer.get(), inSize, outProps.get(), &outPropsSize, 9, 1 << 24, 3, 0, 2, 32, 1); + + switch(res) + { + case SZ_OK: + { + // store on output buffer + COFile outStream(lzmaFileName); + + // unable to create file + if (!outStream.isOpen()) + { + nlwarning("packLZMA: Unable to create '%s'", srcFileName.c_str()); + return false; + } + + try + { + // write props + outStream.serialBuffer(outProps.get(), (uint)outPropsSize); + + // write uncompressed size + uint64 uncompressSize = inSize; + outStream.serial(uncompressSize); + + // write content + outStream.serialBuffer(outBuffer.get(), (uint)outSize); + } + catch(const EFile &e) + { + nlwarning("packLZMA: Error while writing '%s': %s", lzmaFileName.c_str(), e.what()); + CFile::deleteFile(lzmaFileName); + return false; + } + + return true; + } + + case SZ_ERROR_MEM: + nlwarning("packLZMA: Memory allocation error while compressing '%s' (input buffer size: %u, output buffer size: %u)", srcFileName.c_str(), (uint)inSize, (uint)outSize); + break; + + case SZ_ERROR_PARAM: + nlwarning("packLZMA: Incorrect parameter while compressing '%s'", srcFileName.c_str()); + break; + + case SZ_ERROR_OUTPUT_EOF: + nlwarning("packLZMA: Output buffer overflow while compressing '%s' (input buffer size: %u, output buffer size: %u)", srcFileName.c_str(), (uint)inSize, (uint)outSize); + break; + + case SZ_ERROR_THREAD: + nlwarning("packLZMA: Errors in multithreading functions (only for Mt version)"); + break; + + default: + nlwarning("packLZMA: Unknown error (%d) while compressing '%s'", res, srcFileName.c_str()); + } + + return false; +} diff --git a/code/ryzom/client/src/seven_zip/seven_zip.h b/code/ryzom/client/src/seven_zip/seven_zip.h new file mode 100644 index 000000000..e471a9ac0 --- /dev/null +++ b/code/ryzom/client/src/seven_zip/seven_zip.h @@ -0,0 +1,31 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SEVEN_ZIP_H +#define SEVEN_ZIP_H + +#include + +// utility func to decompress a monofile 7zip archive +bool unpack7Zip(const std::string &sevenZipFileName, const std::string &destFileName); + +// utility func to decompress a single LZMA packed file +bool unpackLZMA(const std::string &lzmaFileName, const std::string &destFileName); + +// utility func to compress a single file to LZMA packed file +bool packLZMA(const std::string &srcFileName, const std::string &lzmaFileName); + +#endif