9.04 beta

This commit is contained in:
Igor Pavlov
2009-06-02 00:00:00 +00:00
committed by Kornel Lesiński
parent 8874e4fbc9
commit 829409452d
440 changed files with 19803 additions and 9941 deletions
+2 -2
View File
@@ -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"
+14 -14
View File
@@ -1,21 +1,21 @@
// Encode.cpp
// 7zEncode.cpp
#include "StdAfx.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 "7zEncode.h"
#include "7zSpecStream.h"
#include "../../IPassword.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.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;
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;
}
+65 -89
View File
@@ -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)
{
for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
_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()
{
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;
}
}}
+23 -27
View File
@@ -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
{
COutStreamWithCRC *_crcStreamSpec;
CMyComPtr<ISequentialOutStream> _crcStream;
const CArchiveDatabaseEx *_db;
const CBoolVector *_extractStatuses;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
UInt32 _ref2Offset;
UInt32 _startIndex;
int _currentIndex;
bool _testMode;
bool _checkCrc;
bool _fileIsOpen;
UInt64 _rem;
HRESULT OpenFile();
HRESULT CloseFileAndSetResult(Int32 res);
HRESULT CloseFileAndSetResult();
HRESULT ProcessEmptyFiles();
public:
MY_UNKNOWN_IMP
CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
COutStreamWithCRC *_outStreamWithHashSpec;
CMyComPtr<ISequentialOutStream> _outStreamWithHash;
const CArchiveDatabaseEx *_archiveDatabase;
const CBoolVector *_extractStatuses;
UInt32 _startIndex;
UInt32 _ref2Offset;
int _currentIndex;
// UInt64 _currentDataPos;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
bool _testMode;
bool _fileIsOpen;
bool _checkCrc;
UInt64 _filePos;
HRESULT OpenFile();
HRESULT WriteEmptyFiles();
public:
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; }
};
}}
+69 -79
View File
@@ -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)
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)
{
methodsString += L":";
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_PPMD)
*/
}
}
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() >= 5)
{
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);
}
}
else if (coderInfo.MethodID == k_AES)
{
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;
+3 -5
View File
@@ -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
+35 -35
View File
@@ -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);
+12 -15
View File
@@ -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)
+4 -4
View File
@@ -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);
+4 -6
View File
@@ -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)
+4 -4
View File
@@ -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,
File diff suppressed because it is too large Load Diff
+7 -3
View File
@@ -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
+1 -1
View File
@@ -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)
+3 -6
View File
@@ -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"
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)
+17 -8
View File
@@ -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;
-216
View File
@@ -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
}}
-68
View File
@@ -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
-156
View File
@@ -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;
}
}}
-20
View File
@@ -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
-74
View File
@@ -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);
}
}}
-26
View File
@@ -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
-8
View File
@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif
-18
View File
@@ -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)
+428
View File
@@ -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)
}}
@@ -2,10 +2,7 @@
#include "StdAfx.h"
extern "C"
{
#include "../../../../C/Alloc.h"
}
#include "Common/Defs.h"
+3 -3
View File
@@ -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);
}
+1 -1
View File
@@ -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,
+13 -16
View File
@@ -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;
}
+4 -2
View File
@@ -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();
+99 -99
View File
@@ -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
}
}}
+5 -5
View File
@@ -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);
};
}}
+67 -65
View File
@@ -2,19 +2,19 @@
#include "StdAfx.h"
extern "C"
{
#include "../../../../C/Alloc.h"
}
#include "../../../../C/CpuArch.h"
#include "Common/MyCom.h"
#include "../../Common/StreamUtils.h"
#include "Common/IntToString.h"
#include "Common/MyCom.h"
#include "../../Common/StreamUtils.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);
}
}}
+24 -13
View File
@@ -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);
}}
+61 -58
View File
@@ -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 j = 0; j < oneMethodInfo.Props.Size(); j++)
if (oneMethodInfo.Props[j].Id == propID)
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 < 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)
prop.Id = nameToPropID.PropID;
if (prop.Id == NCoderPropID::kBlockSize ||
prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize)
{
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)
{
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];
+2
View File
@@ -12,6 +12,8 @@ struct COneMethodInfo
{
CObjectVector<CProp> Props;
UString MethodName;
bool IsLzma() const;
};
class COutHandler
+5 -7
View File
@@ -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,
+7 -13
View File
@@ -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;
}
+4 -6
View File
@@ -3,13 +3,11 @@
#ifndef __OUT_STREAM_WITH_CRC_H
#define __OUT_STREAM_WITH_CRC_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
extern "C"
{
#include "../../../../C/7zCrc.h"
}
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class COutStreamWithCRC:
public ISequentialOutStream,
+7 -13
View File
@@ -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;
}
+3 -5
View File
@@ -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,
-240
View File
@@ -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
}
}}
-30
View File
@@ -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
-23
View File
@@ -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;
}
}}}
-70
View File
@@ -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
-272
View File
@@ -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);
}
}}
-41
View File
@@ -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
-55
View File
@@ -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
-13
View File
@@ -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)
-8
View File
@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif
+625
View File
@@ -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)
}}
+37 -54
View File
@@ -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)
-3
View File
@@ -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"
+11 -19
View File
@@ -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));
+983
View File
@@ -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)
}}
-284
View File
@@ -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
}}
-63
View File
@@ -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
-202
View File
@@ -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;
}
}}
-20
View File
@@ -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;
}}
-85
View File
@@ -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
-119
View File
@@ -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);
}
}}
-30
View File
@@ -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
-59
View File
@@ -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
-65
View File
@@ -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);
}
}}
-29
View File
@@ -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
-18
View File
@@ -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)
-112
View File
@@ -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);
}
}}
-37
View File
@@ -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
-8
View File
@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif
+820
View File
@@ -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)
}}
+9 -3
View File
@@ -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; }
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+42 -15
View File
@@ -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
}
}}
+8 -11
View File
@@ -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
{
public:
MY_UNKNOWN_IMP1(
IInArchive
)
INTERFACE_IInArchive(;)
private:
CMyComPtr<IInStream> _inStream;
CMyComPtr<IInStream> _stream;
CInArchive _archive;
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
}}
+9 -12
View File
@@ -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])
+6 -6
View File
@@ -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();
-43
View File
@@ -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;
}
}}
-27
View File
@@ -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
-387
View File
@@ -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
}
}}
-30
View File
@@ -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
-19
View File
@@ -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
-172
View File
@@ -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;
}
}}
-29
View File
@@ -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
-172
View File
@@ -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
@@ -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;
}
}}
@@ -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
-13
View File
@@ -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)
-8
View File
@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif
+783
View File
@@ -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)
}}
-14
View File
@@ -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)
@@ -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;
}
}}
-26
View File
@@ -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
-243
View File
@@ -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
}}
-69
View File
@@ -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
-56
View File
@@ -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;
}
}}
-16
View File
@@ -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

Some files were not shown because too many files have changed in this diff Show More