Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive')
-rwxr-xr-xCPP/7zip/Archive/7z/7z.dsp4
-rwxr-xr-xCPP/7zip/Archive/7z/7zEncode.cpp26
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.cpp154
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.h48
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.cpp148
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.h8
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandlerOut.cpp70
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.cpp27
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.h8
-rwxr-xr-xCPP/7zip/Archive/7z/7zOut.cpp10
-rwxr-xr-xCPP/7zip/Archive/7z/7zOut.h8
-rwxr-xr-xCPP/7zip/Archive/7z/7zUpdate.cpp773
-rwxr-xr-xCPP/7zip/Archive/7z/7zUpdate.h10
-rwxr-xr-xCPP/7zip/Archive/7z/makefile2
-rwxr-xr-xCPP/7zip/Archive/ArchiveExports.cpp9
-rwxr-xr-xCPP/7zip/Archive/ArjHandler.cpp25
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Handler.cpp216
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Handler.h68
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp156
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Item.h20
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Update.cpp74
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Update.h26
-rwxr-xr-xCPP/7zip/Archive/BZip2/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/BZip2/bz2Register.cpp18
-rwxr-xr-xCPP/7zip/Archive/Bz2Handler.cpp428
-rwxr-xr-xCPP/7zip/Archive/Cab/CabBlockInStream.cpp3
-rwxr-xr-xCPP/7zip/Archive/Cab/CabIn.cpp6
-rwxr-xr-xCPP/7zip/Archive/Cab/CabIn.h2
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmIn.cpp29
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmIn.h6
-rwxr-xr-xCPP/7zip/Archive/Com/ComHandler.cpp198
-rwxr-xr-xCPP/7zip/Archive/Com/ComHandler.h10
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.cpp130
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.h37
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.cpp119
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.h2
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.h12
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.cpp20
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.h8
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithSha1.cpp20
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithSha1.h8
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHandler.cpp240
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHandler.h30
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHeader.cpp23
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHeader.h70
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioIn.cpp272
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioIn.h41
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioItem.h55
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioRegister.cpp13
-rwxr-xr-xCPP/7zip/Archive/Cpio/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/CpioHandler.cpp625
-rwxr-xr-xCPP/7zip/Archive/DebHandler.cpp91
-rwxr-xr-xCPP/7zip/Archive/DllExports2.cpp3
-rwxr-xr-xCPP/7zip/Archive/ElfHandler.cpp30
-rwxr-xr-xCPP/7zip/Archive/FatHandler.cpp983
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandler.cpp284
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandler.h63
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandlerOut.cpp202
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHeader.cpp20
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHeader.h85
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipIn.cpp119
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipIn.h30
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipItem.h59
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipOut.cpp65
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipOut.h29
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipRegister.cpp18
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipUpdate.cpp112
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipUpdate.h37
-rwxr-xr-xCPP/7zip/Archive/GZip/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/GzHandler.cpp820
-rwxr-xr-xCPP/7zip/Archive/IArchive.h12
-rwxr-xr-xCPP/7zip/Archive/Icons/fat.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/ntfs.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/vhd.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/xar.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/xz.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.cpp57
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.h17
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoIn.cpp21
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoIn.h12
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhCRC.cpp43
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhCRC.h27
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHandler.cpp387
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHandler.h30
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHeader.h19
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhIn.cpp172
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhIn.h29
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhItem.h172
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp27
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h38
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhRegister.cpp13
-rwxr-xr-xCPP/7zip/Archive/Lzh/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/LzhHandler.cpp783
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaArcRegister.cpp14
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp86
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaFiltersDecode.h26
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaHandler.cpp243
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaHandler.h69
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaIn.cpp56
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaIn.h16
-rwxr-xr-xCPP/7zip/Archive/Lzma/LzmaItem.h27
-rwxr-xr-xCPP/7zip/Archive/Lzma/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/LzmaHandler.cpp436
-rwxr-xr-xCPP/7zip/Archive/MachoHandler.cpp38
-rwxr-xr-xCPP/7zip/Archive/MbrHandler.cpp508
-rwxr-xr-xCPP/7zip/Archive/MubHandler.cpp35
-rwxr-xr-xCPP/7zip/Archive/NtfsHandler.cpp1725
-rwxr-xr-xCPP/7zip/Archive/PeHandler.cpp27
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHandler.cpp5
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.cpp8
-rwxr-xr-xCPP/7zip/Archive/Rar/RarVolumeInStream.cpp10
-rwxr-xr-xCPP/7zip/Archive/RpmHandler.cpp128
-rwxr-xr-xCPP/7zip/Archive/Split/SplitHandler.h37
-rwxr-xr-xCPP/7zip/Archive/Split/SplitHandlerOut.cpp102
-rwxr-xr-xCPP/7zip/Archive/Split/SplitRegister.cpp20
-rwxr-xr-xCPP/7zip/Archive/Split/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/SplitHandler.cpp (renamed from CPP/7zip/Archive/Split/SplitHandler.cpp)139
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.cpp193
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.h36
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandlerOut.cpp100
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp23
-rwxr-xr-xCPP/7zip/Archive/Tar/TarItem.h10
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.cpp15
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.cpp23
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.h10
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfHandler.cpp276
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfHandler.h4
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfIn.cpp22
-rwxr-xr-xCPP/7zip/Archive/VhdHandler.cpp731
-rwxr-xr-xCPP/7zip/Archive/Wim/WimIn.cpp11
-rwxr-xr-xCPP/7zip/Archive/XzHandler.cpp714
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.cpp3
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.cpp160
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.h15
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp175
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.h12
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.cpp25
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.h12
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipRegister.cpp2
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.cpp3
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(&currentTotalPacked));
-
- 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(&currentTotalPacked));
+ 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(&currentTotalSize));
+ 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 &param, 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(&currentTotalPacked));
- 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(&currentTotalPacked));
+ 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
new file mode 100755
index 00000000..882753ac
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/fat.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico
new file mode 100755
index 00000000..6b2aeb00
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/ntfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico
new file mode 100755
index 00000000..33bed3c9
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/vhd.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico
index 02707351..281aa7dc 100755
--- a/CPP/7zip/Archive/Icons/xar.ico
+++ b/CPP/7zip/Archive/Icons/xar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico
new file mode 100755
index 00000000..02707351
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/xz.ico
Binary files differ
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, &currentItemUnPacked, 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, &currentItemUnPacked, 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, &currentItemUnPacked, 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, &currentItemUnPacked, 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(&currentTotalSize));
- 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(&currentTotalSize));
- 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(&currentTotalPacked));
+ 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,