diff options
Diffstat (limited to 'CPP/7zip/Archive')
140 files changed, 9888 insertions, 5714 deletions
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp index bddb2673..cf7aa975 100755 --- a/CPP/7zip/Archive/7z/7z.dsp +++ b/CPP/7zip/Archive/7z/7z.dsp @@ -598,11 +598,11 @@ SOURCE=..\..\..\Windows\Thread.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\Copy\CopyCoder.cpp +SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\Copy\CopyCoder.h +SOURCE=..\..\Compress\CopyCoder.h # End Source File # End Group # Begin Group "C" diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 01803842..c97f893b 100755 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -1,21 +1,21 @@ -// Encode.cpp +// 7zEncode.cpp #include "StdAfx.h" -#include "7zEncode.h" -#include "7zSpecStream.h" - -#include "../../IPassword.h" -#include "../../Common/ProgressUtils.h" +#include "../../Common/CreateCoder.h" +#include "../../Common/FilterCoder.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" -#include "../../Common/CreateCoder.h" -#include "../../Common/FilterCoder.h" -static const UInt64 k_AES = 0x06F10701; -static const UInt64 k_BCJ = 0x03030103; +#include "7zEncode.h" +#include "7zSpecStream.h" + +static const UInt64 k_Delta = 0x03; +static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; +static const UInt64 k_AES = 0x06F10701; namespace NArchive { namespace N7z { @@ -240,10 +240,10 @@ HRESULT CEncoder::Encode( UInt32 progressIndex = mainCoderIndex; - for (i = 0; i < _codersInfo.Size(); i++) + for (i = 0; i + 1 < _codersInfo.Size(); i++) { - const CCoderInfo &e = _codersInfo[i]; - if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) + UInt64 m = _codersInfo[i].MethodID; + if (m == k_Delta || m == k_BCJ || m == k_BCJ2) progressIndex = i + 1; } diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 61b938d0..75505863 100755 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -9,156 +9,132 @@ namespace N7z { CFolderOutStream::CFolderOutStream() { - _outStreamWithHashSpec = new COutStreamWithCRC; - _outStreamWithHash = _outStreamWithHashSpec; + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, - UInt32 ref2Offset, - UInt32 startIndex, + UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, - bool testMode, - bool checkCrc) + bool testMode, bool checkCrc) { - _archiveDatabase = archiveDatabase; + _db = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; - _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; - return WriteEmptyFiles(); + return ProcessEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { - Int32 askMode; - if((*_extractStatuses)[_currentIndex]) - askMode = _testMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - else - askMode = NArchive::NExtract::NAskMode::kSkip; + Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract): + NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; - UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); - - _outStreamWithHashSpec->SetStream(realOutStream); - _outStreamWithHashSpec->Init(_checkCrc); - if (askMode == NArchive::NExtract::NAskMode::kExtract && - (!realOutStream)) - { - const CFileItem &fi = _archiveDatabase->Files[index]; - if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) - askMode = NArchive::NExtract::NAskMode::kSkip; - } + _crcStreamSpec->SetStream(realOutStream); + _crcStreamSpec->Init(_checkCrc); + _fileIsOpen = true; + const CFileItem &fi = _db->Files[index]; + _rem = fi.Size; + if (askMode == NArchive::NExtract::NAskMode::kExtract && !realOutStream && + !_db->IsItemAnti(index) && !fi.IsDir) + askMode = NArchive::NExtract::NAskMode::kSkip; return _extractCallback->PrepareOperation(askMode); } -HRESULT CFolderOutStream::WriteEmptyFiles() +HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res) +{ + _crcStreamSpec->ReleaseStream(); + _fileIsOpen = false; + _currentIndex++; + return _extractCallback->SetOperationResult(res); +} + +HRESULT CFolderOutStream::CloseFileAndSetResult() +{ + const CFileItem &fi = _db->Files[_startIndex + _currentIndex]; + return CloseFileAndSetResult( + (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ? + NArchive::NExtract::NOperationResult::kOK : + NArchive::NExtract::NOperationResult::kCRCError); +} + +HRESULT CFolderOutStream::ProcessEmptyFiles() { - for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) { - UInt32 index = _startIndex + _currentIndex; - const CFileItem &fi = _archiveDatabase->Files[index]; - if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) - return S_OK; RINOK(OpenFile()); - RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - _outStreamWithHashSpec->ReleaseStream(); + RINOK(CloseFileAndSetResult()); } return S_OK; } -STDMETHODIMP CFolderOutStream::Write(const void *data, - UInt32 size, UInt32 *processedSize) +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize = 0; - while(_currentIndex < _extractStatuses->Size()) + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) { if (_fileIsOpen) { - UInt32 index = _startIndex + _currentIndex; - const CFileItem &fi = _archiveDatabase->Files[index]; - UInt64 fileSize = fi.Size; - - UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, - UInt64(size - realProcessedSize)); - - UInt32 processedSizeLocal; - RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, - numBytesToWrite, &processedSizeLocal)); - - _filePos += processedSizeLocal; - realProcessedSize += processedSizeLocal; - if (_filePos == fileSize) + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) { - bool digestsAreEqual; - if (fi.CrcDefined && _checkCrc) - digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); - else - digestsAreEqual = true; - - RINOK(_extractCallback->SetOperationResult( - digestsAreEqual ? - NArchive::NExtract::NOperationResult::kOK : - NArchive::NExtract::NOperationResult::kCRCError)); - _outStreamWithHashSpec->ReleaseStream(); - _fileIsOpen = false; - _currentIndex++; - } - if (realProcessedSize == size) - { - if (processedSize != NULL) - *processedSize = realProcessedSize; - return WriteEmptyFiles(); + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; } } else { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we support partial extracting + if (processedSize != NULL) + *processedSize += size; + break; + } RINOK(OpenFile()); - _fileIsOpen = true; - _filePos = 0; } } - if (processedSize != NULL) - *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { - while(_currentIndex < _extractStatuses->Size()) + while (_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { - RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); - _outStreamWithHashSpec->ReleaseStream(); - _fileIsOpen = false; - _currentIndex++; + RINOK(CloseFileAndSetResult(resultEOperationResult)); } else { RINOK(OpenFile()); - _fileIsOpen = true; } } return S_OK; } -HRESULT CFolderOutStream::WasWritingFinished() -{ - if (_currentIndex == _extractStatuses->Size()) - return S_OK; - return E_FAIL; -} - }} diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h index f54fba3e..e6e05b85 100755 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -1,7 +1,7 @@ // 7zFolderOutStream.h -#ifndef __7Z_FOLDEROUTSTREAM_H -#define __7Z_FOLDEROUTSTREAM_H +#ifndef __7Z_FOLDER_OUT_STREAM_H +#define __7Z_FOLDER_OUT_STREAM_H #include "7zIn.h" @@ -16,43 +16,39 @@ class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP - - CFolderOutStream(); - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -private: - - COutStreamWithCRC *_outStreamWithHashSpec; - CMyComPtr<ISequentialOutStream> _outStreamWithHash; - const CArchiveDatabaseEx *_archiveDatabase; + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + const CArchiveDatabaseEx *_db; const CBoolVector *_extractStatuses; - UInt32 _startIndex; + CMyComPtr<IArchiveExtractCallback> _extractCallback; UInt32 _ref2Offset; + UInt32 _startIndex; int _currentIndex; - // UInt64 _currentDataPos; - CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; - - bool _fileIsOpen; - bool _checkCrc; - UInt64 _filePos; + bool _fileIsOpen; + UInt64 _rem; HRESULT OpenFile(); - HRESULT WriteEmptyFiles(); + HRESULT CloseFileAndSetResult(Int32 res); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); public: + MY_UNKNOWN_IMP + + CFolderOutStream(); + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, - UInt32 ref2Offset, - UInt32 startIndex, + UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, - bool testMode, - bool checkCrc); + bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); - HRESULT WasWritingFinished(); + HRESULT WasWritingFinished() const + { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } }; }} diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 44131fae..6f0cf6b2 100755 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "../../../../C/CpuArch.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" @@ -176,6 +173,8 @@ static UString GetStringForSizeValue(UInt32 value) } static const UInt64 k_Copy = 0x0; +static const UInt64 k_Delta = 3; +static const UInt64 k_LZMA2 = 0x21; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; @@ -183,12 +182,10 @@ static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } -static inline UString GetHex2(Byte value) +static inline void AddHexToString(UString &res, Byte value) { - UString result; - result += GetHex((Byte)(value >> 4)); - result += GetHex((Byte)(value & 0xF)); - return result; + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); } #endif @@ -273,89 +270,82 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { - const CCoderInfo &coderInfo = folderInfo.Coders[i]; + const CCoderInfo &coder = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; + UString methodName, propsString; + bool methodIsKnown = FindMethod( + EXTERNAL_CODECS_VARS + coder.MethodID, methodName); + + if (!methodIsKnown) + methodsString += ConvertMethodIdToString(coder.MethodID); + else { - UString methodName; - bool methodIsKnown = FindMethod( - EXTERNAL_CODECS_VARS - coderInfo.MethodID, methodName); - - if (methodIsKnown) + methodsString += methodName; + if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1) + propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1); + else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5) { - methodsString += methodName; - if (coderInfo.MethodID == k_LZMA) - { - if (coderInfo.Props.GetCapacity() >= 5) - { - methodsString += L":"; - UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); - methodsString += GetStringForSizeValue(dicSize); - } - } - else if (coderInfo.MethodID == k_PPMD) + UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); + propsString = GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1) + { + Byte p = coder.Props[0]; + UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); + propsString = GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5) + { + Byte order = *(const Byte *)coder.Props; + methodsString += L'o'; + methodsString += ConvertUInt32ToString(order); + methodsString += L":mem"; + UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); + propsString = GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1) + { + const Byte *data = (const Byte *)coder.Props; + Byte firstByte = *data++; + UInt32 numCyclesPower = firstByte & 0x3F; + propsString = ConvertUInt32ToString(numCyclesPower); + /* + if ((firstByte & 0xC0) != 0) { - if (coderInfo.Props.GetCapacity() >= 5) + UInt32 saltSize = (firstByte >> 7) & 1; + UInt32 ivSize = (firstByte >> 6) & 1; + if (coder.Props.GetCapacity() >= 2) { - Byte order = *(const Byte *)coderInfo.Props; - methodsString += L":o"; - methodsString += ConvertUInt32ToString(order); - methodsString += L":mem"; - UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); - methodsString += GetStringForSizeValue(dicSize); + Byte secondByte = *data++; + saltSize += (secondByte >> 4); + ivSize += (secondByte & 0x0F); } } - else if (coderInfo.MethodID == k_AES) + */ + } + } + if (!propsString.IsEmpty()) + { + methodsString += L':'; + methodsString += propsString; + } + else if (coder.Props.GetCapacity() > 0) + { + methodsString += L":["; + for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++) + { + if (bi > 5 && bi + 1 < coder.Props.GetCapacity()) { - if (coderInfo.Props.GetCapacity() >= 1) - { - methodsString += L":"; - const Byte *data = (const Byte *)coderInfo.Props; - Byte firstByte = *data++; - UInt32 numCyclesPower = firstByte & 0x3F; - methodsString += ConvertUInt32ToString(numCyclesPower); - /* - if ((firstByte & 0xC0) != 0) - { - methodsString += L":"; - return S_OK; - UInt32 saltSize = (firstByte >> 7) & 1; - UInt32 ivSize = (firstByte >> 6) & 1; - if (coderInfo.Props.GetCapacity() >= 2) - { - Byte secondByte = *data++; - saltSize += (secondByte >> 4); - ivSize += (secondByte & 0x0F); - } - } - */ - } + methodsString += L".."; + break; } else - { - if (coderInfo.Props.GetCapacity() > 0) - { - methodsString += L":["; - for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) - { - if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) - { - methodsString += L".."; - break; - } - else - methodsString += GetHex2(coderInfo.Props[bi]); - } - methodsString += L"]"; - } - } - } - else - { - methodsString += ConvertMethodIdToString(coderInfo.MethodID); + AddHexToString(methodsString, coder.Props[bi]); } + methodsString += L']'; } } prop = methodsString; diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 9adf8464..68fb034f 100755 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -5,9 +5,6 @@ #include "../../ICoder.h" #include "../IArchive.h" -#include "7zIn.h" - -#include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" @@ -15,6 +12,9 @@ #include "../Common/HandlerOut.h" #endif +#include "7zCompressionMode.h" +#include "7zIn.h" + namespace NArchive { namespace N7z { @@ -90,8 +90,6 @@ private: CRecordVector<CBind> _binds; - HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); - HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 3e2591d5..e2c250ab 100755 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -40,31 +40,6 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, - IArchiveUpdateCallback *updateCallback) -{ - CMyComPtr<ICryptoGetTextPassword2> getTextPassword; - if (!getTextPassword) - { - CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); - udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); - } - - if (getTextPassword) - { - CMyComBSTR password; - Int32 passwordIsDefined; - RINOK(getTextPassword->CryptoGetTextPassword2( - &passwordIsDefined, &password)); - methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); - if (methodMode.PasswordIsDefined) - methodMode.Password = password; - } - else - methodMode.PasswordIsDefined = false; - return S_OK; -} - HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) @@ -210,7 +185,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL - if(_volumes.Size() > 1) + if (_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) @@ -227,14 +202,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt for (UInt32 i = 0; i < numItems; i++) { - Int32 newData; - Int32 newProperties; + Int32 newData, newProps; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; - RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); + RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); CUpdateItem ui; - ui.NewProperties = IntToBool(newProperties); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; @@ -243,6 +217,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (ui.IndexInArchive != -1) { + if (db == 0 || ui.IndexInArchive >= db->Files.Size()) + return E_INVALIDARG; const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; @@ -254,7 +230,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } - if (ui.NewProperties) + if (ui.NewProps) { bool nameIsDefined; bool folderStatusIsDefined; @@ -350,7 +326,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt headerMethod.NumThreads = 1; #endif - RINOK(SetPassword(methodMode, updateCallback)); + CMyComPtr<ICryptoGetTextPassword2> getPassword2; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); + + if (getPassword2) + { + CMyComBSTR password; + Int32 passwordIsDefined; + RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); + methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); + if (methodMode.PasswordIsDefined) + methodMode.Password = password; + } + else + methodMode.PasswordIsDefined = false; bool compressMainHeader = _compressHeaders; // check it @@ -365,8 +354,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; - if(encryptHeaders) - RINOK(SetPassword(headerMethod, updateCallback)); + if (encryptHeaders) + { + headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; + headerMethod.Password = methodMode.Password; + } } if (numItems < 2) @@ -391,6 +383,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COutArchive archive; CArchiveDatabase newDatabase; + + CMyComPtr<ICryptoGetTextPassword> getPassword; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); + HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL @@ -401,7 +397,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db, #endif updateItems, - archive, newDatabase, outStream, updateCallback, options); + archive, newDatabase, outStream, updateCallback, options + #ifndef _NO_CRYPTO + , getPassword + #endif + ); RINOK(res); diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index ab78eeae..f1458e0c 100755 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -2,11 +2,8 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../../C/7zCrc.h" - #include "../../../../C/CpuArch.h" -} +#include "../../../../C/7zCrc.h" +#include "../../../../C/CpuArch.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" @@ -198,16 +195,16 @@ void CInByte2::ReadBytes(Byte *data, size_t size) data[i] = _buffer[_pos++]; } -void CInByte2::SkeepData(UInt64 size) +void CInByte2::SkipData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } -void CInByte2::SkeepData() +void CInByte2::SkipData() { - SkeepData(ReadNumber()); + SkipData(ReadNumber()); } UInt64 CInByte2::ReadNumber() @@ -363,7 +360,7 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { if (ReadID() == NID::kEnd) break; - SkeepData(); + SkipData(); } } @@ -456,7 +453,7 @@ void CInArchive::WaitAttribute(UInt64 attribute) return; if (type == NID::kEnd) ThrowIncorrect(); - SkeepData(); + SkipData(); } } @@ -502,7 +499,7 @@ void CInArchive::ReadPackInfo( ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } - SkeepData(); + SkipData(); } if (packCRCsDefined.IsEmpty()) { @@ -563,7 +560,7 @@ void CInArchive::ReadUnpackInfo( } continue; } - SkeepData(); + SkipData(); } } @@ -590,7 +587,7 @@ void CInArchive::ReadSubStreamsInfo( break; if (type == NID::kEnd) break; - SkeepData(); + SkipData(); } if (numUnpackStreamsInFolders.IsEmpty()) @@ -665,7 +662,7 @@ void CInArchive::ReadSubStreamsInfo( return; } else - SkeepData(); + SkipData(); type = ReadID(); } } @@ -1006,7 +1003,7 @@ HRESULT CInArchive::ReadHeader( db.ArchiveInfo.FileInfoPopIDs.Add(type); } else - SkeepData(size); + SkipData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 09c51105..971f27b2 100755 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -110,8 +110,8 @@ public: } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); - void SkeepData(UInt64 size); - void SkeepData(); + void SkipData(UInt64 size); + void SkipData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); @@ -162,8 +162,8 @@ private: UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } - void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } - void SkeepData() { _inByteBack->SkeepData(); } + void SkipData(UInt64 size) { _inByteBack->SkipData(size); } + void SkipData() { _inByteBack->SkipData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index 7ac3c18c..e897680e 100755 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -2,16 +2,14 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "../../../Common/AutoPtr.h" + #include "../../Common/StreamObjects.h" #include "7zOut.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} - static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) @@ -141,7 +139,7 @@ void COutArchive::Close() Stream.Release(); } -HRESULT COutArchive::SkeepPrefixArchiveHeader() +HRESULT COutArchive::SkipPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h index bdd84abc..9d8ef308 100755 --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -1,12 +1,12 @@ -// 7z/Out.h +// 7zOut.h #ifndef __7Z_OUT_H #define __7Z_OUT_H -#include "7zHeader.h" -#include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" +#include "7zHeader.h" +#include "7zItem.h" #include "../../Common/OutBuffer.h" @@ -137,7 +137,7 @@ public: CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); - HRESULT SkeepPrefixArchiveHeader(); + HRESULT SkipPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 0285b189..9506e8f7 100755 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -5,10 +5,14 @@ #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/CreateCoder.h" + #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" +#include "7zDecode.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" @@ -18,6 +22,11 @@ namespace NArchive { namespace N7z { +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_BCJ = 0x03030103; +static const UInt64 k_BCJ2 = 0x0303011B; +static const UInt64 k_AES = 0x06F10701; + static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; @@ -64,27 +73,29 @@ UString CUpdateItem::GetExtension() const #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } +#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) + static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); - RINOZ(MyCompare(c1, c2)); + RINOZ_COMP(c1, c2); for (size_t i = 0; i < c1; i++) - RINOZ(MyCompare(a1[i], a2[i])); + RINOZ_COMP(a1[i], a2[i]); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { - RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); - RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); - RINOZ(MyCompare(c1.MethodID, c2.MethodID)); + RINOZ_COMP(c1.NumInStreams, c2.NumInStreams); + RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams); + RINOZ_COMP(c1.MethodID, c2.MethodID); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { - RINOZ(MyCompare(b1.InIndex, b2.InIndex)); + RINOZ_COMP(b1.InIndex, b2.InIndex); return MyCompare(b1.OutIndex, b2.OutIndex); } @@ -92,39 +103,52 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); - RINOZ(MyCompare(s1, s2)); + RINOZ_COMP(s1, s2); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); - RINOZ(MyCompare(s1, s2)); + RINOZ_COMP(s1, s2); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } +/* static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } +*/ + +const struct CFolderRepack +{ + int FolderIndex; + int Group; + CNum NumCopyFiles; +}; -static int CompareFolderRefs(const int *p1, const int *p2, void *param) +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param) { - int i1 = *p1; - int i2 = *p2; + RINOZ_COMP(p1->Group, p2->Group); + int i1 = p1->FolderIndex; + int i2 = p2->FolderIndex; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); - RINOZ(MyCompare( + return MyCompare(i1, i2); + /* + RINOZ_COMP( db.NumUnpackStreamsVector[i1], - db.NumUnpackStreamsVector[i2])); + db.NumUnpackStreamsVector[i2]); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); + */ } //////////////////////////////////////////////////////////// @@ -277,20 +301,19 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para bool sortByType = *(bool *)param; if (sortByType) { - RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) + RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; - if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); - RINOZ(MyCompare(u1.Size, u2.Size)) + if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); + RINOZ_COMP(u1.Size, u2.Size); } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { - CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; @@ -303,7 +326,7 @@ static wchar_t *g_ExeExts[] = L"sys" }; -static bool IsExeFile(const UString &ext) +static bool IsExeExt(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) @@ -311,31 +334,23 @@ static bool IsExeFile(const UString &ext) return false; } -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - -static bool GetMethodFull(UInt64 methodID, - UInt32 numInStreams, CMethodFull &methodResult) +static void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; - return true; } -static bool MakeExeMethod(const CCompressionMethodMode &method, +static void MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; - if (!GetMethodFull(k_BCJ2, 4, methodFull)) - return false; + GetMethodFull(k_BCJ2, 4, methodFull); exeMethod.Methods.Insert(0, methodFull); - if (!GetMethodFull(k_LZMA, 1, methodFull)) - return false; + GetMethodFull(k_LZMA, 1, methodFull); { CProp prop; prop.Id = NCoderPropID::kAlgorithm; @@ -383,8 +398,7 @@ static bool MakeExeMethod(const CCompressionMethodMode &method, else { CMethodFull methodFull; - if (!GetMethodFull(k_BCJ, 1, methodFull)) - return false; + GetMethodFull(k_BCJ, 1, methodFull); exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; @@ -393,55 +407,6 @@ static bool MakeExeMethod(const CCompressionMethodMode &method, bind.OutStream = 0; exeMethod.Binds.Add(bind); } - return true; -} - -static void SplitFilesToGroups( - const CCompressionMethodMode &method, - bool useFilters, bool maxFilter, - const CObjectVector<CUpdateItem> &updateItems, - CObjectVector<CSolidGroup> &groups) -{ - if (method.Methods.Size() != 1 || method.Binds.Size() != 0) - useFilters = false; - groups.Clear(); - groups.Add(CSolidGroup()); - groups.Add(CSolidGroup()); - CSolidGroup &generalGroup = groups[0]; - CSolidGroup &exeGroup = groups[1]; - generalGroup.Method = method; - int i; - for (i = 0; i < updateItems.Size(); i++) - { - const CUpdateItem &ui = updateItems[i]; - if (!ui.NewData) - continue; - if (!ui.HasStream()) - continue; - if (useFilters) - { - const UString name = ui.Name; - int dotPos = name.ReverseFind(L'.'); - if (dotPos >= 0) - { - UString ext = name.Mid(dotPos + 1); - if (IsExeFile(ext)) - { - exeGroup.Indices.Add(i); - continue; - } - } - } - generalGroup.Indices.Add(i); - } - if (exeGroup.Indices.Size() > 0) - if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) - exeGroup.Method = method; - for (i = 0; i < groups.Size();) - if (groups[i].Indices.Size() == 0) - groups.Delete(i); - else - i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, @@ -462,7 +427,250 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui, file.HasStream = ui.HasStream(); } -static HRESULT Update2( +class CFolderOutStream2: + public ISequentialOutStream, + public CMyUnknownImp +{ + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + const CArchiveDatabaseEx *_db; + const CBoolVector *_extractStatuses; + CMyComPtr<ISequentialOutStream> _outStream; + UInt32 _startIndex; + int _currentIndex; + bool _fileIsOpen; + UInt64 _rem; + + void OpenFile(); + void CloseFile(); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); +public: + MY_UNKNOWN_IMP + + CFolderOutStream2() + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + } + + HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream); + void ReleaseOutStream(); + HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream) +{ + _db = db; + _startIndex = startIndex; + _extractStatuses = extractStatuses; + _outStream = outStream; + + _currentIndex = 0; + _fileIsOpen = false; + return ProcessEmptyFiles(); +} + +void CFolderOutStream2::ReleaseOutStream() +{ + _outStream.Release(); + _crcStreamSpec->ReleaseStream(); +} + +void CFolderOutStream2::OpenFile() +{ + _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL); + _crcStreamSpec->Init(true); + _fileIsOpen = true; + _rem = _db->Files[_startIndex + _currentIndex].Size; +} + +void CFolderOutStream2::CloseFile() +{ + _crcStreamSpec->ReleaseStream(); + _fileIsOpen = false; + _currentIndex++; +} + +HRESULT CFolderOutStream2::CloseFileAndSetResult() +{ + const CFileItem &file = _db->Files[_startIndex + _currentIndex]; + CloseFile(); + return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE; +} + +HRESULT CFolderOutStream2::ProcessEmptyFiles() +{ + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) + { + OpenFile(); + RINOK(CloseFileAndSetResult()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) + { + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; + } + } + else + { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we don't support partial extracting + return E_FAIL; + } + OpenFile(); + } + } + return S_OK; +} + +class CThreadDecoder: public CVirtThread +{ +public: + HRESULT Result; + CMyComPtr<IInStream> InStream; + + CFolderOutStream2 *FosSpec; + CMyComPtr<ISequentialOutStream> Fos; + + UInt64 StartPos; + const UInt64 *PackSizes; + const CFolder *Folder; + #ifndef _NO_CRYPTO + CMyComPtr<ICryptoGetTextPassword> GetTextPassword; + #endif + + DECL_EXTERNAL_CODECS_VARS + CDecoder Decoder; + + #ifdef COMPRESS_MT + bool MtMode; + UInt32 NumThreads; + #endif + + CThreadDecoder(): + Decoder(true) + { + #ifdef COMPRESS_MT + MtMode = false; + NumThreads = 1; + #endif + FosSpec = new CFolderOutStream2; + Fos = FosSpec; + Result = E_FAIL; + } + virtual void Execute(); +}; + +void CThreadDecoder::Execute() +{ + try + { + #ifndef _NO_CRYPTO + bool passwordIsDefined; + #endif + Result = Decoder.Decode( + EXTERNAL_CODECS_VARS + InStream, + StartPos, + PackSizes, + *Folder, + Fos, + NULL + #ifndef _NO_CRYPTO + , GetTextPassword, passwordIsDefined + #endif + #ifdef COMPRESS_MT + , MtMode, NumThreads + #endif + ); + } + catch(...) + { + Result = E_FAIL; + } + if (Result == S_OK) + Result = FosSpec->CheckFinishedState(); + FosSpec->ReleaseOutStream(); +} + +bool static Is86FilteredFolder(const CFolder &f) +{ + for (int i = 0; i < f.Coders.Size(); i++) + { + CMethodId m = f.Coders[i].MethodID; + if (m == k_BCJ || m == k_BCJ2) + return true; + } + return false; +} + +bool static IsEncryptedFolder(const CFolder &f) +{ + for (int i = 0; i < f.Coders.Size(); i++) + { + CMethodId m = f.Coders[i].MethodID; + if (m == k_AES) + return true; + } + return false; +} + +#ifndef _NO_CRYPTO + +class CCryptoGetTextPassword: + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + UString Password; + + MY_UNKNOWN_IMP + STDMETHOD(CryptoGetTextPassword)(BSTR *password); +}; + +STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) +{ + return StringToBstr(Password, password); +} + +#endif + +static const int kNumGroupsMax = 4; + +static bool Is86Group(int group) { return (group & 1) != 0; } +static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } +static int GetGroupIndex(bool encrypted, int bcjFiltered) + { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } + +HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, @@ -471,7 +679,11 @@ static HRESULT Update2( CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options) + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) @@ -490,153 +702,305 @@ static HRESULT Update2( } CRecordVector<int> fileIndexToUpdateIndexMap; + CRecordVector<CFolderRepack> folderRefs; + UInt64 complexity = 0; + UInt64 inSizeForReduce2 = 0; + bool needEncryptedRepack = false; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); - for (int i = 0; i < db->Files.Size(); i++) + int i; + for (i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); - } - int i; - for(i = 0; i < updateItems.Size(); i++) - { - int index = updateItems[i].IndexInArchive; - if (index != -1) - fileIndexToUpdateIndexMap[index] = i; - } - CRecordVector<int> folderRefs; - if (db != 0) - { - for(i = 0; i < db->Folders.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) + { + int index = updateItems[i].IndexInArchive; + if (index != -1) + fileIndexToUpdateIndexMap[index] = i; + } + + for (i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; - for (CNum fileIndex = db->FolderStartFileIndex[i]; - indexInFolder < numUnpackStreams; fileIndex++) + UInt64 repackSize = 0; + for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) { - if (db->Files[fileIndex].HasStream) + const CFileItem &file = db->Files[fi]; + if (file.HasStream) { indexInFolder++; - int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; - if (updateIndex >= 0) - if (!updateItems[updateIndex].NewData) - numCopyItems++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + { + numCopyItems++; + repackSize += file.Size; + } } } - if (numCopyItems != numUnpackStreams && numCopyItems != 0) - return E_NOTIMPL; // It needs repacking !!! - if (numCopyItems > 0) - folderRefs.Add(i); + + if (numCopyItems == 0) + continue; + + CFolderRepack rep; + rep.FolderIndex = i; + rep.NumCopyFiles = numCopyItems; + const CFolder &f = db->Folders[i]; + bool isEncrypted = IsEncryptedFolder(f); + rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); + folderRefs.Add(rep); + if (numCopyItems == numUnpackStreams) + complexity += db->GetFolderFullPackSize(i); + else + { + complexity += repackSize; + if (repackSize > inSizeForReduce2) + inSizeForReduce2 = repackSize; + if (isEncrypted) + needEncryptedRepack = true; + } } - folderRefs.Sort(CompareFolderRefs, (void *)db); + folderRefs.Sort(CompareFolderRepacks, (void *)db); } - //////////////////////////// - - RINOK(archive.Create(seqOutStream, false)); - RINOK(archive.SkeepPrefixArchiveHeader()); - UInt64 complexity = 0; - for(i = 0; i < folderRefs.Size(); i++) - complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; - for(i = 0; i < updateItems.Size(); i++) + int i; + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; - if (numSolidFiles == 1) - { - if (ui.Size > inSizeForReduce) - inSizeForReduce = ui.Size; - } - else + if (numSolidFiles != 1) inSizeForReduce += ui.Size; + else if (ui.Size > inSizeForReduce) + inSizeForReduce = ui.Size; } } - RINOK(updateCallback->SetTotal(complexity)); - complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); + if (inSizeForReduce2 > inSizeForReduce) + inSizeForReduce = inSizeForReduce2; + + const UInt32 kMinReduceSize = (1 << 16); + if (inSizeForReduce < kMinReduceSize) + inSizeForReduce = kMinReduceSize; + + RINOK(updateCallback->SetTotal(complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - ///////////////////////////////////////// - // Write Copy Items + CThreadDecoder threadDecoder; + if (!folderRefs.IsEmpty()) + { + #ifdef EXTERNAL_CODECS + threadDecoder._codecsInfo = codecsInfo; + threadDecoder._externalCodecs = *externalCodecs; + #endif + RINOK(threadDecoder.Create()); + } + + CObjectVector<CSolidGroup> groups; + for (i = 0; i < kNumGroupsMax; i++) + groups.Add(CSolidGroup()); - for(i = 0; i < folderRefs.Size(); i++) { - int folderIndex = folderRefs[i]; - - lps->ProgressOffset = complexity; - UInt64 packSize = db->GetFolderFullPackSize(folderIndex); - RINOK(WriteRange(inStream, archive.SeqStream, - db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); - complexity += packSize; - - const CFolder &folder = db->Folders[folderIndex]; - CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; - for (int j = 0; j < folder.PackStreams.Size(); j++) + // ---------- Split files to 2 groups ---------- + + bool useFilters = options.UseFilters; + const CCompressionMethodMode &method = *options.Method; + if (method.Methods.Size() != 1 || method.Binds.Size() != 0) + useFilters = false; + for (i = 0; i < updateItems.Size(); i++) { - newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); - // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); - // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + const CUpdateItem &ui = updateItems[i]; + if (!ui.NewData || !ui.HasStream()) + continue; + bool filteredGroup = false; + if (useFilters) + { + int dotPos = ui.Name.ReverseFind(L'.'); + if (dotPos >= 0) + filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + } + groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); } - newDatabase.Folders.Add(folder); + } - CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; - newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); + #ifndef _NO_CRYPTO - CNum indexInFolder = 0; - for (CNum fi = db->FolderStartFileIndex[folderIndex]; - indexInFolder < numUnpackStreams; fi++) + CCryptoGetTextPassword *getPasswordSpec = NULL; + if (needEncryptedRepack) + { + getPasswordSpec = new CCryptoGetTextPassword; + threadDecoder.GetTextPassword = getPasswordSpec; + + if (options.Method->PasswordIsDefined) + getPasswordSpec->Password = options.Method->Password; + else { - CFileItem file; - CFileItem2 file2; - db->GetFile(fi, file, file2); - if (file.HasStream) - { - indexInFolder++; - int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0) - { - const CUpdateItem &ui = updateItems[updateIndex]; - if (ui.NewProperties) - { - CFileItem uf; - FromUpdateItemToFileItem(ui, uf, file2); - uf.Size = file.Size; - uf.Crc = file.Crc; - uf.CrcDefined = file.CrcDefined; - uf.HasStream = file.HasStream; - file = uf; - } - } - newDatabase.AddFile(file, file2); - } + if (!getDecoderPassword) + return E_NOTIMPL; + CMyComBSTR password; + RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); + getPasswordSpec->Password = password; } } - folderRefs.ClearAndFree(); - fileIndexToUpdateIndexMap.ClearAndFree(); + #endif - ///////////////////////////////////////// - // Compress New Files + // ---------- Compress ---------- - CObjectVector<CSolidGroup> groups; - SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, - updateItems, groups); + RINOK(archive.Create(seqOutStream, false)); + RINOK(archive.SkipPrefixArchiveHeader()); - const UInt32 kMinReduceSize = (1 << 16); - if (inSizeForReduce < kMinReduceSize) - inSizeForReduce = kMinReduceSize; + int folderRefIndex = 0; + lps->ProgressOffset = 0; - for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) + for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) { const CSolidGroup &group = groups[groupIndex]; + + CCompressionMethodMode method; + if (Is86Group(groupIndex)) + MakeExeMethod(*options.Method, options.MaxFilter, method); + else + method = *options.Method; + + if (IsEncryptedGroup(groupIndex)) + { + if (!method.PasswordIsDefined) + { + #ifndef _NO_CRYPTO + if (getPasswordSpec) + method.Password = getPasswordSpec->Password; + #endif + method.PasswordIsDefined = true; + } + } + else + { + method.PasswordIsDefined = false; + method.Password.Empty(); + } + + CEncoder encoder(method); + + for (; folderRefIndex < folderRefs.Size(); folderRefIndex++) + { + const CFolderRepack &rep = folderRefs[folderRefIndex]; + if (rep.Group != groupIndex) + break; + int folderIndex = rep.FolderIndex; + + if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) + { + UInt64 packSize = db->GetFolderFullPackSize(folderIndex); + RINOK(WriteRange(inStream, archive.SeqStream, + db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); + lps->ProgressOffset += packSize; + + const CFolder &folder = db->Folders[folderIndex]; + CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; + for (int j = 0; j < folder.PackStreams.Size(); j++) + { + newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); + // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); + // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + } + newDatabase.Folders.Add(folder); + } + else + { + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CMyComPtr<ISequentialOutStream> sbOutStream; + CMyComPtr<ISequentialInStream> sbInStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + CBoolVector extractStatuses; + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + CNum indexInFolder = 0; + + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + bool needExtract = false; + if (db->Files[fi].HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + needExtract = true; + } + extractStatuses.Add(needExtract); + } + + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + sbOutStream.Release(); + + threadDecoder.InStream = inStream; + threadDecoder.Folder = &db->Folders[folderIndex]; + threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; + + threadDecoder.Start(); + + int startPackIndex = newDatabase.PackSizes.Size(); + CFolder newFolder; + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, newFolder, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitFinish(); + + RINOK(threadDecoder.Result); + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + lps->InSize += newFolder.GetUnpackSize(); + + newDatabase.Folders.Add(newFolder); + } + + newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + CFileItem file; + CFileItem2 file2; + db->GetFile(fi, file, file2); + if (file.HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0) + { + const CUpdateItem &ui = updateItems[updateIndex]; + if (ui.NewData) + continue; + if (ui.NewProps) + { + CFileItem uf; + FromUpdateItemToFileItem(ui, uf, file2); + uf.Size = file.Size; + uf.Crc = file.Crc; + uf.CrcDefined = file.CrcDefined; + uf.HasStream = file.HasStream; + file = uf; + } + newDatabase.AddFile(file, file2); + } + } + } + } + int numFiles = group.Indices.Size(); if (numFiles == 0) continue; @@ -657,7 +1021,7 @@ static HRESULT Update2( /* const CUpdateItem &ui = updateItems[index]; CFileItem file; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; @@ -667,8 +1031,6 @@ static HRESULT Update2( */ } - CEncoder encoder(group.Method); - for (i = 0; i < numFiles;) { UInt64 totalSize = 0; @@ -710,7 +1072,7 @@ static HRESULT Update2( lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); - // for() + // for () // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); @@ -722,7 +1084,7 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); @@ -761,14 +1123,20 @@ static HRESULT Update2( } } + if (folderRefIndex != folderRefs.Size()) + return E_FAIL; + + /* + folderRefs.ClearAndFree(); + fileIndexToUpdateIndexMap.ClearAndFree(); groups.ClearAndFree(); + */ { - ///////////////////////////////////////// - // Write Empty Files & Folders + // ---------- Write Folders & Empty Files ---------- CRecordVector<int> emptyRefs; - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) @@ -776,10 +1144,8 @@ static HRESULT Update2( if (ui.HasStream()) continue; } - else - if (ui.IndexInArchive != -1) - if (db->Files[ui.IndexInArchive].HasStream) - continue; + else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) + continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); @@ -788,7 +1154,7 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); @@ -800,21 +1166,4 @@ static HRESULT Update2( return S_OK; } -HRESULT Update( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, - const CArchiveDatabaseEx *db, - const CObjectVector<CUpdateItem> &updateItems, - COutArchive &archive, - CArchiveDatabase &newDatabase, - ISequentialOutStream *seqOutStream, - IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options) -{ - return Update2( - EXTERNAL_CODECS_LOC_VARS - inStream, db, updateItems, - archive, newDatabase, seqOutStream, updateCallback, options); -} - }} diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index bcc7cef7..31e36224 100755 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -3,9 +3,9 @@ #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H +#include "7zCompressionMode.h" #include "7zIn.h" #include "7zOut.h" -#include "7zCompressionMode.h" #include "../IArchive.h" @@ -27,7 +27,7 @@ struct CUpdateItem UInt32 Attrib; bool NewData; - bool NewProperties; + bool NewProps; bool IsAnti; bool IsDir; @@ -78,7 +78,11 @@ HRESULT Update( CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options); + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ); }} #endif diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile index 1a72da0e..4489f290 100755 --- a/CPP/7zip/Archive/7z/makefile +++ b/CPP/7zip/Archive/7z/makefile @@ -104,7 +104,7 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) -$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp +$O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index ae388d67..f7bc9c69 100755 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -3,15 +3,12 @@ #include "StdAfx.h" #include "../../Common/ComTry.h" -#include "../../Common/Types.h" + #include "../../Windows/PropVariant.h" -#include "../Common/RegisterArc.h" -#include "IArchive.h" -#include "../ICoder.h" -#include "../IPassword.h" +#include "../Common/RegisterArc.h" -static const unsigned int kNumArcsMax = 32; +static const unsigned int kNumArcsMax = 48; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index c40cbbcd..66ad1677 100755 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -2,14 +2,14 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "Common/ComTry.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" -#include "../../../C/CpuArch.h" - #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -180,6 +180,7 @@ struct CItem UInt32 PackSize; UInt32 Size; UInt32 FileCRC; + UInt32 SplitPos; Byte Version; Byte ExtractVersion; @@ -197,6 +198,8 @@ struct CItem bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; } bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); } + bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; } + bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; } UInt32 GetWinAttributes() const { UInt32 winAtrributes; @@ -240,6 +243,10 @@ HRESULT CItem::Parse(const Byte *p, unsigned size) // FirstChapter = p[28]; // FirstChapter = p[29]; + SplitPos = 0; + if (IsSplitBefore() && firstHeaderSize >= 34) + SplitPos = Get32(p + 30); + unsigned pos = firstHeaderSize; unsigned size1 = size - pos; RINOK(ReadString(p + pos, size1, Name)); @@ -270,7 +277,7 @@ class CInArchive HRESULT ReadBlock(bool &filled); HRESULT ReadSignatureAndBlock(bool &filled); - HRESULT SkeepExtendedHeaders(); + HRESULT SkipExtendedHeaders(); HRESULT SafeReadBytes(void *data, UInt32 size); @@ -389,7 +396,7 @@ HRESULT CInArchive::ReadSignatureAndBlock(bool &filled) return ReadBlock(filled); } -HRESULT CInArchive::SkeepExtendedHeaders() +HRESULT CInArchive::SkipExtendedHeaders() { for (UInt32 i = 0;; i++) { @@ -412,7 +419,7 @@ HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit) if (!filled) return S_FALSE; RINOK(Header.Parse(_block, _blockSize)); - return SkeepExtendedHeaders(); + return SkipExtendedHeaders(); } HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) @@ -428,7 +435,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) extraData = GetUi32(_block + pos); */ - RINOK(SkeepExtendedHeaders()); + RINOK(SkipExtendedHeaders()); filled = true; return S_OK; } @@ -482,8 +489,9 @@ STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPosition, VT_UI8}, + { NULL, kpidPackSize, VT_UI4}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidEncrypted, VT_BOOL}, @@ -556,6 +564,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidIsDir: prop = item.IsDir(); break; case kpidSize: prop = item.Size; break; case kpidPackSize: prop = item.PackSize; break; + case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break; case kpidAttrib: prop = item.GetWinAttributes(); break; case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidCRC: prop = item.FileCRC; break; diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.cpp b/CPP/7zip/Archive/BZip2/BZip2Handler.cpp deleted file mode 100755 index 05716b62..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Handler.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// BZip2Handler.cpp - -#include "StdAfx.h" - -#include "Common/ComTry.h" - -#include "Windows/PropVariant.h" - -#include "../../Common/CreateCoder.h" -#include "../../Common/ProgressUtils.h" -#include "../../Common/StreamUtils.h" - -#include "../Common/DummyOutStream.h" - -#include "BZip2Handler.h" - -using namespace NWindows; - -namespace NArchive { -namespace NBZip2 { - -static const CMethodId kMethodId_BZip2 = 0x040202; - -STATPROPSTG kProps[] = -{ - { NULL, kpidPackSize, VT_UI8} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = 1; - return S_OK; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) -{ - NWindows::NCOM::CPropVariant prop; - switch(propID) - { - case kpidPackSize: prop = _item.PackSize; break; - } - prop.Detach(value); - return S_OK; -} - -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) -{ - COM_TRY_BEGIN - try - { - RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition)); - const int kSignatureSize = 3; - Byte buffer[kSignatureSize]; - RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize)); - if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h') - return S_FALSE; - - UInt64 endPosition; - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); - _item.PackSize = endPosition - _streamStartPosition; - - _stream = stream; - } - catch(...) - { - return S_FALSE; - } - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - _stream.Release(); - return S_OK; -} - - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 testModeSpec, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); - if (!allFilesMode) - { - if (numItems == 0) - return S_OK; - if (numItems != 1) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } - - bool testMode = (testModeSpec != 0); - - extractCallback->SetTotal(_item.PackSize); - - UInt64 currentTotalPacked = 0; - - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); - - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - if(!testMode && !realOutStream) - return S_OK; - - - extractCallback->PrepareOperation(askMode); - - CMyComPtr<ICompressCoder> decoder; - HRESULT loadResult = CreateCoder( - EXTERNAL_CODECS_VARS - kMethodId_BZip2, decoder, false); - if (loadResult != S_OK || !decoder) - { - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); - return S_OK; - } - - #ifdef COMPRESS_MT - { - CMyComPtr<ICompressSetCoderMt> setCoderMt; - decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); - if (setCoderMt) - { - RINOK(setCoderMt->SetNumberOfThreads(_numThreads)); - } - } - #endif - - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - - realOutStream.Release(); - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL)); - - HRESULT result = S_OK; - - bool firstItem = true; - for (;;) - { - lps->InSize = currentTotalPacked; - lps->OutSize = outStreamSpec->GetSize(); - - RINOK(lps->SetCur()); - - const int kSignatureSize = 3; - Byte buffer[kSignatureSize]; - size_t processedSize = kSignatureSize; - RINOK(ReadStream(_stream, buffer, &processedSize)); - if (processedSize != kSignatureSize) - { - if (firstItem) - return E_FAIL; - break; - } - if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h') - { - if (firstItem) - return E_FAIL; - break; - } - firstItem = false; - - UInt64 dataStartPos; - RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos)); - - result = decoder->Code(_stream, outStream, NULL, NULL, progress); - - if (result != S_OK) - break; - - CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; - decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); - if (!getInStreamProcessedSize) - break; - UInt64 packSize; - RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize)); - UInt64 pos; - RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos)); - currentTotalPacked = pos - _streamStartPosition; - } - outStream.Release(); - - Int32 retResult; - if (result == S_OK) - retResult = NExtract::NOperationResult::kOK; - else if (result == S_FALSE) - retResult = NExtract::NOperationResult::kDataError; - else - return result; - return extractCallback->SetOperationResult(retResult); - - COM_TRY_END -} - -IMPL_ISetCompressCodecsInfo - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.h b/CPP/7zip/Archive/BZip2/BZip2Handler.h deleted file mode 100755 index 5bb3360a..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Handler.h +++ /dev/null @@ -1,68 +0,0 @@ -// BZip2/Handler.h - -#ifndef __BZIP2_HANDLER_H -#define __BZIP2_HANDLER_H - -#include "Common/MyCom.h" -#include "../IArchive.h" -#include "../../Common/CreateCoder.h" -#include "BZip2Item.h" - -#ifdef COMPRESS_MT -#include "../../../Windows/System.h" -#endif - -namespace NArchive { -namespace NBZip2 { - -class CHandler: - public IInArchive, - public IOutArchive, - public ISetProperties, - PUBLIC_ISetCompressCodecsInfo - public CMyUnknownImp -{ - CMyComPtr<IInStream> _stream; - NArchive::NBZip2::CItem _item; - UInt64 _streamStartPosition; - - UInt32 _level; - UInt32 _dicSize; - UInt32 _numPasses; - #ifdef COMPRESS_MT - UInt32 _numThreads; - #endif - - DECL_EXTERNAL_CODECS_VARS - - void InitMethodProperties() - { - _level = 5; - _dicSize = - _numPasses = 0xFFFFFFFF; - #ifdef COMPRESS_MT - _numThreads = NWindows::NSystem::GetNumberOfProcessors();; - #endif - } - -public: - MY_QUERYINTERFACE_BEGIN2(IInArchive) - MY_QUERYINTERFACE_ENTRY(IOutArchive) - MY_QUERYINTERFACE_ENTRY(ISetProperties) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - - INTERFACE_IInArchive(;) - INTERFACE_IOutArchive(;) - - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); - - DECL_ISetCompressCodecsInfo - - CHandler() { InitMethodProperties(); } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp b/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp deleted file mode 100755 index 71311c32..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// BZip2HandlerOut.cpp - -#include "StdAfx.h" - -#include "BZip2Handler.h" -#include "BZip2Update.h" - -#include "Common/Defs.h" - -#include "Windows/PropVariant.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/ParseProperties.h" - -using namespace NWindows; - -static const UInt32 kNumPassesX1 = 1; -static const UInt32 kNumPassesX7 = 2; -static const UInt32 kNumPassesX9 = 7; - -static const UInt32 kDicSizeX1 = 100000; -static const UInt32 kDicSizeX3 = 500000; -static const UInt32 kDicSizeX5 = 900000; - -namespace NArchive { -namespace NBZip2 { - -STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) -{ - *type = NFileTimeType::kUnix; - return S_OK; -} - -static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream) -{ - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); -} - -STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, - IArchiveUpdateCallback *updateCallback) -{ - if (numItems != 1) - return E_INVALIDARG; - - Int32 newData; - Int32 newProperties; - UInt32 indexInArchive; - if (!updateCallback) - return E_FAIL; - RINOK(updateCallback->GetUpdateItemInfo(0,&newData, &newProperties, &indexInArchive)); - - if (IntToBool(newProperties)) - { - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); - if (prop.vt == VT_BOOL) - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; - } - } - - if (IntToBool(newData)) - { - UInt64 size; - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - - UInt32 dicSize = _dicSize; - if (dicSize == 0xFFFFFFFF) - dicSize = (_level >= 5 ? kDicSizeX5 : - (_level >= 3 ? kDicSizeX3 : - kDicSizeX1)); - - UInt32 numPasses = _numPasses; - if (numPasses == 0xFFFFFFFF) - numPasses = (_level >= 9 ? kNumPassesX9 : - (_level >= 7 ? kNumPassesX7 : - kNumPassesX1)); - - return UpdateArchive( - EXTERNAL_CODECS_VARS - size, outStream, 0, dicSize, numPasses, - #ifdef COMPRESS_MT - _numThreads, - #endif - updateCallback); - } - if (indexInArchive != 0) - return E_INVALIDARG; - RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL)); - return CopyStreams(_stream, outStream); -} - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) -{ - InitMethodProperties(); - #ifdef COMPRESS_MT - const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); - _numThreads = numProcessors; - #endif - - for (int i = 0; i < numProperties; i++) - { - UString name = UString(names[i]); - name.MakeUpper(); - if (name.IsEmpty()) - return E_INVALIDARG; - - const PROPVARIANT &prop = values[i]; - - if (name[0] == 'X') - { - UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - _level = level; - continue; - } - if (name[0] == 'D') - { - UInt32 dicSize = kDicSizeX5; - RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); - _dicSize = dicSize; - continue; - } - if (name.Left(4) == L"PASS") - { - UInt32 num = kNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - _numPasses = num; - continue; - } - if (name.Left(2) == L"MT") - { - #ifdef COMPRESS_MT - RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); - #endif - continue; - } - return E_INVALIDARG; - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Item.h b/CPP/7zip/Archive/BZip2/BZip2Item.h deleted file mode 100755 index d7508ab9..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Item.h +++ /dev/null @@ -1,20 +0,0 @@ -// Archive/BZip2Item.h - -#ifndef __ARCHIVE_BZIP2_ITEM_H -#define __ARCHIVE_BZIP2_ITEM_H - -namespace NArchive { -namespace NBZip2 { - -struct CItem -{ - UInt64 PackSize; - UInt64 UnPackSize; -}; - -}} - -#endif - - - diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.cpp b/CPP/7zip/Archive/BZip2/BZip2Update.cpp deleted file mode 100755 index 300d8844..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Update.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// BZip2Update.cpp - -#include "StdAfx.h" - -#include "../../Common/ProgressUtils.h" -#include "../../Common/CreateCoder.h" -#include "Windows/PropVariant.h" - -#include "BZip2Update.h" - -namespace NArchive { -namespace NBZip2 { - -static const CMethodId kMethodId_BZip2 = 0x040202; - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt64 unpackSize, - ISequentialOutStream *outStream, - int indexInClient, - UInt32 dictionary, - UInt32 numPasses, - #ifdef COMPRESS_MT - UInt32 numThreads, - #endif - IArchiveUpdateCallback *updateCallback) -{ - RINOK(updateCallback->SetTotal(unpackSize)); - UInt64 complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); - - CMyComPtr<ISequentialInStream> fileInStream; - - RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); - - CLocalProgress *localProgressSpec = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; - localProgressSpec->Init(updateCallback, true); - - CMyComPtr<ICompressCoder> encoder; - RINOK(CreateCoder( - EXTERNAL_CODECS_LOC_VARS - kMethodId_BZip2, encoder, true)); - if (!encoder) - return E_NOTIMPL; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); - if (setCoderProperties) - { - NWindows::NCOM::CPropVariant properties[] = - { - dictionary, - numPasses - #ifdef COMPRESS_MT - , numThreads - #endif - }; - PROPID propIDs[] = - { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumPasses - #ifdef COMPRESS_MT - , NCoderPropID::kNumThreads - #endif - }; - RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); - } - - RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); - - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); -} - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.h b/CPP/7zip/Archive/BZip2/BZip2Update.h deleted file mode 100755 index e54a7e16..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Update.h +++ /dev/null @@ -1,26 +0,0 @@ -// BZip2Update.h - -#ifndef __BZIP2_UPDATE_H -#define __BZIP2_UPDATE_H - -#include "../IArchive.h" -#include "../../Common/CreateCoder.h" - -namespace NArchive { -namespace NBZip2 { - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt64 unpackSize, - ISequentialOutStream *outStream, - int indexInClient, - UInt32 dictionary, - UInt32 numPasses, - #ifdef COMPRESS_MT - UInt32 numThreads, - #endif - IArchiveUpdateCallback *updateCallback); - -}} - -#endif diff --git a/CPP/7zip/Archive/BZip2/StdAfx.h b/CPP/7zip/Archive/BZip2/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/BZip2/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/BZip2/bz2Register.cpp b/CPP/7zip/Archive/BZip2/bz2Register.cpp deleted file mode 100755 index 76d3d25b..00000000 --- a/CPP/7zip/Archive/BZip2/bz2Register.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// BZip2Register.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "BZip2Handler.h" -static IInArchive *CreateArc() { return new NArchive::NBZip2::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NBZip2::CHandler; } -#else -#define CreateArcOut 0 -#endif - -static CArcInfo g_ArcInfo = - { L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut }; - -REGISTER_ARC(BZip2) diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp new file mode 100755 index 00000000..9b2c4048 --- /dev/null +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -0,0 +1,428 @@ +// Bz2Handler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#ifdef COMPRESS_MT +#include "../../Windows/System.h" +#endif + +#include "../Common/CreateCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/BZip2Decoder.h" +#include "../Compress/BZip2Encoder.h" +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" +#include "Common/ParseProperties.h" + +using namespace NWindows; + +namespace NArchive { +namespace NBz2 { + +static const UInt32 kNumPassesX1 = 1; +static const UInt32 kNumPassesX7 = 2; +static const UInt32 kNumPassesX9 = 7; + +static const UInt32 kDicSizeX1 = 100000; +static const UInt32 kDicSizeX3 = 500000; +static const UInt32 kDicSizeX5 = 900000; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + UInt64 _packSize; + UInt64 _startPosition; + bool _packSizeDefined; + + UInt32 _level; + UInt32 _dicSize; + UInt32 _numPasses; + #ifdef COMPRESS_MT + UInt32 _numThreads; + #endif + + void InitMethodProperties() + { + _level = 5; + _dicSize = + _numPasses = 0xFFFFFFFF; + #ifdef COMPRESS_MT + _numThreads = NWindows::NSystem::GetNumberOfProcessors();; + #endif + } + +public: + MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + + CHandler() { InitMethodProperties(); } +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPackSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + try + { + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + const int kSignatureSize = 3; + Byte buf[kSignatureSize]; + RINOK(ReadStream_FALSE(stream, buf, kSignatureSize)); + if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h') + return S_FALSE; + + UInt64 endPosition; + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); + _packSize = endPosition - _startPosition; + _packSizeDefined = true; + _stream = stream; + _seqStream = stream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _seqStream.Release(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (!allFilesMode) + { + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + } + + bool testMode = (_aTestMode != 0); + if (_stream) + extractCallback->SetTotal(_packSize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; + CMyComPtr<ICompressCoder> decoder = decoderSpec; + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + decoderSpec->SetInStream(_seqStream); + + #if defined( COMPRESS_MT) && defined( COMPRESS_BZIP2_MT) + RINOK(decoderSpec->SetNumberOfThreads(_numThreads)); + #endif + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + HRESULT result = S_OK; + + bool firstItem = true; + for (;;) + { + lps->InSize = currentTotalPacked; + lps->OutSize = outStreamSpec->GetSize(); + + RINOK(lps->SetCur()); + + bool isBz2; + result = decoderSpec->CodeResume(outStream, isBz2, progress); + + if (result != S_OK) + break; + if (!isBz2) + { + if (firstItem) + result = S_FALSE; + break; + } + firstItem = false; + + _packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize(); + _packSizeDefined = true; + } + decoderSpec->ReleaseInStream(); + outStream.Release(); + + Int32 retResult; + if (result == S_OK) + retResult = NExtract::NOperationResult::kOK; + else if (result == S_FALSE) + retResult = NExtract::NOperationResult::kDataError; + else + return result; + return extractCallback->SetOperationResult(retResult); + + COM_TRY_END +} + +static HRESULT UpdateArchive( + UInt64 unpackSize, + ISequentialOutStream *outStream, + int indexInClient, + UInt32 dictionary, + UInt32 numPasses, + #ifdef COMPRESS_MT + UInt32 numThreads, + #endif + IArchiveUpdateCallback *updateCallback) +{ + RINOK(updateCallback->SetTotal(unpackSize)); + UInt64 complexity = 0; + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr<ISequentialInStream> fileInStream; + + RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; + localProgressSpec->Init(updateCallback, true); + + NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; + CMyComPtr<ICompressCoder> encoder = encoderSpec; + { + NWindows::NCOM::CPropVariant properties[] = + { + dictionary, + numPasses + #ifdef COMPRESS_MT + , numThreads + #endif + }; + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kNumPasses + #ifdef COMPRESS_MT + , NCoderPropID::kNumThreads + #endif + }; + RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); + } + + RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); + + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + if (numItems != 1) + return E_INVALIDARG; + + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); + + if (IntToBool(newProps)) + { + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); + if (prop.vt == VT_BOOL) + { + if (prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + } + + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + + UInt32 dicSize = _dicSize; + if (dicSize == 0xFFFFFFFF) + dicSize = (_level >= 5 ? kDicSizeX5 : + (_level >= 3 ? kDicSizeX3 : + kDicSizeX1)); + + UInt32 numPasses = _numPasses; + if (numPasses == 0xFFFFFFFF) + numPasses = (_level >= 9 ? kNumPassesX9 : + (_level >= 7 ? kNumPassesX7 : + kNumPassesX1)); + + return UpdateArchive( + size, outStream, 0, dicSize, numPasses, + #ifdef COMPRESS_MT + _numThreads, + #endif + updateCallback); + } + if (indexInArchive != 0) + return E_INVALIDARG; + if (_stream) + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProperties(); + #ifdef COMPRESS_MT + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + #endif + + for (int i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &prop = values[i]; + if (name[0] == L'X') + { + UInt32 level = 9; + RINOK(ParsePropValue(name.Mid(1), prop, level)); + _level = level; + } + else if (name[0] == L'D') + { + UInt32 dicSize = kDicSizeX5; + RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); + _dicSize = dicSize; + } + else if (name.Left(4) == L"PASS") + { + UInt32 num = kNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + _numPasses = num; + } + else if (name.Left(2) == L"MT") + { + #ifdef COMPRESS_MT + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + #endif + } + else + return E_INVALIDARG; + } + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(BZip2) + +}} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp index 308616b8..12c73eb5 100755 --- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/Alloc.h" -} #include "Common/Defs.h" diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index 2b0a426b..afc0faed 100755 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -57,7 +57,7 @@ void CInArchive::ReadOtherArchive(COtherArchive &oa) oa.DiskName = SafeReadName(); } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); @@ -104,7 +104,7 @@ HRESULT CInArchive::Open2(IInStream *stream, ai.PerFolderAreaSize = ReadByte(); ai.PerDataBlockAreaSize = ReadByte(); - Skeep(ai.PerCabinetAreaSize); + Skip(ai.PerCabinetAreaSize); } { @@ -124,7 +124,7 @@ HRESULT CInArchive::Open2(IInStream *stream, folder.CompressionTypeMajor = ReadByte(); folder.CompressionTypeMinor = ReadByte(); - Skeep(ai.PerFolderAreaSize); + Skip(ai.PerFolderAreaSize); database.Folders.Add(folder); } diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index 197017b9..c9cfcbdd 100755 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -149,7 +149,7 @@ class CInArchive UInt16 ReadUInt16(); UInt32 ReadUInt32(); AString SafeReadName(); - void Skeep(size_t size); + void Skip(size_t size); void ReadOtherArchive(COtherArchive &oa); HRESULT Open2(IInStream *inStream, diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 1379b1fd..cc571937 100755 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -2,13 +2,11 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/MyCom.h" -#include "Common/UTFConvert.h" #include "Common/IntToString.h" -#include "Windows/Defs.h" +#include "Common/UTFConvert.h" #include "../../Common/LimitedStreams.h" + #include "ChmIn.h" namespace NArchive{ @@ -96,9 +94,8 @@ UString CMethodInfo::GetName() const if (IsLzx()) { s = L"LZX:"; - UInt32 numDictBits = LzxInfo.GetNumDictBits(); - wchar_t temp[32]; - ConvertUInt64ToString(numDictBits, temp); + wchar_t temp[16]; + ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp); s += temp; } else @@ -111,7 +108,7 @@ UString CMethodInfo::GetName() const s2 = GetGuidString(); if (ControlData.GetCapacity() > 0) { - s2 += ":"; + s2 += ':'; for (size_t i = 0; i < ControlData.GetCapacity(); i++) PrintByte(ControlData[i], s2); } @@ -141,7 +138,7 @@ UString CSectionInfo::GetMethodName() const for (int i = 0; i < Methods.Size(); i++) { if (i != 0) - s += L" "; + s += L' '; s += Methods[i].GetName(); } return s; @@ -155,7 +152,7 @@ Byte CInArchive::ReadByte() return b; } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); @@ -221,7 +218,7 @@ void CInArchive::ReadString(int size, AString &s) char c = (char)ReadByte(); if (c == 0) { - Skeep(size); + Skip(size); return; } s += c; @@ -236,7 +233,7 @@ void CInArchive::ReadUString(int size, UString &s) wchar_t c = ReadUInt16(); if (c == 0) { - Skeep(2 * size); + Skip(2 * size); return; } s += c; @@ -372,12 +369,12 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) RINOK(ReadDirEntry(database)); numItems++; } - Skeep(quickrefLength - 2); + Skip(quickrefLength - 2); if (ReadUInt16() != numItems) return S_FALSE; } else - Skeep(dirChunkSize - 4); + Skip(dirChunkSize - 4); } return S_OK; } @@ -579,7 +576,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) } numItems++; } - Skeep(quickrefLength - 2); + Skip(quickrefLength - 2); if (ReadUInt16() != numItems) return S_FALSE; if (numItems > numDirEntries) @@ -587,7 +584,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) numDirEntries -= numItems; } else - Skeep(dirChunkSize - 4); + Skip(dirChunkSize - 4); } return numDirEntries == 0 ? S_OK : S_FALSE; } diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index 943336cb..4719a484 100755 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -3,10 +3,12 @@ #ifndef __ARCHIVE_CHM_IN_H #define __ARCHIVE_CHM_IN_H -#include "Common/MyString.h" #include "Common/Buffer.h" +#include "Common/MyString.h" + #include "../../IStream.h" #include "../../Common/InBuffer.h" + #include "ChmHeader.h" namespace NArchive { @@ -215,7 +217,7 @@ class CInArchive Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); - void Skeep(size_t size); + void Skip(size_t size); UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp index 8b46976c..287f6156 100755 --- a/CPP/7zip/Archive/Com/ComHandler.cpp +++ b/CPP/7zip/Archive/Com/ComHandler.cpp @@ -3,8 +3,15 @@ #include "StdAfx.h" #include "Common/ComTry.h" + #include "Windows/PropVariant.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" + #include "ComHandler.h" namespace NArchive { @@ -15,16 +22,15 @@ STATPROPSTG kProps[] = { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, - // { NULL, kpidAttributes, VT_UI4}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME} }; - STATPROPSTG kArcProps[] = { - { NULL, kpidClusterSize, VT_UI4} + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4} }; IMP_IInArchive_Props @@ -37,6 +43,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) switch(propID) { case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; + case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; } prop.Detach(value); return S_OK; @@ -52,33 +59,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch(propID) { - case kpidPath: - { - UString name = _db.GetItemPath(index); - prop = name; - break; - } + case kpidPath: prop = _db.GetItemPath(index); break; case kpidIsDir: prop = item.IsDir(); break; case kpidCTime: prop = item.CTime; break; case kpidMTime: prop = item.MTime; break; - /* - case kpidAttributes: - prop = item.Falgs; - break; - */ - case kpidPackSize: - if (!item.IsDir()) - { - int numBits = _db.IsLargeStream(item.Size) ? - _db.SectorSizeBits : - _db.MiniSectorSizeBits; - prop = (item.Size + ((UInt64)1 << numBits) - 1) >> numBits << numBits; - break; - } - case kpidSize: - if (!item.IsDir()) - prop = (UInt64)item.Size; - break; + case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; } prop.Detach(value); return S_OK; @@ -93,7 +79,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, Close(); try { - if (OpenArchive(inStream, _db) != S_OK) + if (_db.Open(inStream) != S_OK) return S_FALSE; _stream = inStream; } @@ -129,25 +115,29 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, } RINOK(extractCallback->SetTotal(totalSize)); - UInt64 currentTotalSize = 0, currentItemSize = 0; + UInt64 totalPackSize; + totalSize = totalPackSize = 0; - CByteBuffer sect; - sect.SetCapacity((UInt32)1 << _db.SectorSizeBits); + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) { - RINOK(extractCallback->SetCompleted(¤tTotalSize)); + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); Int32 index = allFilesMode ? i : indices[i]; const CItem &item = _db.Items[_db.Refs[index].Did]; - currentItemSize = 0; - if (!item.IsDir()) - currentItemSize = item.Size; - CMyComPtr<ISequentialOutStream> realOutStream; + CMyComPtr<ISequentialOutStream> outStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->GetStream(index, &outStream, askMode)); if (item.IsDir()) { @@ -155,75 +145,31 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - if (!testMode && (!realOutStream)) + + totalPackSize += _db.GetItemPackSize(item.Size); + totalSize += item.Size; + + if (!testMode && (!outStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); Int32 res = NArchive::NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + HRESULT hres = GetStream(index, &inStream); + if (hres == S_FALSE) + res = NArchive::NExtract::NOperationResult::kDataError; + else if (hres == E_NOTIMPL) + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else { - UInt32 sid = item.Sid; - UInt64 prev = 0; - for (UInt64 pos = 0;;) + RINOK(hres); + if (inStream) { - if (sid == NFatID::kEndOfChain) - { - if (pos != item.Size) - break; + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) res = NArchive::NExtract::NOperationResult::kOK; - break; - } - if (pos >= item.Size) - break; - - UInt64 offset; - UInt32 size; - - if (_db.IsLargeStream(item.Size)) - { - if (pos - prev > (1 << 20)) - { - UInt64 processed = currentTotalSize + pos; - RINOK(extractCallback->SetCompleted(&processed)); - prev = pos; - } - size = 1 << _db.SectorSizeBits; - offset = ((UInt64)sid + 1) << _db.SectorSizeBits; - if (sid >= _db.FatSize) - break; - sid = _db.Fat[sid]; - } - else - { - int subBits = (_db.SectorSizeBits - _db.MiniSectorSizeBits); - UInt32 fid = sid >> subBits; - if (fid >= _db.NumSectorsInMiniStream) - break; - size = 1 << _db.MiniSectorSizeBits; - offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) + - ((sid & ((1 << subBits) - 1)) << _db.MiniSectorSizeBits); - if (sid >= _db.MatSize) - break; - sid = _db.Mat[sid]; - } - - // last sector can be smaller than sector size (it can contain requied data only). - UInt64 rem = item.Size - pos; - if (size > rem) - size = (UInt32)rem; - - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - size_t realProcessedSize = size; - RINOK(ReadStream(_stream, sect, &realProcessedSize)); - if (realProcessedSize != size) - break; - - if (realOutStream) - { - RINOK(WriteStream(realOutStream, sect, size)); - } - pos += size; } } - realOutStream.Release(); + outStream.Release(); RINOK(extractCallback->SetOperationResult(res)); } return S_OK; @@ -236,4 +182,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + const CItem &item = _db.Items[_db.Refs[index].Did]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->Stream = _stream; + streamSpec->StartOffset = 0; + + bool isLargeStream = _db.IsLargeStream(item.Size); + int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits; + streamSpec->BlockSizeLog = bsLog; + streamSpec->Size = item.Size; + + UInt32 clusterSize = (UInt32)1 << bsLog; + UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; + if (numClusters64 >= ((UInt32)1 << 31)) + return E_NOTIMPL; + streamSpec->Vector.Reserve((int)numClusters64); + UInt32 sid = item.Sid; + UInt64 size = item.Size; + + if (size != 0) + { + for (;; size -= clusterSize) + { + if (isLargeStream) + { + if (sid >= _db.FatSize) + return S_FALSE; + streamSpec->Vector.Add(sid + 1); + sid = _db.Fat[sid]; + } + else + { + UInt64 val; + if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32) + return S_FALSE; + streamSpec->Vector.Add((UInt32)val); + sid = _db.Mat[sid]; + } + if (size <= clusterSize) + break; + } + } + if (sid != NFatID::kEndOfChain) + return S_FALSE; + RINOK(streamSpec->InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + }} diff --git a/CPP/7zip/Archive/Com/ComHandler.h b/CPP/7zip/Archive/Com/ComHandler.h index 89bc98d0..f2b7de96 100755 --- a/CPP/7zip/Archive/Com/ComHandler.h +++ b/CPP/7zip/Archive/Com/ComHandler.h @@ -12,15 +12,15 @@ namespace NCom { class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP1(IInArchive) - INTERFACE_IInArchive(;) - -private: CMyComPtr<IInStream> _stream; CDatabase _db; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Com/ComIn.cpp b/CPP/7zip/Archive/Com/ComIn.cpp index 74e601c1..8f622122 100755 --- a/CPP/7zip/Archive/Com/ComIn.cpp +++ b/CPP/7zip/Archive/Com/ComIn.cpp @@ -2,19 +2,19 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/Alloc.h" -} - #include "../../../../C/CpuArch.h" +#include "Common/IntToString.h" #include "Common/MyCom.h" + #include "../../Common/StreamUtils.h" -#include "Common/IntToString.h" #include "ComIn.h" +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + namespace NArchive{ namespace NCom{ @@ -50,31 +50,40 @@ static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt3 RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)); UInt32 sectorSize = (UInt32)1 << sectorSizeBits; for (UInt32 t = 0; t < sectorSize; t += 4) - *dest++ = GetUi32(buf + t); + *dest++ = Get32(buf + t); return S_OK; } static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) { - ft->dwLowDateTime = GetUi32(p); - ft->dwHighDateTime = GetUi32(p + 4); + ft->dwLowDateTime = Get32(p); + ft->dwHighDateTime = Get32(p + 4); } -static void ReadItem(Byte *p, CItem &item, bool mode64bit) +void CItem::Parse(const Byte *p, bool mode64bit) { - memcpy(item.Name, p, 64); - // item.NameSize = GetUi16(p + 64); - item.Type = p[66]; - item.LeftDid = GetUi32(p + 68); - item.RightDid = GetUi32(p + 72); - item.SonDid = GetUi32(p + 76); - // item.Flags = GetUi32(p + 96); - GetFileTimeFromMem(p + 100, &item.CTime); - GetFileTimeFromMem(p + 108, &item.MTime); - item.Sid = GetUi32(p + 116); - item.Size = GetUi32(p + 120); + memcpy(Name, p, kNameSizeMax); + // NameSize = Get16(p + 64); + Type = p[66]; + LeftDid = Get32(p + 68); + RightDid = Get32(p + 72); + SonDid = Get32(p + 76); + // Flags = Get32(p + 96); + GetFileTimeFromMem(p + 100, &CTime); + GetFileTimeFromMem(p + 108, &MTime); + Sid = Get32(p + 116); + Size = Get32(p + 120); if (mode64bit) - item.Size |= ((UInt64)GetUi32(p + 124) << 32); + Size |= ((UInt64)Get32(p + 124) << 32); +} + +void CDatabase::Clear() +{ + Fat.Free(); + MiniSids.Free(); + Mat.Free(); + Items.Clear(); + Refs.Clear(); } static const UInt32 kNoDid = 0xFFFFFFFF; @@ -106,13 +115,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did) static const char kCharOpenBracket = '['; static const char kCharCloseBracket = ']'; -UString DWORDToString(UInt32 val) -{ - wchar_t buf[32]; - ConvertUInt64ToString(val, buf); - return buf; -} - static UString CompoundNameToFileName(const UString &s) { UString res; @@ -122,7 +124,9 @@ static UString CompoundNameToFileName(const UString &s) if (c < 0x20) { res += kCharOpenBracket; - res += DWORDToString(c); + wchar_t buf[32]; + ConvertUInt32ToString(c, buf); + res += buf; res += kCharCloseBracket; } else @@ -201,31 +205,30 @@ UString CDatabase::GetItemPath(UInt32 index) const return s; } -HRESULT OpenArchive(IInStream *inStream, CDatabase &db) +HRESULT CDatabase::Open(IInStream *inStream) { static const UInt32 kHeaderSize = 512; Byte p[kHeaderSize]; RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); if (memcmp(p, kSignature, kSignatureSize) != 0) return S_FALSE; - UInt16 majorVer = GetUi16(p + 0x1A); - if (majorVer > 4) + if (Get16(p + 0x1A) > 4) // majorVer return S_FALSE; - if (GetUi16(p + 0x1C) != 0xFFFE) + if (Get16(p + 0x1C) != 0xFFFE) return S_FALSE; - UInt16 sectorSizeBits = GetUi16(p + 0x1E); + int sectorSizeBits = Get16(p + 0x1E); bool mode64bit = (sectorSizeBits >= 12); - UInt16 miniSectorSizeBits = GetUi16(p + 0x20); - db.SectorSizeBits = sectorSizeBits; - db.MiniSectorSizeBits = miniSectorSizeBits; + int miniSectorSizeBits = Get16(p + 0x20); + SectorSizeBits = sectorSizeBits; + MiniSectorSizeBits = miniSectorSizeBits; if (sectorSizeBits > 28 || miniSectorSizeBits > 28 || sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits) return S_FALSE; - UInt32 numSectorsForFAT = GetUi32(p + 0x2C); - db.LongStreamMinSize = GetUi32(p + 0x38); + UInt32 numSectorsForFAT = Get32(p + 0x2C); + LongStreamMinSize = Get32(p + 0x38); - UInt32 sectSize = (UInt32)1 << (int)(sectorSizeBits); + UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits; CByteBuffer sect; sect.SetCapacity(sectSize); @@ -235,11 +238,11 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) UInt32 numFatItems = numSectorsForFAT << ssb2; if ((numFatItems >> ssb2) != numSectorsForFAT) return S_FALSE; - db.FatSize = numFatItems; + FatSize = numFatItems; { CUInt32Buf bat; - UInt32 numSectorsForBat = GetUi32(p + 0x48); + UInt32 numSectorsForBat = Get32(p + 0x48); const UInt32 kNumHeaderBatItems = 109; UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) @@ -248,8 +251,8 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) return S_FALSE; UInt32 i; for (i = 0; i < kNumHeaderBatItems; i++) - bat[i] = GetUi32(p + 0x4c + i * 4); - UInt32 sid = GetUi32(p + 0x44); + bat[i] = Get32(p + 0x4c + i * 4); + UInt32 sid = Get32(p + 0x44); for (UInt32 s = 0; s < numSectorsForBat; s++) { RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)); @@ -258,7 +261,7 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) } numBatItems = i; - if (!db.Fat.Allocate(numFatItems)) + if (!Fat.Allocate(numFatItems)) return S_FALSE; UInt32 j = 0; @@ -266,33 +269,33 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) { if (j >= numBatItems) return S_FALSE; - RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], db.Fat + i)); + RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i)); } } UInt32 numMatItems; { - UInt32 numSectorsForMat = GetUi32(p + 0x40); + UInt32 numSectorsForMat = Get32(p + 0x40); numMatItems = (UInt32)numSectorsForMat << ssb2; if ((numMatItems >> ssb2) != numSectorsForMat) return S_FALSE; - if (!db.Mat.Allocate(numMatItems)) + if (!Mat.Allocate(numMatItems)) return S_FALSE; UInt32 i; - UInt32 sid = GetUi32(p + 0x3C); + UInt32 sid = Get32(p + 0x3C); for (i = 0; i < numMatItems; i += numSidsInSec) { - RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, db.Mat + i)); + RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i)); if (sid >= numFatItems) return S_FALSE; - sid = db.Fat[sid]; + sid = Fat[sid]; } if (sid != NFatID::kEndOfChain) return S_FALSE; } { - UInt32 sid = GetUi32(p + 0x30); + UInt32 sid = Get32(p + 0x30); for (;;) { if (sid >= numFatItems) @@ -301,16 +304,16 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) for (UInt32 i = 0; i < sectSize; i += 128) { CItem item; - ReadItem(sect + i, item, mode64bit); - db.Items.Add(item); + item.Parse(sect + i, mode64bit); + Items.Add(item); } - sid = db.Fat[sid]; + sid = Fat[sid]; if (sid == NFatID::kEndOfChain) break; } } - CItem root = db.Items[0]; + CItem root = Items[0]; { UInt32 numSectorsInMiniStream; @@ -320,19 +323,18 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) return S_FALSE; numSectorsInMiniStream = (UInt32)numSatSects64; } - db.NumSectorsInMiniStream = numSectorsInMiniStream; - if (!db.MiniSids.Allocate(numSectorsInMiniStream)) + NumSectorsInMiniStream = numSectorsInMiniStream; + if (!MiniSids.Allocate(numSectorsInMiniStream)) return S_FALSE; { UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; if (matSize64 > NFatID::kMaxValue) return S_FALSE; - db.MatSize = (UInt32)matSize64; - if (numMatItems < db.MatSize) + MatSize = (UInt32)matSize64; + if (numMatItems < MatSize) return S_FALSE; } - UInt32 sid = root.Sid; for (UInt32 i = 0; ; i++) { @@ -344,14 +346,14 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) } if (i >= numSectorsInMiniStream) return S_FALSE; - db.MiniSids[i] = sid; + MiniSids[i] = sid; if (sid >= numFatItems) return S_FALSE; - sid = db.Fat[sid]; + sid = Fat[sid]; } } - return db.AddNode(-1, root.SonDid); + return AddNode(-1, root.SonDid); } }} diff --git a/CPP/7zip/Archive/Com/ComIn.h b/CPP/7zip/Archive/Com/ComIn.h index 081c6aaa..05fc7387 100755 --- a/CPP/7zip/Archive/Com/ComIn.h +++ b/CPP/7zip/Archive/Com/ComIn.h @@ -57,6 +57,8 @@ struct CItem bool IsEmpty() const { return Type == NItemType::kEmpty; } bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } + + void Parse(const Byte *p, bool mode64bit); }; struct CRef @@ -67,15 +69,15 @@ struct CRef class CDatabase { -public: + UInt32 NumSectorsInMiniStream; + CUInt32Buf MiniSids; + HRESULT AddNode(int parent, UInt32 did); +public: CUInt32Buf Fat; UInt32 FatSize; - CUInt32Buf MiniSids; - UInt32 NumSectorsInMiniStream; - CUInt32Buf Mat; UInt32 MatSize; @@ -86,20 +88,29 @@ public: int SectorSizeBits; int MiniSectorSizeBits; - void Clear() + void Clear(); + bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } + UString GetItemPath(UInt32 index) const; + + UInt64 GetItemPackSize(UInt64 size) const { - Fat.Free(); - MiniSids.Free(); - Mat.Free(); - Items.Clear(); - Refs.Clear(); + UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; + return (size + mask) & ~mask; } - bool IsLargeStream(UInt64 size) { return size >= LongStreamMinSize; } - UString GetItemPath(UInt32 index) const; + bool GetMiniCluster(UInt32 sid, UInt64 &res) const + { + int subBits = SectorSizeBits - MiniSectorSizeBits; + UInt32 fid = sid >> subBits; + if (fid >= NumSectorsInMiniStream) + return false; + res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); + return true; + } + + HRESULT Open(IInStream *inStream); }; -HRESULT OpenArchive(IInStream *inStream, CDatabase &database); }} diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 76739e94..46f835ef 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -82,11 +82,11 @@ static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } -static inline bool IsLZMAMethod(const UString &methodName) +bool COneMethodInfo::IsLzma() const { return - AreEqual(methodName, kLZMAMethodName) || - AreEqual(methodName, kLZMA2MethodName); + AreEqual(MethodName, kLZMAMethodName) || + AreEqual(MethodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) @@ -109,8 +109,12 @@ struct CNameToPropID const wchar_t *Name; }; -CNameToPropID g_NameToPropID[] = +static CNameToPropID g_NameToPropID[] = { + { NCoderPropID::kBlockSize, VT_UI4, L"C" }, + { NCoderPropID::kDictionarySize, VT_UI4, L"D" }, + { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" }, + { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, @@ -122,7 +126,8 @@ CNameToPropID g_NameToPropID[] = { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, - { NCoderPropID::kNumThreads, VT_UI4, L"mt" } + { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, + { NCoderPropID::kDefaultProp, VT_UI4, L"" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) @@ -154,7 +159,7 @@ static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVar return false; } -static int FindPropIdFromStringName(const UString &name) +static int FindPropIdExact(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) @@ -162,16 +167,26 @@ static int FindPropIdFromStringName(const UString &name) return -1; } -static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, - const NWindows::NCOM::CPropVariant &value) +static int FindPropIdStart(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + { + UString t = g_NameToPropID[i].Name; + if (t.CompareNoCase(name.Left(t.Length())) == 0) + return i; + } + return -1; +} + +static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) { - for (int j = 0; j < oneMethodInfo.Props.Size(); j++) - if (oneMethodInfo.Props[j].Id == propID) + for (int j = 0; j < m.Props.Size(); j++) + if (m.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; - oneMethodInfo.Props.Add(prop); + m.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo @@ -184,7 +199,7 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; - if (IsLZMAMethod(oneMethodInfo.MethodName)) + if (oneMethodInfo.IsLzma()) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : @@ -205,12 +220,12 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) @@ -229,9 +244,9 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { @@ -245,10 +260,10 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) @@ -265,8 +280,8 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); + SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } @@ -316,25 +331,22 @@ static void SplitParam(const UString ¶m, UString &name, UString &value) HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; - if (name.CompareNoCase(L"D") == 0 || - name.CompareNoCase(L"MEM") == 0) + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); - prop.Id = (name.CompareNoCase(L"D") == 0) ? - NCoderPropID::kDictionarySize : - NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { - int index = FindPropIdFromStringName(name); - if (index < 0) - return E_INVALIDARG; - - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) @@ -465,7 +477,7 @@ void COutHandler::Init() WriteMTime = true; #ifdef COMPRESS_MT - _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + _numThreads = NSystem::GetNumberOfProcessors(); #endif _level = 5; @@ -576,35 +588,26 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val } else { + int index = FindPropIdStart(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; CProp prop; - if (realName.Left(1).CompareNoCase(L"D") == 0) - { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = dicSize; - if (number <= mainDicMethodIndex) - mainDicSize = dicSize; - } - else if (realName.Left(1).CompareNoCase(L"C") == 0) - { - UInt32 blockSize; - RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); - prop.Id = NCoderPropID::kBlockSize; - prop.Value = blockSize; - } - else if (realName.Left(3).CompareNoCase(L"MEM") == 0) + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) { UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); - prop.Id = NCoderPropID::kUsedMemorySize; + RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { - int index = FindPropIdFromStringName(realName); + int index = FindPropIdExact(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 89c81c1f..7ba22b24 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -12,6 +12,8 @@ struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; + + bool IsLzma() const; }; class COutHandler diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h index c5ada6fe..0492a5f8 100755 --- a/CPP/7zip/Archive/Common/InStreamWithCRC.h +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h @@ -1,15 +1,13 @@ // InStreamWithCRC.h -#ifndef __INSTREAMWITHCRC_H -#define __INSTREAMWITHCRC_H +#ifndef __IN_STREAM_WITH_CRC_H +#define __IN_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" #include "../../../Common/MyCom.h" -#include "../../IStream.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} +#include "../../IStream.h" class CSequentialInStreamWithCRC: public ISequentialInStream, diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp index 2ab2da66..f955c225 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -6,19 +6,13 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); if (_calculate) - _crc = CrcUpdate(_crc, data, realProcessedSize); - _size += realProcessedSize; - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h index a034ee9b..115b442a 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithCRC.h +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -3,13 +3,11 @@ #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H +#include "../../../../C/7zCrc.h" + #include "../../../Common/MyCom.h" -#include "../../IStream.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} +#include "../../IStream.h" class COutStreamWithCRC: public ISequentialOutStream, diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 51d2568a..0526c1b1 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -6,19 +6,13 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); if (_calculate) - _sha.Update((const Byte *)data, realProcessedSize); - _size += realProcessedSize; - if(processedSize != NULL) - *processedSize = realProcessedSize; + _sha.Update((const Byte *)data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 4eab42a7..3bbfbbe1 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -3,13 +3,11 @@ #ifndef __OUT_STREAM_WITH_SHA1_H #define __OUT_STREAM_WITH_SHA1_H -#include "../../../Common/MyCom.h" -#include "../../IStream.h" - - - #include "../../Crypto/Sha1.h" +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" class COutStreamWithSha1: public ISequentialOutStream, diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.cpp b/CPP/7zip/Archive/Cpio/CpioHandler.cpp deleted file mode 100755 index d49c854f..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHandler.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// CpioHandler.cpp - -#include "StdAfx.h" - -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/NewHandler.h" -#include "Common/StringConvert.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../../Common/LimitedStreams.h" -#include "../../Common/ProgressUtils.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/ItemNameUtils.h" - -#include "CpioHandler.h" -#include "CpioIn.h" - -using namespace NWindows; -using namespace NTime; - -namespace NArchive { -namespace NCpio { - -/* -enum -{ - kpidinode = kpidUserDefined, - kpidiChkSum -}; -*/ - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME}, - // { NULL, kpidUser, VT_BSTR}, - // { NULL, kpidGroup, VT_BSTR}, - // { L"inode", kpidinode, VT_UI4} - // { L"CheckSum", kpidiChkSum, VT_UI4} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *callback) -{ - COM_TRY_BEGIN - // try - { - CInArchive archive; - - UInt64 endPos = 0; - bool needSetTotal = true; - - if (callback != NULL) - { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - } - - RINOK(archive.Open(stream)); - - _items.Clear(); - - for (;;) - { - CItemEx item; - bool filled; - HRESULT result = archive.GetNextItem(filled, item); - if (result == S_FALSE) - return S_FALSE; - if (result != S_OK) - return S_FALSE; - if (!filled) - break; - _items.Add(item); - archive.SkeepDataRecords(item.Size, item.Align); - if (callback != NULL) - { - if (needSetTotal) - { - RINOK(callback->SetTotal(NULL, &endPos)); - needSetTotal = false; - } - if (_items.Size() % 100 == 0) - { - UInt64 numFiles = _items.Size(); - UInt64 numBytes = item.HeaderPosition; - RINOK(callback->SetCompleted(&numFiles, &numBytes)); - } - } - } - if (_items.Size() == 0) - return S_FALSE; - - _inStream = stream; - } - /* - catch(...) - { - return S_FALSE; - } - */ - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - _items.Clear(); - _inStream.Release(); - return S_OK; -} - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = _items.Size(); - return S_OK; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; - - switch(propID) - { - case kpidPath: - prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); - break; - case kpidIsDir: - prop = item.IsDir(); - break; - case kpidSize: - case kpidPackSize: - prop = (UInt64)item.Size; - break; - case kpidMTime: - { - FILETIME utcFileTime; - if (item.ModificationTime != 0) - NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime); - else - { - utcFileTime.dwLowDateTime = 0; - utcFileTime.dwHighDateTime = 0; - } - prop = utcFileTime; - break; - } - /* - case kpidinode: prop = item.inode; break; - case kpidiChkSum: prop = item.ChkSum; break; - */ - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 _aTestMode, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool testMode = (_aTestMode != 0); - bool allFilesMode = (numItems == UInt32(-1)); - if (allFilesMode) - numItems = _items.Size(); - if (numItems == 0) - return S_OK; - UInt64 totalSize = 0; - UInt32 i; - for (i = 0; i < numItems; i++) - totalSize += _items[allFilesMode ? i : indices[i]].Size; - extractCallback->SetTotal(totalSize); - - UInt64 currentTotalSize = 0; - UInt64 currentItemSize; - - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, false); - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); - - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) - { - lps->InSize = lps->OutSize = currentTotalSize; - RINOK(lps->SetCur()); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode = testMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - currentItemSize = item.Size; - if (item.IsDir()) - { - RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - continue; - } - if (!testMode && (!realOutStream)) - continue; - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - continue; - } - RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); - streamSpec->Init(item.Size); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); - realOutStream.Release(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? - NArchive::NExtract::NOperationResult::kOK: - NArchive::NExtract::NOperationResult::kDataError)); - } - return S_OK; - COM_TRY_END -} - -}} diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.h b/CPP/7zip/Archive/Cpio/CpioHandler.h deleted file mode 100755 index 1993c37f..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHandler.h +++ /dev/null @@ -1,30 +0,0 @@ -// Archive/cpio/Handler.h - -#ifndef __ARCHIVE_CPIO_HANDLER_H -#define __ARCHIVE_CPIO_HANDLER_H - -#include "Common/MyCom.h" -#include "../IArchive.h" - -#include "CpioItem.h" - -namespace NArchive { -namespace NCpio { - -class CHandler: - public IInArchive, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP1(IInArchive) - - INTERFACE_IInArchive(;) - -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _inStream; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.cpp b/CPP/7zip/Archive/Cpio/CpioHeader.cpp deleted file mode 100755 index f7b5a414..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHeader.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Archive/cpio/Header.h - -#include "StdAfx.h" - -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { -namespace NFileHeader { - - namespace NMagic - { - extern const char *kMagic1 = "070701"; - extern const char *kMagic2 = "070702"; - extern const char *kMagic3 = "070707"; - extern const char *kEndName = "TRAILER!!!"; - - const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; - // unsigned short kMagicForRecord2BE = 0xC771; - } - -}}} - diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.h b/CPP/7zip/Archive/Cpio/CpioHeader.h deleted file mode 100755 index 21afcc17..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHeader.h +++ /dev/null @@ -1,70 +0,0 @@ -// Archive/cpio/Header.h - -#ifndef __ARCHIVE_CPIO_HEADER_H -#define __ARCHIVE_CPIO_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NCpio { - -namespace NFileHeader -{ - namespace NMagic - { - extern const char *kMagic1; - extern const char *kMagic2; - extern const char *kMagic3; - extern const char *kEndName; - extern const Byte kMagicForRecord2[2]; - } - - const UInt32 kRecord2Size = 26; - /* - struct CRecord2 - { - unsigned short c_magic; - short c_dev; - unsigned short c_ino; - unsigned short c_mode; - unsigned short c_uid; - unsigned short c_gid; - unsigned short c_nlink; - short c_rdev; - unsigned short c_mtimes[2]; - unsigned short c_namesize; - unsigned short c_filesizes[2]; - }; - */ - - const UInt32 kRecordSize = 110; - /* - struct CRecord - { - char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format - char inode[8]; - char Mode[8]; - char UID[8]; - char GID[8]; - char nlink[8]; - char mtime[8]; - char Size[8]; // must be 0 for FIFOs and directories - char DevMajor[8]; - char DevMinor[8]; - char RDevMajor[8]; //only valid for chr and blk special files - char RDevMinor[8]; //only valid for chr and blk special files - char NameSize[8]; // count includes terminating NUL in pathname - char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file - bool CheckMagic() const - { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || - memcmp(Magic, NMagic::kMagic2, 6) == 0; }; - }; - */ - - const UInt32 kOctRecordSize = 76; - -} - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioIn.cpp b/CPP/7zip/Archive/Cpio/CpioIn.cpp deleted file mode 100755 index d4d807e1..00000000 --- a/CPP/7zip/Archive/Cpio/CpioIn.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Archive/cpioIn.cpp - -#include "StdAfx.h" - -#include "CpioIn.h" - -#include "Common/StringToInt.h" -#include "Windows/Defs.h" - -#include "../../Common/StreamUtils.h" - -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -Byte CInArchive::ReadByte() -{ - if (_blockPos >= _blockSize) - throw "Incorrect cpio archive"; - return _block[_blockPos++]; -} - -UInt16 CInArchive::ReadUInt16() -{ - UInt16 value = 0; - for (int i = 0; i < 2; i++) - { - Byte b = ReadByte(); - value |= (UInt16(b) << (8 * i)); - } - return value; -} - -UInt32 CInArchive::ReadUInt32() -{ - UInt32 value = 0; - for (int i = 0; i < 4; i++) - { - Byte b = ReadByte(); - value |= (UInt32(b) << (8 * i)); - } - return value; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - -bool CInArchive::ReadNumber(UInt32 &resultValue) -{ - resultValue = 0; - for (int i = 0; i < 8; i++) - { - char c = char(ReadByte()); - int d; - if (c >= '0' && c <= '9') - d = c - '0'; - else if (c >= 'A' && c <= 'F') - d = 10 + c - 'A'; - else if (c >= 'a' && c <= 'f') - d = 10 + c - 'a'; - else - return false; - resultValue *= 0x10; - resultValue += d; - } - return true; -} - -static bool OctalToNumber(const char *s, UInt64 &res) -{ - const char *end; - res = ConvertOctStringToUInt64(s, &end); - return (*end == ' ' || *end == 0); -} - -static bool OctalToNumber32(const char *s, UInt32 &res) -{ - UInt64 res64; - if (!OctalToNumber(s, res64)) - return false; - res = (UInt32)res64; - return (res64 <= 0xFFFFFFFF); -} - -bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) -{ - char sz[32 + 4]; - int i; - for (i = 0; i < size && i < 32; i++) - sz[i] = (char)ReadByte(); - sz[i] = 0; - return OctalToNumber32(sz, resultValue); -} - -#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } -#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } -#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } - -static unsigned short ConvertValue(unsigned short value, bool convert) -{ - if (!convert) - return value; - return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); -} - -static UInt32 GetAlignedSize(UInt32 size, UInt32 align) -{ - while ((size & (align - 1)) != 0) - size++; - return size; -} - - -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) -{ - filled = false; - - UInt32 processedSize; - item.HeaderPosition = m_Position; - - _blockSize = kMaxBlockSize; - RINOK(ReadBytes(_block, 2, processedSize)); - if (processedSize != 2) - return S_FALSE; - _blockPos = 0; - - UInt32 nameSize; - - bool oldBE = - _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; - - bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || - oldBE; - - if (binMode) - { - RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); - if (processedSize != NFileHeader::kRecord2Size - 2) - return S_FALSE; - item.Align = 2; - _blockPos = 2; - item.DevMajor = 0; - item.DevMinor = ConvertValue(ReadUInt16(), oldBE); - item.inode = ConvertValue(ReadUInt16(), oldBE); - item.Mode = ConvertValue(ReadUInt16(), oldBE); - item.UID = ConvertValue(ReadUInt16(), oldBE); - item.GID = ConvertValue(ReadUInt16(), oldBE); - item.NumLinks = ConvertValue(ReadUInt16(), oldBE); - item.RDevMajor =0; - item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); - item.ModificationTime = (UInt32(timeHigh) << 16) + timeLow; - nameSize = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); - item.Size = (UInt32(sizeHigh) << 16) + sizeLow; - - item.ChkSum = 0; - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecord2Size, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecord2Size; - } - else - { - RINOK(ReadBytes(_block + 2, 4, processedSize)); - if (processedSize != 4) - return S_FALSE; - - bool magicOK = - memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || - memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; - _blockPos = 6; - if (magicOK) - { - RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kRecordSize - 6) - return S_FALSE; - item.Align = 4; - - GetFromHex(item.inode); - GetFromHex(item.Mode); - GetFromHex(item.UID); - GetFromHex(item.GID); - GetFromHex(item.NumLinks); - UInt32 modificationTime; - GetFromHex(modificationTime); - item.ModificationTime = modificationTime; - GetFromHex(item.Size); - GetFromHex(item.DevMajor); - GetFromHex(item.DevMinor); - GetFromHex(item.RDevMajor); - GetFromHex(item.RDevMinor); - GetFromHex(nameSize); - GetFromHex(item.ChkSum); - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecordSize; - } - else - { - if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) - return S_FALSE; - RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kOctRecordSize - 6) - return S_FALSE; - item.Align = 1; - item.DevMajor = 0; - GetFromOct6(item.DevMinor); - GetFromOct6(item.inode); - GetFromOct6(item.Mode); - GetFromOct6(item.UID); - GetFromOct6(item.GID); - GetFromOct6(item.NumLinks); - item.RDevMajor = 0; - GetFromOct6(item.RDevMinor); - UInt32 modificationTime; - GetFromOct11(modificationTime); - item.ModificationTime = modificationTime; - GetFromOct6(nameSize); - GetFromOct11(item.Size); // ????? - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kOctRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; - } - } - if (nameSize == 0 || nameSize >= (1 << 27)) - return E_FAIL; - RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); - if (processedSize != nameSize) - return E_FAIL; - item.Name.ReleaseBuffer(); - if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) - return S_OK; - filled = true; - return S_OK; -} - -HRESULT CInArchive::Skeep(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - -HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize, UInt32 align) -{ - while ((dataSize & (align - 1)) != 0) - dataSize++; - return Skeep(dataSize); -} - -}} diff --git a/CPP/7zip/Archive/Cpio/CpioIn.h b/CPP/7zip/Archive/Cpio/CpioIn.h deleted file mode 100755 index 19e3da10..00000000 --- a/CPP/7zip/Archive/Cpio/CpioIn.h +++ /dev/null @@ -1,41 +0,0 @@ -// CpioIn.h - -#ifndef __ARCHIVE_CPIO_IN_H -#define __ARCHIVE_CPIO_IN_H - -#include "Common/MyCom.h" -#include "Common/Types.h" -#include "../../IStream.h" -#include "CpioItem.h" - -namespace NArchive { -namespace NCpio { - -const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - UInt16 _blockSize; - Byte _block[kMaxBlockSize]; - UInt32 _blockPos; - Byte ReadByte(); - UInt16 ReadUInt16(); - UInt32 ReadUInt32(); - - bool ReadNumber(UInt32 &resultValue); - bool ReadOctNumber(int size, UInt32 &resultValue); - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); - HRESULT SkeepDataRecords(UInt64 dataSize, UInt32 align); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioItem.h b/CPP/7zip/Archive/Cpio/CpioItem.h deleted file mode 100755 index 70aa384d..00000000 --- a/CPP/7zip/Archive/Cpio/CpioItem.h +++ /dev/null @@ -1,55 +0,0 @@ -// Archive/cpio/ItemInfo.h - -#ifndef __ARCHIVE_CPIO_ITEMINFO_H -#define __ARCHIVE_CPIO_ITEMINFO_H - -#include <sys/stat.h> - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { - -struct CItem -{ - AString Name; - UInt32 inode; - UInt32 Mode; - UInt32 UID; - UInt32 GID; - UInt32 Size; - UInt32 ModificationTime; - - // char LinkFlag; - // AString LinkName; ????? - char Magic[8]; - UInt32 NumLinks; - UInt32 DevMajor; - UInt32 DevMinor; - UInt32 RDevMajor; - UInt32 RDevMinor; - UInt32 ChkSum; - - UInt32 Align; - - bool IsDir() const -#ifdef _WIN32 - { return (Mode & _S_IFMT) == _S_IFDIR; } -#else - { return (Mode & S_IFMT) == S_IFDIR; } -#endif -}; - -class CItemEx: public CItem -{ -public: - UInt64 HeaderPosition; - UInt32 HeaderSize; - UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioRegister.cpp b/CPP/7zip/Archive/Cpio/CpioRegister.cpp deleted file mode 100755 index 62d1265e..00000000 --- a/CPP/7zip/Archive/Cpio/CpioRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// CpioRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "CpioHandler.h" -static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; - -REGISTER_ARC(Cpio) diff --git a/CPP/7zip/Archive/Cpio/StdAfx.h b/CPP/7zip/Archive/Cpio/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Cpio/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp new file mode 100755 index 00000000..e5a32936 --- /dev/null +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -0,0 +1,625 @@ +// CpioHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringToInt.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/ItemNameUtils.h" + +namespace NArchive { +namespace NCpio { + +namespace NFileHeader +{ + namespace NMagic + { + extern const char *kMagic1 = "070701"; + extern const char *kMagic2 = "070702"; + extern const char *kMagic3 = "070707"; + extern const char *kEndName = "TRAILER!!!"; + + const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; + } + + const UInt32 kRecord2Size = 26; + /* + struct CRecord2 + { + unsigned short c_magic; + short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + short c_rdev; + unsigned short c_mtimes[2]; + unsigned short c_namesize; + unsigned short c_filesizes[2]; + }; + */ + + const UInt32 kRecordSize = 110; + /* + struct CRecord + { + char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format + char inode[8]; + char Mode[8]; + char UID[8]; + char GID[8]; + char nlink[8]; + char mtime[8]; + char Size[8]; // must be 0 for FIFOs and directories + char DevMajor[8]; + char DevMinor[8]; + char RDevMajor[8]; //only valid for chr and blk special files + char RDevMinor[8]; //only valid for chr and blk special files + char NameSize[8]; // count includes terminating NUL in pathname + char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file + bool CheckMagic() const + { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || + memcmp(Magic, NMagic::kMagic2, 6) == 0; }; + }; + */ + + const UInt32 kOctRecordSize = 76; + +} + +struct CItem +{ + AString Name; + UInt32 inode; + UInt32 Mode; + UInt32 UID; + UInt32 GID; + UInt32 Size; + UInt32 MTime; + + // char LinkFlag; + // AString LinkName; ????? + char Magic[8]; + UInt32 NumLinks; + UInt32 DevMajor; + UInt32 DevMinor; + UInt32 RDevMajor; + UInt32 RDevMinor; + UInt32 ChkSum; + + UInt32 Align; + + bool IsDir() const { return (Mode & 0170000) == 0040000; } +}; + +class CItemEx: public CItem +{ +public: + UInt64 HeaderPosition; + UInt32 HeaderSize; + UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; +}; + +const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; + +class CInArchive +{ + CMyComPtr<IInStream> m_Stream; + UInt64 m_Position; + + UInt16 _blockSize; + Byte _block[kMaxBlockSize]; + UInt32 _blockPos; + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + + bool ReadNumber(UInt32 &resultValue); + bool ReadOctNumber(int size, UInt32 &resultValue); + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); + HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +Byte CInArchive::ReadByte() +{ + if (_blockPos >= _blockSize) + throw "Incorrect cpio archive"; + return _block[_blockPos++]; +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = ReadByte(); + value |= (UInt16(b) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + Byte b = ReadByte(); + value |= (UInt32(b) << (8 * i)); + } + return value; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +bool CInArchive::ReadNumber(UInt32 &resultValue) +{ + resultValue = 0; + for (int i = 0; i < 8; i++) + { + char c = char(ReadByte()); + int d; + if (c >= '0' && c <= '9') + d = c - '0'; + else if (c >= 'A' && c <= 'F') + d = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + d = 10 + c - 'a'; + else + return false; + resultValue *= 0x10; + resultValue += d; + } + return true; +} + +static bool OctalToNumber(const char *s, UInt64 &res) +{ + const char *end; + res = ConvertOctStringToUInt64(s, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *s, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(s, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) +{ + char sz[32 + 4]; + int i; + for (i = 0; i < size && i < 32; i++) + sz[i] = (char)ReadByte(); + sz[i] = 0; + return OctalToNumber32(sz, resultValue); +} + +#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } +#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } +#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } + +static unsigned short ConvertValue(unsigned short value, bool convert) +{ + if (!convert) + return value; + return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); +} + +static UInt32 GetAlignedSize(UInt32 size, UInt32 align) +{ + while ((size & (align - 1)) != 0) + size++; + return size; +} + + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + item.HeaderPosition = m_Position; + + _blockSize = kMaxBlockSize; + RINOK(ReadBytes(_block, 2, processedSize)); + if (processedSize != 2) + return S_FALSE; + _blockPos = 0; + + UInt32 nameSize; + + bool oldBE = + _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; + + bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || + oldBE; + + if (binMode) + { + RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); + if (processedSize != NFileHeader::kRecord2Size - 2) + return S_FALSE; + item.Align = 2; + _blockPos = 2; + item.DevMajor = 0; + item.DevMinor = ConvertValue(ReadUInt16(), oldBE); + item.inode = ConvertValue(ReadUInt16(), oldBE); + item.Mode = ConvertValue(ReadUInt16(), oldBE); + item.UID = ConvertValue(ReadUInt16(), oldBE); + item.GID = ConvertValue(ReadUInt16(), oldBE); + item.NumLinks = ConvertValue(ReadUInt16(), oldBE); + item.RDevMajor =0; + item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); + item.MTime = (UInt32(timeHigh) << 16) + timeLow; + nameSize = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); + item.Size = (UInt32(sizeHigh) << 16) + sizeLow; + + item.ChkSum = 0; + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecord2Size, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecord2Size; + } + else + { + RINOK(ReadBytes(_block + 2, 4, processedSize)); + if (processedSize != 4) + return S_FALSE; + + bool magicOK = + memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || + memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; + _blockPos = 6; + if (magicOK) + { + RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kRecordSize - 6) + return S_FALSE; + item.Align = 4; + + GetFromHex(item.inode); + GetFromHex(item.Mode); + GetFromHex(item.UID); + GetFromHex(item.GID); + GetFromHex(item.NumLinks); + UInt32 mTime; + GetFromHex(mTime); + item.MTime = mTime; + GetFromHex(item.Size); + GetFromHex(item.DevMajor); + GetFromHex(item.DevMinor); + GetFromHex(item.RDevMajor); + GetFromHex(item.RDevMinor); + GetFromHex(nameSize); + GetFromHex(item.ChkSum); + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecordSize; + } + else + { + if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) + return S_FALSE; + RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kOctRecordSize - 6) + return S_FALSE; + item.Align = 1; + item.DevMajor = 0; + GetFromOct6(item.DevMinor); + GetFromOct6(item.inode); + GetFromOct6(item.Mode); + GetFromOct6(item.UID); + GetFromOct6(item.GID); + GetFromOct6(item.NumLinks); + item.RDevMajor = 0; + GetFromOct6(item.RDevMinor); + UInt32 mTime; + GetFromOct11(mTime); + item.MTime = mTime; + GetFromOct6(nameSize); + GetFromOct11(item.Size); // ????? + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kOctRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; + } + } + if (nameSize == 0 || nameSize >= (1 << 27)) + return E_FAIL; + RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); + if (processedSize != nameSize) + return E_FAIL; + item.Name.ReleaseBuffer(); + if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) + return S_OK; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align) +{ + while ((dataSize & (align - 1)) != 0) + dataSize++; + return Skip(dataSize); +} + + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +/* +enum +{ + kpidinode = kpidUserDefined, + kpidiChkSum +}; +*/ + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4}, + // { L"inode", kpidinode, VT_UI4} + // { L"CheckSum", kpidiChkSum, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + // try + { + CInArchive archive; + + UInt64 endPos = 0; + bool needSetTotal = true; + + if (callback != NULL) + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + RINOK(archive.Open(stream)); + + _items.Clear(); + + for (;;) + { + CItemEx item; + bool filled; + HRESULT result = archive.GetNextItem(filled, item); + if (result == S_FALSE) + return S_FALSE; + if (result != S_OK) + return S_FALSE; + if (!filled) + break; + _items.Add(item); + archive.SkipDataRecords(item.Size, item.Align); + if (callback != NULL) + { + if (needSetTotal) + { + RINOK(callback->SetTotal(NULL, &endPos)); + needSetTotal = false; + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = item.HeaderPosition; + RINOK(callback->SetCompleted(&numFiles, &numBytes)); + } + } + } + if (_items.Size() == 0) + return S_FALSE; + + _stream = stream; + } + /* + catch(...) + { + return S_FALSE; + } + */ + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItemEx &item = _items[index]; + + switch(propID) + { + case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size; + break; + case kpidMTime: + { + if (item.MTime != 0) + { + FILETIME utc; + NWindows::NTime::UnixTimeToFileTime(item.MTime, utc); + prop = utc; + } + break; + } + case kpidPosixAttrib: prop = item.Mode; break; + /* + case kpidinode: prop = item.inode; break; + case kpidiChkSum: prop = item.ChkSum; break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx &item = _items[index]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + currentTotalSize += item.Size; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Cpio) + +}} diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp index fc962df3..0381e0fd 100755 --- a/CPP/7zip/Archive/DebHandler.cpp +++ b/CPP/7zip/Archive/DebHandler.cpp @@ -30,7 +30,7 @@ namespace NHeader { const int kSignatureLen = 8; - const char *kSignature = "!<arch>\n"; + const char *kSignature = "!<arch>\n"; const int kNameSize = 16; const int kTimeSize = 12; @@ -53,20 +53,15 @@ namespace NHeader const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1; } -class CItem +struct CItem { -public: AString Name; UInt64 Size; UInt32 MTime; UInt32 Mode; -}; -class CItemEx: public CItem -{ -public: - UInt64 HeaderPosition; - UInt64 GetDataPosition() const { return HeaderPosition + NHeader::kHeaderSize; }; + UInt64 HeaderPos; + UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; }; // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; }; }; @@ -75,12 +70,11 @@ class CInArchive CMyComPtr<IInStream> m_Stream; UInt64 m_Position; - HRESULT GetNextItemReal(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); + HRESULT GetNextItemReal(bool &filled, CItem &itemInfo); public: HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT SkeepData(UInt64 dataSize); + HRESULT GetNextItem(bool &filled, CItem &itemInfo); + HRESULT SkipData(UInt64 dataSize); }; HRESULT CInArchive::Open(IInStream *inStream) @@ -151,7 +145,7 @@ static bool DecimalToNumber32(const char *s, int size, UInt32 &res) #define RIF(x) { if (!(x)) return S_FALSE; } -HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) +HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item) { filled = false; @@ -159,7 +153,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) const char *cur = header; size_t processedSize = sizeof(header); - item.HeaderPosition = m_Position; + item.HeaderPos = m_Position; RINOK(ReadStream(m_Stream, header, &processedSize)); m_Position += processedSize; if (processedSize != sizeof(header)) @@ -191,7 +185,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) return S_OK; } -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) { for (;;) { @@ -202,38 +196,26 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) return S_OK; if (item.Size != 4) return S_OK; - SkeepData(item.Size); + SkipData(item.Size); } } -HRESULT CInArchive::Skeep(UInt64 numBytes) +HRESULT CInArchive::SkipData(UInt64 dataSize) { - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; + return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position); } -HRESULT CInArchive::SkeepData(UInt64 dataSize) -{ - return Skeep((dataSize + 1) & (~((UInt64)0x1))); -} - - class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CObjectVector<CItem> _items; + CMyComPtr<IInStream> _stream; public: - MY_UNKNOWN_IMP1(IInArchive) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _inStream; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; @@ -241,7 +223,6 @@ STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME} }; @@ -268,7 +249,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, for (;;) { - CItemEx item; + CItem item; bool filled; HRESULT result = archive.GetNextItem(filled, item); if (result == S_FALSE) @@ -278,14 +259,14 @@ STDMETHODIMP CHandler::Open(IInStream *stream, if (!filled) break; _items.Add(item); - archive.SkeepData(item.Size); + archive.SkipData(item.Size); if (openArchiveCallback != NULL) { UInt64 numFiles = _items.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } - _inStream = stream; + _stream = stream; } return S_OK; COM_TRY_END @@ -293,7 +274,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { - _inStream.Release(); + _stream.Release(); _items.Clear(); return S_OK; } @@ -308,7 +289,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; switch(propID) { @@ -350,7 +331,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -361,9 +341,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -372,14 +352,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - currentItemSize = item.Size; - - - - - + currentTotalSize += item.Size; if (!testMode && (!realOutStream)) continue; @@ -389,7 +364,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); streamSpec->Init(item.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); realOutStream.Release(); @@ -401,10 +376,18 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; } static CArcInfo g_ArcInfo = - { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 }; + { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 }; REGISTER_ARC(Deb) diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 545fcbd3..fd8bff28 100755 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -7,10 +7,7 @@ #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) -extern "C" -{ #include "../../../C/Alloc.h" -} #endif #include "IArchive.h" diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index cac7c3ad..66b18e7a 100755 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -17,8 +17,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - static UInt16 Get16(const Byte *p, int be) { if (be) return GetBe16(p); return GetUi16(p); } static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } @@ -28,11 +26,11 @@ using namespace NWindows; namespace NArchive { namespace NElf { -#define ELF_CLASS_32 1 -#define ELF_CLASS_64 2 +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 -#define ELF_DATA_2LSB 1 -#define ELF_DATA_2MSB 2 +#define ELF_DATA_2LSB 1 +#define ELF_DATA_2MSB 2 #define NUM_SCAN_SECTIONS_MAX (1 << 6) @@ -321,7 +319,7 @@ public: INTERFACE_IInArchive(;) }; -#define ELF_PT_PHDR 6 +#define ELF_PT_PHDR 6 bool CHandler::Parse(const Byte *buf, UInt32 size) { @@ -498,9 +496,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -511,20 +506,17 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSegment &item = _sections[index]; currentItemSize = item.PSize; - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); + outStream.Release(); RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp new file mode 100755 index 00000000..f07d4ccb --- /dev/null +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -0,0 +1,983 @@ +// FatHandler.cpp + +#include "StdAfx.h" + +// #include <stdio.h> + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define PRF(x) /* x */ + +namespace NArchive { +namespace NFat { + +static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31; + +struct CHeader +{ + UInt32 NumSectors; + UInt16 NumReservedSectors; + Byte NumFats; + UInt32 NumFatSectors; + UInt32 RootDirSector; + UInt32 NumRootDirSectors; + UInt32 DataSector; + + UInt32 FatSize; + UInt32 BadCluster; + + Byte NumFatBits; + Byte SectorSizeLog; + Byte SectorsPerClusterLog; + Byte ClusterSizeLog; + + UInt16 SectorsPerTrack; + UInt16 NumHeads; + UInt32 NumHiddenSectors; + + bool VolFieldsDefined; + + UInt32 VolId; + // Byte VolName[11]; + // Byte FileSys[8]; + + // Byte OemName[5]; + Byte MediaType; + + // 32-bit FAT + UInt16 Flags; + UInt16 FsInfoSector; + UInt32 RootCluster; + + bool IsFat32() const { return NumFatBits == 32; } + UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; } + UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); } + UInt32 IsEoc(UInt32 c) const { return c > BadCluster; } + UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; } + UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; } + UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; } + UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); } + + UInt32 GetFatSector() const + { + UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0; + if (index > NumFats) + index = 0; + return NumReservedSectors + index * NumFatSectors; + } + + UInt64 GetFilePackSize(UInt32 unpackSize) const + { + UInt64 mask = ClusterSize() - 1; + return (unpackSize + mask) & ~mask; + } + + UInt32 GetNumClusters(UInt32 size) const + { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); } + + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + SectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog; + } + + NumReservedSectors = Get16(p + 14); + if (NumReservedSectors == 0) + return false; + + NumFats = p[16]; + if (NumFats < 1 || NumFats > 4) + return false; + + UInt16 numRootDirEntries = Get16(p + 17); + if (numRootDirEntries == 0) + { + if (codeOffset < 90) + return false; + NumFatBits = 32; + NumRootDirSectors = 0; + } + else + { + if (codeOffset < 62) + return false; + NumFatBits = 0; + UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; + if ((numRootDirEntries & mask) != 0) + return false; + NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5); + } + + NumSectors = Get16(p + 19); + if (NumSectors == 0) + NumSectors = Get32(p + 32); + else if (IsFat32()) + return false; + + MediaType = p[21]; + NumFatSectors = Get16(p + 22); + SectorsPerTrack = Get16(p + 24); + NumHeads = Get16(p + 26); + NumHiddenSectors = Get32(p + 28); + + // memcpy(OemName, p + 3, 5); + + p += 36; + if (IsFat32()) + { + if (NumFatSectors != 0) + return false; + NumFatSectors = Get32(p); + if (NumFatSectors >= (1 << 24)) + return false; + + Flags = Get16(p + 4); + if (Get16(p + 6) != 0) + return false; + RootCluster = Get32(p + 8); + FsInfoSector = Get16(p + 12); + for (int i = 16; i < 28; i++) + if (p[i] != 0) + return false; + p += 28; + } + + // DriveNumber = p[0]; + VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig + VolId = Get32(p + 3); + // memcpy(VolName, p + 7, 11); + // memcpy(FileSys, p + 18, 8); + + if (NumFatSectors == 0) + return false; + RootDirSector = NumReservedSectors + NumFatSectors * NumFats; + DataSector = RootDirSector + NumRootDirSectors; + if (NumSectors < DataSector) + return false; + UInt32 numDataSectors = NumSectors - DataSector; + UInt32 numClusters = numDataSectors >> SectorsPerClusterLog; + + BadCluster = 0x0FFFFFF7; + if (numClusters < 0xFFF5) + { + if (NumFatBits == 32) + return false; + NumFatBits = (numClusters < 0xFF5) ? 12: 16; + BadCluster &= ((1 << NumFatBits) - 1); + } + else if (NumFatBits != 32) + return false; + + FatSize = numClusters + 2; + if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors) + return false; + return true; +} + +struct CItem +{ + UString UName; + char DosName[11]; + Byte CTime2; + UInt32 CTime; + UInt32 MTime; + UInt16 ADate; + Byte Attrib; + Byte Flags; + UInt32 Size; + UInt32 Cluster; + Int32 Parent; + + // NT uses Flags to store Low Case status + bool NameIsLow() const { return (Flags & 0x8) != 0; } + bool ExtIsLow() const { return (Flags & 0x10) != 0; } + bool IsDir() const { return (Attrib & 0x10) != 0; } + UString GetShortName() const; + UString GetName() const; + UString GetVolName() const; +}; + +static int CopyAndTrim(char *dest, const char *src, int size, bool toLower) +{ + int i; + memcpy(dest, src, size); + if (toLower) + for (i = 0; i < size; i++) + { + char c = dest[i]; + if (c >= 'A' && c <= 'Z') + dest[i] = c + 0x20; + } + for (i = size - 1; i >= 0 && dest[i] == ' '; i--); + return i + 1; +} + +static UString FatStringToUnicode(const char *s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + +UString CItem::GetShortName() const +{ + char s[16]; + int i = CopyAndTrim(s, DosName, 8, NameIsLow()); + s[i++] = '.'; + int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); + if (j == 0) + j--; + s[i + j] = 0; + return FatStringToUnicode(s); +} + +UString CItem::GetName() const +{ + if (!UName.IsEmpty()) + return UName; + return GetShortName(); +} + +UString CItem::GetVolName() const +{ + if (!UName.IsEmpty()) + return UName; + char s[12]; + int i = CopyAndTrim(s, DosName, 11, false); + s[i] = 0; + return FatStringToUnicode(s); +} + +struct CDatabase +{ + CHeader Header; + CObjectVector<CItem> Items; + UInt32 *Fat; + CMyComPtr<IInStream> InStream; + IArchiveOpenCallback *OpenCallback; + + UInt32 NumFreeClusters; + bool VolItemDefined; + CItem VolItem; + UInt32 NumDirClusters; + CByteBuffer ByteBuf; + UInt64 NumCurUsedBytes; + + CDatabase(): Fat(0) {} + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + HRESULT OpenProgressFat(bool changeTotal = true); + HRESULT OpenProgress(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + UInt64 GetHeadersSize() const + { + return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog; + } + HRESULT SeekToSector(UInt32 sector); + HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); } +}; + +HRESULT CDatabase::SeekToSector(UInt32 sector) +{ + return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + VolItemDefined = false; + NumDirClusters = 0; + NumCurUsedBytes = 0; + + Items.Clear(); + delete []Fat; + Fat = 0; +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +HRESULT CDatabase::OpenProgressFat(bool changeTotal) +{ + if (!OpenCallback) + return S_OK; + if (changeTotal) + { + UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) + + ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); + RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)); + } + return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes); +} + +HRESULT CDatabase::OpenProgress() +{ + if (!OpenCallback) + return S_OK; + UInt64 numItems = Items.Size(); + return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes); +} + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->GetName(); + for (;;) + { + index = item->Parent; + if (index < 0) + return name; + item = &Items[index]; + name = item->GetName() + WCHAR_PATH_SEPARATOR + name; + } +} + +static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars) +{ + for (int i = 0; i < numChars; i++) + { + wchar_t c = Get16(p + i * 2); + if (c != 0 && c != 0xFFFF) + *dest++ = c; + } + *dest = 0; + return dest; +} + +HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) +{ + int startIndex = Items.Size(); + if (startIndex >= (1 << 30) || level > 256) + return S_FALSE; + + UInt32 sectorIndex = 0; + UInt32 blockSize = Header.ClusterSize(); + bool clusterMode = (Header.IsFat32() || parent >= 0); + if (!clusterMode) + { + blockSize = Header.SectorSize(); + RINOK(SeekToSector(Header.RootDirSector)); + } + + ByteBuf.SetCapacity(blockSize); + UString curName; + int checkSum = -1; + int numLongRecords = -1; + for (UInt32 pos = blockSize;; pos += 32) + { + if (pos == blockSize) + { + pos = 0; + + if ((NumDirClusters & 0xFF) == 0) + { + RINOK(OpenProgress()); + } + + if (clusterMode) + { + if (Header.IsEoc(cluster)) + break; + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + PRF(printf("\nCluster = %4X", cluster)); + RINOK(SeekToCluster(cluster)); + UInt32 newCluster = Fat[cluster]; + if ((newCluster & kFatItemUsedByDirMask) != 0) + return S_FALSE; + Fat[cluster] |= kFatItemUsedByDirMask; + cluster = newCluster; + NumDirClusters++; + NumCurUsedBytes += Header.ClusterSize(); + } + else if (sectorIndex++ >= Header.NumRootDirSectors) + break; + + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + } + const Byte *p = ByteBuf + pos; + if (p[0] == 0) + { + if (clusterMode && !Header.IsEoc(cluster)) + return S_FALSE; + break; + } + if (p[0] == 0xE5) + { + if (numLongRecords > 0) + return S_FALSE; + continue; + } + + Byte attrib = p[11]; + if ((attrib & 0x3F) == 0xF) + { + if (p[0] > 0x7F || Get16(p + 26) != 0) + return S_FALSE; + int longIndex = p[0] & 0x3F; + if (longIndex == 0) + return S_FALSE; + bool isLast = (p[0] & 0x40) != 0; + if (numLongRecords < 0) + { + if (!isLast) + return S_FALSE; + numLongRecords = longIndex; + } + else if (isLast || numLongRecords != longIndex) + return S_FALSE; + + numLongRecords--; + + if (p[12] == 0) + { + wchar_t nameBuf[14]; + wchar_t *dest; + + dest = AddSubStringToName(nameBuf, p + 1, 5); + dest = AddSubStringToName(dest, p + 14, 6); + AddSubStringToName(dest, p + 28, 2); + curName = nameBuf + curName; + if (isLast) + checkSum = p[13]; + if (checkSum != p[13]) + return S_FALSE; + } + } + else + { + if (numLongRecords > 0) + return S_FALSE; + CItem item; + memcpy(item.DosName, p, 11); + + if (checkSum >= 0) + { + Byte sum = 0; + for (int i = 0; i < 11; i++) + sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]; + if (sum == checkSum) + item.UName = curName; + } + + if (item.DosName[0] == 5) + item.DosName[0] = (char)(Byte)0xE5; + item.Attrib = attrib; + item.Flags = p[12]; + item.Size = Get32(p + 28); + item.Cluster = Get16(p + 26) | ((UInt32)Get16(p + 20) << 16); + item.CTime = Get32(p + 14); + item.CTime2 = p[13]; + item.ADate = Get16(p + 18); + item.MTime = Get32(p + 22); + item.Parent = parent; + + if (attrib == 8) + { + VolItem = item; + VolItemDefined = true; + } + else + if (memcmp(item.DosName, ". ", 11) != 0 && + memcmp(item.DosName, ".. ", 11) != 0) + { + if (!item.IsDir()) + NumCurUsedBytes += Header.GetFilePackSize(item.Size); + Items.Add(item); + PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); + } + numLongRecords = -1; + curName.Empty(); + checkSum = -1; + } + } + + int finishIndex = Items.Size(); + for (int i = startIndex; i < finishIndex; i++) + { + const CItem &item = Items[i]; + if (item.IsDir()) + { + PRF(printf("\n%S", GetItemPath(i))); + RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1)); + } + } + return S_OK; +} + +HRESULT CDatabase::Open() +{ + Clear(); + bool numFreeClustersDefined = false; + { + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < Header.GetPhySize()) + return S_FALSE; + + if (Header.IsFat32()) + { + SeekToSector(Header.FsInfoSector); + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272) + { + NumFreeClusters = Get32(buf + 488); + numFreeClustersDefined = (NumFreeClusters <= Header.FatSize); + } + } + } + + // numFreeClustersDefined = false; // to recalculate NumFreeClusters + if (!numFreeClustersDefined) + NumFreeClusters = 0; + + CByteBuffer byteBuf; + Fat = new UInt32[Header.FatSize]; + + RINOK(OpenProgressFat()); + RINOK(SeekToSector(Header.GetFatSector())); + if (Header.NumFatBits == 32) + { + const UInt32 kBufSize = (1 << 15); + byteBuf.SetCapacity(kBufSize); + for (UInt32 i = 0; i < Header.FatSize;) + { + UInt32 size = Header.FatSize - i; + const UInt32 kBufSize32 = kBufSize / 4; + if (size > kBufSize32) + size = kBufSize32; + UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog; + RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)); + NumCurUsedBytes += readSize; + + const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf; + UInt32 *dest = Fat + i; + if (numFreeClustersDefined) + for (UInt32 j = 0; j < size; j++) + dest[j] = Get32(src + j) & 0x0FFFFFFF; + else + { + UInt32 numFreeClusters = 0; + for (UInt32 j = 0; j < size; j++) + { + UInt32 v = Get32(src + j) & 0x0FFFFFFF; + numFreeClusters += (UInt32)(v - 1) >> 31; + dest[j] = v; + } + NumFreeClusters += numFreeClusters; + } + i += size; + if ((i & 0xFFFFF) == 0) + { + RINOK(OpenProgressFat(!numFreeClustersDefined)); + } + } + } + else + { + const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog; + NumCurUsedBytes += kBufSize; + byteBuf.SetCapacity(kBufSize); + Byte *p = byteBuf; + RINOK(ReadStream_FALSE(InStream, p, kBufSize)); + UInt32 fatSize = Header.FatSize; + UInt32 *fat = &Fat[0]; + if (Header.NumFatBits == 16) + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = Get16(p + j * 2); + else + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; + + if (!numFreeClustersDefined) + { + UInt32 numFreeClusters = 0; + for (UInt32 i = 0; i < fatSize; i++) + numFreeClusters += (UInt32)(fat[i] - 1) >> 31; + NumFreeClusters = numFreeClusters; + } + } + + RINOK(OpenProgressFat()); + + if ((Fat[0] & 0xFF) != Header.MediaType) + return S_FALSE; + + return ReadDir(-1, Header.RootCluster, 0); +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + const CItem &item = Items[index]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->Stream = InStream; + streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog; + streamSpec->BlockSizeLog = Header.ClusterSizeLog; + streamSpec->Size = item.Size; + + UInt32 numClusters = Header.GetNumClusters(item.Size); + streamSpec->Vector.Reserve(numClusters); + UInt32 cluster = item.Cluster; + UInt32 size = item.Size; + + if (size == 0) + { + if (cluster != 0) + return S_FALSE; + } + else + { + UInt32 clusterSize = Header.ClusterSize(); + for (;; size -= clusterSize) + { + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + streamSpec->Vector.Add(cluster - 2); + cluster = Fat[cluster]; + if (size <= clusterSize) + break; + } + if (!Header.IsEocAndUnused(cluster)) + return S_FALSE; + } + RINOK(streamSpec->InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI8}, + { NULL, kpidShortName, VT_BSTR} +}; + +enum +{ + kpidNumFats = kpidUserDefined + // kpidOemName, + // kpidVolName, + // kpidFileSysType +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidVolumeName, VT_BSTR}, + + { L"FATs", kpidNumFats, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI4}, + // { L"OEM Name", kpidOemName, VT_BSTR}, + // { L"Volume Name", kpidVolName, VT_BSTR}, + // { L"File System Type", kpidFileSysType, VT_BSTR} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME localFileTime, utc; + if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime)) + if (LocalFileTimeToFileTime(&localFileTime, &utc)) + { + UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; + t64 += ms10 * 100000; + utc.dwLowDateTime = (DWORD)t64; + utc.dwHighDateTime = (DWORD)(t64 >> 32); + prop = utc; + } +} + +/* +static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop) +{ + char dest[32]; + memcpy(dest, src, size); + dest[size] = 0; + prop = FatStringToUnicode(dest); +} + +#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop) +*/ + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidFileSystem: + { + wchar_t s[32] = { L'F', L'A', L'T' }; + ConvertUInt32ToString(Header.NumFatBits, s + 3); + prop = s; + break; + } + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; + case kpidHeadersSize: prop = GetHeadersSize(); break; + case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break; + case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; + case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break; + case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break; + // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; + // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + switch(propID) + { + case kpidPath: prop = GetItemPath(index); break; + case kpidShortName: prop = item.GetShortName(); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break; + case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; + case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break; + case kpidAttrib: prop = (UInt32)item.Attrib; break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = Items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + totalPackSize += Header.GetFilePackSize(item.Size); + totalSize += item.Size; + + if (!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + int res = NArchive::NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + HRESULT hres = GetStream(index, &inStream); + if (hres != S_FALSE) + { + RINOK(hres); + if (inStream) + { + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) + res = NArchive::NExtract::NOperationResult::kOK; + } + } + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/GZip/GZipHandler.cpp b/CPP/7zip/Archive/GZip/GZipHandler.cpp deleted file mode 100755 index 96ae85f1..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandler.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// GZipHandler.cpp - -#include "StdAfx.h" - -#include "GZipHandler.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" -#include "Common/ComTry.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../../ICoder.h" -#include "../../Common/ProgressUtils.h" -#include "../../Common/CreateCoder.h" -#include "../Common/OutStreamWithCRC.h" - -using namespace NWindows; - -namespace NArchive { -namespace NGZip { - -static const CMethodId kMethodId_Deflate = 0x040108; - -const wchar_t *kHostOS[] = -{ - L"FAT", - L"AMIGA", - L"VMS", - L"Unix", - L"VM_CMS", - L"Atari", // what if it's a minix filesystem? [cjh] - L"HPFS", // filesystem used by OS/2 (and NT 3.x) - L"Mac", - L"Z_System", - L"CPM", - L"TOPS20", // pkzip 2.50 NTFS - L"NTFS", // filesystem used by Windows NT - L"QDOS ", // SMS/QDOS - L"Acorn", // Archimedes Acorn RISC OS - L"VFAT", // filesystem used by Windows 95, NT - L"MVS", - L"BeOS", // hybrid POSIX/database filesystem - // BeBOX or PowerMac - L"Tandem", - L"THEOS" -}; - -static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); - -static const wchar_t *kUnknownOS = L"Unknown"; - -/* -enum // PropID -{ - kpidExtraIsPresent = kpidUserDefined, - kpidExtraFlags, - kpidIsText -}; -*/ - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME}, - // { NULL, kpidMethod, VT_UI1}, - { NULL, kpidHostOS, VT_BSTR}, - { NULL, kpidCRC, VT_UI4} - // { L"Extra", kpidExtraIsPresent, VT_BOOL} - // { L"Extra flags", kpidExtraFlags, VT_UI1}, - // { L"Is Text", kpidIsText, VT_BOOL}, -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = 1; - return S_OK; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) - { - case kpidPath: - if (m_Item.NameIsPresent()) - prop = MultiByteToUnicodeString(m_Item.Name, CP_ACP); - break; - case kpidMTime: - { - FILETIME utcTime; - if (m_Item.Time != 0) - { - NTime::UnixTimeToFileTime((UInt32)m_Item.Time, utcTime); - prop = utcTime; - } - else - { - // utcTime.dwLowDateTime = utcTime.dwHighDateTime = 0; - // prop = utcTime; - } - break; - } - case kpidSize: prop = UInt64(m_Item.UnPackSize32); break; - case kpidPackSize: prop = m_PackSize; break; - case kpidCommented: prop = m_Item.CommentIsPresent(); break; - case kpidHostOS: - prop = (m_Item.HostOS < kNumHostOSes) ? - kHostOS[m_Item.HostOS] : kUnknownOS; - break; - case kpidMethod: prop = m_Item.CompressionMethod; break; - case kpidCRC: prop = m_Item.FileCRC; break; - /* - case kpidExtraFlags: prop = m_Item.ExtraFlags; break; - case kpidIsText: prop = m_Item.IsText(); break; - case kpidExtraIsPresent: prop = m_Item.ExtraFieldIsPresent(); break; - */ - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) -{ - COM_TRY_BEGIN - try - { - CInArchive archive; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); - RINOK(archive.ReadHeader(inStream, m_Item)); - m_DataOffset = archive.GetOffset(); - UInt64 newPosition; - RINOK(inStream->Seek(-8, STREAM_SEEK_END, &newPosition)); - m_PackSize = newPosition - (m_StreamStartPosition + m_DataOffset); - if (archive.ReadPostHeader(inStream, m_Item) != S_OK) - return S_FALSE; - m_Stream = inStream; - } - catch(...) - { - return S_FALSE; - } - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - m_Stream.Release(); - return S_OK; -} - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 _aTestMode, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); - if (!allFilesMode) - { - if (numItems == 0) - return S_OK; - if (numItems != 1) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } - - bool testMode = (_aTestMode != 0); - - extractCallback->SetTotal(m_PackSize); - - UInt64 currentTotalPacked = 0; - - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - if(!testMode && !realOutStream) - return S_OK; - - extractCallback->PrepareOperation(askMode); - - COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - realOutStream.Release(); - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - CMyComPtr<ICompressCoder> deflateDecoder; - bool firstItem = true; - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - Int32 opRes; - for (;;) - { - lps->InSize = currentTotalPacked; - lps->OutSize = outStreamSpec->GetSize(); - - CInArchive archive; - CItem item; - HRESULT result = archive.ReadHeader(m_Stream, item); - if (result != S_OK) - { - if (firstItem) - return E_FAIL; - opRes = NArchive::NExtract::NOperationResult::kOK; - break; - } - firstItem = false; - - UInt64 dataStartPos; - RINOK(m_Stream->Seek(0, STREAM_SEEK_CUR, &dataStartPos)); - - outStreamSpec->InitCRC(); - - if (item.CompressionMethod != NFileHeader::NCompressionMethod::kDeflate) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - - if (!deflateDecoder) - { - RINOK(CreateCoder( - EXTERNAL_CODECS_VARS - kMethodId_Deflate, deflateDecoder, false)); - if (!deflateDecoder) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - } - result = deflateDecoder->Code(m_Stream, outStream, NULL, NULL, progress); - if (result != S_OK) - { - if (result != S_FALSE) - return result; - opRes = NArchive::NExtract::NOperationResult::kDataError; - break; - } - - CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; - RINOK(deflateDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, - &getInStreamProcessedSize)); - UInt64 packSize; - RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize)); - UInt64 pos; - RINOK(m_Stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos)); - - currentTotalPacked = pos - m_StreamStartPosition; - - CItem postItem; - if (archive.ReadPostHeader(m_Stream, postItem) != S_OK) - return E_FAIL; - if((outStreamSpec->GetCRC() != postItem.FileCRC)) - { - opRes = NArchive::NExtract::NOperationResult::kCRCError; - break; - } - } - outStream.Release(); - return extractCallback->SetOperationResult(opRes); - COM_TRY_END -} - -IMPL_ISetCompressCodecsInfo - -}} diff --git a/CPP/7zip/Archive/GZip/GZipHandler.h b/CPP/7zip/Archive/GZip/GZipHandler.h deleted file mode 100755 index 49a01a8d..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandler.h +++ /dev/null @@ -1,63 +0,0 @@ -// GZip/Handler.h - -#ifndef __GZIP_HANDLER_H -#define __GZIP_HANDLER_H - -#include "Common/MyCom.h" - -#include "../IArchive.h" - -#include "../../Common/CreateCoder.h" - -#include "GZipIn.h" -#include "GZipUpdate.h" - -namespace NArchive { -namespace NGZip { - -class CHandler: - public IInArchive, - public IOutArchive, - public ISetProperties, - PUBLIC_ISetCompressCodecsInfo - public CMyUnknownImp -{ -public: - MY_QUERYINTERFACE_BEGIN2(IInArchive) - MY_QUERYINTERFACE_ENTRY(IOutArchive) - MY_QUERYINTERFACE_ENTRY(ISetProperties) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - - INTERFACE_IInArchive(;) - INTERFACE_IOutArchive(;) - - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); - - DECL_ISetCompressCodecsInfo - - CHandler() { InitMethodProperties(); } - -private: - NArchive::NGZip::CItem m_Item; - UInt64 m_StreamStartPosition; - UInt64 m_DataOffset; - UInt64 m_PackSize; - CMyComPtr<IInStream> m_Stream; - CCompressionMethodMode m_Method; - UInt32 m_Level; - - DECL_EXTERNAL_CODECS_VARS - - void InitMethodProperties() - { - m_Method.NumMatchFinderCyclesDefined = false; - m_Level = m_Method.NumPasses = m_Method.NumFastBytes = - m_Method.NumMatchFinderCycles = m_Method.Algo = 0xFFFFFFFF; - } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp deleted file mode 100755 index bcbfc7e2..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// GZipHandlerOut.cpp - -#include "StdAfx.h" - -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/ParseProperties.h" - -#include "GZipHandler.h" -#include "GZipUpdate.h" - -using namespace NWindows; -using namespace NTime; - -namespace NArchive { -namespace NGZip { - -static const UInt32 kAlgoX1 = 0; -static const UInt32 kAlgoX5 = 1; - -static const UInt32 kNumPassesX1 = 1; -static const UInt32 kNumPassesX7 = 3; -static const UInt32 kNumPassesX9 = 10; - -static const UInt32 kNumFastBytesX1 = 32; -static const UInt32 kNumFastBytesX7 = 64; -static const UInt32 kNumFastBytesX9 = 128; - - -STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) -{ - *timeType = NFileTimeType::kUnix; - return S_OK; -} - -static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream) -{ - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); -} - -STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, - IArchiveUpdateCallback *updateCallback) -{ - if (numItems != 1) - return E_INVALIDARG; - - UInt64 size; - Int32 newData; - Int32 newProperties; - UInt32 indexInArchive; - UInt32 itemIndex = 0; - if (!updateCallback) - return E_FAIL; - RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProperties, &indexInArchive)); - - CItem newItem = m_Item; - newItem.ExtraFlags = 0; - newItem.Flags = 0; - if (IntToBool(newProperties)) - { - FILETIME utcTime; - UString name; - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidMTime, &prop)); - if (prop.vt != VT_FILETIME) - return E_INVALIDARG; - utcTime = prop.filetime; - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidPath, &prop)); - if (prop.vt == VT_EMPTY) - name.Empty(); - else if (prop.vt != VT_BSTR) - return E_INVALIDARG; - else - name = prop.bstrVal; - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidIsDir, &prop)); - if (prop.vt == VT_BOOL) - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; - } - if(!FileTimeToUnixTime(utcTime, newItem.Time)) - return E_INVALIDARG; - newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); - int dirDelimiterPos = newItem.Name.ReverseFind(CHAR_PATH_SEPARATOR); - if (dirDelimiterPos >= 0) - newItem.Name = newItem.Name.Mid(dirDelimiterPos + 1); - - newItem.SetNameIsPresentFlag(!newItem.Name.IsEmpty()); - } - - if (IntToBool(newData)) - { - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - newItem.UnPackSize32 = (UInt32)size; - - UInt32 level = m_Level; - if (level == 0xFFFFFFFF) - level = 5; - if (m_Method.NumPasses == 0xFFFFFFFF) - m_Method.NumPasses = (level >= 9 ? kNumPassesX9 : - (level >= 7 ? kNumPassesX7 : - kNumPassesX1)); - if (m_Method.NumFastBytes == 0xFFFFFFFF) - m_Method.NumFastBytes = (level >= 9 ? kNumFastBytesX9 : - (level >= 7 ? kNumFastBytesX7 : - kNumFastBytesX1)); - if (m_Method.Algo == 0xFFFFFFFF) - m_Method.Algo = - (level >= 5 ? kAlgoX5 : - kAlgoX1); - - return UpdateArchive( - EXTERNAL_CODECS_VARS - m_Stream, size, outStream, newItem, m_Method, itemIndex, updateCallback); - } - - if (indexInArchive != 0) - return E_INVALIDARG; - - if (IntToBool(newProperties)) - { - COutArchive outArchive; - outArchive.Create(outStream); - outArchive.WriteHeader(newItem); - RINOK(m_Stream->Seek(m_StreamStartPosition + m_DataOffset, STREAM_SEEK_SET, NULL)); - } - else - { - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - } - return CopyStreams(m_Stream, outStream); -} - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) -{ - InitMethodProperties(); - for (int i = 0; i < numProperties; i++) - { - UString name = names[i]; - name.MakeUpper(); - const PROPVARIANT &prop = values[i]; - if (name[0] == L'X') - { - UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - m_Level = level; - } - else if (name.Left(4) == L"PASS") - { - UInt32 num = kNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - m_Method.NumPasses = num; - } - else if (name.Left(2) == L"FB") - { - UInt32 num = kNumFastBytesX9; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_Method.NumFastBytes = num; - } - else if (name.Left(2) == L"MC") - { - UInt32 num = 0xFFFFFFFF; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_Method.NumMatchFinderCycles = num; - m_Method.NumMatchFinderCyclesDefined = true; - } - else if (name.Left(1) == L"A") - { - UInt32 num = kAlgoX5; - RINOK(ParsePropValue(name.Mid(1), prop, num)); - m_Method.Algo = num; - } - else - return E_INVALIDARG; - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipHeader.cpp b/CPP/7zip/Archive/GZip/GZipHeader.cpp deleted file mode 100755 index 88b34e86..00000000 --- a/CPP/7zip/Archive/GZip/GZipHeader.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Archive/GZip/Header.h - -#include "StdAfx.h" - -#include "GZipHeader.h" - -namespace NArchive { -namespace NGZip { - -extern UInt16 kSignature = 0x8B1F + 1; - -static class CMarkersInitializer -{ -public: - CMarkersInitializer() - { kSignature--; } -} g_MarkerInitializer; - -}} - diff --git a/CPP/7zip/Archive/GZip/GZipHeader.h b/CPP/7zip/Archive/GZip/GZipHeader.h deleted file mode 100755 index 010a60aa..00000000 --- a/CPP/7zip/Archive/GZip/GZipHeader.h +++ /dev/null @@ -1,85 +0,0 @@ -// Archive/GZip/Header.h - -#ifndef __ARCHIVE_GZIP_HEADER_H -#define __ARCHIVE_GZIP_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NGZip { - -extern UInt16 kSignature; -static const UInt32 kSignatureSize = 2; - -namespace NFileHeader -{ - /* - struct CBlock - { - UInt16 Id; - Byte CompressionMethod; - Byte Flags; - UInt32 Time; - Byte ExtraFlags; - Byte HostOS; - }; - */ - - namespace NFlags - { - const int kDataIsText = 1 << 0; - const int kHeaderCRCIsPresent = 1 << 1; - const int kExtraIsPresent = 1 << 2; - const int kNameIsPresent = 1 << 3; - const int kComentIsPresent = 1 << 4; - } - - namespace NExtraFlags - { - enum EEnum - { - kMaximum = 2, - kFastest = 4 - }; - } - - namespace NCompressionMethod - { - const Byte kDeflate = 8; - } - - namespace NHostOS - { - enum EEnum - { - kFAT = 0, // filesystem used by MS-DOS, OS/2, Win32 - // pkzip 2.50 (FAT / VFAT / FAT32 file systems) - kAMIGA = 1, - kVMS = 2, // VAX/VMS - kUnix = 3, - kVM_CMS = 4, - kAtari = 5, // what if it's a minix filesystem? [cjh] - kHPFS = 6, // filesystem used by OS/2 (and NT 3.x) - kMac = 7, - kZ_System = 8, - kCPM = 9, - kTOPS20 = 10, // pkzip 2.50 NTFS - kNTFS = 11, // filesystem used by Windows NT - kQDOS = 12, // SMS/QDOS - kAcorn = 13, // Archimedes Acorn RISC OS - kVFAT = 14, // filesystem used by Windows 95, NT - kMVS = 15, - kBeOS = 16, // hybrid POSIX/database filesystem - // BeBOX or PowerMac - kTandem = 17, - kTHEOS = 18, - - kUnknown = 255 - }; - const int kNumHostSystems = 19; - } -} - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipIn.cpp b/CPP/7zip/Archive/GZip/GZipIn.cpp deleted file mode 100755 index d754c045..00000000 --- a/CPP/7zip/Archive/GZip/GZipIn.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Archive/GZipIn.cpp - -#include "StdAfx.h" - -#include "GZipIn.h" - -#include "Common/Defs.h" -#include "Common/MyCom.h" -#include "Windows/Defs.h" - -#include "../../Common/StreamUtils.h" - -extern "C" -{ - #include "../../../../C/7zCrc.h" -} - -namespace NArchive { -namespace NGZip { - -HRESULT CInArchive::ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size) -{ - RINOK(ReadStream_FALSE(inStream, data, size)); - m_Position += size; - return S_OK; -} - -HRESULT CInArchive::ReadByte(ISequentialInStream *inStream, Byte &value, UInt32 &crc) -{ - RINOK(ReadBytes(inStream, &value, 1)); - crc = CRC_UPDATE_BYTE(crc, value); - return S_OK; -} - -HRESULT CInArchive::ReadUInt16(ISequentialInStream *inStream, UInt16 &value, UInt32 &crc) -{ - value = 0; - for (int i = 0; i < 2; i++) - { - Byte b; - RINOK(ReadByte(inStream, b, crc)); - value |= (UInt16(b) << (8 * i)); - } - return S_OK; -} - -HRESULT CInArchive::ReadUInt32(ISequentialInStream *inStream, UInt32 &value, UInt32 &crc) -{ - value = 0; - for (int i = 0; i < 4; i++) - { - Byte b; - RINOK(ReadByte(inStream, b, crc)); - value |= (UInt32(b) << (8 * i)); - } - return S_OK; -} - -HRESULT CInArchive::ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, UInt32 &crc) -{ - resString.Empty(); - for (;;) - { - Byte c; - RINOK(ReadByte(inStream, c, crc)); - if (c == 0) - return S_OK; - resString += char(c); - } -} - -HRESULT CInArchive::ReadHeader(ISequentialInStream *inStream, CItem &item) -{ - item.Clear(); - m_Position = 0; - - UInt16 signature; - UInt32 crc = CRC_INIT_VAL;; - RINOK(ReadUInt16(inStream, signature, crc)); - if (signature != kSignature) - return S_FALSE; - - RINOK(ReadByte(inStream, item.CompressionMethod, crc)); - RINOK(ReadByte(inStream, item.Flags, crc)); - RINOK(ReadUInt32(inStream, item.Time, crc)); - RINOK(ReadByte(inStream, item.ExtraFlags, crc)); - RINOK(ReadByte(inStream, item.HostOS, crc)); - - if (item.ExtraFieldIsPresent()) - { - UInt16 extraSize; - RINOK(ReadUInt16(inStream, extraSize, crc)); - item.Extra.SetCapacity(extraSize); - RINOK(ReadBytes(inStream, item.Extra, extraSize)); - crc = CrcUpdate(crc, item.Extra, extraSize); - } - if (item.NameIsPresent()) - RINOK(ReadZeroTerminatedString(inStream, item.Name, crc)); - if (item.CommentIsPresent()) - RINOK(ReadZeroTerminatedString(inStream, item.Comment, crc)); - if (item.HeaderCRCIsPresent()) - { - UInt16 headerCRC; - UInt32 dummy = 0; - RINOK(ReadUInt16(inStream, headerCRC, dummy)); - if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC) - return S_FALSE; - } - return S_OK; -} - -HRESULT CInArchive::ReadPostHeader(ISequentialInStream *inStream, CItem &item) -{ - UInt32 dummy = 0; - RINOK(ReadUInt32(inStream, item.FileCRC, dummy)); - return ReadUInt32(inStream, item.UnPackSize32, dummy); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipIn.h b/CPP/7zip/Archive/GZip/GZipIn.h deleted file mode 100755 index c2e07490..00000000 --- a/CPP/7zip/Archive/GZip/GZipIn.h +++ /dev/null @@ -1,30 +0,0 @@ -// Archive/GZipIn.h - -#ifndef __ARCHIVE_GZIP_IN_H -#define __ARCHIVE_GZIP_IN_H - -#include "GZipHeader.h" -#include "GZipItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NGZip { - -class CInArchive -{ - UInt64 m_Position; - - HRESULT ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size); - HRESULT ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, UInt32 &crc); - HRESULT ReadByte(ISequentialInStream *inStream, Byte &value, UInt32 &crc); - HRESULT ReadUInt16(ISequentialInStream *inStream, UInt16 &value, UInt32 &crc); - HRESULT ReadUInt32(ISequentialInStream *inStream, UInt32 &value, UInt32 &crc); -public: - HRESULT ReadHeader(ISequentialInStream *inStream, CItem &item); - HRESULT ReadPostHeader(ISequentialInStream *inStream, CItem &item); - UInt64 GetOffset() const { return m_Position; } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipItem.h b/CPP/7zip/Archive/GZip/GZipItem.h deleted file mode 100755 index 678962a9..00000000 --- a/CPP/7zip/Archive/GZip/GZipItem.h +++ /dev/null @@ -1,59 +0,0 @@ -// Archive/GZipItem.h - -#ifndef __ARCHIVE_GZIP_ITEM_H -#define __ARCHIVE_GZIP_ITEM_H - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "Common/Buffer.h" - -namespace NArchive { -namespace NGZip { - -class CItem -{ -private: - bool TestFlag(Byte flag) const { return ((Flags & flag) != 0); } -public: - Byte CompressionMethod; - Byte Flags; - UInt32 Time; - Byte ExtraFlags; - Byte HostOS; - UInt32 FileCRC; - UInt32 UnPackSize32; - - AString Name; - AString Comment; - CByteBuffer Extra; - - bool IsText() const - { return TestFlag(NFileHeader::NFlags::kDataIsText); } - bool HeaderCRCIsPresent() const - { return TestFlag(NFileHeader::NFlags::kHeaderCRCIsPresent); } - bool ExtraFieldIsPresent() const - { return TestFlag(NFileHeader::NFlags::kExtraIsPresent); } - bool NameIsPresent() const - { return TestFlag(NFileHeader::NFlags::kNameIsPresent); } - bool CommentIsPresent() const - { return TestFlag(NFileHeader::NFlags::kComentIsPresent); } - - void SetNameIsPresentFlag(bool nameIsPresent) - { - if (nameIsPresent) - Flags |= NFileHeader::NFlags::kNameIsPresent; - else - Flags &= (~NFileHeader::NFlags::kNameIsPresent); - } - - void Clear() - { - Name.Empty(); - Comment.Empty();; - Extra.SetCapacity(0); - } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipOut.cpp b/CPP/7zip/Archive/GZip/GZipOut.cpp deleted file mode 100755 index 3d0d4f7a..00000000 --- a/CPP/7zip/Archive/GZip/GZipOut.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// Archive/GZipOut.cpp - -#include "StdAfx.h" - -#include "GZipOut.h" - -#include "Windows/Defs.h" -#include "../../Common/StreamUtils.h" - -namespace NArchive { -namespace NGZip { - -HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) -{ - return WriteStream(m_Stream, buffer, size); -} - -HRESULT COutArchive::WriteByte(Byte value) -{ - return WriteBytes(&value, 1); -} - -HRESULT COutArchive::WriteUInt16(UInt16 value) -{ - for (int i = 0; i < 2; i++) - { - RINOK(WriteByte((Byte)value)); - value >>= 8; - } - return S_OK; -} - -HRESULT COutArchive::WriteUInt32(UInt32 value) -{ - for (int i = 0; i < 4; i++) - { - RINOK(WriteByte((Byte)value)); - value >>= 8; - } - return S_OK; -} - -HRESULT COutArchive::WriteHeader(const CItem &item) -{ - RINOK(WriteUInt16(kSignature)); - RINOK(WriteByte(item.CompressionMethod)); - RINOK(WriteByte((Byte)(item.Flags & NFileHeader::NFlags::kNameIsPresent))); - RINOK(WriteUInt32(item.Time)); - RINOK(WriteByte(item.ExtraFlags)); - RINOK(WriteByte(item.HostOS)); - if (item.NameIsPresent()) - { - RINOK(WriteBytes((const char *)item.Name, item.Name.Length())); - RINOK(WriteByte(0)); - } - return S_OK; -} - -HRESULT COutArchive::WritePostHeader(const CItem &item) -{ - RINOK(WriteUInt32(item.FileCRC)); - return WriteUInt32(item.UnPackSize32); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipOut.h b/CPP/7zip/Archive/GZip/GZipOut.h deleted file mode 100755 index a2ba2ebf..00000000 --- a/CPP/7zip/Archive/GZip/GZipOut.h +++ /dev/null @@ -1,29 +0,0 @@ -// Archive/GZipOut.h - -#ifndef __ARCHIVE_GZIP_OUT_H -#define __ARCHIVE_GZIP_OUT_H - -#include "Common/MyCom.h" -#include "GZipHeader.h" -#include "GZipItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NGZip { - -class COutArchive -{ - CMyComPtr<ISequentialOutStream> m_Stream; - HRESULT WriteBytes(const void *buffer, UInt32 size); - HRESULT WriteByte(Byte value); - HRESULT WriteUInt16(UInt16 value); - HRESULT WriteUInt32(UInt32 value); -public: - void Create(ISequentialOutStream *outStream) { m_Stream = outStream; } - HRESULT WriteHeader(const CItem &item); - HRESULT WritePostHeader(const CItem &item); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipRegister.cpp b/CPP/7zip/Archive/GZip/GZipRegister.cpp deleted file mode 100755 index b4bc6ded..00000000 --- a/CPP/7zip/Archive/GZip/GZipRegister.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// GZipRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "GZipHandler.h" -static IInArchive *CreateArc() { return new NArchive::NGZip::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NGZip::CHandler; } -#else -#define CreateArcOut 0 -#endif - -static CArcInfo g_ArcInfo = - { L"GZip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; - -REGISTER_ARC(GZip) diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.cpp b/CPP/7zip/Archive/GZip/GZipUpdate.cpp deleted file mode 100755 index f3a4d331..00000000 --- a/CPP/7zip/Archive/GZip/GZipUpdate.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// GZipUpdate.cpp - -#include "StdAfx.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" - -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" - -#include "../../ICoder.h" - -#include "../../Common/CreateCoder.h" -#include "../../Common/ProgressUtils.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/InStreamWithCRC.h" - -#include "GZipUpdate.h" - -namespace NArchive { -namespace NGZip { - -static const CMethodId kMethodId_Deflate = 0x040108; - -static const Byte kHostOS = - #ifdef _WIN32 - NFileHeader::NHostOS::kFAT; - #else - NFileHeader::NHostOS::kUnix; - #endif - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream * /* inStream */, - UInt64 unpackSize, - ISequentialOutStream *outStream, - const CItem &newItem, - const CCompressionMethodMode &compressionMethod, - int indexInClient, - IArchiveUpdateCallback *updateCallback) -{ - UInt64 complexity = unpackSize; - - RINOK(updateCallback->SetTotal(complexity)); - - CMyComPtr<ICompressCoder> deflateEncoder; - - complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); - - CMyComPtr<ISequentialInStream> fileInStream; - - RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); - - CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; - CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); - inStreamSpec->SetStream(fileInStream); - inStreamSpec->Init(); - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(updateCallback, true); - - COutArchive outArchive; - outArchive.Create(outStream); - - CItem item = newItem; - item.CompressionMethod = NFileHeader::NCompressionMethod::kDeflate; - item.ExtraFlags = 0; - item.HostOS = kHostOS; - - RINOK(outArchive.WriteHeader(item)); - - { - RINOK(CreateCoder( - EXTERNAL_CODECS_LOC_VARS - kMethodId_Deflate, deflateEncoder, true)); - if (!deflateEncoder) - return E_NOTIMPL; - - NWindows::NCOM::CPropVariant properties[] = - { - compressionMethod.Algo, - compressionMethod.NumPasses, - compressionMethod.NumFastBytes, - compressionMethod.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kNumPasses, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!compressionMethod.NumMatchFinderCyclesDefined) - numProps--; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - RINOK(deflateEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); - RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps)); - } - RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); - - item.FileCRC = inStreamSpec->GetCRC(); - item.UnPackSize32 = (UInt32)inStreamSpec->GetSize(); - RINOK(outArchive.WritePostHeader(item)); - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.h b/CPP/7zip/Archive/GZip/GZipUpdate.h deleted file mode 100755 index 231d7972..00000000 --- a/CPP/7zip/Archive/GZip/GZipUpdate.h +++ /dev/null @@ -1,37 +0,0 @@ -// GZip/Update.h - -#ifndef __GZIP_UPDATE_H -#define __GZIP_UPDATE_H - -#include "../IArchive.h" - -#include "../../Common/CreateCoder.h" - -#include "GZipOut.h" -#include "GZipItem.h" - -namespace NArchive { -namespace NGZip { - -struct CCompressionMethodMode -{ - UInt32 NumPasses; - UInt32 NumFastBytes; - UInt32 Algo; - bool NumMatchFinderCyclesDefined; - UInt32 NumMatchFinderCycles; -}; - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, - UInt64 unpackSize, - ISequentialOutStream *outStream, - const CItem &newItem, - const CCompressionMethodMode &compressionMethod, - int indexInClient, - IArchiveUpdateCallback *updateCallback); - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/StdAfx.h b/CPP/7zip/Archive/GZip/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/GZip/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp new file mode 100755 index 00000000..8f91003f --- /dev/null +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -0,0 +1,820 @@ +// GzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/DeflateDecoder.h" +#include "../Compress/DeflateEncoder.h" + +#include "Common/InStreamWithCRC.h" +#include "Common/OutStreamWithCRC.h" +#include "Common/ParseProperties.h" + +#define Get32(p) GetUi32(p) + +using namespace NWindows; + +namespace NArchive { +namespace NGz { + +static const UInt16 kSignature = 0x8B1F; + +namespace NHeader +{ + namespace NFlags + { + const Byte kIsText = 1 << 0; + const Byte kCrc = 1 << 1; + const Byte kExtra = 1 << 2; + const Byte kName = 1 << 3; + const Byte kComment = 1 << 4; + } + + namespace NExtraFlags + { + const Byte kMaximum = 2; + const Byte kFastest = 4; + } + + namespace NCompressionMethod + { + const Byte kDeflate = 8; + } + + namespace NHostOS + { + enum EEnum + { + kFAT = 0, + kAMIGA, + kVMS, + kUnix, + kVM_CMS, + kAtari, + kHPFS, + kMac, + kZ_System, + kCPM, + kTOPS20, + kNTFS, + kQDOS, + kAcorn, + kVFAT, + kMVS, + kBeOS, + kTandem, + + kUnknown = 255 + }; + } +} + +static const char *kHostOSes[] = +{ + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" +}; + +static const char *kUnknownOS = "Unknown"; + +class CItem +{ + bool TestFlag(Byte flag) const { return (Flags & flag) != 0; } +public: + Byte Method; + Byte Flags; + Byte ExtraFlags; + Byte HostOS; + UInt32 Time; + UInt32 Crc; + UInt32 Size32; + + AString Name; + AString Comment; + // CByteBuffer Extra; + + // bool IsText() const { return TestFlag(NHeader::NFlags::kIsText); } + bool HeaderCrcIsPresent() const { return TestFlag(NHeader::NFlags::kCrc); } + bool ExtraFieldIsPresent() const { return TestFlag(NHeader::NFlags::kExtra); } + bool NameIsPresent() const { return TestFlag(NHeader::NFlags::kName); } + bool CommentIsPresent() const { return TestFlag(NHeader::NFlags::kComment); } + + void Clear() + { + Name.Empty(); + Comment.Empty(); + // Extra.SetCapacity(0); + } + + HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter2(ISequentialInStream *stream); + + HRESULT WriteHeader(ISequentialOutStream *stream); + HRESULT WriteFooter(ISequentialOutStream *stream); +}; + +static HRESULT ReadBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */) +{ + value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + value |= (UInt16(b) << (8 * i)); + } + return S_OK; +} + +static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */) +{ + s.Empty(); + for (UInt32 i = 0; i < limit; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + if (b == 0) + return S_OK; + s += (char)b; + } + return S_FALSE; +} + +HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Clear(); + + // Header-CRC field had another meaning in old version of gzip! + // UInt32 crc = CRC_INIT_VAL; + Byte buf[10]; + + RINOK(ReadBytes(stream, buf, 10)); + + if (GetUi16(buf) != kSignature) + return S_FALSE; + + Method = buf[2]; + + if (Method != NHeader::NCompressionMethod::kDeflate) + return S_FALSE; + + Flags = buf[3]; + Time = Get32(buf + 4); + ExtraFlags = buf[8]; + HostOS = buf[9]; + + // crc = CrcUpdate(crc, buf, 10); + + if (ExtraFieldIsPresent()) + { + UInt16 extraSize; + RINOK(ReadUInt16(stream, extraSize /* , crc */)); + RINOK(SkipBytes(stream, extraSize)); + // Extra.SetCapacity(extraSize); + // RINOK(ReadStream_FALSE(stream, Extra, extraSize)); + // crc = CrcUpdate(crc, Extra, extraSize); + } + if (NameIsPresent()) + RINOK(ReadString(stream, Name, (1 << 10) /* , crc */)); + if (CommentIsPresent()) + RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */)); + + if (HeaderCrcIsPresent()) + { + UInt16 headerCRC; + // UInt32 dummy = 0; + RINOK(ReadUInt16(stream, headerCRC /* , dummy */)); + /* + if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC) + return S_FALSE; + */ + } + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Byte buf[8]; + RINOK(ReadBytes(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter2(ISequentialInStream *stream) +{ + Byte buf[8]; + RINOK(ReadStream_FALSE(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return S_OK; +} + +HRESULT CItem::WriteHeader(ISequentialOutStream *stream) +{ + Byte buf[10]; + SetUi16(buf, kSignature); + buf[2] = Method; + buf[3] = Flags & NHeader::NFlags::kName; + // buf[3] |= NHeader::NFlags::kCrc; + SetUi32(buf + 4, Time); + buf[8] = ExtraFlags; + buf[9] = HostOS; + RINOK(WriteStream(stream, buf, 10)); + // crc = CrcUpdate(CRC_INIT_VAL, buf, 10); + if (NameIsPresent()) + { + // crc = CrcUpdate(crc, (const char *)Name, Name.Length() + 1); + RINOK(WriteStream(stream, (const char *)Name, Name.Length() + 1)); + } + // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc)); + // RINOK(WriteStream(stream, buf, 2)); + return S_OK; +} + +HRESULT CItem::WriteFooter(ISequentialOutStream *stream) +{ + Byte buf[8]; + SetUi32(buf, Crc); + SetUi32(buf + 4, Size32); + return WriteStream(stream, buf, 8); +} + +static const UInt32 kAlgoX1 = 0; +static const UInt32 kAlgoX5 = 1; + +static const UInt32 kNumPassesX1 = 1; +static const UInt32 kNumPassesX7 = 3; +static const UInt32 kNumPassesX9 = 10; + +static const UInt32 kNumFastBytesX1 = 32; +static const UInt32 kNumFastBytesX7 = 64; +static const UInt32 kNumFastBytesX9 = 128; + +struct CCompressMode +{ + UInt32 NumPasses; + UInt32 NumFastBytes; + UInt32 Algo; + UInt32 Mc; + bool McDefined; + + bool IsMaximum() const { return Algo > 0; } + + void Init() + { + NumPasses = NumFastBytes = Mc = Algo = 0xFFFFFFFF; + McDefined = false; + } + + void Normalize(UInt32 level) + { + if (level == 0xFFFFFFFF) + level = 5; + if (NumPasses == 0xFFFFFFFF) + NumPasses = + (level >= 9 ? kNumPassesX9 : + (level >= 7 ? kNumPassesX7 : + kNumPassesX1)); + if (NumFastBytes == 0xFFFFFFFF) + NumFastBytes = + (level >= 9 ? kNumFastBytesX9 : + (level >= 7 ? kNumFastBytesX7 : + kNumFastBytesX1)); + if (Algo == 0xFFFFFFFF) + Algo = (level >= 5 ? + kAlgoX5 : + kAlgoX1); + } +}; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CItem _item; + UInt64 _startPosition; + UInt64 _headerSize; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr<IInStream> _stream; + CMyComPtr<ICompressCoder> _decoder; + NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; + + CCompressMode _method; + UInt32 _level; + + void InitMethodProperties() + { + _level = 0xFFFFFFFF; + _method.Init(); + } + +public: + MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + + CHandler() + { + InitMethodProperties(); + _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + _decoder = _decoderSpec; + } +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidCRC, VT_UI4} + // { NULL, kpidComment, VT_BSTR} +} +; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: + if (_item.NameIsPresent()) + prop = MultiByteToUnicodeString(_item.Name, CP_ACP); + break; + // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; + case kpidMTime: + { + if (_item.Time != 0) + { + FILETIME utc; + NTime::UnixTimeToFileTime(_item.Time, utc); + prop = utc; + } + break; + } + case kpidSize: if (_stream) prop = (UInt64)_item.Size32; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidHostOS: prop = (_item.HostOS < sizeof(kHostOSes) / sizeof(kHostOSes[0])) ? + kHostOSes[_item.HostOS] : kUnknownOS; break; + case kpidCRC: if (_stream) prop = _item.Crc; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + res = OpenSeq(stream); + if (res == S_OK) + { + UInt64 endPos; + res = stream->Seek(-8, STREAM_SEEK_END, &endPos); + _packSize = endPos + 8 - _startPosition; + _packSizeDefined = true; + if (res == S_OK) + { + res = _item.ReadFooter2(stream); + _stream = stream; + } + } + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + Close(); + _decoderSpec->SetInStream(stream); + _decoderSpec->InitInStream(true); + res = _item.ReadHeader(_decoderSpec); + _headerSize = _decoderSpec->GetInputProcessedSize(); + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _decoderSpec->ReleaseInStream(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (!allFilesMode) + { + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + } + + bool testMode = (_aTestMode != 0); + if (_stream) + extractCallback->SetTotal(_packSize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + _decoderSpec->InitInStream(true); + } + bool firstItem = true; + Int32 opRes; + for (;;) + { + lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize(); + _packSizeDefined = true; + lps->OutSize = outStreamSpec->GetSize(); + RINOK(lps->SetCur()); + + CItem item; + if (!firstItem || _stream) + { + HRESULT result = item.ReadHeader(_decoderSpec); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = firstItem ? + NArchive::NExtract::NOperationResult::kDataError : + NArchive::NExtract::NOperationResult::kOK; + break; + } + } + firstItem = false; + + UInt64 startOffset = outStreamSpec->GetSize(); + outStreamSpec->InitCRC(); + + HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + + _decoderSpec->AlignToByte(); + if (item.ReadFooter1(_decoderSpec) != S_OK) + { + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + if (item.Crc != outStreamSpec->GetCRC() || + item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset)) + { + opRes = NArchive::NExtract::NOperationResult::kCRCError; + break; + } + } + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +static const Byte kHostOS = + #ifdef _WIN32 + NHeader::NHostOS::kFAT; + #else + NHeader::NHostOS::kUnix; + #endif + +static HRESULT UpdateArchive( + ISequentialOutStream *outStream, + UInt64 unpackSize, + const CItem &newItem, + const CCompressMode &compressionMode, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + RINOK(updateCallback->SetTotal(unpackSize)); + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr<ISequentialInStream> fileInStream; + + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; + CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); + inStreamSpec->SetStream(fileInStream); + inStreamSpec->Init(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CItem item = newItem; + item.Method = NHeader::NCompressionMethod::kDeflate; + item.ExtraFlags = compressionMode.IsMaximum() ? + NHeader::NExtraFlags::kMaximum : + NHeader::NExtraFlags::kFastest; + + item.HostOS = kHostOS; + + RINOK(item.WriteHeader(outStream)); + + NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; + CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec; + { + NWindows::NCOM::CPropVariant props[] = + { + compressionMode.Algo, + compressionMode.NumPasses, + compressionMode.NumFastBytes, + compressionMode.Mc + }; + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kNumPasses, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!compressionMode.McDefined) + numProps--; + RINOK(deflateEncoderSpec->SetCoderProperties(propIDs, props, numProps)); + } + RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); + + item.Crc = inStreamSpec->GetCRC(); + item.Size32 = (UInt32)inStreamSpec->GetSize(); + RINOK(item.WriteFooter(outStream)); + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + if (numItems != 1) + return E_INVALIDARG; + + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); + + CItem newItem = _item; + newItem.ExtraFlags = 0; + newItem.Flags = 0; + if (IntToBool(newProps)) + { + { + FILETIME utcTime; + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); + if (prop.vt != VT_FILETIME) + return E_INVALIDARG; + utcTime = prop.filetime; + if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time)) + return E_INVALIDARG; + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + { + UString name = prop.bstrVal; + int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR); + if (dirDelimiterPos >= 0) + name = name.Mid(dirDelimiterPos + 1); + newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); + if (!newItem.Name.IsEmpty()) + newItem.Flags |= NHeader::NFlags::kName; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); + if (prop.vt == VT_BOOL) + { + if (prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + } + + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + + _method.Normalize(_level); + return UpdateArchive(outStream, size, newItem, _method, updateCallback); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + if (!_stream) + return E_NOTIMPL; + + UInt64 offset = _startPosition; + if (IntToBool(newProps)) + { + newItem.WriteHeader(outStream); + offset += _headerSize; + } + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProperties(); + for (int i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &prop = values[i]; + if (name[0] == L'X') + { + UInt32 level = 9; + RINOK(ParsePropValue(name.Mid(1), prop, level)); + _level = level; + } + else if (name.Left(4) == L"PASS") + { + UInt32 num = kNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + _method.NumPasses = num; + } + else if (name.Left(2) == L"FB") + { + UInt32 num = kNumFastBytesX9; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + _method.NumFastBytes = num; + } + else if (name.Left(2) == L"MC") + { + UInt32 num = 0xFFFFFFFF; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + _method.Mc = num; + _method.McDefined = true; + } + else if (name.Left(1) == L"A") + { + UInt32 num = kAlgoX5; + RINOK(ParsePropValue(name.Mid(1), prop, num)); + _method.Algo = num; + } + else + return E_INVALIDARG; + } + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"GZip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(GZip) + +}} diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index 88d6c408..85320276 100755 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -3,8 +3,8 @@ #ifndef __IARCHIVE_H #define __IARCHIVE_H -#include "../IStream.h" #include "../IProgress.h" +#include "../IStream.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) @@ -82,7 +82,6 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ - /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ @@ -139,6 +138,10 @@ ARCHIVE_INTERFACE(IInArchive, 0x60) INTERFACE_IInArchive(PURE) }; +ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) +{ + STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; +}; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ @@ -217,11 +220,14 @@ ARCHIVE_INTERFACE(ISetProperties, 0x03) { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) -#define IMP_IInArchive_ArcProps_NO \ +#define IMP_IInArchive_ArcProps_NO_Table \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ + +#define IMP_IInArchive_ArcProps_NO \ + IMP_IInArchive_ArcProps_NO_Table \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico Binary files differnew file mode 100755 index 00000000..882753ac --- /dev/null +++ b/CPP/7zip/Archive/Icons/fat.ico diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico Binary files differnew file mode 100755 index 00000000..6b2aeb00 --- /dev/null +++ b/CPP/7zip/Archive/Icons/ntfs.ico diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico Binary files differnew file mode 100755 index 00000000..33bed3c9 --- /dev/null +++ b/CPP/7zip/Archive/Icons/vhd.ico diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico Binary files differindex 02707351..281aa7dc 100755 --- a/CPP/7zip/Archive/Icons/xar.ico +++ b/CPP/7zip/Archive/Icons/xar.ico diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico Binary files differnew file mode 100755 index 00000000..02707351 --- /dev/null +++ b/CPP/7zip/Archive/Icons/xz.ico diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index f0c926c4..ed8da189 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -46,9 +46,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream, Close(); // try { - if(_archive.Open(stream) != S_OK) + if (_archive.Open(stream) != S_OK) return S_FALSE; - _inStream = stream; + _stream = stream; } // catch(...) { return S_FALSE; } return S_OK; @@ -58,7 +58,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { _archive.Clear(); - _inStream.Release(); + _stream.Release(); return S_OK; } @@ -160,7 +160,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = _archive.Refs.Size(); - if(numItems == 0) + if (numItems == 0) return S_OK; UInt64 totalSize = 0; UInt32 i; @@ -192,7 +192,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { @@ -211,7 +214,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, { const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; - if(item.IsDir()) + if (item.IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); @@ -231,16 +234,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, if (!testMode && (!realOutStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - continue; - } - RINOK(_inStream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); - streamSpec->Init(currentItemSize); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? + outStreamSpec->Init(currentItemSize); + RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); } @@ -248,4 +249,30 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + UInt64 blockIndex; + UInt64 currentItemSize; + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + if (item.IsDir()) + return S_FALSE; + currentItemSize = item.DataLength; + blockIndex = item.ExtentLocation; + } + else + { + int bootIndex = index - _archive.Refs.Size(); + const CBootInitialEntry &be = _archive.BootEntries[bootIndex]; + currentItemSize = _archive.GetBootItemSize(bootIndex); + blockIndex = be.LoadRBA; + } + return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); + COM_TRY_END +} + }} diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h index bb905a22..1dcade8f 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.h +++ b/CPP/7zip/Archive/Iso/IsoHandler.h @@ -1,4 +1,4 @@ -// Iso/Handler.h +// IsoHandler.h #ifndef __ISO_HANDLER_H #define __ISO_HANDLER_H @@ -6,26 +6,23 @@ #include "Common/MyCom.h" #include "../IArchive.h" -#include "IsoItem.h" #include "IsoIn.h" +#include "IsoItem.h" namespace NArchive { namespace NIso { class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CMyComPtr<IInStream> _stream; + CInArchive _archive; public: - MY_UNKNOWN_IMP1( - IInArchive - ) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CMyComPtr<IInStream> _inStream; - CInArchive _archive; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index dee23395..84143348 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -3,9 +3,6 @@ #include "StdAfx.h" #include "IsoIn.h" -#include "IsoHeader.h" - -#include "Windows/Defs.h" #include "../../Common/StreamUtils.h" @@ -35,13 +32,13 @@ void CInArchive::ReadBytes(Byte *data, UInt32 size) data[i] = ReadByte(); } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); } -void CInArchive::SkeepZeros(size_t size) +void CInArchive::SkipZeros(size_t size) { while (size-- != 0) { @@ -174,8 +171,8 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) ReadBytes((Byte *)r.FileId, idLen); int padSize = 1 - (idLen & 1); - // SkeepZeros(1 - (idLen & 1)); - Skeep(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros + // SkipZeros(1 - (idLen & 1)); + Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros int curPos = 33 + idLen + padSize; if (curPos > len) @@ -199,7 +196,7 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) d.VolFlags = ReadByte(); ReadBytes(d.SystemId, sizeof(d.SystemId)); ReadBytes(d.VolumeId, sizeof(d.VolumeId)); - SkeepZeros(8); + SkipZeros(8); d.VolumeSpaceSize = ReadUInt32(); ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence)); d.VolumeSetSize = ReadUInt16(); @@ -223,9 +220,9 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) ReadDateTime(d.ExpirationTime); ReadDateTime(d.EffectiveTime); d.FileStructureVersion = ReadByte(); // = 1 - SkeepZeros(1); + SkipZeros(1); ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse)); - SkeepZeros(653); + SkipZeros(653); } static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; @@ -371,7 +368,7 @@ HRESULT CInArchive::Open2() } else break; - SkeepZeros(0x800 - 7); + SkipZeros(0x800 - 7); continue; */ } @@ -382,7 +379,7 @@ HRESULT CInArchive::Open2() if (sig[0] == NVolDescType::kTerminator) { break; - // Skeep(0x800 - 7); + // Skip(0x800 - 7); // continue; } switch(sig[0]) diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index ce53a1e3..49687e27 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -3,13 +3,13 @@ #ifndef __ARCHIVE_ISO_IN_H #define __ARCHIVE_ISO_IN_H -#include "Common/MyCom.h" #include "Common/IntToString.h" +#include "Common/MyCom.h" #include "../../IStream.h" -#include "IsoItem.h" #include "IsoHeader.h" +#include "IsoItem.h" namespace NArchive { namespace NIso { @@ -159,8 +159,8 @@ struct CBootInitialEntry s += L"_"; if (BootMediaType >= kNumBootMediaTypes) { - wchar_t name[32]; - ConvertUInt64ToString(BootMediaType, name); + wchar_t name[16]; + ConvertUInt32ToString(BootMediaType, name); s += name; } else @@ -232,8 +232,8 @@ class CInArchive bool _bootIsDefined; CBootRecordDescriptor _bootDesc; - void Skeep(size_t size); - void SkeepZeros(size_t size); + void Skip(size_t size); + void SkipZeros(size_t size); Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); UInt16 ReadUInt16Spec(); diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.cpp b/CPP/7zip/Archive/Lzh/LzhCRC.cpp deleted file mode 100755 index e299bf6c..00000000 --- a/CPP/7zip/Archive/Lzh/LzhCRC.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// LzhCRC.cpp - -#include "StdAfx.h" - -#include "LzhCRC.h" - -namespace NArchive { -namespace NLzh { - -static const UInt16 kCRCPoly = 0xA001; - -UInt16 CCRC::Table[256]; - -void CCRC::InitTable() -{ - for (UInt32 i = 0; i < 256; i++) - { - UInt32 r = i; - for (int j = 0; j < 8; j++) - if (r & 1) - r = (r >> 1) ^ kCRCPoly; - else - r >>= 1; - CCRC::Table[i] = (UInt16)r; - } -} - -class CCRCTableInit -{ -public: - CCRCTableInit() { CCRC::InitTable(); } -} g_CRCTableInit; - -void CCRC::Update(const void *data, size_t size) -{ - UInt16 v = _value; - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); - _value = v; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.h b/CPP/7zip/Archive/Lzh/LzhCRC.h deleted file mode 100755 index be2a4569..00000000 --- a/CPP/7zip/Archive/Lzh/LzhCRC.h +++ /dev/null @@ -1,27 +0,0 @@ -// LzhCRC.h - -#ifndef __LZH_CRC_H -#define __LZH_CRC_H - -#include <stddef.h> -#include "Common/Types.h" - -namespace NArchive { -namespace NLzh { - -class CCRC -{ - UInt16 _value; -public: - static UInt16 Table[256]; - static void InitTable(); - - CCRC(): _value(0){}; - void Init() { _value = 0; } - void Update(const void *data, size_t size); - UInt16 GetDigest() const { return _value; } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.cpp b/CPP/7zip/Archive/Lzh/LzhHandler.cpp deleted file mode 100755 index 66153f7a..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHandler.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// LzhHandler.cpp - -#include "StdAfx.h" - -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "LzhHandler.h" -#include "LzhOutStreamWithCRC.h" - -#include "../../ICoder.h" - -#include "../../Common/LimitedStreams.h" -#include "../../Common/ProgressUtils.h" - -#include "../../Compress/CopyCoder.h" -#include "../../Compress/LzhDecoder.h" - -#include "../Common/ItemNameUtils.h" - -using namespace NWindows; -using namespace NTime; - -namespace NArchive { -namespace NLzh{ - -struct COsPair -{ - Byte Id; - const wchar_t *Name; -}; - -COsPair g_OsPairs[] = -{ - { 'M', L"MS-DOS" }, - { '2', L"OS/2" }, - { '9', L"OS9" }, - { 'K', L"OS/68K" }, - { '3', L"OS/386" }, - { 'H', L"HUMAN" }, - { 'U', L"UNIX" }, - { 'C', L"CP/M" }, - { 'F', L"FLEX" }, - { 'm', L"Mac" }, - { 'R', L"Runser" }, - { 'T', L"TownsOS" }, - { 'X', L"XOSK" }, - { 'w', L"Windows95" }, - { 'W', L"WindowsNT" }, - { 0, L"MS-DOS" }, - { 'J', L"Java VM" } -}; - -const wchar_t *kUnknownOS = L"Unknown"; - -const int kNumHostOSes = sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); - -static const wchar_t *GetOS(Byte osId) -{ - for (int i = 0; i < kNumHostOSes; i++) - if (g_OsPairs[i].Id == osId) - return g_OsPairs[i].Name; - return kUnknownOS; -}; - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME}, - { NULL, kpidAttrib, VT_UI4}, - - // { NULL, kpidCommented, VT_BOOL}, - - { NULL, kpidCRC, VT_UI4}, - - { NULL, kpidMethod, VT_UI1}, - { NULL, kpidHostOS, VT_BSTR} - -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -CHandler::CHandler() {} - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = _items.Size(); - return S_OK; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; - switch(propID) - { - case kpidPath: - { - UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); - if (!s.IsEmpty()) - { - if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) - s.Delete(s.Length() - 1); - prop = s; - } - break; - } - case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; - case kpidPackSize: prop = item.PackSize; break; - case kpidCRC: prop = (UInt32)item.CRC; break; - case kpidHostOS: prop = GetOS(item.OsId); break; - case kpidMTime: - { - FILETIME utcFileTime; - UInt32 unixTime; - if (item.GetUnixTime(unixTime)) - NTime::UnixTimeToFileTime(unixTime, utcFileTime); - else - { - FILETIME localFileTime; - if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) - { - if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; - } - else - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; - } - prop = utcFileTime; - break; - } - /* - case kpidAttrib: prop = (UInt32)item.Attributes; break; - case kpidCommented: prop = item.IsCommented(); break; - */ - case kpidMethod: - { - wchar_t method2[kMethodIdSize + 1]; - method2[kMethodIdSize] = 0; - for (int i = 0; i < kMethodIdSize; i++) - method2[i] = item.Method[i]; - prop = method2; - break; - } - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -/* -class CProgressImp: public CProgressVirt -{ -public: - CMyComPtr<IArchiveOpenCallback> Callback; - STDMETHOD(SetCompleted)(const UInt64 *numFiles); -}; - -STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) -{ - if (Callback) - return Callback->SetCompleted(numFiles, NULL); - return S_OK; -} -*/ - -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) -{ - COM_TRY_BEGIN - try - { - _items.Clear(); - CInArchive archive; - - UInt64 endPos = 0; - bool needSetTotal = true; - - if (callback != NULL) - { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - } - - RINOK(archive.Open(stream)); - for (;;) - { - CItemEx item; - bool filled; - HRESULT result = archive.GetNextItem(filled, item); - if (result == S_FALSE) - return S_FALSE; - if (result != S_OK) - return S_FALSE; - if (!filled) - break; - _items.Add(item); - archive.Skeep(item.PackSize); - if (callback != NULL) - { - if (needSetTotal) - { - RINOK(callback->SetTotal(NULL, &endPos)); - needSetTotal = false; - } - if (_items.Size() % 100 == 0) - { - UInt64 numFiles = _items.Size(); - UInt64 numBytes = item.DataPosition; - RINOK(callback->SetCompleted(&numFiles, &numBytes)); - } - } - } - if (_items.IsEmpty()) - return S_FALSE; - - _stream = stream; - } - catch(...) - { - return S_FALSE; - } - COM_TRY_END - return S_OK; -} - -STDMETHODIMP CHandler::Close() -{ - _items.Clear(); - _stream.Release(); - return S_OK; -} - - - -////////////////////////////////////// -// CHandler::DecompressItems - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 testModeSpec, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool testMode = (testModeSpec != 0); - UInt64 totalUnPacked = 0, totalPacked = 0; - bool allFilesMode = (numItems == UInt32(-1)); - if (allFilesMode) - numItems = _items.Size(); - if(numItems == 0) - return S_OK; - UInt32 i; - for(i = 0; i < numItems; i++) - { - const CItemEx &item = _items[allFilesMode ? i : indices[i]]; - totalUnPacked += item.Size; - totalPacked += item.PackSize; - } - extractCallback->SetTotal(totalUnPacked); - - UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; - UInt64 currentItemUnPacked, currentItemPacked; - - NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; - CMyComPtr<ICompressCoder> lzhDecoder; - CMyComPtr<ICompressCoder> lzh1Decoder; - CMyComPtr<ICompressCoder> arj2Decoder; - - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, false); - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_stream); - - for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, - currentTotalPacked += currentItemPacked) - { - currentItemUnPacked = 0; - currentItemPacked = 0; - - lps->InSize = currentTotalPacked; - lps->OutSize = currentTotalUnPacked; - RINOK(lps->SetCur()); - - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - if (item.IsDir()) - { - // if (!testMode) - { - RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); - } - continue; - } - - if (!testMode && (!realOutStream)) - continue; - - RINOK(extractCallback->PrepareOperation(askMode)); - currentItemUnPacked = item.Size; - currentItemPacked = item.PackSize; - - { - COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->Init(realOutStream); - realOutStream.Release(); - - UInt64 pos; - _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); - - streamSpec->Init(item.PackSize); - - HRESULT result = S_OK; - Int32 opRes = NExtract::NOperationResult::kOK; - - if (item.IsCopyMethod()) - { - result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); - if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) - result = S_FALSE; - } - else if (item.IsLh4GroupMethod()) - { - if (!lzhDecoder) - { - lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; - lzhDecoder = lzhDecoderSpec; - } - lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); - result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); - } - /* - else if (item.IsLh1GroupMethod()) - { - if (!lzh1Decoder) - { - lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; - lzh1Decoder = lzh1DecoderSpec; - } - lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); - result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); - } - */ - else - opRes = NExtract::NOperationResult::kUnSupportedMethod; - - if (opRes == NExtract::NOperationResult::kOK) - { - if (result == S_FALSE) - opRes = NExtract::NOperationResult::kDataError; - else - { - RINOK(result); - if (outStreamSpec->GetCRC() != item.CRC) - opRes = NExtract::NOperationResult::kCRCError; - } - } - outStream.Release(); - RINOK(extractCallback->SetOperationResult(opRes)); - } - } - return S_OK; - COM_TRY_END -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.h b/CPP/7zip/Archive/Lzh/LzhHandler.h deleted file mode 100755 index ed504dd2..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHandler.h +++ /dev/null @@ -1,30 +0,0 @@ -// LzhHandler.h - -#ifndef __LZH_HANDLER_H -#define __LZH_HANDLER_H - -#include "Common/MyCom.h" -#include "../IArchive.h" -#include "LzhIn.h" - -namespace NArchive { -namespace NLzh { - -class CHandler: - public IInArchive, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP1(IInArchive) - - INTERFACE_IInArchive(;) - - CHandler(); -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _stream; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhHeader.h b/CPP/7zip/Archive/Lzh/LzhHeader.h deleted file mode 100755 index 845b9a21..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHeader.h +++ /dev/null @@ -1,19 +0,0 @@ -// Archive/Lzh/Header.h - -#ifndef __ARCHIVE_LZH_HEADER_H -#define __ARCHIVE_LZH_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NLzh { - -const int kMethodIdSize = 5; - -const Byte kExtIdFileName = 0x01; -const Byte kExtIdDirName = 0x02; -const Byte kExtIdUnixTime = 0x54; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhIn.cpp b/CPP/7zip/Archive/Lzh/LzhIn.cpp deleted file mode 100755 index 6783654c..00000000 --- a/CPP/7zip/Archive/Lzh/LzhIn.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Archive/LzhIn.cpp - -#include "StdAfx.h" - -#include "Common/StringConvert.h" -#include "Common/Buffer.h" - -#include "../../Common/StreamUtils.h" - -#include "LzhIn.h" - -namespace NArchive { -namespace NLzh { - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) -{ - UInt32 processedSize; - RINOK(ReadBytes(data, size, processedSize)); - return (processedSize == size) ? S_OK: S_FALSE; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - -static const Byte *ReadUInt32(const Byte *p, UInt32 &v) -{ - v = 0; - for (int i = 0; i < 4; i++) - v |= ((UInt32)(*p++) << (i * 8)); - return p; -} - -static const Byte *ReadUInt16(const Byte *p, UInt16 &v) -{ - v = 0; - for (int i = 0; i < 2; i++) - v |= ((UInt16)(*p++) << (i * 8)); - return p; -} - -static const Byte *ReadString(const Byte *p, size_t size, AString &s) -{ - s.Empty(); - for (size_t i = 0; i < size; i++) - { - char c = p[i]; - if (c == 0) - break; - s += c; - } - return p + size; -} - -static Byte CalcSum(const Byte *data, size_t size) -{ - Byte sum = 0; - for (size_t i = 0; i < size; i++) - sum = (Byte)(sum + data[i]); - return sum; -} - -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) -{ - filled = false; - - UInt32 processedSize; - Byte startHeader[2]; - RINOK(ReadBytes(startHeader, 2, processedSize)) - if (processedSize == 0) - return S_OK; - if (processedSize == 1) - return (startHeader[0] == 0) ? S_OK: S_FALSE; - if (startHeader[0] == 0 && startHeader[1] == 0) - return S_OK; - - Byte header[256]; - const UInt32 kBasicPartSize = 22; - RINOK(ReadBytes(header, kBasicPartSize, processedSize)); - if (processedSize != kBasicPartSize) - return (startHeader[0] == 0) ? S_OK: S_FALSE; - - const Byte *p = header; - memmove(item.Method, p, kMethodIdSize); - if (!item.IsValidMethod()) - return S_OK; - p += kMethodIdSize; - p = ReadUInt32(p, item.PackSize); - p = ReadUInt32(p, item.Size); - p = ReadUInt32(p, item.ModifiedTime); - item.Attributes = *p++; - item.Level = *p++; - if (item.Level > 2) - return S_FALSE; - UInt32 headerSize; - if (item.Level < 2) - { - headerSize = startHeader[0]; - if (headerSize < kBasicPartSize) - return S_FALSE; - UInt32 remain = headerSize - kBasicPartSize; - RINOK(CheckReadBytes(header + kBasicPartSize, remain)); - if (startHeader[1] != CalcSum(header, headerSize)) - return S_FALSE; - size_t nameLength = *p++; - if ((p - header) + nameLength + 2 > headerSize) - return S_FALSE; - p = ReadString(p, nameLength, item.Name); - } - else - headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); - p = ReadUInt16(p, item.CRC); - if (item.Level != 0) - { - if (item.Level == 2) - { - RINOK(CheckReadBytes(header + kBasicPartSize, 2)); - } - if ((size_t)(p - header) + 3 > headerSize) - return S_FALSE; - item.OsId = *p++; - UInt16 nextSize; - p = ReadUInt16(p, nextSize); - while (nextSize != 0) - { - if (nextSize < 3) - return S_FALSE; - if (item.Level == 1) - { - if (item.PackSize < nextSize) - return S_FALSE; - item.PackSize -= nextSize; - } - CExtension ext; - RINOK(CheckReadBytes(&ext.Type, 1)) - nextSize -= 3; - ext.Data.SetCapacity(nextSize); - RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) - item.Extensions.Add(ext); - Byte hdr2[2]; - RINOK(CheckReadBytes(hdr2, 2)); - ReadUInt16(hdr2, nextSize); - } - } - item.DataPosition = m_Position; - filled = true; - return S_OK; -} - -HRESULT CInArchive::Skeep(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhIn.h b/CPP/7zip/Archive/Lzh/LzhIn.h deleted file mode 100755 index 344a133f..00000000 --- a/CPP/7zip/Archive/Lzh/LzhIn.h +++ /dev/null @@ -1,29 +0,0 @@ -// Archive/LzhIn.h - -#ifndef __ARCHIVE_LZHIN_H -#define __ARCHIVE_LZHIN_H - -#include "Common/MyCom.h" -#include "../../IStream.h" - -#include "LzhItem.h" - -namespace NArchive { -namespace NLzh { - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); - HRESULT CheckReadBytes(void *data, UInt32 size); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhItem.h b/CPP/7zip/Archive/Lzh/LzhItem.h deleted file mode 100755 index 494a65bf..00000000 --- a/CPP/7zip/Archive/Lzh/LzhItem.h +++ /dev/null @@ -1,172 +0,0 @@ -// Archive/LzhItem.h - -#ifndef __ARCHIVE_LZH_ITEM_H -#define __ARCHIVE_LZH_ITEM_H - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "Common/Buffer.h" -#include "LzhHeader.h" - -namespace NArchive { -namespace NLzh { - -struct CExtension -{ - Byte Type; - CByteBuffer Data; - AString GetString() const - { - AString s; - for (size_t i = 0; i < Data.GetCapacity(); i++) - { - char c = (char)Data[i]; - if (c == 0) - break; - s += c; - } - return s; - } -}; - -struct CItem -{ -public: - AString Name; - Byte Method[kMethodIdSize]; - UInt32 PackSize; - UInt32 Size; - UInt32 ModifiedTime; - Byte Attributes; - Byte Level; - UInt16 CRC; - Byte OsId; - CObjectVector<CExtension> Extensions; - - bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); } - bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); } - bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); } - - bool IsCopyMethod() const - { - return (IsLhMethod() && Method[3] == '0') || - (IsValidMethod() && Method[2] == 'z' && Method[3] == '4'); - } - - bool IsLh1GroupMethod() const - { - if (!IsLhMethod()) - return false; - switch(Method[3]) - { - case '1': - return true; - } - return false; - } - - bool IsLh4GroupMethod() const - { - if (!IsLhMethod()) - return false; - switch(Method[3]) - { - case '4': - case '5': - case '6': - case '7': - return true; - } - return false; - } - - int GetNumDictBits() const - { - if (!IsLhMethod()) - return 0; - switch(Method[3]) - { - case '1': - return 12; - case '2': - return 13; - case '3': - return 13; - case '4': - return 12; - case '5': - return 13; - case '6': - return 15; - case '7': - return 16; - } - return 0; - } - - int FindExt(Byte type) const - { - for (int i = 0; i < Extensions.Size(); i++) - if (Extensions[i].Type == type) - return i; - return -1; - } - bool GetUnixTime(UInt32 &value) const - { - int index = FindExt(kExtIdUnixTime); - if (index < 0) - { - if (Level == 2) - { - value = ModifiedTime; - return true; - } - return false; - } - const Byte *data = (const Byte *)(Extensions[index].Data); - value = data[0] | - ((UInt32)data[1] << 8) | - ((UInt32)data[2] << 16) | - ((UInt32)data[3] << 24); - return true; - } - - AString GetDirName() const - { - int index = FindExt(kExtIdDirName); - if (index < 0) - return AString(); - return Extensions[index].GetString(); - } - - AString GetFileName() const - { - int index = FindExt(kExtIdFileName); - if (index < 0) - return Name; - return Extensions[index].GetString(); - } - - AString GetName() const - { - AString dirName = GetDirName(); - dirName.Replace((char)(unsigned char)0xFF, '\\'); - if (!dirName.IsEmpty()) - { - char c = dirName[dirName.Length() - 1]; - if (c != '\\') - dirName += '\\'; - } - return dirName + GetFileName(); - } -}; - -class CItemEx: public CItem -{ -public: - UInt64 DataPosition; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp deleted file mode 100755 index 2281a884..00000000 --- a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// LzhOutStreamWithCRC.cpp - -#include "StdAfx.h" - -#include "LzhOutStreamWithCRC.h" - -namespace NArchive { -namespace NLzh { - -STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h deleted file mode 100755 index fd73f4ae..00000000 --- a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h +++ /dev/null @@ -1,38 +0,0 @@ -// LzhOutStreamWithCRC.h - -#ifndef __LZHOUTSTREAMWITHCRC_H -#define __LZHOUTSTREAMWITHCRC_H - -#include "LzhCRC.h" -#include "../../../Common/MyCom.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NLzh { - -class COutStreamWithCRC: - public ISequentialOutStream, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -private: - CCRC _crc; - CMyComPtr<ISequentialOutStream> _stream; -public: - void Init(ISequentialOutStream *stream) - { - _stream = stream; - _crc.Init(); - } - void ReleaseStream() { _stream.Release(); } - UInt32 GetCRC() const { return _crc.GetDigest(); } - void InitCRC() { _crc.Init(); } - -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhRegister.cpp b/CPP/7zip/Archive/Lzh/LzhRegister.cpp deleted file mode 100755 index b9b1d473..00000000 --- a/CPP/7zip/Archive/Lzh/LzhRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// LzhRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "LzhHandler.h" -static IInArchive *CreateArc() { return new NArchive::NLzh::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; - -REGISTER_ARC(Lzh) diff --git a/CPP/7zip/Archive/Lzh/StdAfx.h b/CPP/7zip/Archive/Lzh/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Lzh/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp new file mode 100755 index 00000000..19a9516a --- /dev/null +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -0,0 +1,783 @@ +// LzhHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../ICoder.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/LzhDecoder.h" + +#include "IArchive.h" + +#include "Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NLzh{ + +const int kMethodIdSize = 5; + +const Byte kExtIdFileName = 0x01; +const Byte kExtIdDirName = 0x02; +const Byte kExtIdUnixTime = 0x54; + +struct CExtension +{ + Byte Type; + CByteBuffer Data; + AString GetString() const + { + AString s; + for (size_t i = 0; i < Data.GetCapacity(); i++) + { + char c = (char)Data[i]; + if (c == 0) + break; + s += c; + } + return s; + } +}; + +struct CItem +{ + AString Name; + Byte Method[kMethodIdSize]; + Byte Attributes; + Byte Level; + Byte OsId; + UInt32 PackSize; + UInt32 Size; + UInt32 ModifiedTime; + UInt16 CRC; + CObjectVector<CExtension> Extensions; + + bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); } + bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); } + bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); } + + bool IsCopyMethod() const + { + return (IsLhMethod() && Method[3] == '0') || + (IsValidMethod() && Method[2] == 'z' && Method[3] == '4'); + } + + bool IsLh1GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '1': + return true; + } + return false; + } + + bool IsLh4GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '4': + case '5': + case '6': + case '7': + return true; + } + return false; + } + + int GetNumDictBits() const + { + if (!IsLhMethod()) + return 0; + switch(Method[3]) + { + case '1': return 12; + case '2': return 13; + case '3': return 13; + case '4': return 12; + case '5': return 13; + case '6': return 15; + case '7': return 16; + } + return 0; + } + + int FindExt(Byte type) const + { + for (int i = 0; i < Extensions.Size(); i++) + if (Extensions[i].Type == type) + return i; + return -1; + } + bool GetUnixTime(UInt32 &value) const + { + int index = FindExt(kExtIdUnixTime); + if (index < 0) + { + if (Level == 2) + { + value = ModifiedTime; + return true; + } + return false; + } + const Byte *data = (const Byte *)(Extensions[index].Data); + value = GetUi32(data); + return true; + } + + AString GetDirName() const + { + int index = FindExt(kExtIdDirName); + if (index < 0) + return AString(); + return Extensions[index].GetString(); + } + + AString GetFileName() const + { + int index = FindExt(kExtIdFileName); + if (index < 0) + return Name; + return Extensions[index].GetString(); + } + + AString GetName() const + { + AString dirName = GetDirName(); + dirName.Replace((char)(unsigned char)0xFF, '\\'); + if (!dirName.IsEmpty()) + { + char c = dirName[dirName.Length() - 1]; + if (c != '\\') + dirName += '\\'; + } + return dirName + GetFileName(); + } +}; + +struct CItemEx: public CItem +{ + UInt64 DataPosition; +}; + +class CInArchive +{ + CMyComPtr<IInStream> m_Stream; + UInt64 m_Position; + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); + HRESULT CheckReadBytes(void *data, UInt32 size); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) +{ + UInt32 processedSize; + RINOK(ReadBytes(data, size, processedSize)); + return (processedSize == size) ? S_OK: S_FALSE; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +static const Byte *ReadUInt16(const Byte *p, UInt16 &v) +{ + v = Get16(p); + return p + 2; +} + +static const Byte *ReadString(const Byte *p, size_t size, AString &s) +{ + s.Empty(); + for (size_t i = 0; i < size; i++) + { + char c = p[i]; + if (c == 0) + break; + s += c; + } + return p + size; +} + +static Byte CalcSum(const Byte *data, size_t size) +{ + Byte sum = 0; + for (size_t i = 0; i < size; i++) + sum = (Byte)(sum + data[i]); + return sum; +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + Byte startHeader[2]; + RINOK(ReadBytes(startHeader, 2, processedSize)) + if (processedSize == 0) + return S_OK; + if (processedSize == 1) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + if (startHeader[0] == 0 && startHeader[1] == 0) + return S_OK; + + Byte header[256]; + const UInt32 kBasicPartSize = 22; + RINOK(ReadBytes(header, kBasicPartSize, processedSize)); + if (processedSize != kBasicPartSize) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + + const Byte *p = header; + memmove(item.Method, p, kMethodIdSize); + if (!item.IsValidMethod()) + return S_OK; + p += kMethodIdSize; + item.PackSize = Get32(p); + item.Size = Get32(p + 4); + item.ModifiedTime = Get32(p + 8); + item.Attributes = p[12]; + item.Level = p[13]; + p += 14; + if (item.Level > 2) + return S_FALSE; + UInt32 headerSize; + if (item.Level < 2) + { + headerSize = startHeader[0]; + if (headerSize < kBasicPartSize) + return S_FALSE; + UInt32 remain = headerSize - kBasicPartSize; + RINOK(CheckReadBytes(header + kBasicPartSize, remain)); + if (startHeader[1] != CalcSum(header, headerSize)) + return S_FALSE; + size_t nameLength = *p++; + if ((p - header) + nameLength + 2 > headerSize) + return S_FALSE; + p = ReadString(p, nameLength, item.Name); + } + else + headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); + p = ReadUInt16(p, item.CRC); + if (item.Level != 0) + { + if (item.Level == 2) + { + RINOK(CheckReadBytes(header + kBasicPartSize, 2)); + } + if ((size_t)(p - header) + 3 > headerSize) + return S_FALSE; + item.OsId = *p++; + UInt16 nextSize; + p = ReadUInt16(p, nextSize); + while (nextSize != 0) + { + if (nextSize < 3) + return S_FALSE; + if (item.Level == 1) + { + if (item.PackSize < nextSize) + return S_FALSE; + item.PackSize -= nextSize; + } + CExtension ext; + RINOK(CheckReadBytes(&ext.Type, 1)) + nextSize -= 3; + ext.Data.SetCapacity(nextSize); + RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) + item.Extensions.Add(ext); + Byte hdr2[2]; + RINOK(CheckReadBytes(hdr2, 2)); + ReadUInt16(hdr2, nextSize); + } + } + item.DataPosition = m_Position; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +struct COsPair +{ + Byte Id; + const char *Name; +}; + +static COsPair g_OsPairs[] = +{ + { 0, "MS-DOS" }, + { 'M', "MS-DOS" }, + { '2', "OS/2" }, + { '9', "OS9" }, + { 'K', "OS/68K" }, + { '3', "OS/386" }, + { 'H', "HUMAN" }, + { 'U', "UNIX" }, + { 'C', "CP/M" }, + { 'F', "FLEX" }, + { 'm', "Mac" }, + { 'R', "Runser" }, + { 'T', "TownsOS" }, + { 'X', "XOSK" }, + { 'w', "Windows 95" }, + { 'W', "Windows NT" }, + { 'J', "Java VM" } +}; + +static const char *kUnknownOS = "Unknown"; + +static const char *GetOS(Byte osId) +{ + for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++) + if (g_OsPairs[i].Id == osId) + return g_OsPairs[i].Name; + return kUnknownOS; +}; + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + // { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR} +}; + +class CCRC +{ + UInt16 _value; +public: + static UInt16 Table[256]; + static void InitTable(); + + CCRC(): _value(0){}; + void Init() { _value = 0; } + void Update(const void *data, size_t size); + UInt16 GetDigest() const { return _value; } +}; + +static const UInt16 kCRCPoly = 0xA001; + +UInt16 CCRC::Table[256]; + +void CCRC::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = (UInt16)r; + } +} + +class CCRCTableInit +{ +public: + CCRCTableInit() { CCRC::InitTable(); } +} g_CRCTableInit; + +void CCRC::Update(const void *data, size_t size) +{ + UInt16 v = _value; + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); + _value = v; +} + + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + CCRC _crc; + CMyComPtr<ISequentialOutStream> _stream; +public: + void Init(ISequentialOutStream *stream) + { + _stream = stream; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return _crc.GetDigest(); } + void InitCRC() { _crc.Init(); } + +}; + +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result; + if(!_stream) + { + realProcessedSize = size; + result = S_OK; + } + else + result = _stream->Write(data, size, &realProcessedSize); + _crc.Update(data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) + CHandler(); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +CHandler::CHandler() {} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItemEx &item = _items[index]; + switch(propID) + { + case kpidPath: + { + UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); + if (!s.IsEmpty()) + { + if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) + s.Delete(s.Length() - 1); + prop = s; + } + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidCRC: prop = (UInt32)item.CRC; break; + case kpidHostOS: prop = GetOS(item.OsId); break; + case kpidMTime: + { + FILETIME utc; + UInt32 unixTime; + if (item.GetUnixTime(unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + { + FILETIME localFileTime; + if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + else + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + prop = utc; + break; + } + // case kpidAttrib: prop = (UInt32)item.Attributes; break; + case kpidMethod: + { + char method2[kMethodIdSize + 1]; + method2[kMethodIdSize] = 0; + memcpy(method2, item.Method, kMethodIdSize); + prop = method2; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + _items.Clear(); + CInArchive archive; + + UInt64 endPos = 0; + bool needSetTotal = true; + + if (callback != NULL) + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + RINOK(archive.Open(stream)); + for (;;) + { + CItemEx item; + bool filled; + HRESULT result = archive.GetNextItem(filled, item); + if (result == S_FALSE) + return S_FALSE; + if (result != S_OK) + return S_FALSE; + if (!filled) + break; + _items.Add(item); + archive.Skip(item.PackSize); + if (callback != NULL) + { + if (needSetTotal) + { + RINOK(callback->SetTotal(NULL, &endPos)); + needSetTotal = false; + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = item.DataPosition; + RINOK(callback->SetCompleted(&numFiles, &numBytes)); + } + } + } + if (_items.IsEmpty()) + return S_FALSE; + + _stream = stream; + } + catch(...) + { + return S_FALSE; + } + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + + + +////////////////////////////////////// +// CHandler::DecompressItems + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (testModeSpec != 0); + UInt64 totalUnPacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = _items.Size(); + if(numItems == 0) + return S_OK; + UInt32 i; + for(i = 0; i < numItems; i++) + { + const CItemEx &item = _items[allFilesMode ? i : indices[i]]; + totalUnPacked += item.Size; + totalPacked += item.PackSize; + } + extractCallback->SetTotal(totalUnPacked); + + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; + CMyComPtr<ICompressCoder> lzhDecoder; + CMyComPtr<ICompressCoder> lzh1Decoder; + CMyComPtr<ICompressCoder> arj2Decoder; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + RINOK(lps->SetCur()); + + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode; + askMode = testMode ? NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + continue; + } + + if (!testMode && (!realOutStream)) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + currentItemUnPacked = item.Size; + currentItemPacked = item.PackSize; + + { + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->Init(realOutStream); + realOutStream.Release(); + + UInt64 pos; + _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); + + streamSpec->Init(item.PackSize); + + HRESULT result = S_OK; + Int32 opRes = NExtract::NOperationResult::kOK; + + if (item.IsCopyMethod()) + { + result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) + result = S_FALSE; + } + else if (item.IsLh4GroupMethod()) + { + if (!lzhDecoder) + { + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; + lzhDecoder = lzhDecoderSpec; + } + lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + /* + else if (item.IsLh1GroupMethod()) + { + if (!lzh1Decoder) + { + lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; + lzh1Decoder = lzh1DecoderSpec; + } + lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + */ + else + opRes = NExtract::NOperationResult::kUnSupportedMethod; + + if (opRes == NExtract::NOperationResult::kOK) + { + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else + { + RINOK(result); + if (outStreamSpec->GetCRC() != item.CRC) + opRes = NExtract::NOperationResult::kCRCError; + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Lzh) + +}} diff --git a/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp b/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp deleted file mode 100755 index bbeb177b..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// LzmaArcRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "LzmaHandler.h" - -static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; - -REGISTER_ARC(Lzma) diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp deleted file mode 100755 index 26c1092f..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// LzmaFiltersDecode.cpp - -#include "StdAfx.h" - -#include "LzmaFiltersDecode.h" - -namespace NArchive { -namespace NLzma { - -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; - -HRESULT CDecoder::Code( - DECL_EXTERNAL_CODECS_LOC_VARS - const CHeader &block, - ISequentialInStream *inStream, ISequentialOutStream *outStream, - UInt64 *inProcessedSize, ICompressProgressInfo *progress) -{ - *inProcessedSize = (UInt64)(Int64)-1; - - if (block.FilterMethod > 1) - return E_NOTIMPL; - - if (!_lzmaDecoder) - { - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); - if (_lzmaDecoder == 0) - return E_NOTIMPL; - } - - { - CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; - _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); - if (!setDecoderProperties) - return E_NOTIMPL; - RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); - } - - bool filteredMode = (block.FilterMethod == 1); - - CMyComPtr<ICompressSetOutStream> setOutStream; - - if (filteredMode) - { - if (!_bcjStream) - { - CMyComPtr<ICompressCoder> coder; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); - if (!coder) - return E_NOTIMPL; - coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); - if (!_bcjStream) - return E_NOTIMPL; - } - - _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (!setOutStream) - return E_NOTIMPL; - RINOK(setOutStream->SetOutStream(outStream)); - outStream = _bcjStream; - } - - const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; - RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); - - if (filteredMode) - { - CMyComPtr<IOutStreamFlush> flush; - _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - { - RINOK(flush->Flush()); - } - RINOK(setOutStream->ReleaseOutStream()); - } - - CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; - _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); - if (getInStreamProcessedSize) - { - RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h deleted file mode 100755 index 36de4966..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h +++ /dev/null @@ -1,26 +0,0 @@ -// LzmaFiltersDecode.h - -#ifndef __LZMA_FILTERS_DECODE_H -#define __LZMA_FILTERS_DECODE_H - -#include "../../Common/CreateCoder.h" - -#include "LzmaItem.h" - -namespace NArchive { -namespace NLzma { - -class CDecoder -{ - CMyComPtr<ICompressCoder> _lzmaDecoder; - CMyComPtr<ISequentialOutStream> _bcjStream; -public: - HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS - const CHeader &block, - ISequentialInStream *inStream, ISequentialOutStream *outStream, - UInt64 *inProcessedSize, ICompressProgressInfo *progress); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.cpp b/CPP/7zip/Archive/Lzma/LzmaHandler.cpp deleted file mode 100755 index c434595d..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaHandler.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// LzmaHandler.cpp - -#include "StdAfx.h" - -#include "LzmaHandler.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" - -#include "Windows/PropVariant.h" - -#include "../../Common/ProgressUtils.h" -#include "../../Common/StreamUtils.h" -#include "../Common/DummyOutStream.h" - -#include "LzmaFiltersDecode.h" - -namespace NArchive { -namespace NLzma { - -STATPROPSTG kProps[] = -{ - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_UI1} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = 1; - return S_OK; -} - -static void ConvertUInt32ToString(UInt32 value, wchar_t *s) -{ - ConvertUInt64ToString(value, s + MyStringLen(s)); -} - -static void DictSizeToString(UInt32 value, wchar_t *s) -{ - for (int i = 0; i <= 31; i++) - if ((UInt32(1) << i) == value) - { - ConvertUInt32ToString(i, s); - return; - } - wchar_t c = L'b'; - if ((value & ((1 << 20) - 1)) == 0) - { - value >>= 20; - c = L'm'; - } - else if ((value & ((1 << 10) - 1)) == 0) - { - value >>= 10; - c = L'k'; - } - ConvertUInt32ToString(value, s); - int p = MyStringLen(s); - s[p++] = c; - s[p++] = L'\0'; -} - -static void MyStrCat(wchar_t *d, const wchar_t *s) -{ - MyStringCopy(d + MyStringLen(d), s); -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - if (index != 0) - return E_INVALIDARG; - NWindows::NCOM::CPropVariant propVariant; - switch(propID) - { - case kpidSize: - if (m_StreamInfo.HasUnpackSize()) - propVariant = (UInt64)m_StreamInfo.UnpackSize; - break; - case kpidPackSize: - propVariant = (UInt64)m_PackSize; - break; - case kpidMethod: - { - wchar_t s[64]; - s[0] = '\0'; - if (m_StreamInfo.IsThereFilter) - { - const wchar_t *f; - if (m_StreamInfo.FilterMethod == 0) - f = L"Copy"; - else if (m_StreamInfo.FilterMethod == 1) - f = L"BCJ"; - else - f = L"Unknown"; - MyStrCat(s, f); - MyStrCat(s, L" "); - } - MyStrCat(s, L"LZMA:"); - DictSizeToString(m_StreamInfo.GetDicSize(), s); - propVariant = s; - break; - } - } - propVariant.Detach(value); - return S_OK; -} - -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) -{ - { - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); - - HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); - if (res != S_OK) - return S_FALSE; - - Byte b; - RINOK(ReadStream_FALSE(inStream, &b, 1)); - if (b != 0) - return S_FALSE; - - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); - - m_Stream = inStream; - } - return S_OK; -} - -STDMETHODIMP CHandler::Close() -{ - m_Stream.Release(); - return S_OK; -} - - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 _aTestMode, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); - if (!allFilesMode) - { - if (numItems == 0) - return S_OK; - if (numItems != 1) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } - - bool testMode = (_aTestMode != 0); - - RINOK(extractCallback->SetTotal(m_PackSize)); - - UInt64 currentTotalPacked = 0; - - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - - { - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode = testMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - if(!testMode && !realOutStream) - return S_OK; - extractCallback->PrepareOperation(askMode); - } - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - CDecoder decoder; - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - UInt64 streamPos = m_StreamStartPosition; - Int32 opRes = NArchive::NExtract::NOperationResult::kOK; - bool firstItem = true; - for (;;) - { - CHeader st; - HRESULT result = ReadStreamHeader(m_Stream, st); - if (result != S_OK) - { - if (firstItem) - return E_FAIL; - break; - } - firstItem = false; - - lps->OutSize = outStreamSpec->GetSize(); - lps->InSize = currentTotalPacked; - RINOK(lps->SetCur()); - - streamPos += st.GetHeaderSize(); - UInt64 packProcessed; - - { - result = decoder.Code( - EXTERNAL_CODECS_VARS - st, m_Stream, outStream, &packProcessed, progress); - if (result == E_NOTIMPL) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - if (result == S_FALSE) - { - opRes = NArchive::NExtract::NOperationResult::kDataError; - break; - } - RINOK(result); - } - - if (packProcessed == (UInt64)(Int64)-1) - break; - RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); - currentTotalPacked += packProcessed; - streamPos += packProcessed; - } - outStream.Release(); - return extractCallback->SetOperationResult(opRes); - COM_TRY_END -} - -IMPL_ISetCompressCodecsInfo - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.h b/CPP/7zip/Archive/Lzma/LzmaHandler.h deleted file mode 100755 index e8fdcedc..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaHandler.h +++ /dev/null @@ -1,69 +0,0 @@ -// Lzma/Handler.h - -#ifndef __GZIP_HANDLER_H -#define __GZIP_HANDLER_H - -#include "Common/MyCom.h" - -#include "../IArchive.h" -#include "../../Common/CreateCoder.h" - -#include "LzmaIn.h" - -namespace NArchive { -namespace NLzma { - -// const UInt64 k_LZMA = 0x030101; - -class CHandler: - public IInArchive, - PUBLIC_ISetCompressCodecsInfo - public CMyUnknownImp -{ -public: - MY_QUERYINTERFACE_BEGIN - MY_QUERYINTERFACE_ENTRY(IInArchive) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - - STDMETHOD(Open)(IInStream *inStream, - const UInt64 *maxCheckStartPosition, - IArchiveOpenCallback *openArchiveCallback); - STDMETHOD(Close)(); - - STDMETHOD(GetNumberOfItems)(UInt32 *numItems); - STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); - STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback); - - STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); - - STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); - STDMETHOD(GetPropertyInfo)(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType); - - STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); - STDMETHOD(GetArchivePropertyInfo)(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType); - - UString GetMethodString(); -public: - CHandler() { } - -private: - CHeader m_StreamInfo; - UInt64 m_StreamStartPosition; - UInt64 m_PackSize; - - CMyComPtr<IInStream> m_Stream; - - DECL_EXTERNAL_CODECS_VARS - - DECL_ISetCompressCodecsInfo - -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.cpp b/CPP/7zip/Archive/Lzma/LzmaIn.cpp deleted file mode 100755 index 342b01e1..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaIn.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Archive/LzmaIn.cpp - -#include "StdAfx.h" - -#include "LzmaIn.h" - -#include "../../Common/StreamUtils.h" - -namespace NArchive { -namespace NLzma { - -static bool CheckDictSize(const Byte *p) -{ - UInt32 dicSize = GetUi32(p); - int i; - for (i = 1; i <= 30; i++) - if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) - return true; - return false; -} - -HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) -{ - Byte sig[5 + 9]; - RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); - - const Byte kMaxProp0Val = 5 * 5 * 9 - 1; - if (sig[0] > kMaxProp0Val) - return S_FALSE; - - for (int i = 0; i < 5; i++) - block.LzmaProps[i] = sig[i]; - - block.IsThereFilter = false; - block.FilterMethod = 0; - - if (!CheckDictSize(sig + 1)) - { - if (sig[0] > 1 || sig[1] > kMaxProp0Val) - return S_FALSE; - block.IsThereFilter = true; - block.FilterMethod = sig[0]; - for (int i = 0; i < 5; i++) - block.LzmaProps[i] = sig[i + 1]; - if (!CheckDictSize(block.LzmaProps + 1)) - return S_FALSE; - RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); - } - UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); - block.UnpackSize = GetUi64(sig + unpOffset); - if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) - return S_FALSE; - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.h b/CPP/7zip/Archive/Lzma/LzmaIn.h deleted file mode 100755 index 6f237f2d..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaIn.h +++ /dev/null @@ -1,16 +0,0 @@ -// Archive/LzmaIn.h - -#ifndef __ARCHIVE_LZMA_IN_H -#define __ARCHIVE_LZMA_IN_H - -#include "LzmaItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NLzma { - -HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaItem.h b/CPP/7zip/Archive/Lzma/LzmaItem.h deleted file mode 100755 index 8fcae210..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaItem.h +++ /dev/null @@ -1,27 +0,0 @@ -// Archive/LzmaItem.h - -#ifndef __ARCHIVE_LZMA_ITEM_H -#define __ARCHIVE_LZMA_ITEM_H - -#include "Common/Types.h" - -#include "../../../../C/CpuArch.h" - -namespace NArchive { -namespace NLzma { - -struct CHeader -{ - UInt64 UnpackSize; - bool IsThereFilter; - Byte FilterMethod; - Byte LzmaProps[5]; - - UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } - bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } - unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/StdAfx.h b/CPP/7zip/Archive/Lzma/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Lzma/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp new file mode 100755 index 00000000..5dd0aac7 --- /dev/null +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -0,0 +1,436 @@ +// LzmaHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/CreateCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/LzmaDecoder.h" + +#include "Common/DummyOutStream.h" + +using namespace NWindows; + +namespace NArchive { +namespace NLzma { + +static bool CheckDicSize(const Byte *p) +{ + UInt32 dicSize = GetUi32(p); + for (int i = 1; i <= 30; i++) + if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) + return true; + return (dicSize == 0xFFFFFFFF); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +struct CHeader +{ + UInt64 Size; + Byte FilterID; + Byte LzmaProps[5]; + + UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } + bool HasSize() const { return (Size != (UInt64)(Int64)-1); } + bool Parse(const Byte *buf, bool isThereFilter); +}; + +bool CHeader::Parse(const Byte *buf, bool isThereFilter) +{ + FilterID = 0; + if (isThereFilter) + FilterID = buf[0]; + const Byte *sig = buf + (isThereFilter ? 1 : 0); + for (int i = 0; i < 5; i++) + LzmaProps[i] = sig[i]; + Size = GetUi64(sig + 5); + return + LzmaProps[0] < 5 * 5 * 9 && + FilterID < 2 && + (!HasSize() || Size < ((UInt64)1 << 56)) && + CheckDicSize(LzmaProps + 1); +} + +class CDecoder +{ + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + CMyComPtr<ICompressCoder> _lzmaDecoder; + CMyComPtr<ISequentialOutStream> _bcjStream; +public: + ~CDecoder(); + HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS + bool filtered, ISequentialInStream *inStream); + + HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + + UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); } + + void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); } + + HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) + { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } +}; + +static const UInt64 k_BCJ = 0x03030103; + +HRESULT CDecoder::Create( + DECL_EXTERNAL_CODECS_LOC_VARS + bool filteredMode, ISequentialInStream *inStream) +{ + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoder = _lzmaDecoderSpec; + } + + if (filteredMode) + { + if (!_bcjStream) + { + CMyComPtr<ICompressCoder> coder; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); + if (!coder) + return E_NOTIMPL; + coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); + if (!_bcjStream) + return E_NOTIMPL; + } + } + + return _lzmaDecoderSpec->SetInStream(inStream); +} + +CDecoder::~CDecoder() +{ + ReleaseInStream(); +} + +HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, + ICompressProgressInfo *progress) +{ + if (header.FilterID > 1) + return E_NOTIMPL; + + { + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; + _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (!setDecoderProperties) + return E_NOTIMPL; + RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5)); + } + + CMyComPtr<ICompressSetOutStream> setOutStream; + + bool filteredMode = (header.FilterID == 1); + + if (filteredMode) + { + _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + RINOK(setOutStream->SetOutStream(outStream)); + outStream = _bcjStream; + } + + const UInt64 *Size = header.HasSize() ? &header.Size : NULL; + HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); + + if (filteredMode) + { + CMyComPtr<IOutStreamFlush> flush; + _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + { + HRESULT res2 = flush->Flush(); + if (res == S_OK) + res = res2; + } + HRESULT res2 = setOutStream->ReleaseOutStream(); + if (res == S_OK) + res = res2; + } + RINOK(res); + + return S_OK; +} + + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ + CHeader _header; + bool _lzma86; + UInt64 _startPosition; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + + DECL_EXTERNAL_CODECS_VARS + DECL_ISetCompressCodecsInfo + +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + CHandler(bool lzma86) { _lzma86 = lzma86; } + + unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } + +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +static void DictSizeToString(UInt32 value, char *s) +{ + for (int i = 0; i <= 31; i++) + if ((UInt32(1) << i) == value) + { + ::ConvertUInt32ToString(i, s); + return; + } + char c = 'b'; + if ((value & ((1 << 20) - 1)) == 0) + { + value >>= 20; + c = 'm'; + } + else if ((value & ((1 << 10) - 1)) == 0) + { + value >>= 10; + c = 'k'; + } + ::ConvertUInt32ToString(value, s); + int p = MyStringLen(s); + s[p++] = c; + s[p++] = '\0'; +} + +static void MyStrCat(char *d, const char *s) +{ + MyStringCopy(d + MyStringLen(d), s); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: + if (_stream) + { + char s[64]; + s[0] = '\0'; + if (_header.FilterID != 0) + MyStrCat(s, "BCJ "); + MyStrCat(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s + MyStringLen(s)); + prop = s; + } + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + + const UInt32 kBufSize = 1 + 5 + 8 + 1; + Byte buf[kBufSize]; + + RINOK(ReadStream_FALSE(inStream, buf, kBufSize)); + + if (!_header.Parse(buf, _lzma86)) + return S_FALSE; + const Byte *start = buf + GetHeaderSize(); + if (start[0] != 0) + return S_FALSE; + + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + _packSize = endPos - _startPosition; + _packSizeDefined = true; + + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _seqStream.Release(); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (!allFilesMode) + { + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + } + + bool testMode = (_aTestMode != 0); + if (_stream) + extractCallback->SetTotal(_packSize); + + + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CDecoder decoder; + HRESULT result = decoder.Create( + EXTERNAL_CODECS_VARS + _lzma86, _seqStream); + RINOK(result); + + Int32 opRes = NArchive::NExtract::NOperationResult::kOK; + bool firstItem = true; + + for (;;) + { + lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = _packSize = decoder.GetInputProcessedSize(); + _packSizeDefined = true; + RINOK(lps->SetCur()); + + CHeader st; + + const UInt32 kBufSize = 1 + 5 + 8; + Byte buf[kBufSize]; + const UInt32 headerSize = GetHeaderSize(); + UInt32 processed; + RINOK(decoder.ReadInput(buf, headerSize, &processed)); + if (processed != headerSize) + break; + + if (!st.Parse(buf, _lzma86)) + break; + firstItem = false; + + result = decoder.Code(st, outStream, progress); + if (result == E_NOTIMPL) + { + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + break; + } + if (result == S_FALSE) + { + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + RINOK(result); + } + if (firstItem) + return E_FAIL; + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +static IInArchive *CreateArc() { return new CHandler(false); } +static IInArchive *CreateArc86() { return new CHandler(true); } + +namespace NLzmaAr { + +static CArcInfo g_ArcInfo = + { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL }; +REGISTER_ARC(Lzma) + +} + +namespace NLzma86Ar { + +static CArcInfo g_ArcInfo = + { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL }; +REGISTER_ARC(Lzma86) + +} + +}} diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 76f63a21..342a8e76 100755 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -16,8 +16,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } @@ -35,8 +33,8 @@ namespace NMacho { #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) -#define MACH_CMD_SEGMENT_32 1 -#define MACH_CMD_SEGMENT_64 0x19 +#define MACH_CMD_SEGMENT_32 1 +#define MACH_CMD_SEGMENT_64 0x19 #define MACH_SECT_TYPE_MASK 0x000000FF #define MACH_SECT_ATTR_MASK 0xFFFFFF00 @@ -427,22 +425,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - - - - - - - - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -453,24 +439,19 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSection &item = _sections[index]; currentItemSize = item.GetPackSize(); - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? - + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? NArchive::NExtract::NOperationResult::kOK: - NArchive::NExtract::NOperationResult::kDataError)); } return S_OK; @@ -485,4 +466,3 @@ static CArcInfo g_ArcInfo = REGISTER_ARC(Macho) }} -
\ No newline at end of file diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp new file mode 100755 index 00000000..47b18f15 --- /dev/null +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -0,0 +1,508 @@ +// MbrHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include <stdio.h> +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +using namespace NWindows; + +namespace NArchive { +namespace NMbr { + +struct CChs +{ + Byte Head; + Byte SectCyl; + Byte Cyl8; + + UInt32 GetSector() const { return SectCyl & 0x3F; } + UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; } + void ToString(NCOM::CPropVariant &prop) const; + + void Parse(const Byte *p) + { + Head = p[0]; + SectCyl = p[1]; + Cyl8 = p[2]; + } + bool Check() const { return GetSector() > 0; } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareChs(const CChs &c1, const CChs &c2) +{ + RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); + RINOZ(MyCompare(c1.Head, c2.Head)); + return MyCompare(c1.GetSector(), c2.GetSector()); +} + +static void AddUIntToString(UInt32 val, AString &res) +{ + char s[16]; + ConvertUInt32ToString(val, s); + res += s; +} + +void CChs::ToString(NCOM::CPropVariant &prop) const +{ + AString s; + AddUIntToString(GetCyl(), s); + s += '-'; + AddUIntToString(Head, s); + s += '-'; + AddUIntToString(GetSector(), s); + prop = s; +} + +struct CPartition +{ + Byte Status; + CChs BeginChs; + Byte Type; + CChs EndChs; + UInt32 Lba; + UInt32 NumBlocks; + + CPartition() { memset (this, 0, sizeof(*this)); } + + bool IsEmpty() const { return Type == 0; } + bool IsExtended() const { return Type == 5 || Type == 0xF; } + UInt32 GetLimit() const { return Lba + NumBlocks; } + // bool IsActive() const { return Status == 0x80; } + UInt64 GetPos() const { return (UInt64)Lba * 512; } + UInt64 GetSize() const { return (UInt64)NumBlocks * 512; } + + bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; } + bool Parse(const Byte *p) + { + Status = p[0]; + BeginChs.Parse(p + 1); + Type = p[4]; + EndChs.Parse(p + 5); + Lba = GetUi32(p + 8); + NumBlocks = GetUi32(p + 12); + if (Type == 0) + return true; + if (Status != 0 && Status != 0x80) + return false; + return + BeginChs.Check() && + EndChs.Check() && + CompareChs(BeginChs, EndChs) <= 0 && + NumBlocks > 0 && + CheckLbaLimits(); + } + + #ifdef SHOW_DEBUG_INFO + void Print() const + { + NCOM::CPropVariant prop, prop2; + BeginChs.ToString(prop); + EndChs.ToString(prop2); + printf(" %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal); + } + #endif +}; + +struct CPartType +{ + UInt32 Id; + const char *Ext; + const char *Name; +}; + +static const char *kFat = "fat"; + +static const CPartType kPartTypes[] = +{ + { 0x01, kFat, "FAT12" }, + { 0x04, kFat, "FAT16 DOS 3.0+" }, + { 0x05, 0, "Extended" }, + { 0x06, kFat, "FAT16 DOS 3.31+" }, + { 0x07, "ntfs", "NTFS" }, + { 0x0B, kFat, "FAT32" }, + { 0x0C, kFat, "FAT32-LBA" }, + { 0x0E, kFat, "FAT16-LBA" }, + { 0x0F, 0, "Extended-LBA" }, + { 0x11, kFat, "FAT12-Hidden" }, + { 0x14, kFat, "FAT16-Hidden < 32 MB" }, + { 0x16, kFat, "FAT16-Hidden >= 32 MB" }, + { 0x1B, kFat, "FAT32-Hidden" }, + { 0x1C, kFat, "FAT32-LBA-Hidden" }, + { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, + { 0x82, 0, "Solaris x86 / Linux swap" }, + { 0x83, 0, "Linux" }, + { 0xBE, 0, "Solaris 8 boot" }, + { 0xBF, 0, "New Solaris x86" }, + { 0xC2, 0, "Linux-Hidden" }, + { 0xC3, 0, "Linux swap-Hidden" }, + { 0xEE, 0, "EFI-MBR" }, + { 0xEE, 0, "EFI" } +}; + +static int FindPartType(UInt32 type) +{ + for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++) + if (kPartTypes[i].Id == type) + return i; + return -1; +} + +struct CItem +{ + bool IsReal; + bool IsPrim; + UInt64 Size; + CPartition Part; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr<IInStream> _stream; + CObjectVector<CItem> _items; + UInt64 _totalSize; + CByteBuffer _buffer; + + HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level) +{ + if (level >= 128 || _items.Size() >= 128) + return S_FALSE; + + const int kNumHeaderParts = 4; + CPartition parts[kNumHeaderParts]; + + { + const UInt32 kSectorSize = 512; + _buffer.SetCapacity(kSectorSize); + Byte *buf = _buffer; + UInt64 newPos = (UInt64)lba << 9; + if (newPos + 512 > _totalSize) + return S_FALSE; + RINOK(stream->Seek(newPos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + if (!parts[i].Parse(buf + 0x1BE + 16 * i)) + return S_FALSE; + } + + PRF(printf("\n# %8X", lba)); + + UInt32 limLba = lba + 1; + if (limLba == 0) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + { + CPartition &part = parts[i]; + + if (part.IsEmpty()) + continue; + PRF(printf("\n %2d ", (int)level)); + #ifdef SHOW_DEBUG_INFO + part.Print(); + #endif + + int numItems = _items.Size(); + UInt32 newLba = lba + part.Lba; + + if (part.IsExtended()) + { + // if (part.Type == 5) // Check it! + newLba = baseLba + part.Lba; + if (newLba < limLba) + return S_FALSE; + HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1); + if (res != S_FALSE && res != S_OK) + return res; + } + if (newLba < limLba) + return S_FALSE; + part.Lba = newLba; + if (!part.CheckLbaLimits()) + return S_FALSE; + + CItem n; + n.Part = part; + bool addItem = false; + if (numItems == _items.Size()) + { + n.IsPrim = (level == 0); + n.IsReal = true; + addItem = true; + } + else + { + const CItem &back = _items.Back(); + UInt32 backLimit = back.Part.GetLimit(); + UInt32 partLimit = part.GetLimit(); + if (backLimit < partLimit) + { + n.IsReal = false; + n.Part.Lba = backLimit; + n.Part.NumBlocks = partLimit - backLimit; + addItem = true; + } + } + if (addItem) + { + if (n.Part.GetLimit() < limLba) + return S_FALSE; + limLba = n.Part.GetLimit(); + n.Size = n.Part.GetSize(); + _items.Add(n); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_END, &_totalSize)); + RINOK(ReadTables(stream, 0, 0, 0)); + if (_items.IsEmpty()) + return S_FALSE; + UInt32 lbaLimit = _items.Back().Part.GetLimit(); + UInt64 lim = (UInt64)lbaLimit << 9; + if (lim < _totalSize) + { + CItem n; + n.Part.Lba = lbaLimit; + n.Size = _totalSize - lim; + n.IsReal = false; + _items.Add(n); + } + _stream = stream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +enum +{ + kpidPrimary = kpidUserDefined, + kpidBegChs, + kpidEndChs, +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { L"Primary", kpidPrimary, VT_BOOL}, + { L"Begin CHS", kpidBegChs, VT_BSTR}, + { L"End CHS", kpidEndChs, VT_BSTR} +}; + +IMP_IInArchive_Props_WITH_NAME +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: + { + int mainIndex = -1; + for (int i = 0; i < _items.Size(); i++) + if (_items[i].IsReal) + { + if (mainIndex >= 0) + { + mainIndex = -1; + break; + } + mainIndex = i; + } + if (mainIndex >= 0) + prop = (UInt32)mainIndex; + break; + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + + const CItem &item = _items[index]; + const CPartition &part = item.Part; + switch(propID) + { + case kpidPath: + { + AString s; + AddUIntToString(index, s); + if (item.IsReal) + { + int typeIndex = FindPartType(part.Type); + s += '.'; + const char *ext = "img"; + if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0) + ext = kPartTypes[typeIndex].Ext; + s += ext; + } + prop = s; + break; + } + case kpidFileSystem: + if (item.IsReal) + { + char s[32]; + ConvertUInt32ToString(part.Type, s); + const char *res = s; + int typeIndex = FindPartType(part.Type); + if (typeIndex >= 0 && kPartTypes[typeIndex].Name) + res = kPartTypes[typeIndex].Name; + prop = res; + } + break; + case kpidSize: prop = item.Size; break;; + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = part.GetPos(); break; + case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break; + case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break; + case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + const CPartition &part = item.Part; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + totalSize += item.Size; + if (!testMode && (!outStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 }; + +REGISTER_ARC(Mbr) + +}} diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 25c3815e..f099aad2 100755 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -34,22 +34,23 @@ const UInt32 kNumFilesMax = 10; class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { UInt64 _startPos; - CMyComPtr<IInStream> _inStream; + CMyComPtr<IInStream> _stream; UInt32 _numItems; CItem _items[kNumFilesMax + 1]; HRESULT Open2(IInStream *stream); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; STATPROPSTG kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + { NULL, kpidSize, VT_UI8} }; IMP_IInArchive_Props @@ -166,7 +167,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, { if (Open2(inStream) != S_OK) return S_FALSE; - _inStream = inStream; + _stream = inStream; } catch(...) { return S_FALSE; } return S_OK; @@ -175,7 +176,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { - _inStream.Release(); + _stream.Release(); _numItems = 0; return S_OK; } @@ -203,7 +204,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -214,9 +214,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -227,12 +227,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - currentItemSize = item.Size; - - - - - + currentTotalSize += item.Size; if (!testMode && (!realOutStream)) continue; @@ -242,7 +237,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - RINOK(_inStream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(item.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); realOutStream.Release(); @@ -254,6 +249,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new CHandler; } static CArcInfo g_ArcInfo = diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp new file mode 100755 index 00000000..37847a24 --- /dev/null +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -0,0 +1,1725 @@ +// NtfsHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO +// #define SHOW_DEBUG_INFO2 + +#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2) +#include <stdio.h> +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef SHOW_DEBUG_INFO2 +#define PRF2(x) x +#else +#define PRF2(x) +#endif + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +#define G16(p, dest) dest = Get16(p); +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +namespace NArchive { +namespace Ntfs { + +static const UInt32 kNumSysRecs = 16; +static const UInt32 kRecIndex_Volume = 3; +static const UInt32 kRecIndex_BadClus = 8; + +struct CHeader +{ + Byte SectorSizeLog; + Byte ClusterSizeLog; + // Byte MediaType; + UInt32 NumHiddenSectors; + UInt64 NumClusters; + UInt64 MftCluster; + UInt64 SerialNumber; + UInt16 SectorsPerTrack; + UInt16 NumHeads; + + UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + Byte sectorsPerClusterLog; + + if (memcmp(p + 3, "NTFS ", 8) != 0) + return false; + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + sectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog; + } + + for (int i = 14; i < 21; i++) + if (p[i] != 0) + return false; + + // MediaType = p[21]; + if (Get16(p + 22) != 0) // NumFatSectors + return false; + G16(p + 24, SectorsPerTrack); + G16(p + 26, NumHeads); + G32(p + 28, NumHiddenSectors); + if (Get32(p + 32) != 0) // NumSectors32 + return false; + + // DriveNumber = p[0x24]; + if (p[0x25] != 0) // CurrentHead + return false; + if (p[0x26] != 0x80) // ExtendedBootSig + return false; + if (p[0x27] != 0) // reserved + return false; + UInt64 numSectors = Get64(p + 0x28); + NumClusters = numSectors >> sectorsPerClusterLog; + + G64(p + 0x30, MftCluster); + // G64(p + 0x38, Mft2Cluster); + G64(p + 0x48, SerialNumber); + UInt32 numClustersInMftRec; + UInt32 numClustersInIndexBlock; + G32(p + 0x40, numClustersInMftRec); + G32(p + 0x44, numClustersInIndexBlock); + return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256); +} + +struct CMftRef +{ + UInt64 Val; + UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); } + UInt16 GetNumber() const { return (UInt16)(Val >> 48); } + bool IsBaseItself() const { return Val == 0; } +}; + +#define ATNAME(n) ATTR_TYPE_ ## n +#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v + +typedef enum +{ + DEF_ATTR_TYPE(0x00, UNUSED), + DEF_ATTR_TYPE(0x10, STANDARD_INFO), + DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST), + DEF_ATTR_TYPE(0x30, FILE_NAME), + DEF_ATTR_TYPE(0x40, OBJECT_ID), + DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR), + DEF_ATTR_TYPE(0x60, VOLUME_NAME), + DEF_ATTR_TYPE(0x70, VOLUME_INFO), + DEF_ATTR_TYPE(0x80, DATA), + DEF_ATTR_TYPE(0x90, INDEX_ROOT), + DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION), + DEF_ATTR_TYPE(0xB0, BITMAP), + DEF_ATTR_TYPE(0xC0, REPARSE_POINT), + DEF_ATTR_TYPE(0xD0, EA_INFO), + DEF_ATTR_TYPE(0xE0, EA), + DEF_ATTR_TYPE(0xF0, PROPERTY_SET), + DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM), + DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE) +}; + +static const Byte kFileNameType_Posix = 0; +static const Byte kFileNameType_Win32 = 1; +static const Byte kFileNameType_Dos = 2; +static const Byte kFileNameType_Win32Dos = 3; + +struct CFileNameAttr +{ + CMftRef ParentDirRef; + // UInt64 CTime; + // UInt64 MTime; + // UInt64 ThisRecMTime; + // UInt64 ATime; + // UInt64 AllocatedSize; + // UInt64 DataSize; + // UInt16 PackedEaSize; + UString Name; + UInt32 Attrib; + Byte NameType; + + bool IsDos() const { return NameType == kFileNameType_Dos; } + bool Parse(const Byte *p, unsigned size); +}; + +static void GetString(const Byte *p, unsigned length, UString &res) +{ + wchar_t *s = res.GetBuffer(length); + for (unsigned i = 0; i < length; i++) + s[i] = Get16(p + i * 2); + s[length] = 0; + res.ReleaseBuffer(); +} + +bool CFileNameAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x42) + return false; + G64(p + 0x00, ParentDirRef.Val); + // G64(p + 0x08, CTime); + // G64(p + 0x10, MTime); + // G64(p + 0x18, ThisRecMTime); + // G64(p + 0x20, ATime); + // G64(p + 0x28, AllocatedSize); + // G64(p + 0x30, DataSize); + G32(p + 0x38, Attrib); + // G16(p + 0x3C, PackedEaSize); + NameType = p[0x41]; + unsigned length = p[0x40]; + if (0x42 + length > size) + return false; + GetString(p + 0x42, length, Name); + return true; +} + +struct CSiAttr +{ + UInt64 CTime; + UInt64 MTime; + // UInt64 ThisRecMTime; + UInt64 ATime; + UInt32 Attrib; + + /* + UInt32 MaxVersions; + UInt32 Version; + UInt32 ClassId; + UInt32 OwnerId; + UInt32 SecurityId; + UInt64 QuotaCharged; + */ + + bool Parse(const Byte *p, unsigned size); +}; + +bool CSiAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x24) + return false; + G64(p + 0x00, CTime); + G64(p + 0x08, MTime); + // G64(p + 0x10, ThisRecMTime); + G64(p + 0x18, ATime); + G32(p + 0x20, Attrib); + return true; +} + +static const UInt64 kEmptyExtent = (UInt64)(Int64)-1; + +struct CExtent +{ + UInt64 Virt; + UInt64 Phy; + + bool IsEmpty() const { return Phy == kEmptyExtent; } +}; + +struct CVolInfo +{ + Byte MajorVer; + Byte MinorVer; + // UInt16 Flags; + + bool Parse(const Byte *p, unsigned size); +}; + +bool CVolInfo::Parse(const Byte *p, unsigned size) +{ + if (size < 12) + return false; + MajorVer = p[8]; + MinorVer = p[9]; + // Flags = Get16(p + 10); + return true; +} + +struct CAttr +{ + UInt32 Type; + // UInt32 Length; + UString Name; + // UInt16 Flags; + // UInt16 Instance; + CByteBuffer Data; + Byte NonResident; + + // Non-Resident + Byte CompressionUnit; + UInt64 LowVcn; + UInt64 HighVcn; + UInt64 AllocatedSize; + UInt64 Size; + UInt64 PackSize; + UInt64 InitializedSize; + + // Resident + // UInt16 ResidentFlags; + + bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; } + + UInt32 Parse(const Byte *p, unsigned size); + bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const; + UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); } + UInt64 GetPackSize() const + { + if (!NonResident) + return Data.GetCapacity(); + if (CompressionUnit != 0) + return PackSize; + return AllocatedSize; + } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareAttr(void *const *elem1, void *const *elem2, void *) +{ + const CAttr &a1 = *(*((const CAttr **)elem1)); + const CAttr &a2 = *(*((const CAttr **)elem2)); + RINOZ(MyCompare(a1.Type, a2.Type)); + RINOZ(MyCompare(a1.Name, a2.Name)); + return MyCompare(a1.LowVcn, a2.LowVcn); +} + +UInt32 CAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 4) + return 0; + G32(p, Type); + if (Type == 0xFFFFFFFF) + return 4; + if (size < 0x18) + return 0; + PRF(printf(" T=%2X", Type)); + + UInt32 length = Get32(p + 0x04); + PRF(printf(" L=%3d", length)); + if (length > size) + return 0; + NonResident = p[0x08]; + { + int nameLength = p[9]; + UInt32 nameOffset = Get16(p + 0x0A); + if (nameLength != 0) + { + if (nameOffset + nameLength * 2 > length) + return 0; + GetString(p + nameOffset, nameLength, Name); + PRF(printf(" N=%S", Name)); + } + } + + // G16(p + 0x0C, Flags); + // G16(p + 0x0E, Instance); + // PRF(printf(" F=%4X", Flags)); + // PRF(printf(" Inst=%d", Instance)); + + UInt32 dataSize; + UInt32 offs; + if (NonResident) + { + if (length < 0x40) + return 0; + PRF(printf(" NR")); + G64(p + 0x10, LowVcn); + G64(p + 0x18, HighVcn); + G64(p + 0x28, AllocatedSize); + G64(p + 0x30, Size); + G64(p + 0x38, InitializedSize); + G16(p + 0x20, offs); + CompressionUnit = p[0x22]; + + PackSize = Size; + if (CompressionUnit != 0) + { + if (length < 0x48) + return 0; + G64(p + 0x40, PackSize); + PRF(printf(" PS=%I64x", PackSize)); + } + + // PRF(printf("\n")); + PRF(printf(" ASize=%4I64d", AllocatedSize)); + PRF(printf(" Size=%I64d", Size)); + PRF(printf(" IS=%I64d", InitializedSize)); + PRF(printf(" Low=%I64d", LowVcn)); + PRF(printf(" High=%I64d", HighVcn)); + PRF(printf(" CU=%d", (int)CompressionUnit)); + dataSize = length - offs; + } + else + { + if (length < 0x18) + return 0; + PRF(printf(" RES")); + dataSize = Get32(p + 0x10); + PRF(printf(" dataSize=%3d", dataSize)); + offs = Get16(p + 0x14); + // G16(p + 0x16, ResidentFlags); + // PRF(printf(" ResFlags=%4X", ResidentFlags)); + } + if (offs > length || dataSize > length || length - dataSize < offs) + return 0; + Data.SetCapacity(dataSize); + memcpy(Data, p + offs, dataSize); + #ifdef SHOW_DEBUG_INFO + PRF(printf(" : ")); + for (unsigned i = 0; i < Data.GetCapacity(); i++) + { + PRF(printf(" %02X", (int)Data[i])); + } + #endif + return length; +} + +bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const +{ + const Byte *p = Data; + unsigned size = (unsigned)Data.GetCapacity(); + UInt64 vcn = LowVcn; + UInt64 lcn = 0; + UInt64 highVcn1 = HighVcn + 1; + if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63) + return false; + + extents.DeleteBack(); + + PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn)); + + while (size > 0) + { + Byte b = *p++; + size--; + if (b == 0) + break; + UInt32 num = b & 0xF; + if (num == 0 || num > 8 || num > size) + return false; + + int i; + UInt64 vSize = p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + vSize = (vSize << 8) | p[i]; + if (vSize == 0) + return false; + p += num; + size -= num; + if ((highVcn1 - vcn) < vSize) + return false; + + num = (b >> 4) & 0xF; + if (num > 8 || num > size) + return false; + CExtent e; + e.Virt = vcn; + if (num == 0) + { + if (compressionUnit == 0) + return false; + e.Phy = kEmptyExtent; + } + else + { + Int64 v = (signed char)p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + v = (v << 8) | p[i]; + p += num; + size -= num; + lcn += v; + if (lcn > numClustersMax) + return false; + e.Phy = lcn; + } + extents.Add(e); + vcn += vSize; + } + CExtent e; + e.Phy = kEmptyExtent; + e.Virt = vcn; + extents.Add(e); + return (highVcn1 == vcn); +} + +static const UInt64 kEmptyTag = (UInt64)(Int64)-1; + +static const int kNumCacheChunksLog = 1; +static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog); + +class CInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _curRem; + bool _sparseMode; + size_t _compressedPos; + + UInt64 _tags[kNumCacheChunks]; + int _chunkSizeLog; + CByteBuffer _inBuf; + CByteBuffer _outBuf; +public: + CMyComPtr<IInStream> Stream; + UInt64 Size; + UInt64 InitializedSize; + int BlockSizeLog; + int CompressionUnit; + bool InUse; + CRecordVector<CExtent> Extents; + + HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + + UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); } + HRESULT InitAndSeek(int compressionUnit) + { + CompressionUnit = compressionUnit; + if (compressionUnit != 0) + { + UInt32 cuSize = GetCuSize(); + _inBuf.SetCapacity(cuSize); + _chunkSizeLog = BlockSizeLog + CompressionUnit; + _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog); + } + for (int i = 0; i < kNumCacheChunks; i++) + _tags[i] = kEmptyTag; + + _sparseMode = false; + _curRem = 0; + _virtPos = 0; + _physPos = 0; + const CExtent &e = Extents[0]; + if (!e.IsEmpty()) + _physPos = e.Phy << BlockSizeLog; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen) +{ + size_t destSize = 0; + while (destSize < destLen) + { + if (srcLen < 2 || (destSize & 0xFFF) != 0) + break; + UInt32 v = Get16(src); + if (v == 0) + break; + src += 2; + srcLen -= 2; + UInt32 comprSize = (v & 0xFFF) + 1; + if (comprSize > srcLen) + break; + srcLen -= comprSize; + if ((v & 0x8000) == 0) + { + if (comprSize != (1 << 12)) + break; + memcpy(dest + destSize, src, comprSize); + src += comprSize; + destSize += comprSize; + } + else + { + if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) + return 0; + int numDistBits = 4; + UInt32 sbOffset = 0; + UInt32 pos = 0; + + do + { + comprSize--; + for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1) + { + if ((mask & 1) == 0) + { + if (sbOffset >= (1 << 12)) + return 0; + dest[destSize++] = src[pos++]; + sbOffset++; + comprSize--; + } + else + { + if (comprSize < 2) + return 0; + UInt32 v = Get16(src + pos); + pos += 2; + comprSize -= 2; + + while (((sbOffset - 1) >> numDistBits) != 0) + numDistBits++; + + UInt32 len = (v & (0xFFFF >> numDistBits)) + 3; + if (sbOffset + len > (1 << 12)) + return 0; + UInt32 dist = (v >> (16 - numDistBits)); + if (dist >= sbOffset) + return 0; + Int32 offs = -1 - dist; + Byte *p = dest + destSize; + for (UInt32 t = 0; t < len; t++) + p[t] = p[t + offs]; + destSize += len; + sbOffset += len; + } + } + } + while (comprSize > 0); + src += pos; + } + } + return destSize; +} + +STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Size) + return (Size == _virtPos) ? S_OK: E_FAIL; + if (size == 0) + return S_OK; + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + if (_virtPos >= InitializedSize) + { + memset((Byte *)data, 0, size); + _virtPos += size; + *processedSize = size; + return S_OK; + } + rem = InitializedSize - _virtPos; + if (size > rem) + size = (UInt32)rem; + + while (_curRem == 0) + { + UInt64 cacheTag = _virtPos >> _chunkSizeLog; + UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1); + if (_tags[cacheIndex] == cacheTag) + { + UInt32 chunkSize = (UInt32)1 << _chunkSizeLog; + UInt32 offset = (UInt32)_virtPos & (chunkSize - 1); + UInt32 cur = MyMin(chunkSize - offset, size); + memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur); + *processedSize = cur; + _virtPos += cur; + return S_OK; + } + + PRF2(printf("\nVirtPos = %6d", _virtPos)); + + UInt32 comprUnitSize = (UInt32)1 << CompressionUnit; + UInt64 virtBlock = _virtPos >> BlockSizeLog; + UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1); + + int left = 0, right = Extents.Size(); + for (;;) + { + int mid = (left + right) / 2; + if (mid == left) + break; + if (virtBlock2 < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + bool isCompressed = false; + UInt64 virtBlock2End = virtBlock2 + comprUnitSize; + if (CompressionUnit != 0) + for (int i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.Virt >= virtBlock2End) + break; + if (e.IsEmpty()) + { + isCompressed = true; + break; + } + } + + int i; + for (i = left; Extents[i + 1].Virt <= virtBlock; i++); + + _sparseMode = false; + if (!isCompressed) + { + const CExtent &e = Extents[i]; + UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog); + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 next = Extents[i + 1].Virt; + if (next > virtBlock2End) + next &= ~((UInt64)comprUnitSize - 1); + next <<= BlockSizeLog; + if (next > Size) + next = Size; + _curRem = next - _virtPos; + break; + } + bool thereArePhy = false; + for (int i2 = left; i2 < Extents.Size(); i2++) + { + const CExtent &e = Extents[i2]; + if (e.Virt >= virtBlock2End) + break; + if (!e.IsEmpty()) + { + thereArePhy = true; + break; + } + } + if (!thereArePhy) + { + _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos; + _sparseMode = true; + break; + } + + size_t offs = 0; + UInt64 curVirt = virtBlock2; + for (i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.IsEmpty()) + break; + if (e.Virt >= virtBlock2End) + return S_FALSE; + UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 numChunks = Extents[i + 1].Virt - curVirt; + if (curVirt + numChunks > virtBlock2End) + numChunks = virtBlock2End - curVirt; + size_t compressed = (size_t)numChunks << BlockSizeLog; + RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)); + curVirt += numChunks; + _physPos += compressed; + offs += compressed; + } + size_t destLenMax = GetCuSize(); + size_t destLen = destLenMax; + UInt64 rem = Size - (virtBlock2 << BlockSizeLog); + if (destLen > rem) + destLen = (size_t)rem; + + Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog); + size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs); + _tags[cacheIndex] = cacheTag; + + // some files in Vista have destSize > destLen + if (destSizeRes < destLen) + { + memset(dest, 0, destLenMax); + if (InUse) + return S_FALSE; + } + } + if (size > _curRem) + size = (UInt32)_curRem; + HRESULT res = S_OK; + if (_sparseMode) + memset(data, 0, size); + else + { + res = Stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; + case STREAM_SEEK_END: newVirtPos += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (_virtPos != newVirtPos) + _curRem = 0; + _virtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; +} + +class CByteBufStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CByteBuffer Buf; + void Init() { _virtPos = 0; } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Buf.GetCapacity()) + return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL; + UInt64 rem = Buf.GetCapacity() - _virtPos; + if (rem < size) + size = (UInt32)rem; + memcpy(data, Buf + (size_t)_virtPos, size); + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return S_OK; +} + +STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> attrs, + int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents) +{ + CExtent e; + e.Virt = 0; + e.Phy = kEmptyExtent; + Extents.Add(e); + const CAttr &attr0 = attrs[attrIndex]; + + if (attr0.AllocatedSize < attr0.Size || + (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) || + (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) + return S_FALSE; + + for (int i = attrIndex; i < attrIndexLim; i++) + if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit)) + return S_FALSE; + + UInt64 packSizeCalc = 0; + for (int k = 0; k < Extents.Size(); k++) + { + CExtent &e = Extents[k]; + if (!e.IsEmpty()) + packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog; + PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt)); + PRF2(printf(" Pos = %4I64X", e.Phy)); + } + + if (attr0.CompressionUnit != 0) + { + if (packSizeCalc != attr0.PackSize) + return S_FALSE; + } + else + { + if (packSizeCalc != attr0.AllocatedSize) + return S_FALSE; + } + return S_OK; +} + +struct CDataRef +{ + int Start; + int Num; +}; + +struct CMftRec +{ + UInt32 Magic; + // UInt64 Lsn; + UInt16 SeqNumber; + UInt16 Flags; + // UInt16 LinkCount; + // UInt16 NextAttrInstance; + CMftRef BaseMftRef; + // UInt32 ThisRecNumber; + UInt32 MyNumNameLinks; + + CObjectVector<CAttr> DataAttrs; + CObjectVector<CFileNameAttr> FileNames; + CRecordVector<CDataRef> DataRefs; + + CSiAttr SiAttr; + + + void MoveAttrsFrom(CMftRec &src) + { + DataAttrs += src.DataAttrs; + FileNames += src.FileNames; + src.DataAttrs.ClearAndFree(); + src.FileNames.ClearAndFree(); + } + + UInt64 GetPackSize() const + { + UInt64 res = 0; + for (int i = 0; i < DataRefs.Size(); i++) + res += DataAttrs[DataRefs[i].Start].GetPackSize(); + return res; + } + + bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs); + + bool IsEmpty() const { return (Magic <= 2); } + + bool InUse() const { return (Flags & 1) != 0; } + bool IsDir() const { return (Flags & 2) != 0; } + + void ParseDataNames(); + HRESULT GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const; + + UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } + + CMftRec(): MyNumNameLinks(0) {} +}; + +void CMftRec::ParseDataNames() +{ + DataRefs.Clear(); + DataAttrs.Sort(CompareAttr, 0); + + for (int i = 0; i < DataAttrs.Size();) + { + CDataRef ref; + ref.Start = i; + for (i++; i < DataAttrs.Size(); i++) + if (DataAttrs[ref.Start].Name != DataAttrs[i].Name) + break; + ref.Num = i - ref.Start; + DataRefs.Add(ref); + } +} + +HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const +{ + *destStream = 0; + CByteBufStream *streamSpec = new CByteBufStream; + CMyComPtr<IInStream> streamTemp = streamSpec; + + if (dataIndex < 0) + return E_FAIL; + + if (dataIndex < DataRefs.Size()) + { + const CDataRef &ref = DataRefs[dataIndex]; + int numNonResident = 0; + int i; + for (i = ref.Start; i < ref.Start + ref.Num; i++) + if (DataAttrs[i].NonResident) + numNonResident++; + + const CAttr &attr0 = DataAttrs[ref.Start]; + + if (numNonResident != 0 || ref.Num != 1) + { + if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) + return S_FALSE; + CInStream *streamSpec = new CInStream; + CMyComPtr<IInStream> streamTemp = streamSpec; + RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents)); + streamSpec->Size = attr0.Size; + streamSpec->InitializedSize = attr0.InitializedSize; + streamSpec->Stream = mainStream; + streamSpec->BlockSizeLog = clusterSizeLog; + streamSpec->InUse = InUse(); + RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit)); + *destStream = streamTemp.Detach(); + return S_OK; + } + streamSpec->Buf = attr0.Data; + } + streamSpec->Init(); + *destStream = streamTemp.Detach(); + return S_OK; +} + +bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, + CObjectVector<CAttr> *attrs) +{ + G32(p, Magic); + if (IsEmpty()) + return true; + if (Magic != 0x454c4946) + return false; + + UInt32 usaOffset; + UInt32 numUsaItems; + G16(p + 0x04, usaOffset); + G16(p + 0x06, numUsaItems); + + if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 || + numUsaItems == 0 || numUsaItems - 1 != numSectors) + return false; + + UInt16 usn = Get16(p + usaOffset); + // PRF(printf("\nusn = %d", usn)); + for (UInt32 i = 1; i < numUsaItems; i++) + { + void *pp = p + (i << sectorSizeLog) - 2; + if (Get16(pp) != usn) + return false; + SetUi16(pp, Get16(p + usaOffset + i * 2)); + } + + // G64(p + 0x08, Lsn); + G16(p + 0x10, SeqNumber); + // G16(p + 0x12, LinkCount); + // PRF(printf(" L=%d", LinkCount)); + UInt32 attrOffs = Get16(p + 0x14); + G16(p + 0x16, Flags); + PRF(printf(" F=%4X", Flags)); + + UInt32 bytesInUse = Get32(p + 0x18); + UInt32 bytesAlloc = Get32(p + 0x1C); + G64(p + 0x20, BaseMftRef.Val); + if (BaseMftRef.Val != 0) + { + PRF(printf(" BaseRef=%d", (int)BaseMftRef.Val)); + // return false; // Check it; + } + // G16(p + 0x28, NextAttrInstance); + if (usaOffset >= 0x30) + if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+ + return false; + + UInt32 limit = numSectors << sectorSizeLog; + if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit + || bytesAlloc != limit) + return false; + + + for (UInt32 t = attrOffs; t < limit;) + { + CAttr attr; + // PRF(printf("\n %2d:", Attrs.Size())); + PRF(printf("\n")); + UInt32 length = attr.Parse(p + t, limit - t); + if (length == 0 || limit - t < length) + return false; + t += length; + if (attr.Type == 0xFFFFFFFF) + break; + switch(attr.Type) + { + case ATTR_TYPE_FILE_NAME: + { + CFileNameAttr fna; + if (!attr.ParseFileName(fna)) + return false; + FileNames.Add(fna); + PRF(printf(" flags = %4x", (int)fna.NameType)); + PRF(printf("\n %S", fna.Name)); + break; + } + case ATTR_TYPE_STANDARD_INFO: + if (!attr.ParseSi(SiAttr)) + return false; + break; + case ATTR_TYPE_DATA: + DataAttrs.Add(attr); + break; + default: + if (attrs) + attrs->Add(attr); + break; + } + } + + return true; +} + +struct CItem +{ + int RecIndex; + int DataIndex; + CMftRef ParentRef; + UString Name; + UInt32 Attrib; + + bool IsDir() const { return (DataIndex < 0); } +}; + +struct CDatabase +{ + CHeader Header; + CObjectVector<CItem> Items; + CObjectVector<CMftRec> Recs; + CMyComPtr<IInStream> InStream; + IArchiveOpenCallback *OpenCallback; + + CByteBuffer ByteBuf; + + CObjectVector<CAttr> VolAttrs; + + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + HRESULT SeekToCluster(UInt64 cluster); + + int FindMtfRec(const CMftRef &ref) const + { + UInt64 val = ref.GetIndex(); + int left = 0, right = Items.Size(); + while (left != right) + { + int mid = (left + right) / 2; + UInt64 midValue = Items[mid].RecIndex; + if (val == midValue) + return mid; + if (val < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + +}; + +HRESULT CDatabase::SeekToCluster(UInt64 cluster) +{ + return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + Items.Clear(); + Recs.Clear(); +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->Name; + for (int j = 0; j < 256; j++) + { + CMftRef ref = item->ParentRef; + index = FindMtfRec(ref); + if (ref.GetIndex() == 5) + return name; + if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber()) + return MY_DIR_PREFIX(L"UNKNOWN") + name; + item = &Items[index]; + name = item->Name + WCHAR_PATH_SEPARATOR + name; + } + return MY_DIR_PREFIX(L"BAD") + name; +} + +HRESULT CDatabase::Open() +{ + Clear(); + + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < Header.GetPhySize()) + return S_FALSE; + + SeekToCluster(Header.MftCluster); + + CMftRec mftRec; + UInt32 numSectorsInRec; + int recSizeLog; + CMyComPtr<IInStream> mftStream; + { + UInt32 blockSize = 1 << 12; + ByteBuf.SetCapacity(blockSize); + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + + UInt32 allocSize = Get32(ByteBuf + 0x1C); + recSizeLog = GetLog(allocSize); + if (recSizeLog < Header.SectorSizeLog) + return false; + numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog); + if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0)) + return S_FALSE; + if (mftRec.IsEmpty()) + return S_FALSE; + mftRec.ParseDataNames(); + if (mftRec.DataRefs.IsEmpty()) + return S_FALSE; + RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream)); + if (!mftStream) + return S_FALSE; + } + + UInt64 mftSize = mftRec.DataAttrs[0].Size; + if ((mftSize >> 4) > Header.GetPhySize()) + return S_FALSE; + + UInt64 numFiles = mftSize >> recSizeLog; + if (numFiles > (1 << 30)) + return S_FALSE; + if (OpenCallback) + { + RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)); + } + const UInt32 kBufSize = (1 << 15); + if (kBufSize < (1 << recSizeLog)) + return S_FALSE; + + ByteBuf.SetCapacity((size_t)kBufSize); + Recs.Reserve((int)numFiles); + for (UInt64 pos64 = 0;;) + { + if (OpenCallback) + { + // Sleep(0); + UInt64 numFiles = Recs.Size(); + RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); + } + UInt32 readSize = kBufSize; + UInt64 rem = mftSize - pos64; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize < ((UInt32)1 << recSizeLog)) + break; + RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize)); + pos64 += readSize; + for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++) + { + PRF(printf("\n---------------------")); + PRF(printf("\n%5d:", Recs.Size())); + Byte *p = ByteBuf + ((UInt32)i << recSizeLog); + CMftRec rec; + if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), + (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL)) + return S_FALSE; + Recs.Add(rec); + } + } + + int i; + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (!rec.BaseMftRef.IsBaseItself()) + { + UInt64 refIndex = rec.BaseMftRef.GetIndex(); + if (refIndex > (UInt32)Recs.Size()) + return S_FALSE; + CMftRec &refRec = Recs[(int)refIndex]; + bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself()); + if (rec.InUse() && refRec.InUse()) + { + if (!moveAttrs) + return S_FALSE; + } + else if (rec.InUse() || refRec.InUse()) + moveAttrs = false; + if (moveAttrs) + refRec.MoveAttrsFrom(rec); + } + } + + for (i = 0; i < Recs.Size(); i++) + Recs[i].ParseDataNames(); + + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (rec.IsEmpty() || !rec.BaseMftRef.IsBaseItself()) + continue; + int numNames = 0; + // printf("\n%4d: ", i); + for (int t = 0; t < rec.FileNames.Size(); t++) + { + const CFileNameAttr &fna = rec.FileNames[t]; + // printf("%4d %S | ", (int)fna.NameType, fna.Name); + if (fna.IsDos()) + continue; + int numDatas = rec.DataRefs.Size(); + + // For hard linked files we show substreams only for first Name. + if (numDatas > 1 && numNames > 0) + numDatas = 1; + numNames++; + + if (rec.IsDir()) + { + CItem item; + item.Name = fna.Name; + item.RecIndex = i; + item.DataIndex = -1; + item.ParentRef = fna.ParentDirRef; + item.Attrib = rec.SiAttr.Attrib | 0x10; + // item.Attrib = fna.Attrib; + Items.Add(item); + } + for (int di = 0; di < numDatas; di++) + { + CItem item; + item.Name = fna.Name; + item.Attrib = rec.SiAttr.Attrib; + const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; + if (!subName.IsEmpty()) + { + // $BadClus:$Bad is sparse file for all clusters. So we skip it. + if (i == kRecIndex_BadClus && subName == L"$Bad") + continue; + item.Name += L":"; + item.Name += subName; + item.Attrib = fna.Attrib; + } + + PRF(printf("\n%3d", i)); + PRF(printf(" attrib=%2x", rec.SiAttr.Attrib)); + PRF(printf(" %S", item.Name)); + + item.RecIndex = i; + item.DataIndex = di; + item.ParentRef = fna.ParentDirRef; + + Items.Add(item); + rec.MyNumNameLinks++; + } + } + rec.FileNames.ClearAndFree(); + } + + return S_OK; +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + IInStream *stream2; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2); + *stream = (ISequentialInStream *)stream2; + return res; + COM_TRY_END +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidLinks, VT_UI4} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidVolumeName, VT_BSTR}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI8} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME ft; + ft.dwLowDateTime = (DWORD)t; + ft.dwHighDateTime = (DWORD)(t >> 32); + prop = ft; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL); + + switch(propID) + { + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + /* + case kpidHeadersSize: + { + UInt64 val = 0; + for (int i = 0; i < kNumSysRecs; i++) + { + printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize()); + if (i == 8) + i = i + val += Recs[i].GetPackSize(); + } + prop = val; + break; + } + */ + case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break; + case kpidVolumeName: + { + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_NAME) + { + UString name; + GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name); + prop = name; + break; + } + } + break; + } + case kpidFileSystem: + { + AString s = "NTFS"; + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_INFO) + { + CVolInfo vi; + if (attr.ParseVolInfo(vi)) + { + s += ' '; + char temp[16]; + ConvertUInt32ToString(vi.MajorVer, temp); + s += temp; + s += '.'; + ConvertUInt32ToString(vi.MinorVer, temp); + s += temp; + } + break; + } + } + prop = s; + break; + } + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + case kpidId: prop = Header.SerialNumber; break; + // case kpidMediaType: prop = Header.MediaType; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + + const CAttr *data= NULL; + if (item.DataIndex >= 0) + data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + switch(propID) + { + case kpidPath: + { + UString name = GetItemPath(index); + const wchar_t *prefix = NULL; + if (!rec.InUse()) + prefix = MY_DIR_PREFIX(L"DELETED"); + else if (item.RecIndex < kNumSysRecs) + prefix = MY_DIR_PREFIX(L"SYSTEM"); + if (prefix) + name = prefix + name; + prop = name; + break; + } + + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break; + + case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break; + case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break; + case kpidAttrib: + prop = item.Attrib; + break; + case kpidLinks: prop = rec.MyNumNameLinks; break; + case kpidSize: if (data) prop = data->GetSize(); break; + case kpidPackSize: if (data) prop = data->GetPackSize(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + const CMftRec &rec = Recs[item.RecIndex]; + if (!rec.IsDir()) + totalSize += rec.GetSize(item.DataIndex); + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + CByteBuffer buf; + UInt32 clusterSize = Header.ClusterSize(); + buf.SetCapacity(clusterSize); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + const CItem &item = Items[index]; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + if (!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + const CMftRec &rec = Recs[item.RecIndex]; + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + int res = NArchive::NExtract::NOperationResult::kDataError; + { + CMyComPtr<IInStream> inStream; + HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream); + if (hres == S_FALSE) + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + if (inStream) + { + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres != S_OK && hres != S_FALSE) + { + RINOK(hres); + } + if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) + res = NArchive::NExtract::NOperationResult::kOK; + } + } + } + totalPackSize += data.GetPackSize(); + totalSize += data.GetSize(); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 70af37c7..a1304ae4 100755 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -18,8 +18,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -549,11 +547,6 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidStackCommit: prop = _optHeader.StackCommit; break; case kpidHeapReserve: prop = _optHeader.HeapReserve; break; case kpidHeapCommit: prop = _optHeader.HeapCommit; break; - - /* - if (_optHeader.Is64Bit()) - s += " 64-bit"; - */ } prop.Detach(value); return S_OK; @@ -785,8 +778,6 @@ HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos RINOK(ReadStream(stream, buf, &processed)); /* - */ - /* for (; processed < rem; processed++) buf[processed] = 0; */ @@ -880,9 +871,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -893,20 +881,17 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSection &item = _sections[index]; currentItemSize = item.GetPackSize(); - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); + outStream.Release(); RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? checkSumOK ? NArchive::NExtract::NOperationResult::kOK: diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 2431e449..93c19265 100755 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -251,7 +251,10 @@ public: } else if (!_newStyle) { - if (ext.CompareNoCase(L"000") == 0 || ext.CompareNoCase(L"001") == 0) + if (ext.CompareNoCase(L"000") == 0 || + ext.CompareNoCase(L"001") == 0 || + ext.CompareNoCase(L"r00") == 0 || + ext.CompareNoCase(L"r01") == 0) { _afterPart.Empty(); _first = false; diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp index 18669405..4810649b 100755 --- a/CPP/7zip/Archive/Rar/RarIn.cpp +++ b/CPP/7zip/Archive/Rar/RarIn.cpp @@ -2,19 +2,17 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "Common/StringConvert.h" #include "Common/UTFConvert.h" -#include "RarIn.h" #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" #include "../Common/FindSignature.h" -extern "C" -{ - #include "../../../../C/7zCrc.h" -} +#include "RarIn.h" namespace NArchive { namespace NRar { diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp index 1845e20a..25194f91 100755 --- a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp +++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp @@ -2,15 +2,9 @@ #include "StdAfx.h" -#include "RarVolumeInStream.h" - -#include "Windows/Defs.h" -#include "Common/Defs.h" +#include "../../../../C/7zCrc.h" -extern "C" -{ - #include "../../../../C/7zCrc.h" -} +#include "RarVolumeInStream.h" namespace NArchive { namespace NRar { diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index c6951799..13b67390 100755 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -9,6 +9,7 @@ #include "Windows/PropVariant.h" +#include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" @@ -113,23 +114,23 @@ HRESULT OpenArchive(IInStream *inStream) return S_FALSE; CSigHeaderSig sigHeader, header; - if(lead.SignatureType == RPMSIG_NONE) + if (lead.SignatureType == RPMSIG_NONE) { ; } - else if(lead.SignatureType == RPMSIG_PGP262_1024) + else if (lead.SignatureType == RPMSIG_PGP262_1024) { UInt64 pos; RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos)); } - else if(lead.SignatureType == RPMSIG_HEADERSIG) + else if (lead.SignatureType == RPMSIG_HEADERSIG) { RINOK(RedSigHeaderSig(inStream, sigHeader)); - if(!sigHeader.MagicCheck()) + if (!sigHeader.MagicCheck()) return S_FALSE; UInt32 len = sigHeader.GetLostHeaderLen(); RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos)); - if((pos % 8) != 0) + if ((pos % 8) != 0) { RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos, STREAM_SEEK_CUR, &pos)); @@ -139,10 +140,10 @@ HRESULT OpenArchive(IInStream *inStream) return S_FALSE; RINOK(RedSigHeaderSig(inStream, header)); - if(!header.MagicCheck()) + if (!header.MagicCheck()) return S_FALSE; int headerLen = header.GetLostHeaderLen(); - if(headerLen == -1) + if (headerLen == -1) return S_FALSE; RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos)); return S_OK; @@ -150,28 +151,34 @@ HRESULT OpenArchive(IInStream *inStream) class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CMyComPtr<IInStream> _stream; + UInt64 _pos; + UInt64 _size; + Byte _sig[4]; public: - MY_UNKNOWN_IMP1(IInArchive) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CMyComPtr<IInStream> m_InStream; - UInt64 m_Pos; - UInt64 m_Size; - Byte _sig[4]; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; STATPROPSTG kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + { NULL, kpidSize, VT_UI8} }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; } + prop.Detach(value); + return S_OK; +} STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, @@ -180,29 +187,24 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, COM_TRY_BEGIN try { - if(OpenArchive(inStream) != S_OK) + Close(); + if (OpenArchive(inStream) != S_OK) return S_FALSE; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Pos)); + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos)); + RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0]))); UInt64 endPosition; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition)); - m_Size = endPosition - m_Pos; - - RINOK(inStream->Seek(m_Pos, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0]))); - - m_InStream = inStream; + _size = endPosition - _pos; + _stream = inStream; return S_OK; } - catch(...) - { - return S_FALSE; - } + catch(...) { return S_FALSE; } COM_TRY_END } STDMETHODIMP CHandler::Close() { - m_InStream.Release(); + _stream.Release(); return S_OK; } @@ -219,19 +221,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN { case kpidSize: case kpidPackSize: - prop = m_Size; + prop = _size; break; case kpidExtension: { - wchar_t s[32]; - MyStringCopy(s, L"cpio."); - const wchar_t *ext; + char s[32]; + MyStringCopy(s, "cpio."); + const char *ext; if (_sig[0] == 0x1F && _sig[1] == 0x8B) - ext = L"gz"; + ext = "gz"; else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h') - ext = L"bz2"; + ext = "bz2"; else - ext = L"lzma"; + ext = "lzma"; MyStringCopy(s + MyStringLen(s), ext); prop = s; break; @@ -245,58 +247,50 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); - if (allFilesMode) + if (numItems == UInt32(-1)) numItems = 1; - if(numItems == 0) + if (numItems == 0) return S_OK; - if(numItems != 1) - return E_FAIL; - if (indices[0] != 0) - return E_FAIL; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; bool testMode = (_aTestMode != 0); - - UInt64 currentTotalSize = 0; - RINOK(extractCallback->SetTotal(m_Size)); - RINOK(extractCallback->SetCompleted(¤tTotalSize)); - CMyComPtr<ISequentialOutStream> realOutStream; + + RINOK(extractCallback->SetTotal(_size)); + CMyComPtr<ISequentialOutStream> outStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; - Int32 index = 0; - - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - if(!testMode && (!realOutStream)) + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) return S_OK; - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - return S_OK; - } - - RINOK(m_InStream->Seek(m_Pos, STREAM_SEEK_SET, NULL)); - + CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - RINOK(copyCoder->Code(m_InStream, realOutStream, NULL, NULL, progress)); - realOutStream.Release(); + RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress)); + outStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + return CreateLimitedInStream(_stream, _pos, _size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; } static CArcInfo g_ArcInfo = - { L"Rpm", L"rpm", 0, 0xEB, { 0}, 0, false, CreateArc, 0 }; + { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 }; REGISTER_ARC(Rpm) diff --git a/CPP/7zip/Archive/Split/SplitHandler.h b/CPP/7zip/Archive/Split/SplitHandler.h deleted file mode 100755 index 9e020763..00000000 --- a/CPP/7zip/Archive/Split/SplitHandler.h +++ /dev/null @@ -1,37 +0,0 @@ -// Split/Handler.h - -#ifndef __SPLIT_HANDLER_H -#define __SPLIT_HANDLER_H - -#include "Common/MyCom.h" -#include "Common/MyString.h" -#include "../IArchive.h" - -namespace NArchive { -namespace NSplit { - -class CHandler: - public IInArchive, - public IInArchiveGetStream, - // public IOutArchive, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) - - INTERFACE_IInArchive(;) - - STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - -private: - UString _subName; - UString _name; - CObjectVector<CMyComPtr<IInStream> > _streams; - CRecordVector<UInt64> _sizes; - - UInt64 _totalSize; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Split/SplitHandlerOut.cpp b/CPP/7zip/Archive/Split/SplitHandlerOut.cpp deleted file mode 100755 index 6edf86f4..00000000 --- a/CPP/7zip/Archive/Split/SplitHandlerOut.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Split/OutHandler.cpp - -#include "StdAfx.h" - -#include "SplitHandler.h" -#include "../../../Windows/PropVariant.h" -#include "../../../Common/ComTry.h" -#include "../../../Common/StringToInt.h" - -using namespace NWindows; - -namespace NArchive { -namespace NSplit { - -/* -STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) -{ - *type = NFileTimeType::kWindows; - return S_OK; -} - -STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, - IArchiveUpdateCallback *updateCallback) -{ - COM_TRY_BEGIN - - if (numItems != 1) - return E_INVALIDARG; - - UInt64 volumeSize = 0; - - CMyComPtr<IArchiveUpdateCallback2> callback2; - updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, - (void **)&callback2); - - RINOK(callback2->GetVolumeSize(0, &volumeSize)); - - Int32 newData; - Int32 newProperties; - UInt32 indexInArchive; - if (!updateCallback) - return E_FAIL; - - UInt32 fileIndex = 0; - RINOK(updateCallback->GetUpdateItemInfo(fileIndex, - &newData, &newProperties, &indexInArchive)); - - if (newProperties != 0) - { - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); - if (prop.vt == VT_EMPTY) - { - } - else if (prop.vt != VT_BOOL) - return E_INVALIDARG; - else - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); - if (prop.vt == VT_EMPTY) - { - } - else if (prop.vt != VT_BOOL) - return E_INVALIDARG; - else - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - } - } - UInt64 newSize; - bool thereIsCopyData = false; - if (newData != 0) - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - newSize = prop.uhVal.QuadPart; - } - else - thereIsCopyData = true; - - UInt64 pos = 0; - while(pos < newSize) - { - - } - return S_OK; - COM_TRY_END -} -*/ - -}} diff --git a/CPP/7zip/Archive/Split/SplitRegister.cpp b/CPP/7zip/Archive/Split/SplitRegister.cpp deleted file mode 100755 index 56ddba29..00000000 --- a/CPP/7zip/Archive/Split/SplitRegister.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// SplitRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "SplitHandler.h" -static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } -/* -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } -#else -#define CreateArcOut 0 -#endif -*/ - -static CArcInfo g_ArcInfo = -{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; - -REGISTER_ARC(Split) diff --git a/CPP/7zip/Archive/Split/StdAfx.h b/CPP/7zip/Archive/Split/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Split/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/Split/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 61b7f4a7..892e12af 100755 --- a/CPP/7zip/Archive/Split/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -3,24 +3,18 @@ #include "StdAfx.h" #include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/NewHandler.h" -#include "Common/StringConvert.h" +#include "Common/MyString.h" #include "Windows/PropVariant.h" -#include "Windows/Time.h" -#include "../../Common/ProgressUtils.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" -#include "../../Compress/CopyCoder.h" +#include "../Compress/CopyCoder.h" -#include "../Common/ItemNameUtils.h" -#include "../Common/MultiStream.h" - -#include "SplitHandler.h" +#include "Common/MultiStream.h" using namespace NWindows; -using namespace NTime; namespace NArchive { namespace NSplit { @@ -28,19 +22,50 @@ namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidSize, VT_UI8} }; -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +STATPROPSTG kArcProps[] = +{ + { NULL, kpidNumVolumes, VT_UI4} +}; -class CSeqName +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp { + UString _subName; + CObjectVector<CMyComPtr<IInStream> > _streams; + CRecordVector<UInt64> _sizes; + UInt64 _totalSize; public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; + } + prop.Detach(value); + return S_OK; +} + +struct CSeqName +{ UString _unchangedPart; UString _changedPart; bool _splitStyle; + UString GetNextName() { UString newName; @@ -125,23 +150,24 @@ STDMETHODIMP CHandler::Open(IInStream *stream, &openVolumeCallback) != S_OK) return S_FALSE; + UString name; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; - _name = prop.bstrVal; + name = prop.bstrVal; } - int dotPos = _name.ReverseFind('.'); + int dotPos = name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { - prefix = _name.Left(dotPos + 1); - ext = _name.Mid(dotPos + 1); + prefix = name.Left(dotPos + 1); + ext = name.Mid(dotPos + 1); } else - ext = _name; + ext = name; UString extBig = ext; extBig.MakeUpper(); @@ -258,9 +284,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN NWindows::NCOM::CPropVariant prop; switch(propID) { - case kpidPath: - prop = _subName; - break; + case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; @@ -271,48 +295,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + if (numItems == UInt32(-1)) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; - if (numItems != UInt32(-1)) - { - if (numItems != 1) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } bool testMode = (_aTestMode != 0); - CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; - extractCallback->SetTotal(_totalSize); - - /* - CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; - if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) - return E_FAIL; - */ - UInt64 currentTotalSize = 0; - UInt64 currentItemSize; - - RINOK(extractCallback->SetCompleted(¤tTotalSize)); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - Int32 index = 0; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + RINOK(extractCallback->SetTotal(_totalSize)); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) return S_OK; - } + RINOK(extractCallback->PrepareOperation(askMode)); - if (!testMode && (!realOutStream)) - return S_OK; - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -320,22 +324,23 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) + for (int i = 0; i < _streams.Size(); i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); - currentItemSize = copyCoderSpec->TotalSize; + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + currentTotalSize += copyCoderSpec->TotalSize; } - realOutStream.Release(); + outStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { + COM_TRY_BEGIN if (index != 0) return E_INVALIDARG; *stream = 0; @@ -352,6 +357,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; + COM_TRY_END } +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = +{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Split) + }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index f8000c85..aa4b2aec 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -13,9 +13,6 @@ #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" -#include "../../Compress/CopyCoder.h" - -#include "../Common/DummyOutStream.h" #include "../Common/ItemNameUtils.h" #include "TarHandler.h" @@ -33,22 +30,35 @@ STATPROPSTG kProps[] = { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4}, { NULL, kpidUser, VT_BSTR}, - { NULL, kpidGroup, VT_BSTR} + { NULL, kpidGroup, VT_BSTR}, + { NULL, kpidLink, VT_BSTR} }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; + } + prop.Detach(value); + return S_OK; +} HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { UInt64 endPos = 0; - if (callback != NULL) { RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } + _isGood = true; UInt64 pos = 0; for (;;) { @@ -61,8 +71,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _items.Add(item); RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); - if (pos >= endPos) + if (pos > endPos) return S_FALSE; + if (pos == endPos) + { + _isGood = false; + break; + } if (callback != NULL) { if (_items.Size() == 1) @@ -98,70 +113,134 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) return S_OK; } -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *openArchiveCallback) +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN { Close(); RINOK(Open2(stream, openArchiveCallback)); - _inStream = stream; + _stream = stream; } return S_OK; COM_TRY_END } +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + STDMETHODIMP CHandler::Close() { + _phySizeDefined = false; + _curIndex = 0; + _latestIsRead = false; _items.Clear(); - _inStream.Release(); + _seqStream.Release(); + _stream.Release(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = _items.Size(); + *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1); + return S_OK; +} + +CHandler::CHandler() +{ + copyCoderSpec = new NCompress::CCopyCoder(); + copyCoder = copyCoderSpec; +} + +HRESULT CHandler::SkipTo(UInt32 index) +{ + while (_curIndex < index || !_latestIsRead) + { + if (_latestIsRead) + { + UInt64 packSize = _latestItem.GetPackSize(); + RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); + _latestIsRead = false; + _curIndex++; + } + else + { + bool filled; + // item.HeaderPosition = pos; + RINOK(ReadItem(_seqStream, filled, _latestItem)); + if (!filled) + return E_INVALIDARG; + _latestIsRead = true; + } + } return S_OK; } +static UString TarStringToUnicode(const AString &s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; + + const CItemEx *item; + if (_stream) + item = &_items[index]; + else + { + if (index < _curIndex) + return E_INVALIDARG; + else + { + RINOK(SkipTo(index)); + item = &_latestItem; + } + } switch(propID) { - case kpidPath: prop = NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; - case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; - case kpidPackSize: prop = item.GetPackSize(); break; + case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; + case kpidIsDir: prop = item->IsDir(); break; + case kpidSize: prop = item->Size; break; + case kpidPackSize: prop = item->GetPackSize(); break; case kpidMTime: - if (item.MTime != 0) + if (item->MTime != 0) { FILETIME ft; - NTime::UnixTimeToFileTime(item.MTime, ft); + NTime::UnixTimeToFileTime(item->MTime, ft); prop = ft; } break; - case kpidUser: prop = MultiByteToUnicodeString(item.UserName, CP_OEMCP); break; - case kpidGroup: prop = MultiByteToUnicodeString(item.GroupName, CP_OEMCP); break; + case kpidPosixAttrib: prop = item->Mode; break; + case kpidUser: prop = TarStringToUnicode(item->User); break; + case kpidGroup: prop = TarStringToUnicode(item->Group); break; + case kpidLink: prop = TarStringToUnicode(item->LinkName); break; } prop.Detach(value); return S_OK; COM_TRY_END } -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, +HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + ISequentialInStream *stream = _seqStream; + bool seqMode = (_stream == NULL); + if (!seqMode) + stream = _stream; + bool testMode = (_aTestMode != 0); - bool allFilesMode = (numItems == UInt32(-1)); + bool allFilesMode = (numItems == (UInt32)-1); if (allFilesMode) numItems = _items.Size(); - if (numItems == 0) + if (_stream && numItems == 0) return S_OK; UInt64 totalSize = 0; UInt32 i; @@ -169,24 +248,21 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, totalSize += _items[allFilesMode ? i : indices[i]].Size; extractCallback->SetTotal(totalSize); - UInt64 totalPackSize, curPackSize, curSize; + UInt64 totalPackSize; totalSize = totalPackSize = 0; - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(stream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, totalSize += curSize, totalPackSize += curPackSize) + for (i = 0; i < numItems || seqMode; i++) { lps->InSize = totalPackSize; lps->OutSize = totalSize; @@ -196,29 +272,54 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; + const CItemEx *item; + if (seqMode) + { + HRESULT res = SkipTo(index); + if (res == E_INVALIDARG) + break; + RINOK(res); + item = &_latestItem; + } + else + item = &_items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - curSize = item.Size; - curPackSize = item.GetPackSize(); - if (item.IsDir()) + totalSize += item->Size; + totalPackSize += item->GetPackSize(); + if (item->IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - if (!testMode && (!realOutStream)) - continue; + bool skipMode = false; + if (!testMode && !realOutStream) + { + if (!seqMode) + continue; + skipMode = true; + askMode = NArchive::NExtract::NAskMode::kSkip; + } RINOK(extractCallback->PrepareOperation(askMode)); outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - outStreamSpec->Init(); + outStreamSpec->Init(skipMode ? 0 : item->Size, true); - RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); - streamSpec->Init(item.Size); + if (!seqMode) + { + RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + } + streamSpec->Init(item->GetPackSize()); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (seqMode) + { + _latestIsRead = false; + _curIndex++; + } outStreamSpec->ReleaseStream(); - RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? + RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); } @@ -226,4 +327,12 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index a98b5404..d2def9a1 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -1,4 +1,4 @@ -// Tar/Handler.h +// TarHandler.h #ifndef __TAR_HANDLER_H #define __TAR_HANDLER_H @@ -6,6 +6,8 @@ #include "Common/MyCom.h" #include "../IArchive.h" +#include "../../Compress/CopyCoder.h" + #include "TarItem.h" namespace NArchive { @@ -13,23 +15,43 @@ namespace NTar { class CHandler: public IInArchive, + public IArchiveOpenSeq, + public IInArchiveGetStream, public IOutArchive, public CMyUnknownImp { + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + bool _isGood; + + UInt32 _curIndex; + bool _latestIsRead; + CItemEx _latestItem; + + UInt64 _phySize; + bool _phySizeDefined; + + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr<ICompressCoder> copyCoder; + + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); + HRESULT SkipTo(UInt32 index); + public: - MY_UNKNOWN_IMP2( + MY_UNKNOWN_IMP4( IInArchive, + IArchiveOpenSeq, + IInArchiveGetStream, IOutArchive ) INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); - -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _inStream; + CHandler(); }; }} diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 3454868e..4c0cb5f8 100755 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -1,20 +1,17 @@ -// Tar/HandlerOut.cpp +// TarHandlerOut.cpp #include "StdAfx.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" +#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" -#include "../Common/ItemNameUtils.h" - #include "TarHandler.h" #include "TarUpdate.h" using namespace NWindows; -using namespace NCOM; namespace NArchive { namespace NTar { @@ -25,94 +22,95 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } +static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res) +{ + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return S_OK; +} + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback) { COM_TRY_BEGIN + if ((_stream && !_isGood) || _seqStream) + return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; Int32 newData; - Int32 newProperties; + Int32 newProps; UInt32 indexInArchive; if (!callback) return E_FAIL; - RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); - ui.NewProperties = IntToBool(newProperties); + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; - if (IntToBool(newProperties)) + if (IntToBool(newProps)) { - FILETIME utcTime; - UString name; - /* - UInt32 attributes; { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidAttrib, &prop)); + RINOK(callback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) - attributes = 0; - else if (prop.vt != VT_UI4) + ui.IsDir = false; + else if (prop.vt != VT_BOOL) return E_INVALIDARG; else - attributes = prop.ulVal; - } - */ - { - NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidMTime, &prop)); - if (prop.vt != VT_FILETIME) - return E_INVALIDARG; - utcTime = prop.filetime; + ui.IsDir = (prop.boolVal != VARIANT_FALSE); } + { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidPath, &prop)); + RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop)); if (prop.vt == VT_EMPTY) - name.Empty(); - else if (prop.vt != VT_BSTR) + ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000); + else if (prop.vt != VT_UI4) return E_INVALIDARG; else - name = prop.bstrVal; + ui.Mode = prop.ulVal; } { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidIsDir, &prop)); + RINOK(callback->GetProperty(i, kpidMTime, &prop)); if (prop.vt == VT_EMPTY) - ui.IsDir = false; - else if (prop.vt != VT_BOOL) + ui.Time = 0; + else if (prop.vt != VT_FILETIME) return E_INVALIDARG; - else - ui.IsDir = (prop.boolVal != VARIANT_FALSE); + else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time)) + ui.Time = 0; } - ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(name), CP_OEMCP); - if (ui.IsDir) - ui.Name += '/'; - - if (!NTime::FileTimeToUnixTime(utcTime, ui.Time)) { - ui.Time = 0; - // return E_INVALIDARG; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (ui.IsDir) + ui.Name += '/'; } + RINOK(GetPropString(callback, i, kpidUser, ui.User)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group)); } if (IntToBool(newData)) { - UInt64 size; - { - NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - ui.Size = size; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = prop.uhVal.QuadPart; } updateItems.Add(ui); } - return UpdateArchive(_inStream, outStream, _items, updateItems, callback); + return UpdateArchive(_stream, outStream, _items, updateItems, callback); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 55215ac7..b8409195 100755 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -1,15 +1,13 @@ -// Archive/TarIn.cpp +// TarIn.cpp #include "StdAfx.h" -#include "TarIn.h" -#include "TarHeader.h" - #include "Common/StringToInt.h" -#include "Windows/Defs.h" #include "../../Common/StreamUtils.h" +#include "TarIn.h" + namespace NArchive { namespace NTar { @@ -98,8 +96,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE memcpy(item.Magic, p, 8); p += 8; - ReadString(p, NFileHeader::kUserNameSize, item.UserName); p += NFileHeader::kUserNameSize; - ReadString(p, NFileHeader::kUserNameSize, item.GroupName); p += NFileHeader::kUserNameSize; + ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize; + ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize; item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8; item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8; @@ -132,7 +130,8 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) if (!filled) return S_OK; // GNUtar extension - if (item.LinkFlag == 'L') + if (item.LinkFlag == 'L' || // NEXT file has a long name + item.LinkFlag == 'K') // NEXT file has a long linkname { if (item.Name.Compare(NFileHeader::kLongLink) != 0) if (item.Name.Compare(NFileHeader::kLongLink2) != 0) @@ -150,11 +149,17 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) fullName.ReleaseBuffer(); UInt64 headerPosition = item.HeaderPosition; + if (item.LinkFlag == 'L') { size_t processedSize2; RINOK(GetNextItemReal(stream, filled, item, processedSize2)); + item.LongLinkSize = (unsigned)processedSize; + } + else + { + item.LongLinkSize = (unsigned)processedSize - NFileHeader::kRecordSize; + item.Size = 0; } - item.LongLinkSize = (unsigned)processedSize; item.Name = fullName; item.HeaderPosition = headerPosition; } diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 7d95844d..afe8997d 100755 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -1,12 +1,10 @@ -// Archive/Tar/Item.h +// TarItem.h #ifndef __ARCHIVE_TAR_ITEM_H #define __ARCHIVE_TAR_ITEM_H -#include "Common/Types.h" -#include "Common/MyString.h" - #include "../Common/ItemNameUtils.h" + #include "TarHeader.h" namespace NArchive { @@ -25,8 +23,8 @@ struct CItem UInt32 DeviceMinor; AString LinkName; - AString UserName; - AString GroupName; + AString User; + AString Group; char Magic[8]; char LinkFlag; diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index 0892748f..1ec314c7 100755 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -1,14 +1,13 @@ -// Archive/TarOut.cpp +// TarOut.cpp #include "StdAfx.h" -#include "TarOut.h" -#include "TarHeader.h" - #include "Common/IntToString.h" -#include "Windows/Defs.h" + #include "../../Common/StreamUtils.h" +#include "TarOut.h" + namespace NArchive { namespace NTar { @@ -114,10 +113,10 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) memmove(cur, item.Magic, 8); cur += 8; - RETURN_IF_NOT_TRUE(CopyString(cur, item.UserName, NFileHeader::kUserNameSize)); - cur += NFileHeader::kUserNameSize; - RETURN_IF_NOT_TRUE(CopyString(cur, item.GroupName, NFileHeader::kGroupNameSize)); + RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize)); cur += NFileHeader::kUserNameSize; + RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize)); + cur += NFileHeader::kGroupNameSize; if (item.DeviceMajorDefined) diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 1c048915..0577848f 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -55,10 +55,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CUpdateItem &ui = updateItems[i]; CItem item; - if (ui.NewProperties) + if (ui.NewProps) { - item.Mode = 0777; - item.Name = (ui.Name); + item.Mode = ui.Mode; + item.Name = ui.Name; + item.User = ui.User; + item.Group = ui.Group; if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; @@ -77,21 +79,16 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); } else - { - const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; - item = existItemInfo; - } + item = inputItems[ui.IndexInArchive]; + if (ui.NewData) { item.Size = ui.Size; - if (item.Size == UInt64(Int64(-1))) + if (item.Size == (UInt64)(Int64)-1) return E_INVALIDARG; } else - { - const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; - item.Size = existItemInfo.Size; - } + item.Size = inputItems[ui.IndexInArchive].Size; if (ui.NewData) { @@ -116,7 +113,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, { const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; UInt64 size; - if (ui.NewProperties) + if (ui.NewProps) { RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL)); diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index 7d196d1c..fb217d19 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -1,4 +1,4 @@ -// Tar/Update.h +// TarUpdate.h #ifndef __TAR_UPDATE_H #define __TAR_UPDATE_H @@ -11,14 +11,16 @@ namespace NTar { struct CUpdateItem { - bool NewData; - bool NewProperties; int IndexInArchive; int IndexInClient; - UInt32 Time; + UInt32 Mode; UInt64 Size; AString Name; + AString User; + AString Group; + bool NewData; + bool NewProps; bool IsDir; }; diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 12329147..07b61c51 100755 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -8,12 +8,11 @@ #include "Windows/PropVariant.h" #include "Windows/Time.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" -#include "../Common/DummyOutStream.h" - #include "UdfHandler.h" namespace NArchive { @@ -201,79 +200,129 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -class CUdfInStream: - public ISequentialInStream, +class CBufInStream: + public IInStream, public CMyUnknownImp { + CByteBuffer _data; + UInt64 _pos; + +public: + void Init(const CByteBuffer &data) + { + _data = data; + _pos = 0; + } + MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - UInt64 _rem; + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + + +STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_pos > _data.GetCapacity()) + return E_FAIL; + size_t rem = _data.GetCapacity() - (size_t)_pos; + if (size < rem) + rem = (size_t)size; + memcpy(data, (const Byte *)_data + _pos, rem); + _pos += rem; + if (processedSize != NULL) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _pos = offset; break; + case STREAM_SEEK_CUR: _pos += offset; break; + case STREAM_SEEK_END: _pos = _data.GetCapacity() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _pos; + return S_OK; +} + +struct CSeekExtent +{ + UInt64 Phy; + UInt64 Virt; +}; + +class CExtentsStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + + HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + public: - CInArchive *_archive; - CMyComPtr<IInStream> _stream; - CRef2 _ref2; - int _extentIndex; - UInt32 _offsetInExtent; + CMyComPtr<IInStream> Stream; + CRecordVector<CSeekExtent> Extents; - void Init(UInt64 size) + MY_UNKNOWN_IMP1(IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + void ReleaseStream() { Stream.Release(); } + + void Init() { - _extentIndex = 0; - _offsetInExtent = 0; - _rem = size; + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; } - void ReleaseStream() { _stream.Release(); } + }; -STDMETHODIMP CUdfInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; - if (size > _rem) - size = (UInt32)_rem; - while (size > 0) + if (size > 0) { - const CLogVol &vol = _archive->LogVols[_ref2.Vol]; - const CRef &ref = vol.FileSets[_ref2.Fs].Refs[_ref2.Ref]; - const CFile &file = _archive->Files[ref.FileIndex]; - const CItem &item = _archive->Items[file.ItemIndex]; - - HRESULT res = S_OK; - if (item.IsInline) + UInt64 totalSize = Extents.Back().Virt; + if (_virtPos >= totalSize) + return (_virtPos == totalSize) ? S_OK : E_FAIL; + int left = 0, right = Extents.Size() - 1; + for (;;) { - size_t rem = item.InlineData.GetCapacity() - _offsetInExtent; - if (rem == 0) - return S_OK; - if (rem > _rem) - rem = (size_t)_rem; - memcpy(data, (const Byte *)item.InlineData + _offsetInExtent, rem); + int mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < Extents[mid].Virt) + right = mid; + else + left = mid; } - else + + const CSeekExtent &extent = Extents[left]; + UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); + if (_needStartSeek || _phyPos != phyPos) { - if (_extentIndex >= item.Extents.Size()) - return S_OK; - const CMyExtent &extent = item.Extents[_extentIndex]; - UInt32 rem = extent.GetLen() - _offsetInExtent; - if (rem == 0) - { - _extentIndex++; - _offsetInExtent = 0; - continue; - } - if (size > rem) - size = rem; - - int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; - UInt32 logBlockNumber = extent.Pos; - const CPartition &partition = _archive->Partitions[partitionIndex]; - UInt64 offset = ((UInt64)partition.Pos << _archive->SecLogSize) + - (UInt64)logBlockNumber * vol.BlockSize + _offsetInExtent; - - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - res = _stream->Read(data, size, &size); + _needStartSeek = false; + _phyPos = phyPos; + RINOK(SeekToPhys()); } - _offsetInExtent += size; - _rem -= size; + + UInt64 rem = Extents[left + 1].Virt - _virtPos; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = Stream->Read(data, size, &size); + _phyPos += size; + _virtPos += size; if (processedSize) *processedSize = size; return res; @@ -281,6 +330,83 @@ STDMETHODIMP CUdfInStream::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; } +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Extents.Back().Virt + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + *stream = 0; + + const CRef2 &ref2 = _refs2[index]; + const CLogVol &vol = _archive.LogVols[ref2.Vol]; + const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + UInt64 size = item.Size; + + if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item)) + return E_NOTIMPL; + + if (item.IsInline) + { + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr<ISequentialInStream> inStream = inStreamSpec; + inStreamSpec->Init(item.InlineData); + *stream = inStream .Detach(); + return S_OK; + } + + CExtentsStream *extentStreamSpec = new CExtentsStream(); + CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; + + extentStreamSpec->Stream = _inStream; + + UInt64 virtOffset = 0; + for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++) + { + const CMyExtent &extent = item.Extents[extentIndex]; + UInt32 len = extent.GetLen(); + if (len == 0) + continue; + if (size < len) + return S_FALSE; + + int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; + UInt32 logBlockNumber = extent.Pos; + const CPartition &partition = _archive.Partitions[partitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) + + (UInt64)logBlockNumber * vol.BlockSize; + + CSeekExtent se; + se.Phy = offset; + se.Virt = virtOffset; + virtOffset += len; + extentStreamSpec->Extents.Add(se); + + size -= len; + } + if (size != 0) + return S_FALSE; + CSeekExtent se; + se.Phy = 0; + se.Virt = virtOffset; + extentStreamSpec->Extents.Add(se); + extentStreamSpec->Init(); + *stream = extentStream.Detach(); + return S_OK; +} + STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { @@ -307,7 +433,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -316,20 +441,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - CUdfInStream *udfInStreamSpec = new CUdfInStream(); - CMyComPtr<ISequentialInStream> udfInStream = udfInStreamSpec; - - udfInStreamSpec->_archive = &_archive; - udfInStreamSpec->_stream = _inStream; - - CDummyOutStream *outStreamSpec = new CDummyOutStream; + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); - currentItemSize = 0; CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : @@ -349,24 +467,28 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - currentItemSize = item.Size; + currentTotalSize += item.Size; - if (!testMode && (!realOutStream)) + if (!testMode && !realOutStream) continue; - RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - outStreamSpec->Init(); - Int32 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - if (item.IsRecAndAlloc() && item.CheckChunkSizes() && _archive.CheckItemExtents(ref2.Vol, item)) + outStreamSpec->Init(item.Size); + Int32 opRes; + CMyComPtr<ISequentialInStream> udfInStream; + HRESULT res = GetStream(index, &udfInStream); + if (res == E_NOTIMPL) + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else if (res != S_OK) + opRes = NArchive::NExtract::NOperationResult::kDataError; + else { - udfInStreamSpec->_ref2 = ref2; - udfInStreamSpec->Init(item.Size); RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress)); - opRes = (outStreamSpec->GetSize() == currentItemSize) ? - NArchive::NExtract::NOperationResult::kOK: - NArchive::NExtract::NOperationResult::kDataError; + opRes = outStreamSpec->IsFinishedOK() ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError; } outStreamSpec->ReleaseStream(); RINOK(extractCallback->SetOperationResult(opRes)); diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h index ceab85ae..63f859af 100755 --- a/CPP/7zip/Archive/Udf/UdfHandler.h +++ b/CPP/7zip/Archive/Udf/UdfHandler.h @@ -20,14 +20,16 @@ struct CRef2 class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { CMyComPtr<IInStream> _inStream; CInArchive _archive; CRecordVector<CRef2> _refs2; public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 75a0c333..d2f9e731 100755 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -2,14 +2,11 @@ #include "StdAfx.h" -#include "UdfIn.h" +#include "../../../../C/CpuArch.h" #include "../../Common/StreamUtils.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "UdfIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) @@ -580,11 +577,16 @@ HRESULT CInArchive::Open2() UInt64 fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - const int kSecLogSizeMax = 11; - const int kSecLogSizeMin = 8; + // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11. + const int kSecLogSizeMax = 12; Byte buf[1 << kSecLogSizeMax]; - for (SecLogSize = kSecLogSizeMax; SecLogSize >= kSecLogSizeMin; SecLogSize -= 3) + Byte kSizesLog[] = { 11, 8, 12 }; + + for (int i = 0;; i++) { + if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0])) + return S_FALSE; + SecLogSize = kSizesLog[i]; Int32 bufSize = 1 << SecLogSize; if (bufSize > fileSize) return S_FALSE; @@ -595,8 +597,8 @@ HRESULT CInArchive::Open2() if (tag.Id == DESC_TYPE_AnchorVolPtr) break; } - if (SecLogSize < kSecLogSizeMin) - return S_FALSE; + if (SecLogSize == 12) + SecLogSize = 11; CExtent extentVDS; extentVDS.Parse(buf + 16); diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp new file mode 100755 index 00000000..5fc2c918 --- /dev/null +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -0,0 +1,731 @@ +// VhdHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +using namespace NWindows; + +namespace NArchive { +namespace NVhd { + +static const UInt32 kUnusedBlock = 0xFFFFFFFF; + +static const UInt32 kDiskType_Fixed = 2; +static const UInt32 kDiskType_Dynamic = 3; +static const UInt32 kDiskType_Diff = 4; + +static const char *kDiskTypes[] = +{ + "0", + "1", + "Fixed", + "Dynamic", + "Differencing" +}; + +struct CFooter +{ + // UInt32 Features; + // UInt32 FormatVersion; + UInt64 DataOffset; + UInt32 CTime; + UInt32 CreatorApp; + UInt32 CreatorVersion; + UInt32 CreatorHostOS; + // UInt64 OriginalSize; + UInt64 CurrentSize; + UInt32 DiskGeometry; + UInt32 Type; + Byte Id[16]; + Byte SavedState; + + bool IsFixed() const { return Type == kDiskType_Fixed; } + bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + UInt32 NumCyls() const { return DiskGeometry >> 16; } + UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; } + UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; } + AString GetTypeString() const; + bool Parse(const Byte *p); +}; + +AString CFooter::GetTypeString() const +{ + if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0])) + return kDiskTypes[Type]; + char s[16]; + ConvertUInt32ToString(Type, s); + return s; +} + +static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset) +{ + UInt32 sum = 0; + unsigned i; + for (i = 0; i < checkSumOffset; i++) + sum += p[i]; + for (i = checkSumOffset + 4; i < size; i++) + sum += p[i]; + if (~sum != Get32(p + checkSumOffset)) + return false; + for (i = zeroOffset; i < size; i++) + if (p[i] != 0) + return false; + return true; +} + +bool CFooter::Parse(const Byte *p) +{ + if (memcmp(p, "conectix", 8) != 0) + return false; + // G32(p + 0x08, Features); + // G32(p + 0x0C, FormatVersion); + G64(p + 0x10, DataOffset); + G32(p + 0x18, CTime); + G32(p + 0x1C, CreatorApp); + G32(p + 0x20, CreatorVersion); + G32(p + 0x24, CreatorHostOS); + // G64(p + 0x28, OriginalSize); + G64(p + 0x30, CurrentSize); + G32(p + 0x38, DiskGeometry); + G32(p + 0x3C, Type); + memcpy(Id, p + 0x44, 16); + SavedState = p[0x54]; + return CheckBlock(p, 512, 0x40, 0x55); +} + +/* +struct CParentLocatorEntry +{ + UInt32 Code; + UInt32 DataSpace; + UInt32 DataLen; + UInt64 DataOffset; + + bool Parse(const Byte *p); +}; +bool CParentLocatorEntry::Parse(const Byte *p) +{ + G32(p + 0x00, Code); + G32(p + 0x04, DataSpace); + G32(p + 0x08, DataLen); + G32(p + 0x10, DataOffset); + return (Get32(p + 0x0C) == 0); // Resrved +} +*/ + +struct CDynHeader +{ + // UInt64 DataOffset; + UInt64 TableOffset; + // UInt32 HeaderVersion; + UInt32 NumBlocks; + int BlockSizeLog; + UInt32 ParentTime; + Byte ParentId[16]; + UString ParentName; + // CParentLocatorEntry ParentLocators[8]; + + bool Parse(const Byte *p); + UInt32 NumBitMapSectors() const + { + UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9)); + return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8); + } +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CDynHeader::Parse(const Byte *p) +{ + if (memcmp(p, "cxsparse", 8) != 0) + return false; + // G64(p + 0x08, DataOffset); + G64(p + 0x10, TableOffset); + // G32(p + 0x18, HeaderVersion); + G32(p + 0x1C, NumBlocks); + BlockSizeLog = GetLog(Get32(p + 0x20)); + if (BlockSizeLog < 9 || BlockSizeLog > 30) + return false; + G32(p + 0x38, ParentTime); + if (Get32(p + 0x3C) != 0) // reserved + return false; + memcpy(ParentId, p + 0x28, 16); + { + const int kNameLength = 256; + wchar_t *s = ParentName.GetBuffer(kNameLength); + for (unsigned i = 0; i < kNameLength; i++) + s[i] = Get16(p + 0x40 + i * 2); + s[kNameLength] = 0; + ParentName.ReleaseBuffer(); + } + /* + for (int i = 0; i < 8; i++) + if (!ParentLocators[i].Parse(p + 0x240 + i * 24)) + return false; + */ + return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24); +} + +class CHandler: + public IInStream, + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _phyPos; + UInt64 _phyLimit; + + CFooter Footer; + CDynHeader Dyn; + CRecordVector<UInt32> Bat; + CByteBuffer BitMap; + UInt32 BitMapTag; + UInt32 NumUsedBlocks; + CMyComPtr<IInStream> Stream; + CMyComPtr<IInStream> ParentStream; + CHandler *Parent; + + HRESULT Seek(UInt64 offset); + HRESULT InitAndSeek(); + HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); + + bool NeedParent() const { return Footer.Type == kDiskType_Diff; } + UInt64 GetSize() const { return Footer.CurrentSize; } + UInt64 GetPackSize() const + { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; } + + UString GetParentName() const + { + const CHandler *p = this; + UString res; + while (p && p->NeedParent()) + { + if (!res.IsEmpty()) + res += L" -> "; + res += p->Dyn.ParentName; + p = p->Parent; + } + return res; + } + + bool IsOK() const + { + const CHandler *p = this; + while (p->NeedParent()) + { + p = p->Parent; + if (p == 0) + return false; + } + return true; + } + + HRESULT Open3(); + HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level); + +public: + MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } + +HRESULT CHandler::InitAndSeek() +{ + if (ParentStream) + { + RINOK(Parent->InitAndSeek()); + } + _virtPos = _phyPos = 0; + BitMapTag = kUnusedBlock; + BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9); + return Seek(0); +} + +HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) +{ + if (offset + size > _phyLimit) + return S_FALSE; + if (offset != _phyPos) + { + _phyPos = offset; + RINOK(Seek(offset)); + } + HRESULT res = ReadStream_FALSE(Stream, data, size); + _phyPos += size; + return res; +} + +HRESULT CHandler::Open3() +{ + RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos)); + if (_phyPos < 512) + return S_FALSE; + const UInt32 kDynSize = 1024; + Byte buf[kDynSize]; + + _phyLimit = _phyPos; + RINOK(ReadPhy(_phyLimit - 512, buf, 512)); + if (!Footer.Parse(buf)) + return S_FALSE; + _phyLimit -= 512; + + if (!Footer.ThereIsDynamic()) + return S_OK; + + RINOK(ReadPhy(0, buf + 512, 512)); + if (memcmp(buf, buf + 512, 512) != 0) + return S_FALSE; + + RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize)); + if (!Dyn.Parse(buf)) + return S_FALSE; + + if (Dyn.NumBlocks >= (UInt32)1 << 31) + return S_FALSE; + if (GetSize() != ((UInt64)Dyn.NumBlocks << Dyn.BlockSizeLog)) + return S_FALSE; + + Bat.Reserve(Dyn.NumBlocks); + while ((UInt32)Bat.Size() < Dyn.NumBlocks) + { + RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512)); + for (UInt32 j = 0; j < 512; j += 4) + { + UInt32 v = Get32(buf + j); + if (v != kUnusedBlock) + NumUsedBlocks++; + Bat.Add(v); + if ((UInt32)Bat.Size() >= Dyn.NumBlocks) + break; + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= GetSize()) + return (GetSize() == _virtPos) ? S_OK: E_FAIL; + if (size == 0) + return S_OK; + UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog); + UInt32 blockSectIndex = Bat[blockIndex]; + UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog; + UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + size = MyMin(blockSize - offsetInBlock, size); + + HRESULT res = S_OK; + if (blockSectIndex == kUnusedBlock) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos, STREAM_SEEK_SET, NULL)); + res = ParentStream->Read(data, size, &size); + } + else + memset(data, 0, size); + } + else + { + UInt64 newPos = (UInt64)blockSectIndex << 9; + if (BitMapTag != blockIndex) + { + RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity())); + BitMapTag = blockIndex; + } + RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size)); + for (UInt32 cur = 0; cur < size;) + { + UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur); + UInt32 bmi = offsetInBlock >> 9; + if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos + cur, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem)); + } + else + { + const Byte *p = (const Byte *)data + cur; + for (UInt32 i = 0; i < rem; i++) + if (p[i] != 0) + return S_FALSE; + } + } + offsetInBlock += rem; + cur += rem; + } + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = GetSize() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +enum +{ + kpidParent = kpidUserDefined, + kpidSavedState +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidClusterSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { L"Parent", kpidParent, VT_BSTR}, + { NULL, kpidCreatorApp, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR}, + { L"Saved State", kpidSavedState, VT_BOOL}, + { NULL, kpidId, VT_BSTR} + }; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME} + + /* + { NULL, kpidNumCyls, VT_UI4}, + { NULL, kpidNumHeads, VT_UI4}, + { NULL, kpidSectorsPerTrack, VT_UI4} + */ +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +// VHD start time: 2000-01-01 +static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4); + +static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop) +{ + FILETIME ft, utc; + UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); + // specification says that it's UTC time, but Virtual PC 6 writes local time. Why? + LocalFileTimeToFileTime(&ft, &utc); + prop = utc; +} + +static void StringToAString(char *dest, UInt32 s) +{ + for (int i = 24; i >= 0; i -= 8) + { + Byte b = (Byte)((s >> i) & 0xFF); + if (b < 0x20 || b > 0x7F) + break; + *dest++ = b; + } + *dest = 0; +} + +static void ConvertByteToHex(unsigned value, char *s) +{ + for (int i = 0; i < 2; i++) + { + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break; + case kpidMethod: + { + AString s = Footer.GetTypeString(); + if (NeedParent()) + { + s += " -> "; + const CHandler *p = this; + while (p != 0 && p->NeedParent()) + p = p->Parent; + if (p == 0) + s += '?'; + else + s += p->Footer.GetTypeString(); + } + prop = s; + break; + } + case kpidCreatorApp: + { + char s[16]; + StringToAString(s, Footer.CreatorApp); + AString res = s; + res.Trim(); + ConvertUInt32ToString(Footer.CreatorVersion >> 16, s); + res += ' '; + res += s; + res += '.'; + ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s); + res += s; + prop = res; + break; + } + case kpidHostOS: + { + if (Footer.CreatorHostOS == 0x5769326b) + prop = "Windows"; + else + { + char s[16]; + StringToAString(s, Footer.CreatorHostOS); + prop = s; + } + break; + } + case kpidId: + { + char s[32 + 4]; + for (int i = 0; i < 16; i++) + ConvertByteToHex(Footer.Id[i], s + i * 2); + s[32] = 0; + prop = s; + break; + } + case kpidSavedState: prop = Footer.SavedState ? true : false; break; + case kpidParent: if (NeedParent()) prop = GetParentName(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level) +{ + Close(); + Stream = stream; + if (level > 32) + return S_FALSE; + RINOK(Open3()); + if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0) + return S_FALSE; + if (Footer.Type != kDiskType_Diff) + return S_OK; + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; + if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK) + return S_FALSE; + CMyComPtr<IInStream> nextStream; + HRESULT res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream); + if (res == S_FALSE) + return S_OK; + RINOK(res); + + Parent = new CHandler; + ParentStream = Parent; + return Parent->Open2(nextStream, this, openArchiveCallback, level + 1); +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * openArchiveCallback) +{ + COM_TRY_BEGIN + { + HRESULT res; + try + { + res = Open2(stream, NULL, openArchiveCallback, 0); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + Bat.Clear(); + NumUsedBlocks = 0; + Parent = 0; + Stream.Release(); + ParentStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + switch(propID) + { + case kpidSize: prop = GetSize(); break; + case kpidPackSize: prop = GetPackSize(); break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + /* + case kpidNumCyls: prop = Footer.NumCyls(); break; + case kpidNumHeads: prop = Footer.NumHeads(); break; + case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == UInt32(-1)) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + + bool testMode = (_aTestMode != 0); + + RINOK(extractCallback->SetTotal(GetSize())); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) + return S_OK; + RINOK(extractCallback->PrepareOperation(askMode)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + int res = NArchive::NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + HRESULT hres = GetStream(0, &inStream); + if (hres == S_FALSE) + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres == S_OK) + { + if (copyCoderSpec->TotalSize == GetSize()) + res = NArchive::NExtract::NOperationResult::kOK; + } + else + { + if (hres != S_FALSE) + { + RINOK(hres); + } + } + } + outStream.Release(); + return extractCallback->SetOperationResult(res); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + if (Footer.IsFixed()) + { + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->SetStream(Stream); + streamSpec->InitAndSeek(0, GetSize()); + RINOK(streamSpec->SeekToStart()); + *stream = streamTemp.Detach(); + return S_OK; + } + if (!Footer.ThereIsDynamic() || !IsOK()) + return S_FALSE; + CMyComPtr<ISequentialInStream> streamTemp = this; + RINOK(InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"VHD", L"vhd", L".mbr", 0xDC, { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 }, 10, false, CreateArc, 0 }; + +REGISTER_ARC(Vhd) + +}} diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 121e33ab..90c3c2c2 100755 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -2,7 +2,8 @@ #include "StdAfx.h" -#include "Common/MyCom.h" +#include "../../../../C/CpuArch.h" + #include "Common/IntToString.h" #include "../../Common/StreamUtils.h" @@ -11,8 +12,6 @@ #include "../Common/OutStreamWithSha1.h" -#include "../../../../C/CpuArch.h" - #include "WimIn.h" #define Get16(p) GetUi16(p) @@ -354,7 +353,7 @@ static HRESULT ParseDir(const Byte *base, size_t size, sum += len; pos += 8; } - pos += sum; // skeep security descriptors + pos += sum; // skip security descriptors while ((pos & 7) != 0) pos++; if (pos != totalLength) @@ -498,8 +497,8 @@ HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDa RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash)); if (memcmp(hash, si.Hash, kHashSize) != 0) return S_FALSE; - wchar_t sz[32]; - ConvertUInt64ToString(imageIndex++, sz); + wchar_t sz[16]; + ConvertUInt32ToString(imageIndex++, sz); UString s = sz; s += WCHAR_PATH_SEPARATOR; RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items)); diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp new file mode 100755 index 00000000..116e96b6 --- /dev/null +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -0,0 +1,714 @@ +// XzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/XzCrc64.h" +#include "../../../C/XzEnc.h" + +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" + +#include "../ICoder.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "IArchive.h" + +#include "Common/HandlerOut.h" + +using namespace NWindows; + +namespace NCompress { +namespace NLzma2 { + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); + +}} + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +namespace NArchive { +namespace NXz { + +struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + #ifndef EXTRACT_ONLY + public IOutArchive, + public ISetProperties, + public COutHandler, + #endif + public CMyUnknownImp +{ + Int64 _startPosition; + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numBlocks; + AString _methodsString; + bool _useSeq; + UInt64 _unpackSizeDefined; + UInt64 _packSizeDefined; + + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + + UInt32 _crcSize; + + void Init() + { + _crcSize = 4; + COutHandler::Init(); + } + + HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutArchive) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + #endif + + CHandler(); +}; + +CHandler::CHandler() +{ + Init(); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static inline void AddHexToString(AString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} + +static AString ConvertUInt32ToString(UInt32 value) +{ + char temp[32]; + ::ConvertUInt32ToString(value, temp); + return temp; +} + +static AString Lzma2PropToString(int prop) +{ + if ((prop & 1) == 0) + return ConvertUInt32ToString(prop / 2 + 12); + AString res; + char c; + + UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1); + + if (prop > 17) + { + res = ConvertUInt32ToString(size >> 10); + c = 'm'; + } + else + { + res = ConvertUInt32ToString(size); + c = 'k'; + } + return res + c; +} + +struct CMethodNamePair +{ + UInt32 Id; + const char *Name; +}; + +static CMethodNamePair g_NamePairs[] = +{ + { XZ_ID_Subblock, "SB" }, + { XZ_ID_Delta, "Delta" }, + { XZ_ID_X86, "x86" }, + { XZ_ID_PPC, "PPC" }, + { XZ_ID_IA64, "IA64" }, + { XZ_ID_ARM, "ARM" }, + { XZ_ID_ARMT, "ARMT" }, + { XZ_ID_SPARC, "SPARC" }, + { XZ_ID_LZMA2, "LZMA2" } +}; + +static AString GetMethodString(const CXzFilter &f) +{ + AString s; + + for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + if (g_NamePairs[i].Id == f.id) + s = g_NamePairs[i].Name; + if (s.IsEmpty()) + { + char temp[32]; + ::ConvertUInt64ToString(f.id, temp); + s = temp; + } + + if (f.propsSize > 0) + { + s += ':'; + if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) + s += Lzma2PropToString(f.props[0]); + else if (f.id == XZ_ID_Delta && f.propsSize == 1) + s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + else + { + s += '['; + for (UInt32 bi = 0; bi < f.propsSize; bi++) + AddHexToString(s, f.props[bi]); + s += ']'; + } + } + return s; +} + +static void AddString(AString &dest, const AString &src) +{ + if (!dest.IsEmpty()) + dest += ' '; + dest += src; +} + +static const char *kChecks[] = +{ + "NoCheck", + "CRC32", + NULL, + NULL, + "CRC64", + NULL, + NULL, + NULL, + NULL, + NULL, + "SHA256", + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static AString GetCheckString(const CXzs &xzs) +{ + size_t i; + UInt32 mask = 0; + for (i = 0; i < xzs.num; i++) + mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); + AString s; + for (i = 0; i <= XZ_CHECK_MASK; i++) + if (((mask >> i) & 1) != 0) + { + AString s2; + if (kChecks[i]) + s2 = kChecks[i]; + else + s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + AddString(s, s2); + } + return s; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +struct COpenCallbackWrap +{ + ICompressProgress p; + IArchiveOpenCallback *OpenCallback; + HRESULT Res; + COpenCallbackWrap(IArchiveOpenCallback *progress); +}; + +static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */) +{ + COpenCallbackWrap *p = (COpenCallbackWrap *)pp; + p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); + return (SRes)p->Res; +} + +COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) +{ + p.Progress = OpenCallbackProgress; + OpenCallback = callback; + Res = SZ_OK; +} + +struct CXzsCPP +{ + CXzs p; + CXzsCPP() { Xzs_Construct(&p); } + ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } +}; + +HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) +{ + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); + RINOK(callback->SetTotal(NULL, &_packSize)); + + CXzsCPP xzs; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + if (res == SZ_OK) + { + _packSize -= _startPosition; + _unpackSize = Xzs_GetUnpackSize(&xzs.p); + _unpackSizeDefined = _packSizeDefined = true; + _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); + + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + + if (res2 == SZ_OK) + { + CXzBlock block; + Bool isIndex; + UInt32 headerSizeRes; + res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + if (res2 == SZ_OK && !isIndex) + { + int numFilters = XzBlock_GetNumFilters(&block); + for (int i = 0; i < numFilters; i++) + AddString(_methodsString, GetMethodString(block.filters[i])); + } + } + AddString(_methodsString, GetCheckString(xzs.p)); + } + + if (res != SZ_OK || _startPosition != 0) + { + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res2 == SZ_OK) + { + res = res2; + _startPosition = 0; + _useSeq = True; + _unpackSizeDefined = _packSizeDefined = false; + } + } + if (res == SZ_ERROR_NO_ARCHIVE) + return S_FALSE; + RINOK(SResToHRESULT(res)); + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + Close(); + return Open2(inStream, callback); + } + catch(...) { return S_FALSE; } + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _numBlocks = 0; + _useSeq = true; + _unpackSizeDefined = _packSizeDefined = false; + _methodsString.Empty(); + _stream.Release(); + _seqStream.Release(); + return S_OK; +} + +class CSeekToSeqStream: + public IInStream, + public CMyUnknownImp +{ +public: + CMyComPtr<ISequentialInStream> Stream; + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return Stream->Read(data, size, processedSize); +} + +STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } + +struct CXzUnpackerCPP +{ + Byte *InBuf; + Byte *OutBuf; + CXzUnpacker p; + CXzUnpackerCPP(): InBuf(0), OutBuf(0) {} + ~CXzUnpackerCPP() + { + XzUnpacker_Free(&p); + MyFree(InBuf); + MyFree(OutBuf); + } +}; + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == UInt32(-1)); + if (!allFilesMode) + { + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + } + + bool testMode = (_aTestMode != 0); + + extractCallback->SetTotal(_packSize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + CCompressProgressWrap progressWrap(progress); + + SRes res; + + const UInt32 kInBufSize = 1 << 15; + const UInt32 kOutBufSize = 1 << 21; + + UInt32 inPos = 0; + UInt32 inSize = 0; + UInt32 outPos = 0; + CXzUnpackerCPP xzu; + res = XzUnpacker_Create(&xzu.p, &g_Alloc); + if (res == SZ_OK) + { + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + if (xzu.InBuf == 0 || xzu.OutBuf == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + for (;;) + { + if (inPos == inSize) + { + inPos = inSize = 0; + RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + } + + SizeT inLen = inSize - inPos; + SizeT outLen = kOutBufSize - outPos; + ECoderStatus status; + res = XzUnpacker_Code(&xzu.p, + xzu.OutBuf + outPos, &outLen, + xzu.InBuf + inPos, &inLen, + (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); + + // printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen); + + inPos += (UInt32)inLen; + outPos += (UInt32)outLen; + lps->InSize += inLen; + lps->OutSize += outLen; + + bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + + if (outPos == kOutBufSize || finished) + { + if (realOutStream && outPos > 0) + { + RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + } + outPos = 0; + } + if (finished) + { + _packSize = lps->InSize; + _unpackSize = lps->OutSize; + _packSizeDefined = _unpackSizeDefined = true; + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + if (XzUnpacker_IsStreamWasFinished(&xzu.p)) + _packSize -= xzu.p.padSize; + else + res = SZ_ERROR_DATA; + } + else + res = SZ_ERROR_DATA; + } + break; + } + RINOK(lps->SetCur()); + } + + Int32 opRes; + switch(res) + { + case SZ_OK: + opRes = NArchive::NExtract::NOperationResult::kOK; break; + case SZ_ERROR_UNSUPPORTED: + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; + case SZ_ERROR_CRC: + opRes = NArchive::NExtract::NOperationResult::kCRCError; break; + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + opRes = NArchive::NExtract::NOperationResult::kDataError; break; + default: + return SResToHRESULT(res); + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + return S_OK; + COM_TRY_END +} + +#ifndef EXTRACT_ONLY + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + CSeqOutStreamWrap seqOutStream(outStream); + + if (numItems == 0) + { + SRes res = Xz_EncodeEmpty(&seqOutStream.p); + return SResToHRESULT(res); + } + + if (numItems != 1) + return E_INVALIDARG; + + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); + + if (IntToBool(newProps)) + { + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); + if (prop.vt != VT_EMPTY) + if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + } + + if (IntToBool(newData)) + { + { + UInt64 size; + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + RINOK(updateCallback->SetTotal(size)); + } + + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + lzma2Props.lzmaProps.level = _level; + + CMyComPtr<ISequentialInStream> fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSeqInStreamWrap seqInStream(fileInStream); + + for (int i = 0; i < _methods.Size(); i++) + { + COneMethodInfo &m = _methods[i]; + SetCompressionMethod2(m + #ifdef COMPRESS_MT + , _numThreads + #endif + ); + if (m.IsLzma()) + { + for (int j = 0; j < m.Props.Size(); j++) + { + const CProp &prop = m.Props[j]; + RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); + } + } + } + + #ifdef COMPRESS_MT + lzma2Props.numTotalThreads = _numThreads; + #endif + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CCompressProgressWrap progressWrap(progress); + SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p); + if (res == SZ_OK) + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + return SResToHRESULT(res); + } + if (indexInArchive != 0) + return E_INVALIDARG; + if (_stream) + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, 0); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + COM_TRY_BEGIN + BeforeSetProperty(); + for (int i = 0; i < numProps; i++) + { + RINOK(SetProperty(names[i], values[i])); + } + return S_OK; + COM_TRY_END +} + +#endif + +static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(xz) + +}} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 212a8b4b..9157deeb 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/7zCrc.h" -} #include "Windows/PropVariant.h" diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 25cbd886..547ecf92 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -3,16 +3,13 @@ #include "StdAfx.h" #include "Common/ComTry.h" -#include "Common/Defs.h" #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../IPassword.h" -#include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" @@ -37,38 +34,34 @@ using namespace NWindows; namespace NArchive { namespace NZip { -// static const CMethodId kMethodId_Store = 0; static const CMethodId kMethodId_ZipBase = 0x040100; static const CMethodId kMethodId_BZip2 = 0x040202; -const wchar_t *kHostOS[] = +static const char *kHostOS[] = { - L"FAT", - L"AMIGA", - L"VMS", - L"Unix", - L"VM/CMS", - L"Atari", - L"HPFS", - L"Macintosh", - L"Z-System", - L"CP/M", - L"TOPS-20", - L"NTFS", - L"SMS/QDOS", - L"Acorn", - L"VFAT", - L"MVS", - L"BeOS", - L"Tandem", - L"OS/400", - L"OS/X" + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" }; - -static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); - -static const wchar_t *kUnknownOS = L"Unknown"; +static const char *kUnknownOS = "Unknown"; STATPROPSTG kProps[] = { @@ -93,50 +86,50 @@ STATPROPSTG kProps[] = // { NULL, kpidUnpackVer, VT_UI1}, }; -const wchar_t *kMethods[] = +const char *kMethods[] = { - L"Store", - L"Shrink", - L"Reduced1", - L"Reduced2", - L"Reduced2", - L"Reduced3", - L"Implode", - L"Tokenizing", - L"Deflate", - L"Deflate64", - L"PKImploding" + "Store", + "Shrink", + "Reduced1", + "Reduced2", + "Reduced2", + "Reduced3", + "Implode", + "Tokenizing", + "Deflate", + "Deflate64", + "PKImploding" }; const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); -const wchar_t *kBZip2Method = L"BZip2"; -const wchar_t *kLZMAMethod = L"LZMA"; -const wchar_t *kJpegMethod = L"Jpeg"; -const wchar_t *kWavPackMethod = L"WavPack"; -const wchar_t *kPPMdMethod = L"PPMd"; -const wchar_t *kAESMethod = L"AES"; -const wchar_t *kZipCryptoMethod = L"ZipCrypto"; -const wchar_t *kStrongCryptoMethod = L"StrongCrypto"; +const char *kBZip2Method = "BZip2"; +const char *kLZMAMethod = "LZMA"; +const char *kJpegMethod = "Jpeg"; +const char *kWavPackMethod = "WavPack"; +const char *kPPMdMethod = "PPMd"; +const char *kAESMethod = "AES"; +const char *kZipCryptoMethod = "ZipCrypto"; +const char *kStrongCryptoMethod = "StrongCrypto"; struct CStrongCryptoPair { UInt16 Id; - const wchar_t *Name; + const char *Name; }; CStrongCryptoPair g_StrongCryptoPairs[] = { - { NStrongCryptoFlags::kDES, L"DES" }, - { NStrongCryptoFlags::kRC2old, L"RC2a" }, - { NStrongCryptoFlags::k3DES168, L"3DES-168" }, - { NStrongCryptoFlags::k3DES112, L"3DES-112" }, - { NStrongCryptoFlags::kAES128, L"pkAES-128" }, - { NStrongCryptoFlags::kAES192, L"pkAES-192" }, - { NStrongCryptoFlags::kAES256, L"pkAES-256" }, - { NStrongCryptoFlags::kRC2, L"RC2" }, - { NStrongCryptoFlags::kBlowfish, L"Blowfish" }, - { NStrongCryptoFlags::kTwofish, L"Twofish" }, - { NStrongCryptoFlags::kRC4, L"RC4" } + { NStrongCryptoFlags::kDES, "DES" }, + { NStrongCryptoFlags::kRC2old, "RC2a" }, + { NStrongCryptoFlags::k3DES168, "3DES-168" }, + { NStrongCryptoFlags::k3DES112, "3DES-112" }, + { NStrongCryptoFlags::kAES128, "pkAES-128" }, + { NStrongCryptoFlags::kAES192, "pkAES-192" }, + { NStrongCryptoFlags::kAES256, "pkAES-256" }, + { NStrongCryptoFlags::kRC2, "RC2" }, + { NStrongCryptoFlags::kBlowfish, "Blowfish" }, + { NStrongCryptoFlags::kTwofish, "Twofish" }, + { NStrongCryptoFlags::kRC4, "RC4" } }; STATPROPSTG kArcProps[] = @@ -202,9 +195,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPackSize: prop = item.PackSize; break; case kpidTimeType: { - FILETIME utcFileTime; - if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kTagTime, utcFileTime)) + FILETIME ft; + UInt32 unixTime; + if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) prop = (UInt32)NFileTimeType::kWindows; + else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + prop = (UInt32)NFileTimeType::kUnix; + else + prop = (UInt32)NFileTimeType::kDOS; break; } case kpidCTime: @@ -223,19 +221,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidMTime: { - FILETIME utcFileTime; - if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utcFileTime)) + FILETIME utc; + if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { - FILETIME localFileTime; - if (NTime::DosTimeToFileTime(item.Time, localFileTime)) + UInt32 unixTime; + if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else { - if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + FILETIME localFileTime; + if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || + !LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; } - else - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; } - prop = utcFileTime; + prop = utc; break; } case kpidAttrib: prop = item.GetWinAttributes(); break; @@ -245,7 +245,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { UInt16 methodId = item.CompressionMethod; - UString method; + AString method; if (item.IsEncrypted()) { if (methodId == NFileHeader::NCompressionMethod::kWzAES) @@ -254,11 +254,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val CWzAesExtraField aesField; if (item.CentralExtra.GetWzAesField(aesField)) { - method += L"-"; - wchar_t s[32]; + method += '-'; + char s[32]; ConvertUInt64ToString((aesField.Strength + 1) * 64 , s); method += s; - method += L" "; + method += ' '; methodId = aesField.Method; } } @@ -286,7 +286,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else method += kZipCryptoMethod; - method += L" "; + method += ' '; } } if (methodId < kNumMethods) @@ -296,7 +296,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case NFileHeader::NCompressionMethod::kLZMA: method += kLZMAMethod; if (item.IsLzmaEOS()) - method += L":EOS"; + method += ":EOS"; break; case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break; case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break; @@ -304,7 +304,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break; default: { - wchar_t s[32]; + char s[32]; ConvertUInt64ToString(methodId, s); method += s; } @@ -313,7 +313,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } case kpidHostOS: - prop = (item.MadeByVersion.HostOS < kNumHostOSes) ? + prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ? (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; break; } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index e974079d..4839f554 100755 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -93,6 +93,7 @@ namespace NFileHeader kZip64 = 0x01, kNTFS = 0x0A, kStrongEncrypt = 0x17, + kUnixTime = 0x5455, kWzAES = 0x9901 }; } @@ -103,8 +104,18 @@ namespace NFileHeader enum { kMTime = 0, - kATime = 1, - kCTime = 2 + kATime, + kCTime + }; + } + + namespace NUnixTime + { + enum + { + kMTime = 0, + kATime, + kCTime }; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 5fb53ef2..e396fe5b 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -2,17 +2,14 @@ #include "StdAfx.h" -#include "ZipIn.h" -#include "Windows/Defs.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" + #include "Common/DynamicBuffer.h" + #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "ZipIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) @@ -21,10 +18,9 @@ extern "C" namespace NArchive { namespace NZip { -// static const char kEndOfString = '\0'; - HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { + _inBufMode = false; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); m_Position = m_StreamStartPosition; @@ -36,6 +32,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) void CInArchive::Close() { + _inBuffer.ReleaseStream(); m_Stream.Release(); } @@ -117,13 +114,26 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHea HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { size_t realProcessedSize = size; - HRESULT result = ReadStream(m_Stream, data, &realProcessedSize); + HRESULT result = S_OK; + if (_inBufMode) + { + try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); } + catch (const CInBufferException &e) { return e.ErrorCode; } + } + else + result = ReadStream(m_Stream, data, &realProcessedSize); if (processedSize != NULL) *processedSize = (UInt32)realProcessedSize; m_Position += realProcessedSize; return result; } +void CInArchive::Skip(UInt64 num) +{ + for (UInt64 i = 0; i < num; i++) + ReadByte(); +} + void CInArchive::IncreaseRealPosition(UInt64 addValue) { if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) @@ -160,51 +170,42 @@ Byte CInArchive::ReadByte() UInt16 CInArchive::ReadUInt16() { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - value |= (((UInt16)ReadByte()) << (8 * i)); - return value; + Byte buf[2]; + SafeReadBytes(buf, 2); + return Get16(buf); } UInt32 CInArchive::ReadUInt32() { - UInt32 value = 0; - for (int i = 0; i < 4; i++) - value |= (((UInt32)ReadByte()) << (8 * i)); - return value; + Byte buf[4]; + SafeReadBytes(buf, 4); + return Get32(buf); } UInt64 CInArchive::ReadUInt64() { - UInt64 value = 0; - for (int i = 0; i < 8; i++) - value |= (((UInt64)ReadByte()) << (8 * i)); - return value; + Byte buf[8]; + SafeReadBytes(buf, 8); + return Get64(buf); } bool CInArchive::ReadUInt32(UInt32 &value) { - value = 0; - for (int i = 0; i < 4; i++) - { - Byte b; - if (!ReadBytesAndTestSize(&b, 1)) - return false; - value |= (UInt32(b) << (8 * i)); - } + Byte buf[4]; + if (!ReadBytesAndTestSize(buf, 4)) + return false; + value = Get32(buf); return true; } - -AString CInArchive::ReadFileName(UInt32 nameSize) +void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) { if (nameSize == 0) - return AString(); - char *p = m_NameBuffer.GetBuffer(nameSize); + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); SafeReadBytes(p, nameSize); p[nameSize] = 0; - m_NameBuffer.ReleaseBuffer(); - return m_NameBuffer; + dest.ReleaseBuffer(); } void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const @@ -212,38 +213,6 @@ void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const archiveInfo = m_ArchiveInfo; } -/* -void CInArchive::ThrowIncorrectArchiveException() -{ - throw CInArchiveException(CInArchiveException::kIncorrectArchive); -} -*/ - -static UInt32 GetUInt32(const Byte *data) -{ - return - ((UInt32)(Byte)data[0]) | - (((UInt32)(Byte)data[1]) << 8) | - (((UInt32)(Byte)data[2]) << 16) | - (((UInt32)(Byte)data[3]) << 24); -} - -/* -static UInt16 GetUInt16(const Byte *data) -{ - return - ((UInt16)(Byte)data[0]) | - (((UInt16)(Byte)data[1]) << 8); -} -*/ - -static UInt64 GetUInt64(const Byte *data) -{ - return GetUInt32(data) | ((UInt64)GetUInt32(data + 4) << 32); -} - - - void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) { @@ -301,22 +270,26 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, } remain -= dataSize; } - IncreaseRealPosition(remain); + Skip(remain); } HRESULT CInArchive::ReadLocalItem(CItemEx &item) { - item.ExtractVersion.Version = ReadByte(); - item.ExtractVersion.HostOS = ReadByte(); - item.Flags = ReadUInt16(); - item.CompressionMethod = ReadUInt16(); - item.Time = ReadUInt32(); - item.FileCRC = ReadUInt32(); - item.PackSize = ReadUInt32(); - item.UnPackSize = ReadUInt32(); - UInt32 fileNameSize = ReadUInt16(); - item.LocalExtraSize = ReadUInt16(); - item.Name = ReadFileName(fileNameSize); + const int kBufSize = 26; + Byte p[kBufSize]; + SafeReadBytes(p, kBufSize); + + item.ExtractVersion.Version = p[0]; + item.ExtractVersion.HostOS = p[1]; + item.Flags = Get16(p + 2); + item.CompressionMethod = Get16(p + 4); + item.Time = Get32(p + 6); + item.FileCRC = Get32(p + 10); + item.PackSize = Get32(p + 14); + item.UnPackSize = Get32(p + 18); + UInt32 fileNameSize = Get16(p + 22); + item.LocalExtraSize = Get16(p + 24); + ReadFileName(fileNameSize, item.Name); item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize; if (item.LocalExtraSize > 0) { @@ -400,16 +373,16 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) { // descriptorSignature field is Info-ZIP's extension // to Zip specification. - UInt32 descriptorSignature = GetUInt32(buffer + i); + UInt32 descriptorSignature = Get32(buffer + i); // !!!! It must be fixed for Zip64 archives - UInt32 descriptorPackSize = GetUInt32(buffer + i + 8); + UInt32 descriptorPackSize = Get32(buffer + i + 8); if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i) { descriptorWasFound = true; - item.FileCRC = GetUInt32(buffer + i + 4); + item.FileCRC = Get32(buffer + i + 4); item.PackSize = descriptorPackSize; - item.UnPackSize = GetUInt32(buffer + i + 12); + item.UnPackSize = Get32(buffer + i + 12); IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); break; } @@ -487,7 +460,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) item.InternalAttributes = Get16(p + 32); item.ExternalAttributes = Get32(p + 34); item.LocalHeaderPosition = Get32(p + 38); - item.Name = ReadFileName(headerNameSize); + ReadFileName(headerNameSize, item.Name); if (headerExtraSize > 0) { @@ -515,11 +488,11 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) Byte buf[kEcd64Size]; if (!ReadBytesAndTestSize(buf, kEcd64Size)) return S_FALSE; - if (GetUInt32(buf) != NSignature::kZip64EndOfCentralDir) + if (Get32(buf) != NSignature::kZip64EndOfCentralDir) return S_FALSE; - // cdInfo.NumEntries = GetUInt64(buf + 24); - cdInfo.Size = GetUInt64(buf + 40); - cdInfo.Offset = GetUInt64(buf + 48); + // cdInfo.NumEntries = Get64(buf + 24); + cdInfo.Size = Get64(buf + 40); + cdInfo.Offset = Get64(buf + 48); return S_OK; } @@ -540,14 +513,14 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) return S_FALSE; for (int i = (int)(bufSize - kEcdSize); i >= 0; i--) { - if (GetUInt32(buf + i) == NSignature::kEndOfCentralDir) + if (Get32(buf + i) == NSignature::kEndOfCentralDir) { if (i >= kZip64EcdLocatorSize) { const Byte *locator = buf + i - kZip64EcdLocatorSize; - if (GetUInt32(locator) == NSignature::kZip64EndOfCentralDirLocator) + if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator) { - UInt64 ecd64Offset = GetUInt64(locator + 8); + UInt64 ecd64Offset = Get64(locator + 8); if (TryEcd64(ecd64Offset, cdInfo) == S_OK) return S_OK; if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) @@ -557,11 +530,11 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) } } } - if (GetUInt32(buf + i + 4) == 0) + if (Get32(buf + i + 4) == 0) { // cdInfo.NumEntries = GetUInt16(buf + i + 10); - cdInfo.Size = GetUInt32(buf + i + 12); - cdInfo.Offset = GetUInt32(buf + i + 16); + cdInfo.Size = Get32(buf + i + 12); + cdInfo.Offset = Get32(buf + i + 16); UInt64 curPos = endPosition - bufSize + i; UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; if (curPos > cdEnd) @@ -579,6 +552,13 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UI RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); if (m_Position != cdOffset) return S_FALSE; + + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(m_Stream); + _inBuffer.Init(); + _inBufMode = true; + while(m_Position - cdOffset < cdSize) { if (ReadUInt32() != NSignature::kCentralFileHeader) @@ -765,6 +745,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr if (res == S_FALSE) { + _inBufMode = false; m_ArchiveInfo.Base = 0; RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position)); if (m_Position != m_ArchiveInfo.StartPosition) @@ -789,7 +770,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr SafeReadBytes(buf, kBufSize); ecd64.Parse(buf); - IncreaseRealPosition(recordSize - kZip64EcdSize); + Skip(recordSize - kZip64EcdSize); if (!ReadUInt32(m_Signature)) return S_FALSE; if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) @@ -838,6 +819,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr (!items.IsEmpty()))) return S_FALSE; + _inBufMode = false; + _inBuffer.Free(); return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 750095d6..5f4fe143 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -4,8 +4,11 @@ #define __ZIP_IN_H #include "Common/MyCom.h" + #include "../../IStream.h" +#include "../../Common/InBuffer.h" + #include "ZipHeader.h" #include "ZipItemEx.h" @@ -65,13 +68,14 @@ class CInArchive UInt32 m_Signature; UInt64 m_StreamStartPosition; UInt64 m_Position; - AString m_NameBuffer; + + bool _inBufMode; + CInBuffer _inBuffer; HRESULT Seek(UInt64 offset); HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - bool ReadUInt32(UInt32 &signature); - AString ReadFileName(UInt32 nameSize); + void ReadFileName(UInt32 nameSize, AString &dest); HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); bool ReadBytesAndTestSize(void *data, UInt32 size); @@ -81,7 +85,9 @@ class CInArchive UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); + bool ReadUInt32(UInt32 &signature); + void Skip(UInt64 num); void IncreaseRealPosition(UInt64 addValue); void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 03472d85..139b0129 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -51,6 +51,31 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const return false; } +bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const +{ + res = 0; + UInt32 size = (UInt32)Data.GetCapacity(); + if (ID != NFileHeader::NExtraID::kUnixTime || size < 5) + return false; + const Byte *p = (const Byte *)Data; + Byte flags = *p++; + size--; + for (int i = 0; i < 3; i++) + if ((flags & (1 << i)) != 0) + { + if (size < 4) + return false; + if (index == i) + { + res = GetUi32(p); + return true; + } + p += 4; + size -= 4; + } + return false; +} + bool CLocalItem::IsDir() const { return NItemName::HasTailSlash(Name, GetCodePage()); diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index c0f780f8..31f2de73 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -28,6 +28,7 @@ struct CExtraSubBlock UInt16 ID; CByteBuffer Data; bool ExtractNtfsTime(int index, FILETIME &ft) const; + bool ExtractUnixTime(int index, UInt32 &res) const; }; struct CWzAesExtraField @@ -151,6 +152,17 @@ struct CExtraBlock return false; } + bool GetUnixTime(int index, UInt32 &res) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixTime) + return sb.ExtractUnixTime(index, res); + } + return false; + } + /* bool HasStrongCryptoField() const { diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index 12db3e44..2fd36950 100755 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -13,6 +13,6 @@ static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; } #endif static CArcInfo g_ArcInfo = - { L"Zip", L"zip jar xpi", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; + { L"Zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; REGISTER_ARC(Zip) diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 5c7e64db..c76ee488 100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -47,8 +47,7 @@ static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, { CMyComPtr<ISequentialOutStream> outStream; outArchive.CreateStreamForCopying(&outStream); - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, progress); + return NCompress::CopyStream(inStream, outStream, progress); } static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, |